]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
1. Add definition for SSP(StorageSecurityCommand Protocol)
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AtaBusDxe / AtaBus.c
CommitLineData
ad86a50a 1/** @file\r
2 This file implements protocol interfaces for ATA bus driver.\r
3 \r
4 This file implements protocol interfaces: Driver Binding protocol,\r
5 Block IO protocol and DiskInfo protocol.\r
6 \r
e519983a 7 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 8 This program and the accompanying materials\r
ad86a50a 9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16\r
17**/\r
18\r
19#include "AtaBus.h"\r
20\r
21//\r
22// ATA Bus Driver Binding Protocol Instance\r
23//\r
24EFI_DRIVER_BINDING_PROTOCOL gAtaBusDriverBinding = {\r
25 AtaBusDriverBindingSupported,\r
26 AtaBusDriverBindingStart,\r
27 AtaBusDriverBindingStop,\r
28 0x10,\r
29 NULL,\r
30 NULL\r
31};\r
32\r
33//\r
34// Template for ATA Child Device.\r
35//\r
36ATA_DEVICE gAtaDeviceTemplate = {\r
05a44e91 37 ATA_DEVICE_SIGNATURE, // Signature\r
38 NULL, // Handle\r
ad86a50a 39 { // BlockIo\r
40 EFI_BLOCK_IO_PROTOCOL_REVISION,\r
41 NULL,\r
42 AtaBlockIoReset,\r
43 AtaBlockIoReadBlocks,\r
44 AtaBlockIoWriteBlocks,\r
45 AtaBlockIoFlushBlocks\r
46 },\r
490b5ea1 47 { // BlockIo2\r
48 NULL,\r
49 AtaBlockIoResetEx,\r
50 AtaBlockIoReadBlocksEx,\r
51 AtaBlockIoWriteBlocksEx,\r
52 AtaBlockIoFlushBlocksEx\r
53 },\r
ad86a50a 54 { // BlockMedia\r
55 0, // MediaId\r
56 FALSE, // RemovableMedia\r
57 TRUE, // MediaPresent\r
58 FALSE, // LogicPartition\r
59 FALSE, // ReadOnly\r
60 FALSE, // WritingCache\r
61 0x200, // BlockSize \r
907c1a00 62 0, // IoAlign\r
3bfa77f0 63 0, // LastBlock\r
64 0, // LowestAlignedLba\r
65 1 // LogicalBlocksPerPhysicalBlock\r
ad86a50a 66 },\r
67 { // DiskInfo\r
68 EFI_DISK_INFO_IDE_INTERFACE_GUID,\r
69 AtaDiskInfoInquiry,\r
70 AtaDiskInfoIdentify,\r
71 AtaDiskInfoSenseData,\r
72 AtaDiskInfoWhichIde\r
73 },\r
05a44e91 74 NULL, // DevicePath\r
75 NULL, // AtaBusDriverData\r
76 0, // Port\r
77 0, // PortMultiplierPort\r
ad86a50a 78 { 0, }, // Packet\r
79 {{ 0}, }, // Acb\r
80 NULL, // Asb\r
81 FALSE, // UdmaValid\r
82 FALSE, // Lba48Bit\r
83 NULL, // IdentifyData\r
84 NULL, // ControllerNameTable\r
490b5ea1 85 {L'\0', }, // ModelName\r
86 {NULL, NULL} // AtaTaskList\r
ad86a50a 87};\r
88\r
89/**\r
90 Allocates an aligned buffer for ATA device.\r
91\r
92 This function allocates an aligned buffer for the ATA device to perform\r
93 ATA pass through operations. The alignment requirement is from ATA pass\r
94 through interface.\r
95\r
96 @param AtaDevice The ATA child device involved for the operation.\r
97 @param BufferSize The request buffer size.\r
98\r
99 @return A pointer to the aligned buffer or NULL if the allocation fails.\r
100\r
101**/\r
102VOID *\r
103AllocateAlignedBuffer (\r
104 IN ATA_DEVICE *AtaDevice,\r
105 IN UINTN BufferSize\r
106 )\r
107{\r
108 return AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), AtaDevice->AtaBusDriverData->AtaPassThru->Mode->IoAlign);\r
109}\r
110\r
111/**\r
112 Frees an aligned buffer for ATA device.\r
113\r
114 This function frees an aligned buffer for the ATA device to perform\r
115 ATA pass through operations.\r
116\r
05a44e91 117 @param Buffer The aligned buffer to be freed.\r
ad86a50a 118 @param BufferSize The request buffer size.\r
119\r
120**/\r
121VOID\r
122FreeAlignedBuffer (\r
123 IN VOID *Buffer,\r
124 IN UINTN BufferSize\r
125 )\r
126{\r
127 if (Buffer != NULL) {\r
128 FreePages (Buffer, EFI_SIZE_TO_PAGES (BufferSize));\r
129 }\r
130}\r
131\r
132\r
133/**\r
134 Release all the resources allocated for the ATA device.\r
135\r
136 This function releases all the resources allocated for the ATA device.\r
137\r
138 @param AtaDevice The ATA child device involved for the operation.\r
139\r
140**/\r
141VOID\r
142ReleaseAtaResources (\r
143 IN ATA_DEVICE *AtaDevice\r
144 )\r
145{\r
490b5ea1 146 ATA_BUS_ASYN_TASK *Task;\r
147 LIST_ENTRY *Entry;\r
148 LIST_ENTRY *DelEntry;\r
149 EFI_TPL OldTpl;\r
150\r
ad86a50a 151 FreeUnicodeStringTable (AtaDevice->ControllerNameTable);\r
152 FreeAlignedBuffer (AtaDevice->Asb, sizeof (*AtaDevice->Asb));\r
153 FreeAlignedBuffer (AtaDevice->IdentifyData, sizeof (*AtaDevice->IdentifyData));\r
154 if (AtaDevice->DevicePath != NULL) {\r
155 FreePool (AtaDevice->DevicePath);\r
156 }\r
490b5ea1 157 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
158 if (!IsListEmpty (&AtaDevice->AtaTaskList)) {\r
159 //\r
160 // Free the Subtask list.\r
161 //\r
162 for(Entry = (&AtaDevice->AtaTaskList)->ForwardLink; \r
163 Entry != (&AtaDevice->AtaTaskList);\r
164 ) {\r
165 DelEntry = Entry;\r
166 Entry = Entry->ForwardLink;\r
167 Task = ATA_AYNS_TASK_FROM_ENTRY (DelEntry);\r
168 \r
169 RemoveEntryList (DelEntry);\r
170 FreeAtaSubTask (Task);\r
171 }\r
172 }\r
173 gBS->RestoreTPL (OldTpl);\r
ad86a50a 174 FreePool (AtaDevice);\r
175}\r
176\r
177\r
178/**\r
179 Registers an ATA device.\r
180\r
181 This function allocates an ATA device structure for the ATA device specified by\r
182 Port and PortMultiplierPort if the ATA device is identified as a valid one. \r
183 Then it will create child handle and install Block IO and Disk Info protocol on\r
184 it.\r
185\r
05a44e91 186 @param AtaBusDriverData The parent ATA bus driver data structure.\r
ad86a50a 187 @param Port The port number of the ATA device.\r
188 @param PortMultiplierPort The port multiplier port number of the ATA device.\r
189\r
190 @retval EFI_SUCCESS The ATA device is successfully registered.\r
191 @retval EFI_OUT_OF_RESOURCES There is not enough memory to allocate the ATA device\r
192 and related data structures.\r
193 @return Others Some error occurs when registering the ATA device.\r
194**/\r
195EFI_STATUS\r
196RegisterAtaDevice (\r
197 IN OUT ATA_BUS_DRIVER_DATA *AtaBusDriverData,\r
198 IN UINT16 Port,\r
199 IN UINT16 PortMultiplierPort\r
200 )\r
201{\r
202 EFI_STATUS Status;\r
203 ATA_DEVICE *AtaDevice;\r
204 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
205 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
e519983a 206 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
207 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
208 EFI_HANDLE DeviceHandle;\r
ad86a50a 209\r
e519983a 210 AtaDevice = NULL;\r
ad86a50a 211 NewDevicePathNode = NULL;\r
e519983a 212 DevicePath = NULL;\r
213 RemainingDevicePath = NULL;\r
214\r
215 //\r
216 // Build device path \r
217 //\r
218 AtaPassThru = AtaBusDriverData->AtaPassThru;\r
219 Status = AtaPassThru->BuildDevicePath (AtaPassThru, Port, PortMultiplierPort, &NewDevicePathNode);\r
220 if (EFI_ERROR (Status)) {\r
221 goto Done;\r
222 }\r
223\r
224 DevicePath = AppendDevicePathNode (AtaBusDriverData->ParentDevicePath, NewDevicePathNode);\r
225 if (DevicePath == NULL) {\r
e70ae46c 226 Status = EFI_OUT_OF_RESOURCES;\r
e519983a 227 goto Done;\r
228 }\r
229\r
230 DeviceHandle = NULL;\r
e70ae46c 231 RemainingDevicePath = DevicePath;\r
e519983a 232 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);\r
233 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {\r
234 Status = EFI_ALREADY_STARTED;\r
e70ae46c 235 FreePool (DevicePath);\r
e519983a 236 goto Done;\r
237 }\r
ad86a50a 238\r
239 //\r
240 // Allocate ATA device from the template.\r
241 //\r
242 AtaDevice = AllocateCopyPool (sizeof (gAtaDeviceTemplate), &gAtaDeviceTemplate);\r
243 if (AtaDevice == NULL) {\r
e519983a 244 Status = EFI_OUT_OF_RESOURCES;\r
245 goto Done;\r
ad86a50a 246 }\r
247\r
248 //\r
249 // Initializes ATA device structures and allocates the required buffer.\r
250 //\r
490b5ea1 251 AtaDevice->BlockIo.Media = &AtaDevice->BlockMedia;\r
252 AtaDevice->BlockIo2.Media = &AtaDevice->BlockMedia;\r
253 AtaDevice->AtaBusDriverData = AtaBusDriverData;\r
254 AtaDevice->DevicePath = DevicePath;\r
255 AtaDevice->Port = Port;\r
ad86a50a 256 AtaDevice->PortMultiplierPort = PortMultiplierPort;\r
257 AtaDevice->Asb = AllocateAlignedBuffer (AtaDevice, sizeof (*AtaDevice->Asb));\r
258 if (AtaDevice->Asb == NULL) {\r
259 Status = EFI_OUT_OF_RESOURCES;\r
260 goto Done;\r
261 }\r
262 AtaDevice->IdentifyData = AllocateAlignedBuffer (AtaDevice, sizeof (*AtaDevice->IdentifyData));\r
263 if (AtaDevice->IdentifyData == NULL) {\r
264 Status = EFI_OUT_OF_RESOURCES;\r
265 goto Done;\r
266 }\r
267\r
490b5ea1 268 //\r
269 // Initial Ata Task List\r
270 //\r
271 InitializeListHead (&AtaDevice->AtaTaskList);\r
272\r
ad86a50a 273 //\r
274 // Try to identify the ATA device via the ATA pass through command. \r
275 //\r
276 Status = DiscoverAtaDevice (AtaDevice);\r
277 if (EFI_ERROR (Status)) {\r
278 goto Done;\r
279 }\r
490b5ea1 280\r
ad86a50a 281 //\r
282 // Build controller name for Component Name (2) protocol.\r
283 //\r
284 Status = AddUnicodeString2 (\r
285 "eng",\r
286 gAtaBusComponentName.SupportedLanguages,\r
287 &AtaDevice->ControllerNameTable,\r
288 AtaDevice->ModelName,\r
289 TRUE\r
290 );\r
291 if (EFI_ERROR (Status)) {\r
292 goto Done;\r
293 }\r
294\r
295 Status = AddUnicodeString2 (\r
296 "en",\r
297 gAtaBusComponentName2.SupportedLanguages,\r
298 &AtaDevice->ControllerNameTable,\r
299 AtaDevice->ModelName,\r
300 FALSE\r
301 );\r
302 if (EFI_ERROR (Status)) {\r
303 goto Done;\r
304 }\r
305\r
ad86a50a 306 //\r
307 // Update to AHCI interface GUID based on device path node. The default one\r
308 // is IDE interface GUID copied from template.\r
309 //\r
310 if (NewDevicePathNode->SubType == MSG_SATA_DP) {\r
311 CopyGuid (&AtaDevice->DiskInfo.Interface, &gEfiDiskInfoAhciInterfaceGuid);\r
312 }\r
313\r
ad86a50a 314 Status = gBS->InstallMultipleProtocolInterfaces (\r
315 &AtaDevice->Handle,\r
316 &gEfiDevicePathProtocolGuid,\r
317 AtaDevice->DevicePath,\r
318 &gEfiBlockIoProtocolGuid,\r
319 &AtaDevice->BlockIo,\r
490b5ea1 320 &gEfiBlockIo2ProtocolGuid,\r
321 &AtaDevice->BlockIo2,\r
ad86a50a 322 &gEfiDiskInfoProtocolGuid,\r
323 &AtaDevice->DiskInfo,\r
324 NULL\r
325 );\r
326 if (EFI_ERROR (Status)) {\r
327 goto Done;\r
328 }\r
329\r
330 gBS->OpenProtocol (\r
331 AtaBusDriverData->Controller,\r
332 &gEfiAtaPassThruProtocolGuid,\r
333 (VOID **) &AtaPassThru,\r
334 AtaBusDriverData->DriverBindingHandle,\r
335 AtaDevice->Handle,\r
336 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
337 );\r
e519983a 338\r
ad86a50a 339Done:\r
340 if (NewDevicePathNode != NULL) {\r
341 FreePool (NewDevicePathNode);\r
342 }\r
343\r
e519983a 344 if (EFI_ERROR (Status) && (AtaDevice != NULL)) {\r
ad86a50a 345 ReleaseAtaResources (AtaDevice); \r
346 DEBUG ((DEBUG_ERROR | DEBUG_INIT, "Failed to initialize Port %x PortMultiplierPort %x, status = %r\n", Port, PortMultiplierPort, Status));\r
347 }\r
348 return Status;\r
349}\r
350\r
351\r
352/**\r
353 Unregisters an ATA device.\r
354\r
355 This function removes the protocols installed on the controller handle and \r
356 frees the resources allocated for the ATA device. \r
357\r
05a44e91 358 @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.\r
ad86a50a 359 @param Controller The controller handle of the ATA device.\r
360 @param Handle The child handle.\r
361\r
362 @retval EFI_SUCCESS The ATA device is successfully unregistered.\r
363 @return Others Some error occurs when unregistering the ATA device.\r
364\r
365**/\r
366EFI_STATUS\r
367UnregisterAtaDevice (\r
368 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
369 IN EFI_HANDLE Controller,\r
370 IN EFI_HANDLE Handle\r
371 )\r
372{\r
373 EFI_STATUS Status;\r
374 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
490b5ea1 375 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;\r
ad86a50a 376 ATA_DEVICE *AtaDevice;\r
377 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
490b5ea1 378 BlockIo2 = NULL;\r
379 BlockIo = NULL;\r
ad86a50a 380\r
381 Status = gBS->OpenProtocol (\r
382 Handle,\r
383 &gEfiBlockIoProtocolGuid,\r
384 (VOID **) &BlockIo,\r
385 This->DriverBindingHandle,\r
386 Controller,\r
387 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
388 );\r
389 if (EFI_ERROR (Status)) {\r
490b5ea1 390 //\r
391 // Locate BlockIo2 protocol\r
392 //\r
393 Status = gBS->OpenProtocol (\r
394 Handle,\r
395 &gEfiBlockIo2ProtocolGuid,\r
396 (VOID **) &BlockIo2,\r
397 This->DriverBindingHandle,\r
398 Controller,\r
399 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
400 );\r
401 if (EFI_ERROR (Status)) {\r
402 return Status;\r
403 }\r
ad86a50a 404 }\r
405\r
490b5ea1 406 //\r
407 // Get AtaDevice data.\r
408 //\r
409 if (BlockIo != NULL) {\r
410 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (BlockIo);\r
411 } else {\r
412 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (BlockIo2);\r
413 } \r
ad86a50a 414\r
415 //\r
416 // Close the child handle\r
417 //\r
418 gBS->CloseProtocol (\r
419 Controller,\r
420 &gEfiAtaPassThruProtocolGuid,\r
421 This->DriverBindingHandle,\r
422 Handle\r
423 );\r
424\r
490b5ea1 425 //\r
426 // The Ata Bus driver installs the BlockIo and BlockIo2 in the DriverBindingStart().\r
427 // Here should uninstall both of them.\r
428 //\r
ad86a50a 429 Status = gBS->UninstallMultipleProtocolInterfaces (\r
430 Handle,\r
431 &gEfiDevicePathProtocolGuid,\r
432 AtaDevice->DevicePath,\r
433 &gEfiBlockIoProtocolGuid,\r
434 &AtaDevice->BlockIo,\r
490b5ea1 435 &gEfiBlockIo2ProtocolGuid,\r
436 &AtaDevice->BlockIo2,\r
ad86a50a 437 &gEfiDiskInfoProtocolGuid,\r
438 &AtaDevice->DiskInfo,\r
439 NULL\r
440 );\r
441\r
442 if (EFI_ERROR (Status)) {\r
443 gBS->OpenProtocol (\r
444 Controller,\r
445 &gEfiAtaPassThruProtocolGuid,\r
446 (VOID **) &AtaPassThru,\r
447 This->DriverBindingHandle,\r
448 Handle,\r
449 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
450 );\r
451 return Status;\r
452 }\r
453\r
454 ReleaseAtaResources (AtaDevice);\r
ad86a50a 455 return Status;\r
456}\r
457\r
458\r
459\r
460/**\r
461 Tests to see if this driver supports a given controller. If a child device is provided, \r
462 it further tests to see if this driver supports creating a handle for the specified child device.\r
463\r
464 This function checks to see if the driver specified by This supports the device specified by \r
465 ControllerHandle. Drivers will typically use the device path attached to \r
466 ControllerHandle and/or the services from the bus I/O abstraction attached to \r
467 ControllerHandle to determine if the driver supports ControllerHandle. This function \r
468 may be called many times during platform initialization. In order to reduce boot times, the tests \r
469 performed by this function must be very small, and take as little time as possible to execute. This \r
470 function must not change the state of any hardware devices, and this function must be aware that the \r
471 device specified by ControllerHandle may already be managed by the same driver or a \r
472 different driver. This function must match its calls to AllocatePages() with FreePages(), \r
473 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
474 Since ControllerHandle may have been previously started by the same driver, if a protocol is \r
475 already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
476 to guarantee the state of ControllerHandle is not modified by this function.\r
477\r
478 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
479 @param[in] ControllerHandle The handle of the controller to test. This handle \r
480 must support a protocol interface that supplies \r
481 an I/O abstraction to the driver.\r
482 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
483 parameter is ignored by device drivers, and is optional for bus \r
484 drivers. For bus drivers, if this parameter is not NULL, then \r
485 the bus driver must determine if the bus controller specified \r
486 by ControllerHandle and the child controller specified \r
487 by RemainingDevicePath are both supported by this \r
488 bus driver.\r
489\r
490 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
491 RemainingDevicePath is supported by the driver specified by This.\r
492 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
493 RemainingDevicePath is already being managed by the driver\r
494 specified by This.\r
495 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
496 RemainingDevicePath is already being managed by a different\r
497 driver or an application that requires exclusive access.\r
498 Currently not implemented.\r
499 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
500 RemainingDevicePath is not supported by the driver specified by This.\r
501**/\r
502EFI_STATUS\r
503EFIAPI\r
504AtaBusDriverBindingSupported (\r
505 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
506 IN EFI_HANDLE Controller,\r
507 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
508 )\r
509{\r
510 EFI_STATUS Status;\r
511 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
512 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
513 UINT16 Port;\r
514 UINT16 PortMultiplierPort;\r
490b5ea1 515\r
ad86a50a 516 //\r
517 // Test EFI_ATA_PASS_THRU_PROTOCOL on controller handle.\r
518 //\r
519 Status = gBS->OpenProtocol (\r
520 Controller,\r
521 &gEfiAtaPassThruProtocolGuid,\r
522 (VOID **) &AtaPassThru,\r
523 This->DriverBindingHandle,\r
524 Controller,\r
525 EFI_OPEN_PROTOCOL_BY_DRIVER\r
526 );\r
527\r
528 if (Status == EFI_ALREADY_STARTED) {\r
529 return EFI_SUCCESS;\r
530 }\r
531\r
532 if (EFI_ERROR (Status)) {\r
533 return Status;\r
534 }\r
535\r
536 //\r
537 // Test RemainingDevicePath is valid or not.\r
538 //\r
539 if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {\r
540 Status = AtaPassThru->GetDevice (AtaPassThru, RemainingDevicePath, &Port, &PortMultiplierPort);\r
541 if (EFI_ERROR (Status)) {\r
542 return Status;\r
543 }\r
544 }\r
545\r
546 //\r
547 // Close the I/O Abstraction(s) used to perform the supported test\r
548 //\r
549 gBS->CloseProtocol (\r
550 Controller,\r
551 &gEfiAtaPassThruProtocolGuid,\r
552 This->DriverBindingHandle,\r
553 Controller\r
554 );\r
555\r
556 //\r
557 // Open the EFI Device Path protocol needed to perform the supported test\r
558 //\r
559 Status = gBS->OpenProtocol (\r
560 Controller,\r
561 &gEfiDevicePathProtocolGuid,\r
562 (VOID **) &ParentDevicePath,\r
563 This->DriverBindingHandle,\r
564 Controller,\r
565 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
566 );\r
567 return Status;\r
568}\r
569\r
570\r
571/**\r
572 Starts a device controller or a bus controller.\r
573\r
574 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
575 As a result, much of the error checking on the parameters to Start() has been moved into this \r
576 common boot service. It is legal to call Start() from other locations, \r
577 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
578 1. ControllerHandle must be a valid EFI_HANDLE.\r
579 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
580 EFI_DEVICE_PATH_PROTOCOL.\r
581 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
582 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
583\r
584 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
585 @param[in] ControllerHandle The handle of the controller to start. This handle \r
586 must support a protocol interface that supplies \r
587 an I/O abstraction to the driver.\r
588 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
589 parameter is ignored by device drivers, and is optional for bus \r
590 drivers. For a bus driver, if this parameter is NULL, then handles \r
490b5ea1 591 for all the children of Controller are created by this driver.\r
ad86a50a 592 If this parameter is not NULL and the first Device Path Node is \r
593 not the End of Device Path Node, then only the handle for the \r
594 child device specified by the first Device Path Node of \r
595 RemainingDevicePath is created by this driver.\r
596 If the first Device Path Node of RemainingDevicePath is \r
597 the End of Device Path Node, no child handle is created by this\r
598 driver.\r
599\r
600 @retval EFI_SUCCESS The device was started.\r
601 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
602 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
603 @retval Others The driver failded to start the device.\r
604\r
605**/\r
606EFI_STATUS\r
607EFIAPI\r
608AtaBusDriverBindingStart (\r
609 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
610 IN EFI_HANDLE Controller,\r
611 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
612 )\r
613{\r
614 EFI_STATUS Status;\r
615 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
616 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
617 ATA_BUS_DRIVER_DATA *AtaBusDriverData;\r
618 UINT16 Port;\r
619 UINT16 PortMultiplierPort;\r
620\r
621 AtaBusDriverData = NULL;\r
622\r
623 Status = gBS->OpenProtocol (\r
624 Controller,\r
625 &gEfiDevicePathProtocolGuid,\r
626 (VOID **) &ParentDevicePath,\r
627 This->DriverBindingHandle,\r
628 Controller,\r
629 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
630 );\r
631 if (EFI_ERROR (Status)) {\r
632 return Status;\r
633 }\r
634\r
635 Status = gBS->OpenProtocol (\r
636 Controller,\r
637 &gEfiAtaPassThruProtocolGuid,\r
638 (VOID **) &AtaPassThru,\r
639 This->DriverBindingHandle,\r
640 Controller,\r
641 EFI_OPEN_PROTOCOL_BY_DRIVER\r
642 );\r
643 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
644 goto ErrorExit;\r
645 }\r
646\r
647 //\r
648 // Check EFI_ALREADY_STARTED to reuse the original ATA_BUS_DRIVER_DATA.\r
649 //\r
650 if (Status != EFI_ALREADY_STARTED) {\r
651 AtaBusDriverData = AllocateZeroPool (sizeof (ATA_BUS_DRIVER_DATA));\r
652 if (AtaBusDriverData == NULL) {\r
653 Status = EFI_OUT_OF_RESOURCES;\r
654 goto ErrorExit;\r
655 }\r
656\r
657 AtaBusDriverData->AtaPassThru = AtaPassThru;\r
490b5ea1 658 AtaBusDriverData->Controller = Controller;\r
ad86a50a 659 AtaBusDriverData->ParentDevicePath = ParentDevicePath;\r
660 AtaBusDriverData->DriverBindingHandle = This->DriverBindingHandle;\r
661\r
662 Status = gBS->InstallMultipleProtocolInterfaces (\r
663 &Controller,\r
664 &gEfiCallerIdGuid,\r
665 AtaBusDriverData,\r
666 NULL\r
667 );\r
668 if (EFI_ERROR (Status)) {\r
669 goto ErrorExit;\r
670 }\r
671\r
672 } else {\r
673 Status = gBS->OpenProtocol (\r
674 Controller,\r
675 &gEfiCallerIdGuid,\r
676 (VOID **) &AtaBusDriverData,\r
677 This->DriverBindingHandle,\r
678 Controller,\r
679 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
680 );\r
681 if (EFI_ERROR (Status)) {\r
682 AtaBusDriverData = NULL;\r
683 goto ErrorExit;\r
684 }\r
685 }\r
686\r
687 if (RemainingDevicePath == NULL) {\r
688 Port = 0xFFFF;\r
689 while (TRUE) {\r
690 Status = AtaPassThru->GetNextPort (AtaPassThru, &Port);\r
691 if (EFI_ERROR (Status)) {\r
692 //\r
693 // We cannot find more legal port then we are done.\r
694 //\r
695 break;\r
696 }\r
490b5ea1 697\r
ad86a50a 698 PortMultiplierPort = 0xFFFF;\r
699 while (TRUE) {\r
700 Status = AtaPassThru->GetNextDevice (AtaPassThru, Port, &PortMultiplierPort);\r
701 if (EFI_ERROR (Status)) {\r
702 //\r
703 // We cannot find more legal port multiplier port number for ATA device\r
704 // on the port, then we are done.\r
705 //\r
706 break;\r
707 }\r
708 RegisterAtaDevice (AtaBusDriverData, Port, PortMultiplierPort);\r
709 }\r
710 }\r
711 Status = EFI_SUCCESS;\r
712 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
713 Status = AtaPassThru->GetDevice (AtaPassThru, RemainingDevicePath, &Port, &PortMultiplierPort);\r
714 if (!EFI_ERROR (Status)) {\r
715 Status = RegisterAtaDevice (AtaBusDriverData,Port, PortMultiplierPort);\r
716 }\r
717 }\r
490b5ea1 718\r
ad86a50a 719 return Status;\r
720\r
721ErrorExit:\r
722\r
723 if (AtaBusDriverData != NULL) {\r
724 gBS->UninstallMultipleProtocolInterfaces (\r
725 Controller,\r
726 &gEfiCallerIdGuid,\r
727 AtaBusDriverData,\r
728 NULL\r
729 );\r
730 FreePool (AtaBusDriverData);\r
731 }\r
732\r
733 gBS->CloseProtocol (\r
734 Controller,\r
735 &gEfiAtaPassThruProtocolGuid,\r
736 This->DriverBindingHandle,\r
737 Controller\r
738 );\r
739\r
740 return Status;\r
741\r
742}\r
743\r
744\r
745/**\r
746 Stops a device controller or a bus controller.\r
747 \r
748 The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
749 As a result, much of the error checking on the parameters to Stop() has been moved \r
750 into this common boot service. It is legal to call Stop() from other locations, \r
751 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
752 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
753 same driver's Start() function.\r
754 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
755 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
756 Start() function, and the Start() function must have called OpenProtocol() on\r
757 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
758 \r
759 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
760 @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
761 support a bus specific I/O protocol for the driver \r
762 to use to stop the device.\r
763 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
764 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
765 if NumberOfChildren is 0.\r
766\r
767 @retval EFI_SUCCESS The device was stopped.\r
768 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
769\r
770**/\r
771EFI_STATUS\r
772EFIAPI\r
773AtaBusDriverBindingStop (\r
774 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
775 IN EFI_HANDLE Controller,\r
776 IN UINTN NumberOfChildren,\r
777 IN EFI_HANDLE *ChildHandleBuffer\r
778 )\r
779{\r
780 EFI_STATUS Status;\r
781 BOOLEAN AllChildrenStopped;\r
782 UINTN Index;\r
783 ATA_BUS_DRIVER_DATA *AtaBusDriverData;\r
784\r
785 if (NumberOfChildren == 0) {\r
786 Status = gBS->OpenProtocol (\r
787 Controller,\r
788 &gEfiCallerIdGuid,\r
789 (VOID **) &AtaBusDriverData,\r
790 This->DriverBindingHandle,\r
791 Controller,\r
792 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
793 );\r
794 if (!EFI_ERROR (Status)) {\r
795 gBS->UninstallMultipleProtocolInterfaces (\r
796 Controller,\r
797 &gEfiCallerIdGuid,\r
798 AtaBusDriverData,\r
799 NULL\r
800 );\r
801 FreePool (AtaBusDriverData);\r
802 }\r
803\r
804 gBS->CloseProtocol (\r
805 Controller,\r
806 &gEfiAtaPassThruProtocolGuid,\r
807 This->DriverBindingHandle,\r
808 Controller\r
809 );\r
810\r
811 return EFI_SUCCESS;\r
812 }\r
813\r
814 AllChildrenStopped = TRUE;\r
815\r
816 for (Index = 0; Index < NumberOfChildren; Index++) {\r
817\r
818 Status = UnregisterAtaDevice (This, Controller, ChildHandleBuffer[Index]);\r
819 if (EFI_ERROR (Status)) {\r
820 AllChildrenStopped = FALSE;\r
821 }\r
822 }\r
823\r
824 if (!AllChildrenStopped) {\r
825 return EFI_DEVICE_ERROR;\r
826 }\r
827\r
828 return EFI_SUCCESS;\r
829}\r
830\r
831\r
832/**\r
833 Reset the Block Device.\r
834\r
835 @param This Indicates a pointer to the calling context.\r
836 @param ExtendedVerification Driver may perform diagnostics on reset.\r
837\r
838 @retval EFI_SUCCESS The device was reset.\r
839 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
840 not be reset.\r
841\r
842**/\r
843EFI_STATUS\r
844EFIAPI\r
845AtaBlockIoReset (\r
846 IN EFI_BLOCK_IO_PROTOCOL *This,\r
847 IN BOOLEAN ExtendedVerification\r
848 )\r
849{\r
850 EFI_STATUS Status;\r
851 ATA_DEVICE *AtaDevice;\r
852 EFI_TPL OldTpl;\r
853\r
854 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
855\r
856 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (This);\r
857\r
490b5ea1 858 Status = ResetAtaDevice (AtaDevice);\r
ad86a50a 859\r
c6e797ae 860 if (EFI_ERROR (Status)) {\r
861 Status = EFI_DEVICE_ERROR;\r
862 }\r
863\r
ad86a50a 864 gBS->RestoreTPL (OldTpl);\r
865 return Status;\r
866}\r
867\r
868\r
869/**\r
870 Read/Write BufferSize bytes from Lba from/into Buffer.\r
871\r
490b5ea1 872 @param[in] This Indicates a pointer to the calling context. Either be\r
873 block I/O or block I/O2. \r
874 @param[in] MediaId The media ID that the read/write request is for.\r
875 @param[in] Lba The starting logical block address to be read/written.\r
876 The caller is responsible for reading/writing to only\r
877 legitimate locations.\r
878 @param[in, out] Token A pointer to the token associated with the transaction.\r
879 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
880 @param[out] Buffer A pointer to the destination/source buffer for the data.\r
881 @param[in] IsBlockIo2 Indicate the calling is from BlockIO or BlockIO2. TURE is\r
882 from BlockIO2, FALSE is for BlockIO.\r
883 @param[in] IsWrite Indicates whether it is a write operation.\r
ad86a50a 884\r
885 @retval EFI_SUCCESS The data was read/written correctly to the device.\r
886 @retval EFI_WRITE_PROTECTED The device can not be read/written to.\r
887 @retval EFI_DEVICE_ERROR The device reported an error while performing the read/write.\r
888 @retval EFI_NO_MEDIA There is no media in the device.\r
889 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
890 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
891 @retval EFI_INVALID_PARAMETER The read/write request contains LBAs that are not valid, \r
892 or the buffer is not on proper alignment.\r
893\r
894**/\r
895EFI_STATUS\r
896BlockIoReadWrite (\r
490b5ea1 897 IN VOID *This,\r
898 IN UINT32 MediaId,\r
899 IN EFI_LBA Lba,\r
900 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
901 IN UINTN BufferSize,\r
902 OUT VOID *Buffer,\r
903 IN BOOLEAN IsBlockIo2,\r
904 IN BOOLEAN IsWrite\r
ad86a50a 905 )\r
906{\r
907 ATA_DEVICE *AtaDevice;\r
908 EFI_STATUS Status;\r
909 EFI_TPL OldTpl;\r
910 EFI_BLOCK_IO_MEDIA *Media;\r
911 UINTN BlockSize;\r
912 UINTN NumberOfBlocks;\r
913 UINTN IoAlign;\r
914\r
490b5ea1 915 if (IsBlockIo2) {\r
916 Media = ((EFI_BLOCK_IO2_PROTOCOL *) This)->Media;\r
917 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (This);\r
918 } else {\r
919 Media = ((EFI_BLOCK_IO_PROTOCOL *) This)->Media;\r
920 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (This);\r
921 }\r
922\r
fcf5e49d
RN
923 if (MediaId != Media->MediaId) {\r
924 return EFI_MEDIA_CHANGED;\r
925 }\r
926\r
490b5ea1 927 //\r
928 // Check parameters.\r
929 //\r
ad86a50a 930 if (Buffer == NULL) {\r
931 return EFI_INVALID_PARAMETER;\r
932 }\r
933\r
934 if (BufferSize == 0) {\r
935 return EFI_SUCCESS;\r
490b5ea1 936 } \r
ad86a50a 937\r
ad86a50a 938 BlockSize = Media->BlockSize;\r
939 if ((BufferSize % BlockSize) != 0) {\r
940 return EFI_BAD_BUFFER_SIZE;\r
941 }\r
942 \r
943 NumberOfBlocks = BufferSize / BlockSize;\r
944 if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {\r
945 return EFI_INVALID_PARAMETER;\r
946 }\r
947\r
948 IoAlign = Media->IoAlign;\r
949 if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {\r
950 return EFI_INVALID_PARAMETER;\r
951 }\r
952\r
953 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
ad86a50a 954 \r
955 //\r
956 // Invoke low level AtaDevice Access Routine.\r
957 //\r
490b5ea1 958 Status = AccessAtaDevice (AtaDevice, Buffer, Lba, NumberOfBlocks, IsWrite, Token);\r
ad86a50a 959 \r
960 gBS->RestoreTPL (OldTpl);\r
961\r
962 return Status;\r
963}\r
964\r
965\r
966/**\r
967 Read BufferSize bytes from Lba into Buffer.\r
968\r
969 @param This Indicates a pointer to the calling context.\r
970 @param MediaId Id of the media, changes every time the media is replaced.\r
971 @param Lba The starting Logical Block Address to read from\r
972 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
973 @param Buffer A pointer to the destination buffer for the data. The caller is\r
974 responsible for either having implicit or explicit ownership of the buffer.\r
975\r
976 @retval EFI_SUCCESS The data was read correctly from the device.\r
977 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
978 @retval EFI_NO_MEDIA There is no media in the device.\r
979 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
980 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
981 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
982 or the buffer is not on proper alignment.\r
983\r
984**/\r
985EFI_STATUS\r
986EFIAPI\r
987AtaBlockIoReadBlocks (\r
988 IN EFI_BLOCK_IO_PROTOCOL *This,\r
989 IN UINT32 MediaId,\r
990 IN EFI_LBA Lba,\r
991 IN UINTN BufferSize,\r
992 OUT VOID *Buffer\r
993 )\r
994{\r
490b5ea1 995 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, NULL, BufferSize, Buffer, FALSE, FALSE);\r
ad86a50a 996}\r
997\r
998\r
999/**\r
1000 Write BufferSize bytes from Lba into Buffer.\r
1001\r
1002 @param This Indicates a pointer to the calling context.\r
1003 @param MediaId The media ID that the write request is for.\r
1004 @param Lba The starting logical block address to be written. The caller is\r
1005 responsible for writing to only legitimate locations.\r
1006 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
1007 @param Buffer A pointer to the source buffer for the data.\r
1008\r
1009 @retval EFI_SUCCESS The data was written correctly to the device.\r
1010 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
1011 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
1012 @retval EFI_NO_MEDIA There is no media in the device.\r
1013 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
1014 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
1015 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
1016 or the buffer is not on proper alignment.\r
1017\r
1018**/\r
1019EFI_STATUS\r
1020EFIAPI\r
1021AtaBlockIoWriteBlocks (\r
1022 IN EFI_BLOCK_IO_PROTOCOL *This,\r
1023 IN UINT32 MediaId,\r
1024 IN EFI_LBA Lba,\r
1025 IN UINTN BufferSize,\r
1026 IN VOID *Buffer\r
1027 )\r
1028{\r
490b5ea1 1029 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, NULL, BufferSize, Buffer, FALSE, TRUE);\r
ad86a50a 1030}\r
1031\r
1032\r
1033/**\r
1034 Flush the Block Device.\r
1035\r
1036 @param This Indicates a pointer to the calling context.\r
1037\r
1038 @retval EFI_SUCCESS All outstanding data was written to the device\r
1039 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data\r
1040 @retval EFI_NO_MEDIA There is no media in the device.\r
1041\r
1042**/\r
1043EFI_STATUS\r
1044EFIAPI\r
1045AtaBlockIoFlushBlocks (\r
1046 IN EFI_BLOCK_IO_PROTOCOL *This\r
1047 )\r
1048{\r
1049 //\r
1050 // return directly\r
1051 //\r
1052 return EFI_SUCCESS;\r
1053}\r
1054\r
490b5ea1 1055/**\r
1056 Reset the Block Device.\r
1057\r
1058 @param[in] This Indicates a pointer to the calling context.\r
1059 @param[in] ExtendedVerification Driver may perform diagnostics on reset.\r
1060\r
1061 @retval EFI_SUCCESS The device was reset.\r
1062 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
1063 not be reset.\r
1064\r
1065**/\r
1066EFI_STATUS\r
1067EFIAPI\r
1068AtaBlockIoResetEx (\r
1069 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1070 IN BOOLEAN ExtendedVerification\r
1071 )\r
1072{\r
1073 EFI_STATUS Status;\r
1074 ATA_DEVICE *AtaDevice;\r
1075 EFI_TPL OldTpl;\r
1076\r
1077 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1078\r
1079 AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (This);\r
1080\r
1081 Status = ResetAtaDevice (AtaDevice);\r
1082\r
1083 if (EFI_ERROR (Status)) {\r
1084 Status = EFI_DEVICE_ERROR;\r
1085 }\r
1086\r
1087 gBS->RestoreTPL (OldTpl);\r
1088 return Status;\r
1089}\r
1090\r
1091/**\r
1092 Read BufferSize bytes from Lba into Buffer.\r
1093\r
1094 @param[in] This Indicates a pointer to the calling context.\r
1095 @param[in] MediaId Id of the media, changes every time the media is replaced.\r
1096 @param[in] Lba The starting Logical Block Address to read from.\r
1097 @param[in, out] Token A pointer to the token associated with the transaction.\r
1098 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
1099 @param[out] Buffer A pointer to the destination buffer for the data. The caller is\r
1100 responsible for either having implicit or explicit ownership of the buffer.\r
1101\r
1102 @retval EFI_SUCCESS The read request was queued if Event is not NULL.\r
1103 The data was read correctly from the device if\r
1104 the Event is NULL.\r
1105 @retval EFI_DEVICE_ERROR The device reported an error while performing\r
1106 the read.\r
1107 @retval EFI_NO_MEDIA There is no media in the device.\r
1108 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
1109 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
1110 intrinsic block size of the device.\r
1111 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
1112 or the buffer is not on proper alignment.\r
1113 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
1114 of resources.\r
1115\r
1116**/\r
1117EFI_STATUS\r
1118EFIAPI\r
1119AtaBlockIoReadBlocksEx (\r
1120 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1121 IN UINT32 MediaId,\r
1122 IN EFI_LBA Lba,\r
1123 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
1124 IN UINTN BufferSize,\r
1125 OUT VOID *Buffer\r
1126 )\r
1127{\r
1128 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, Token, BufferSize, Buffer, TRUE, FALSE);\r
1129}\r
1130\r
1131\r
1132/**\r
1133 Write BufferSize bytes from Lba into Buffer.\r
1134\r
1135 @param[in] This Indicates a pointer to the calling context.\r
1136 @param[in] MediaId The media ID that the write request is for.\r
1137 @param[in] Lba The starting logical block address to be written. The\r
1138 caller is responsible for writing to only legitimate\r
1139 locations.\r
1140 @param[in, out] Token A pointer to the token associated with the transaction.\r
1141 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
1142 @param[in] Buffer A pointer to the source buffer for the data.\r
ad86a50a 1143\r
490b5ea1 1144 @retval EFI_SUCCESS The data was written correctly to the device.\r
1145 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
1146 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
1147 @retval EFI_NO_MEDIA There is no media in the device.\r
1148 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
1149 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
1150 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
1151 or the buffer is not on proper alignment.\r
1152\r
1153**/\r
1154EFI_STATUS\r
1155EFIAPI\r
1156AtaBlockIoWriteBlocksEx (\r
1157 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1158 IN UINT32 MediaId,\r
1159 IN EFI_LBA Lba,\r
1160 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
1161 IN UINTN BufferSize,\r
1162 IN VOID *Buffer\r
1163 )\r
1164{\r
1165 return BlockIoReadWrite ((VOID *) This, MediaId, Lba, Token, BufferSize, Buffer, TRUE, TRUE);\r
1166}\r
1167\r
1168\r
1169/**\r
1170 Flush the Block Device.\r
1171\r
1172 @param[in] This Indicates a pointer to the calling context.\r
1173 @param[in, out] Token A pointer to the token associated with the transaction.\r
1174\r
1175 @retval EFI_SUCCESS All outstanding data was written to the device\r
1176 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data\r
1177 @retval EFI_NO_MEDIA There is no media in the device.\r
1178\r
1179**/\r
1180EFI_STATUS\r
1181EFIAPI\r
1182AtaBlockIoFlushBlocksEx (\r
1183 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1184 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
1185 )\r
1186{\r
1187 //\r
1188 // Signla event and return directly.\r
1189 //\r
1190 if (Token != NULL && Token->Event != NULL) {\r
1191 Token->TransactionStatus = EFI_SUCCESS;\r
1192 gBS->SignalEvent (Token->Event);\r
1193 }\r
1194 return EFI_SUCCESS;\r
1195}\r
ad86a50a 1196/**\r
1197 Provides inquiry information for the controller type.\r
1198 \r
1199 This function is used by the IDE bus driver to get inquiry data. Data format\r
1200 of Identify data is defined by the Interface GUID.\r
1201\r
05a44e91 1202 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
1203 @param[in, out] InquiryData Pointer to a buffer for the inquiry data.\r
1204 @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size.\r
ad86a50a 1205\r
1206 @retval EFI_SUCCESS The command was accepted without any errors.\r
1207 @retval EFI_NOT_FOUND Device does not support this data class \r
1208 @retval EFI_DEVICE_ERROR Error reading InquiryData from device \r
1209 @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough \r
1210\r
1211**/\r
1212EFI_STATUS\r
1213EFIAPI\r
1214AtaDiskInfoInquiry (\r
1215 IN EFI_DISK_INFO_PROTOCOL *This,\r
1216 IN OUT VOID *InquiryData,\r
1217 IN OUT UINT32 *InquiryDataSize\r
1218 )\r
1219{\r
1220 return EFI_NOT_FOUND;\r
1221}\r
1222\r
1223\r
1224/**\r
1225 Provides identify information for the controller type.\r
1226\r
1227 This function is used by the IDE bus driver to get identify data. Data format\r
1228 of Identify data is defined by the Interface GUID.\r
1229\r
05a44e91 1230 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL \r
ad86a50a 1231 instance.\r
05a44e91 1232 @param[in, out] IdentifyData Pointer to a buffer for the identify data.\r
1233 @param[in, out] IdentifyDataSize Pointer to the value for the identify data\r
ad86a50a 1234 size.\r
1235\r
1236 @retval EFI_SUCCESS The command was accepted without any errors.\r
1237 @retval EFI_NOT_FOUND Device does not support this data class \r
1238 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device \r
1239 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough \r
1240\r
1241**/\r
1242EFI_STATUS\r
1243EFIAPI\r
1244AtaDiskInfoIdentify (\r
1245 IN EFI_DISK_INFO_PROTOCOL *This,\r
1246 IN OUT VOID *IdentifyData,\r
1247 IN OUT UINT32 *IdentifyDataSize\r
1248 )\r
1249{\r
1250 EFI_STATUS Status;\r
1251 ATA_DEVICE *AtaDevice;\r
1252\r
1253 AtaDevice = ATA_DEVICE_FROM_DISK_INFO (This);\r
1254\r
1255 Status = EFI_BUFFER_TOO_SMALL;\r
1256 if (*IdentifyDataSize >= sizeof (*AtaDevice->IdentifyData)) {\r
1257 Status = EFI_SUCCESS;\r
1258 CopyMem (IdentifyData, AtaDevice->IdentifyData, sizeof (*AtaDevice->IdentifyData));\r
1259 }\r
1260 *IdentifyDataSize = sizeof (*AtaDevice->IdentifyData);\r
1261\r
1262 return Status;\r
1263}\r
1264\r
1265\r
1266/**\r
1267 Provides sense data information for the controller type.\r
1268 \r
1269 This function is used by the IDE bus driver to get sense data. \r
1270 Data format of Sense data is defined by the Interface GUID.\r
1271\r
05a44e91 1272 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
1273 @param[in, out] SenseData Pointer to the SenseData.\r
1274 @param[in, out] SenseDataSize Size of SenseData in bytes.\r
1275 @param[out] SenseDataNumber Pointer to the value for the sense data size.\r
ad86a50a 1276\r
1277 @retval EFI_SUCCESS The command was accepted without any errors.\r
1278 @retval EFI_NOT_FOUND Device does not support this data class.\r
1279 @retval EFI_DEVICE_ERROR Error reading SenseData from device.\r
1280 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.\r
1281\r
1282**/\r
1283EFI_STATUS\r
1284EFIAPI\r
1285AtaDiskInfoSenseData (\r
1286 IN EFI_DISK_INFO_PROTOCOL *This,\r
1287 IN OUT VOID *SenseData,\r
1288 IN OUT UINT32 *SenseDataSize,\r
1289 OUT UINT8 *SenseDataNumber\r
1290 )\r
1291{\r
1292 return EFI_NOT_FOUND;\r
1293}\r
1294\r
1295\r
1296/**\r
1297 This function is used by the IDE bus driver to get controller information.\r
1298\r
1299 @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. \r
1300 @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.\r
1301 @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.\r
1302\r
1303 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.\r
1304 @retval EFI_UNSUPPORTED This is not an IDE device.\r
1305\r
1306**/\r
1307EFI_STATUS\r
1308EFIAPI\r
1309AtaDiskInfoWhichIde (\r
1310 IN EFI_DISK_INFO_PROTOCOL *This,\r
1311 OUT UINT32 *IdeChannel,\r
1312 OUT UINT32 *IdeDevice\r
1313 )\r
1314{\r
1315 ATA_DEVICE *AtaDevice;\r
1316\r
1317 AtaDevice = ATA_DEVICE_FROM_DISK_INFO (This);\r
1318 *IdeChannel = AtaDevice->Port;\r
1319 *IdeDevice = AtaDevice->PortMultiplierPort;\r
1320\r
1321 return EFI_SUCCESS;\r
1322}\r
1323\r
1324\r
1325/**\r
1326 The user Entry Point for module AtaBus. The user code starts with this function.\r
1327\r
1328 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
1329 @param[in] SystemTable A pointer to the EFI System Table.\r
1330\r
1331 @retval EFI_SUCCESS The entry point is executed successfully.\r
1332 @retval other Some error occurs when executing this entry point.\r
1333\r
1334**/\r
1335EFI_STATUS\r
1336EFIAPI\r
1337InitializeAtaBus(\r
1338 IN EFI_HANDLE ImageHandle,\r
1339 IN EFI_SYSTEM_TABLE *SystemTable\r
1340 )\r
1341{\r
1342 EFI_STATUS Status;\r
1343\r
1344 //\r
1345 // Install driver model protocol(s).\r
1346 //\r
1347 Status = EfiLibInstallDriverBindingComponentName2 (\r
1348 ImageHandle,\r
1349 SystemTable,\r
1350 &gAtaBusDriverBinding,\r
1351 ImageHandle,\r
1352 &gAtaBusComponentName,\r
1353 &gAtaBusComponentName2\r
1354 );\r
1355 ASSERT_EFI_ERROR (Status);\r
1356\r
1357 return Status;\r
1358}\r