1 /* $NetBSD: efinet.c,v 1.5 2009/03/18 17:06:45 cegger Exp $ */
4 * Copyright (c) 2001 Doug Rabson
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 /* __FBSDID("$FreeBSD: src/sys/boot/efi/libefi/efinet.c,v 1.6 2004/01/04 23:28:16 obrien Exp $"); */
32 #include <sys/param.h>
33 #include <netinet/in.h>
34 #include <netinet/in_systm.h>
36 #include <lib/libsa/stand.h>
43 extern struct netif_driver efi_net
;
47 dump_mode(EFI_SIMPLE_NETWORK_MODE
*mode
)
51 printf("State = %x\n", mode
->State
);
52 printf("HwAddressSize = %u\n", mode
->HwAddressSize
);
53 printf("MediaHeaderSize = %u\n", mode
->MediaHeaderSize
);
54 printf("MaxPacketSize = %u\n", mode
->MaxPacketSize
);
55 printf("NvRamSize = %u\n", mode
->NvRamSize
);
56 printf("NvRamAccessSize = %u\n", mode
->NvRamAccessSize
);
57 printf("ReceiveFilterMask = %x\n", mode
->ReceiveFilterMask
);
58 printf("ReceiveFilterSetting = %u\n", mode
->ReceiveFilterSetting
);
59 printf("MaxMCastFilterCount = %u\n", mode
->MaxMCastFilterCount
);
60 printf("MCastFilterCount = %u\n", mode
->MCastFilterCount
);
61 printf("MCastFilter = {");
62 for (i
= 0; i
< mode
->MCastFilterCount
; i
++)
63 printf(" %s", ether_sprintf(mode
->MCastFilter
[i
].Addr
));
65 printf("CurrentAddress = %s\n",
66 ether_sprintf(mode
->CurrentAddress
.Addr
));
67 printf("BroadcastAddress = %s\n",
68 ether_sprintf(mode
->BroadcastAddress
.Addr
));
69 printf("PermanentAddress = %s\n",
70 ether_sprintf(mode
->PermanentAddress
.Addr
));
71 printf("IfType = %u\n", mode
->IfType
);
72 printf("MacAddressChangeable = %d\n", mode
->MacAddressChangeable
);
73 printf("MultipleTxSupported = %d\n", mode
->MultipleTxSupported
);
74 printf("MediaPresentSupported = %d\n", mode
->MediaPresentSupported
);
75 printf("MediaPresent = %d\n", mode
->MediaPresent
);
80 efinet_match(struct netif
*nif
, void *machdep_hint
)
87 efinet_probe(struct netif
*nif
, void *machdep_hint
)
94 efinet_put(struct iodesc
*desc
, void *pkt
, size_t len
)
96 struct netif
*nif
= desc
->io_netif
;
97 EFI_SIMPLE_NETWORK
*net
;
101 net
= nif
->nif_devdata
;
103 status
= net
->Transmit(net
, 0, len
, pkt
, 0, 0, 0);
104 if (status
!= EFI_SUCCESS
)
107 /* Wait for the buffer to be transmitted */
109 buf
= 0; /* XXX Is this needed? */
110 status
= net
->GetStatus(net
, 0, &buf
);
112 * XXX EFI1.1 and the E1000 card returns a different
113 * address than we gave. Sigh.
115 } while (status
== EFI_SUCCESS
&& buf
== 0);
117 /* XXX How do we deal with status != EFI_SUCCESS now? */
118 return (status
== EFI_SUCCESS
) ? len
: -1;
123 efinet_get(struct iodesc
*desc
, void *pkt
, size_t len
, time_t timeout
)
125 struct netif
*nif
= desc
->io_netif
;
126 EFI_SIMPLE_NETWORK
*net
;
132 net
= nif
->nif_devdata
;
135 while ((time(0) - t
) < timeout
) {
137 status
= net
->Receive(net
, 0, &bufsz
, buf
, 0, 0, 0);
138 if (status
== EFI_SUCCESS
) {
140 * XXX EFI1.1 and the E1000 card trash our
141 * workspace if we do not do this silly copy.
142 * Either they are not respecting the len
143 * value or do not like the alignment.
147 memcpy(pkt
, buf
, bufsz
);
150 if (status
!= EFI_NOT_READY
)
158 efinet_init(struct iodesc
*desc
, void *machdep_hint
)
160 struct netif
*nif
= desc
->io_netif
;
161 EFI_SIMPLE_NETWORK
*net
;
164 net
= nif
->nif_driver
->netif_ifs
[nif
->nif_unit
].dif_private
;
165 nif
->nif_devdata
= net
;
167 if (net
->Mode
->State
== EfiSimpleNetworkStopped
) {
168 status
= net
->Start(net
);
169 if (status
!= EFI_SUCCESS
) {
170 printf("net%d: cannot start interface (status=%ld)\n",
171 nif
->nif_unit
, status
);
176 if (net
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
177 status
= net
->Initialize(net
, 0, 0);
178 if (status
!= EFI_SUCCESS
) {
179 printf("net%d: cannot init. interface (status=%ld)\n",
180 nif
->nif_unit
, status
);
185 if (net
->Mode
->ReceiveFilterSetting
== 0) {
186 UINT32 mask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
187 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
189 status
= net
->ReceiveFilters(net
, mask
, 0, FALSE
, 0, 0);
190 if (status
!= EFI_SUCCESS
) {
191 printf("net%d: cannot set rx. filters (status=%ld)\n",
192 nif
->nif_unit
, status
);
198 dump_mode(net
->Mode
);
201 memcpy(desc
->myea
, net
->Mode
->CurrentAddress
.Addr
, 6);
208 efinet_init_driver(void)
212 static EFI_GUID netid
= EFI_SIMPLE_NETWORK_PROTOCOL
;
215 #define MAX_INTERFACES 4
216 static struct netif_dif difs
[MAX_INTERFACES
];
217 static struct netif_stats stats
[MAX_INTERFACES
];
220 status
= BS
->LocateHandle(ByProtocol
, &netid
, 0, &sz
, 0);
221 if (status
!= EFI_BUFFER_TOO_SMALL
)
223 handles
= (EFI_HANDLE
*) alloc(sz
);
224 status
= BS
->LocateHandle(ByProtocol
, &netid
, 0, &sz
, handles
);
225 if (EFI_ERROR(status
)) {
230 nifs
= sz
/ sizeof(EFI_HANDLE
);
231 if (nifs
> MAX_INTERFACES
)
232 nifs
= MAX_INTERFACES
;
234 efi_net
.netif_nifs
= nifs
;
235 efi_net
.netif_ifs
= difs
;
237 memset(stats
, 0, sizeof(stats
));
238 for (i
= 0; i
< nifs
; i
++) {
239 struct netif_dif
*dif
= &efi_net
.netif_ifs
[i
];
242 dif
->dif_stats
= &stats
[i
];
244 BS
->HandleProtocol(handles
[i
], &netid
,
245 (VOID
**) &dif
->dif_private
);
252 efinet_end(struct netif
*nif
)
254 EFI_SIMPLE_NETWORK
*net
= nif
->nif_devdata
;
259 struct netif_driver efi_net
= {
260 "net", /* netif_bname */
261 efinet_match
, /* netif_match */
262 efinet_probe
, /* netif_probe */
263 efinet_init
, /* netif_init */
264 efinet_get
, /* netif_get */
265 efinet_put
, /* netif_put */
266 efinet_end
, /* netif_end */