1 /** @file 2 Implement the driver binding protocol for Asix AX88772 Ethernet driver. 3 4 Copyright (c) 2011-2013, Intel Corporation. All rights reserved.<BR> 5 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 // 41 // Connect to the USB stack 42 // 43 Status = gBS->OpenProtocol ( 44 Controller, 45 &gEfiUsbIoProtocolGuid, 46 (VOID **) &pUsbIo, 47 pThis->DriverBindingHandle, 48 Controller, 49 EFI_OPEN_PROTOCOL_BY_DRIVER 50 ); 51 if (!EFI_ERROR ( Status )) { 52 53 // 54 // Get the interface descriptor to check the USB class and find a transport 55 // protocol handler. 56 // 57 Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device ); 58 if (!EFI_ERROR ( Status )) { 59 60 // 61 // Validate the adapter 62 // 63 if (( VENDOR_ID != Device.IdVendor ) 64 || ( PRODUCT_ID != Device.IdProduct )) { 65 Status = EFI_UNSUPPORTED; 66 } 67 } 68 69 // 70 // Done with the USB stack 71 // 72 gBS->CloseProtocol ( 73 Controller, 74 &gEfiUsbIoProtocolGuid, 75 pThis->DriverBindingHandle, 76 Controller 77 ); 78 } 79 80 // 81 // Return the device supported status 82 // 83 return Status; 84 } 85 86 87 /** 88 Start this driver on Controller by opening UsbIo and DevicePath protocols. 89 Initialize PXE structures, create a copy of the Controller Device Path with the 90 NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol 91 on the newly created Device Path. 92 93 @param [in] pThis Protocol instance pointer. 94 @param [in] Controller Handle of device to work with. 95 @param [in] pRemainingDevicePath Not used, always produce all possible children. 96 97 @retval EFI_SUCCESS This driver is added to Controller. 98 @retval other This driver does not support this device. 99 100 **/ 101 EFI_STATUS 102 EFIAPI 103 DriverStart ( 104 IN EFI_DRIVER_BINDING_PROTOCOL * pThis, 105 IN EFI_HANDLE Controller, 106 IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath 107 ) 108 { 109 EFI_STATUS Status; 110 NIC_DEVICE * pNicDevice; 111 UINTN LengthInBytes; 112 113 DBG_ENTER ( ); 114 115 // 116 // Allocate the device structure 117 // 118 LengthInBytes = sizeof ( *pNicDevice ); 119 Status = gBS->AllocatePool ( 120 EfiRuntimeServicesData, 121 LengthInBytes, 122 (VOID **) &pNicDevice 123 ); 124 if ( !EFI_ERROR ( Status )) { 125 DEBUG (( DEBUG_POOL | DEBUG_INIT, 126 "0x%08x: Allocate pNicDevice, %d bytes\r\n", 127 pNicDevice, 128 sizeof ( *pNicDevice ))); 129 130 // 131 // Set the structure signature 132 // 133 ZeroMem ( pNicDevice, LengthInBytes ); 134 pNicDevice->Signature = DEV_SIGNATURE; 135 136 // 137 // Connect to the USB I/O protocol 138 // 139 Status = gBS->OpenProtocol ( 140 Controller, 141 &gEfiUsbIoProtocolGuid, 142 (VOID **) &pNicDevice->pUsbIo, 143 pThis->DriverBindingHandle, 144 Controller, 145 EFI_OPEN_PROTOCOL_BY_DRIVER 146 ); 147 148 if ( !EFI_ERROR ( Status )) { 149 // 150 // Allocate the necessary events 151 // 152 Status = gBS->CreateEvent ( EVT_TIMER, 153 TPL_AX88772, 154 (EFI_EVENT_NOTIFY)Ax88772Timer, 155 pNicDevice, 156 (VOID **)&pNicDevice->Timer ); 157 if ( !EFI_ERROR ( Status )) { 158 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, 159 "0x%08x: Allocated timer\r\n", 160 pNicDevice->Timer )); 161 162 // 163 // Initialize the simple network protocol 164 // 165 pNicDevice->Controller = Controller; 166 SN_Setup ( pNicDevice ); 167 168 // 169 // Start the timer 170 // 171 Status = gBS->SetTimer ( pNicDevice->Timer, 172 TimerPeriodic, 173 TIMER_MSEC ); 174 if ( !EFI_ERROR ( Status )) { 175 // 176 // Install both the simple network and device path protocols. 177 // 178 Status = gBS->InstallMultipleProtocolInterfaces ( 179 &Controller, 180 &gEfiCallerIdGuid, 181 pNicDevice, 182 &gEfiSimpleNetworkProtocolGuid, 183 &pNicDevice->SimpleNetwork, 184 NULL 185 ); 186 187 if ( !EFI_ERROR ( Status )) { 188 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, 189 "Installed: gEfiCallerIdGuid on 0x%08x\r\n", 190 Controller )); 191 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, 192 "Installed: gEfiSimpleNetworkProtocolGuid on 0x%08x\r\n", 193 Controller )); 194 DBG_EXIT_STATUS ( Status ); 195 return Status; 196 } 197 DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO, 198 "ERROR - Failed to install gEfiSimpleNetworkProtocol on 0x%08x\r\n", 199 Controller )); 200 } 201 else { 202 DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO, 203 "ERROR - Failed to start the timer, Status: %r\r\n", 204 Status )); 205 } 206 } 207 else { 208 DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO, 209 "ERROR - Failed to create timer event, Status: %r\r\n", 210 Status )); 211 } 212 213 // 214 // Done with the USB stack 215 // 216 gBS->CloseProtocol ( 217 Controller, 218 &gEfiUsbIoProtocolGuid, 219 pThis->DriverBindingHandle, 220 Controller 221 ); 222 } 223 224 // 225 // Done with the device 226 // 227 gBS->FreePool ( pNicDevice ); 228 } 229 230 // 231 // Display the driver start status 232 // 233 DBG_EXIT_STATUS ( Status ); 234 return Status; 235 } 236 237 238 /** 239 Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and 240 closing the DevicePath and PciIo protocols on Controller. 241 242 @param [in] pThis Protocol instance pointer. 243 @param [in] Controller Handle of device to stop driver on. 244 @param [in] NumberOfChildren How many children need to be stopped. 245 @param [in] pChildHandleBuffer Not used. 246 247 @retval EFI_SUCCESS This driver is removed Controller. 248 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. 249 @retval other This driver was not removed from this device. 250 251 **/ 252 EFI_STATUS 253 EFIAPI 254 DriverStop ( 255 IN EFI_DRIVER_BINDING_PROTOCOL * pThis, 256 IN EFI_HANDLE Controller, 257 IN UINTN NumberOfChildren, 258 IN EFI_HANDLE * pChildHandleBuffer 259 ) 260 { 261 NIC_DEVICE * pNicDevice; 262 EFI_STATUS Status; 263 264 DBG_ENTER ( ); 265 266 // 267 // Determine if this driver is already attached 268 // 269 Status = gBS->OpenProtocol ( 270 Controller, 271 &gEfiCallerIdGuid, 272 (VOID **) &pNicDevice, 273 pThis->DriverBindingHandle, 274 Controller, 275 EFI_OPEN_PROTOCOL_GET_PROTOCOL 276 ); 277 if ( !EFI_ERROR ( Status )) { 278 // 279 // AX88772 driver is no longer running on this device 280 // 281 gBS->UninstallMultipleProtocolInterfaces ( 282 Controller, 283 &gEfiSimpleNetworkProtocolGuid, 284 &pNicDevice->SimpleNetwork, 285 &gEfiCallerIdGuid, 286 pNicDevice, 287 NULL ); 288 DEBUG (( DEBUG_POOL | DEBUG_INIT, 289 "Removed: gEfiSimpleNetworkProtocolGuid from 0x%08x\r\n", 290 Controller )); 291 DEBUG (( DEBUG_POOL | DEBUG_INIT, 292 "Removed: gEfiCallerIdGuid from 0x%08x\r\n", 293 Controller )); 294 295 // 296 // Stop the timer 297 // 298 if ( NULL != pNicDevice->Timer ) { 299 gBS->SetTimer ( pNicDevice->Timer, TimerCancel, 0 ); 300 gBS->CloseEvent ( pNicDevice->Timer ); 301 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, 302 "0x%08x: Released timer\r\n", 303 pNicDevice->Timer )); 304 } 305 306 // 307 // Done with the device context 308 // 309 DEBUG (( DEBUG_POOL | DEBUG_INIT, 310 "0x%08x: Free pNicDevice, %d bytes\r\n", 311 pNicDevice, 312 sizeof ( *pNicDevice ))); 313 gBS->FreePool ( pNicDevice ); 314 } 315 316 // 317 // Return the shutdown status 318 // 319 DBG_EXIT_STATUS ( Status ); 320 return Status; 321 } 322 323 324 /** 325 Driver binding protocol declaration 326 **/ 327 EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = { 328 DriverSupported, 329 DriverStart, 330 DriverStop, 331 0xa, 332 NULL, 333 NULL 334 }; 335 336 337 /** 338 Ax88772 driver unload routine. 339 340 @param [in] ImageHandle Handle for the image. 341 342 @retval EFI_SUCCESS Image may be unloaded 343 344 **/ 345 EFI_STATUS 346 EFIAPI 347 DriverUnload ( 348 IN EFI_HANDLE ImageHandle 349 ) 350 { 351 UINTN BufferSize; 352 UINTN Index; 353 UINTN Max; 354 EFI_HANDLE * pHandle; 355 EFI_STATUS Status; 356 357 // 358 // Determine which devices are using this driver 359 // 360 BufferSize = 0; 361 pHandle = NULL; 362 Status = gBS->LocateHandle ( 363 ByProtocol, 364 &gEfiCallerIdGuid, 365 NULL, 366 &BufferSize, 367 NULL ); 368 if ( EFI_BUFFER_TOO_SMALL == Status ) { 369 for ( ; ; ) { 370 // 371 // One or more block IO devices are present 372 // 373 Status = gBS->AllocatePool ( 374 EfiRuntimeServicesData, 375 BufferSize, 376 (VOID **) &pHandle 377 ); 378 if ( EFI_ERROR ( Status )) { 379 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, 380 "Insufficient memory, failed handle buffer allocation\r\n" )); 381 break; 382 } 383 384 // 385 // Locate the block IO devices 386 // 387 Status = gBS->LocateHandle ( 388 ByProtocol, 389 &gEfiCallerIdGuid, 390 NULL, 391 &BufferSize, 392 pHandle ); 393 if ( EFI_ERROR ( Status )) { 394 // 395 // Error getting handles 396 // 397 DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO, 398 "Failure getting Telnet handles\r\n" )); 399 break; 400 } 401 402 // 403 // Remove any use of the driver 404 // 405 Max = BufferSize / sizeof ( pHandle[ 0 ]); 406 for ( Index = 0; Max > Index; Index++ ) { 407 Status = DriverStop ( &gDriverBinding, 408 pHandle[ Index ], 409 0, 410 NULL ); 411 if ( EFI_ERROR ( Status )) { 412 DEBUG (( DEBUG_WARN | DEBUG_INIT | DEBUG_INFO, 413 "WARNING - Failed to shutdown the driver on handle %08x\r\n", pHandle[ Index ])); 414 break; 415 } 416 } 417 break; 418 } 419 } 420 else { 421 if ( EFI_NOT_FOUND == Status ) { 422 // 423 // No devices were found 424 // 425 Status = EFI_SUCCESS; 426 } 427 } 428 429 // 430 // Free the handle array 431 // 432 if ( NULL != pHandle ) { 433 gBS->FreePool ( pHandle ); 434 } 435 436 // 437 // Remove the protocols installed by the EntryPoint routine. 438 // 439 if ( !EFI_ERROR ( Status )) { 440 gBS->UninstallMultipleProtocolInterfaces ( 441 ImageHandle, 442 &gEfiDriverBindingProtocolGuid, 443 &gDriverBinding, 444 &gEfiComponentNameProtocolGuid, 445 &gComponentName, 446 &gEfiComponentName2ProtocolGuid, 447 &gComponentName2, 448 NULL 449 ); 450 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, 451 "Removed: gEfiComponentName2ProtocolGuid from 0x%08x\r\n", 452 ImageHandle )); 453 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, 454 "Removed: gEfiComponentNameProtocolGuid from 0x%08x\r\n", 455 ImageHandle )); 456 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, 457 "Removed: gEfiDriverBindingProtocolGuid from 0x%08x\r\n", 458 ImageHandle )); 459 } 460 461 // 462 // Return the unload status 463 // 464 return Status; 465 } 466 467 468 /** 469 Ax88772 driver entry point. 470 471 @param [in] ImageHandle Handle for the image. 472 @param [in] pSystemTable Address of the system table. 473 474 @retval EFI_SUCCESS Image successfully loaded. 475 476 **/ 477 EFI_STATUS 478 EFIAPI 479 EntryPoint ( 480 IN EFI_HANDLE ImageHandle, 481 IN EFI_SYSTEM_TABLE * pSystemTable 482 ) 483 { 484 EFI_STATUS Status; 485 486 DBG_ENTER ( ); 487 488 // 489 // Add the driver to the list of drivers 490 // 491 Status = EfiLibInstallDriverBindingComponentName2 ( 492 ImageHandle, 493 pSystemTable, 494 &gDriverBinding, 495 ImageHandle, 496 &gComponentName, 497 &gComponentName2 498 ); 499 ASSERT_EFI_ERROR (Status); 500 if ( !EFI_ERROR ( Status )) { 501 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, 502 "Installed: gEfiDriverBindingProtocolGuid on 0x%08x\r\n", 503 ImageHandle )); 504 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, 505 "Installed: gEfiComponentNameProtocolGuid on 0x%08x\r\n", 506 ImageHandle )); 507 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, 508 "Installed: gEfiComponentName2ProtocolGuid on 0x%08x\r\n", 509 ImageHandle )); 510 } 511 DBG_EXIT_STATUS ( Status ); 512 return Status; 513 } 514