]>
Commit | Line | Data |
---|---|---|
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 | |
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 | 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 |