]> git.proxmox.com Git - mirror_edk2.git/blame - PcAtChipsetPkg/8259InterruptControllerDxe/8259.c
Move IntelFrameworkModulePkg/Universal/Legacy8259Dxe to
[mirror_edk2.git] / PcAtChipsetPkg / 8259InterruptControllerDxe / 8259.c
CommitLineData
1166d068 1/**@file\r
2 This contains the installation function for the driver.\r
3 \r
a694b670 4Copyright (c) 2005 - 2008, Intel Corporation \r
1166d068 5All rights reserved. This 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
12\r
13**/\r
14\r
15#include "8259.h"\r
16\r
1166d068 17//\r
18// Global for the Legacy 8259 Protocol that is prodiced by this driver\r
19//\r
20EFI_LEGACY_8259_PROTOCOL m8259 = {\r
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
41UINT16 mLegacyModeMask = 0x06b8;\r
42UINT16 mProtectedModeEdgeLevel = 0x0000;\r
43UINT16 mLegacyModeEdgeLevel = 0x0000;\r
44\r
45//\r
46// Worker Functions\r
47//\r
1166d068 48VOID\r
49Interrupt8259WriteMask (\r
50 IN UINT16 Mask,\r
51 IN UINT16 EdgeLevel\r
52 )\r
53/**\r
54\r
55 Routine Description:\r
56 Sets the 8250 mask to the valud specified by Mask\r
57\r
58 Arguments:\r
59 Mask - A 16 bit valute that represents the master and slave mask values\r
60\r
61 Returns:\r
62 None\r
63\r
64**/\r
65// TODO: EdgeLevel - add argument and description to function comment\r
66{\r
67 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, (UINT8) Mask);\r
68 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8) (Mask >> 8));\r
69 IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER, (UINT8) EdgeLevel);\r
70 IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE, (UINT8) (EdgeLevel >> 8));\r
71}\r
72\r
73VOID\r
74Interrupt8259ReadMask (\r
75 IN UINT16 *Mask,\r
76 IN UINT16 *EdgeLevel\r
77 )\r
78/**\r
79\r
80 Routine Description:\r
81 Sets the 8250 mask to the valud specified by Mask\r
82\r
83 Arguments:\r
84 Mask - A 16 bit valute that represents the master and slave mask values\r
85\r
86 Returns:\r
87 None\r
88\r
89**/\r
90// TODO: EdgeLevel - add argument and description to function comment\r
91{\r
a694b670 92 UINT16 MasterValue;\r
93 UINT16 SlaveValue;\r
94\r
1166d068 95 if (Mask != NULL) {\r
a694b670 96 MasterValue = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER);\r
97 SlaveValue = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE);\r
98\r
99 *Mask = (UINT16) (MasterValue | (SlaveValue << 8));\r
1166d068 100 }\r
101\r
102 if (EdgeLevel != NULL) {\r
a694b670 103 MasterValue = IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER);\r
104 SlaveValue = IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE);\r
105\r
106 *EdgeLevel = (UINT16) (MasterValue | (SlaveValue << 8));\r
1166d068 107 }\r
108}\r
109//\r
110// Legacy 8259 Protocol Interface Function\r
111//\r
112EFI_STATUS\r
113EFIAPI\r
114Interrupt8259SetVectorBase (\r
115 IN EFI_LEGACY_8259_PROTOCOL *This,\r
116 IN UINT8 MasterBase,\r
117 IN UINT8 SlaveBase\r
118 )\r
119/**\r
120\r
121 Routine Description:\r
122 Sets the base vector for the 8250 Master and Slave interrupt controllers\r
123\r
124 Arguments:\r
125 This - Protocol instance pointer.\r
126 MasterBase - Base vector of the 8259 Master\r
127 SlaveBase - Base vector of the 8259 Slave\r
128\r
129 Returns:\r
130 EFI_SUCCESS - 8259 programmed\r
131\r
132**/\r
133{\r
134 UINT8 Mask;\r
135\r
136 if (SlaveBase != mSlaveBase) {\r
137 mSlaveBase = SlaveBase;\r
138\r
139 //\r
140 // Initialize Slave interrupt controller.\r
141 //\r
142 Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE);\r
143 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, 0x11);\r
144 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, mSlaveBase);\r
145 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x02);\r
146 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x01);\r
147 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, Mask);\r
148 }\r
149\r
150 if (MasterBase != mMasterBase) {\r
151 mMasterBase = MasterBase;\r
152\r
153 //\r
154 // Initialize Master interrupt controller.\r
155 //\r
156 Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER);\r
157 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, 0x11);\r
158 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, mMasterBase);\r
159 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x04);\r
160 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x01);\r
161 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, Mask);\r
162 }\r
163\r
164 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, 0x20);\r
165 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, 0x20);\r
166\r
167 return EFI_SUCCESS;\r
168}\r
169\r
170EFI_STATUS\r
171EFIAPI\r
172Interrupt8259GetMask (\r
173 IN EFI_LEGACY_8259_PROTOCOL * This,\r
174 OUT UINT16 *LegacyMask, OPTIONAL\r
175 OUT UINT16 *LegacyEdgeLevel, OPTIONAL\r
176 OUT UINT16 *ProtectedMask, OPTIONAL\r
177 OUT UINT16 *ProtectedEdgeLevel OPTIONAL\r
178 )\r
179/**\r
180\r
181 Routine Description:\r
182 Get the 8259 master and slave address that maps IRQ to processor interrupt \r
183 vector number. Get the Context of the device including the state of the\r
184 interrupt mask.\r
185\r
186 Arguments:\r
187 This - Protocol instance pointer.\r
188\r
189 Returns:\r
190 EFI_SUCCESS - 8259 programmed\r
191 EFI_DEVICE_ERROR - Error writting to 8259\r
192\r
193**/\r
194// TODO: LegacyMask - add argument and description to function comment\r
195// TODO: LegacyEdgeLevel - add argument and description to function comment\r
196// TODO: ProtectedMask - add argument and description to function comment\r
197// TODO: ProtectedEdgeLevel - add argument and description to function comment\r
198{\r
199 if (LegacyMask != NULL) {\r
200 *LegacyMask = mLegacyModeMask;\r
201 }\r
202\r
203 if (LegacyEdgeLevel != NULL) {\r
204 *LegacyEdgeLevel = mLegacyModeEdgeLevel;\r
205 }\r
206\r
207 if (ProtectedMask != NULL) {\r
208 *ProtectedMask = mProtectedModeMask;\r
209 }\r
210\r
211 if (ProtectedEdgeLevel != NULL) {\r
212 *ProtectedEdgeLevel = mProtectedModeEdgeLevel;\r
213 }\r
214\r
215 return EFI_SUCCESS;\r
216}\r
217\r
218EFI_STATUS\r
219EFIAPI\r
220Interrupt8259SetMask (\r
221 IN EFI_LEGACY_8259_PROTOCOL * This,\r
222 IN UINT16 *LegacyMask, OPTIONAL\r
223 IN UINT16 *LegacyEdgeLevel, OPTIONAL\r
224 IN UINT16 *ProtectedMask, OPTIONAL\r
225 IN UINT16 *ProtectedEdgeLevel OPTIONAL\r
226 )\r
227/**\r
228\r
229 Routine Description:\r
230 Set the 8259 interrupt and edge/level masks for legacy and/or protected \r
231 mode operation. This routine does not touch the hardware but only the\r
232 RAM copies of the masks.\r
233\r
234 Arguments:\r
235 This - Protocol instance pointer.\r
236\r
237 Returns:\r
238 EFI_SUCCESS - 8259 masks updated\r
239\r
240**/\r
241// TODO: LegacyMask - add argument and description to function comment\r
242// TODO: LegacyEdgeLevel - add argument and description to function comment\r
243// TODO: ProtectedMask - add argument and description to function comment\r
244// TODO: ProtectedEdgeLevel - add argument and description to function comment\r
245{\r
246 if (LegacyMask != NULL) {\r
247 mLegacyModeMask = *LegacyMask;\r
248 }\r
249\r
250 if (LegacyEdgeLevel != NULL) {\r
251 mLegacyModeEdgeLevel = *LegacyEdgeLevel;\r
252 }\r
253\r
254 if (ProtectedMask != NULL) {\r
255 mProtectedModeMask = *ProtectedMask;\r
256 }\r
257\r
258 if (ProtectedEdgeLevel != NULL) {\r
259 mProtectedModeEdgeLevel = *ProtectedEdgeLevel;\r
260 }\r
261\r
262 return EFI_SUCCESS;\r
263}\r
264\r
265EFI_STATUS\r
266EFIAPI\r
267Interrupt8259SetMode (\r
268 IN EFI_LEGACY_8259_PROTOCOL * This,\r
269 IN EFI_8259_MODE Mode,\r
270 IN UINT16 *Mask, OPTIONAL\r
271 IN UINT16 *EdgeLevel OPTIONAL\r
272 )\r
273/**\r
274\r
275 Routine Description:\r
276 Set the 8259 master and slave address that maps IRQ to processor interrupt \r
277 vector number. Restore the Context of the device, so that the interrupt\r
278 mask is put back in it's previous mode.\r
279\r
280 Arguments:\r
281 This - Protocol instance pointer.\r
282 Mode - \r
283 Mask -\r
284\r
285 Returns:\r
286 EFI_SUCCESS - 8259 programmed\r
287 EFI_DEVICE_ERROR - Error writting to 8259\r
288\r
289**/\r
290// TODO: EdgeLevel - add argument and description to function comment\r
291// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
292{\r
293 if (Mode == mMode) {\r
294 return EFI_SUCCESS;\r
295 }\r
296\r
297 if (Mode == Efi8259LegacyMode) {\r
298 //\r
299 // Save the protected mode mask\r
300 //\r
301 Interrupt8259ReadMask (&mProtectedModeMask, &mProtectedModeEdgeLevel);\r
302\r
303 if (Mask != NULL) {\r
304 //\r
305 // Update the Mask for the new mode\r
306 //\r
307 mLegacyModeMask = *Mask;\r
308 }\r
309\r
310 if (EdgeLevel != NULL) {\r
311 //\r
312 // Update the Edge/Level triggered mask for the new mode\r
313 //\r
314 mLegacyModeEdgeLevel = *EdgeLevel;\r
315 }\r
316\r
317 mMode = Mode;\r
318\r
319 //\r
320 // Set 8259 Vector Base\r
321 //\r
322 //\r
323 Interrupt8259SetVectorBase (This, LEGACY_MODE_BASE_VECTOR_MASTER, LEGACY_MODE_BASE_VECTOR_SLAVE);\r
324\r
325 //\r
326 // Enable Interrupts\r
327 //\r
328 Interrupt8259WriteMask (mLegacyModeMask, mLegacyModeEdgeLevel);\r
329\r
330 return EFI_SUCCESS;\r
331 }\r
332\r
333 if (Mode == Efi8259ProtectedMode) {\r
334 //\r
335 // Save the legacy mode mask\r
336 //\r
337 Interrupt8259ReadMask (&mLegacyModeMask, &mLegacyModeEdgeLevel);\r
338 //\r
339 // Always force Timer to be enabled after return from 16-bit code.\r
340 // This always insures that on next entry, timer is counting.\r
341 //\r
342 mLegacyModeMask &= 0xFFFE;\r
343\r
344 if (Mask != NULL) {\r
345 //\r
346 // Update the Mask for the new mode\r
347 //\r
348 mProtectedModeMask = *Mask;\r
349 }\r
350\r
351 if (EdgeLevel != NULL) {\r
352 //\r
353 // Update the Edge/Level triggered mask for the new mode\r
354 //\r
355 mProtectedModeEdgeLevel = *EdgeLevel;\r
356 }\r
357\r
358 mMode = Mode;\r
359\r
360 //\r
361 // Set 8259 Vector Base\r
362 //\r
363 //\r
364 Interrupt8259SetVectorBase (This, PROTECTED_MODE_BASE_VECTOR_MASTER, PROTECTED_MODE_BASE_VECTOR_SLAVE);\r
365\r
366 //\r
367 // Enable Interrupts\r
368 //\r
369 Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);\r
370\r
371 return EFI_SUCCESS;\r
372 }\r
373\r
374 return EFI_INVALID_PARAMETER;\r
375}\r
376\r
377EFI_STATUS\r
378EFIAPI\r
379Interrupt8259GetVector (\r
380 IN EFI_LEGACY_8259_PROTOCOL *This,\r
381 IN EFI_8259_IRQ Irq,\r
382 OUT UINT8 *Vector\r
383 )\r
384/**\r
385\r
386 Routine Description:\r
387 Convert from IRQ to processor interrupt vector number.\r
388\r
389 Arguments:\r
390 This - Protocol instance pointer.\r
391 Irq - 8259 IRQ0 - IRQ15\r
392 Vector - Processor vector number that matches Irq\r
393\r
394 Returns:\r
395 EFI_SUCCESS - The Vector matching Irq is returned\r
396 EFI_INVALID_PARAMETER - Irq not valid\r
397\r
398**/\r
399{\r
400 if (Irq < Efi8259Irq0 || Irq > Efi8259Irq15) {\r
401 return EFI_INVALID_PARAMETER;\r
402 }\r
403\r
404 if (Irq <= Efi8259Irq7) {\r
405 *Vector = (UINT8) (mMasterBase + Irq);\r
406 } else {\r
407 *Vector = (UINT8) (mSlaveBase + (Irq - Efi8259Irq8));\r
408 }\r
409\r
410 return EFI_SUCCESS;\r
411}\r
412\r
413EFI_STATUS\r
414EFIAPI\r
415Interrupt8259EnableIrq (\r
416 IN EFI_LEGACY_8259_PROTOCOL *This,\r
417 IN EFI_8259_IRQ Irq,\r
418 IN BOOLEAN LevelTriggered\r
419 )\r
420/**\r
421\r
422 Routine Description:\r
423 Enable Irq by unmasking interrupt in 8259\r
424\r
425 Arguments:\r
426 This - Protocol instance pointer.\r
427 Irq - 8259 IRQ0 - IRQ15\r
428\r
429 Returns:\r
430 EFI_SUCCESS - Irq enabled on 8259\r
431 EFI_INVALID_PARAMETER - Irq not valid\r
432\r
433**/\r
434// TODO: LevelTriggered - add argument and description to function comment\r
435{\r
436 if (Irq < Efi8259Irq0 || Irq > Efi8259Irq15) {\r
437 return EFI_INVALID_PARAMETER;\r
438 }\r
439\r
a694b670 440 mProtectedModeMask = (UINT16) (mProtectedModeMask & ~(1 << Irq));\r
1166d068 441 if (LevelTriggered) {\r
a694b670 442 mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel | (1 << Irq));\r
1166d068 443 } else {\r
a694b670 444 mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1 << Irq));\r
1166d068 445 }\r
446\r
447 Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);\r
448\r
449 return EFI_SUCCESS;\r
450}\r
451\r
452EFI_STATUS\r
453EFIAPI\r
454Interrupt8259DisableIrq (\r
455 IN EFI_LEGACY_8259_PROTOCOL *This,\r
456 IN EFI_8259_IRQ Irq\r
457 )\r
458/**\r
459\r
460 Routine Description:\r
461 Disable Irq by masking interrupt in 8259\r
462\r
463 Arguments:\r
464 This - Protocol instance pointer.\r
465 Irq - 8259 IRQ0 - IRQ15\r
466\r
467 Returns:\r
468 EFI_SUCCESS - Irq disabled on 8259\r
469 EFI_INVALID_PARAMETER - Irq not valid\r
470\r
471**/\r
472{\r
473 if (Irq < Efi8259Irq0 || Irq > Efi8259Irq15) {\r
474 return EFI_INVALID_PARAMETER;\r
475 }\r
476\r
a694b670 477 mProtectedModeMask = (UINT16) (mProtectedModeMask | (1 << Irq));\r
478 mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1 << Irq));\r
1166d068 479\r
480 Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);\r
481\r
482 return EFI_SUCCESS;\r
483}\r
484\r
485EFI_STATUS\r
486EFIAPI\r
487Interrupt8259GetInterruptLine (\r
488 IN EFI_LEGACY_8259_PROTOCOL *This,\r
489 IN EFI_HANDLE PciHandle,\r
490 OUT UINT8 *Vector\r
491 )\r
492/**\r
493\r
494 Routine Description:\r
495 PciHandle represents a PCI config space of a PCI function. Vector \r
496 represents Interrupt Pin (from PCI config space) and it is the data\r
497 that is programmed into the Interrupt Line (from the PCI config space)\r
498 register.\r
499\r
500 Arguments:\r
501 This - Protocol instance pointer.\r
502 PciHandle - PCI function to return vector for \r
503 Vector - Vector for fucntion that matches \r
504\r
505 Returns:\r
506 EFI_SUCCESS - A valid Vector is returned\r
507 EFI_INVALID_PARAMETER - PciHandle not valid\r
508\r
509**/\r
510{\r
511 return EFI_UNSUPPORTED;\r
512}\r
513\r
514EFI_STATUS\r
515EFIAPI\r
516Interrupt8259EndOfInterrupt (\r
517 IN EFI_LEGACY_8259_PROTOCOL *This,\r
518 IN EFI_8259_IRQ Irq\r
519 )\r
520/**\r
521\r
522 Routine Description:\r
523 Send an EOI to 8259\r
524\r
525 Arguments:\r
526 This - Protocol instance pointer.\r
527 Irq - 8259 IRQ0 - IRQ15\r
528\r
529 Returns:\r
530 EFI_SUCCESS - EOI successfully sent to 8259\r
531 EFI_INVALID_PARAMETER - Irq not valid\r
532\r
533**/\r
534{\r
535 if (Irq < Efi8259Irq0 || Irq > Efi8259Irq15) {\r
536 return EFI_INVALID_PARAMETER;\r
537 }\r
538\r
539 if (Irq >= Efi8259Irq8) {\r
540 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI);\r
541 }\r
542\r
543 IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, LEGACY_8259_EOI);\r
544\r
545 return EFI_SUCCESS;\r
546}\r
547\r
548//\r
549// Legacy 8259 Driver Entry Point\r
550//\r
551EFI_STATUS\r
552EFIAPI\r
553Install8259 (\r
554 IN EFI_HANDLE ImageHandle,\r
555 IN EFI_SYSTEM_TABLE *SystemTable\r
556 )\r
557/**\r
558\r
559Routine Description:\r
560 \r
561\r
562Arguments:\r
563\r
564 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
565\r
566Returns:\r
567\r
568 EFI_SUCCESS - Legacy 8259 Protocol Installed\r
569\r
570**/\r
571// TODO: ImageHandle - add argument and description to function comment\r
572// TODO: SystemTable - add argument and description to function comment\r
573{\r
574 EFI_STATUS Status;\r
575 EFI_8259_IRQ Irq;\r
576\r
1166d068 577 //\r
578 // Clear all pending interrupt\r
579 //\r
580 for (Irq = Efi8259Irq0; Irq <= Efi8259Irq15; Irq++) {\r
581 Interrupt8259EndOfInterrupt (&m8259, Irq);\r
582 }\r
583\r
584 //\r
585 // Set the 8259 Master base to 0x68 and the 8259 Slave base to 0x70\r
586 //\r
587 Status = Interrupt8259SetVectorBase (&m8259, PROTECTED_MODE_BASE_VECTOR_MASTER, PROTECTED_MODE_BASE_VECTOR_SLAVE);\r
588\r
589 //\r
590 // Set all 8259 interrupts to edge triggered and disabled\r
591 //\r
592 Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel);\r
593\r
594 //\r
595 // Install 8259 Protocol onto a new handle\r
596 //\r
597 Status = gBS->InstallProtocolInterface (\r
598 &m8259Handle,\r
599 &gEfiLegacy8259ProtocolGuid,\r
600 EFI_NATIVE_INTERFACE,\r
601 &m8259\r
602 );\r
1166d068 603 return Status;\r
604}\r
605\r