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