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