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