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