]> git.proxmox.com Git - mirror_edk2.git/blob - OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772/DriverBinding.c
794b87e7f341227ed8d736f709766909bbac4f90
[mirror_edk2.git] / OptionRomPkg / Bus / Usb / UsbNetworking / Ax88772 / DriverBinding.c
1 /** @file
2 Implement the driver binding protocol for Asix AX88772 Ethernet driver.
3
4 Copyright (c) 2011, 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_LOADED_IMAGE_PROTOCOL * pLoadedImage;
485 EFI_STATUS Status;
486
487 DBG_ENTER ( );
488
489 //
490 // Enable unload support
491 //
492 Status = gBS->HandleProtocol (
493 gImageHandle,
494 &gEfiLoadedImageProtocolGuid,
495 (VOID **)&pLoadedImage
496 );
497 if (!EFI_ERROR (Status)) {
498 pLoadedImage->Unload = DriverUnload;
499 }
500
501 //
502 // Add the driver to the list of drivers
503 //
504 Status = EfiLibInstallDriverBindingComponentName2 (
505 ImageHandle,
506 pSystemTable,
507 &gDriverBinding,
508 ImageHandle,
509 &gComponentName,
510 &gComponentName2
511 );
512 ASSERT_EFI_ERROR (Status);
513 if ( !EFI_ERROR ( Status )) {
514 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
515 "Installed: gEfiDriverBindingProtocolGuid on 0x%08x\r\n",
516 ImageHandle ));
517 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
518 "Installed: gEfiComponentNameProtocolGuid on 0x%08x\r\n",
519 ImageHandle ));
520 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
521 "Installed: gEfiComponentName2ProtocolGuid on 0x%08x\r\n",
522 ImageHandle ));
523 }
524 DBG_EXIT_STATUS ( Status );
525 return Status;
526 }