Files
net/exec/detect.c
2025-12-20 18:49:21 -08:00

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);
}
}