]> git.proxmox.com Git - mirror_edk2.git/blob - OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772b/DriverBinding.c
OptionRomPkg: Ax88772b: Fixing register access issue in Apple Eth Adapter
[mirror_edk2.git] / OptionRomPkg / Bus / Usb / UsbNetworking / Ax88772b / DriverBinding.c
1 /** @file
2 Implement the driver binding protocol for Asix AX88772 Ethernet driver.
3
4 Copyright (c) 2011-2013, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Ax88772.h"
16
17 ASIX_DONGLE ASIX_DONGLES[] = {
18 { 0x05AC, 0x1402, FLAG_TYPE_AX88772 }, // Apple USB Ethernet Adapter
19 // ASIX 88772B
20 { 0x0B95, 0x772B, FLAG_TYPE_AX88772B | FLAG_EEPROM_MAC },
21 { 0x0000, 0x0000, FLAG_NONE } // END - Do not remove
22 };
23
24 /**
25 Verify the controller type
26
27 @param [in] pThis Protocol instance pointer.
28 @param [in] Controller Handle of device to test.
29 @param [in] pRemainingDevicePath Not used.
30
31 @retval EFI_SUCCESS This driver supports this device.
32 @retval other This driver does not support this device.
33
34 **/
35 EFI_STATUS
36 EFIAPI
37 DriverSupported (
38 IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
39 IN EFI_HANDLE Controller,
40 IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath
41 )
42 {
43 EFI_USB_DEVICE_DESCRIPTOR Device;
44 EFI_USB_IO_PROTOCOL * pUsbIo;
45 EFI_STATUS Status;
46 UINT32 Index;
47
48 //
49 // Connect to the USB stack
50 //
51 Status = gBS->OpenProtocol (
52 Controller,
53 &gEfiUsbIoProtocolGuid,
54 (VOID **) &pUsbIo,
55 pThis->DriverBindingHandle,
56 Controller,
57 EFI_OPEN_PROTOCOL_BY_DRIVER
58 );
59 if (!EFI_ERROR ( Status )) {
60
61 //
62 // Get the interface descriptor to check the USB class and find a transport
63 // protocol handler.
64 //
65 Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device );
66 if (EFI_ERROR ( Status )) {
67 Status = EFI_UNSUPPORTED;
68 }
69 else {
70 //
71 // Validate the adapter
72 //
73 for (Index = 0; ASIX_DONGLES[Index].VendorId != 0; Index++) {
74 if (ASIX_DONGLES[Index].VendorId == Device.IdVendor &&
75 ASIX_DONGLES[Index].ProductId == Device.IdProduct) {
76 DEBUG ((EFI_D_INFO, "Found the AX88772B\r\n"));
77 break;
78 }
79 }
80
81 if (ASIX_DONGLES[Index].VendorId == 0)
82 Status = EFI_UNSUPPORTED;
83 }
84
85 //
86 // Done with the USB stack
87 //
88 gBS->CloseProtocol (
89 Controller,
90 &gEfiUsbIoProtocolGuid,
91 pThis->DriverBindingHandle,
92 Controller
93 );
94 }
95 return Status;
96 }
97
98
99 /**
100 Start this driver on Controller by opening UsbIo and DevicePath protocols.
101 Initialize PXE structures, create a copy of the Controller Device Path with the
102 NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol
103 on the newly created Device Path.
104
105 @param [in] pThis Protocol instance pointer.
106 @param [in] Controller Handle of device to work with.
107 @param [in] pRemainingDevicePath Not used, always produce all possible children.
108
109 @retval EFI_SUCCESS This driver is added to Controller.
110 @retval other This driver does not support this device.
111
112 **/
113 EFI_STATUS
114 EFIAPI
115 DriverStart (
116 IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
117 IN EFI_HANDLE Controller,
118 IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath
119 )
120 {
121
122 EFI_STATUS Status;
123 NIC_DEVICE *pNicDevice;
124 UINTN LengthInBytes;
125 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath = NULL;
126 MAC_ADDR_DEVICE_PATH MacDeviceNode;
127 EFI_USB_DEVICE_DESCRIPTOR Device;
128 UINT32 Index;
129
130 //
131 // Allocate the device structure
132 //
133 LengthInBytes = sizeof ( *pNicDevice );
134 Status = gBS->AllocatePool (
135 EfiRuntimeServicesData,
136 LengthInBytes,
137 (VOID **) &pNicDevice
138 );
139
140 if (EFI_ERROR (Status)) {
141 DEBUG ((EFI_D_ERROR, "gBS->AllocatePool:pNicDevice ERROR Status = %r\n", Status));
142 goto EXIT;
143 }
144
145 //
146 // Set the structure signature
147 //
148 ZeroMem ( pNicDevice, LengthInBytes );
149 pNicDevice->Signature = DEV_SIGNATURE;
150
151 Status = gBS->OpenProtocol (
152 Controller,
153 &gEfiUsbIoProtocolGuid,
154 (VOID **) &pNicDevice->pUsbIo,
155 pThis->DriverBindingHandle,
156 Controller,
157 EFI_OPEN_PROTOCOL_BY_DRIVER
158 );
159
160 if (EFI_ERROR (Status)) {
161 DEBUG ((EFI_D_ERROR, "gBS->OpenProtocol:EFI_USB_IO_PROTOCOL ERROR Status = %r\n", Status));
162 gBS->FreePool ( pNicDevice );
163 goto EXIT;
164 }
165
166 //
167 // Initialize the simple network protocol
168 //
169 Status = SN_Setup ( pNicDevice );
170
171 if (EFI_ERROR(Status)){
172 DEBUG ((EFI_D_ERROR, "SN_Setup ERROR Status = %r\n", Status));
173 gBS->CloseProtocol (
174 Controller,
175 &gEfiUsbIoProtocolGuid,
176 pThis->DriverBindingHandle,
177 Controller
178 );
179 gBS->FreePool ( pNicDevice );
180 goto EXIT;
181 }
182
183 Status = pNicDevice->pUsbIo->UsbGetDeviceDescriptor ( pNicDevice->pUsbIo, &Device );
184 if (EFI_ERROR ( Status )) {
185 gBS->CloseProtocol (
186 Controller,
187 &gEfiUsbIoProtocolGuid,
188 pThis->DriverBindingHandle,
189 Controller
190 );
191 gBS->FreePool ( pNicDevice );
192 goto EXIT;
193 } else {
194 //
195 // Validate the adapter
196 //
197 for (Index = 0; ASIX_DONGLES[Index].VendorId != 0; Index++) {
198 if (ASIX_DONGLES[Index].VendorId == Device.IdVendor &&
199 ASIX_DONGLES[Index].ProductId == Device.IdProduct) {
200 break;
201 }
202 }
203
204 if (ASIX_DONGLES[Index].VendorId == 0) {
205 gBS->CloseProtocol (
206 Controller,
207 &gEfiUsbIoProtocolGuid,
208 pThis->DriverBindingHandle,
209 Controller
210 );
211 gBS->FreePool ( pNicDevice );
212 goto EXIT;
213 }
214
215 pNicDevice->Flags = ASIX_DONGLES[Index].Flags;
216 }
217
218 //
219 // Set Device Path
220 //
221 Status = gBS->OpenProtocol (
222 Controller,
223 &gEfiDevicePathProtocolGuid,
224 (VOID **) &ParentDevicePath,
225 pThis->DriverBindingHandle,
226 Controller,
227 EFI_OPEN_PROTOCOL_BY_DRIVER
228 );
229 if (EFI_ERROR(Status)) {
230 DEBUG ((EFI_D_ERROR, "gBS->OpenProtocol:EFI_DEVICE_PATH_PROTOCOL error. Status = %r\n",
231 Status));
232 gBS->CloseProtocol (
233 Controller,
234 &gEfiUsbIoProtocolGuid,
235 pThis->DriverBindingHandle,
236 Controller
237 );
238 gBS->FreePool ( pNicDevice );
239 goto EXIT;
240 }
241
242 ZeroMem (&MacDeviceNode, sizeof (MAC_ADDR_DEVICE_PATH));
243 MacDeviceNode.Header.Type = MESSAGING_DEVICE_PATH;
244 MacDeviceNode.Header.SubType = MSG_MAC_ADDR_DP;
245
246 SetDevicePathNodeLength (&MacDeviceNode.Header, sizeof (MAC_ADDR_DEVICE_PATH));
247
248 CopyMem (&MacDeviceNode.MacAddress,
249 &pNicDevice->SimpleNetworkData.CurrentAddress,
250 PXE_HWADDR_LEN_ETHER);
251
252 MacDeviceNode.IfType = pNicDevice->SimpleNetworkData.IfType;
253
254 pNicDevice->MyDevPath = AppendDevicePathNode (
255 ParentDevicePath,
256 (EFI_DEVICE_PATH_PROTOCOL *) &MacDeviceNode
257 );
258
259 pNicDevice->Controller = NULL;
260
261 //
262 // Install both the simple network and device path protocols.
263 //
264 Status = gBS->InstallMultipleProtocolInterfaces (
265 &pNicDevice->Controller,
266 &gEfiCallerIdGuid,
267 pNicDevice,
268 &gEfiSimpleNetworkProtocolGuid,
269 &pNicDevice->SimpleNetwork,
270 &gEfiDevicePathProtocolGuid,
271 pNicDevice->MyDevPath,
272 NULL
273 );
274
275 if (EFI_ERROR(Status)){
276 DEBUG ((EFI_D_ERROR, "gBS->InstallMultipleProtocolInterfaces error. Status = %r\n",
277 Status));
278 gBS->CloseProtocol (
279 Controller,
280 &gEfiDevicePathProtocolGuid,
281 pThis->DriverBindingHandle,
282 Controller);
283 gBS->CloseProtocol (
284 Controller,
285 &gEfiUsbIoProtocolGuid,
286 pThis->DriverBindingHandle,
287 Controller
288 );
289 gBS->FreePool ( pNicDevice );
290 goto EXIT;
291 }
292
293 //
294 // Open For Child Device
295 //
296 Status = gBS->OpenProtocol (
297 Controller,
298 &gEfiUsbIoProtocolGuid,
299 (VOID **) &pNicDevice->pUsbIo,
300 pThis->DriverBindingHandle,
301 pNicDevice->Controller,
302 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
303 );
304
305 if (EFI_ERROR(Status)){
306 gBS->UninstallMultipleProtocolInterfaces (
307 &pNicDevice->Controller,
308 &gEfiCallerIdGuid,
309 pNicDevice,
310 &gEfiSimpleNetworkProtocolGuid,
311 &pNicDevice->SimpleNetwork,
312 &gEfiDevicePathProtocolGuid,
313 pNicDevice->MyDevPath,
314 NULL
315 );
316 gBS->CloseProtocol (
317 Controller,
318 &gEfiDevicePathProtocolGuid,
319 pThis->DriverBindingHandle,
320 Controller);
321 gBS->CloseProtocol (
322 Controller,
323 &gEfiUsbIoProtocolGuid,
324 pThis->DriverBindingHandle,
325 Controller
326 );
327 gBS->FreePool ( pNicDevice );
328 }
329
330 EXIT:
331 return Status;
332
333 }
334
335 /**
336 Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
337 closing the DevicePath and PciIo protocols on Controller.
338
339 @param [in] pThis Protocol instance pointer.
340 @param [in] Controller Handle of device to stop driver on.
341 @param [in] NumberOfChildren How many children need to be stopped.
342 @param [in] pChildHandleBuffer Not used.
343
344 @retval EFI_SUCCESS This driver is removed Controller.
345 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
346 @retval other This driver was not removed from this device.
347
348 **/
349 EFI_STATUS
350 EFIAPI
351 DriverStop (
352 IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
353 IN EFI_HANDLE Controller,
354 IN UINTN NumberOfChildren,
355 IN EFI_HANDLE * ChildHandleBuffer
356 )
357 {
358 BOOLEAN AllChildrenStopped;
359 UINTN Index;
360 EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
361 EFI_STATUS Status = EFI_SUCCESS;
362 NIC_DEVICE *pNicDevice;
363
364 //
365 // Complete all outstanding transactions to Controller.
366 // Don't allow any new transaction to Controller to be started.
367 //
368 if (NumberOfChildren == 0) {
369
370 Status = gBS->OpenProtocol (
371 Controller,
372 &gEfiSimpleNetworkProtocolGuid,
373 (VOID **) &SimpleNetwork,
374 pThis->DriverBindingHandle,
375 Controller,
376 EFI_OPEN_PROTOCOL_GET_PROTOCOL
377 );
378
379 if (EFI_ERROR(Status)) {
380 //
381 // This is a 2nd type handle(multi-lun root), it needs to close devicepath
382 // and usbio protocol.
383 //
384 gBS->CloseProtocol (
385 Controller,
386 &gEfiDevicePathProtocolGuid,
387 pThis->DriverBindingHandle,
388 Controller
389 );
390 gBS->CloseProtocol (
391 Controller,
392 &gEfiUsbIoProtocolGuid,
393 pThis->DriverBindingHandle,
394 Controller
395 );
396 return EFI_SUCCESS;
397 }
398
399 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork );
400
401 Status = gBS->UninstallMultipleProtocolInterfaces (
402 Controller,
403 &gEfiCallerIdGuid,
404 pNicDevice,
405 &gEfiSimpleNetworkProtocolGuid,
406 &pNicDevice->SimpleNetwork,
407 &gEfiDevicePathProtocolGuid,
408 pNicDevice->MyDevPath,
409 NULL
410 );
411
412 if (EFI_ERROR (Status)) {
413 return Status;
414 }
415 //
416 // Close the bus driver
417 //
418 Status = gBS->CloseProtocol (
419 Controller,
420 &gEfiDevicePathProtocolGuid,
421 pThis->DriverBindingHandle,
422 Controller
423 );
424
425 if (EFI_ERROR(Status)){
426 DEBUG ((EFI_D_ERROR, "driver stop: gBS->CloseProtocol:EfiDevicePathProtocol error. Status %r\n", Status));
427 }
428
429 Status = gBS->CloseProtocol (
430 Controller,
431 &gEfiUsbIoProtocolGuid,
432 pThis->DriverBindingHandle,
433 Controller
434 );
435
436 if (EFI_ERROR(Status)){
437 DEBUG ((EFI_D_ERROR, "driver stop: gBS->CloseProtocol:EfiUsbIoProtocol error. Status %r\n", Status));
438 }
439 return EFI_SUCCESS;
440 }
441 AllChildrenStopped = TRUE;
442
443 for (Index = 0; Index < NumberOfChildren; Index++) {
444
445 Status = gBS->OpenProtocol (
446 ChildHandleBuffer[Index],
447 &gEfiSimpleNetworkProtocolGuid,
448 (VOID **) &SimpleNetwork,
449 pThis->DriverBindingHandle,
450 Controller,
451 EFI_OPEN_PROTOCOL_GET_PROTOCOL
452 );
453
454 if (EFI_ERROR (Status)) {
455 AllChildrenStopped = FALSE;
456 DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when opening SimpleNetwork\n", (UINT32)Index));
457 continue;
458 }
459
460 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork );
461
462 gBS->CloseProtocol (
463 Controller,
464 &gEfiUsbIoProtocolGuid,
465 pThis->DriverBindingHandle,
466 ChildHandleBuffer[Index]
467 );
468
469 Status = gBS->UninstallMultipleProtocolInterfaces (
470 ChildHandleBuffer[Index],
471 &gEfiCallerIdGuid,
472 pNicDevice,
473 &gEfiSimpleNetworkProtocolGuid,
474 &pNicDevice->SimpleNetwork,
475 &gEfiDevicePathProtocolGuid,
476 pNicDevice->MyDevPath,
477 NULL
478 );
479
480 if (EFI_ERROR (Status)) {
481 Status = gBS->OpenProtocol (
482 Controller,
483 &gEfiUsbIoProtocolGuid,
484 (VOID **) &pNicDevice->pUsbIo,
485 pThis->DriverBindingHandle,
486 ChildHandleBuffer[Index],
487 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
488 );
489 }
490 else {
491 int i;
492 RX_PKT * pCurr = pNicDevice->QueueHead;
493 RX_PKT * pFree;
494
495 for ( i = 0 ; i < MAX_QUEUE_SIZE ; i++) {
496 if ( NULL != pCurr ) {
497 pFree = pCurr;
498 pCurr = pCurr->pNext;
499 gBS->FreePool (pFree);
500 }
501 }
502
503 if ( NULL != pNicDevice->pRxTest)
504 gBS->FreePool (pNicDevice->pRxTest);
505
506 if ( NULL != pNicDevice->pTxTest)
507 gBS->FreePool (pNicDevice->pTxTest);
508
509 if ( NULL != pNicDevice->MyDevPath)
510 gBS->FreePool (pNicDevice->MyDevPath);
511
512 if ( NULL != pNicDevice)
513 gBS->FreePool (pNicDevice);
514 }
515 }
516
517 if (!AllChildrenStopped) {
518 return EFI_DEVICE_ERROR;
519 }
520 return EFI_SUCCESS;
521 }
522
523
524 /**
525 Driver binding protocol declaration
526 **/
527 EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
528 DriverSupported,
529 DriverStart,
530 DriverStop,
531 0xa,
532 NULL,
533 NULL
534 };
535
536
537 /**
538 Ax88772 driver unload routine.
539
540 @param [in] ImageHandle Handle for the image.
541
542 @retval EFI_SUCCESS Image may be unloaded
543
544 **/
545 EFI_STATUS
546 EFIAPI
547 DriverUnload (
548 IN EFI_HANDLE ImageHandle
549 )
550 {
551 UINTN BufferSize;
552 UINTN Index;
553 UINTN Max;
554 EFI_HANDLE * pHandle;
555 EFI_STATUS Status;
556
557 //
558 // Determine which devices are using this driver
559 //
560 BufferSize = 0;
561 pHandle = NULL;
562 Status = gBS->LocateHandle (
563 ByProtocol,
564 &gEfiCallerIdGuid,
565 NULL,
566 &BufferSize,
567 NULL );
568 if ( EFI_BUFFER_TOO_SMALL == Status ) {
569 for ( ; ; ) {
570 //
571 // One or more block IO devices are present
572 //
573 Status = gBS->AllocatePool (
574 EfiRuntimeServicesData,
575 BufferSize,
576 (VOID **) &pHandle
577 );
578 if ( EFI_ERROR ( Status )) {
579 DEBUG ((EFI_D_ERROR, "Insufficient memory, failed handle buffer allocation\r\n"));
580 break;
581 }
582
583 //
584 // Locate the block IO devices
585 //
586 Status = gBS->LocateHandle (
587 ByProtocol,
588 &gEfiCallerIdGuid,
589 NULL,
590 &BufferSize,
591 pHandle );
592 if ( EFI_ERROR ( Status )) {
593 //
594 // Error getting handles
595 //
596 break;
597 }
598
599 //
600 // Remove any use of the driver
601 //
602 Max = BufferSize / sizeof ( pHandle[ 0 ]);
603 for ( Index = 0; Max > Index; Index++ ) {
604 Status = DriverStop ( &gDriverBinding,
605 pHandle[ Index ],
606 0,
607 NULL );
608 if ( EFI_ERROR ( Status )) {
609 DEBUG ((EFI_D_ERROR, "WARNING - Failed to shutdown the driver on handle %08x\r\n", pHandle[ Index ]));
610 break;
611 }
612 }
613 break;
614 }
615 }
616 else {
617 if ( EFI_NOT_FOUND == Status ) {
618 //
619 // No devices were found
620 //
621 Status = EFI_SUCCESS;
622 }
623 }
624
625 //
626 // Free the handle array
627 //
628 if ( NULL != pHandle ) {
629 gBS->FreePool ( pHandle );
630 }
631
632 //
633 // Remove the protocols installed by the EntryPoint routine.
634 //
635 if ( !EFI_ERROR ( Status )) {
636 gBS->UninstallMultipleProtocolInterfaces (
637 ImageHandle,
638 &gEfiDriverBindingProtocolGuid,
639 &gDriverBinding,
640 &gEfiComponentNameProtocolGuid,
641 &gComponentName,
642 &gEfiComponentName2ProtocolGuid,
643 &gComponentName2,
644 NULL
645 );
646
647 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
648 "Removed: gEfiComponentName2ProtocolGuid from 0x%08x\r\n",
649 ImageHandle ));
650 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
651 "Removed: gEfiComponentNameProtocolGuid from 0x%08x\r\n",
652 ImageHandle ));
653 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
654 "Removed: gEfiDriverBindingProtocolGuid from 0x%08x\r\n",
655 ImageHandle ));
656
657 }
658
659 return Status;
660 }
661
662
663 /**
664 Ax88772 driver entry point.
665
666 @param [in] ImageHandle Handle for the image.
667 @param [in] pSystemTable Address of the system table.
668
669 @retval EFI_SUCCESS Image successfully loaded.
670
671 **/
672 EFI_STATUS
673 EFIAPI
674 EntryPoint (
675 IN EFI_HANDLE ImageHandle,
676 IN EFI_SYSTEM_TABLE * pSystemTable
677 )
678 {
679 EFI_STATUS Status;
680
681 //
682 // Add the driver to the list of drivers
683 //
684 Status = EfiLibInstallDriverBindingComponentName2 (
685 ImageHandle,
686 pSystemTable,
687 &gDriverBinding,
688 ImageHandle,
689 &gComponentName,
690 &gComponentName2
691 );
692 if ( !EFI_ERROR ( Status )) {
693 DEBUG ((EFI_D_INFO, "Installed: gEfiDriverBindingProtocolGuid on 0x%08x\r\n",
694 ImageHandle));
695 DEBUG ((EFI_D_INFO, "Installed: gEfiComponentNameProtocolGuid on 0x%08x\r\n",
696 ImageHandle));
697 DEBUG ((EFI_D_INFO,"Installed: gEfiComponentName2ProtocolGuid on 0x%08x\r\n",
698 ImageHandle ));
699
700 }
701 return Status;
702 }