]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c
Make EdkModulePkg pass Intel IPF compiler with /W4 /WX switches, solving warning...
[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
4d1fe68e 611 switch (Direction) {\r
612 case EfiUsbDataOut:\r
613 case EfiUsbNoData:\r
614 cbw.bmCBWFlags = 0;\r
615 break;\r
616 case EfiUsbDataIn:\r
617 cbw.bmCBWFlags = 0x80;\r
618 break;\r
619 default:\r
620 break;\r
621 }\r
878ddf1f 622 cbw.bCBWCBLength = CommandSize;\r
623\r
624 CopyMem (cbw.CBWCB, Command, CommandSize);\r
625\r
626 DataSize = sizeof (CBW);\r
627\r
628 Status = UsbIo->UsbBulkTransfer (\r
629 UsbIo,\r
4d1fe68e 630 UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress,\r
878ddf1f 631 &cbw,\r
632 &DataSize,\r
633 Timeout,\r
634 &Result\r
635 );\r
4d1fe68e 636 return Status;\r
878ddf1f 637}\r
638\r
639STATIC\r
640EFI_STATUS\r
641BotDataPhase (\r
642 IN USB_BOT_DEVICE *UsbBotDev,\r
4d1fe68e 643 IN UINTN *DataSize,\r
878ddf1f 644 IN OUT VOID *DataBuffer,\r
645 IN EFI_USB_DATA_DIRECTION Direction,\r
646 IN UINT16 Timeout\r
647 )\r
648/*++\r
649\r
650 Routine Description:\r
651 Get/Send Data through BOT interface\r
652\r
653 Parameters:\r
654 UsbBotDev - USB_BOT_DEVICE pointer\r
655 DataSize - Data size\r
656 DataBuffer - Data buffer pointer\r
657 Direction - IN/OUT/NODATA\r
658 Timeout - Time out value in milliseconds\r
659 Return Value:\r
660 EFI_SUCCESS\r
661 Others\r
662\r
663--*/\r
664{\r
665 EFI_STATUS Status;\r
666 UINT32 Result;\r
667 EFI_USB_IO_PROTOCOL *UsbIo;\r
668 UINT8 EndpointAddr;\r
878ddf1f 669 UINT8 *BufferPtr;\r
878ddf1f 670\r
671 UsbIo = UsbBotDev->UsbIo;\r
878ddf1f 672 BufferPtr = (UINT8 *) DataBuffer;\r
878ddf1f 673\r
674 //\r
675 // retrieve the the max packet length of the given endpoint\r
676 //\r
677 if (Direction == EfiUsbDataIn) {\r
4d1fe68e 678 EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;\r
878ddf1f 679 } else {\r
4d1fe68e 680 EndpointAddr = UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress;\r
878ddf1f 681 }\r
682\r
878ddf1f 683 Status = UsbIo->UsbBulkTransfer (\r
684 UsbIo,\r
685 EndpointAddr,\r
686 BufferPtr,\r
4d1fe68e 687 DataSize,\r
688 (UINT16)(Timeout),\r
878ddf1f 689 &Result\r
690 );\r
691\r
878ddf1f 692 if (EFI_ERROR (Status)) {\r
4d1fe68e 693 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
694 if (Direction == EfiUsbDataIn) {\r
695 DEBUG((gBOTErrorLevel, "BOT: Data IN Stall, ClearBulkInPipe\n"));\r
696 ClearBulkInPipe (UsbBotDev);\r
697 } else {\r
698 DEBUG((gBOTErrorLevel, "BOT: Data OUT Stall, ClearBulkInPipe\n"));\r
699 ClearBulkOutPipe (UsbBotDev);\r
700 }\r
878ddf1f 701 }\r
4d1fe68e 702 // BotRecoveryReset (UsbBotDev);\r
703 }\r
878ddf1f 704\r
878ddf1f 705\r
706 return Status;\r
878ddf1f 707}\r
708\r
709STATIC\r
710EFI_STATUS\r
711BotStatusPhase (\r
4d1fe68e 712 IN USB_BOT_DEVICE *UsbBotDev,\r
713 OUT UINT32 *DataResidue,\r
714 IN UINT16 Timeout\r
878ddf1f 715 )\r
716/*++\r
717\r
718 Routine Description:\r
719 Get transfer status through BOT interface\r
720\r
721 Parameters:\r
722 UsbBotDev - USB_BOT_DEVICE pointer\r
878ddf1f 723 Timeout - Time out value in milliseconds\r
724 Return Value:\r
725 EFI_SUCCESS\r
726 Others\r
727\r
728--*/\r
729{\r
730 CSW csw;\r
731 EFI_STATUS Status;\r
878ddf1f 732 EFI_USB_IO_PROTOCOL *UsbIo;\r
733 UINT8 EndpointAddr;\r
734 UINTN DataSize;\r
4d1fe68e 735 UINT32 Result;\r
736 UINT8 Index;\r
878ddf1f 737\r
738 UsbIo = UsbBotDev->UsbIo;\r
4d1fe68e 739 EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;\r
878ddf1f 740\r
878ddf1f 741\r
4d1fe68e 742 for (Index = 0; Index < 3; Index ++) {\r
878ddf1f 743 ZeroMem (&csw, sizeof (CSW));\r
4d1fe68e 744 DataSize = sizeof (CSW);\r
745 Result = 0;\r
878ddf1f 746\r
878ddf1f 747 Status = UsbIo->UsbBulkTransfer (\r
748 UsbIo,\r
749 EndpointAddr,\r
750 &csw,\r
751 &DataSize,\r
752 Timeout,\r
753 &Result\r
754 );\r
755 if (EFI_ERROR (Status)) {\r
756 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
4d1fe68e 757 DEBUG((gBOTDebugLevel, "BOT: CSW Stall, ClearBulkInPipe\n"));\r
758 ClearBulkInPipe (UsbBotDev);\r
759 continue;\r
760 }\r
761 }\r
762\r
763 if (csw.dCSWSignature == CSWSIG) {\r
764 if (csw.bCSWStatus == 0 || csw.bCSWStatus == 0x01) {\r
765 if (DataResidue != NULL) {\r
766 *DataResidue = csw.dCSWDataResidue;\r
767 }\r
768 if (csw.bCSWStatus == 0x01) {\r
769 return EFI_DEVICE_ERROR;\r
770 }\r
771 break;\r
772 } else if (csw.bCSWStatus == 0x02) {\r
773 DEBUG((gBOTErrorLevel, "BOT: Bot Phase error\n"));\r
774 BotRecoveryReset (UsbBotDev);\r
878ddf1f 775 }\r
776\r
878ddf1f 777 }\r
778 }\r
779\r
4d1fe68e 780 if (Index == 3) {\r
878ddf1f 781 return EFI_DEVICE_ERROR;\r
782 }\r
783\r
784 return EFI_SUCCESS;\r
785}\r
4d1fe68e 786\r
878ddf1f 787//\r
788// Usb Atapi Protocol implementation\r
789//\r
790EFI_STATUS\r
791EFIAPI\r
792BotAtapiCommand (\r
793 IN EFI_USB_ATAPI_PROTOCOL *This,\r
794 IN VOID *Command,\r
795 IN UINT8 CommandSize,\r
796 IN VOID *DataBuffer,\r
797 IN UINT32 BufferLength,\r
798 IN EFI_USB_DATA_DIRECTION Direction,\r
799 IN UINT16 TimeOutInMilliSeconds\r
800 )\r
801/*++\r
802\r
803 Routine Description:\r
804 Send ATAPI command using BOT protocol.\r
805\r
806 Arguments:\r
807 This - Protocol instance pointer.\r
808 Command - Command buffer\r
809 CommandSize - Size of Command Buffer\r
810 DataBuffer - Data buffer\r
811 BufferLength - Length of Data buffer\r
812 Direction - Data direction of this command\r
813 TimeoutInMilliSeconds - Timeout value in ms\r
814\r
815 Returns:\r
816 EFI_SUCCESS - Command succeeded.\r
817 EFI_DEVICE_ERROR - Command failed.\r
818\r
819--*/\r
820{\r
821 EFI_STATUS Status;\r
822 EFI_STATUS BotDataStatus;\r
878ddf1f 823 USB_BOT_DEVICE *UsbBotDev;\r
4d1fe68e 824 UINTN BufferSize;\r
825 UINT8 Index;\r
826 UINT32 DataResidue;\r
878ddf1f 827\r
828 //\r
829 // Get the context\r
830 //\r
4d1fe68e 831 UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);\r
832 BotDataStatus = EFI_SUCCESS;\r
833 BufferSize = 0;\r
878ddf1f 834\r
4d1fe68e 835 for (Index = 0; Index < 3; Index ++) {\r
836 //\r
837 // First send ATAPI command through Bot\r
838 //\r
839 Status = BotCommandPhase (\r
840 UsbBotDev,\r
841 Command,\r
842 CommandSize,\r
843 BufferLength,\r
844 Direction,\r
845 10 * 1000\r
846 );\r
878ddf1f 847\r
4d1fe68e 848 if (EFI_ERROR (Status)) {\r
849 DEBUG((gBOTErrorLevel, "BotCommandPhase Fail\n"));\r
850 return Status;\r
851 }\r
852 //\r
853 // Send/Get Data if there is a Data Stage\r
854 //\r
855 switch (Direction) {\r
878ddf1f 856\r
4d1fe68e 857 case EfiUsbDataIn:\r
858 case EfiUsbDataOut:\r
859 BufferSize = BufferLength;\r
878ddf1f 860\r
4d1fe68e 861 BotDataStatus = BotDataPhase (\r
862 UsbBotDev,\r
863 &BufferSize,\r
864 DataBuffer,\r
865 Direction,\r
866 (UINT16) (TimeOutInMilliSeconds)\r
867 );\r
878ddf1f 868\r
878ddf1f 869\r
4d1fe68e 870 if (EFI_ERROR (BotDataStatus)) {\r
871 DEBUG((gBOTErrorLevel, "BotDataPhase Fail\n"));\r
872 }\r
873 break;\r
878ddf1f 874\r
4d1fe68e 875 case EfiUsbNoData:\r
876 break;\r
877 }\r
878\r
879 DataResidue = 0;\r
878ddf1f 880 //\r
4d1fe68e 881 // Status Phase\r
878ddf1f 882 //\r
4d1fe68e 883 Status = BotStatusPhase (\r
884 UsbBotDev,\r
885 &DataResidue,\r
886 10 * 1000\r
887 );\r
878ddf1f 888\r
4d1fe68e 889 if (EFI_ERROR (Status)) {\r
890 DEBUG((gBOTErrorLevel, "BotStatusPhase Fail\n"));\r
891 return Status;\r
892 }\r
878ddf1f 893\r
4d1fe68e 894 if (!EFI_ERROR (BotDataStatus)) {\r
895 break;\r
896 }\r
897\r
898 }\r
878ddf1f 899 return BotDataStatus;\r
900}\r
901\r
902EFI_STATUS\r
903EFIAPI\r
904BotMassStorageReset (\r
905 IN EFI_USB_ATAPI_PROTOCOL *This,\r
906 IN BOOLEAN ExtendedVerification\r
907 )\r
908/*++\r
909\r
910 Routine Description:\r
911 Reset Bot Devices\r
912\r
913 Arguments:\r
914 This - Protocol instance pointer.\r
915 ExtendedVerification - TRUE if we need to do strictly reset.\r
916\r
917 Returns:\r
918 EFI_SUCCESS - Command succeeded.\r
919 EFI_DEVICE_ERROR - Command failed.\r
920\r
921--*/\r
922{\r
923 EFI_STATUS Status;\r
924 USB_BOT_DEVICE *UsbBotDev;\r
925 EFI_USB_IO_PROTOCOL *UsbIo;\r
926\r
927 UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);\r
928 UsbIo = UsbBotDev->UsbIo;\r
929\r
930 if (ExtendedVerification) {\r
931 //\r
932 // If we need to do strictly reset, reset its parent hub port\r
933 //\r
934 Status = UsbIo->UsbPortReset (UsbIo);\r
935 if (EFI_ERROR (Status)) {\r
936 return Status;\r
937 }\r
938 }\r
939\r
940 Status = BotRecoveryReset (UsbBotDev);\r
941\r
942 return Status;\r
943}\r
944\r
92dda53e 945STATIC\r
878ddf1f 946VOID\r
947BotReportStatusCode (\r
948 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
949 IN EFI_STATUS_CODE_TYPE CodeType,\r
950 IN EFI_STATUS_CODE_VALUE Value\r
951 )\r
952/*++\r
953\r
954 Routine Description:\r
955 Report Status Code in Usb Bot Driver\r
956\r
957 Arguments:\r
958 DevicePath - Use this to get Device Path\r
959 CodeType - Status Code Type\r
960 CodeValue - Status Code Value\r
961\r
962 Returns:\r
963 None\r
964\r
965--*/\r
966{\r
967 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
968 CodeType,\r
969 Value,\r
970 DevicePath\r
971 );\r
972}\r