]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c
1) Initialize gBS, gST, gImageHandle in UefiBootServicesTableLib.c to NULL
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbBot / Dxe / bot.c
CommitLineData
878ddf1f 1/*++\r
2\r
4d1fe68e 3Copyright (c) 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
878ddf1f 11\r
12Module Name:\r
13\r
14 BOT.c\r
15\r
16Abstract:\r
17\r
18--*/\r
19\r
20#include "bot.h"\r
21\r
4d1fe68e 22GLOBAL_REMOVE_IF_UNREFERENCED UINT32 gBOTDebugLevel = EFI_D_INFO;\r
23GLOBAL_REMOVE_IF_UNREFERENCED UINT32 gBOTErrorLevel = EFI_D_INFO;\r
878ddf1f 24\r
25EFI_DRIVER_BINDING_PROTOCOL gUsbBotDriverBinding = {\r
26 BotDriverBindingSupported,\r
27 BotDriverBindingStart,\r
28 BotDriverBindingStop,\r
61fb1657 29 0xa,\r
878ddf1f 30 NULL,\r
31 NULL\r
32};\r
33\r
34//\r
35// Bot Protocol\r
36//\r
37STATIC\r
38EFI_STATUS\r
39BotCommandPhase (\r
40 IN USB_BOT_DEVICE *UsbBotDev,\r
41 IN VOID *Command,\r
42 IN UINT8 CommandSize,\r
43 IN UINT32 DataTransferLength,\r
44 IN EFI_USB_DATA_DIRECTION Direction,\r
45 IN UINT16 Timeout\r
46 );\r
47\r
48STATIC\r
49EFI_STATUS\r
50BotDataPhase (\r
51 IN USB_BOT_DEVICE *UsbBotDev,\r
4d1fe68e 52 IN UINTN *DataSize,\r
878ddf1f 53 IN OUT VOID *DataBuffer,\r
54 IN EFI_USB_DATA_DIRECTION Direction,\r
55 IN UINT16 Timeout\r
56 );\r
57\r
58STATIC\r
59EFI_STATUS\r
60BotStatusPhase (\r
4d1fe68e 61 IN USB_BOT_DEVICE *UsbBotDev,\r
62 OUT UINT32 *DataResidue, \r
63 IN UINT16 Timeout\r
878ddf1f 64 );\r
878ddf1f 65//\r
66// USB Atapi protocol prototype\r
67//\r
68STATIC\r
69EFI_STATUS\r
70EFIAPI\r
71BotAtapiCommand (\r
72 IN EFI_USB_ATAPI_PROTOCOL *This,\r
73 IN VOID *Command,\r
74 IN UINT8 CommandSize,\r
75 IN VOID *DataBuffer,\r
76 IN UINT32 BufferLength,\r
77 IN EFI_USB_DATA_DIRECTION Direction,\r
78 IN UINT16 TimeOutInMilliSeconds\r
79 );\r
80\r
81STATIC\r
82EFI_STATUS\r
83EFIAPI\r
84BotMassStorageReset (\r
85 IN EFI_USB_ATAPI_PROTOCOL *This,\r
86 IN BOOLEAN ExtendedVerification\r
87 );\r
88\r
92dda53e 89STATIC\r
878ddf1f 90VOID\r
91BotReportStatusCode (\r
92 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
93 IN EFI_STATUS_CODE_TYPE CodeType,\r
94 IN EFI_STATUS_CODE_VALUE Value\r
95 );\r
96\r
97STATIC EFI_USB_ATAPI_PROTOCOL BotAtapiProtocol = {\r
98 BotAtapiCommand,\r
99 BotMassStorageReset,\r
100 0\r
101};\r
102\r
103EFI_STATUS\r
104EFIAPI\r
105BotDriverBindingSupported (\r
106 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
107 IN EFI_HANDLE ControllerHandle,\r
108 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
109 )\r
110/*++\r
111\r
112 Routine Description:\r
113 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
114 than contains a BlockIo and DiskIo protocol can be supported.\r
115\r
116 Arguments:\r
117 This - Protocol instance pointer.\r
118 ControllerHandle - Handle of device to test\r
119 RemainingDevicePath - Not used\r
120\r
121 Returns:\r
122 EFI_SUCCESS - This driver supports this device\r
123 EFI_ALREADY_STARTED - This driver is already running on this device\r
124 other - This driver does not support this device\r
125\r
126--*/\r
127{\r
128 EFI_STATUS Status;\r
129 EFI_USB_IO_PROTOCOL *UsbIo;\r
130 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;\r
131\r
132 //\r
133 // Check if the Controller supports USB IO protocol\r
134 //\r
135 Status = gBS->OpenProtocol (\r
136 ControllerHandle,\r
137 &gEfiUsbIoProtocolGuid,\r
138 (VOID **) &UsbIo,\r
139 This->DriverBindingHandle,\r
140 ControllerHandle,\r
141 EFI_OPEN_PROTOCOL_BY_DRIVER\r
142 );\r
143 if (EFI_ERROR (Status)) {\r
144 return Status;\r
145 }\r
146 //\r
147 // Get the Default interface descriptor, now we only\r
148 // suppose interface 1\r
149 //\r
150 Status = UsbIo->UsbGetInterfaceDescriptor (\r
151 UsbIo,\r
152 &InterfaceDescriptor\r
153 );\r
154 if (EFI_ERROR (Status)) {\r
155 goto Exit;\r
156 }\r
157 //\r
158 // Check if it is a BOT type Mass Storage Device\r
159 //\r
4d1fe68e 160 if ((InterfaceDescriptor.InterfaceClass != MASS_STORAGE_CLASS) ||\r
878ddf1f 161 (InterfaceDescriptor.InterfaceProtocol != BOT)) {\r
162 Status = EFI_UNSUPPORTED;\r
163 goto Exit;\r
164 }\r
165\r
166Exit:\r
167 gBS->CloseProtocol (\r
168 ControllerHandle,\r
169 &gEfiUsbIoProtocolGuid,\r
170 This->DriverBindingHandle,\r
171 ControllerHandle\r
172 );\r
173 return Status;\r
174}\r
175\r
176EFI_STATUS\r
177EFIAPI\r
178BotDriverBindingStart (\r
179 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
180 IN EFI_HANDLE ControllerHandle,\r
181 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
182 )\r
183/*++\r
184\r
185 Routine Description:\r
186 Start this driver on ControllerHandle by opening a Block IO and Disk IO\r
187 protocol, reading Device Path, and creating a child handle with a\r
188 Disk IO and device path protocol.\r
189\r
190 Arguments:\r
191 This - Protocol instance pointer.\r
192 ControllerHandle - Handle of device to bind driver to\r
193 RemainingDevicePath - Not used\r
194\r
195 Returns:\r
196 EFI_SUCCESS - This driver is added to DeviceHandle\r
197 EFI_ALREADY_STARTED - This driver is already running on DeviceHandle\r
198 EFI_OUT_OF_RESOURCES- Can't allocate the memory resource\r
199 other - This driver does not support this device\r
200\r
201--*/\r
202{\r
203 USB_BOT_DEVICE *UsbBotDev;\r
204 UINT8 Index;\r
205 EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;\r
206 EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor;\r
207 EFI_STATUS Status;\r
208 EFI_USB_IO_PROTOCOL *UsbIo;\r
209\r
210 //\r
211 // Check if the Controller supports USB IO protocol\r
212 //\r
213 UsbBotDev = NULL;\r
214\r
215 Status = gBS->OpenProtocol (\r
216 ControllerHandle,\r
217 &gEfiUsbIoProtocolGuid,\r
218 (VOID **) &UsbIo,\r
219 This->DriverBindingHandle,\r
220 ControllerHandle,\r
221 EFI_OPEN_PROTOCOL_BY_DRIVER\r
222 );\r
223 if (EFI_ERROR (Status)) {\r
224 return Status;\r
225 }\r
226\r
227 InterfaceDescriptor = AllocateZeroPool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR));\r
228 if (InterfaceDescriptor == NULL) {\r
229 gBS->CloseProtocol (\r
230 ControllerHandle,\r
231 &gEfiUsbIoProtocolGuid,\r
232 This->DriverBindingHandle,\r
233 ControllerHandle\r
234 );\r
235 return EFI_OUT_OF_RESOURCES;\r
236 }\r
237 //\r
238 // Get the controller interface descriptor,\r
239 //\r
240 Status = UsbIo->UsbGetInterfaceDescriptor (\r
241 UsbIo,\r
242 InterfaceDescriptor\r
243 );\r
244 if (EFI_ERROR (Status)) {\r
245 gBS->FreePool (InterfaceDescriptor);\r
246 goto ErrorExit;\r
247 }\r
248\r
249 BotAtapiProtocol.CommandProtocol = InterfaceDescriptor->InterfaceSubClass;\r
250\r
251 UsbBotDev = AllocateZeroPool (sizeof (USB_BOT_DEVICE));\r
252 if (UsbBotDev == NULL) {\r
253 Status = EFI_OUT_OF_RESOURCES;\r
254 gBS->FreePool (InterfaceDescriptor);\r
255 goto ErrorExit;\r
256 }\r
257\r
258 UsbBotDev->Signature = USB_BOT_DEVICE_SIGNATURE;\r
259 UsbBotDev->UsbIo = UsbIo;\r
260 UsbBotDev->InterfaceDescriptor = InterfaceDescriptor;\r
261 CopyMem (&UsbBotDev->UsbAtapiProtocol, &BotAtapiProtocol, sizeof (BotAtapiProtocol));\r
262\r
263 //\r
264 // Get the Device Path Protocol on Controller's handle\r
265 //\r
266 Status = gBS->OpenProtocol (\r
267 ControllerHandle,\r
268 &gEfiDevicePathProtocolGuid,\r
269 (VOID **) &UsbBotDev->DevicePath,\r
270 This->DriverBindingHandle,\r
271 ControllerHandle,\r
272 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
273 );\r
274\r
275 if (EFI_ERROR (Status)) {\r
276 goto ErrorExit;\r
277 }\r
278\r
279 for (Index = 0; Index < InterfaceDescriptor->NumEndpoints; Index++) {\r
280 EndpointDescriptor = AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR));\r
281 if (EndpointDescriptor == NULL) {\r
282 Status = EFI_OUT_OF_RESOURCES;\r
283 goto ErrorExit;\r
284 }\r
285\r
286 UsbIo->UsbGetEndpointDescriptor (\r
287 UsbIo,\r
288 Index,\r
289 EndpointDescriptor\r
290 );\r
291\r
292 //\r
293 // We parse bulk endpoint\r
294 //\r
295 if ((EndpointDescriptor->Attributes & 0x03) == 0x02) {\r
296 if ((EndpointDescriptor->EndpointAddress & 0x80) != 0) {\r
297 UsbBotDev->BulkInEndpointDescriptor = EndpointDescriptor;\r
298 } else {\r
299 UsbBotDev->BulkOutEndpointDescriptor = EndpointDescriptor;\r
300 }\r
301\r
302 continue;\r
303 }\r
304\r
305 gBS->FreePool (EndpointDescriptor);\r
306 }\r
307 //\r
308 // Double check we have these endpoint descriptors\r
309 //\r
310 if (!(UsbBotDev->BulkInEndpointDescriptor &&\r
311 UsbBotDev->BulkOutEndpointDescriptor)) {\r
312 Status = EFI_DEVICE_ERROR;\r
313 goto ErrorExit;\r
314 }\r
315 //\r
316 // After installing Usb-Atapi protocol onto this handle\r
317 // it will be called by upper layer drivers such as Fat\r
318 //\r
319 BotReportStatusCode (\r
320 UsbBotDev->DevicePath,\r
321 EFI_PROGRESS_CODE,\r
322 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE)\r
323 );\r
324\r
325 //\r
326 // Install Usb-Atapi Protocol onto the handle\r
327 //\r
328 Status = gBS->InstallProtocolInterface (\r
329 &ControllerHandle,\r
330 &gEfiUsbAtapiProtocolGuid,\r
331 EFI_NATIVE_INTERFACE,\r
332 &UsbBotDev->UsbAtapiProtocol\r
333 );\r
334\r
335 if (EFI_ERROR (Status)) {\r
336 goto ErrorExit;\r
337 }\r
338\r
339 UsbBotDev->ControllerNameTable = NULL;\r
340 AddUnicodeString (\r
341 "eng",\r
342 gUsbBotComponentName.SupportedLanguages,\r
343 &UsbBotDev->ControllerNameTable,\r
344 (CHAR16 *) L"Usb Bot Mass Storage"\r
345 );\r
346\r
347 return EFI_SUCCESS;\r
348\r
349ErrorExit:\r
350 gBS->CloseProtocol (\r
351 ControllerHandle,\r
352 &gEfiUsbIoProtocolGuid,\r
353 This->DriverBindingHandle,\r
354 ControllerHandle\r
355 );\r
356\r
357 if (UsbBotDev != NULL) {\r
358 if (UsbBotDev->InterfaceDescriptor != NULL) {\r
359 gBS->FreePool (UsbBotDev->InterfaceDescriptor);\r
360 }\r
361\r
362 if (UsbBotDev->BulkInEndpointDescriptor != NULL) {\r
363 gBS->FreePool (UsbBotDev->BulkInEndpointDescriptor);\r
364 }\r
365\r
366 if (UsbBotDev->BulkOutEndpointDescriptor != NULL) {\r
367 gBS->FreePool (UsbBotDev->BulkOutEndpointDescriptor);\r
368 }\r
369\r
370 gBS->FreePool (UsbBotDev);\r
371 }\r
372\r
373 return Status;\r
374}\r
375\r
376EFI_STATUS\r
377EFIAPI\r
378BotDriverBindingStop (\r
379 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
380 IN EFI_HANDLE ControllerHandle,\r
381 IN UINTN NumberOfChildren,\r
382 IN EFI_HANDLE *ChildHandleBuffer\r
383 )\r
384/*++\r
385\r
386 Routine Description:\r
387 Stop this driver on ControllerHandle. Support stoping any child handles\r
388 created by this driver.\r
389\r
390 Arguments:\r
391 This - Protocol instance pointer.\r
392 ControllerHandle - Handle of device to stop driver on\r
393 NumberOfChildren - Number of Children in the ChildHandleBuffer\r
394 ChildHandleBuffer - List of handles for the children we need to stop.\r
395\r
396 Returns:\r
397 EFI_SUCCESS - This driver is removed DeviceHandle\r
4d1fe68e 398 EFI_UNSUPPORTED - Can't open the gEfiUsbAtapiProtocolGuid protocl\r
878ddf1f 399 other - This driver was not removed from this device\r
400\r
401--*/\r
402{\r
403 EFI_STATUS Status;\r
404 EFI_USB_ATAPI_PROTOCOL *BotAtapiProtocol;\r
405 USB_BOT_DEVICE *UsbBotDev;\r
406\r
878ddf1f 407 //\r
408 // Get our context back.\r
409 //\r
410 Status = gBS->OpenProtocol (\r
411 ControllerHandle,\r
412 &gEfiUsbAtapiProtocolGuid,\r
413 (VOID **) &BotAtapiProtocol,\r
414 This->DriverBindingHandle,\r
415 ControllerHandle,\r
416 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
417 );\r
418 if (EFI_ERROR (Status)) {\r
419 return EFI_UNSUPPORTED;\r
420 }\r
421\r
422 UsbBotDev = USB_BOT_DEVICE_FROM_THIS (BotAtapiProtocol);\r
423\r
424 //\r
425 // After installing Usb-Atapi protocol onto this handle\r
426 // it will be called by upper layer drivers such as Fat\r
427 //\r
878ddf1f 428\r
429 BotReportStatusCode (\r
430 UsbBotDev->DevicePath,\r
431 EFI_PROGRESS_CODE,\r
432 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE)\r
433 );\r
434\r
435 //\r
436 // Uninstall protocol\r
437 //\r
438 Status = gBS->UninstallProtocolInterface (\r
439 ControllerHandle,\r
440 &gEfiUsbAtapiProtocolGuid,\r
441 &UsbBotDev->UsbAtapiProtocol\r
442 );\r
443 if (EFI_ERROR (Status)) {\r
444 return Status;\r
445 }\r
446\r
447 Status = gBS->CloseProtocol (\r
448 ControllerHandle,\r
449 &gEfiUsbIoProtocolGuid,\r
450 This->DriverBindingHandle,\r
451 ControllerHandle\r
452 );\r
453 //\r
454 // Free all allocated resources\r
455 //\r
456 if (UsbBotDev->InterfaceDescriptor != NULL) {\r
457 gBS->FreePool (UsbBotDev->InterfaceDescriptor);\r
458 }\r
459\r
460 if (UsbBotDev->BulkInEndpointDescriptor != NULL) {\r
461 gBS->FreePool (UsbBotDev->BulkInEndpointDescriptor);\r
462 }\r
463\r
464 if (UsbBotDev->BulkOutEndpointDescriptor != NULL) {\r
465 gBS->FreePool (UsbBotDev->BulkOutEndpointDescriptor);\r
466 }\r
467\r
468 if (UsbBotDev->ControllerNameTable) {\r
469 FreeUnicodeStringTable (UsbBotDev->ControllerNameTable);\r
470 }\r
471\r
472 gBS->FreePool (UsbBotDev);\r
473\r
474 return Status;\r
475}\r
476\r
4d1fe68e 477\r
478\r
479STATIC\r
480EFI_STATUS\r
481ClearBulkInPipe (\r
482 IN USB_BOT_DEVICE *UsbBotDev\r
483 )\r
484{\r
485 UINT32 Result;\r
486\r
487 return UsbClearEndpointHalt (\r
488 UsbBotDev->UsbIo,\r
489 UsbBotDev->BulkInEndpointDescriptor->EndpointAddress,\r
490 &Result\r
491 );\r
492}\r
493\r
494\r
495STATIC\r
496EFI_STATUS\r
497ClearBulkOutPipe (\r
498 IN USB_BOT_DEVICE *UsbBotDev\r
499 )\r
500{\r
501 UINT32 Result;\r
502 return UsbClearEndpointHalt (\r
503 UsbBotDev->UsbIo,\r
504 UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress,\r
505 &Result\r
506 );\r
507}\r
508\r
878ddf1f 509STATIC\r
510EFI_STATUS\r
511BotRecoveryReset (\r
512 IN USB_BOT_DEVICE *UsbBotDev\r
513 )\r
514/*++\r
515\r
516Routine Description:\r
517\r
518 Bot reset routine\r
519\r
520Arguments:\r
521\r
522 UsbBotDev - USB_BOT_DEVICE pointer\r
523\r
524Returns:\r
525 EFI_SUCCESS - Success the operation\r
4d1fe68e 526\r
878ddf1f 527--*/\r
528{\r
529 EFI_STATUS Status;\r
878ddf1f 530 EFI_USB_DEVICE_REQUEST Request;\r
4d1fe68e 531 UINT32 Result;\r
878ddf1f 532 BotReportStatusCode (\r
533 UsbBotDev->DevicePath,\r
534 EFI_PROGRESS_CODE,\r
535 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET)\r
536 );\r
537\r
538 ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST));\r
539\r
540 //\r
541 // See BOT specification\r
542 //\r
543 Request.RequestType = 0x21;\r
544 Request.Request = 0xFF;\r
545\r
4d1fe68e 546 Status = UsbBotDev->UsbIo->UsbControlTransfer (\r
547 UsbBotDev->UsbIo,\r
548 &Request,\r
549 EfiUsbNoData,\r
550 TIMEOUT_VALUE,\r
551 NULL,\r
552 0,\r
553 &Result\r
554 );\r
878ddf1f 555\r
556 gBS->Stall (100 * 1000);\r
557\r
4d1fe68e 558 ClearBulkInPipe (UsbBotDev);\r
559 ClearBulkOutPipe (UsbBotDev);\r
878ddf1f 560\r
561 return Status;\r
562}\r
4d1fe68e 563\r
878ddf1f 564//\r
565// Bot Protocol Implementation\r
566//\r
567STATIC\r
568EFI_STATUS\r
569BotCommandPhase (\r
570 IN USB_BOT_DEVICE *UsbBotDev,\r
571 IN VOID *Command,\r
572 IN UINT8 CommandSize,\r
573 IN UINT32 DataTransferLength,\r
574 IN EFI_USB_DATA_DIRECTION Direction,\r
575 IN UINT16 Timeout\r
576 )\r
577/*++\r
578\r
579 Routine Description:\r
580 Send ATAPI command through BOT interface.\r
581\r
582 Parameters:\r
583 UsbBotDev - USB_BOT_DEVICE\r
584 Command - command packet\r
585 CommandSize - Command size\r
586 DataTransferLength - Data Transfer Length\r
587 Direction - Data IN/OUT/NODATA\r
588 Timeout - Time out value in milliseconds\r
589 Return Values:\r
590 EFI_SUCCESS\r
591 Others\r
592\r
593--*/\r
594{\r
595 CBW cbw;\r
596 EFI_STATUS Status;\r
597 UINT32 Result;\r
598 EFI_USB_IO_PROTOCOL *UsbIo;\r
599 UINTN DataSize;\r
600\r
601 UsbIo = UsbBotDev->UsbIo;\r
602\r
603 ZeroMem (&cbw, sizeof (CBW));\r
604\r
605 //\r
606 // Fill the command block, detailed see BOT spec\r
607 //\r
608 cbw.dCBWSignature = CBWSIG;\r
609 cbw.dCBWTag = 0x01;\r
610 cbw.dCBWDataTransferLength = DataTransferLength;\r
df557cca 611 cbw.bmCBWFlags = (UINT8) ((Direction == EfiUsbDataIn) ? 0x80 : 0);\r
878ddf1f 612 cbw.bCBWCBLength = CommandSize;\r
613\r
614 CopyMem (cbw.CBWCB, Command, CommandSize);\r
615\r
616 DataSize = sizeof (CBW);\r
617\r
618 Status = UsbIo->UsbBulkTransfer (\r
619 UsbIo,\r
4d1fe68e 620 UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress,\r
878ddf1f 621 &cbw,\r
622 &DataSize,\r
623 Timeout,\r
624 &Result\r
625 );\r
4d1fe68e 626 return Status;\r
878ddf1f 627}\r
628\r
629STATIC\r
630EFI_STATUS\r
631BotDataPhase (\r
632 IN USB_BOT_DEVICE *UsbBotDev,\r
4d1fe68e 633 IN UINTN *DataSize,\r
878ddf1f 634 IN OUT VOID *DataBuffer,\r
635 IN EFI_USB_DATA_DIRECTION Direction,\r
636 IN UINT16 Timeout\r
637 )\r
638/*++\r
639\r
640 Routine Description:\r
641 Get/Send Data through BOT interface\r
642\r
643 Parameters:\r
644 UsbBotDev - USB_BOT_DEVICE pointer\r
645 DataSize - Data size\r
646 DataBuffer - Data buffer pointer\r
647 Direction - IN/OUT/NODATA\r
648 Timeout - Time out value in milliseconds\r
649 Return Value:\r
650 EFI_SUCCESS\r
651 Others\r
652\r
653--*/\r
654{\r
655 EFI_STATUS Status;\r
656 UINT32 Result;\r
657 EFI_USB_IO_PROTOCOL *UsbIo;\r
658 UINT8 EndpointAddr;\r
878ddf1f 659 UINT8 *BufferPtr;\r
878ddf1f 660\r
661 UsbIo = UsbBotDev->UsbIo;\r
878ddf1f 662 BufferPtr = (UINT8 *) DataBuffer;\r
878ddf1f 663\r
664 //\r
665 // retrieve the the max packet length of the given endpoint\r
666 //\r
667 if (Direction == EfiUsbDataIn) {\r
4d1fe68e 668 EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;\r
878ddf1f 669 } else {\r
4d1fe68e 670 EndpointAddr = UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress;\r
878ddf1f 671 }\r
672\r
878ddf1f 673 Status = UsbIo->UsbBulkTransfer (\r
674 UsbIo,\r
675 EndpointAddr,\r
676 BufferPtr,\r
4d1fe68e 677 DataSize,\r
678 (UINT16)(Timeout),\r
878ddf1f 679 &Result\r
680 );\r
681\r
878ddf1f 682 if (EFI_ERROR (Status)) {\r
4d1fe68e 683 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
684 if (Direction == EfiUsbDataIn) {\r
685 DEBUG((gBOTErrorLevel, "BOT: Data IN Stall, ClearBulkInPipe\n"));\r
686 ClearBulkInPipe (UsbBotDev);\r
687 } else {\r
688 DEBUG((gBOTErrorLevel, "BOT: Data OUT Stall, ClearBulkInPipe\n"));\r
689 ClearBulkOutPipe (UsbBotDev);\r
690 }\r
878ddf1f 691 }\r
4d1fe68e 692 // BotRecoveryReset (UsbBotDev);\r
693 }\r
878ddf1f 694\r
878ddf1f 695\r
696 return Status;\r
878ddf1f 697}\r
698\r
699STATIC\r
700EFI_STATUS\r
701BotStatusPhase (\r
4d1fe68e 702 IN USB_BOT_DEVICE *UsbBotDev,\r
703 OUT UINT32 *DataResidue,\r
704 IN UINT16 Timeout\r
878ddf1f 705 )\r
706/*++\r
707\r
708 Routine Description:\r
709 Get transfer status through BOT interface\r
710\r
711 Parameters:\r
712 UsbBotDev - USB_BOT_DEVICE pointer\r
878ddf1f 713 Timeout - Time out value in milliseconds\r
714 Return Value:\r
715 EFI_SUCCESS\r
716 Others\r
717\r
718--*/\r
719{\r
720 CSW csw;\r
721 EFI_STATUS Status;\r
878ddf1f 722 EFI_USB_IO_PROTOCOL *UsbIo;\r
723 UINT8 EndpointAddr;\r
724 UINTN DataSize;\r
4d1fe68e 725 UINT32 Result;\r
726 UINT8 Index;\r
878ddf1f 727\r
728 UsbIo = UsbBotDev->UsbIo;\r
4d1fe68e 729 EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;\r
878ddf1f 730\r
878ddf1f 731\r
4d1fe68e 732 for (Index = 0; Index < 3; Index ++) {\r
878ddf1f 733 ZeroMem (&csw, sizeof (CSW));\r
4d1fe68e 734 DataSize = sizeof (CSW);\r
735 Result = 0;\r
878ddf1f 736\r
878ddf1f 737 Status = UsbIo->UsbBulkTransfer (\r
738 UsbIo,\r
739 EndpointAddr,\r
740 &csw,\r
741 &DataSize,\r
742 Timeout,\r
743 &Result\r
744 );\r
745 if (EFI_ERROR (Status)) {\r
746 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
4d1fe68e 747 DEBUG((gBOTDebugLevel, "BOT: CSW Stall, ClearBulkInPipe\n"));\r
748 ClearBulkInPipe (UsbBotDev);\r
749 continue;\r
750 }\r
751 }\r
752\r
753 if (csw.dCSWSignature == CSWSIG) {\r
754 if (csw.bCSWStatus == 0 || csw.bCSWStatus == 0x01) {\r
755 if (DataResidue != NULL) {\r
756 *DataResidue = csw.dCSWDataResidue;\r
757 }\r
758 if (csw.bCSWStatus == 0x01) {\r
759 return EFI_DEVICE_ERROR;\r
760 }\r
761 break;\r
762 } else if (csw.bCSWStatus == 0x02) {\r
763 DEBUG((gBOTErrorLevel, "BOT: Bot Phase error\n"));\r
764 BotRecoveryReset (UsbBotDev);\r
878ddf1f 765 }\r
766\r
878ddf1f 767 }\r
768 }\r
769\r
4d1fe68e 770 if (Index == 3) {\r
878ddf1f 771 return EFI_DEVICE_ERROR;\r
772 }\r
773\r
774 return EFI_SUCCESS;\r
775}\r
4d1fe68e 776\r
878ddf1f 777//\r
778// Usb Atapi Protocol implementation\r
779//\r
780EFI_STATUS\r
781EFIAPI\r
782BotAtapiCommand (\r
783 IN EFI_USB_ATAPI_PROTOCOL *This,\r
784 IN VOID *Command,\r
785 IN UINT8 CommandSize,\r
786 IN VOID *DataBuffer,\r
787 IN UINT32 BufferLength,\r
788 IN EFI_USB_DATA_DIRECTION Direction,\r
789 IN UINT16 TimeOutInMilliSeconds\r
790 )\r
791/*++\r
792\r
793 Routine Description:\r
794 Send ATAPI command using BOT protocol.\r
795\r
796 Arguments:\r
797 This - Protocol instance pointer.\r
798 Command - Command buffer\r
799 CommandSize - Size of Command Buffer\r
800 DataBuffer - Data buffer\r
801 BufferLength - Length of Data buffer\r
802 Direction - Data direction of this command\r
803 TimeoutInMilliSeconds - Timeout value in ms\r
804\r
805 Returns:\r
806 EFI_SUCCESS - Command succeeded.\r
807 EFI_DEVICE_ERROR - Command failed.\r
808\r
809--*/\r
810{\r
811 EFI_STATUS Status;\r
812 EFI_STATUS BotDataStatus;\r
878ddf1f 813 USB_BOT_DEVICE *UsbBotDev;\r
4d1fe68e 814 UINTN BufferSize;\r
815 UINT8 Index;\r
816 UINT32 DataResidue;\r
878ddf1f 817\r
818 //\r
819 // Get the context\r
820 //\r
4d1fe68e 821 UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);\r
822 BotDataStatus = EFI_SUCCESS;\r
823 BufferSize = 0;\r
878ddf1f 824\r
4d1fe68e 825 for (Index = 0; Index < 3; Index ++) {\r
826 //\r
827 // First send ATAPI command through Bot\r
828 //\r
829 Status = BotCommandPhase (\r
830 UsbBotDev,\r
831 Command,\r
832 CommandSize,\r
833 BufferLength,\r
834 Direction,\r
835 10 * 1000\r
836 );\r
878ddf1f 837\r
4d1fe68e 838 if (EFI_ERROR (Status)) {\r
839 DEBUG((gBOTErrorLevel, "BotCommandPhase Fail\n"));\r
840 return Status;\r
841 }\r
842 //\r
843 // Send/Get Data if there is a Data Stage\r
844 //\r
845 switch (Direction) {\r
878ddf1f 846\r
4d1fe68e 847 case EfiUsbDataIn:\r
848 case EfiUsbDataOut:\r
849 BufferSize = BufferLength;\r
878ddf1f 850\r
4d1fe68e 851 BotDataStatus = BotDataPhase (\r
852 UsbBotDev,\r
853 &BufferSize,\r
854 DataBuffer,\r
855 Direction,\r
856 (UINT16) (TimeOutInMilliSeconds)\r
857 );\r
878ddf1f 858\r
878ddf1f 859\r
4d1fe68e 860 if (EFI_ERROR (BotDataStatus)) {\r
861 DEBUG((gBOTErrorLevel, "BotDataPhase Fail\n"));\r
862 }\r
863 break;\r
878ddf1f 864\r
4d1fe68e 865 case EfiUsbNoData:\r
866 break;\r
867 }\r
868\r
869 DataResidue = 0;\r
878ddf1f 870 //\r
4d1fe68e 871 // Status Phase\r
878ddf1f 872 //\r
4d1fe68e 873 Status = BotStatusPhase (\r
874 UsbBotDev,\r
875 &DataResidue,\r
876 10 * 1000\r
877 );\r
878ddf1f 878\r
4d1fe68e 879 if (EFI_ERROR (Status)) {\r
880 DEBUG((gBOTErrorLevel, "BotStatusPhase Fail\n"));\r
881 return Status;\r
882 }\r
878ddf1f 883\r
4d1fe68e 884 if (!EFI_ERROR (BotDataStatus)) {\r
885 break;\r
886 }\r
887\r
888 }\r
878ddf1f 889 return BotDataStatus;\r
890}\r
891\r
892EFI_STATUS\r
893EFIAPI\r
894BotMassStorageReset (\r
895 IN EFI_USB_ATAPI_PROTOCOL *This,\r
896 IN BOOLEAN ExtendedVerification\r
897 )\r
898/*++\r
899\r
900 Routine Description:\r
901 Reset Bot Devices\r
902\r
903 Arguments:\r
904 This - Protocol instance pointer.\r
905 ExtendedVerification - TRUE if we need to do strictly reset.\r
906\r
907 Returns:\r
908 EFI_SUCCESS - Command succeeded.\r
909 EFI_DEVICE_ERROR - Command failed.\r
910\r
911--*/\r
912{\r
913 EFI_STATUS Status;\r
914 USB_BOT_DEVICE *UsbBotDev;\r
915 EFI_USB_IO_PROTOCOL *UsbIo;\r
916\r
917 UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);\r
918 UsbIo = UsbBotDev->UsbIo;\r
919\r
920 if (ExtendedVerification) {\r
921 //\r
922 // If we need to do strictly reset, reset its parent hub port\r
923 //\r
924 Status = UsbIo->UsbPortReset (UsbIo);\r
925 if (EFI_ERROR (Status)) {\r
926 return Status;\r
927 }\r
928 }\r
929\r
930 Status = BotRecoveryReset (UsbBotDev);\r
931\r
932 return Status;\r
933}\r
934\r
92dda53e 935STATIC\r
878ddf1f 936VOID\r
937BotReportStatusCode (\r
938 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
939 IN EFI_STATUS_CODE_TYPE CodeType,\r
940 IN EFI_STATUS_CODE_VALUE Value\r
941 )\r
942/*++\r
943\r
944 Routine Description:\r
945 Report Status Code in Usb Bot Driver\r
946\r
947 Arguments:\r
948 DevicePath - Use this to get Device Path\r
949 CodeType - Status Code Type\r
950 CodeValue - Status Code Value\r
951\r
952 Returns:\r
953 None\r
954\r
955--*/\r
956{\r
957 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
958 CodeType,\r
959 Value,\r
960 DevicePath\r
961 );\r
962}\r