2 * Copyright (c) 2001 Doug Rabson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/sys/boot/efi/libefi/efinet.c,v 1.5 2002/07/20 03:52:18 peter Exp $
27 * $DragonFly: src/sys/boot/efi/libefi/efinet.c,v 1.1 2003/11/10 06:08:33 dillon Exp $
30 #include <sys/param.h>
31 #include <netinet/in.h>
32 #include <netinet/in_systm.h>
41 extern struct netif_driver efi_net
;
45 dump_mode(EFI_SIMPLE_NETWORK_MODE
*mode
)
49 printf("State = %x\n", mode
->State
);
50 printf("HwAddressSize = %u\n", mode
->HwAddressSize
);
51 printf("MediaHeaderSize = %u\n", mode
->MediaHeaderSize
);
52 printf("MaxPacketSize = %u\n", mode
->MaxPacketSize
);
53 printf("NvRamSize = %u\n", mode
->NvRamSize
);
54 printf("NvRamAccessSize = %u\n", mode
->NvRamAccessSize
);
55 printf("ReceiveFilterMask = %x\n", mode
->ReceiveFilterMask
);
56 printf("ReceiveFilterSetting = %u\n", mode
->ReceiveFilterSetting
);
57 printf("MaxMCastFilterCount = %u\n", mode
->MaxMCastFilterCount
);
58 printf("MCastFilterCount = %u\n", mode
->MCastFilterCount
);
59 printf("MCastFilter = {");
60 for (i
= 0; i
< mode
->MCastFilterCount
; i
++)
61 printf(" %s", ether_sprintf(mode
->MCastFilter
[i
].Addr
));
63 printf("CurrentAddress = %s\n",
64 ether_sprintf(mode
->CurrentAddress
.Addr
));
65 printf("BroadcastAddress = %s\n",
66 ether_sprintf(mode
->BroadcastAddress
.Addr
));
67 printf("PermanentAddress = %s\n",
68 ether_sprintf(mode
->PermanentAddress
.Addr
));
69 printf("IfType = %u\n", mode
->IfType
);
70 printf("MacAddressChangeable = %d\n", mode
->MacAddressChangeable
);
71 printf("MultipleTxSupported = %d\n", mode
->MultipleTxSupported
);
72 printf("MediaPresentSupported = %d\n", mode
->MediaPresentSupported
);
73 printf("MediaPresent = %d\n", mode
->MediaPresent
);
78 efinet_match(struct netif
*nif
, void *machdep_hint
)
85 efinet_probe(struct netif
*nif
, void *machdep_hint
)
92 efinet_put(struct iodesc
*desc
, void *pkt
, size_t len
)
94 struct netif
*nif
= desc
->io_netif
;
95 EFI_SIMPLE_NETWORK
*net
;
99 net
= nif
->nif_devdata
;
101 status
= net
->Transmit(net
, 0, len
, pkt
, 0, 0, 0);
102 if (status
!= EFI_SUCCESS
)
105 /* Wait for the buffer to be transmitted */
107 buf
= 0; /* XXX Is this needed? */
108 status
= net
->GetStatus(net
, 0, &buf
);
110 * XXX EFI1.1 and the E1000 card returns a different
111 * address than we gave. Sigh.
113 } while (status
== EFI_SUCCESS
&& buf
== 0);
115 /* XXX How do we deal with status != EFI_SUCCESS now? */
116 return (status
== EFI_SUCCESS
) ? len
: -1;
121 efinet_get(struct iodesc
*desc
, void *pkt
, size_t len
, time_t timeout
)
123 struct netif
*nif
= desc
->io_netif
;
124 EFI_SIMPLE_NETWORK
*net
;
130 net
= nif
->nif_devdata
;
133 while ((time(0) - t
) < timeout
) {
135 status
= net
->Receive(net
, 0, &bufsz
, buf
, 0, 0, 0);
136 if (status
== EFI_SUCCESS
) {
138 * XXX EFI1.1 and the E1000 card trash our
139 * workspace if we do not do this silly copy.
140 * Either they are not respecting the len
141 * value or do not like the alignment.
145 bcopy(buf
, pkt
, bufsz
);
148 if (status
!= EFI_NOT_READY
)
156 efinet_init(struct iodesc
*desc
, void *machdep_hint
)
158 struct netif
*nif
= desc
->io_netif
;
159 EFI_SIMPLE_NETWORK
*net
;
162 net
= nif
->nif_driver
->netif_ifs
[nif
->nif_unit
].dif_private
;
163 nif
->nif_devdata
= net
;
165 if (net
->Mode
->State
== EfiSimpleNetworkStopped
) {
166 status
= net
->Start(net
);
167 if (status
!= EFI_SUCCESS
) {
168 printf("net%d: cannot start interface (status=%ld)\n",
169 nif
->nif_unit
, status
);
174 if (net
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
175 status
= net
->Initialize(net
, 0, 0);
176 if (status
!= EFI_SUCCESS
) {
177 printf("net%d: cannot init. interface (status=%ld)\n",
178 nif
->nif_unit
, status
);
183 if (net
->Mode
->ReceiveFilterSetting
== 0) {
184 UINT32 mask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
185 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
187 status
= net
->ReceiveFilters(net
, mask
, 0, FALSE
, 0, 0);
188 if (status
!= EFI_SUCCESS
) {
189 printf("net%d: cannot set rx. filters (status=%ld)\n",
190 nif
->nif_unit
, status
);
196 dump_mode(net
->Mode
);
199 bcopy(net
->Mode
->CurrentAddress
.Addr
, desc
->myea
, 6);
210 static EFI_GUID netid
= EFI_SIMPLE_NETWORK_PROTOCOL
;
213 #define MAX_INTERFACES 4
214 static struct netif_dif difs
[MAX_INTERFACES
];
215 static struct netif_stats stats
[MAX_INTERFACES
];
218 status
= BS
->LocateHandle(ByProtocol
, &netid
, 0, &sz
, 0);
219 if (status
!= EFI_BUFFER_TOO_SMALL
)
221 handles
= (EFI_HANDLE
*) malloc(sz
);
222 status
= BS
->LocateHandle(ByProtocol
, &netid
, 0, &sz
, handles
);
223 if (EFI_ERROR(status
)) {
228 nifs
= sz
/ sizeof(EFI_HANDLE
);
229 if (nifs
> MAX_INTERFACES
)
230 nifs
= MAX_INTERFACES
;
232 efi_net
.netif_nifs
= nifs
;
233 efi_net
.netif_ifs
= difs
;
235 bzero(stats
, sizeof(stats
));
236 for (i
= 0; i
< nifs
; i
++) {
237 struct netif_dif
*dif
= &efi_net
.netif_ifs
[i
];
240 dif
->dif_stats
= &stats
[i
];
242 BS
->HandleProtocol(handles
[i
], &netid
,
243 (VOID
**) &dif
->dif_private
);
250 efinet_end(struct netif
*nif
)
252 EFI_SIMPLE_NETWORK
*net
= nif
->nif_devdata
;
257 struct netif_driver efi_net
= {
258 "net", /* netif_bname */
259 efinet_match
, /* netif_match */
260 efinet_probe
, /* netif_probe */
261 efinet_init
, /* netif_init */
262 efinet_get
, /* netif_get */
263 efinet_put
, /* netif_put */
264 efinet_end
, /* netif_end */