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