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