Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenioapic.c
Go to the documentation of this file.
00001 /* $Id$ 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS kernel 00005 * FILE: hal/halx86/mp/ioapic.c 00006 * PURPOSE: 00007 * PROGRAMMER: 00008 */ 00009 00010 /* INCLUDES *****************************************************************/ 00011 00012 #include <hal.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* GLOBALS *****************************************************************/ 00017 00018 MP_CONFIGURATION_INTSRC IRQMap[MAX_IRQ_SOURCE]; /* Map of all IRQs */ 00019 ULONG IRQCount = 0; /* Number of IRQs */ 00020 ULONG IrqApicMap[MAX_IRQ_SOURCE]; 00021 00022 UCHAR BUSMap[MAX_BUS]; /* Map of all buses in the system */ 00023 UCHAR PCIBUSMap[MAX_BUS]; /* Map of all PCI buses in the system */ 00024 00025 IOAPIC_INFO IOAPICMap[MAX_IOAPIC]; /* Map of all I/O APICs in the system */ 00026 ULONG IOAPICCount; /* Number of I/O APICs in the system */ 00027 00028 ULONG IRQVectorMap[MAX_IRQ_SOURCE]; /* IRQ to vector map */ 00029 00030 /* EISA interrupts are always polarity zero and can be edge or level 00031 * trigger depending on the ELCR value. If an interrupt is listed as 00032 * EISA conforming in the MP table, that means its trigger type must 00033 * be read in from the ELCR */ 00034 00035 #define default_EISA_trigger(idx) (EISA_ELCR_Read(IRQMap[idx].SrcBusIrq)) 00036 #define default_EISA_polarity(idx) (0) 00037 00038 /* ISA interrupts are always polarity zero edge triggered, 00039 * when listed as conforming in the MP table. */ 00040 00041 #define default_ISA_trigger(idx) (0) 00042 #define default_ISA_polarity(idx) (0) 00043 00044 /* PCI interrupts are always polarity one level triggered, 00045 * when listed as conforming in the MP table. */ 00046 00047 #define default_PCI_trigger(idx) (1) 00048 #define default_PCI_polarity(idx) (1) 00049 00050 /* MCA interrupts are always polarity zero level triggered, 00051 * when listed as conforming in the MP table. */ 00052 00053 #define default_MCA_trigger(idx) (1) 00054 #define default_MCA_polarity(idx) (0) 00055 00056 /***************************************************************************/ 00057 00058 extern VOID Disable8259AIrq(ULONG irq); 00059 ULONG IOAPICRead(ULONG Apic, ULONG Offset); 00060 VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value); 00061 00062 /* FUNCTIONS ***************************************************************/ 00063 00064 /* 00065 * EISA Edge/Level control register, ELCR 00066 */ 00067 static ULONG EISA_ELCR_Read(ULONG irq) 00068 { 00069 if (irq < 16) 00070 { 00071 PUCHAR port = (PUCHAR)(0x4d0 + (irq >> 3)); 00072 return (READ_PORT_UCHAR(port) >> (irq & 7)) & 1; 00073 } 00074 DPRINT("Broken MPtable reports ISA irq %d\n", irq); 00075 return 0; 00076 } 00077 00078 static ULONG 00079 IRQPolarity(ULONG idx) 00080 { 00081 ULONG bus = IRQMap[idx].SrcBusId; 00082 ULONG polarity; 00083 00084 /* 00085 * Determine IRQ line polarity (high active or low active): 00086 */ 00087 switch (IRQMap[idx].IrqFlag & 3) 00088 { 00089 case 0: /* conforms, ie. bus-type dependent polarity */ 00090 { 00091 switch (BUSMap[bus]) 00092 { 00093 case MP_BUS_ISA: /* ISA pin */ 00094 polarity = default_ISA_polarity(idx); 00095 break; 00096 00097 case MP_BUS_EISA: /* EISA pin */ 00098 polarity = default_EISA_polarity(idx); 00099 break; 00100 00101 case MP_BUS_PCI: /* PCI pin */ 00102 polarity = default_PCI_polarity(idx); 00103 break; 00104 00105 case MP_BUS_MCA: /* MCA pin */ 00106 polarity = default_MCA_polarity(idx); 00107 break; 00108 00109 default: 00110 DPRINT("Broken BIOS!!\n"); 00111 polarity = 1; 00112 } 00113 } 00114 break; 00115 00116 case 1: /* high active */ 00117 polarity = 0; 00118 break; 00119 00120 case 2: /* reserved */ 00121 DPRINT("Broken BIOS!!\n"); 00122 polarity = 1; 00123 break; 00124 00125 case 3: /* low active */ 00126 polarity = 1; 00127 break; 00128 00129 default: /* invalid */ 00130 DPRINT("Broken BIOS!!\n"); 00131 polarity = 1; 00132 } 00133 return polarity; 00134 } 00135 00136 static ULONG 00137 IRQTrigger(ULONG idx) 00138 { 00139 ULONG bus = IRQMap[idx].SrcBusId; 00140 ULONG trigger; 00141 00142 /* 00143 * Determine IRQ trigger mode (edge or level sensitive): 00144 */ 00145 switch ((IRQMap[idx].IrqFlag >> 2) & 3) 00146 { 00147 case 0: /* conforms, ie. bus-type dependent */ 00148 { 00149 switch (BUSMap[bus]) 00150 { 00151 case MP_BUS_ISA: /* ISA pin */ 00152 trigger = default_ISA_trigger(idx); 00153 break; 00154 00155 case MP_BUS_EISA: /* EISA pin */ 00156 trigger = default_EISA_trigger(idx); 00157 break; 00158 00159 case MP_BUS_PCI: /* PCI pin */ 00160 trigger = default_PCI_trigger(idx); 00161 break; 00162 00163 case MP_BUS_MCA: /* MCA pin */ 00164 trigger = default_MCA_trigger(idx); 00165 break; 00166 00167 default: 00168 DPRINT("Broken BIOS!!\n"); 00169 trigger = 1; 00170 } 00171 } 00172 break; 00173 00174 case 1: /* edge */ 00175 trigger = 0; 00176 break; 00177 00178 case 2: /* reserved */ 00179 DPRINT("Broken BIOS!!\n"); 00180 trigger = 1; 00181 break; 00182 00183 case 3: /* level */ 00184 trigger = 1; 00185 break; 00186 00187 default: /* invalid */ 00188 DPRINT("Broken BIOS!!\n"); 00189 trigger = 0; 00190 } 00191 return trigger; 00192 } 00193 00194 static ULONG 00195 Pin2Irq(ULONG idx, 00196 ULONG apic, 00197 ULONG pin) 00198 { 00199 ULONG irq, i; 00200 ULONG bus = IRQMap[idx].SrcBusId; 00201 00202 /* 00203 * Debugging check, we are in big trouble if this message pops up! 00204 */ 00205 if (IRQMap[idx].DstApicInt != pin) 00206 { 00207 DPRINT("broken BIOS or MPTABLE parser, ayiee!!\n"); 00208 } 00209 00210 switch (BUSMap[bus]) 00211 { 00212 case MP_BUS_ISA: /* ISA pin */ 00213 case MP_BUS_EISA: 00214 case MP_BUS_MCA: 00215 irq = IRQMap[idx].SrcBusIrq; 00216 break; 00217 00218 case MP_BUS_PCI: /* PCI pin */ 00219 /* 00220 * PCI IRQs are mapped in order 00221 */ 00222 i = irq = 0; 00223 while (i < apic) 00224 { 00225 irq += IOAPICMap[i++].EntryCount; 00226 } 00227 irq += pin; 00228 break; 00229 00230 default: 00231 DPRINT("Unknown bus type %d.\n",bus); 00232 irq = 0; 00233 } 00234 return irq; 00235 } 00236 00237 static ULONG 00238 AssignIrqVector(ULONG irq) 00239 { 00240 #if 0 00241 static ULONG current_vector = FIRST_DEVICE_VECTOR, vector_offset = 0; 00242 #endif 00243 ULONG vector; 00244 /* There may already have been assigned a vector for this IRQ */ 00245 vector = IRQVectorMap[irq]; 00246 if (vector > 0) 00247 { 00248 return vector; 00249 } 00250 #if 0 00251 if (current_vector > FIRST_SYSTEM_VECTOR) 00252 { 00253 vector_offset++; 00254 current_vector = FIRST_DEVICE_VECTOR + vector_offset; 00255 } 00256 else if (current_vector == FIRST_SYSTEM_VECTOR) 00257 { 00258 DPRINT1("Ran out of interrupt sources!"); 00259 ASSERT(FALSE); 00260 } 00261 00262 vector = current_vector; 00263 IRQVectorMap[irq] = vector; 00264 current_vector += 8; 00265 return vector; 00266 #else 00267 vector = IRQ2VECTOR(irq); 00268 IRQVectorMap[irq] = vector; 00269 return vector; 00270 #endif 00271 } 00272 00273 /* 00274 * Find the IRQ entry number of a certain pin. 00275 */ 00276 static ULONG 00277 IOAPICGetIrqEntry(ULONG apic, 00278 ULONG pin, 00279 ULONG type) 00280 { 00281 ULONG i; 00282 00283 for (i = 0; i < IRQCount; i++) 00284 { 00285 if (IRQMap[i].IrqType == type && 00286 (IRQMap[i].DstApicId == IOAPICMap[apic].ApicId || IRQMap[i].DstApicId == MP_APIC_ALL) && 00287 IRQMap[i].DstApicInt == pin) 00288 { 00289 return i; 00290 } 00291 } 00292 return -1; 00293 } 00294 00295 00296 VOID 00297 IOAPICSetupIrqs(VOID) 00298 { 00299 IOAPIC_ROUTE_ENTRY entry; 00300 ULONG apic, pin, idx, irq, first_notcon = 1, vector, trigger; 00301 00302 DPRINT("Init IO_APIC IRQs\n"); 00303 00304 /* Setup IRQ to vector translation map */ 00305 memset(&IRQVectorMap, 0, sizeof(IRQVectorMap)); 00306 00307 for (apic = 0; apic < IOAPICCount; apic++) 00308 { 00309 for (pin = 0; pin < IOAPICMap[apic].EntryCount; pin++) 00310 { 00311 /* 00312 * add it to the IO-APIC irq-routing table 00313 */ 00314 memset(&entry,0,sizeof(entry)); 00315 00316 entry.delivery_mode = (APIC_DM_LOWEST >> 8); 00317 entry.dest_mode = 1; /* logical delivery */ 00318 entry.mask = 1; /* disable IRQ */ 00319 entry.dest.logical.logical_dest = 0; 00320 00321 idx = IOAPICGetIrqEntry(apic,pin,INT_VECTORED); 00322 if (idx == (ULONG)-1) 00323 { 00324 if (first_notcon) 00325 { 00326 DPRINT(" IO-APIC (apicid-pin) %d-%d\n", IOAPICMap[apic].ApicId, pin); 00327 first_notcon = 0; 00328 } 00329 else 00330 { 00331 DPRINT(", %d-%d\n", IOAPICMap[apic].ApicId, pin); 00332 } 00333 continue; 00334 } 00335 00336 trigger = IRQTrigger(idx); 00337 entry.polarity = IRQPolarity(idx); 00338 00339 if (trigger) 00340 { 00341 entry.trigger = 1; 00342 } 00343 00344 irq = Pin2Irq(idx, apic, pin); 00345 00346 vector = AssignIrqVector(irq); 00347 entry.vector = vector; 00348 00349 DPRINT("vector 0x%.08x assigned to irq 0x%.02x\n", vector, irq); 00350 00351 if (irq == 0) 00352 { 00353 /* Mask timer IRQ */ 00354 entry.mask = 1; 00355 } 00356 00357 if ((apic == 0) && (irq < 16)) 00358 { 00359 Disable8259AIrq(irq); 00360 } 00361 IOAPICWrite(apic, IOAPIC_REDTBL+2*pin+1, *(((PULONG)&entry)+1)); 00362 IOAPICWrite(apic, IOAPIC_REDTBL+2*pin, *(((PULONG)&entry)+0)); 00363 00364 IrqApicMap[irq] = apic; 00365 00366 DPRINT("Vector %x, Pin %x, Irq %x\n", vector, pin, irq); 00367 } 00368 } 00369 } 00370 00371 static VOID 00372 IOAPICClearPin(ULONG Apic, ULONG Pin) 00373 { 00374 IOAPIC_ROUTE_ENTRY Entry; 00375 00376 DPRINT("IOAPICClearPin(Apic %d, Pin %d\n", Apic, Pin); 00377 /* 00378 * Disable it in the IO-APIC irq-routing table 00379 */ 00380 memset(&Entry, 0, sizeof(Entry)); 00381 Entry.mask = 1; 00382 00383 IOAPICWrite(Apic, IOAPIC_REDTBL + 2 * Pin, *(((PULONG)&Entry) + 0)); 00384 IOAPICWrite(Apic, IOAPIC_REDTBL + 1 + 2 * Pin, *(((PULONG)&Entry) + 1)); 00385 } 00386 00387 static VOID 00388 IOAPICClear(ULONG Apic) 00389 { 00390 ULONG Pin; 00391 00392 for (Pin = 0; Pin < /*IOAPICMap[Apic].EntryCount*/24; Pin++) 00393 { 00394 IOAPICClearPin(Apic, Pin); 00395 } 00396 } 00397 00398 static VOID 00399 IOAPICClearAll(VOID) 00400 { 00401 ULONG Apic; 00402 00403 for (Apic = 0; Apic < IOAPICCount; Apic++) 00404 { 00405 IOAPICClear(Apic); 00406 } 00407 } 00408 00409 VOID 00410 IOAPICEnable(VOID) 00411 { 00412 ULONG i, tmp; 00413 00414 /* Setup IRQ to vector translation map */ 00415 memset(&IRQVectorMap, 0, sizeof(IRQVectorMap)); 00416 00417 /* 00418 * The number of IO-APIC IRQ registers (== #pins): 00419 */ 00420 for (i = 0; i < IOAPICCount; i++) 00421 { 00422 tmp = IOAPICRead(i, IOAPIC_VER); 00423 IOAPICMap[i].EntryCount = GET_IOAPIC_MRE(tmp) + 1; 00424 } 00425 00426 /* 00427 * Do not trust the IO-APIC being empty at bootup 00428 */ 00429 IOAPICClearAll(); 00430 } 00431 00432 VOID 00433 IOAPICSetupIds(VOID) 00434 { 00435 ULONG tmp, apic, i; 00436 UCHAR old_id; 00437 00438 /* 00439 * Set the IOAPIC ID to the value stored in the MPC table. 00440 */ 00441 for (apic = 0; apic < IOAPICCount; apic++) 00442 { 00443 00444 /* Read the register 0 value */ 00445 tmp = IOAPICRead(apic, IOAPIC_ID); 00446 00447 old_id = IOAPICMap[apic].ApicId; 00448 00449 if (IOAPICMap[apic].ApicId >= 0xf) 00450 { 00451 DPRINT1("BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", 00452 apic, IOAPICMap[apic].ApicId); 00453 DPRINT1("... fixing up to %d. (tell your hw vendor)\n", 00454 GET_IOAPIC_ID(tmp)); 00455 IOAPICMap[apic].ApicId = GET_IOAPIC_ID(tmp); 00456 } 00457 00458 /* 00459 * We need to adjust the IRQ routing table 00460 * if the ID changed. 00461 */ 00462 if (old_id != IOAPICMap[apic].ApicId) 00463 { 00464 for (i = 0; i < IRQCount; i++) 00465 { 00466 if (IRQMap[i].DstApicId == old_id) 00467 { 00468 IRQMap[i].DstApicId = IOAPICMap[apic].ApicId; 00469 } 00470 } 00471 } 00472 00473 /* 00474 * Read the right value from the MPC table and 00475 * write it into the ID register. 00476 */ 00477 DPRINT("Changing IO-APIC physical APIC ID to %d\n", 00478 IOAPICMap[apic].ApicId); 00479 00480 tmp &= ~IOAPIC_ID_MASK; 00481 tmp |= SET_IOAPIC_ID(IOAPICMap[apic].ApicId); 00482 00483 IOAPICWrite(apic, IOAPIC_ID, tmp); 00484 00485 /* 00486 * Sanity check 00487 */ 00488 tmp = IOAPICRead(apic, 0); 00489 if (GET_IOAPIC_ID(tmp) != IOAPICMap[apic].ApicId) 00490 { 00491 DPRINT1("Could not set I/O APIC ID!\n"); 00492 ASSERT(FALSE); 00493 } 00494 } 00495 } 00496 00497 /* This is performance critical and should probably be done in assembler */ 00498 VOID IOAPICMaskIrq(ULONG Irq) 00499 { 00500 IOAPIC_ROUTE_ENTRY Entry; 00501 ULONG Apic = IrqApicMap[Irq]; 00502 00503 *(((PULONG)&Entry)+0) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq); 00504 *(((PULONG)&Entry)+1) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq+1); 00505 Entry.dest.logical.logical_dest &= ~(1 << KeGetCurrentProcessorNumber()); 00506 if (Entry.dest.logical.logical_dest == 0) 00507 { 00508 Entry.mask = 1; 00509 } 00510 IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq+1, *(((PULONG)&Entry)+1)); 00511 IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *(((PULONG)&Entry)+0)); 00512 } 00513 00514 /* This is performance critical and should probably be done in assembler */ 00515 VOID IOAPICUnmaskIrq(ULONG Irq) 00516 { 00517 IOAPIC_ROUTE_ENTRY Entry; 00518 ULONG Apic = IrqApicMap[Irq]; 00519 00520 *(((PULONG)&Entry)+0) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq); 00521 *(((PULONG)&Entry)+1) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq+1); 00522 Entry.dest.logical.logical_dest |= 1 << KeGetCurrentProcessorNumber(); 00523 Entry.mask = 0; 00524 IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq+1, *(((PULONG)&Entry)+1)); 00525 IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *(((PULONG)&Entry)+0)); 00526 } 00527 00528 VOID IOAPICDump(VOID) 00529 { 00530 ULONG apic, i; 00531 ULONG reg0, reg1, reg2=0; 00532 00533 DbgPrint("Number of MP IRQ sources: %d.\n", IRQCount); 00534 for (i = 0; i < IOAPICCount; i++) 00535 { 00536 DbgPrint("Number of IO-APIC #%d registers: %d.\n", 00537 IOAPICMap[i].ApicId, 00538 IOAPICMap[i].EntryCount); 00539 } 00540 00541 /* 00542 * We are a bit conservative about what we expect. We have to 00543 * know about every hardware change ASAP. 00544 */ 00545 DbgPrint("Testing the IO APIC.......................\n"); 00546 00547 for (apic = 0; apic < IOAPICCount; apic++) 00548 { 00549 reg0 = IOAPICRead(apic, IOAPIC_ID); 00550 reg1 = IOAPICRead(apic, IOAPIC_VER); 00551 if (GET_IOAPIC_VERSION(reg1) >= 0x10) 00552 { 00553 reg2 = IOAPICRead(apic, IOAPIC_ARB); 00554 } 00555 00556 DbgPrint("\n"); 00557 DbgPrint("IO APIC #%d......\n", IOAPICMap[apic].ApicId); 00558 DbgPrint(".... register #00: %08X\n", reg0); 00559 DbgPrint("....... : physical APIC id: %02X\n", GET_IOAPIC_ID(reg0)); 00560 if (reg0 & 0xF0FFFFFF) 00561 { 00562 DbgPrint(" WARNING: Unexpected IO-APIC\n"); 00563 } 00564 00565 DbgPrint(".... register #01: %08X\n", reg1); 00566 i = GET_IOAPIC_MRE(reg1); 00567 00568 DbgPrint("....... : max redirection entries: %04X\n", i); 00569 if ((i != 0x0f) && /* older (Neptune) boards */ 00570 (i != 0x17) && /* typical ISA+PCI boards */ 00571 (i != 0x1b) && /* Compaq Proliant boards */ 00572 (i != 0x1f) && /* dual Xeon boards */ 00573 (i != 0x22) && /* bigger Xeon boards */ 00574 (i != 0x2E) && 00575 (i != 0x3F)) 00576 { 00577 DbgPrint(" WARNING: Unexpected IO-APIC\n"); 00578 } 00579 00580 i = GET_IOAPIC_VERSION(reg1); 00581 DbgPrint("....... : IO APIC version: %04X\n", i); 00582 if ((i != 0x01) && /* 82489DX IO-APICs */ 00583 (i != 0x10) && /* oldest IO-APICs */ 00584 (i != 0x11) && /* Pentium/Pro IO-APICs */ 00585 (i != 0x13)) /* Xeon IO-APICs */ 00586 { 00587 DbgPrint(" WARNING: Unexpected IO-APIC\n"); 00588 } 00589 00590 if (reg1 & 0xFF00FF00) 00591 { 00592 DbgPrint(" WARNING: Unexpected IO-APIC\n"); 00593 } 00594 00595 if (GET_IOAPIC_VERSION(reg1) >= 0x10) 00596 { 00597 DbgPrint(".... register #02: %08X\n", reg2); 00598 DbgPrint("....... : arbitration: %02X\n", 00599 GET_IOAPIC_ARB(reg2)); 00600 if (reg2 & 0xF0FFFFFF) 00601 { 00602 DbgPrint(" WARNING: Unexpected IO-APIC\n"); 00603 } 00604 } 00605 00606 DbgPrint(".... IRQ redirection table:\n"); 00607 DbgPrint(" NR Log Phy Mask Trig IRR Pol" 00608 " Stat Dest Deli Vect: \n"); 00609 00610 for (i = 0; i <= GET_IOAPIC_MRE(reg1); i++) 00611 { 00612 IOAPIC_ROUTE_ENTRY entry; 00613 00614 *(((PULONG)&entry)+0) = IOAPICRead(apic, 0x10+i*2); 00615 *(((PULONG)&entry)+1) = IOAPICRead(apic, 0x11+i*2); 00616 00617 DbgPrint(" %02x %03X %02X ", 00618 i, 00619 entry.dest.logical.logical_dest, 00620 entry.dest.physical.physical_dest); 00621 00622 DbgPrint("%C %C %1d %C %C %C %03X %02X\n", 00623 (entry.mask == 0) ? 'U' : 'M', // Unmasked/masked 00624 (entry.trigger == 0) ? 'E' : 'L', // Edge/level sensitive 00625 entry.irr, 00626 (entry.polarity == 0) ? 'H' : 'L', // Active high/active low 00627 (entry.delivery_status == 0) ? 'I' : 'S', // Idle / send pending 00628 (entry.dest_mode == 0) ? 'P' : 'L', // Physical logical 00629 entry.delivery_mode, 00630 entry.vector); 00631 } 00632 } 00633 00634 DbgPrint(".................................... done.\n"); 00635 } 00636 00637 VOID 00638 HaliReconfigurePciInterrupts(VOID) 00639 { 00640 ULONG i; 00641 00642 for (i = 0; i < IRQCount; i++) 00643 { 00644 if (BUSMap[IRQMap[i].SrcBusId] == MP_BUS_PCI) 00645 { 00646 DPRINT("%02x: IrqType %02x, IrqFlag %02x, SrcBusId %02x, SrcBusIrq %02x" 00647 ", DstApicId %02x, DstApicInt %02x\n", 00648 i, IRQMap[i].IrqType, IRQMap[i].IrqFlag, IRQMap[i].SrcBusId, 00649 IRQMap[i].SrcBusIrq, IRQMap[i].DstApicId, IRQMap[i].DstApicInt); 00650 00651 HalSetBusDataByOffset(PCIConfiguration, 00652 IRQMap[i].SrcBusId, 00653 (IRQMap[i].SrcBusIrq >> 2) & 0x1f, 00654 &IRQMap[i].DstApicInt, 00655 0x3c /*PCI_INTERRUPT_LINE*/, 00656 1); 00657 00658 } 00659 } 00660 } 00661 00662 VOID Disable8259AIrq(ULONG irq) 00663 { 00664 UCHAR tmp; 00665 00666 if (irq >= 8) 00667 { 00668 tmp = READ_PORT_UCHAR((PUCHAR)0xA1); 00669 tmp |= (1 << (irq - 8)); 00670 WRITE_PORT_UCHAR((PUCHAR)0xA1, tmp); 00671 } 00672 else 00673 { 00674 tmp = READ_PORT_UCHAR((PUCHAR)0x21); 00675 tmp |= (1 << irq); 00676 WRITE_PORT_UCHAR((PUCHAR)0x21, tmp); 00677 } 00678 } 00679 00680 ULONG IOAPICRead(ULONG Apic, ULONG Offset) 00681 { 00682 PULONG Base; 00683 00684 Base = (PULONG)IOAPICMap[Apic].ApicAddress; 00685 *Base = Offset; 00686 return *((PULONG)((ULONG)Base + IOAPIC_IOWIN)); 00687 } 00688 00689 VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value) 00690 { 00691 PULONG Base; 00692 00693 Base = (PULONG)IOAPICMap[Apic].ApicAddress; 00694 *Base = Offset; 00695 *((PULONG)((ULONG)Base + IOAPIC_IOWIN)) = Value; 00696 } 00697 00698 /* EOF */ Generated on Sun May 27 2012 04:28:44 for ReactOS by
1.7.6.1
|