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