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