dfaaa5a5 |
1 | /** @file\r |
1166d068 |
2 | This contains the installation function for the driver.\r |
47ca9c95 |
3 | \r |
3d78c020 |
4 | Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r |
47ca9c95 |
5 | This program and the accompanying materials\r |
6 | are licensed and made available under the terms and conditions of the BSD License\r |
7 | which accompanies this distribution. The full text of the license may be found at\r |
8 | http://opensource.org/licenses/bsd-license.php\r |
9 | \r |
10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r |
11 | WITHOUT 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 |
20 | EFI_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 |
35 | EFI_HANDLE m8259Handle = NULL;\r |
36 | \r |
37 | UINT8 mMasterBase = 0xff;\r |
38 | UINT8 mSlaveBase = 0xff;\r |
39 | EFI_8259_MODE mMode = Efi8259ProtectedMode;\r |
40 | UINT16 mProtectedModeMask = 0xffff;\r |
856f592c |
41 | UINT16 mLegacyModeMask;\r |
1166d068 |
42 | UINT16 mProtectedModeEdgeLevel = 0x0000;\r |
856f592c |
43 | UINT16 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 |
58 | VOID\r |
59 | Interrupt8259WriteMask (\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 |
79 | VOID\r |
80 | Interrupt8259ReadMask (\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 |
118 | EFI_STATUS\r |
119 | EFIAPI\r |
120 | Interrupt8259SetVectorBase (\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 |
619ad10f |
142 | // because it will be cleared during initialization\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 |
619ad10f |
184 | // because it will be cleared during initialization\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 |
235 | EFI_STATUS\r |
236 | EFIAPI\r |
237 | Interrupt8259GetMask (\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 |
277 | EFI_STATUS\r |
278 | EFIAPI\r |
279 | Interrupt8259SetMask (\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 |
318 | EFI_STATUS\r |
319 | EFIAPI\r |
320 | Interrupt8259SetMode (\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 |
412 | EFI_STATUS\r |
413 | EFIAPI\r |
414 | Interrupt8259GetVector (\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 |
444 | EFI_STATUS\r |
445 | EFIAPI\r |
446 | Interrupt8259EnableIrq (\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 |
478 | EFI_STATUS\r |
479 | EFIAPI\r |
480 | Interrupt8259DisableIrq (\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 |
508 | EFI_STATUS\r |
509 | EFIAPI\r |
510 | Interrupt8259GetInterruptLine (\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 |
555 | EFI_STATUS\r |
556 | EFIAPI\r |
557 | Interrupt8259EndOfInterrupt (\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 |
585 | EFI_STATUS\r |
586 | EFIAPI\r |
587 | Install8259 (\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 |