]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / IdeBusDxe / IdeBus.c
... / ...
CommitLineData
1/** @file\r
2 This file implement UEFI driver for IDE Bus which includes device identification,\r
3 Child device(Disk, CDROM, etc) enumeration and child handler installation, and\r
4 driver stop.\r
5\r
6 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
8\r
9 @par Revision Reference:\r
10 This module is modified from DXE\IDE module for Ide Contriller Init support\r
11\r
12**/\r
13\r
14#include "IdeBus.h"\r
15\r
16#define PCI_CLASS_MASS_STORAGE 0x01\r
17#define PCI_SUB_CLASS_IDE 0x01\r
18\r
19\r
20//\r
21// IDE Bus Driver Binding Protocol Instance\r
22//\r
23EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = {\r
24 IDEBusDriverBindingSupported,\r
25 IDEBusDriverBindingStart,\r
26 IDEBusDriverBindingStop,\r
27 0xa,\r
28 NULL,\r
29 NULL\r
30};\r
31/**\r
32 Deregister an IDE device and free resources\r
33\r
34 @param This Protocol instance pointer.\r
35 @param Controller Ide device handle\r
36 @param Handle Handle of device to deregister driver on\r
37\r
38 @retval EFI_SUCCESS Deregiter a specific IDE device successfully\r
39\r
40\r
41**/\r
42EFI_STATUS\r
43DeRegisterIdeDevice (\r
44 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
45 IN EFI_HANDLE Controller,\r
46 IN EFI_HANDLE Handle\r
47 )\r
48{\r
49 EFI_STATUS Status;\r
50 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
51 IDE_BLK_IO_DEV *IdeBlkIoDevice;\r
52 EFI_PCI_IO_PROTOCOL *PciIo;\r
53 UINTN Index;\r
54\r
55 Status = gBS->OpenProtocol (\r
56 Handle,\r
57 &gEfiBlockIoProtocolGuid,\r
58 (VOID **) &BlkIo,\r
59 This->DriverBindingHandle,\r
60 Controller,\r
61 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
62 );\r
63 if (EFI_ERROR (Status)) {\r
64 return Status;\r
65 }\r
66\r
67 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);\r
68\r
69 //\r
70 // Report Status code: Device disabled\r
71 //\r
72 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
73 EFI_PROGRESS_CODE,\r
74 (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE),\r
75 IdeBlkIoDevice->DevicePath\r
76 );\r
77\r
78 //\r
79 // Close the child handle\r
80 //\r
81 Status = gBS->CloseProtocol (\r
82 Controller,\r
83 &gEfiPciIoProtocolGuid,\r
84 This->DriverBindingHandle,\r
85 Handle\r
86 );\r
87\r
88 Status = gBS->UninstallMultipleProtocolInterfaces (\r
89 Handle,\r
90 &gEfiDevicePathProtocolGuid,\r
91 IdeBlkIoDevice->DevicePath,\r
92 &gEfiBlockIoProtocolGuid,\r
93 &IdeBlkIoDevice->BlkIo,\r
94 &gEfiDiskInfoProtocolGuid,\r
95 &IdeBlkIoDevice->DiskInfo,\r
96 NULL\r
97 );\r
98\r
99 if (EFI_ERROR (Status)) {\r
100 gBS->OpenProtocol (\r
101 Controller,\r
102 &gEfiPciIoProtocolGuid,\r
103 (VOID **) &PciIo,\r
104 This->DriverBindingHandle,\r
105 Handle,\r
106 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
107 );\r
108 return Status;\r
109 }\r
110\r
111 //\r
112 // Release allocated resources\r
113 //\r
114 Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device;\r
115 if (Index < MAX_IDE_DEVICE) {\r
116 IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE;\r
117 }\r
118 ReleaseIdeResources (IdeBlkIoDevice);\r
119\r
120 return EFI_SUCCESS;\r
121}\r
122/**\r
123 Supported function of Driver Binding protocol for this driver.\r
124\r
125 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
126 @param ControllerHandle The handle of the controller to test.\r
127 @param RemainingDevicePath A pointer to the remaining portion of a device path.\r
128\r
129 @retval EFI_SUCCESS Driver loaded.\r
130 @retval other Driver not loaded.\r
131\r
132**/\r
133EFI_STATUS\r
134EFIAPI\r
135IDEBusDriverBindingSupported (\r
136 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
137 IN EFI_HANDLE Controller,\r
138 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
139 )\r
140{\r
141 EFI_STATUS Status;\r
142 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
143 EFI_DEV_PATH *Node;\r
144 EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;\r
145 EFI_PCI_IO_PROTOCOL *PciIo;\r
146 PCI_TYPE00 PciData;\r
147\r
148 if (RemainingDevicePath != NULL) {\r
149 Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
150 //\r
151 // Check if RemainingDevicePath is the End of Device Path Node,\r
152 // if yes, go on checking other conditions\r
153 //\r
154 if (!IsDevicePathEnd (Node)) {\r
155 //\r
156 // If RemainingDevicePath isn't the End of Device Path Node,\r
157 // check its validation\r
158 //\r
159 if (Node->DevPath.Type != MESSAGING_DEVICE_PATH ||\r
160 Node->DevPath.SubType != MSG_ATAPI_DP ||\r
161 DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) {\r
162 return EFI_UNSUPPORTED;\r
163 }\r
164 }\r
165 }\r
166\r
167 //\r
168 // Verify the Ide Controller Init Protocol, which installed by the\r
169 // IdeController module.\r
170 //\r
171 Status = gBS->OpenProtocol (\r
172 Controller,\r
173 &gEfiIdeControllerInitProtocolGuid,\r
174 (VOID **) &IdeInit,\r
175 This->DriverBindingHandle,\r
176 Controller,\r
177 EFI_OPEN_PROTOCOL_BY_DRIVER\r
178 );\r
179\r
180 if (Status == EFI_ALREADY_STARTED) {\r
181 return EFI_SUCCESS;\r
182 }\r
183\r
184 if (EFI_ERROR (Status)) {\r
185 return Status;\r
186 }\r
187\r
188 //\r
189 // Close the I/O Abstraction(s) used to perform the supported test\r
190 //\r
191 gBS->CloseProtocol (\r
192 Controller,\r
193 &gEfiIdeControllerInitProtocolGuid,\r
194 This->DriverBindingHandle,\r
195 Controller\r
196 );\r
197\r
198 //\r
199 // Open the EFI Device Path protocol needed to perform the supported test\r
200 //\r
201 Status = gBS->OpenProtocol (\r
202 Controller,\r
203 &gEfiDevicePathProtocolGuid,\r
204 (VOID **) &ParentDevicePath,\r
205 This->DriverBindingHandle,\r
206 Controller,\r
207 EFI_OPEN_PROTOCOL_BY_DRIVER\r
208 );\r
209 if (Status == EFI_ALREADY_STARTED) {\r
210 return EFI_SUCCESS;\r
211 }\r
212\r
213 //\r
214 // Close protocol, don't use device path protocol in the Support() function\r
215 //\r
216 gBS->CloseProtocol (\r
217 Controller,\r
218 &gEfiDevicePathProtocolGuid,\r
219 This->DriverBindingHandle,\r
220 Controller\r
221 );\r
222\r
223 //\r
224 // Get the EfiPciIoProtocol\r
225 //\r
226 Status = gBS->OpenProtocol (\r
227 Controller,\r
228 &gEfiPciIoProtocolGuid,\r
229 (VOID **) &PciIo,\r
230 This->DriverBindingHandle,\r
231 Controller,\r
232 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
233 );\r
234\r
235 if (EFI_ERROR (Status)) {\r
236 return Status;\r
237 }\r
238\r
239 //\r
240 // Now further check the PCI header: Base class (offset 0x0B) and\r
241 // Sub Class (offset 0x0A). This controller should be an IDE controller\r
242 //\r
243 Status = PciIo->Pci.Read (\r
244 PciIo,\r
245 EfiPciIoWidthUint8,\r
246 0,\r
247 sizeof (PciData),\r
248 &PciData\r
249 );\r
250\r
251 if (!EFI_ERROR (Status)) {\r
252 //\r
253 // Examine if it is IDE mode by class code\r
254 //\r
255 if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) || (PciData.Hdr.ClassCode[1] != PCI_SUB_CLASS_IDE)) {\r
256 Status = EFI_UNSUPPORTED;\r
257 } else {\r
258 Status = EFI_SUCCESS;\r
259 }\r
260 }\r
261\r
262 return Status;\r
263}\r
264\r
265\r
266/**\r
267 Start function of Driver binding protocol which start this driver on Controller\r
268 by detecting all disks and installing BlockIo protocol on them.\r
269\r
270 @param This Protocol instance pointer.\r
271 @param Controller Handle of device to bind driver to.\r
272 @param RemainingDevicePath produce all possible children.\r
273\r
274 @retval EFI_SUCCESS This driver is added to ControllerHandle.\r
275 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.\r
276 @retval other This driver does not support this device.\r
277\r
278**/\r
279EFI_STATUS\r
280EFIAPI\r
281IDEBusDriverBindingStart (\r
282 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
283 IN EFI_HANDLE Controller,\r
284 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
285 )\r
286{\r
287 EFI_STATUS Status;\r
288 EFI_STATUS SavedStatus;\r
289 EFI_PCI_IO_PROTOCOL *PciIo;\r
290 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
291 EFI_DEV_PATH *Node;\r
292 UINT8 IdeChannel;\r
293 UINT8 BeginningIdeChannel;\r
294 UINT8 EndIdeChannel;\r
295 UINT8 IdeDevice;\r
296 UINT8 BeginningIdeDevice;\r
297 UINT8 EndIdeDevice;\r
298 IDE_BLK_IO_DEV *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice];\r
299 IDE_BLK_IO_DEV *IdeBlkIoDevicePtr;\r
300 IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];\r
301 ATA_TRANSFER_MODE TransferMode;\r
302 ATA_DRIVE_PARMS DriveParameters;\r
303 EFI_DEV_PATH NewNode;\r
304 UINT8 ConfigurationOptions;\r
305 UINT16 CommandBlockBaseAddr;\r
306 UINT16 ControlBlockBaseAddr;\r
307 UINTN DataSize;\r
308 IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;\r
309 UINT64 Supports;\r
310\r
311 //\r
312 // Local variables declaration for IdeControllerInit support\r
313 //\r
314 EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;\r
315 BOOLEAN EnumAll;\r
316 BOOLEAN ChannelEnabled;\r
317 UINT8 MaxDevices;\r
318 EFI_IDENTIFY_DATA IdentifyData;\r
319 EFI_ATA_COLLECTIVE_MODE *SupportedModes;\r
320\r
321 IdeBusDriverPrivateData = NULL;\r
322 SupportedModes = NULL;\r
323\r
324 //\r
325 // Perform IdeBus initialization\r
326 //\r
327 Status = gBS->OpenProtocol (\r
328 Controller,\r
329 &gEfiDevicePathProtocolGuid,\r
330 (VOID **) &ParentDevicePath,\r
331 This->DriverBindingHandle,\r
332 Controller,\r
333 EFI_OPEN_PROTOCOL_BY_DRIVER\r
334 );\r
335 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
336 return Status;\r
337 }\r
338\r
339 //\r
340 // Now open the IDE_CONTROLLER_INIT protocol. Step7.1\r
341 //\r
342 Status = gBS->OpenProtocol (\r
343 Controller,\r
344 &gEfiIdeControllerInitProtocolGuid,\r
345 (VOID **) &IdeInit,\r
346 This->DriverBindingHandle,\r
347 Controller,\r
348 EFI_OPEN_PROTOCOL_BY_DRIVER\r
349 );\r
350\r
351 //\r
352 // The following OpenProtocol function with _GET_PROTOCOL attribute and\r
353 // will not return EFI_ALREADY_STARTED, so save it for now\r
354 //\r
355 SavedStatus = Status;\r
356\r
357 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
358 DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status));\r
359 //\r
360 // open protocol is not SUCCESS or not ALREADY_STARTED, error exit\r
361 //\r
362 goto ErrorExit;\r
363 }\r
364\r
365 //\r
366 // Save Enumall. Step7.2\r
367 //\r
368 EnumAll = IdeInit->EnumAll;\r
369\r
370 //\r
371 // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL\r
372 // attribute will not return EFI_ALREADY_STARTED\r
373 //\r
374 Status = gBS->OpenProtocol (\r
375 Controller,\r
376 &gEfiPciIoProtocolGuid,\r
377 (VOID **) &PciIo,\r
378 This->DriverBindingHandle,\r
379 Controller,\r
380 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
381 );\r
382 if (EFI_ERROR (Status)) {\r
383 DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status));\r
384 goto ErrorExit;\r
385 }\r
386\r
387 //\r
388 // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable\r
389 //\r
390 if (SavedStatus != EFI_ALREADY_STARTED) {\r
391 IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));\r
392 if (IdeBusDriverPrivateData == NULL) {\r
393 Status = EFI_OUT_OF_RESOURCES;\r
394 goto ErrorExit;\r
395 }\r
396\r
397 ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));\r
398 Status = gBS->InstallMultipleProtocolInterfaces (\r
399 &Controller,\r
400 &gEfiCallerIdGuid,\r
401 IdeBusDriverPrivateData,\r
402 NULL\r
403 );\r
404 if (EFI_ERROR (Status)) {\r
405 goto ErrorExit;\r
406 }\r
407\r
408 } else {\r
409 Status = gBS->OpenProtocol (\r
410 Controller,\r
411 &gEfiCallerIdGuid,\r
412 (VOID **) &IdeBusDriverPrivateData,\r
413 This->DriverBindingHandle,\r
414 Controller,\r
415 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
416 );\r
417 if (EFI_ERROR (Status)) {\r
418 IdeBusDriverPrivateData = NULL;\r
419 goto ErrorExit;\r
420 }\r
421 }\r
422\r
423 Status = PciIo->Attributes (\r
424 PciIo,\r
425 EfiPciIoAttributeOperationSupported,\r
426 0,\r
427 &Supports\r
428 );\r
429 if (!EFI_ERROR (Status)) {\r
430 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;\r
431 Status = PciIo->Attributes (\r
432 PciIo,\r
433 EfiPciIoAttributeOperationEnable,\r
434 Supports,\r
435 NULL\r
436 );\r
437 }\r
438\r
439 if (EFI_ERROR (Status)) {\r
440 goto ErrorExit;\r
441 }\r
442\r
443 //\r
444 // Read the environment variable that contains the IDEBus Driver's\r
445 // Config options that were set by the Driver Configuration Protocol\r
446 //\r
447 DataSize = sizeof (ConfigurationOptions);\r
448 Status = gRT->GetVariable (\r
449 (CHAR16 *) L"Configuration",\r
450 &gEfiCallerIdGuid,\r
451 NULL,\r
452 &DataSize,\r
453 &ConfigurationOptions\r
454 );\r
455 if (EFI_ERROR (Status)) {\r
456 ConfigurationOptions = 0x0f;\r
457 }\r
458\r
459 if (EnumAll || RemainingDevicePath == NULL) {\r
460 //\r
461 // If IdeInit->EnumAll is TRUE or RemainingDevicePath is NULL,\r
462 // must enumerate all IDE devices anyway\r
463 //\r
464 BeginningIdeChannel = IdePrimary;\r
465 EndIdeChannel = IdeSecondary;\r
466 BeginningIdeDevice = IdeMaster;\r
467 EndIdeDevice = IdeSlave;\r
468\r
469 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
470 //\r
471 // If RemainingDevicePath isn't the End of Device Path Node,\r
472 // only scan the specified device by RemainingDevicePath\r
473 //\r
474 Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
475 BeginningIdeChannel = Node->Atapi.PrimarySecondary;\r
476 EndIdeChannel = BeginningIdeChannel;\r
477 BeginningIdeDevice = Node->Atapi.SlaveMaster;\r
478 EndIdeDevice = BeginningIdeDevice;\r
479 if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) {\r
480 Status = EFI_INVALID_PARAMETER;\r
481 goto ErrorExit;\r
482 }\r
483 if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) {\r
484 Status = EFI_INVALID_PARAMETER;\r
485 goto ErrorExit;\r
486 }\r
487\r
488 } else {\r
489 //\r
490 // If RemainingDevicePath is the End of Device Path Node,\r
491 // skip enumerate any device and return EFI_SUCESSS\r
492 //\r
493 BeginningIdeChannel = IdeMaxChannel;\r
494 EndIdeChannel = IdeMaxChannel - 1;\r
495 BeginningIdeDevice = IdeMaxDevice;\r
496 EndIdeDevice = IdeMaxDevice - 1;\r
497 }\r
498\r
499 //\r
500 // Obtain IDE IO port registers' base addresses\r
501 //\r
502 Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);\r
503 if (EFI_ERROR (Status)) {\r
504 goto ErrorExit;\r
505 }\r
506\r
507 //\r
508 // Report status code: begin IdeBus initialization\r
509 //\r
510 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
511 EFI_PROGRESS_CODE,\r
512 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),\r
513 ParentDevicePath\r
514 );\r
515\r
516 //\r
517 // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol\r
518 //\r
519 for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {\r
520\r
521 IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel);\r
522\r
523 //\r
524 // now obtain channel information fron IdeControllerInit protocol. Step9\r
525 //\r
526 Status = IdeInit->GetChannelInfo (\r
527 IdeInit,\r
528 IdeChannel,\r
529 &ChannelEnabled,\r
530 &MaxDevices\r
531 );\r
532 if (EFI_ERROR (Status)) {\r
533 DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status));\r
534 continue;\r
535 }\r
536\r
537 if (!ChannelEnabled) {\r
538 continue;\r
539 }\r
540\r
541 EndIdeDevice = (UINT8) MIN ((MaxDevices - 1), EndIdeDevice);\r
542 ASSERT (EndIdeDevice < IdeMaxDevice);\r
543 //\r
544 // Now inform the IDE Controller Init Module. Sept10\r
545 //\r
546 IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel);\r
547\r
548 //\r
549 // No reset channel function implemented. Sept11\r
550 //\r
551 IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel);\r
552\r
553 //\r
554 // Step13\r
555 //\r
556 IdeInit->NotifyPhase (\r
557 IdeInit,\r
558 EfiIdeBusBeforeDevicePresenceDetection,\r
559 IdeChannel\r
560 );\r
561\r
562 //\r
563 // Prepare to detect IDE device of this channel\r
564 //\r
565 InitializeIDEChannelData ();\r
566\r
567 //\r
568 // -- 1st inner loop --- Master/Slave ------------ Step14\r
569 //\r
570 for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {\r
571 //\r
572 // Check whether the configuration options allow this device\r
573 //\r
574 if ((ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice))) == 0) {\r
575 continue;\r
576 }\r
577\r
578 //\r
579 // The device has been scanned in another Start(), No need to scan it again\r
580 // for perf optimization.\r
581 //\r
582 if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) {\r
583 continue;\r
584 }\r
585\r
586 //\r
587 // create child handle for the detected device.\r
588 //\r
589 IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV));\r
590 if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) {\r
591 continue;\r
592 }\r
593\r
594 IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];\r
595\r
596 ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV));\r
597\r
598 IdeBlkIoDevicePtr->Signature = IDE_BLK_IO_DEV_SIGNATURE;\r
599 IdeBlkIoDevicePtr->Channel = (EFI_IDE_CHANNEL) IdeChannel;\r
600 IdeBlkIoDevicePtr->Device = (EFI_IDE_DEVICE) IdeDevice;\r
601\r
602 //\r
603 // initialize Block IO interface's Media pointer\r
604 //\r
605 IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia;\r
606\r
607 //\r
608 // Initialize IDE IO port addresses, including Command Block registers\r
609 // and Control Block registers\r
610 //\r
611 IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS));\r
612 if (IdeBlkIoDevicePtr->IoPort == NULL) {\r
613 continue;\r
614 }\r
615\r
616 ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS));\r
617 CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;\r
618 ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;\r
619\r
620 IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr;\r
621 (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);\r
622 IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);\r
623 IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);\r
624 IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);\r
625 IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);\r
626 IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);\r
627 (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);\r
628\r
629 (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr;\r
630 IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);\r
631\r
632 IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0);\r
633\r
634 IdeBlkIoDevicePtr->PciIo = PciIo;\r
635 IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData;\r
636 IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr;\r
637\r
638 //\r
639 // Report Status code: is about to detect IDE drive\r
640 //\r
641 REPORT_STATUS_CODE_EX (\r
642 EFI_PROGRESS_CODE,\r
643 (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT),\r
644 0,\r
645 &gEfiCallerIdGuid,\r
646 NULL,\r
647 NULL,\r
648 0\r
649 );\r
650\r
651 //\r
652 // Discover device, now!\r
653 //\r
654 PERF_START (NULL, "DiscoverIdeDevice", "IDE", 0);\r
655 Status = DiscoverIdeDevice (IdeBlkIoDevicePtr);\r
656 PERF_END (NULL, "DiscoverIdeDevice", "IDE", 0);\r
657\r
658 IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice] = TRUE;\r
659 IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = FALSE;\r
660\r
661 if (!EFI_ERROR (Status)) {\r
662 //\r
663 // Set Device Path\r
664 //\r
665 ZeroMem (&NewNode, sizeof (NewNode));\r
666 NewNode.DevPath.Type = MESSAGING_DEVICE_PATH;\r
667 NewNode.DevPath.SubType = MSG_ATAPI_DP;\r
668 SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH));\r
669\r
670 NewNode.Atapi.PrimarySecondary = (UINT8) IdeBlkIoDevicePtr->Channel;\r
671 NewNode.Atapi.SlaveMaster = (UINT8) IdeBlkIoDevicePtr->Device;\r
672 NewNode.Atapi.Lun = IdeBlkIoDevicePtr->Lun;\r
673 IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode (\r
674 ParentDevicePath,\r
675 &NewNode.DevPath\r
676 );\r
677 if (IdeBlkIoDevicePtr->DevicePath == NULL) {\r
678 ReleaseIdeResources (IdeBlkIoDevicePtr);\r
679 continue;\r
680 }\r
681\r
682 //\r
683 // Submit identify data to IDE controller init driver\r
684 //\r
685 CopyMem (&IdentifyData, IdeBlkIoDevicePtr->IdData, sizeof (IdentifyData));\r
686 IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE;\r
687 IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData);\r
688 } else {\r
689 //\r
690 // Device detection failed\r
691 //\r
692 IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;\r
693 IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL);\r
694 ReleaseIdeResources (IdeBlkIoDevicePtr);\r
695 IdeBlkIoDevicePtr = NULL;\r
696 }\r
697 //\r
698 // end of 1st inner loop ---\r
699 //\r
700 }\r
701 //\r
702 // end of 1st outer loop =========\r
703 //\r
704 }\r
705\r
706 //\r
707 // = 2nd outer loop == Primary/Secondary =================\r
708 //\r
709 for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {\r
710\r
711 //\r
712 // -- 2nd inner loop --- Master/Slave --------\r
713 //\r
714 for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {\r
715\r
716 ASSERT (IdeChannel * 2 + IdeDevice < MAX_IDE_DEVICE);\r
717 if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) {\r
718 continue;\r
719 }\r
720\r
721 if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) {\r
722 continue;\r
723 }\r
724\r
725 Status = IdeInit->CalculateMode (\r
726 IdeInit,\r
727 IdeChannel,\r
728 IdeDevice,\r
729 &SupportedModes\r
730 );\r
731 if (EFI_ERROR (Status)) {\r
732 DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status));\r
733 continue;\r
734 }\r
735\r
736 ASSERT (IdeChannel < IdeMaxChannel && IdeDevice < IdeMaxDevice);\r
737 IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];\r
738\r
739 //\r
740 // Set best supported PIO mode on this IDE device\r
741 //\r
742 if (SupportedModes->PioMode.Mode <= AtaPioMode2) {\r
743 TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO;\r
744 } else {\r
745 TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO;\r
746 }\r
747\r
748 TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);\r
749\r
750 if (SupportedModes->ExtModeCount == 0){\r
751 Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);\r
752\r
753 if (EFI_ERROR (Status)) {\r
754 IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;\r
755 ReleaseIdeResources (IdeBlkIoDevicePtr);\r
756 IdeBlkIoDevicePtr = NULL;\r
757 continue;\r
758 }\r
759 }\r
760\r
761 //\r
762 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't\r
763 // be set together. Only one DMA mode can be set to a device. If setting\r
764 // DMA mode operation fails, we can continue moving on because we only use\r
765 // PIO mode at boot time. DMA modes are used by certain kind of OS booting\r
766 //\r
767 if (SupportedModes->UdmaMode.Valid) {\r
768\r
769 TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA;\r
770 TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);\r
771 Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);\r
772\r
773 if (EFI_ERROR (Status)) {\r
774 IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;\r
775 ReleaseIdeResources (IdeBlkIoDevicePtr);\r
776 IdeBlkIoDevicePtr = NULL;\r
777 continue;\r
778 }\r
779 //\r
780 // Record Udma Mode\r
781 //\r
782 IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE;\r
783 IdeBlkIoDevicePtr->UdmaMode.Mode = SupportedModes->UdmaMode.Mode;\r
784 EnableInterrupt (IdeBlkIoDevicePtr);\r
785 } else if (SupportedModes->MultiWordDmaMode.Valid) {\r
786\r
787 TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA;\r
788 TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;\r
789 Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);\r
790\r
791 if (EFI_ERROR (Status)) {\r
792 IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;\r
793 ReleaseIdeResources (IdeBlkIoDevicePtr);\r
794 IdeBlkIoDevicePtr = NULL;\r
795 continue;\r
796 }\r
797\r
798 EnableInterrupt (IdeBlkIoDevicePtr);\r
799 }\r
800 //\r
801 // Init driver parameters\r
802 //\r
803 DriveParameters.Sector = (UINT8) ((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->sectors_per_track;\r
804 DriveParameters.Heads = (UINT8) (((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->heads - 1);\r
805 DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.multi_sector_cmd_max_sct_cnt;\r
806 //\r
807 // Set Parameters for the device:\r
808 // 1) Init\r
809 // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command\r
810 //\r
811 if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) {\r
812 Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters);\r
813 }\r
814\r
815 //\r
816 // Record PIO mode used in private data\r
817 //\r
818 IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode;\r
819\r
820 //\r
821 // Set IDE controller Timing Blocks in the PCI Configuration Space\r
822 //\r
823 IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes);\r
824\r
825 //\r
826 // Add Component Name for the IDE/ATAPI device that was discovered.\r
827 //\r
828 IdeBlkIoDevicePtr->ControllerNameTable = NULL;\r
829 ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr);\r
830\r
831 Status = gBS->InstallMultipleProtocolInterfaces (\r
832 &IdeBlkIoDevicePtr->Handle,\r
833 &gEfiDevicePathProtocolGuid,\r
834 IdeBlkIoDevicePtr->DevicePath,\r
835 &gEfiBlockIoProtocolGuid,\r
836 &IdeBlkIoDevicePtr->BlkIo,\r
837 &gEfiDiskInfoProtocolGuid,\r
838 &IdeBlkIoDevicePtr->DiskInfo,\r
839 NULL\r
840 );\r
841\r
842 if (EFI_ERROR (Status)) {\r
843 ReleaseIdeResources (IdeBlkIoDevicePtr);\r
844 }\r
845\r
846 gBS->OpenProtocol (\r
847 Controller,\r
848 &gEfiPciIoProtocolGuid,\r
849 (VOID **) &PciIo,\r
850 This->DriverBindingHandle,\r
851 IdeBlkIoDevicePtr->Handle,\r
852 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
853 );\r
854\r
855 IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE;\r
856\r
857 //\r
858 // Report status code: device eanbled!\r
859 //\r
860 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
861 EFI_PROGRESS_CODE,\r
862 (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE),\r
863 IdeBlkIoDevicePtr->DevicePath\r
864 );\r
865\r
866 //\r
867 // Create event to clear pending IDE interrupt\r
868 //\r
869 Status = gBS->CreateEventEx (\r
870 EVT_NOTIFY_SIGNAL,\r
871 TPL_NOTIFY,\r
872 ClearInterrupt,\r
873 IdeBlkIoDevicePtr,\r
874 &gEfiEventExitBootServicesGuid,\r
875 &IdeBlkIoDevicePtr->ExitBootServiceEvent\r
876 );\r
877\r
878 //\r
879 // end of 2nd inner loop ----\r
880 //\r
881 }\r
882 //\r
883 // end of 2nd outer loop ==========\r
884 //\r
885 }\r
886\r
887 //\r
888 // All configurations done! Notify IdeController to do post initialization\r
889 // work such as saving IDE controller PCI settings for S3 resume\r
890 //\r
891 IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0);\r
892\r
893 if (SupportedModes != NULL) {\r
894 FreePool (SupportedModes);\r
895 }\r
896\r
897 PERF_START (NULL, "Finish IDE detection", "IDE", 1);\r
898 PERF_END (NULL, "Finish IDE detection", "IDE", 0);\r
899\r
900 return EFI_SUCCESS;\r
901\r
902ErrorExit:\r
903\r
904 //\r
905 // Report error code: controller error\r
906 //\r
907 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
908 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
909 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR),\r
910 ParentDevicePath\r
911 );\r
912\r
913 gBS->CloseProtocol (\r
914 Controller,\r
915 &gEfiIdeControllerInitProtocolGuid,\r
916 This->DriverBindingHandle,\r
917 Controller\r
918 );\r
919\r
920 gBS->UninstallMultipleProtocolInterfaces (\r
921 Controller,\r
922 &gEfiCallerIdGuid,\r
923 IdeBusDriverPrivateData,\r
924 NULL\r
925 );\r
926\r
927 if (IdeBusDriverPrivateData != NULL) {\r
928 gBS->FreePool (IdeBusDriverPrivateData);\r
929 }\r
930\r
931 if (SupportedModes != NULL) {\r
932 gBS->FreePool (SupportedModes);\r
933 }\r
934\r
935 gBS->CloseProtocol (\r
936 Controller,\r
937 &gEfiPciIoProtocolGuid,\r
938 This->DriverBindingHandle,\r
939 Controller\r
940 );\r
941\r
942 gBS->CloseProtocol (\r
943 Controller,\r
944 &gEfiDevicePathProtocolGuid,\r
945 This->DriverBindingHandle,\r
946 Controller\r
947 );\r
948\r
949 return Status;\r
950\r
951}\r
952/**\r
953 Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all\r
954 child handle attached to the controller handle if there are.\r
955\r
956 @param This Protocol instance pointer.\r
957 @param Controller Handle of device to stop driver on\r
958 @param NumberOfChildren Not used\r
959 @param ChildHandleBuffer Not used\r
960\r
961 @retval EFI_SUCCESS This driver is removed DeviceHandle\r
962 @retval other This driver was not removed from this device\r
963\r
964**/\r
965EFI_STATUS\r
966EFIAPI\r
967IDEBusDriverBindingStop (\r
968 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
969 IN EFI_HANDLE Controller,\r
970 IN UINTN NumberOfChildren,\r
971 IN EFI_HANDLE *ChildHandleBuffer\r
972 )\r
973{\r
974 EFI_STATUS Status;\r
975 EFI_PCI_IO_PROTOCOL *PciIo;\r
976 BOOLEAN AllChildrenStopped;\r
977 UINTN Index;\r
978 IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;\r
979 UINT64 Supports;\r
980\r
981 IdeBusDriverPrivateData = NULL;\r
982\r
983 if (NumberOfChildren == 0) {\r
984\r
985 Status = gBS->OpenProtocol (\r
986 Controller,\r
987 &gEfiPciIoProtocolGuid,\r
988 (VOID **) &PciIo,\r
989 This->DriverBindingHandle,\r
990 Controller,\r
991 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
992 );\r
993 if (!EFI_ERROR (Status)) {\r
994 Status = PciIo->Attributes (\r
995 PciIo,\r
996 EfiPciIoAttributeOperationSupported,\r
997 0,\r
998 &Supports\r
999 );\r
1000 if (!EFI_ERROR (Status)) {\r
1001 Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE);\r
1002 PciIo->Attributes (\r
1003 PciIo,\r
1004 EfiPciIoAttributeOperationDisable,\r
1005 Supports,\r
1006 NULL\r
1007 );\r
1008 }\r
1009 }\r
1010\r
1011 gBS->OpenProtocol (\r
1012 Controller,\r
1013 &gEfiCallerIdGuid,\r
1014 (VOID **) &IdeBusDriverPrivateData,\r
1015 This->DriverBindingHandle,\r
1016 Controller,\r
1017 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1018 );\r
1019\r
1020 gBS->UninstallMultipleProtocolInterfaces (\r
1021 Controller,\r
1022 &gEfiCallerIdGuid,\r
1023 IdeBusDriverPrivateData,\r
1024 NULL\r
1025 );\r
1026\r
1027 if (IdeBusDriverPrivateData != NULL) {\r
1028 gBS->FreePool (IdeBusDriverPrivateData);\r
1029 }\r
1030 //\r
1031 // Close the bus driver\r
1032 //\r
1033 gBS->CloseProtocol (\r
1034 Controller,\r
1035 &gEfiIdeControllerInitProtocolGuid,\r
1036 This->DriverBindingHandle,\r
1037 Controller\r
1038 );\r
1039 gBS->CloseProtocol (\r
1040 Controller,\r
1041 &gEfiPciIoProtocolGuid,\r
1042 This->DriverBindingHandle,\r
1043 Controller\r
1044 );\r
1045 gBS->CloseProtocol (\r
1046 Controller,\r
1047 &gEfiDevicePathProtocolGuid,\r
1048 This->DriverBindingHandle,\r
1049 Controller\r
1050 );\r
1051\r
1052 return EFI_SUCCESS;\r
1053 }\r
1054\r
1055 AllChildrenStopped = TRUE;\r
1056\r
1057 for (Index = 0; Index < NumberOfChildren; Index++) {\r
1058\r
1059 Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]);\r
1060\r
1061 if (EFI_ERROR (Status)) {\r
1062 AllChildrenStopped = FALSE;\r
1063 }\r
1064 }\r
1065\r
1066 if (!AllChildrenStopped) {\r
1067 return EFI_DEVICE_ERROR;\r
1068 }\r
1069\r
1070 return EFI_SUCCESS;\r
1071}\r
1072\r
1073/**\r
1074 issue ATA or ATAPI command to reset a block IO device.\r
1075 @param This Block IO protocol instance pointer.\r
1076 @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method\r
1077 If TRUE, for ATAPI device, driver need invoke ATA reset method after\r
1078 invoke ATAPI reset method\r
1079\r
1080 @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device.\r
1081 @retval EFI_SUCCESS The device reset successfully\r
1082\r
1083**/\r
1084EFI_STATUS\r
1085EFIAPI\r
1086IDEBlkIoReset (\r
1087 IN EFI_BLOCK_IO_PROTOCOL *This,\r
1088 IN BOOLEAN ExtendedVerification\r
1089 )\r
1090{\r
1091 IDE_BLK_IO_DEV *IdeBlkIoDevice;\r
1092 EFI_STATUS Status;\r
1093 EFI_TPL OldTpl;\r
1094\r
1095 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1096\r
1097 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);\r
1098 //\r
1099 // Requery IDE IO resources in case of the switch of native and legacy modes\r
1100 //\r
1101 ReassignIdeResources (IdeBlkIoDevice);\r
1102\r
1103 //\r
1104 // for ATA device, using ATA reset method\r
1105 //\r
1106 if (IdeBlkIoDevice->Type == IdeHardDisk ||\r
1107 IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
1108 Status = AtaSoftReset (IdeBlkIoDevice);\r
1109 goto Done;\r
1110 }\r
1111\r
1112 if (IdeBlkIoDevice->Type == IdeUnknown) {\r
1113 Status = EFI_DEVICE_ERROR;\r
1114 goto Done;\r
1115 }\r
1116\r
1117 //\r
1118 // for ATAPI device, using ATAPI reset method\r
1119 //\r
1120 Status = AtapiSoftReset (IdeBlkIoDevice);\r
1121 if (ExtendedVerification) {\r
1122 Status = AtaSoftReset (IdeBlkIoDevice);\r
1123 }\r
1124\r
1125Done:\r
1126 gBS->RestoreTPL (OldTpl);\r
1127 return Status;\r
1128}\r
1129\r
1130/**\r
1131 Read data from a block IO device\r
1132\r
1133 @param This Block IO protocol instance pointer.\r
1134 @param MediaId The media ID of the device\r
1135 @param Lba Starting LBA address to read data\r
1136 @param BufferSize The size of data to be read\r
1137 @param Buffer Caller supplied buffer to save data\r
1138\r
1139 @retval EFI_DEVICE_ERROR unknown device type\r
1140 @retval other read data status.\r
1141\r
1142**/\r
1143EFI_STATUS\r
1144EFIAPI\r
1145IDEBlkIoReadBlocks (\r
1146 IN EFI_BLOCK_IO_PROTOCOL *This,\r
1147 IN UINT32 MediaId,\r
1148 IN EFI_LBA Lba,\r
1149 IN UINTN BufferSize,\r
1150 OUT VOID *Buffer\r
1151 )\r
1152{\r
1153 IDE_BLK_IO_DEV *IdeBlkIoDevice;\r
1154 EFI_STATUS Status;\r
1155 EFI_TPL OldTpl;\r
1156\r
1157 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1158\r
1159 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);\r
1160\r
1161 //\r
1162 // Requery IDE IO resources in case of the switch of native and legacy modes\r
1163 //\r
1164 ReassignIdeResources (IdeBlkIoDevice);\r
1165\r
1166 //\r
1167 // For ATA compatible device, use ATA read block's mechanism\r
1168 //\r
1169 if (IdeBlkIoDevice->Type == IdeHardDisk ||\r
1170 IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
1171 Status = AtaBlkIoReadBlocks (\r
1172 IdeBlkIoDevice,\r
1173 MediaId,\r
1174 Lba,\r
1175 BufferSize,\r
1176 Buffer\r
1177 );\r
1178 goto Done;\r
1179 }\r
1180\r
1181 if (IdeBlkIoDevice->Type == IdeUnknown) {\r
1182 Status = EFI_DEVICE_ERROR;\r
1183 goto Done;\r
1184 }\r
1185\r
1186 //\r
1187 // for ATAPI device, using ATAPI read block's mechanism\r
1188 //\r
1189 Status = AtapiBlkIoReadBlocks (\r
1190 IdeBlkIoDevice,\r
1191 MediaId,\r
1192 Lba,\r
1193 BufferSize,\r
1194 Buffer\r
1195 );\r
1196\r
1197Done:\r
1198 gBS->RestoreTPL (OldTpl);\r
1199\r
1200 return Status;\r
1201}\r
1202\r
1203/**\r
1204 Write data to block io device.\r
1205\r
1206 @param This Protocol instance pointer.\r
1207 @param MediaId The media ID of the device\r
1208 @param Lba Starting LBA address to write data\r
1209 @param BufferSize The size of data to be written\r
1210 @param Buffer Caller supplied buffer to save data\r
1211\r
1212 @retval EFI_DEVICE_ERROR unknown device type\r
1213 @retval other write data status\r
1214\r
1215**/\r
1216EFI_STATUS\r
1217EFIAPI\r
1218IDEBlkIoWriteBlocks (\r
1219 IN EFI_BLOCK_IO_PROTOCOL *This,\r
1220 IN UINT32 MediaId,\r
1221 IN EFI_LBA Lba,\r
1222 IN UINTN BufferSize,\r
1223 IN VOID *Buffer\r
1224 )\r
1225{\r
1226 IDE_BLK_IO_DEV *IdeBlkIoDevice;\r
1227 EFI_STATUS Status;\r
1228 EFI_TPL OldTpl;\r
1229\r
1230 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1231\r
1232 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);\r
1233 //\r
1234 // Requery IDE IO resources in case of the switch of native and legacy modes\r
1235 //\r
1236 ReassignIdeResources (IdeBlkIoDevice);\r
1237\r
1238 //\r
1239 // for ATA device, using ATA write block's mechanism\r
1240 //\r
1241 if (IdeBlkIoDevice->Type == IdeHardDisk ||\r
1242 IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
1243\r
1244 Status = AtaBlkIoWriteBlocks (\r
1245 IdeBlkIoDevice,\r
1246 MediaId,\r
1247 Lba,\r
1248 BufferSize,\r
1249 Buffer\r
1250 );\r
1251 goto Done;\r
1252 }\r
1253\r
1254 if (IdeBlkIoDevice->Type == IdeUnknown) {\r
1255 Status = EFI_DEVICE_ERROR;\r
1256 goto Done;\r
1257 }\r
1258\r
1259 //\r
1260 // for ATAPI device, using ATAPI write block's mechanism\r
1261 //\r
1262 Status = AtapiBlkIoWriteBlocks (\r
1263 IdeBlkIoDevice,\r
1264 MediaId,\r
1265 Lba,\r
1266 BufferSize,\r
1267 Buffer\r
1268 );\r
1269\r
1270Done:\r
1271 gBS->RestoreTPL (OldTpl);\r
1272 return Status;\r
1273}\r
1274/**\r
1275 Flushes all modified data to a physical block devices\r
1276\r
1277 @param This Indicates a pointer to the calling context which to sepcify a\r
1278 sepcific block device\r
1279\r
1280 @retval EFI_SUCCESS Always return success.\r
1281**/\r
1282EFI_STATUS\r
1283EFIAPI\r
1284IDEBlkIoFlushBlocks (\r
1285 IN EFI_BLOCK_IO_PROTOCOL *This\r
1286 )\r
1287{\r
1288 //\r
1289 // return directly\r
1290 //\r
1291 return EFI_SUCCESS;\r
1292}\r
1293\r
1294/**\r
1295 This function is used by the IDE bus driver to get inquiry data.\r
1296 Data format of Identify data is defined by the Interface GUID.\r
1297\r
1298 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
1299 @param InquiryData Pointer to a buffer for the inquiry data.\r
1300 @param InquiryDataSize Pointer to the value for the inquiry data size.\r
1301\r
1302 @retval EFI_SUCCESS The command was accepted without any errors.\r
1303 @retval EFI_NOT_FOUND Device does not support this data class\r
1304 @retval EFI_DEVICE_ERROR Error reading InquiryData from device\r
1305 @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough\r
1306\r
1307**/\r
1308EFI_STATUS\r
1309EFIAPI\r
1310IDEDiskInfoInquiry (\r
1311 IN EFI_DISK_INFO_PROTOCOL *This,\r
1312 IN OUT VOID *InquiryData,\r
1313 IN OUT UINT32 *InquiryDataSize\r
1314 )\r
1315{\r
1316 IDE_BLK_IO_DEV *IdeBlkIoDevice;\r
1317\r
1318 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);\r
1319\r
1320 if (*InquiryDataSize < sizeof (ATAPI_INQUIRY_DATA)) {\r
1321 *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);\r
1322 return EFI_BUFFER_TOO_SMALL;\r
1323 }\r
1324\r
1325 if (IdeBlkIoDevice->InquiryData == NULL) {\r
1326 return EFI_NOT_FOUND;\r
1327 }\r
1328\r
1329 gBS->CopyMem (InquiryData, IdeBlkIoDevice->InquiryData, sizeof (ATAPI_INQUIRY_DATA));\r
1330 *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);\r
1331\r
1332 return EFI_SUCCESS;\r
1333}\r
1334\r
1335/**\r
1336 This function is used by the IDE bus driver to get identify data.\r
1337 Data format of Identify data is defined by the Interface GUID.\r
1338\r
1339 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
1340 @param IdentifyData Pointer to a buffer for the identify data.\r
1341 @param IdentifyDataSize Pointer to the value for the identify data size.\r
1342\r
1343 @retval EFI_SUCCESS The command was accepted without any errors.\r
1344 @retval EFI_NOT_FOUND Device does not support this data class\r
1345 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device\r
1346 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough\r
1347\r
1348**/\r
1349EFI_STATUS\r
1350EFIAPI\r
1351IDEDiskInfoIdentify (\r
1352 IN EFI_DISK_INFO_PROTOCOL *This,\r
1353 IN OUT VOID *IdentifyData,\r
1354 IN OUT UINT32 *IdentifyDataSize\r
1355 )\r
1356{\r
1357 IDE_BLK_IO_DEV *IdeBlkIoDevice;\r
1358\r
1359 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);\r
1360\r
1361 if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) {\r
1362 *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);\r
1363 return EFI_BUFFER_TOO_SMALL;\r
1364 }\r
1365\r
1366 if (IdeBlkIoDevice->IdData == NULL) {\r
1367 return EFI_NOT_FOUND;\r
1368 }\r
1369\r
1370 gBS->CopyMem (IdentifyData, IdeBlkIoDevice->IdData, sizeof (EFI_IDENTIFY_DATA));\r
1371 *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);\r
1372\r
1373 return EFI_SUCCESS;\r
1374}\r
1375\r
1376/**\r
1377 This function is used by the IDE bus driver to get sense data.\r
1378 Data format of Sense data is defined by the Interface GUID.\r
1379\r
1380 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
1381 @param SenseData Pointer to the SenseData.\r
1382 @param SenseDataSize Size of SenseData in bytes.\r
1383 @param SenseDataNumber Pointer to the value for the identify data size.\r
1384\r
1385 @retval EFI_SUCCESS The command was accepted without any errors.\r
1386 @retval EFI_NOT_FOUND Device does not support this data class\r
1387 @retval EFI_DEVICE_ERROR Error reading InquiryData from device\r
1388 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough\r
1389\r
1390**/\r
1391EFI_STATUS\r
1392EFIAPI\r
1393IDEDiskInfoSenseData (\r
1394 IN EFI_DISK_INFO_PROTOCOL *This,\r
1395 IN OUT VOID *SenseData,\r
1396 IN OUT UINT32 *SenseDataSize,\r
1397 OUT UINT8 *SenseDataNumber\r
1398 )\r
1399{\r
1400 return EFI_NOT_FOUND;\r
1401}\r
1402\r
1403/**\r
1404 This function is used by the IDE bus driver to get controller information.\r
1405\r
1406 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
1407 @param IdeChannel Pointer to the Ide Channel number. Primary or secondary.\r
1408 @param IdeDevice Pointer to the Ide Device number. Master or slave.\r
1409\r
1410 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid\r
1411 @retval EFI_UNSUPPORTED This is not an IDE device\r
1412\r
1413**/\r
1414EFI_STATUS\r
1415EFIAPI\r
1416IDEDiskInfoWhichIde (\r
1417 IN EFI_DISK_INFO_PROTOCOL *This,\r
1418 OUT UINT32 *IdeChannel,\r
1419 OUT UINT32 *IdeDevice\r
1420 )\r
1421{\r
1422 IDE_BLK_IO_DEV *IdeBlkIoDevice;\r
1423\r
1424 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);\r
1425 *IdeChannel = IdeBlkIoDevice->Channel;\r
1426 *IdeDevice = IdeBlkIoDevice->Device;\r
1427\r
1428 return EFI_SUCCESS;\r
1429}\r
1430\r
1431/**\r
1432 The is an event(generally the event is exitBootService event) call back function.\r
1433 Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.\r
1434\r
1435 @param Event Pointer to this event\r
1436 @param Context Event handler private data\r
1437\r
1438**/\r
1439VOID\r
1440EFIAPI\r
1441ClearInterrupt (\r
1442 IN EFI_EVENT Event,\r
1443 IN VOID *Context\r
1444 )\r
1445{\r
1446 EFI_STATUS Status;\r
1447 UINT64 IoPortForBmis;\r
1448 UINT8 RegisterValue;\r
1449 IDE_BLK_IO_DEV *IdeDev;\r
1450\r
1451 //\r
1452 // Get our context\r
1453 //\r
1454 IdeDev = (IDE_BLK_IO_DEV *) Context;\r
1455\r
1456 //\r
1457 // Obtain IDE IO port registers' base addresses\r
1458 //\r
1459 Status = ReassignIdeResources (IdeDev);\r
1460 if (EFI_ERROR (Status)) {\r
1461 return;\r
1462 }\r
1463\r
1464 //\r
1465 // Check whether interrupt is pending\r
1466 //\r
1467\r
1468 //\r
1469 // Reset IDE device to force it de-assert interrupt pin\r
1470 // Note: this will reset all devices on this IDE channel\r
1471 //\r
1472 Status = AtaSoftReset (IdeDev);\r
1473 if (EFI_ERROR (Status)) {\r
1474 return;\r
1475 }\r
1476\r
1477 //\r
1478 // Get base address of IDE Bus Master Status Regsiter\r
1479 //\r
1480 if (IdePrimary == IdeDev->Channel) {\r
1481 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
1482 } else {\r
1483 if (IdeSecondary == IdeDev->Channel) {\r
1484 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
1485 } else {\r
1486 return;\r
1487 }\r
1488 }\r
1489 //\r
1490 // Read BMIS register and clear ERROR and INTR bit\r
1491 //\r
1492 IdeDev->PciIo->Io.Read (\r
1493 IdeDev->PciIo,\r
1494 EfiPciIoWidthUint8,\r
1495 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1496 IoPortForBmis,\r
1497 1,\r
1498 &RegisterValue\r
1499 );\r
1500\r
1501 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
1502\r
1503 IdeDev->PciIo->Io.Write (\r
1504 IdeDev->PciIo,\r
1505 EfiPciIoWidthUint8,\r
1506 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1507 IoPortForBmis,\r
1508 1,\r
1509 &RegisterValue\r
1510 );\r
1511\r
1512 //\r
1513 // Select the other device on this channel to ensure this device to release the interrupt pin\r
1514 //\r
1515 if (IdeDev->Device == 0) {\r
1516 RegisterValue = (1 << 4) | 0xe0;\r
1517 } else {\r
1518 RegisterValue = (0 << 4) | 0xe0;\r
1519 }\r
1520 IDEWritePortB (\r
1521 IdeDev->PciIo,\r
1522 IdeDev->IoPort->Head,\r
1523 RegisterValue\r
1524 );\r
1525\r
1526}\r
1527\r
1528/**\r
1529 The user Entry Point for module IdeBus. The user code starts with this function.\r
1530\r
1531 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
1532 @param[in] SystemTable A pointer to the EFI System Table.\r
1533\r
1534 @retval EFI_SUCCESS The entry point is executed successfully.\r
1535 @retval other Some error occurs when executing this entry point.\r
1536\r
1537**/\r
1538EFI_STATUS\r
1539EFIAPI\r
1540InitializeIdeBus(\r
1541 IN EFI_HANDLE ImageHandle,\r
1542 IN EFI_SYSTEM_TABLE *SystemTable\r
1543 )\r
1544{\r
1545 EFI_STATUS Status;\r
1546\r
1547 //\r
1548 // Install driver model protocol(s).\r
1549 //\r
1550 Status = EfiLibInstallAllDriverProtocols2 (\r
1551 ImageHandle,\r
1552 SystemTable,\r
1553 &gIDEBusDriverBinding,\r
1554 ImageHandle,\r
1555 &gIDEBusComponentName,\r
1556 &gIDEBusComponentName2,\r
1557 NULL,\r
1558 NULL,\r
1559 &gIDEBusDriverDiagnostics,\r
1560 &gIDEBusDriverDiagnostics2\r
1561 );\r
1562 ASSERT_EFI_ERROR (Status);\r
1563\r
1564 return Status;\r
1565}\r