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 } 703