]> git.proxmox.com Git - mirror_edk2.git/blame - PcAtChipsetPkg/8259InterruptControllerDxe/8259.c
Raise TPL to high to disable CPU interrupt before 8259 legacy base vector is changed...
[mirror_edk2.git] / PcAtChipsetPkg / 8259InterruptControllerDxe / 8259.c
CommitLineData
dfaaa5a5 1/** @file\r
1166d068 2 This contains the installation function for the driver.\r
47ca9c95 3\r
3d78c020 4Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
47ca9c95 5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
1166d068 12\r
13**/\r
14\r
15#include "8259.h"\r
16\r
1166d068 17//\r
90b8b0ec 18// Global for the Legacy 8259 Protocol that is produced by this driver\r
1166d068 19//\r
24115e44 20EFI_LEGACY_8259_PROTOCOL mInterrupt8259 = {\r
1166d068 21 Interrupt8259SetVectorBase,\r
22 Interrupt8259GetMask,\r
23 Interrupt8259SetMask,\r
24 Interrupt8259SetMode,\r
25 Interrupt8259GetVector,\r
26 Interrupt8259EnableIrq,\r
27 Interrupt8259DisableIrq,\r
28 Interrupt8259GetInterruptLine,\r
29 Interrupt8259EndOfInterrupt\r
30};\r
31\r
32//\r
33// Global for the handle that the Legacy 8259 Protocol is installed\r
34//\r
35EFI_HANDLE m8259Handle = NULL;\r
36\r
37UINT8 mMasterBase = 0xff;\r
38UINT8 mSlaveBase = 0xff;\r
39EFI_8259_MODE mMode = Efi8259ProtectedMode;\r
40UINT16 mProtectedModeMask = 0xffff;\r
856f592c 41UINT16 mLegacyModeMask;\r
1166d068 42UINT16 mProtectedModeEdgeLevel = 0x0000;\r
856f592c 43UINT16 mLegacyModeEdgeLevel;\r
1166d068 44\r
45//\r
46// Worker Functions\r
47//\r
90b8b0ec 48\r
49/**\r
50 Write to mask and edge/level triggered registers of master and slave PICs.\r
51\r
52 @param[in] Mask low byte for master PIC mask register,\r
53 high byte for slave PIC mask register.\r
54 @param[in] EdgeLevel low byte for master PIC edge/level triggered register,\r
55 high byte for slave PIC edge/level triggered register.\r
56\r
57**/\r
1166d068 58VOID\r
59Interrupt8259WriteMask (\r
60 IN UINT16 Mask,\r
61 IN UINT16 EdgeLevel\r
62 )\r
1166d068 63{\r
64 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, (UINT8) Mask);\r
65 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8) (Mask >> 8));\r
66 IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER, (UINT8) EdgeLevel);\r
67 IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE, (UINT8) (EdgeLevel >> 8));\r
68}\r
69\r
1166d068 70/**\r
90b8b0ec 71 Read from mask and edge/level triggered registers of master and slave PICs.\r
1166d068 72\r
90b8b0ec 73 @param[out] Mask low byte for master PIC mask register,\r
74 high byte for slave PIC mask register.\r
75 @param[out] EdgeLevel low byte for master PIC edge/level triggered register,\r
76 high byte for slave PIC edge/level triggered register.\r
1166d068 77\r
78**/\r
90b8b0ec 79VOID\r
80Interrupt8259ReadMask (\r
81 OUT UINT16 *Mask,\r
82 OUT UINT16 *EdgeLevel\r
83 )\r
1166d068 84{\r
a694b670 85 UINT16 MasterValue;\r
86 UINT16 SlaveValue;\r
87\r
1166d068 88 if (Mask != NULL) {\r
a694b670 89 MasterValue = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER);\r
90 SlaveValue = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE);\r
91\r
92 *Mask = (UINT16) (MasterValue | (SlaveValue << 8));\r
1166d068 93 }\r
94\r
95 if (EdgeLevel != NULL) {\r
a694b670 96 MasterValue = IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER);\r
97 SlaveValue = IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE);\r
98\r
99 *EdgeLevel = (UINT16) (MasterValue | (SlaveValue << 8));\r
1166d068 100 }\r
101}\r
90b8b0ec 102\r
1166d068 103//\r
90b8b0ec 104// Legacy 8259 Protocol Interface Functions\r
1166d068 105//\r
1166d068 106\r
90b8b0ec 107/**\r
108 Sets the base address for the 8259 master and slave PICs.\r
1166d068 109\r
90b8b0ec 110 @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance.\r
111 @param[in] MasterBase Interrupt vectors for IRQ0-IRQ7.\r
112 @param[in] SlaveBase Interrupt vectors for IRQ8-IRQ15.\r
1166d068 113\r
90b8b0ec 114 @retval EFI_SUCCESS The 8259 PIC was programmed successfully.\r
115 @retval EFI_DEVICE_ERROR There was an error while writing to the 8259 PIC.\r
1166d068 116\r
117**/\r
90b8b0ec 118EFI_STATUS\r
119EFIAPI\r
120Interrupt8259SetVectorBase (\r
121 IN EFI_LEGACY_8259_PROTOCOL *This,\r
122 IN UINT8 MasterBase,\r
123 IN UINT8 SlaveBase\r
124 )\r
1166d068 125{\r
4fde0f15 126 UINT8 Mask;\r
127 EFI_TPL OriginalTpl;\r
1166d068 128\r
4fde0f15 129 OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
90b8b0ec 130 //\r
131 // Set vector base for slave PIC\r
132 //\r
1166d068 133 if (SlaveBase != mSlaveBase) {\r
134 mSlaveBase = SlaveBase;\r
135\r
136 //\r
90b8b0ec 137 // Initialization sequence is needed for setting vector base.\r
138 //\r
139\r
140 //\r
141 // Preserve interrtup mask register before initialization sequence\r
142 // because it will be cleared during intialization\r
1166d068 143 //\r
144 Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE);\r
90b8b0ec 145\r
146 //\r
147 // ICW1: cascade mode, ICW4 write required\r
148 //\r
1166d068 149 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, 0x11);\r
90b8b0ec 150\r
151 //\r
152 // ICW2: new vector base (must be multiple of 8)\r
153 //\r
1166d068 154 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, mSlaveBase);\r
90b8b0ec 155\r
156 //\r
157 // ICW3: slave indentification code must be 2\r
158 //\r
1166d068 159 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x02);\r
90b8b0ec 160\r
161 //\r
162 // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor\r
163 //\r
1166d068 164 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x01);\r
90b8b0ec 165\r
166 //\r
167 // Restore interrupt mask register\r
168 //\r
1166d068 169 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, Mask);\r
170 }\r
171\r
90b8b0ec 172 //\r
173 // Set vector base for master PIC\r
174 //\r
1166d068 175 if (MasterBase != mMasterBase) {\r
176 mMasterBase = MasterBase;\r
177\r
178 //\r
90b8b0ec 179 // Initialization sequence is needed for setting vector base.\r
180 //\r
181\r
182 //\r
183 // Preserve interrtup mask register before initialization sequence\r
184 // because it will be cleared during intialization\r
1166d068 185 //\r
186 Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER);\r
90b8b0ec 187\r
188 //\r
189 // ICW1: cascade mode, ICW4 write required\r
190 //\r
1166d068 191 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, 0x11);\r
90b8b0ec 192\r
193 //\r
194 // ICW2: new vector base (must be multiple of 8)\r
195 //\r
1166d068 196 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, mMasterBase);\r
90b8b0ec 197\r
198 //\r
199 // ICW3: slave PIC is cascaded on IRQ2\r
200 //\r
1166d068 201 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x04);\r
90b8b0ec 202\r
203 //\r
204 // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor\r
205 //\r
1166d068 206 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x01);\r
90b8b0ec 207\r
208 //\r
209 // Restore interrupt mask register\r
210 //\r
1166d068 211 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, Mask);\r
212 }\r
213\r
ae6a37f0 214 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI);\r
215 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, LEGACY_8259_EOI);\r
4fde0f15 216 \r
217 gBS->RestoreTPL (OriginalTpl);\r
1166d068 218\r
219 return EFI_SUCCESS;\r
220}\r
221\r
90b8b0ec 222/**\r
223 Gets the current 16-bit real mode and 32-bit protected-mode IRQ masks.\r
224\r
225 @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance.\r
226 @param[out] LegacyMask 16-bit mode interrupt mask for IRQ0-IRQ15.\r
227 @param[out] LegacyEdgeLevel 16-bit mode edge/level mask for IRQ-IRQ15.\r
228 @param[out] ProtectedMask 32-bit mode interrupt mask for IRQ0-IRQ15.\r
229 @param[out] ProtectedEdgeLevel 32-bit mode edge/level mask for IRQ0-IRQ15.\r
230\r
231 @retval EFI_SUCCESS The 8259 PIC was programmed successfully.\r
232 @retval EFI_DEVICE_ERROR There was an error while reading the 8259 PIC.\r
233\r
234**/\r
1166d068 235EFI_STATUS\r
236EFIAPI\r
237Interrupt8259GetMask (\r
90b8b0ec 238 IN EFI_LEGACY_8259_PROTOCOL *This,\r
1166d068 239 OUT UINT16 *LegacyMask, OPTIONAL\r
240 OUT UINT16 *LegacyEdgeLevel, OPTIONAL\r
241 OUT UINT16 *ProtectedMask, OPTIONAL\r
242 OUT UINT16 *ProtectedEdgeLevel OPTIONAL\r
243 )\r
1166d068 244{\r
245 if (LegacyMask != NULL) {\r
246 *LegacyMask = mLegacyModeMask;\r
247 }\r
248\r
249 if (LegacyEdgeLevel != NULL) {\r
250 *LegacyEdgeLevel = mLegacyModeEdgeLevel;\r
251 }\r
252\r
253 if (ProtectedMask != NULL) {\r
254 *ProtectedMask = mProtectedModeMask;\r
255 }\r
256\r
257 if (ProtectedEdgeLevel != NULL) {\r
258 *ProtectedEdgeLevel = mProtectedModeEdgeLevel;\r
259 }\r
260\r
261 return EFI_SUCCESS;\r
262}\r
263\r
1166d068 264/**\r
90b8b0ec 265 Sets the current 16-bit real mode and 32-bit protected-mode IRQ masks.\r
1166d068 266\r
90b8b0ec 267 @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance.\r
268 @param[in] LegacyMask 16-bit mode interrupt mask for IRQ0-IRQ15.\r
269 @param[in] LegacyEdgeLevel 16-bit mode edge/level mask for IRQ-IRQ15.\r
270 @param[in] ProtectedMask 32-bit mode interrupt mask for IRQ0-IRQ15.\r
271 @param[in] ProtectedEdgeLevel 32-bit mode edge/level mask for IRQ0-IRQ15.\r
1166d068 272\r
90b8b0ec 273 @retval EFI_SUCCESS The 8259 PIC was programmed successfully.\r
274 @retval EFI_DEVICE_ERROR There was an error while writing the 8259 PIC.\r
1166d068 275\r
276**/\r
90b8b0ec 277EFI_STATUS\r
278EFIAPI\r
279Interrupt8259SetMask (\r
280 IN EFI_LEGACY_8259_PROTOCOL *This,\r
281 IN UINT16 *LegacyMask, OPTIONAL\r
282 IN UINT16 *LegacyEdgeLevel, OPTIONAL\r
283 IN UINT16 *ProtectedMask, OPTIONAL\r
284 IN UINT16 *ProtectedEdgeLevel OPTIONAL\r
285 )\r
1166d068 286{\r
287 if (LegacyMask != NULL) {\r
288 mLegacyModeMask = *LegacyMask;\r
289 }\r
290\r
291 if (LegacyEdgeLevel != NULL) {\r
292 mLegacyModeEdgeLevel = *LegacyEdgeLevel;\r
293 }\r
294\r
295 if (ProtectedMask != NULL) {\r
296 mProtectedModeMask = *ProtectedMask;\r
297 }\r
298\r
299 if (ProtectedEdgeLevel != NULL) {\r
300 mProtectedModeEdgeLevel = *ProtectedEdgeLevel;\r
301 }\r
302\r
303 return EFI_SUCCESS;\r
304}\r
305\r
1166d068 306/**\r
90b8b0ec 307 Sets the mode of the PICs.\r
1166d068 308\r
90b8b0ec 309 @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance.\r
310 @param[in] Mode 16-bit real or 32-bit protected mode.\r
311 @param[in] Mask The value with which to set the interrupt mask.\r
312 @param[in] EdgeLevel The value with which to set the edge/level mask.\r
1166d068 313\r
90b8b0ec 314 @retval EFI_SUCCESS The mode was set successfully.\r
315 @retval EFI_INVALID_PARAMETER The mode was not set.\r
1166d068 316\r
317**/\r
90b8b0ec 318EFI_STATUS\r
319EFIAPI\r
320Interrupt8259SetMode (\r
321 IN EFI_LEGACY_8259_PROTOCOL *This,\r
322 IN EFI_8259_MODE Mode,\r
323 IN UINT16 *Mask, OPTIONAL\r
324 IN UINT16 *EdgeLevel OPTIONAL\r
325 )\r
1166d068 326{\r
327 if (Mode == mMode) {\r
328 return EFI_SUCCESS;\r
329 }\r
330\r
331 if (Mode == Efi8259LegacyMode) {\r
332 //\r
90b8b0ec 333 // In Efi8259ProtectedMode, mask and edge/level trigger registers should\r
334 // be changed through this protocol, so we can track them in the\r
335 // corresponding module variables.\r
1166d068 336 //\r
337 Interrupt8259ReadMask (&mProtectedModeMask, &mProtectedModeEdgeLevel);\r
338\r
339 if (Mask != NULL) {\r
340 //\r
341 // Update the Mask for the new mode\r
342 //\r
343 mLegacyModeMask = *Mask;\r
344 }\r
345\r
346 if (EdgeLevel != NULL) {\r
347 //\r
348 // Update the Edge/Level triggered mask for the new mode\r
349 //\r
350 mLegacyModeEdgeLevel = *EdgeLevel;\r
351 }\r
352\r
353 mMode = Mode;\r
354\r
355 //\r
90b8b0ec 356 // Write new legacy mode mask/trigger level\r
1166d068 357 //\r
1166d068 358 Interrupt8259WriteMask (mLegacyModeMask, mLegacyModeEdgeLevel);\r
359\r
360 return EFI_SUCCESS;\r
361 }\r
362\r
363 if (Mode == Efi8259ProtectedMode) {\r
364 //\r
90b8b0ec 365 // Save the legacy mode mask/trigger level\r
1166d068 366 //\r
367 Interrupt8259ReadMask (&mLegacyModeMask, &mLegacyModeEdgeLevel);\r
368 //\r
369 // Always force Timer to be enabled after return from 16-bit code.\r
370 // This always insures that on next entry, timer is counting.\r
371 //\r
372 mLegacyModeMask &= 0xFFFE;\r
373\r
374 if (Mask != NULL) {\r
375 //\r
376 // Update the Mask for the new mode\r
377 //\r
378 mProtectedModeMask = *Mask;\r
379 }\r
380\r
381 if (EdgeLevel != NULL) {\r
382 //\r
383 // Update the Edge/Level triggered mask for the new mode\r
384 //\r
385 mProtectedModeEdgeLevel = *EdgeLevel;\r
386 }\r
387\r
388 mMode = Mode;\r
389\r
390 //\r
90b8b0ec 391 // Write new protected mode mask/trigger level\r
1166d068 392 //\r
1166d068 393 Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);\r
394\r
395 return EFI_SUCCESS;\r
396 }\r
397\r
398 return EFI_INVALID_PARAMETER;\r
399}\r
400\r
90b8b0ec 401/**\r
402 Translates the IRQ into a vector.\r
403\r
404 @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance.\r
405 @param[in] Irq IRQ0-IRQ15.\r
406 @param[out] Vector The vector that is assigned to the IRQ.\r
407\r
408 @retval EFI_SUCCESS The Vector that matches Irq was returned.\r
409 @retval EFI_INVALID_PARAMETER Irq is not valid.\r
410\r
411**/\r
1166d068 412EFI_STATUS\r
413EFIAPI\r
414Interrupt8259GetVector (\r
415 IN EFI_LEGACY_8259_PROTOCOL *This,\r
416 IN EFI_8259_IRQ Irq,\r
417 OUT UINT8 *Vector\r
418 )\r
1166d068 419{\r
3d78c020 420 if ((UINT32)Irq > Efi8259Irq15) {\r
1166d068 421 return EFI_INVALID_PARAMETER;\r
422 }\r
423\r
424 if (Irq <= Efi8259Irq7) {\r
425 *Vector = (UINT8) (mMasterBase + Irq);\r
426 } else {\r
427 *Vector = (UINT8) (mSlaveBase + (Irq - Efi8259Irq8));\r
428 }\r
429\r
430 return EFI_SUCCESS;\r
431}\r
432\r
1166d068 433/**\r
90b8b0ec 434 Enables the specified IRQ.\r
1166d068 435\r
90b8b0ec 436 @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance.\r
437 @param[in] Irq IRQ0-IRQ15.\r
438 @param[in] LevelTriggered 0 = Edge triggered; 1 = Level triggered.\r
1166d068 439\r
90b8b0ec 440 @retval EFI_SUCCESS The Irq was enabled on the 8259 PIC.\r
441 @retval EFI_INVALID_PARAMETER The Irq is not valid.\r
1166d068 442\r
443**/\r
90b8b0ec 444EFI_STATUS\r
445EFIAPI\r
446Interrupt8259EnableIrq (\r
447 IN EFI_LEGACY_8259_PROTOCOL *This,\r
448 IN EFI_8259_IRQ Irq,\r
449 IN BOOLEAN LevelTriggered\r
450 )\r
1166d068 451{\r
3d78c020 452 if ((UINT32)Irq > Efi8259Irq15) {\r
1166d068 453 return EFI_INVALID_PARAMETER;\r
454 }\r
455\r
a694b670 456 mProtectedModeMask = (UINT16) (mProtectedModeMask & ~(1 << Irq));\r
1166d068 457 if (LevelTriggered) {\r
a694b670 458 mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel | (1 << Irq));\r
1166d068 459 } else {\r
a694b670 460 mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1 << Irq));\r
1166d068 461 }\r
462\r
463 Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);\r
464\r
465 return EFI_SUCCESS;\r
466}\r
467\r
1166d068 468/**\r
90b8b0ec 469 Disables the specified IRQ.\r
1166d068 470\r
90b8b0ec 471 @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance.\r
472 @param[in] Irq IRQ0-IRQ15.\r
1166d068 473\r
90b8b0ec 474 @retval EFI_SUCCESS The Irq was disabled on the 8259 PIC.\r
475 @retval EFI_INVALID_PARAMETER The Irq is not valid.\r
1166d068 476\r
477**/\r
90b8b0ec 478EFI_STATUS\r
479EFIAPI\r
480Interrupt8259DisableIrq (\r
481 IN EFI_LEGACY_8259_PROTOCOL *This,\r
482 IN EFI_8259_IRQ Irq\r
483 )\r
1166d068 484{\r
3d78c020 485 if ((UINT32)Irq > Efi8259Irq15) {\r
1166d068 486 return EFI_INVALID_PARAMETER;\r
487 }\r
488\r
90b8b0ec 489 mProtectedModeMask = (UINT16) (mProtectedModeMask | (1 << Irq));\r
490\r
a694b670 491 mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1 << Irq));\r
1166d068 492\r
493 Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);\r
494\r
495 return EFI_SUCCESS;\r
496}\r
497\r
90b8b0ec 498/**\r
499 Reads the PCI configuration space to get the interrupt number that is assigned to the card.\r
500\r
501 @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance.\r
502 @param[in] PciHandle PCI function for which to return the vector.\r
503 @param[out] Vector IRQ number that corresponds to the interrupt line.\r
504\r
505 @retval EFI_SUCCESS The interrupt line value was read successfully.\r
506\r
507**/\r
1166d068 508EFI_STATUS\r
509EFIAPI\r
510Interrupt8259GetInterruptLine (\r
511 IN EFI_LEGACY_8259_PROTOCOL *This,\r
512 IN EFI_HANDLE PciHandle,\r
513 OUT UINT8 *Vector\r
514 )\r
1166d068 515{\r
ae6a37f0 516 EFI_PCI_IO_PROTOCOL *PciIo;\r
517 UINT8 InterruptLine;\r
518 EFI_STATUS Status;\r
519\r
520 Status = gBS->HandleProtocol (\r
521 PciHandle,\r
522 &gEfiPciIoProtocolGuid,\r
523 (VOID **) &PciIo\r
524 );\r
525 if (EFI_ERROR (Status)) {\r
526 return EFI_INVALID_PARAMETER;\r
527 }\r
528\r
529 PciIo->Pci.Read (\r
530 PciIo,\r
531 EfiPciIoWidthUint8,\r
532 PCI_INT_LINE_OFFSET,\r
533 1,\r
534 &InterruptLine\r
535 );\r
536 //\r
537 // Interrupt line is same location for standard PCI cards, standard\r
538 // bridge and CardBus bridge.\r
539 //\r
540 *Vector = InterruptLine;\r
541\r
542 return EFI_SUCCESS;\r
1166d068 543}\r
544\r
1166d068 545/**\r
90b8b0ec 546 Issues the End of Interrupt (EOI) commands to PICs.\r
1166d068 547\r
90b8b0ec 548 @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance.\r
549 @param[in] Irq The interrupt for which to issue the EOI command.\r
1166d068 550\r
90b8b0ec 551 @retval EFI_SUCCESS The EOI command was issued.\r
552 @retval EFI_INVALID_PARAMETER The Irq is not valid.\r
1166d068 553\r
554**/\r
90b8b0ec 555EFI_STATUS\r
556EFIAPI\r
557Interrupt8259EndOfInterrupt (\r
558 IN EFI_LEGACY_8259_PROTOCOL *This,\r
559 IN EFI_8259_IRQ Irq\r
560 )\r
1166d068 561{\r
3d78c020 562 if ((UINT32)Irq > Efi8259Irq15) {\r
1166d068 563 return EFI_INVALID_PARAMETER;\r
564 }\r
565\r
566 if (Irq >= Efi8259Irq8) {\r
567 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI);\r
568 }\r
569\r
570 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, LEGACY_8259_EOI);\r
571\r
572 return EFI_SUCCESS;\r
573}\r
574\r
90b8b0ec 575/**\r
576 Driver Entry point.\r
577\r
578 @param[in] ImageHandle ImageHandle of the loaded driver.\r
579 @param[in] SystemTable Pointer to the EFI System Table.\r
580\r
581 @retval EFI_SUCCESS One or more of the drivers returned a success code.\r
582 @retval !EFI_SUCCESS Error installing Legacy 8259 Protocol.\r
583\r
584**/\r
1166d068 585EFI_STATUS\r
586EFIAPI\r
587Install8259 (\r
588 IN EFI_HANDLE ImageHandle,\r
589 IN EFI_SYSTEM_TABLE *SystemTable\r
590 )\r
1166d068 591{\r
592 EFI_STATUS Status;\r
593 EFI_8259_IRQ Irq;\r
594\r
856f592c 595 //\r
596 // Initialze mask values from PCDs\r
597 //\r
598 mLegacyModeMask = PcdGet16 (Pcd8259LegacyModeMask);\r
599 mLegacyModeEdgeLevel = PcdGet16 (Pcd8259LegacyModeEdgeLevel);\r
600\r
1166d068 601 //\r
602 // Clear all pending interrupt\r
603 //\r
604 for (Irq = Efi8259Irq0; Irq <= Efi8259Irq15; Irq++) {\r
24115e44 605 Interrupt8259EndOfInterrupt (&mInterrupt8259, Irq);\r
1166d068 606 }\r
607\r
608 //\r
609 // Set the 8259 Master base to 0x68 and the 8259 Slave base to 0x70\r
610 //\r
24115e44 611 Status = Interrupt8259SetVectorBase (&mInterrupt8259, PROTECTED_MODE_BASE_VECTOR_MASTER, PROTECTED_MODE_BASE_VECTOR_SLAVE);\r
1166d068 612\r
613 //\r
614 // Set all 8259 interrupts to edge triggered and disabled\r
615 //\r
616 Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);\r
617\r
618 //\r
619 // Install 8259 Protocol onto a new handle\r
620 //\r
621 Status = gBS->InstallProtocolInterface (\r
622 &m8259Handle,\r
623 &gEfiLegacy8259ProtocolGuid,\r
624 EFI_NATIVE_INTERFACE,\r
24115e44 625 &mInterrupt8259\r
1166d068 626 );\r
1166d068 627 return Status;\r
628}\r