BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / blob / 5acaf7454950930ccdaeca9388a046c17fb547b8 / kernel / acpi / acpi.c

// Related

Nucleus

Barry ACPI + APIC 232d0f9 (3 years, 3 months ago)
/*
 * This file controls the ACPI
 */

#include <stdint.h>
#include <string.h>
#include <nucleus/panic.h>
#include "acpi.h"

/* Root System Descriptor Pointer */
struct RSDPDesc {
	char signature[8];
	uint8_t checksum;
	char oem[6];
	uint8_t revision;
	uint32_t rsdt;
} __attribute__((packed));

void init_apic(struct SDTHeader *);

/* Table handlers */
struct TableHandler {
	char *sig;
	void (*handler)(struct SDTHeader *);
} handlers[] = {
	{"APIC", init_apic},
};

/* Calculate the ACPI checksum */
static uint32_t
checksum(struct SDTHeader *header)
{
	char *byte = (void *) header;
	uint32_t i, check = 0;
	for (i = 0; i < header->length; i++)
		check += byte[i];
	return ((check % 0x100) == 0);
}

/* Initialise ACPI */
void
init_acpi(void *ebda)
{
	/* Search for Root System Descriptor Table */
	char *sig;
	for (sig = ebda; sig < (char *) 0x100000; sig++) {
		if (!memcmp(sig, "RSD PTR ", 8))
			break;
	}
	if (sig == (char *) 0x100000)
		return;

	/* RSDT checksum */
	uint32_t i, check = 0;
	for (i = 0; i < sizeof(struct RSDPDesc); i++)
		check += sig[i];
	if (check % 0x100)
		return;

	/* Iterate tables */
	uint32_t j;
	struct SDTHeader *rsdt = (void *) ((struct RSDPDesc *) sig)->rsdt;
	struct SDTHeader **table = (void *) (rsdt + 1);
	for (i = 0; i < (rsdt->length - sizeof(struct SDTHeader)) / 4; i++) {
		if (!checksum(table[i]))
			continue;
		/* Try to match to a handler */
		for (j = 0; j < sizeof(handlers)/sizeof(handlers[0]); j++) {
			if (memcmp(table[i]->signature, handlers[j].sig, 4))
				continue;
			handlers[j].handler(table[i]);
		}
	}
}