]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c
Partially make EdkModulePkg pass intel IPF compiler with /W4 /WX switched on.
[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
878ddf1f 460\r
461 //\r
462 // Get our context back.\r
463 //\r
464 Status = gBS->OpenProtocol (\r
465 ControllerHandle,\r
466 &gEfiUsbAtapiProtocolGuid,\r
467 (VOID **) &Cbi0AtapiProtocol,\r
468 This->DriverBindingHandle,\r
469 ControllerHandle,\r
470 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
471 );\r
472 if (EFI_ERROR (Status)) {\r
473 return EFI_UNSUPPORTED;\r
474 }\r
475\r
476 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (Cbi0AtapiProtocol);\r
477\r
878ddf1f 478 Cbi0ReportStatusCode (\r
479 UsbCbiDev->DevicePath,\r
480 EFI_PROGRESS_CODE,\r
481 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE)\r
482 );\r
483\r
484 //\r
485 // Uninstall protocol\r
486 //\r
487 Status = gBS->UninstallProtocolInterface (\r
488 ControllerHandle,\r
489 &gEfiUsbAtapiProtocolGuid,\r
490 &UsbCbiDev->UsbAtapiProtocol\r
491 );\r
492 if (EFI_ERROR (Status)) {\r
493 return Status;\r
494 }\r
495\r
496 Status = gBS->CloseProtocol (\r
497 ControllerHandle,\r
498 &gEfiUsbIoProtocolGuid,\r
499 This->DriverBindingHandle,\r
500 ControllerHandle\r
501 );\r
502 //\r
503 // Free all allocated resources\r
504 //\r
505 if (UsbCbiDev->ControllerNameTable) {\r
506 FreeUnicodeStringTable (UsbCbiDev->ControllerNameTable);\r
507 }\r
508\r
509 gBS->FreePool (UsbCbiDev);\r
510\r
511 return Status;\r
512}\r
513\r
514\r
515STATIC\r
516EFI_STATUS\r
517Cbi0RecoveryReset (\r
518 IN USB_CBI_DEVICE *UsbCbiDev\r
519 )\r
520/*++\r
521\r
522Routine Description:\r
523\r
524 Cbi0 Recovery Reset routine\r
525\r
526Arguments:\r
527\r
528 UsbCbiDev - Cbi0RecoveryReset\r
529\r
530Returns:\r
531\r
532 EFI_SUCCESS - Success\r
533\r
534--*/\r
535{\r
536 UINT8 ResetCommand[12];\r
537 EFI_STATUS Status;\r
538 EFI_USB_IO_PROTOCOL *UsbIo;\r
539 UINT8 EndpointAddress;\r
540 UINT32 Result;\r
541 UINT16 Timeout;\r
542\r
543 UsbIo = UsbCbiDev->UsbIo;\r
544\r
545 Cbi0ReportStatusCode (\r
546 UsbCbiDev->DevicePath,\r
547 EFI_PROGRESS_CODE,\r
548 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET)\r
549 );\r
550 //\r
551 // CBI reset command protocol\r
552 //\r
553 SetMem (ResetCommand, sizeof (ResetCommand), 0xff);\r
554 ResetCommand[0] = 0x1d;\r
555 ResetCommand[1] = 0x04;\r
556\r
557 //\r
558 // (in millisecond unit)\r
559 //\r
560 Timeout = STALL_1_SECOND;\r
561\r
562 Status = Cbi0AtapiCommand (\r
563 &UsbCbiDev->UsbAtapiProtocol,\r
564 ResetCommand,\r
565 12,\r
566 NULL,\r
567 0,\r
568 EfiUsbNoData,\r
569 Timeout\r
570 );\r
571 if (EFI_ERROR (Status)) {\r
572 return Status;\r
573 }\r
574\r
575 gBS->Stall (100 * 1000);\r
576 //\r
577 // clear bulk in endpoint stall feature\r
578 //\r
579 EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;\r
580 Status = UsbClearEndpointHalt (\r
581 UsbIo,\r
582 EndpointAddress,\r
583 &Result\r
584 );\r
585 if (EFI_ERROR (Status)) {\r
586 return Status;\r
587 }\r
588 //\r
589 // clear bulk out endpoint stall feature\r
590 //\r
591 EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;\r
592 Status = UsbClearEndpointHalt (\r
593 UsbIo,\r
594 EndpointAddress,\r
595 &Result\r
596 );\r
597 //\r
598 // according to CBI spec, no need to clear interrupt endpoint feature.\r
599 //\r
600 return Status;\r
601}\r
602\r
603STATIC\r
604EFI_STATUS\r
605Cbi0CommandPhase (\r
606 IN USB_CBI_DEVICE *UsbCbiDev,\r
607 IN VOID *Command,\r
608 IN UINT8 CommandSize,\r
609 IN UINT16 Timeout\r
610 )\r
611/*++\r
612\r
613 Routine Description:\r
614 Send ATAPI command through CBI0 interface.\r
615\r
616 Arguments:\r
617 UsbCbiDev - USB_CBI_DEVICE\r
618 Command - Command to send\r
619 CommandSize - Command size\r
620 Timeout - Time out value in milliseconds\r
621 Returns:\r
622 EFI_SUCCESS - Success\r
623 EFI_DEVICE_ERROR - Fail\r
624 Others\r
625\r
626--*/\r
627{\r
628 EFI_STATUS Status;\r
629 UINT32 Result;\r
630 EFI_USB_IO_PROTOCOL *UsbIo;\r
631 EFI_USB_DEVICE_REQUEST Request;\r
632\r
633 UsbIo = UsbCbiDev->UsbIo;\r
634\r
635 ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST));\r
636\r
637 //\r
638 // Device request see CBI specification\r
639 //\r
640 Request.RequestType = 0x21;\r
641 Request.Request = 0x00;\r
642 Request.Value = 0;\r
643 Request.Index = 0;\r
644 Request.Length = CommandSize;\r
645\r
646 Status = UsbIo->UsbControlTransfer (\r
647 UsbIo,\r
648 &Request,\r
649 EfiUsbDataOut,\r
650 Timeout,\r
651 Command,\r
652 CommandSize,\r
653 &Result\r
654 );\r
655 if (EFI_ERROR (Status)) {\r
656 return EFI_DEVICE_ERROR;\r
657 }\r
658\r
659 return EFI_SUCCESS;\r
660}\r
661\r
662STATIC\r
663EFI_STATUS\r
664Cbi0DataPhase (\r
665 IN USB_CBI_DEVICE *UsbCbiDev,\r
666 IN UINT32 *DataSize,\r
667 IN OUT VOID *DataBuffer,\r
668 IN EFI_USB_DATA_DIRECTION Direction,\r
669 IN UINT16 Timeout\r
670 )\r
671/*++\r
672\r
673 Routine Description:\r
674 Get/Send Data through CBI0 interface\r
675\r
676 Arguments:\r
677 UsbCbiDev - USB_CBI_DEVICE\r
678 DataSize - Data size\r
679 DataBuffer - Data buffer\r
680 Direction - IN/OUT/NODATA\r
681 Timeout - Time out value in milliseconds\r
682 Returns:\r
683 EFI_SUCCESS\r
684 Others\r
685\r
686--*/\r
687{\r
688 EFI_STATUS Status;\r
689 EFI_USB_IO_PROTOCOL *UsbIo;\r
690 UINT8 EndpointAddress;\r
691 UINTN Remain;\r
692 UINTN Increment;\r
693 UINT32 MaxPacketLength;\r
694 UINT8 *BufferPtr;\r
695 UINT32 Result;\r
696 UINTN TransferredSize;\r
697\r
698 UsbIo = UsbCbiDev->UsbIo;\r
699\r
700 Remain = *DataSize;\r
701 BufferPtr = (UINT8 *) DataBuffer;\r
702 TransferredSize = 0;\r
703 //\r
704 // retrieve the the max packet length of the given endpoint\r
705 //\r
706 if (Direction == EfiUsbDataIn) {\r
707 MaxPacketLength = UsbCbiDev->BulkInEndpointDescriptor.MaxPacketSize;\r
708 EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;\r
709 } else {\r
710 MaxPacketLength = UsbCbiDev->BulkOutEndpointDescriptor.MaxPacketSize;\r
711 EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;\r
712 }\r
713\r
714 while (Remain > 0) {\r
715\r
716 if (Remain > 16 * MaxPacketLength) {\r
717 Increment = 16 * MaxPacketLength;\r
718 } else {\r
719 Increment = Remain;\r
720 }\r
721\r
722 Status = UsbIo->UsbBulkTransfer (\r
723 UsbIo,\r
724 EndpointAddress,\r
725 BufferPtr,\r
726 &Increment,\r
727 Timeout,\r
728 &Result\r
729 );\r
730 TransferredSize += Increment;\r
731\r
732 if (EFI_ERROR (Status)) {\r
733 goto ErrorExit;\r
734 }\r
735\r
736 BufferPtr += Increment;\r
737 Remain -= Increment;\r
738 }\r
739\r
740 return EFI_SUCCESS;\r
741\r
742ErrorExit:\r
743\r
744 if (Direction == EfiUsbDataIn) {\r
745 Cbi0ReportStatusCode (\r
746 UsbCbiDev->DevicePath,\r
747 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
748 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR)\r
749 );\r
750 } else {\r
751 Cbi0ReportStatusCode (\r
752 UsbCbiDev->DevicePath,\r
753 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
754 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR)\r
755 );\r
756 }\r
757\r
758 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
759 Status = Cbi0RecoveryReset (UsbCbiDev);\r
760 }\r
761\r
762 *DataSize = (UINT32) TransferredSize;\r
763 return Status;\r
764}\r
765\r
766STATIC\r
767EFI_STATUS\r
768Cbi0StatusPhase (\r
769 IN USB_CBI_DEVICE *UsbCbiDev,\r
770 OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock,\r
771 IN UINT16 Timeout\r
772 )\r
773/*++\r
774\r
775 Routine Description:\r
776 Get transfer status through BOT interface\r
777\r
778 Arguments:\r
779 UsbCbiDev - USB_CBI_DEVICE\r
780 InterruptDataBlock - Interrupt Data Block for interrupt transfer\r
781 Timeout - Time out value in milliseconds \r
782 Returns:\r
783 EFI_SUCCESS\r
784 Others\r
785\r
786--*/\r
787{\r
788 UINT8 EndpointAddress;\r
789 UINTN InterruptDataBlockLength;\r
790 UINT32 Result;\r
791 EFI_STATUS Status;\r
792\r
793 ZeroMem (InterruptDataBlock, sizeof (INTERRUPT_DATA_BLOCK));\r
794\r
795 EndpointAddress = UsbCbiDev->InterruptEndpointDescriptor.EndpointAddress;\r
796 InterruptDataBlockLength = sizeof (INTERRUPT_DATA_BLOCK);\r
797\r
798 Status = UsbCbiDev->UsbIo->UsbSyncInterruptTransfer (\r
799 UsbCbiDev->UsbIo,\r
800 EndpointAddress,\r
801 InterruptDataBlock,\r
802 &InterruptDataBlockLength,\r
803 Timeout,\r
804 &Result\r
805 );\r
806 if (EFI_ERROR (Status)) {\r
807 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
808 //\r
809 // just endpoint stall happens\r
810 //\r
811 UsbClearEndpointHalt (\r
812 UsbCbiDev->UsbIo,\r
813 EndpointAddress,\r
814 &Result\r
815 );\r
816 gBS->Stall (100 * 1000);\r
817 }\r
818\r
819 return Status;\r
820 }\r
821\r
822 return EFI_SUCCESS;\r
823}\r
824//\r
825// Cbi0 Atapi Protocol Implementation\r
826//\r
827STATIC\r
828EFI_STATUS\r
829EFIAPI\r
830Cbi0MassStorageReset (\r
831 IN EFI_USB_ATAPI_PROTOCOL *This,\r
832 IN BOOLEAN ExtendedVerification\r
833 )\r
834/*++\r
835\r
836 Routine Description:\r
837 Reset CBI Devices\r
838 \r
839 Arguments:\r
840 This - Protocol instance pointer.\r
841 ExtendedVerification - TRUE if we need to do strictly reset.\r
842\r
843 Returns:\r
844 EFI_SUCCESS - Command succeeded.\r
845 EFI_DEVICE_ERROR - Command failed.\r
846\r
847--*/\r
848{\r
849 EFI_STATUS Status;\r
878ddf1f 850 USB_CBI_DEVICE *UsbCbiDev;\r
851\r
852 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);\r
878ddf1f 853\r
854 if (ExtendedVerification) {\r
855 //\r
856 // UsbIo->UsbPortReset (UsbIo);\r
857 //\r
858 }\r
859\r
860 Status = Cbi0RecoveryReset (UsbCbiDev);\r
861 return Status;\r
862}\r
863\r
864STATIC\r
865EFI_STATUS\r
866EFIAPI\r
867Cbi0AtapiCommand (\r
868 IN EFI_USB_ATAPI_PROTOCOL *This,\r
869 IN VOID *Command,\r
870 IN UINT8 CommandSize,\r
871 IN VOID *DataBuffer,\r
872 IN UINT32 BufferLength,\r
873 IN EFI_USB_DATA_DIRECTION Direction,\r
874 IN UINT16 TimeOutInMilliSeconds\r
875 )\r
876/*++\r
877\r
878 Routine Description:\r
879 Send ATAPI command using BOT protocol.\r
880\r
881 Arguments:\r
882 This - Protocol instance pointer.\r
883 Command - Command buffer\r
884 CommandSize - Size of Command Buffer\r
885 DataBuffer - Data buffer\r
886 BufferLength - Length of Data buffer\r
887 Direction - Data direction of this command\r
888 TimeOutInMilliSeconds - Timeout value in ms\r
889\r
890 Returns:\r
891 EFI_SUCCESS - Command succeeded.\r
892 EFI_DEVICE_ERROR - Command failed.\r
893 EFI_INVALID_PARAMETER - Invalidate parameter \r
894--*/\r
895{\r
896 EFI_STATUS Status;\r
897 USB_CBI_DEVICE *UsbCbiDev;\r
898 UINT32 BufferSize;\r
899 INTERRUPT_DATA_BLOCK InterruptDataBlock;\r
900 EFI_STATUS DataPhaseStatus;\r
901\r
902 if (Direction != EfiUsbNoData) {\r
903 if (DataBuffer == NULL || BufferLength == 0) {\r
904 return EFI_INVALID_PARAMETER;\r
905 }\r
906 }\r
907\r
908 DataPhaseStatus = EFI_SUCCESS;\r
909 //\r
910 // Get the context\r
911 //\r
912 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);\r
913\r
914 //\r
915 // First send ATAPI command through Cbi\r
916 //\r
917 Status = Cbi0CommandPhase (\r
918 UsbCbiDev,\r
919 Command,\r
920 CommandSize,\r
921 TimeOutInMilliSeconds\r
922 );\r
923 if (EFI_ERROR (Status)) {\r
924 return EFI_DEVICE_ERROR;\r
925 }\r
926 //\r
927 // Send/Get Data if there is a Data Stage\r
928 //\r
929 switch (Direction) {\r
930\r
931 case EfiUsbDataIn:\r
932 case EfiUsbDataOut:\r
933 BufferSize = BufferLength;\r
934\r
935 DataPhaseStatus = Cbi0DataPhase (\r
936 UsbCbiDev,\r
937 &BufferSize,\r
938 DataBuffer,\r
939 Direction,\r
940 TimeOutInMilliSeconds\r
941 );\r
942 break;\r
943\r
944 case EfiUsbNoData:\r
945 break;\r
946 }\r
947\r
948 if (EFI_ERROR (DataPhaseStatus)) {\r
949 return EFI_DEVICE_ERROR;\r
950 }\r
951 \r
952 //\r
953 // Status Phase\r
954 //\r
955 Status = Cbi0StatusPhase (\r
956 UsbCbiDev,\r
957 &InterruptDataBlock,\r
958 TimeOutInMilliSeconds\r
959 );\r
960 if (EFI_ERROR (Status)) {\r
961 return EFI_DEVICE_ERROR;\r
962 }\r
963\r
964 if (This->CommandProtocol != EFI_USB_SUBCLASS_UFI) {\r
965\r
966 if (InterruptDataBlock.bType == 0) {\r
967 //\r
968 // indicates command completion\r
969 //\r
970 switch (InterruptDataBlock.bValue & 0x03) {\r
971\r
972 case 0:\r
973 Status = EFI_SUCCESS;\r
974 break;\r
975\r
976 case 1:\r
977 Status = EFI_DEVICE_ERROR;\r
978 break;\r
979\r
980 case 2:\r
981 Status = Cbi0RecoveryReset (UsbCbiDev);\r
982 if (EFI_ERROR (Status)) {\r
983 UsbCbiDev->UsbIo->UsbPortReset (UsbCbiDev->UsbIo);\r
984 }\r
985\r
986 Status = EFI_DEVICE_ERROR;\r
987 break;\r
988\r
989 case 3:\r
990 Status = EFI_DEVICE_ERROR;\r
991 }\r
992 } else {\r
993 Status = DataPhaseStatus;\r
994 }\r
995\r
996 } else {\r
997 //\r
998 // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code)\r
999 // InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier)\r
1000 //\r
1001 Status = DataPhaseStatus;\r
1002 }\r
1003\r
1004 return Status;\r
1005}\r
1006\r
1007VOID\r
1008Cbi0ReportStatusCode (\r
1009 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1010 IN EFI_STATUS_CODE_TYPE CodeType,\r
1011 IN EFI_STATUS_CODE_VALUE Value\r
1012 )\r
1013/*++\r
1014\r
1015 Routine Description:\r
1016 Report Status Code in Usb Cbi0 Driver\r
1017\r
1018 Arguments:\r
1019 DevicePath - Use this to get Device Path\r
1020 CodeType - Status Code Type\r
1021 CodeValue - Status Code Value\r
1022\r
1023 Returns:\r
1024 None\r
1025\r
1026--*/\r
1027{\r
1028\r
1029 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1030 CodeType,\r
1031 Value,\r
1032 DevicePath\r
1033 );\r
1034}\r