]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c
Move the share file: cbi.h to Cbi0 and Cbi1 directory.
[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
76 0x10,\r
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
357 CopyMem (&UsbCbiDev->BulkInEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));\r
358 // UsbCbiDev->BulkInEndpointDescriptor = EndpointDescriptor;\r
359 EndpointExistMask |= bit (0);\r
360 } else {\r
361 CopyMem (&UsbCbiDev->BulkOutEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));\r
362 // UsbCbiDev->BulkOutEndpointDescriptor = EndpointDescriptor;\r
363 EndpointExistMask |= bit (1);\r
364 }\r
365 }\r
366 //\r
367 // We parse interrupt endpoint\r
368 //\r
369 if (EndpointDescriptor.Attributes == 0x03) {\r
370 CopyMem (&UsbCbiDev->InterruptEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));\r
371 // UsbCbiDev->InterruptEndpointDescriptor = EndpointDescriptor;\r
372 EndpointExistMask |= bit (2);\r
373 }\r
374\r
375 }\r
376 //\r
377 // Double check we have all endpoints needed\r
378 //\r
379 if (EndpointExistMask != (bit (0) | bit (1) | bit (2))) {\r
380 gBS->CloseProtocol (\r
381 ControllerHandle,\r
382 &gEfiUsbIoProtocolGuid,\r
383 This->DriverBindingHandle,\r
384 ControllerHandle\r
385 );\r
386 if (UsbCbiDev != NULL) {\r
387 gBS->FreePool (UsbCbiDev);\r
388 }\r
389\r
390 return EFI_UNSUPPORTED;\r
391 }\r
392 //\r
393 // After installing Usb-Atapi protocol onto this handle\r
394 // it will be called by upper layer drivers such as Fat\r
395 //\r
396 Cbi0ReportStatusCode (\r
397 UsbCbiDev->DevicePath,\r
398 EFI_PROGRESS_CODE,\r
399 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE)\r
400 );\r
401\r
402 Status = gBS->InstallProtocolInterface (\r
403 &ControllerHandle,\r
404 &gEfiUsbAtapiProtocolGuid,\r
405 EFI_NATIVE_INTERFACE,\r
406 &UsbCbiDev->UsbAtapiProtocol\r
407 );\r
408 if (EFI_ERROR (Status)) {\r
409 gBS->CloseProtocol (\r
410 ControllerHandle,\r
411 &gEfiUsbIoProtocolGuid,\r
412 This->DriverBindingHandle,\r
413 ControllerHandle\r
414 );\r
415 if (UsbCbiDev != NULL) {\r
416 gBS->FreePool (UsbCbiDev);\r
417 }\r
418\r
419 return Status;\r
420 }\r
421\r
422 UsbCbiDev->ControllerNameTable = NULL;\r
423 AddUnicodeString (\r
424 "eng",\r
425 gUsbCbi0ComponentName.SupportedLanguages,\r
426 &UsbCbiDev->ControllerNameTable,\r
427 (CHAR16 *) L"Usb Cbi0 Mass Storage"\r
428 );\r
429\r
430 return EFI_SUCCESS;\r
431}\r
432\r
433STATIC\r
434EFI_STATUS\r
435EFIAPI\r
436Cbi0DriverBindingStop (\r
437 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
438 IN EFI_HANDLE ControllerHandle,\r
439 IN UINTN NumberOfChildren,\r
440 IN EFI_HANDLE *ChildHandleBuffer\r
441 )\r
442/*++\r
443\r
444 Routine Description:\r
445 Stop this driver on ControllerHandle. Support stoping any child handles\r
446 created by this driver.\r
447\r
448 Arguments:\r
449 This - Protocol instance pointer.\r
450 ControllerHandle - Handle of device to stop driver on\r
451 NumberOfChildren - Number of Children in the ChildHandleBuffer\r
452 ChildHandleBuffer - List of handles for the children we need to stop.\r
453\r
454 Returns:\r
455 EFI_SUCCESS - This driver is removed DeviceHandle\r
456 EFI_UNSUPPORTED - This driver was not removed from this device\r
457\r
458--*/\r
459{\r
460 EFI_STATUS Status;\r
461 EFI_USB_ATAPI_PROTOCOL *Cbi0AtapiProtocol;\r
462 USB_CBI_DEVICE *UsbCbiDev;\r
463 EFI_USB_IO_PROTOCOL *UsbIo;\r
464\r
465 //\r
466 // Get our context back.\r
467 //\r
468 Status = gBS->OpenProtocol (\r
469 ControllerHandle,\r
470 &gEfiUsbAtapiProtocolGuid,\r
471 (VOID **) &Cbi0AtapiProtocol,\r
472 This->DriverBindingHandle,\r
473 ControllerHandle,\r
474 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
475 );\r
476 if (EFI_ERROR (Status)) {\r
477 return EFI_UNSUPPORTED;\r
478 }\r
479\r
480 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (Cbi0AtapiProtocol);\r
481\r
482 UsbIo = UsbCbiDev->UsbIo;\r
483\r
484 Cbi0ReportStatusCode (\r
485 UsbCbiDev->DevicePath,\r
486 EFI_PROGRESS_CODE,\r
487 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE)\r
488 );\r
489\r
490 //\r
491 // Uninstall protocol\r
492 //\r
493 Status = gBS->UninstallProtocolInterface (\r
494 ControllerHandle,\r
495 &gEfiUsbAtapiProtocolGuid,\r
496 &UsbCbiDev->UsbAtapiProtocol\r
497 );\r
498 if (EFI_ERROR (Status)) {\r
499 return Status;\r
500 }\r
501\r
502 Status = gBS->CloseProtocol (\r
503 ControllerHandle,\r
504 &gEfiUsbIoProtocolGuid,\r
505 This->DriverBindingHandle,\r
506 ControllerHandle\r
507 );\r
508 //\r
509 // Free all allocated resources\r
510 //\r
511 if (UsbCbiDev->ControllerNameTable) {\r
512 FreeUnicodeStringTable (UsbCbiDev->ControllerNameTable);\r
513 }\r
514\r
515 gBS->FreePool (UsbCbiDev);\r
516\r
517 return Status;\r
518}\r
519\r
520\r
521STATIC\r
522EFI_STATUS\r
523Cbi0RecoveryReset (\r
524 IN USB_CBI_DEVICE *UsbCbiDev\r
525 )\r
526/*++\r
527\r
528Routine Description:\r
529\r
530 Cbi0 Recovery Reset routine\r
531\r
532Arguments:\r
533\r
534 UsbCbiDev - Cbi0RecoveryReset\r
535\r
536Returns:\r
537\r
538 EFI_SUCCESS - Success\r
539\r
540--*/\r
541{\r
542 UINT8 ResetCommand[12];\r
543 EFI_STATUS Status;\r
544 EFI_USB_IO_PROTOCOL *UsbIo;\r
545 UINT8 EndpointAddress;\r
546 UINT32 Result;\r
547 UINT16 Timeout;\r
548\r
549 UsbIo = UsbCbiDev->UsbIo;\r
550\r
551 Cbi0ReportStatusCode (\r
552 UsbCbiDev->DevicePath,\r
553 EFI_PROGRESS_CODE,\r
554 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET)\r
555 );\r
556 //\r
557 // CBI reset command protocol\r
558 //\r
559 SetMem (ResetCommand, sizeof (ResetCommand), 0xff);\r
560 ResetCommand[0] = 0x1d;\r
561 ResetCommand[1] = 0x04;\r
562\r
563 //\r
564 // (in millisecond unit)\r
565 //\r
566 Timeout = STALL_1_SECOND;\r
567\r
568 Status = Cbi0AtapiCommand (\r
569 &UsbCbiDev->UsbAtapiProtocol,\r
570 ResetCommand,\r
571 12,\r
572 NULL,\r
573 0,\r
574 EfiUsbNoData,\r
575 Timeout\r
576 );\r
577 if (EFI_ERROR (Status)) {\r
578 return Status;\r
579 }\r
580\r
581 gBS->Stall (100 * 1000);\r
582 //\r
583 // clear bulk in endpoint stall feature\r
584 //\r
585 EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;\r
586 Status = UsbClearEndpointHalt (\r
587 UsbIo,\r
588 EndpointAddress,\r
589 &Result\r
590 );\r
591 if (EFI_ERROR (Status)) {\r
592 return Status;\r
593 }\r
594 //\r
595 // clear bulk out endpoint stall feature\r
596 //\r
597 EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;\r
598 Status = UsbClearEndpointHalt (\r
599 UsbIo,\r
600 EndpointAddress,\r
601 &Result\r
602 );\r
603 //\r
604 // according to CBI spec, no need to clear interrupt endpoint feature.\r
605 //\r
606 return Status;\r
607}\r
608\r
609STATIC\r
610EFI_STATUS\r
611Cbi0CommandPhase (\r
612 IN USB_CBI_DEVICE *UsbCbiDev,\r
613 IN VOID *Command,\r
614 IN UINT8 CommandSize,\r
615 IN UINT16 Timeout\r
616 )\r
617/*++\r
618\r
619 Routine Description:\r
620 Send ATAPI command through CBI0 interface.\r
621\r
622 Arguments:\r
623 UsbCbiDev - USB_CBI_DEVICE\r
624 Command - Command to send\r
625 CommandSize - Command size\r
626 Timeout - Time out value in milliseconds\r
627 Returns:\r
628 EFI_SUCCESS - Success\r
629 EFI_DEVICE_ERROR - Fail\r
630 Others\r
631\r
632--*/\r
633{\r
634 EFI_STATUS Status;\r
635 UINT32 Result;\r
636 EFI_USB_IO_PROTOCOL *UsbIo;\r
637 EFI_USB_DEVICE_REQUEST Request;\r
638\r
639 UsbIo = UsbCbiDev->UsbIo;\r
640\r
641 ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST));\r
642\r
643 //\r
644 // Device request see CBI specification\r
645 //\r
646 Request.RequestType = 0x21;\r
647 Request.Request = 0x00;\r
648 Request.Value = 0;\r
649 Request.Index = 0;\r
650 Request.Length = CommandSize;\r
651\r
652 Status = UsbIo->UsbControlTransfer (\r
653 UsbIo,\r
654 &Request,\r
655 EfiUsbDataOut,\r
656 Timeout,\r
657 Command,\r
658 CommandSize,\r
659 &Result\r
660 );\r
661 if (EFI_ERROR (Status)) {\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
670Cbi0DataPhase (\r
671 IN USB_CBI_DEVICE *UsbCbiDev,\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 CBI0 interface\r
681\r
682 Arguments:\r
683 UsbCbiDev - USB_CBI_DEVICE\r
684 DataSize - Data size\r
685 DataBuffer - Data buffer\r
686 Direction - IN/OUT/NODATA\r
687 Timeout - Time out value in milliseconds\r
688 Returns:\r
689 EFI_SUCCESS\r
690 Others\r
691\r
692--*/\r
693{\r
694 EFI_STATUS Status;\r
695 EFI_USB_IO_PROTOCOL *UsbIo;\r
696 UINT8 EndpointAddress;\r
697 UINTN Remain;\r
698 UINTN Increment;\r
699 UINT32 MaxPacketLength;\r
700 UINT8 *BufferPtr;\r
701 UINT32 Result;\r
702 UINTN TransferredSize;\r
703\r
704 UsbIo = UsbCbiDev->UsbIo;\r
705\r
706 Remain = *DataSize;\r
707 BufferPtr = (UINT8 *) DataBuffer;\r
708 TransferredSize = 0;\r
709 //\r
710 // retrieve the the max packet length of the given endpoint\r
711 //\r
712 if (Direction == EfiUsbDataIn) {\r
713 MaxPacketLength = UsbCbiDev->BulkInEndpointDescriptor.MaxPacketSize;\r
714 EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;\r
715 } else {\r
716 MaxPacketLength = UsbCbiDev->BulkOutEndpointDescriptor.MaxPacketSize;\r
717 EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;\r
718 }\r
719\r
720 while (Remain > 0) {\r
721\r
722 if (Remain > 16 * MaxPacketLength) {\r
723 Increment = 16 * MaxPacketLength;\r
724 } else {\r
725 Increment = Remain;\r
726 }\r
727\r
728 Status = UsbIo->UsbBulkTransfer (\r
729 UsbIo,\r
730 EndpointAddress,\r
731 BufferPtr,\r
732 &Increment,\r
733 Timeout,\r
734 &Result\r
735 );\r
736 TransferredSize += Increment;\r
737\r
738 if (EFI_ERROR (Status)) {\r
739 goto ErrorExit;\r
740 }\r
741\r
742 BufferPtr += Increment;\r
743 Remain -= Increment;\r
744 }\r
745\r
746 return EFI_SUCCESS;\r
747\r
748ErrorExit:\r
749\r
750 if (Direction == EfiUsbDataIn) {\r
751 Cbi0ReportStatusCode (\r
752 UsbCbiDev->DevicePath,\r
753 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
754 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR)\r
755 );\r
756 } else {\r
757 Cbi0ReportStatusCode (\r
758 UsbCbiDev->DevicePath,\r
759 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
760 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR)\r
761 );\r
762 }\r
763\r
764 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
765 Status = Cbi0RecoveryReset (UsbCbiDev);\r
766 }\r
767\r
768 *DataSize = (UINT32) TransferredSize;\r
769 return Status;\r
770}\r
771\r
772STATIC\r
773EFI_STATUS\r
774Cbi0StatusPhase (\r
775 IN USB_CBI_DEVICE *UsbCbiDev,\r
776 OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock,\r
777 IN UINT16 Timeout\r
778 )\r
779/*++\r
780\r
781 Routine Description:\r
782 Get transfer status through BOT interface\r
783\r
784 Arguments:\r
785 UsbCbiDev - USB_CBI_DEVICE\r
786 InterruptDataBlock - Interrupt Data Block for interrupt transfer\r
787 Timeout - Time out value in milliseconds \r
788 Returns:\r
789 EFI_SUCCESS\r
790 Others\r
791\r
792--*/\r
793{\r
794 UINT8 EndpointAddress;\r
795 UINTN InterruptDataBlockLength;\r
796 UINT32 Result;\r
797 EFI_STATUS Status;\r
798\r
799 ZeroMem (InterruptDataBlock, sizeof (INTERRUPT_DATA_BLOCK));\r
800\r
801 EndpointAddress = UsbCbiDev->InterruptEndpointDescriptor.EndpointAddress;\r
802 InterruptDataBlockLength = sizeof (INTERRUPT_DATA_BLOCK);\r
803\r
804 Status = UsbCbiDev->UsbIo->UsbSyncInterruptTransfer (\r
805 UsbCbiDev->UsbIo,\r
806 EndpointAddress,\r
807 InterruptDataBlock,\r
808 &InterruptDataBlockLength,\r
809 Timeout,\r
810 &Result\r
811 );\r
812 if (EFI_ERROR (Status)) {\r
813 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
814 //\r
815 // just endpoint stall happens\r
816 //\r
817 UsbClearEndpointHalt (\r
818 UsbCbiDev->UsbIo,\r
819 EndpointAddress,\r
820 &Result\r
821 );\r
822 gBS->Stall (100 * 1000);\r
823 }\r
824\r
825 return Status;\r
826 }\r
827\r
828 return EFI_SUCCESS;\r
829}\r
830//\r
831// Cbi0 Atapi Protocol Implementation\r
832//\r
833STATIC\r
834EFI_STATUS\r
835EFIAPI\r
836Cbi0MassStorageReset (\r
837 IN EFI_USB_ATAPI_PROTOCOL *This,\r
838 IN BOOLEAN ExtendedVerification\r
839 )\r
840/*++\r
841\r
842 Routine Description:\r
843 Reset CBI Devices\r
844 \r
845 Arguments:\r
846 This - Protocol instance pointer.\r
847 ExtendedVerification - TRUE if we need to do strictly reset.\r
848\r
849 Returns:\r
850 EFI_SUCCESS - Command succeeded.\r
851 EFI_DEVICE_ERROR - Command failed.\r
852\r
853--*/\r
854{\r
855 EFI_STATUS Status;\r
856 EFI_USB_IO_PROTOCOL *UsbIo;\r
857 USB_CBI_DEVICE *UsbCbiDev;\r
858\r
859 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);\r
860 UsbIo = UsbCbiDev->UsbIo;\r
861\r
862 if (ExtendedVerification) {\r
863 //\r
864 // UsbIo->UsbPortReset (UsbIo);\r
865 //\r
866 }\r
867\r
868 Status = Cbi0RecoveryReset (UsbCbiDev);\r
869 return Status;\r
870}\r
871\r
872STATIC\r
873EFI_STATUS\r
874EFIAPI\r
875Cbi0AtapiCommand (\r
876 IN EFI_USB_ATAPI_PROTOCOL *This,\r
877 IN VOID *Command,\r
878 IN UINT8 CommandSize,\r
879 IN VOID *DataBuffer,\r
880 IN UINT32 BufferLength,\r
881 IN EFI_USB_DATA_DIRECTION Direction,\r
882 IN UINT16 TimeOutInMilliSeconds\r
883 )\r
884/*++\r
885\r
886 Routine Description:\r
887 Send ATAPI command using BOT protocol.\r
888\r
889 Arguments:\r
890 This - Protocol instance pointer.\r
891 Command - Command buffer\r
892 CommandSize - Size of Command Buffer\r
893 DataBuffer - Data buffer\r
894 BufferLength - Length of Data buffer\r
895 Direction - Data direction of this command\r
896 TimeOutInMilliSeconds - Timeout value in ms\r
897\r
898 Returns:\r
899 EFI_SUCCESS - Command succeeded.\r
900 EFI_DEVICE_ERROR - Command failed.\r
901 EFI_INVALID_PARAMETER - Invalidate parameter \r
902--*/\r
903{\r
904 EFI_STATUS Status;\r
905 USB_CBI_DEVICE *UsbCbiDev;\r
906 UINT32 BufferSize;\r
907 INTERRUPT_DATA_BLOCK InterruptDataBlock;\r
908 EFI_STATUS DataPhaseStatus;\r
909\r
910 if (Direction != EfiUsbNoData) {\r
911 if (DataBuffer == NULL || BufferLength == 0) {\r
912 return EFI_INVALID_PARAMETER;\r
913 }\r
914 }\r
915\r
916 DataPhaseStatus = EFI_SUCCESS;\r
917 //\r
918 // Get the context\r
919 //\r
920 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);\r
921\r
922 //\r
923 // First send ATAPI command through Cbi\r
924 //\r
925 Status = Cbi0CommandPhase (\r
926 UsbCbiDev,\r
927 Command,\r
928 CommandSize,\r
929 TimeOutInMilliSeconds\r
930 );\r
931 if (EFI_ERROR (Status)) {\r
932 return EFI_DEVICE_ERROR;\r
933 }\r
934 //\r
935 // Send/Get Data if there is a Data Stage\r
936 //\r
937 switch (Direction) {\r
938\r
939 case EfiUsbDataIn:\r
940 case EfiUsbDataOut:\r
941 BufferSize = BufferLength;\r
942\r
943 DataPhaseStatus = Cbi0DataPhase (\r
944 UsbCbiDev,\r
945 &BufferSize,\r
946 DataBuffer,\r
947 Direction,\r
948 TimeOutInMilliSeconds\r
949 );\r
950 break;\r
951\r
952 case EfiUsbNoData:\r
953 break;\r
954 }\r
955\r
956 if (EFI_ERROR (DataPhaseStatus)) {\r
957 return EFI_DEVICE_ERROR;\r
958 }\r
959 \r
960 //\r
961 // Status Phase\r
962 //\r
963 Status = Cbi0StatusPhase (\r
964 UsbCbiDev,\r
965 &InterruptDataBlock,\r
966 TimeOutInMilliSeconds\r
967 );\r
968 if (EFI_ERROR (Status)) {\r
969 return EFI_DEVICE_ERROR;\r
970 }\r
971\r
972 if (This->CommandProtocol != EFI_USB_SUBCLASS_UFI) {\r
973\r
974 if (InterruptDataBlock.bType == 0) {\r
975 //\r
976 // indicates command completion\r
977 //\r
978 switch (InterruptDataBlock.bValue & 0x03) {\r
979\r
980 case 0:\r
981 Status = EFI_SUCCESS;\r
982 break;\r
983\r
984 case 1:\r
985 Status = EFI_DEVICE_ERROR;\r
986 break;\r
987\r
988 case 2:\r
989 Status = Cbi0RecoveryReset (UsbCbiDev);\r
990 if (EFI_ERROR (Status)) {\r
991 UsbCbiDev->UsbIo->UsbPortReset (UsbCbiDev->UsbIo);\r
992 }\r
993\r
994 Status = EFI_DEVICE_ERROR;\r
995 break;\r
996\r
997 case 3:\r
998 Status = EFI_DEVICE_ERROR;\r
999 }\r
1000 } else {\r
1001 Status = DataPhaseStatus;\r
1002 }\r
1003\r
1004 } else {\r
1005 //\r
1006 // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code)\r
1007 // InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier)\r
1008 //\r
1009 Status = DataPhaseStatus;\r
1010 }\r
1011\r
1012 return Status;\r
1013}\r
1014\r
1015VOID\r
1016Cbi0ReportStatusCode (\r
1017 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1018 IN EFI_STATUS_CODE_TYPE CodeType,\r
1019 IN EFI_STATUS_CODE_VALUE Value\r
1020 )\r
1021/*++\r
1022\r
1023 Routine Description:\r
1024 Report Status Code in Usb Cbi0 Driver\r
1025\r
1026 Arguments:\r
1027 DevicePath - Use this to get Device Path\r
1028 CodeType - Status Code Type\r
1029 CodeValue - Status Code Value\r
1030\r
1031 Returns:\r
1032 None\r
1033\r
1034--*/\r
1035{\r
1036\r
1037 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1038 CodeType,\r
1039 Value,\r
1040 DevicePath\r
1041 );\r
1042}\r