VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/E1kNetDxe/DriverBinding.c

Last change on this file was 106066, checked in by vboxsync, 8 weeks ago

Manual copyright year updates.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.9 KB
Line 
1/** @file
2
3 Driver Binding code and its private helpers for the virtio-net driver.
4
5 Copyright (c) 2021 - 2024, Oracle and/or its affiliates.
6 Copyright (C) 2013, Red Hat, Inc.
7 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
8
9 SPDX-License-Identifier: BSD-2-Clause-Patent
10
11**/
12
13#include <IndustryStandard/Pci.h>
14#include <Library/BaseMemoryLib.h>
15#include <Library/DevicePathLib.h>
16#include <Library/MemoryAllocationLib.h>
17#include <Library/UefiBootServicesTableLib.h>
18
19#include "E1kNet.h"
20
21#define RECEIVE_FILTERS_NO_MCAST ((UINT32) ( \
22 EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | \
23 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | \
24 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS \
25 ))
26
27STATIC
28EFI_STATUS
29E1kNetEepromRead (
30 IN E1K_NET_DEV *Dev,
31 IN UINT8 Offset,
32 OUT UINT16 *Data
33 )
34{
35 EFI_STATUS Status;
36 UINT32 RegEerd = 0;
37
38 Status = E1kNetRegWrite32(Dev, E1K_REG_EERD, ((UINT32)Offset << 8) | E1K_REG_EERD_START);
39 if (EFI_ERROR (Status))
40 return Status;
41
42 // Wait for the read to complete
43 while ( !EFI_ERROR (Status)
44 && !(RegEerd & E1K_REG_EERD_DONE)) {
45 gBS->Stall(1);
46 Status = E1kNetRegRead32(Dev, E1K_REG_EERD, &RegEerd);
47 }
48
49 if (!EFI_ERROR(Status))
50 *Data = E1K_REG_EERD_DATA_GET(RegEerd);
51
52 return Status;
53}
54
55STATIC
56EFI_STATUS
57E1kNetMacAddrRead (
58 IN E1K_NET_DEV *Dev
59 )
60{
61 EFI_STATUS Status;
62 UINT8 i;
63
64 for (i = 0; i < 3; i++)
65 {
66 UINT16 MacAddr;
67 Status = E1kNetEepromRead (Dev, i, &MacAddr);
68 if (EFI_ERROR (Status))
69 return Status;
70
71 Dev->Snm.CurrentAddress.Addr[i * 2] = MacAddr & 0xff;
72 Dev->Snm.CurrentAddress.Addr[i * 2 + 1] = (MacAddr >> 8) & 0xff;
73 }
74
75 return Status;
76}
77
78/**
79 Set up the Simple Network Protocol fields, the Simple Network Mode fields,
80 and the Exit Boot Services Event of the virtio-net driver instance.
81
82 This function may only be called by E1kNetDriverBindingStart().
83
84 @param[in,out] Dev The E1K_NET_DEV driver instance being created for the
85 e1000 device.
86
87 @return Status codes from the CreateEvent().
88 @retval EFI_SUCCESS Configuration successful.
89*/
90STATIC
91EFI_STATUS
92EFIAPI
93E1kNetSnpPopulate (
94 IN OUT E1K_NET_DEV *Dev
95 )
96{
97 UINT32 RegSts;
98 EFI_STATUS Status;
99
100 //
101 // We set up a function here that is asynchronously callable by an
102 // external application to check if there are any packets available for
103 // reception. The least urgent task priority level we can specify for such a
104 // "software interrupt" is TPL_CALLBACK.
105 //
106 // TPL_CALLBACK is also the maximum TPL an SNP implementation is allowed to
107 // run at (see 6.1 Event, Timer, and Task Priority Services in the UEFI
108 // Specification 2.3.1+errC).
109 //
110 // Since we raise our TPL to TPL_CALLBACK in every single function that
111 // accesses the device, and the external application also queues its interest
112 // for received packets at the same TPL_CALLBACK, in effect the
113 // E1kNetIsPacketAvailable() function will never interrupt any
114 // device-accessing driver function, it will be scheduled in isolation.
115 //
116 // TPL_CALLBACK (which basically this entire driver runs at) is allowed
117 // for "[l]ong term operations (such as file system operations and disk
118 // I/O)". Because none of our functions block, we'd satisfy an even stronger
119 // requirement.
120 //
121 Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_CALLBACK,
122 &E1kNetIsPacketAvailable, Dev, &Dev->Snp.WaitForPacket);
123 if (EFI_ERROR (Status)) {
124 return Status;
125 }
126
127 Dev->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
128 Dev->Snp.Start = &E1kNetStart;
129 Dev->Snp.Stop = &E1kNetStop;
130 Dev->Snp.Initialize = &E1kNetInitialize;
131 Dev->Snp.Reset = &E1kNetReset;
132 Dev->Snp.Shutdown = &E1kNetShutdown;
133 Dev->Snp.ReceiveFilters = &E1kNetReceiveFilters;
134 Dev->Snp.StationAddress = &E1kNetStationAddress;
135 Dev->Snp.Statistics = &E1kNetStatistics;
136 Dev->Snp.MCastIpToMac = &E1kNetMcastIpToMac;
137 Dev->Snp.NvData = &E1kNetNvData;
138 Dev->Snp.GetStatus = &E1kNetGetStatus;
139 Dev->Snp.Transmit = &E1kNetTransmit;
140 Dev->Snp.Receive = &E1kNetReceive;
141 Dev->Snp.Mode = &Dev->Snm;
142
143 Dev->Snm.State = EfiSimpleNetworkStopped;
144 Dev->Snm.HwAddressSize = sizeof (E1K_NET_MAC);
145 Dev->Snm.MediaHeaderSize = sizeof (E1K_NET_MAC) + // dst MAC
146 sizeof (E1K_NET_MAC) + // src MAC
147 2; // Ethertype
148 Dev->Snm.MaxPacketSize = 1500;
149 Dev->Snm.NvRamSize = 0;
150 Dev->Snm.NvRamAccessSize = 0;
151 Dev->Snm.ReceiveFilterMask = RECEIVE_FILTERS_NO_MCAST;
152 Dev->Snm.ReceiveFilterSetting = RECEIVE_FILTERS_NO_MCAST;
153 Dev->Snm.MaxMCastFilterCount = 0;
154 Dev->Snm.MCastFilterCount = 0;
155 Dev->Snm.IfType = 1; // ethernet
156 Dev->Snm.MacAddressChangeable = FALSE;
157 Dev->Snm.MultipleTxSupported = TRUE;
158
159 ASSERT (sizeof (E1K_NET_MAC) <= sizeof (EFI_MAC_ADDRESS));
160
161 Dev->Snm.MediaPresentSupported = TRUE;
162 Status = E1kNetRegRead32(Dev, E1K_REG_STATUS, &RegSts);
163 if (EFI_ERROR (Status)) {
164 goto CloseWaitForPacket;
165 }
166
167 Dev->Snm.MediaPresent = (BOOLEAN)((RegSts & E1K_REG_STATUS_LU) != 0);
168
169 Status = E1kNetMacAddrRead(Dev);
170 CopyMem (&Dev->Snm.PermanentAddress, &Dev->Snm.CurrentAddress,
171 sizeof (E1K_NET_MAC));
172 SetMem (&Dev->Snm.BroadcastAddress, sizeof (E1K_NET_MAC), 0xFF);
173
174 //
175 // E1kNetExitBoot() is queued by ExitBootServices(); its purpose is to
176 // cancel any pending requests. The TPL_CALLBACK reasoning is
177 // identical to the one above. There's one difference: this kind of
178 // event is "globally visible", which means it can be signalled as soon as
179 // we create it. We haven't raised our TPL here, hence E1kNetExitBoot()
180 // could be entered immediately. E1kNetExitBoot() checks Dev->Snm.State,
181 // so we're safe.
182 //
183 Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
184 &E1kNetExitBoot, Dev, &Dev->ExitBoot);
185 if (EFI_ERROR (Status)) {
186 goto CloseWaitForPacket;
187 }
188
189 return EFI_SUCCESS;
190
191CloseWaitForPacket:
192 gBS->CloseEvent (Dev->Snp.WaitForPacket);
193 return Status;
194}
195
196
197/**
198 Release any resources allocated by E1kNetSnpPopulate().
199
200 This function may only be called by E1kNetDriverBindingStart(), when
201 rolling back a partial, failed driver instance creation, and by
202 E1kNetDriverBindingStop(), when disconnecting a virtio-net device from the
203 driver.
204
205 @param[in,out] Dev The E1K_NET_DEV driver instance being destroyed.
206*/
207STATIC
208VOID
209EFIAPI
210E1kNetSnpEvacuate (
211 IN OUT E1K_NET_DEV *Dev
212 )
213{
214 //
215 // This function runs either at TPL_CALLBACK already (from
216 // E1kNetDriverBindingStop()), or it is part of a teardown following
217 // a partial, failed construction in E1kNetDriverBindingStart(), when
218 // WaitForPacket was never accessible to the world.
219 //
220 gBS->CloseEvent (Dev->ExitBoot);
221 gBS->CloseEvent (Dev->Snp.WaitForPacket);
222}
223
224
225/**
226 Tests to see if this driver supports a given controller. If a child device is
227 provided, it further tests to see if this driver supports creating a handle
228 for the specified child device.
229
230 This function checks to see if the driver specified by This supports the
231 device specified by ControllerHandle. Drivers will typically use the device
232 path attached to ControllerHandle and/or the services from the bus I/O
233 abstraction attached to ControllerHandle to determine if the driver supports
234 ControllerHandle. This function may be called many times during platform
235 initialization. In order to reduce boot times, the tests performed by this
236 function must be very small, and take as little time as possible to execute.
237 This function must not change the state of any hardware devices, and this
238 function must be aware that the device specified by ControllerHandle may
239 already be managed by the same driver or a different driver. This function
240 must match its calls to AllocatePages() with FreePages(), AllocatePool() with
241 FreePool(), and OpenProtocol() with CloseProtocol(). Because ControllerHandle
242 may have been previously started by the same driver, if a protocol is already
243 in the opened state, then it must not be closed with CloseProtocol(). This is
244 required to guarantee the state of ControllerHandle is not modified by this
245 function.
246
247 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
248 instance.
249 @param[in] ControllerHandle The handle of the controller to test. This
250 handle must support a protocol interface
251 that supplies an I/O abstraction to the
252 driver.
253 @param[in] RemainingDevicePath A pointer to the remaining portion of a
254 device path. This parameter is ignored by
255 device drivers, and is optional for bus
256 drivers. For bus drivers, if this parameter
257 is not NULL, then the bus driver must
258 determine if the bus controller specified by
259 ControllerHandle and the child controller
260 specified by RemainingDevicePath are both
261 supported by this bus driver.
262
263 @retval EFI_SUCCESS The device specified by ControllerHandle and
264 RemainingDevicePath is supported by the
265 driver specified by This.
266 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
267 RemainingDevicePath is already being managed
268 by the driver specified by This.
269 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
270 RemainingDevicePath is already being managed
271 by a different driver or an application that
272 requires exclusive access. Currently not
273 implemented.
274 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
275 RemainingDevicePath is not supported by the
276 driver specified by This.
277**/
278
279STATIC
280EFI_STATUS
281EFIAPI
282E1kNetDriverBindingSupported (
283 IN EFI_DRIVER_BINDING_PROTOCOL *This,
284 IN EFI_HANDLE ControllerHandle,
285 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
286 )
287{
288 EFI_STATUS Status;
289 EFI_PCI_IO_PROTOCOL *PciIo;
290 PCI_TYPE00 Pci;
291
292 Status = gBS->OpenProtocol (
293 ControllerHandle,
294 &gEfiPciIoProtocolGuid,
295 (VOID **)&PciIo,
296 This->DriverBindingHandle,
297 ControllerHandle,
298 EFI_OPEN_PROTOCOL_BY_DRIVER
299 );
300 if (EFI_ERROR (Status)) {
301 return Status;
302 }
303
304 Status = PciIo->Pci.Read (
305 PciIo,
306 EfiPciIoWidthUint32,
307 0,
308 sizeof (Pci) / sizeof (UINT32),
309 &Pci
310 );
311 if (EFI_ERROR (Status)) {
312 goto Done;
313 }
314
315 if (Pci.Hdr.VendorId == INTEL_PCI_VENDOR_ID &&
316 (Pci.Hdr.DeviceId == INTEL_82540EM_PCI_DEVICE_ID ||
317 Pci.Hdr.DeviceId == INTEL_82543GC_PCI_DEVICE_ID ||
318 Pci.Hdr.DeviceId == INTEL_82545EM_PCI_DEVICE_ID)) {
319 Status = EFI_SUCCESS;
320 } else {
321 Status = EFI_UNSUPPORTED;
322 }
323
324Done:
325 gBS->CloseProtocol (
326 ControllerHandle,
327 &gEfiPciIoProtocolGuid,
328 This->DriverBindingHandle,
329 ControllerHandle
330 );
331 return Status;
332}
333
334
335/**
336 Starts a device controller or a bus controller.
337
338 The Start() function is designed to be invoked from the EFI boot service
339 ConnectController(). As a result, much of the error checking on the
340 parameters to Start() has been moved into this common boot service. It is
341 legal to call Start() from other locations, but the following calling
342 restrictions must be followed, or the system behavior will not be
343 deterministic.
344 1. ControllerHandle must be a valid EFI_HANDLE.
345 2. If RemainingDevicePath is not NULL, then it must be a pointer to a
346 naturally aligned EFI_DEVICE_PATH_PROTOCOL.
347 3. Prior to calling Start(), the Supported() function for the driver
348 specified by This must have been called with the same calling parameters,
349 and Supported() must have returned EFI_SUCCESS.
350
351 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
352 instance.
353 @param[in] ControllerHandle The handle of the controller to start. This
354 handle must support a protocol interface
355 that supplies an I/O abstraction to the
356 driver.
357 @param[in] RemainingDevicePath A pointer to the remaining portion of a
358 device path. This parameter is ignored by
359 device drivers, and is optional for bus
360 drivers. For a bus driver, if this parameter
361 is NULL, then handles for all the children
362 of Controller are created by this driver.
363 If this parameter is not NULL and the first
364 Device Path Node is not the End of Device
365 Path Node, then only the handle for the
366 child device specified by the first Device
367 Path Node of RemainingDevicePath is created
368 by this driver. If the first Device Path
369 Node of RemainingDevicePath is the End of
370 Device Path Node, no child handle is created
371 by this driver.
372
373 @retval EFI_SUCCESS The device was started.
374 @retval EFI_DEVICE_ERROR The device could not be started due to a
375 device error.Currently not implemented.
376 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
377 lack of resources.
378 @retval Others The driver failed to start the device.
379
380**/
381STATIC
382EFI_STATUS
383EFIAPI
384E1kNetDriverBindingStart (
385 IN EFI_DRIVER_BINDING_PROTOCOL *This,
386 IN EFI_HANDLE ControllerHandle,
387 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
388 )
389{
390 EFI_STATUS Status;
391 E1K_NET_DEV *Dev;
392 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
393 MAC_ADDR_DEVICE_PATH MacNode;
394
395 DEBUG((DEBUG_INFO, "E1kNetControllerStart:\n"));
396
397 Dev = AllocateZeroPool (sizeof (*Dev));
398 if (Dev == NULL) {
399 return EFI_OUT_OF_RESOURCES;
400 }
401
402 Dev->Signature = E1K_NET_DEV_SIGNATURE;
403
404 Status = gBS->OpenProtocol (
405 ControllerHandle,
406 &gEfiPciIoProtocolGuid,
407 (VOID **)&Dev->PciIo,
408 This->DriverBindingHandle,
409 ControllerHandle,
410 EFI_OPEN_PROTOCOL_BY_DRIVER
411 );
412 if (EFI_ERROR (Status)) {
413 goto FreePool;
414 }
415
416 Status = Dev->PciIo->Attributes (
417 Dev->PciIo,
418 EfiPciIoAttributeOperationGet,
419 0,
420 &Dev->OriginalPciAttributes
421 );
422 if (EFI_ERROR (Status)) {
423 goto CloseProtocol;
424 }
425
426 //
427 // Enable I/O Space & Bus-Mastering
428 //
429 Status = Dev->PciIo->Attributes (
430 Dev->PciIo,
431 EfiPciIoAttributeOperationEnable,
432 (EFI_PCI_IO_ATTRIBUTE_IO |
433 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
434 NULL
435 );
436 if (EFI_ERROR (Status)) {
437 goto CloseProtocol;
438 }
439
440 //
441 // Signal device supports 64-bit DMA addresses
442 //
443 Status = Dev->PciIo->Attributes (
444 Dev->PciIo,
445 EfiPciIoAttributeOperationEnable,
446 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
447 NULL
448 );
449 if (EFI_ERROR (Status)) {
450 //
451 // Warn user that device will only be using 32-bit DMA addresses.
452 //
453 // Note that this does not prevent the device/driver from working
454 // and therefore we only warn and continue as usual.
455 //
456 DEBUG ((
457 DEBUG_WARN,
458 "%a: failed to enable 64-bit DMA addresses\n",
459 __FUNCTION__
460 ));
461 }
462
463 DEBUG((DEBUG_INFO, "E1kNetControllerStart: Resetting NIC\n"));
464 Status = E1kNetDevReset (Dev);
465 if (EFI_ERROR (Status)) {
466 goto RestoreAttributes;
467 }
468
469 //
470 // now we can run a basic one-shot e1000 initialization required to
471 // retrieve the MAC address
472 //
473 DEBUG((DEBUG_INFO, "E1kNetControllerStart: Populating SNP interface\n"));
474 Status = E1kNetSnpPopulate (Dev);
475 if (EFI_ERROR (Status)) {
476 goto UninitDev;
477 }
478
479 //
480 // get the device path of the e1000 device -- one-shot open
481 //
482 Status = gBS->OpenProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid,
483 (VOID **)&DevicePath, This->DriverBindingHandle,
484 ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
485 if (EFI_ERROR (Status)) {
486 goto Evacuate;
487 }
488
489 //
490 // create another device path that has the MAC address appended
491 //
492 MacNode.Header.Type = MESSAGING_DEVICE_PATH;
493 MacNode.Header.SubType = MSG_MAC_ADDR_DP;
494 SetDevicePathNodeLength (&MacNode, sizeof MacNode);
495 CopyMem (&MacNode.MacAddress, &Dev->Snm.CurrentAddress,
496 sizeof (EFI_MAC_ADDRESS));
497 MacNode.IfType = Dev->Snm.IfType;
498
499 Dev->MacDevicePath = AppendDevicePathNode (DevicePath, &MacNode.Header);
500 if (Dev->MacDevicePath == NULL) {
501 Status = EFI_OUT_OF_RESOURCES;
502 goto Evacuate;
503 }
504
505 //
506 // create a child handle with the Simple Network Protocol and the new
507 // device path installed on it
508 //
509 Status = gBS->InstallMultipleProtocolInterfaces (&Dev->MacHandle,
510 &gEfiSimpleNetworkProtocolGuid, &Dev->Snp,
511 &gEfiDevicePathProtocolGuid, Dev->MacDevicePath,
512 NULL);
513 if (EFI_ERROR (Status)) {
514 goto FreeMacDevicePath;
515 }
516
517 DEBUG((DEBUG_INFO, "E1kNetControllerStart: returns EFI_SUCCESS\n"));
518 return EFI_SUCCESS;
519
520FreeMacDevicePath:
521 FreePool (Dev->MacDevicePath);
522
523Evacuate:
524 E1kNetSnpEvacuate (Dev);
525
526UninitDev:
527 E1kNetDevReset (Dev);
528
529RestoreAttributes:
530 Dev->PciIo->Attributes (
531 Dev->PciIo,
532 EfiPciIoAttributeOperationSet,
533 Dev->OriginalPciAttributes,
534 NULL
535 );
536
537CloseProtocol:
538 gBS->CloseProtocol (
539 ControllerHandle,
540 &gEfiPciIoProtocolGuid,
541 This->DriverBindingHandle,
542 ControllerHandle
543 );
544
545FreePool:
546 FreePool (Dev);
547
548 DEBUG((DEBUG_INFO, "E1kNetControllerStart: returns %u\n", Status));
549 return Status;
550}
551
552/**
553 Stops a device controller or a bus controller.
554
555 The Stop() function is designed to be invoked from the EFI boot service
556 DisconnectController(). As a result, much of the error checking on the
557 parameters to Stop() has been moved into this common boot service. It is
558 legal to call Stop() from other locations, but the following calling
559 restrictions must be followed, or the system behavior will not be
560 deterministic.
561 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous
562 call to this same driver's Start() function.
563 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a
564 valid EFI_HANDLE. In addition, all of these handles must have been created
565 in this driver's Start() function, and the Start() function must have
566 called OpenProtocol() on ControllerHandle with an Attribute of
567 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
568
569 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
570 instance.
571 @param[in] ControllerHandle A handle to the device being stopped. The
572 handle must support a bus specific I/O
573 protocol for the driver to use to stop the
574 device.
575 @param[in] NumberOfChildren The number of child device handles in
576 ChildHandleBuffer.
577 @param[in] ChildHandleBuffer An array of child handles to be freed. May be
578 NULL if NumberOfChildren is 0.
579
580 @retval EFI_SUCCESS The device was stopped.
581 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device
582 error.
583
584**/
585STATIC
586EFI_STATUS
587EFIAPI
588E1kNetDriverBindingStop (
589 IN EFI_DRIVER_BINDING_PROTOCOL *This,
590 IN EFI_HANDLE ControllerHandle,
591 IN UINTN NumberOfChildren,
592 IN EFI_HANDLE *ChildHandleBuffer
593 )
594{
595 if (NumberOfChildren > 0) {
596 //
597 // free all resources for whose access we need the child handle, because
598 // the child handle is going away
599 //
600 EFI_STATUS Status;
601 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
602 E1K_NET_DEV *Dev;
603 EFI_TPL OldTpl;
604
605 ASSERT (NumberOfChildren == 1);
606
607 Status = gBS->OpenProtocol (ChildHandleBuffer[0],
608 &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp,
609 This->DriverBindingHandle, ControllerHandle,
610 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
611 ASSERT_EFI_ERROR (Status);
612 Dev = E1K_NET_FROM_SNP (Snp);
613
614 //
615 // prevent any interference with WaitForPacket
616 //
617 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
618
619 ASSERT (Dev->MacHandle == ChildHandleBuffer[0]);
620 if (Dev->Snm.State != EfiSimpleNetworkStopped) {
621 //
622 // device in use, cannot stop driver instance
623 //
624 Status = EFI_DEVICE_ERROR;
625 }
626 else {
627 gBS->UninstallMultipleProtocolInterfaces (Dev->MacHandle,
628 &gEfiDevicePathProtocolGuid, Dev->MacDevicePath,
629 &gEfiSimpleNetworkProtocolGuid, &Dev->Snp,
630 NULL);
631 FreePool (Dev->MacDevicePath);
632 E1kNetSnpEvacuate (Dev);
633
634 Dev->PciIo->Attributes (
635 Dev->PciIo,
636 EfiPciIoAttributeOperationSet,
637 Dev->OriginalPciAttributes,
638 NULL
639 );
640
641 gBS->CloseProtocol (
642 ControllerHandle,
643 &gEfiPciIoProtocolGuid,
644 This->DriverBindingHandle,
645 ControllerHandle
646 );
647
648 FreePool (Dev);
649 }
650
651 gBS->RestoreTPL (OldTpl);
652 return Status;
653 }
654
655 return EFI_SUCCESS;
656}
657
658
659EFI_DRIVER_BINDING_PROTOCOL gE1kNetDriverBinding = {
660 &E1kNetDriverBindingSupported,
661 &E1kNetDriverBindingStart,
662 &E1kNetDriverBindingStop,
663 0x10,
664 NULL,
665 NULL
666};
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette