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;
|
||||
}
|
||||
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, BootFlags) == 109);
|
||||
_Static_assert(offsetof(AcpiTableFadt, XDsdt) == 140);
|
||||
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);
|
||||
}
|
||||
_AcpiBootFlags = flags;
|
||||
}
|
||||
if (length >= offsetof(AcpiTableFadt, XDsdt) + sizeof(fadt->XDsdt) &&
|
||||
fadt->XDsdt) {
|
||||
dsdt_phy = fadt->XDsdt;
|
||||
|
|
|
@ -193,13 +193,14 @@ textstartup void _AcpiXsdtInit(void) {
|
|||
ACPI_INFO("no RSDP found");
|
||||
return;
|
||||
}
|
||||
ACPI_INFO("RSDP @ %p", rsdp);
|
||||
ACPI_INFO("RSDP OEM %.6!s @ %p", rsdp->OemId, rsdp);
|
||||
if (rsdp->Revision <= 1 ||
|
||||
rsdp->Length < offsetof(AcpiTableRsdp, Reserved) ||
|
||||
!rsdp->XsdtPhysicalAddress) {
|
||||
const AcpiTableRsdt *rsdt = _AcpiMapTable(rsdp->RsdtPhysicalAddress);
|
||||
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 *));
|
||||
if (ents) {
|
||||
for (i = 0; i < nents; ++i) {
|
||||
|
@ -209,7 +210,8 @@ textstartup void _AcpiXsdtInit(void) {
|
|||
} else {
|
||||
const AcpiTableXsdt *xsdt = _AcpiMapTable(rsdp->XsdtPhysicalAddress);
|
||||
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 *));
|
||||
if (ents) {
|
||||
for (i = 0; i < nents; ++i) {
|
||||
|
|
|
@ -348,8 +348,8 @@ _AcpiCompressHid(const uint8_t *__hid, size_t __len) {
|
|||
__c = __hid[6];
|
||||
if (__c < '0' || __c > 'F' || (__c > '9' && __c < 'A')) return 0;
|
||||
__d3 = __c <= '9' ? __c - '0' : __c - 'A' + 0xA;
|
||||
__evalu = (uint32_t)__a0 << 26 | (uint32_t)__a1 << 21 | (uint32_t)__a2 << 16 |
|
||||
__d0 << 12 | __d1 << 8 | __d2 << 4 | __d3;
|
||||
__evalu = (uint32_t)__a0 << 26 | (uint32_t)__a1 << 21 | (uint32_t)__a2 << 16
|
||||
| __d0 << 12 | __d1 << 8 | __d2 << 4 | __d3;
|
||||
return bswap_32(__evalu);
|
||||
}
|
||||
|
||||
|
@ -382,6 +382,12 @@ forceinline bool _AcpiDecompressHid(uintmax_t __hid,
|
|||
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, ...) \
|
||||
do { \
|
||||
if (!IsTiny()) { \
|
||||
|
|
|
@ -34,7 +34,24 @@
|
|||
|
||||
#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)();
|
||||
ACPI_INFO("starting 8259 IRQs");
|
||||
outb(PIC1_CMD, PIC_INIT | PIC_IC4); /* ICW1 */
|
||||
|
@ -51,12 +68,14 @@ textstartup void _Irq8259Init(void) {
|
|||
/* Send EOIs for good measure. */
|
||||
outb(PIC1_CMD, PIC_EOI);
|
||||
outb(PIC2_CMD, PIC_EOI);
|
||||
/* Reprogram PIT 0. */
|
||||
enable();
|
||||
}
|
||||
|
||||
textstartup void _IrqHwInit(void) {
|
||||
if (!_weaken(_AcpiMadtFlags) ||
|
||||
(_AcpiMadtFlags & kAcpiMadtPcAtCompat) != 0) {
|
||||
_Pit0Init();
|
||||
_Irq8259Init();
|
||||
} else {
|
||||
/* TODO */
|
||||
|
|
|
@ -147,6 +147,21 @@
|
|||
#define PIC_READ_IRR 0x0a /* OCW3 irq ready 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
|
||||
@see Intel Manual V.3A §4.1 §4.5
|
||||
IsValid (ignored on CR3) V┐
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue