]> git.proxmox.com Git - mirror_edk2.git/blob - OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772b/DriverBinding.c
d64bc739c1aea53f4078dbc26e5c2ef6178546de
[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
128 //
129 // Allocate the device structure
130 //
131 LengthInBytes = sizeof ( *pNicDevice );
132 Status = gBS->AllocatePool (
133 EfiRuntimeServicesData,
134 LengthInBytes,
135 (VOID **) &pNicDevice
136 );
137
138 if (EFI_ERROR (Status)) {
139 DEBUG ((EFI_D_ERROR, "gBS->AllocatePool:pNicDevice ERROR Status = %r\n", Status));
140 goto EXIT;
141 }
142
143 //
144 // Set the structure signature
145 //
146 ZeroMem ( pNicDevice, LengthInBytes );
147 pNicDevice->Signature = DEV_SIGNATURE;
148
149 Status = gBS->OpenProtocol (
150 Controller,
151 &gEfiUsbIoProtocolGuid,
152 (VOID **) &pNicDevice->pUsbIo,
153 pThis->DriverBindingHandle,
154 Controller,
155 EFI_OPEN_PROTOCOL_BY_DRIVER
156 );
157
158 if (EFI_ERROR (Status)) {
159 DEBUG ((EFI_D_ERROR, "gBS->OpenProtocol:EFI_USB_IO_PROTOCOL ERROR Status = %r\n", Status));
160 gBS->FreePool ( pNicDevice );
161 goto EXIT;
162 }
163
164 //
165 // Initialize the simple network protocol
166 //
167 Status = SN_Setup ( pNicDevice );
168
169 if (EFI_ERROR(Status)){
170 DEBUG ((EFI_D_ERROR, "SN_Setup ERROR Status = %r\n", Status));
171 gBS->CloseProtocol (
172 Controller,
173 &gEfiUsbIoProtocolGuid,
174 pThis->DriverBindingHandle,
175 Controller
176 );
177 gBS->FreePool ( pNicDevice );
178 goto EXIT;
179 }
180
181 //
182 // Set Device Path
183 //
184 Status = gBS->OpenProtocol (
185 Controller,
186 &gEfiDevicePathProtocolGuid,
187 (VOID **) &ParentDevicePath,
188 pThis->DriverBindingHandle,
189 Controller,
190 EFI_OPEN_PROTOCOL_BY_DRIVER
191 );
192 if (EFI_ERROR(Status)) {
193 DEBUG ((EFI_D_ERROR, "gBS->OpenProtocol:EFI_DEVICE_PATH_PROTOCOL error. Status = %r\n",
194 Status));
195 gBS->CloseProtocol (
196 Controller,
197 &gEfiUsbIoProtocolGuid,
198 pThis->DriverBindingHandle,
199 Controller
200 );
201 gBS->FreePool ( pNicDevice );
202 goto EXIT;
203 }
204
205 ZeroMem (&MacDeviceNode, sizeof (MAC_ADDR_DEVICE_PATH));
206 MacDeviceNode.Header.Type = MESSAGING_DEVICE_PATH;
207 MacDeviceNode.Header.SubType = MSG_MAC_ADDR_DP;
208
209 SetDevicePathNodeLength (&MacDeviceNode.Header, sizeof (MAC_ADDR_DEVICE_PATH));
210
211 CopyMem (&MacDeviceNode.MacAddress,
212 &pNicDevice->SimpleNetworkData.CurrentAddress,
213 PXE_HWADDR_LEN_ETHER);
214
215 MacDeviceNode.IfType = pNicDevice->SimpleNetworkData.IfType;
216
217 pNicDevice->MyDevPath = AppendDevicePathNode (
218 ParentDevicePath,
219 (EFI_DEVICE_PATH_PROTOCOL *) &MacDeviceNode
220 );
221
222 pNicDevice->Controller = NULL;
223
224 //
225 // Install both the simple network and device path protocols.
226 //
227 Status = gBS->InstallMultipleProtocolInterfaces (
228 &pNicDevice->Controller,
229 &gEfiCallerIdGuid,
230 pNicDevice,
231 &gEfiSimpleNetworkProtocolGuid,
232 &pNicDevice->SimpleNetwork,
233 &gEfiDevicePathProtocolGuid,
234 pNicDevice->MyDevPath,
235 NULL
236 );
237
238 if (EFI_ERROR(Status)){
239 DEBUG ((EFI_D_ERROR, "gBS->InstallMultipleProtocolInterfaces error. Status = %r\n",
240 Status));
241 gBS->CloseProtocol (
242 Controller,
243 &gEfiDevicePathProtocolGuid,
244 pThis->DriverBindingHandle,
245 Controller);
246 gBS->CloseProtocol (
247 Controller,
248 &gEfiUsbIoProtocolGuid,
249 pThis->DriverBindingHandle,
250 Controller
251 );
252 gBS->FreePool ( pNicDevice );
253 goto EXIT;
254 }
255
256 //
257 // Open For Child Device
258 //
259 Status = gBS->OpenProtocol (
260 Controller,
261 &gEfiUsbIoProtocolGuid,
262 (VOID **) &pNicDevice->pUsbIo,
263 pThis->DriverBindingHandle,
264 pNicDevice->Controller,
265 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
266 );
267
268 if (EFI_ERROR(Status)){
269 gBS->UninstallMultipleProtocolInterfaces (
270 &pNicDevice->Controller,
271 &gEfiCallerIdGuid,
272 pNicDevice,
273 &gEfiSimpleNetworkProtocolGuid,
274 &pNicDevice->SimpleNetwork,
275 &gEfiDevicePathProtocolGuid,
276 pNicDevice->MyDevPath,
277 NULL
278 );
279 gBS->CloseProtocol (
280 Controller,
281 &gEfiDevicePathProtocolGuid,
282 pThis->DriverBindingHandle,
283 Controller);
284 gBS->CloseProtocol (
285 Controller,
286 &gEfiUsbIoProtocolGuid,
287 pThis->DriverBindingHandle,
288 Controller
289 );
290 gBS->FreePool ( pNicDevice );
291 }
292
293 EXIT:
294 return Status;
295
296 }
297
298 /**
299 Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
300 closing the DevicePath and PciIo protocols on Controller.
301
302 @param [in] pThis Protocol instance pointer.
303 @param [in] Controller Handle of device to stop driver on.
304 @param [in] NumberOfChildren How many children need to be stopped.
305 @param [in] pChildHandleBuffer Not used.
306
307 @retval EFI_SUCCESS This driver is removed Controller.
308 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
309 @retval other This driver was not removed from this device.
310
311 **/
312 EFI_STATUS
313 EFIAPI
314 DriverStop (
315 IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
316 IN EFI_HANDLE Controller,
317 IN UINTN NumberOfChildren,
318 IN EFI_HANDLE * ChildHandleBuffer
319 )
320 {
321 BOOLEAN AllChildrenStopped;
322 UINTN Index;
323 EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
324 EFI_STATUS Status = EFI_SUCCESS;
325 NIC_DEVICE *pNicDevice;
326
327 //
328 // Complete all outstanding transactions to Controller.
329 // Don't allow any new transaction to Controller to be started.
330 //
331 if (NumberOfChildren == 0) {
332
333 Status = gBS->OpenProtocol (
334 Controller,
335 &gEfiSimpleNetworkProtocolGuid,
336 (VOID **) &SimpleNetwork,
337 pThis->DriverBindingHandle,
338 Controller,
339 EFI_OPEN_PROTOCOL_GET_PROTOCOL
340 );
341
342 if (EFI_ERROR(Status)) {
343 //
344 // This is a 2nd type handle(multi-lun root), it needs to close devicepath
345 // and usbio protocol.
346 //
347 gBS->CloseProtocol (
348 Controller,
349 &gEfiDevicePathProtocolGuid,
350 pThis->DriverBindingHandle,
351 Controller
352 );
353 gBS->CloseProtocol (
354 Controller,
355 &gEfiUsbIoProtocolGuid,
356 pThis->DriverBindingHandle,
357 Controller
358 );
359 return EFI_SUCCESS;
360 }
361
362 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork );
363
364 Status = gBS->UninstallMultipleProtocolInterfaces (
365 Controller,
366 &gEfiCallerIdGuid,
367 pNicDevice,
368 &gEfiSimpleNetworkProtocolGuid,
369 &pNicDevice->SimpleNetwork,
370 &gEfiDevicePathProtocolGuid,
371 pNicDevice->MyDevPath,
372 NULL
373 );
374
375 if (EFI_ERROR (Status)) {
376 return Status;
377 }
378 //
379 // Close the bus driver
380 //
381 Status = gBS->CloseProtocol (
382 Controller,
383 &gEfiDevicePathProtocolGuid,
384 pThis->DriverBindingHandle,
385 Controller
386 );
387
388 if (EFI_ERROR(Status)){
389 DEBUG ((EFI_D_ERROR, "driver stop: gBS->CloseProtocol:EfiDevicePathProtocol error. Status %r\n", Status));
390 }
391
392 Status = gBS->CloseProtocol (
393 Controller,
394 &gEfiUsbIoProtocolGuid,
395 pThis->DriverBindingHandle,
396 Controller
397 );
398
399 if (EFI_ERROR(Status)){
400 DEBUG ((EFI_D_ERROR, "driver stop: gBS->CloseProtocol:EfiUsbIoProtocol error. Status %r\n", Status));
401 }
402 return EFI_SUCCESS;
403 }
404 AllChildrenStopped = TRUE;
405
406 for (Index = 0; Index < NumberOfChildren; Index++) {
407
408 Status = gBS->OpenProtocol (
409 ChildHandleBuffer[Index],
410 &gEfiSimpleNetworkProtocolGuid,
411 (VOID **) &SimpleNetwork,
412 pThis->DriverBindingHandle,
413 Controller,
414 EFI_OPEN_PROTOCOL_GET_PROTOCOL
415 );
416
417 if (EFI_ERROR (Status)) {
418 AllChildrenStopped = FALSE;
419 DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when opening SimpleNetwork\n", (UINT32)Index));
420 continue;
421 }
422
423 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork );
424
425 gBS->CloseProtocol (
426 Controller,
427 &gEfiUsbIoProtocolGuid,
428 pThis->DriverBindingHandle,
429 ChildHandleBuffer[Index]
430 );
431
432 Status = gBS->UninstallMultipleProtocolInterfaces (
433 ChildHandleBuffer[Index],
434 &gEfiCallerIdGuid,
435 pNicDevice,
436 &gEfiSimpleNetworkProtocolGuid,
437 &pNicDevice->SimpleNetwork,
438 &gEfiDevicePathProtocolGuid,
439 pNicDevice->MyDevPath,
440 NULL
441 );
442
443 if (EFI_ERROR (Status)) {
444 Status = gBS->OpenProtocol (
445 Controller,
446 &gEfiUsbIoProtocolGuid,
447 (VOID **) &pNicDevice->pUsbIo,
448 pThis->DriverBindingHandle,
449 ChildHandleBuffer[Index],
450 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
451 );
452 }
453 else {
454 int i;
455 RX_PKT * pCurr = pNicDevice->QueueHead;
456 RX_PKT * pFree;
457
458 for ( i = 0 ; i < MAX_QUEUE_SIZE ; i++) {
459 if ( NULL != pCurr ) {
460 pFree = pCurr;
461 pCurr = pCurr->pNext;
462 gBS->FreePool (pFree);
463 }
464 }
465
466 if ( NULL != pNicDevice->pRxTest)
467 gBS->FreePool (pNicDevice->pRxTest);
468
469 if ( NULL != pNicDevice->pTxTest)
470 gBS->FreePool (pNicDevice->pTxTest);
471
472 if ( NULL != pNicDevice->MyDevPath)
473 gBS->FreePool (pNicDevice->MyDevPath);
474
475 if ( NULL != pNicDevice)
476 gBS->FreePool (pNicDevice);
477 }
478 }
479
480 if (!AllChildrenStopped) {
481 return EFI_DEVICE_ERROR;
482 }
483 return EFI_SUCCESS;
484 }
485
486
487 /**
488 Driver binding protocol declaration
489 **/
490 EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
491 DriverSupported,
492 DriverStart,
493 DriverStop,
494 0xa,
495 NULL,
496 NULL
497 };
498
499
500 /**
501 Ax88772 driver unload routine.
502
503 @param [in] ImageHandle Handle for the image.
504
505 @retval EFI_SUCCESS Image may be unloaded
506
507 **/
508 EFI_STATUS
509 EFIAPI
510 DriverUnload (
511 IN EFI_HANDLE ImageHandle
512 )
513 {
514 UINTN BufferSize;
515 UINTN Index;
516 UINTN Max;
517 EFI_HANDLE * pHandle;
518 EFI_STATUS Status;
519
520 //
521 // Determine which devices are using this driver
522 //
523 BufferSize = 0;
524 pHandle = NULL;
525 Status = gBS->LocateHandle (
526 ByProtocol,
527 &gEfiCallerIdGuid,
528 NULL,
529 &BufferSize,
530 NULL );
531 if ( EFI_BUFFER_TOO_SMALL == Status ) {
532 for ( ; ; ) {
533 //
534 // One or more block IO devices are present
535 //
536 Status = gBS->AllocatePool (
537 EfiRuntimeServicesData,
538 BufferSize,
539 (VOID **) &pHandle
540 );
541 if ( EFI_ERROR ( Status )) {
542 DEBUG ((EFI_D_ERROR, "Insufficient memory, failed handle buffer allocation\r\n"));
543 break;
544 }
545
546 //
547 // Locate the block IO devices
548 //
549 Status = gBS->LocateHandle (
550 ByProtocol,
551 &gEfiCallerIdGuid,
552 NULL,
553 &BufferSize,
554 pHandle );
555 if ( EFI_ERROR ( Status )) {
556 //
557 // Error getting handles
558 //
559 break;
560 }
561
562 //
563 // Remove any use of the driver
564 //
565 Max = BufferSize / sizeof ( pHandle[ 0 ]);
566 for ( Index = 0; Max > Index; Index++ ) {
567 Status = DriverStop ( &gDriverBinding,
568 pHandle[ Index ],
569 0,
570 NULL );
571 if ( EFI_ERROR ( Status )) {
572 DEBUG ((EFI_D_ERROR, "WARNING - Failed to shutdown the driver on handle %08x\r\n", pHandle[ Index ]));
573 break;
574 }
575 }
576 break;
577 }
578 }
579 else {
580 if ( EFI_NOT_FOUND == Status ) {
581 //
582 // No devices were found
583 //
584 Status = EFI_SUCCESS;
585 }
586 }
587
588 //
589 // Free the handle array
590 //
591 if ( NULL != pHandle ) {
592 gBS->FreePool ( pHandle );
593 }
594
595 //
596 // Remove the protocols installed by the EntryPoint routine.
597 //
598 if ( !EFI_ERROR ( Status )) {
599 gBS->UninstallMultipleProtocolInterfaces (
600 ImageHandle,
601 &gEfiDriverBindingProtocolGuid,
602 &gDriverBinding,
603 &gEfiComponentNameProtocolGuid,
604 &gComponentName,
605 &gEfiComponentName2ProtocolGuid,
606 &gComponentName2,
607 NULL
608 );
609
610 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
611 "Removed: gEfiComponentName2ProtocolGuid from 0x%08x\r\n",
612 ImageHandle ));
613 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
614 "Removed: gEfiComponentNameProtocolGuid from 0x%08x\r\n",
615 ImageHandle ));
616 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
617 "Removed: gEfiDriverBindingProtocolGuid from 0x%08x\r\n",
618 ImageHandle ));
619
620 }
621
622 return Status;
623 }
624
625
626 /**
627 Ax88772 driver entry point.
628
629 @param [in] ImageHandle Handle for the image.
630 @param [in] pSystemTable Address of the system table.
631
632 @retval EFI_SUCCESS Image successfully loaded.
633
634 **/
635 EFI_STATUS
636 EFIAPI
637 EntryPoint (
638 IN EFI_HANDLE ImageHandle,
639 IN EFI_SYSTEM_TABLE * pSystemTable
640 )
641 {
642 EFI_STATUS Status;
643
644 //
645 // Add the driver to the list of drivers
646 //
647 Status = EfiLibInstallDriverBindingComponentName2 (
648 ImageHandle,
649 pSystemTable,
650 &gDriverBinding,
651 ImageHandle,
652 &gComponentName,
653 &gComponentName2
654 );
655 if ( !EFI_ERROR ( Status )) {
656 DEBUG ((EFI_D_INFO, "Installed: gEfiDriverBindingProtocolGuid on 0x%08x\r\n",
657 ImageHandle));
658 DEBUG ((EFI_D_INFO, "Installed: gEfiComponentNameProtocolGuid on 0x%08x\r\n",
659 ImageHandle));
660 DEBUG ((EFI_D_INFO,"Installed: gEfiComponentName2ProtocolGuid on 0x%08x\r\n",
661 ImageHandle ));
662
663 }
664 return Status;
665 }