mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-08 02:40:28 +00:00
[metal] Reprogram PIT 0 (system timer) before enabling IRQ 0
This commit is contained in:
parent
d0f247f182
commit
915fda840d
5 changed files with 59 additions and 9 deletions
|
@ -493,15 +493,23 @@ textstartup void _AcpiFadtInit(void) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
length = fadt->Header.Length;
|
length = fadt->Header.Length;
|
||||||
ACPI_INFO("FADT @ %p,+%#zx", fadt, length);
|
ACPI_INFO("FADT %.8!s @ %p,+%#zx", fadt->Header.OemTableId, fadt, length);
|
||||||
_Static_assert(offsetof(AcpiTableFadt, Dsdt) == 40);
|
_Static_assert(offsetof(AcpiTableFadt, Dsdt) == 40);
|
||||||
_Static_assert(offsetof(AcpiTableFadt, BootFlags) == 109);
|
_Static_assert(offsetof(AcpiTableFadt, BootFlags) == 109);
|
||||||
_Static_assert(offsetof(AcpiTableFadt, XDsdt) == 140);
|
_Static_assert(offsetof(AcpiTableFadt, XDsdt) == 140);
|
||||||
if (length >= offsetof(AcpiTableFadt, BootFlags) + sizeof(fadt->BootFlags))
|
if (length >= offsetof(AcpiTableFadt, BootFlags) + sizeof(fadt->BootFlags))
|
||||||
{
|
{
|
||||||
_AcpiBootFlags = flags = fadt->BootFlags;
|
flags = fadt->BootFlags;
|
||||||
|
if (READ64LE(fadt->Header.OemTableId) == READ64LE("BXPC ")) {
|
||||||
|
/* Work around incomplete AML tables under QEMU. */
|
||||||
|
ACPI_WARN("FADT: boot flags %#x -> %#x (QEMU workaround)",
|
||||||
|
(unsigned)flags, (unsigned)(flags | kAcpiFadtLegacyDevices));
|
||||||
|
flags |= kAcpiFadtLegacyDevices;
|
||||||
|
} else {
|
||||||
ACPI_INFO("FADT: boot flags %#x", (unsigned)flags);
|
ACPI_INFO("FADT: boot flags %#x", (unsigned)flags);
|
||||||
}
|
}
|
||||||
|
_AcpiBootFlags = flags;
|
||||||
|
}
|
||||||
if (length >= offsetof(AcpiTableFadt, XDsdt) + sizeof(fadt->XDsdt) &&
|
if (length >= offsetof(AcpiTableFadt, XDsdt) + sizeof(fadt->XDsdt) &&
|
||||||
fadt->XDsdt) {
|
fadt->XDsdt) {
|
||||||
dsdt_phy = fadt->XDsdt;
|
dsdt_phy = fadt->XDsdt;
|
||||||
|
|
|
@ -193,13 +193,14 @@ textstartup void _AcpiXsdtInit(void) {
|
||||||
ACPI_INFO("no RSDP found");
|
ACPI_INFO("no RSDP found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ACPI_INFO("RSDP @ %p", rsdp);
|
ACPI_INFO("RSDP OEM %.6!s @ %p", rsdp->OemId, rsdp);
|
||||||
if (rsdp->Revision <= 1 ||
|
if (rsdp->Revision <= 1 ||
|
||||||
rsdp->Length < offsetof(AcpiTableRsdp, Reserved) ||
|
rsdp->Length < offsetof(AcpiTableRsdp, Reserved) ||
|
||||||
!rsdp->XsdtPhysicalAddress) {
|
!rsdp->XsdtPhysicalAddress) {
|
||||||
const AcpiTableRsdt *rsdt = _AcpiMapTable(rsdp->RsdtPhysicalAddress);
|
const AcpiTableRsdt *rsdt = _AcpiMapTable(rsdp->RsdtPhysicalAddress);
|
||||||
nents = (rsdt->Header.Length - sizeof(rsdt->Header)) / sizeof(uint32_t);
|
nents = (rsdt->Header.Length - sizeof(rsdt->Header)) / sizeof(uint32_t);
|
||||||
ACPI_INFO("RSDT @ %p, %#zx entries", rsdt, nents);
|
ACPI_INFO("RSDT %.8!s @ %p, %#zx entries", rsdt->Header.OemTableId, rsdt,
|
||||||
|
nents);
|
||||||
ents = _AcpiOsAllocate(nents * sizeof(AcpiTableHeader *));
|
ents = _AcpiOsAllocate(nents * sizeof(AcpiTableHeader *));
|
||||||
if (ents) {
|
if (ents) {
|
||||||
for (i = 0; i < nents; ++i) {
|
for (i = 0; i < nents; ++i) {
|
||||||
|
@ -209,7 +210,8 @@ textstartup void _AcpiXsdtInit(void) {
|
||||||
} else {
|
} else {
|
||||||
const AcpiTableXsdt *xsdt = _AcpiMapTable(rsdp->XsdtPhysicalAddress);
|
const AcpiTableXsdt *xsdt = _AcpiMapTable(rsdp->XsdtPhysicalAddress);
|
||||||
nents = (xsdt->Header.Length - sizeof(xsdt->Header)) / sizeof(uint64_t);
|
nents = (xsdt->Header.Length - sizeof(xsdt->Header)) / sizeof(uint64_t);
|
||||||
ACPI_INFO("XSDT @ %p, %#zx entries", xsdt, nents);
|
ACPI_INFO("XSDT %.8!s @ %p, %#zx entries", xsdt->Header.OemTableId, xsdt,
|
||||||
|
nents);
|
||||||
ents = _AcpiOsAllocate(nents * sizeof(AcpiTableHeader *));
|
ents = _AcpiOsAllocate(nents * sizeof(AcpiTableHeader *));
|
||||||
if (ents) {
|
if (ents) {
|
||||||
for (i = 0; i < nents; ++i) {
|
for (i = 0; i < nents; ++i) {
|
||||||
|
|
|
@ -348,8 +348,8 @@ _AcpiCompressHid(const uint8_t *__hid, size_t __len) {
|
||||||
__c = __hid[6];
|
__c = __hid[6];
|
||||||
if (__c < '0' || __c > 'F' || (__c > '9' && __c < 'A')) return 0;
|
if (__c < '0' || __c > 'F' || (__c > '9' && __c < 'A')) return 0;
|
||||||
__d3 = __c <= '9' ? __c - '0' : __c - 'A' + 0xA;
|
__d3 = __c <= '9' ? __c - '0' : __c - 'A' + 0xA;
|
||||||
__evalu = (uint32_t)__a0 << 26 | (uint32_t)__a1 << 21 | (uint32_t)__a2 << 16 |
|
__evalu = (uint32_t)__a0 << 26 | (uint32_t)__a1 << 21 | (uint32_t)__a2 << 16
|
||||||
__d0 << 12 | __d1 << 8 | __d2 << 4 | __d3;
|
| __d0 << 12 | __d1 << 8 | __d2 << 4 | __d3;
|
||||||
return bswap_32(__evalu);
|
return bswap_32(__evalu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,6 +382,12 @@ forceinline bool _AcpiDecompressHid(uintmax_t __hid,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forceinline AcpiDeviceHid _AcpiMakePnpHid(uint16_t __pnp_id) {
|
||||||
|
uint32_t __evalu = (uint32_t)16 << 26 | (uint32_t)14 << 21 |
|
||||||
|
(uint32_t)16 << 16 | __pnp_id;
|
||||||
|
return bswap_32(__evalu);
|
||||||
|
}
|
||||||
|
|
||||||
#define ACPI_INFO(FMT, ...) \
|
#define ACPI_INFO(FMT, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (!IsTiny()) { \
|
if (!IsTiny()) { \
|
||||||
|
|
|
@ -34,7 +34,24 @@
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
|
||||||
textstartup void _Irq8259Init(void) {
|
textstartup static const AcpiDefDevice *_AcpiFindDevice(AcpiDeviceHid hid) {
|
||||||
|
const AcpiDefDevice *dev = _AcpiDefDevices;
|
||||||
|
while (dev && dev->hid != hid) dev = dev->next;
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
textstartup static void _Pit0Init(void) {
|
||||||
|
if (!(_AcpiBootFlags & kAcpiFadtLegacyDevices) &&
|
||||||
|
!_AcpiFindDevice(_AcpiMakePnpHid(0x0100))) {
|
||||||
|
ACPI_FATAL("no 8254 PIT");
|
||||||
|
}
|
||||||
|
ACPI_INFO("resetting 8254 PIT");
|
||||||
|
outb(PIT_CMD, PIT_SC0 | PIT_RW | PIT_SQW);
|
||||||
|
outb(PIT0_DATA, 0x00);
|
||||||
|
outb(PIT0_DATA, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
textstartup static void _Irq8259Init(void) {
|
||||||
if (_weaken(_ApicDisableAll)) _weaken(_ApicDisableAll)();
|
if (_weaken(_ApicDisableAll)) _weaken(_ApicDisableAll)();
|
||||||
ACPI_INFO("starting 8259 IRQs");
|
ACPI_INFO("starting 8259 IRQs");
|
||||||
outb(PIC1_CMD, PIC_INIT | PIC_IC4); /* ICW1 */
|
outb(PIC1_CMD, PIC_INIT | PIC_IC4); /* ICW1 */
|
||||||
|
@ -51,12 +68,14 @@ textstartup void _Irq8259Init(void) {
|
||||||
/* Send EOIs for good measure. */
|
/* Send EOIs for good measure. */
|
||||||
outb(PIC1_CMD, PIC_EOI);
|
outb(PIC1_CMD, PIC_EOI);
|
||||||
outb(PIC2_CMD, PIC_EOI);
|
outb(PIC2_CMD, PIC_EOI);
|
||||||
|
/* Reprogram PIT 0. */
|
||||||
enable();
|
enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
textstartup void _IrqHwInit(void) {
|
textstartup void _IrqHwInit(void) {
|
||||||
if (!_weaken(_AcpiMadtFlags) ||
|
if (!_weaken(_AcpiMadtFlags) ||
|
||||||
(_AcpiMadtFlags & kAcpiMadtPcAtCompat) != 0) {
|
(_AcpiMadtFlags & kAcpiMadtPcAtCompat) != 0) {
|
||||||
|
_Pit0Init();
|
||||||
_Irq8259Init();
|
_Irq8259Init();
|
||||||
} else {
|
} else {
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
|
|
@ -147,6 +147,21 @@
|
||||||
#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
|
#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
|
||||||
#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
|
#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see Intel Corporation. 82C54 CHMOS Programmable Interval Timer. 1994.
|
||||||
|
* Intel order number 23124-006.
|
||||||
|
*/
|
||||||
|
#define PIT 0x40 /* IO base address for PIT */
|
||||||
|
#define PIT0_DATA (PIT + 0)
|
||||||
|
#define PIT1_DATA (PIT + 1)
|
||||||
|
#define PIT2_DATA (PIT + 2)
|
||||||
|
#define PIT_CMD (PIT + 3)
|
||||||
|
#define PIT_SC0 0x00 /* select counter 0 */
|
||||||
|
#define PIT_SC1 0x00 /* select counter 1 */
|
||||||
|
#define PIT_SC2 0x00 /* select counter 2 */
|
||||||
|
#define PIT_RW 0x30 /* read/write operation */
|
||||||
|
#define PIT_SQW 0x06 /* square wave mode */
|
||||||
|
|
||||||
/* Long Mode Paging
|
/* Long Mode Paging
|
||||||
@see Intel Manual V.3A §4.1 §4.5
|
@see Intel Manual V.3A §4.1 §4.5
|
||||||
IsValid (ignored on CR3) V┐
|
IsValid (ignored on CR3) V┐
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue