135 lines
4.1 KiB
C
135 lines
4.1 KiB
C
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdarg.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <exec/debcon.h>
|
|
#include <exec/list.h>
|
|
#include <exec/mem.h>
|
|
#include <exec/detect.h>
|
|
|
|
const char *HEX_DIGITS = "0123456789ABCDEF";
|
|
|
|
static struct List detects;
|
|
|
|
void DetectInit(void) {
|
|
NewList(&detects, LP_BLOCK);
|
|
}
|
|
|
|
struct Detect *CreateDetect(char* compat, uint8_t reg_count, uint8_t irq_count) {
|
|
size_t compat_length = strlen(compat);
|
|
size_t size = sizeof(struct Detect) + compat_length + 1 + reg_count * sizeof(struct DetectRegion) + irq_count * sizeof(uint8_t);
|
|
struct Detect *entry = (struct Detect *)AllocMem(size);
|
|
if (!entry) return NULL;
|
|
char *entry_compat = (char *)entry + sizeof(struct Detect);
|
|
|
|
entry->compat_length = compat_length;
|
|
entry->reg_count = reg_count;
|
|
entry->irq_count = irq_count;
|
|
memcpy(entry_compat, compat, compat_length + 1);
|
|
entry->node.name = entry_compat;
|
|
|
|
return entry;
|
|
}
|
|
|
|
void AddDetect(struct Detect* entry) {
|
|
Enqueue(&detects, &entry->node);
|
|
}
|
|
|
|
void SetDetectRegion(struct Detect* entry, uint8_t index, enum HalAddressSpace space, uintptr_t base, size_t limit) {
|
|
struct DetectRegion *region = (struct DetectRegion *)((uintptr_t)entry + sizeof(struct Detect) + entry->compat_length + 1 + index * sizeof(struct DetectRegion));
|
|
region->space = space;
|
|
region->base = base;
|
|
region->limit = limit;
|
|
}
|
|
|
|
void SetDetectIRQ(struct Detect* entry, uint8_t index, uint8_t irq) {
|
|
uint8_t *irq_list = (uint8_t *)((uintptr_t)entry + sizeof(struct Detect) + entry->compat_length + 1 + entry->reg_count * sizeof(struct DetectRegion));
|
|
irq_list[index] = irq;
|
|
}
|
|
|
|
int BuildCompat(char *str, ...) {
|
|
va_list args;
|
|
size_t value;
|
|
uint32_t length;
|
|
char *key;
|
|
bool key_started;
|
|
int key_index, str_index;
|
|
char c;
|
|
|
|
int p = 0;
|
|
|
|
va_start(args, str);
|
|
for (;;) {
|
|
key = va_arg(args, char *);
|
|
if (key == NULL) break;
|
|
value = va_arg(args, size_t);
|
|
length = va_arg(args, uint32_t);
|
|
|
|
/* locate key */
|
|
for (key_started = true, key_index = 0, str_index = 0; str[str_index]; str_index++) {
|
|
if (key_started) {
|
|
if (!strncmp(&str[str_index], key, strlen(key)) && (str[str_index + strlen(key)] == '(')) {
|
|
/* found key */
|
|
str_index += strlen(key);
|
|
goto found_key;
|
|
} else {
|
|
key_started = false;
|
|
}
|
|
} else {
|
|
key_started = (str[str_index] == ')');
|
|
}
|
|
}
|
|
|
|
/* did not find key */
|
|
va_end(args);
|
|
return -1;
|
|
found_key:
|
|
p++;
|
|
if (length & 0x80000000) {
|
|
/* string */
|
|
} else {
|
|
/* number */
|
|
for (int i = 0; i < length; i++) {
|
|
str[str_index + length - i] = HEX_DIGITS[value % 16];
|
|
value /= 16;
|
|
}
|
|
}
|
|
}
|
|
va_end(args);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void PrintDetect(struct Detect *detect) {
|
|
char *compat = (char *)detect + sizeof(struct Detect);
|
|
DebconPrint("Detect \"");
|
|
DebconPrint(compat);
|
|
DebconPrint("\"\n");
|
|
for (int i = 0; i < detect->reg_count; i++) {
|
|
struct DetectRegion *region = (struct DetectRegion *)((uintptr_t)detect + sizeof(struct Detect) + detect->compat_length + 1 + i * sizeof(struct DetectRegion));
|
|
DebconPrint(" Region ");
|
|
DebconPrintHex(i);
|
|
DebconPrint(": Space=");
|
|
DebconPrintHex(region->space);
|
|
DebconPrint(" Base=");
|
|
DebconPrintHex(region->base);
|
|
DebconPrint(" Limit=");
|
|
DebconPrintHex(region->limit);
|
|
DebconPrint("\n");
|
|
}
|
|
uint8_t *irq_list = (uint8_t *)((uintptr_t)detect + sizeof(struct Detect) + detect->compat_length + 1 + detect->reg_count * sizeof(struct DetectRegion));
|
|
for (int i = 0; i < detect->irq_count; i++) {
|
|
DebconPrint(" IRQ ");
|
|
DebconPrintHex(irq_list[i]);
|
|
DebconPutChar('\n');
|
|
}
|
|
}
|
|
|
|
void PrintDetects(void) {
|
|
struct Node *node;
|
|
DebconPrint("Detected devices:\n");
|
|
for (node = detects.head; node != &detects.tail; node = node->next) {
|
|
PrintDetect((struct Detect *)node);
|
|
}
|
|
} |