-/* Functions for handling 8259A PICs */
-
-VOID Disable8259AIrq(ULONG irq)
-{
- ULONG tmp;
-
- if (irq >= 8)
- {
- tmp = READ_PORT_UCHAR((PUCHAR)0xA1);
- tmp |= (1 << (irq - 8));
- WRITE_PORT_UCHAR((PUCHAR)0xA1, tmp);
- }
- else
- {
- tmp = READ_PORT_UCHAR((PUCHAR)0x21);
- tmp |= (1 << irq);
- WRITE_PORT_UCHAR((PUCHAR)0x21, tmp);
- }
-}
-
-
-VOID Enable8259AIrq(ULONG irq)
-{
- ULONG tmp;
-
- if (irq >= 8)
- {
- tmp = READ_PORT_UCHAR((PUCHAR)0xA1);
- tmp &= ~(1 << (irq - 8));
- WRITE_PORT_UCHAR((PUCHAR)0xA1, tmp);
- }
- else
- {
- tmp = READ_PORT_UCHAR((PUCHAR)0x21);
- tmp &= ~(1 << irq);
- WRITE_PORT_UCHAR((PUCHAR)0x21, tmp);
- }
-}
-
-
-/* Functions for handling I/O APICs */
-
-volatile ULONG IOAPICRead(ULONG Apic, ULONG Offset)
-{
- PULONG Base;
-
- Base = (PULONG)IOAPICMap[Apic].ApicAddress;
- *Base = Offset;
- return *((PULONG)((ULONG)Base + IOAPIC_IOWIN));
-}
-
-VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value)
-{
- PULONG Base;
-
- Base = (PULONG)IOAPICMap[Apic].ApicAddress;
- *Base = Offset;
- *((PULONG)((ULONG)Base + IOAPIC_IOWIN)) = Value;
-}
-
-
-VOID IOAPICClearPin(ULONG Apic, ULONG Pin)
-{
- IOAPIC_ROUTE_ENTRY Entry;
-
- DPRINT("IOAPICClearPin(Apic %d, Pin %d\n", Apic, Pin);
- /*
- * Disable it in the IO-APIC irq-routing table
- */
- memset(&Entry, 0, sizeof(Entry));
- Entry.mask = 1;
-
- IOAPICWrite(Apic, IOAPIC_REDTBL + 2 * Pin, *(((PULONG)&Entry) + 0));
- IOAPICWrite(Apic, IOAPIC_REDTBL + 1 + 2 * Pin, *(((PULONG)&Entry) + 1));
-}
-
-static VOID IOAPICClear(ULONG Apic)
-{
- ULONG Pin;
-
- for (Pin = 0; Pin < /*IOAPICMap[Apic].EntryCount*/24; Pin++)
- {
- IOAPICClearPin(Apic, Pin);
- }
-}
-
-static VOID IOAPICClearAll(VOID)
-{
- ULONG Apic;
-
- for (Apic = 0; Apic < IOAPICCount; Apic++)
- {
- IOAPICClear(Apic);
- }
-}
-
-/* This is performance critical and should probably be done in assembler */
-VOID IOAPICMaskIrq(ULONG Irq)
-{
- IOAPIC_ROUTE_ENTRY Entry;
- ULONG Apic = IrqApicMap[Irq];
-
-
- *((PULONG)&Entry) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq);
- Entry.mask = 1;
- IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *((PULONG)&Entry));
-}
-
-
-/* This is performance critical and should probably be done in assembler */
-VOID IOAPICUnmaskIrq(ULONG Irq)
-{
- IOAPIC_ROUTE_ENTRY Entry;
- ULONG Apic = IrqApicMap[Irq];
-
- *((PULONG)&Entry) = IOAPICRead(Apic, IOAPIC_REDTBL+2*IrqPinMap[Irq]);
- Entry.mask = 0;
- IOAPICWrite(Apic, IOAPIC_REDTBL+2*IrqPinMap[Irq], *((PULONG)&Entry));
-}
-
-static VOID
-IOAPICSetupIds(VOID)
-{
- ULONG tmp, apic, i;
- UCHAR old_id;
-
- /*
- * Set the IOAPIC ID to the value stored in the MPC table.
- */
- for (apic = 0; apic < IOAPICCount; apic++)
- {
-
- /* Read the register 0 value */
- tmp = IOAPICRead(apic, IOAPIC_ID);
-
- old_id = IOAPICMap[apic].ApicId;
-
- if (IOAPICMap[apic].ApicId >= 0xf)
- {
- DPRINT1("BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
- apic, IOAPICMap[apic].ApicId);
- DPRINT1("... fixing up to %d. (tell your hw vendor)\n",
- GET_IOAPIC_ID(tmp));
- IOAPICMap[apic].ApicId = GET_IOAPIC_ID(tmp);
- }
-
- /*
- * We need to adjust the IRQ routing table
- * if the ID changed.
- */
- if (old_id != IOAPICMap[apic].ApicId)
- {
- for (i = 0; i < IRQCount; i++)
- {
- if (IRQMap[i].DstApicId == old_id)
- {
- IRQMap[i].DstApicId = IOAPICMap[apic].ApicId;
- }
- }
- }
-
- /*
- * Read the right value from the MPC table and
- * write it into the ID register.
- */
- DPRINT("Changing IO-APIC physical APIC ID to %d\n",
- IOAPICMap[apic].ApicId);
-
- tmp &= ~IOAPIC_ID_MASK;
- tmp |= SET_IOAPIC_ID(IOAPICMap[apic].ApicId);
-
- IOAPICWrite(apic, IOAPIC_ID, tmp);
-
- /*
- * Sanity check
- */
- tmp = IOAPICRead(apic, 0);
- if (GET_IOAPIC_ID(tmp) != IOAPICMap[apic].ApicId)
- {
- DPRINT1("Could not set I/O APIC ID!\n");
- KEBUGCHECK(0);
- }
- }
-}
-
-
-/*
- * EISA Edge/Level control register, ELCR
- */
-static ULONG EISA_ELCR(ULONG irq)
-{
- if (irq < 16)
- {
- PUCHAR port = (PUCHAR)(0x4d0 + (irq >> 3));
- return (READ_PORT_UCHAR(port) >> (irq & 7)) & 1;
- }
- DPRINT("Broken MPtable reports ISA irq %d\n", irq);
- return 0;
-}
-
-/* EISA interrupts are always polarity zero and can be edge or level
- * trigger depending on the ELCR value. If an interrupt is listed as
- * EISA conforming in the MP table, that means its trigger type must
- * be read in from the ELCR */
-
-#define default_EISA_trigger(idx) (EISA_ELCR(IRQMap[idx].SrcBusIrq))
-#define default_EISA_polarity(idx) (0)
-
-/* ISA interrupts are always polarity zero edge triggered,
- * when listed as conforming in the MP table. */
-
-#define default_ISA_trigger(idx) (0)
-#define default_ISA_polarity(idx) (0)
-
-/* PCI interrupts are always polarity one level triggered,
- * when listed as conforming in the MP table. */
-
-#define default_PCI_trigger(idx) (1)
-#define default_PCI_polarity(idx) (1)
-
-/* MCA interrupts are always polarity zero level triggered,
- * when listed as conforming in the MP table. */
-
-#define default_MCA_trigger(idx) (1)
-#define default_MCA_polarity(idx) (0)
-
-static ULONG IRQPolarity(ULONG idx)
-{
- ULONG bus = IRQMap[idx].SrcBusId;
- ULONG polarity;
-
- /*
- * Determine IRQ line polarity (high active or low active):
- */
- switch (IRQMap[idx].IrqFlag & 3)
- {
- case 0: /* conforms, ie. bus-type dependent polarity */
- {
- switch (BUSMap[bus])
- {
- case MP_BUS_ISA: /* ISA pin */
- {
- polarity = default_ISA_polarity(idx);
- break;
- }
- case MP_BUS_EISA: /* EISA pin */
- {
- polarity = default_EISA_polarity(idx);
- break;
- }
- case MP_BUS_PCI: /* PCI pin */
- {
- polarity = default_PCI_polarity(idx);
- break;
- }
- case MP_BUS_MCA: /* MCA pin */
- {
- polarity = default_MCA_polarity(idx);
- break;
- }
- default:
- {
- DPRINT("Broken BIOS!!\n");
- polarity = 1;
- break;
- }
- }
- break;
- }
- case 1: /* high active */
- {
- polarity = 0;
- break;
- }
- case 2: /* reserved */
- {
- DPRINT("Broken BIOS!!\n");
- polarity = 1;
- break;
- }
- case 3: /* low active */
- {
- polarity = 1;
- break;
- }
- default: /* invalid */
- {
- DPRINT("Broken BIOS!!\n");
- polarity = 1;
- break;
- }
- }
- return polarity;
-}
-
-static ULONG IRQTrigger(ULONG idx)
-{
- ULONG bus = IRQMap[idx].SrcBusId;
- ULONG trigger;
-
- /*
- * Determine IRQ trigger mode (edge or level sensitive):
- */
- switch ((IRQMap[idx].IrqFlag >> 2) & 3)
- {
- case 0: /* conforms, ie. bus-type dependent */
- {
- switch (BUSMap[bus])
- {
- case MP_BUS_ISA: /* ISA pin */
- {
- trigger = default_ISA_trigger(idx);
- break;
- }
- case MP_BUS_EISA: /* EISA pin */
- {
- trigger = default_EISA_trigger(idx);
- break;
- }
- case MP_BUS_PCI: /* PCI pin */
- {
- trigger = default_PCI_trigger(idx);
- break;
- }
- case MP_BUS_MCA: /* MCA pin */
- {
- trigger = default_MCA_trigger(idx);
- break;
- }
- default:
- {
- DPRINT("Broken BIOS!!\n");
- trigger = 1;
- break;
- }
- }
- break;
- }
- case 1: /* edge */
- {
- trigger = 0;
- break;
- }
- case 2: /* reserved */
- {
- DPRINT("Broken BIOS!!\n");
- trigger = 1;
- break;
- }
- case 3: /* level */
- {
- trigger = 1;
- break;
- }
- default: /* invalid */
- {
- DPRINT("Broken BIOS!!\n");
- trigger = 0;
- break;
- }
- }
- return trigger;
-}
-
-
-static ULONG Pin2Irq(ULONG idx,
- ULONG apic,
- ULONG pin)
-{
- ULONG irq, i;
- ULONG bus = IRQMap[idx].SrcBusId;
-
- /*
- * Debugging check, we are in big trouble if this message pops up!
- */
- if (IRQMap[idx].DstApicInt != pin) {
- DPRINT("broken BIOS or MPTABLE parser, ayiee!!\n");
- }
-
- switch (BUSMap[bus])
- {
- case MP_BUS_ISA: /* ISA pin */
- case MP_BUS_EISA:
- case MP_BUS_MCA:
- {
- irq = IRQMap[idx].SrcBusIrq;
- break;
- }
- case MP_BUS_PCI: /* PCI pin */
- {
- /*
- * PCI IRQs are mapped in order
- */
- i = irq = 0;
- while (i < apic)
- irq += IOAPICMap[i++].EntryCount;
- irq += pin;
- break;
- }
- default:
- {
- DPRINT("Unknown bus type %d.\n",bus);
- irq = 0;
- break;
- }
- }
-
- return irq;
-}
-
-
-/*
- * Rough estimation of how many shared IRQs there are, can
- * be changed anytime.
- */
-#define MAX_PLUS_SHARED_IRQS PIC_IRQS
-#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + PIC_IRQS)
-
-/*
- * This is performance-critical, we want to do it O(1)
- *
- * the indexing order of this array favors 1:1 mappings
- * between pins and IRQs.
- */
-
-static struct irq_pin_list {
- ULONG apic, pin, next;
-} irq_2_pin[PIN_MAP_SIZE];
-
-/*
- * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
- * shared ISA-space IRQs, so we have to support them. We are super
- * fast in the common case, and fast for shared ISA-space IRQs.
- */
-static VOID AddPinToIrq(ULONG irq,
- ULONG apic,
- ULONG pin)
-{
- static ULONG first_free_entry = PIC_IRQS;
- struct irq_pin_list *entry = irq_2_pin + irq;
-
- while (entry->next)
- {
- entry = irq_2_pin + entry->next;
- }
-
- if (entry->pin != -1)
- {
- entry->next = first_free_entry;
- entry = irq_2_pin + entry->next;
- if (++first_free_entry >= PIN_MAP_SIZE)
- {
- DPRINT1("Ohh no!");
- KEBUGCHECK(0);
- }
- }
- entry->apic = apic;
- entry->pin = pin;
-}
-
-
-/*
- * Find the IRQ entry number of a certain pin.
- */
-static ULONG IOAPICGetIrqEntry(ULONG apic,
- ULONG pin,
- ULONG type)
-{
- ULONG i;
-
- for (i = 0; i < IRQCount; i++)
- {
- if (IRQMap[i].IrqType == type &&
- (IRQMap[i].DstApicId == IOAPICMap[apic].ApicId || IRQMap[i].DstApicId == MP_APIC_ALL) &&
- IRQMap[i].DstApicInt == pin)
- {
- return i;
- }
- }
- return -1;
-}
-
-
-static ULONG AssignIrqVector(ULONG irq)
-{
-#if 0
- static ULONG current_vector = FIRST_DEVICE_VECTOR, vector_offset = 0;
-#endif
- ULONG vector;
- /* There may already have been assigned a vector for this IRQ */
- vector = IRQVectorMap[irq];
- if (vector > 0)
- {
- return vector;
- }
-#if 0
- if (current_vector > FIRST_SYSTEM_VECTOR) {
- vector_offset++;
- current_vector = FIRST_DEVICE_VECTOR + vector_offset;
- } else if (current_vector == FIRST_SYSTEM_VECTOR) {
- DPRINT1("Ran out of interrupt sources!");
- KEBUGCHECK(0);
- }
-
- vector = current_vector;
- IRQVectorMap[irq] = vector;
- current_vector += 8;
- return vector;
-#else
- vector = IRQ2VECTOR(irq);
- IRQVectorMap[irq] = vector;
- return vector;
-#endif
-}
-
-
-VOID IOAPICSetupIrqs(VOID)
-{
- IOAPIC_ROUTE_ENTRY entry;
- ULONG apic, pin, idx, irq, first_notcon = 1, vector;
-
- DPRINT("Init IO_APIC IRQs\n");
-
- for (apic = 0; apic < IOAPICCount; apic++)
- {
- for (pin = 0; pin < IOAPICMap[apic].EntryCount; pin++)
- {
- /*
- * add it to the IO-APIC irq-routing table
- */
- memset(&entry,0,sizeof(entry));
-
- entry.delivery_mode = APIC_DM_LOWEST;
- entry.dest_mode = 1; /* logical delivery */
- entry.mask = 1; /* disable IRQ */
-#if 0
- /*
- * FIXME:
- * Some drivers are not able to deal with more than one cpu.
- */
- entry.dest.logical.logical_dest = OnlineCPUs;
-#else
- entry.dest.logical.logical_dest = 1 << 0;
-#endif
- idx = IOAPICGetIrqEntry(apic,pin,INT_VECTORED);
- if (idx == -1)
- {
- if (first_notcon)
- {
- DPRINT(" IO-APIC (apicid-pin) %d-%d\n", IOAPICMap[apic].ApicId, pin);
- first_notcon = 0;
- }
- else
- {
- DPRINT(", %d-%d\n", IOAPICMap[apic].ApicId, pin);
- }
- continue;
- }
-
- entry.trigger = IRQTrigger(idx);
- entry.polarity = IRQPolarity(idx);
-
- if (entry.trigger)
- {
- entry.trigger = 1;
- entry.mask = 1; // disable
-#if 0
- entry.dest.logical.logical_dest = OnlineCPUs;
-#else
- entry.dest.logical.logical_dest = 1 << 0;
-#endif
- }
-
- irq = Pin2Irq(idx, apic, pin);
- AddPinToIrq(irq, apic, pin);
-
- vector = AssignIrqVector(irq);
- entry.vector = vector;
-
- DPRINT("vector 0x%.08x assigned to irq 0x%.02x\n", vector, irq);
-
- if (irq == 0)
- {
- /* Mask timer IRQ */
- entry.mask = 1;
- }
-
- if ((apic == 0) && (irq < 16))
- {
- Disable8259AIrq(irq);
- }
- IOAPICWrite(apic, IOAPIC_REDTBL+2*pin+1, *(((PULONG)&entry)+1));
- IOAPICWrite(apic, IOAPIC_REDTBL+2*pin, *(((PULONG)&entry)+0));
-
- IrqPinMap[irq] = pin;
- IrqApicMap[irq] = apic;
-
- DPRINT("Vector %x, Pin %x, Irq %x\n", vector, pin, irq);
- }
- }
-}
-
-
-static VOID IOAPICEnable(VOID)
-{
- ULONG i, tmp;
-
- for (i = 0; i < PIN_MAP_SIZE; i++)
- {
- irq_2_pin[i].pin = -1;
- irq_2_pin[i].next = 0;
- }
-
- /*
- * The number of IO-APIC IRQ registers (== #pins):
- */
- for (i = 0; i < IOAPICCount; i++)
- {
- tmp = IOAPICRead(i, IOAPIC_VER);
- IOAPICMap[i].EntryCount = GET_IOAPIC_MRE(tmp) + 1;
- }
-
- /*
- * Do not trust the IO-APIC being empty at bootup
- */
- IOAPICClearAll();
-}
-
-#if 0
-static VOID IOAPICDisable(VOID)
-{
- /*
- * Clear the IO-APIC before rebooting
- */
- IOAPICClearAll();
- APICDisable();
-}
-#endif
-
-
-static VOID IOAPICSetup(VOID)
-{
- IOAPICEnable();
- IOAPICSetupIds();
- APICSyncArbIDs();
- IOAPICSetupIrqs();
-}
-
-
-VOID IOAPICDump(VOID)
-{
- ULONG apic, i;
- ULONG reg0, reg1, reg2=0;
-
- DbgPrint("Number of MP IRQ sources: %d.\n", IRQCount);
- for (i = 0; i < IOAPICCount; i++)
- {
- DbgPrint("Number of IO-APIC #%d registers: %d.\n",
- IOAPICMap[i].ApicId,
- IOAPICMap[i].EntryCount);
- }
-
- /*
- * We are a bit conservative about what we expect. We have to
- * know about every hardware change ASAP.
- */
- DbgPrint("Testing the IO APIC.......................\n");
-
- for (apic = 0; apic < IOAPICCount; apic++)
- {
- reg0 = IOAPICRead(apic, IOAPIC_ID);
- reg1 = IOAPICRead(apic, IOAPIC_VER);
- if (GET_IOAPIC_VERSION(reg1) >= 0x10)
- {
- reg2 = IOAPICRead(apic, IOAPIC_ARB);
- }
-
- DbgPrint("\n");
- DbgPrint("IO APIC #%d......\n", IOAPICMap[apic].ApicId);
- DbgPrint(".... register #00: %08X\n", reg0);
- DbgPrint("....... : physical APIC id: %02X\n", GET_IOAPIC_ID(reg0));
- if (reg0 & 0xF0FFFFFF)
- {
- DbgPrint(" WARNING: Unexpected IO-APIC\n");
- }
-
- DbgPrint(".... register #01: %08X\n", reg1);
- i = GET_IOAPIC_MRE(reg1);
-
- DbgPrint("....... : max redirection entries: %04X\n", i);
- if ((i != 0x0f) && /* older (Neptune) boards */
- (i != 0x17) && /* typical ISA+PCI boards */
- (i != 0x1b) && /* Compaq Proliant boards */
- (i != 0x1f) && /* dual Xeon boards */
- (i != 0x22) && /* bigger Xeon boards */
- (i != 0x2E) &&
- (i != 0x3F))
- {
- DbgPrint(" WARNING: Unexpected IO-APIC\n");
- }
-
- i = GET_IOAPIC_VERSION(reg1);
- DbgPrint("....... : IO APIC version: %04X\n", i);
- if ((i != 0x01) && /* 82489DX IO-APICs */
- (i != 0x10) && /* oldest IO-APICs */
- (i != 0x11) && /* Pentium/Pro IO-APICs */
- (i != 0x13)) /* Xeon IO-APICs */
- {
- DbgPrint(" WARNING: Unexpected IO-APIC\n");
- }
-
- if (reg1 & 0xFF00FF00)
- {
- DbgPrint(" WARNING: Unexpected IO-APIC\n");
- }
-
- if (GET_IOAPIC_VERSION(reg1) >= 0x10)
- {
- DbgPrint(".... register #02: %08X\n", reg2);
- DbgPrint("....... : arbitration: %02X\n",
- GET_IOAPIC_ARB(reg2));
- if (reg2 & 0xF0FFFFFF)
- {
- DbgPrint(" WARNING: Unexpected IO-APIC\n");
- }
- }
-
- DbgPrint(".... IRQ redirection table:\n");
- DbgPrint(" NR Log Phy Mask Trig IRR Pol"
- " Stat Dest Deli Vect: \n");
-
- for (i = 0; i <= GET_IOAPIC_MRE(reg1); i++)
- {
- IOAPIC_ROUTE_ENTRY entry;
-
- *(((PULONG)&entry)+0) = IOAPICRead(apic, 0x10+i*2);
- *(((PULONG)&entry)+1) = IOAPICRead(apic, 0x11+i*2);
-
- DbgPrint(" %02x %03X %02X ",
- i,
- entry.dest.logical.logical_dest,
- entry.dest.physical.physical_dest);
-
- DbgPrint("%C %C %1d %C %C %C %03X %02X\n",
- (entry.mask == 0) ? 'U' : 'M', // Unmasked/masked
- (entry.trigger == 0) ? 'E' : 'L', // Edge/level sensitive
- entry.irr,
- (entry.polarity == 0) ? 'H' : 'L', // Active high/active low
- (entry.delivery_status == 0) ? 'I' : 'S', // Idle / send pending
- (entry.dest_mode == 0) ? 'P' : 'L', // Physical logical
- entry.delivery_mode,
- entry.vector);
- }
- }
- DbgPrint("IRQ to pin mappings:\n");
- for (i = 0; i < PIC_IRQS; i++)
- {
- struct irq_pin_list *entry = irq_2_pin + i;
- if (entry->pin < 0)
- {
- continue;
- }
- DbgPrint("IRQ%d ", i);
- for (;;)
- {
- DbgPrint("-> %d", entry->pin);
- if (!entry->next)
- {
- break;
- }
- entry = irq_2_pin + entry->next;
- }
- if (i % 2)
- {
- DbgPrint("\n");
- }
- else
- {
- DbgPrint(" ");
- }
- }
-
- DbgPrint(".................................... done.\n");
-}
-
-
-
-/* Functions for handling local APICs */
-
-ULONG Read8254Timer(VOID)
-{
- ULONG Count;
-
- WRITE_PORT_UCHAR((PUCHAR)0x43, 0x00);
- Count = READ_PORT_UCHAR((PUCHAR)0x40);
- Count |= READ_PORT_UCHAR((PUCHAR)0x40) << 8;
-
- return Count;
-}
-
-VOID WaitFor8254Wraparound(VOID)
-{
- ULONG CurCount, PrevCount = ~0;
- LONG Delta;
-
- CurCount = Read8254Timer();
- do
- {
- PrevCount = CurCount;
- CurCount = Read8254Timer();
- Delta = CurCount - PrevCount;
-
- /*
- * This limit for delta seems arbitrary, but it isn't, it's
- * slightly above the level of error a buggy Mercury/Neptune
- * chipset timer can cause.
- */
-
- }
- while (Delta < 300);
-}
-
-#define HZ (100)
-#define APIC_DIVISOR (16)
-
-VOID APICSetupLVTT(ULONG ClockTicks)
-{
- ULONG tmp;
-
- tmp = GET_APIC_VERSION(APICRead(APIC_VER));
- if (!APIC_INTEGRATED(tmp))
- {
- tmp = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;;
- }
- else
- {
- /* Periodic timer */
- tmp = APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;;
- }
- APICWrite(APIC_LVTT, tmp);
-
- tmp = APICRead(APIC_TDCR);
- tmp &= ~(APIC_TDCR_1 | APIC_TIMER_BASE_DIV);
- tmp |= APIC_TDCR_16;
- APICWrite(APIC_TDCR, tmp);
- APICWrite(APIC_ICRT, ClockTicks / APIC_DIVISOR);
-}
-
-
-VOID APICCalibrateTimer(ULONG CPU)
-{
- ULARGE_INTEGER t1, t2;
- LONG tt1, tt2;
-
- DPRINT("Calibrating APIC timer for CPU %d\n", CPU);
-
- APICSetupLVTT(1000000000);
-
- /*
- * The timer chip counts down to zero. Let's wait
- * for a wraparound to start exact measurement:
- * (the current tick might have been already half done)
- */
- WaitFor8254Wraparound();
-
- /*
- * We wrapped around just now. Let's start
- */
- ReadPentiumClock(&t1);
- tt1 = APICRead(APIC_CCRT);
-
- WaitFor8254Wraparound();
-
-
- tt2 = APICRead(APIC_CCRT);
- ReadPentiumClock(&t2);
-
- CPUMap[CPU].BusSpeed = (HZ * (long)(tt1 - tt2) * APIC_DIVISOR);
- CPUMap[CPU].CoreSpeed = (HZ * (t2.QuadPart - t1.QuadPart));
-
- /* Setup timer for normal operation */
-// APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100); // 100ns
- APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 10000); // 10ms
-// APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100000); // 100ms
-
- DPRINT("CPU clock speed is %ld.%04ld MHz.\n",
- CPUMap[CPU].CoreSpeed/1000000,
- CPUMap[CPU].CoreSpeed%1000000);
-
- DPRINT("Host bus clock speed is %ld.%04ld MHz.\n",
- CPUMap[CPU].BusSpeed/1000000,
- CPUMap[CPU].BusSpeed%1000000);
-}
-
-VOID
-SetInterruptGate(ULONG index, ULONG address)
-{
- IDT_DESCRIPTOR *idt;
-
- idt = (IDT_DESCRIPTOR*)((ULONG)KeGetCurrentKPCR()->IDT + index * sizeof(IDT_DESCRIPTOR));
- idt->a = (((ULONG)address)&0xffff) + (KERNEL_CS << 16);
- idt->b = 0x8e00 + (((ULONG)address)&0xffff0000);
-}
-