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