|
|
1.1 root 1: /*
2: * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
3: *
4: * This program is free software; you can redistribute it and/or
5: * modify it under the terms of the GNU General Public License as
6: * published by the Free Software Foundation; either version 2 of the
7: * License, or any later version.
8: *
9: * This program is distributed in the hope that it will be useful, but
10: * WITHOUT ANY WARRANTY; without even the implied warranty of
11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12: * General Public License for more details.
13: *
14: * You should have received a copy of the GNU General Public License
15: * along with this program; if not, write to the Free Software
16: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17: */
18:
19: FILE_LICENCE ( GPL2_OR_LATER );
20:
21: #include <errno.h>
22: #include <string.h>
23: #include <ipxe/io.h>
24: #include <ipxe/iobuf.h>
25: #include <ipxe/netdevice.h>
26: #include <ipxe/if_ether.h>
27: #include <ipxe/ethernet.h>
28: #include <ipxe/efi/efi.h>
29: #include <ipxe/efi/Protocol/SimpleNetwork.h>
30: #include "snp.h"
31: #include "snpnet.h"
32:
33: /** @file
34: *
35: * SNP network device driver
36: *
37: */
38:
39: /** SNP net device structure */
40: struct snpnet_device {
41: /** The underlying simple network protocol */
42: EFI_SIMPLE_NETWORK_PROTOCOL *snp;
43:
44: /** State that the SNP should be in after close */
45: UINT32 close_state;
46: };
47:
48: /**
49: * Transmit packet
50: *
51: * @v netdev Network device
52: * @v iobuf I/O buffer
53: * @ret rc Return status code
54: */
55: static int snpnet_transmit ( struct net_device *netdev,
56: struct io_buffer *iobuf ) {
57: struct snpnet_device *snpnetdev = netdev->priv;
58: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
59: EFI_STATUS efirc;
60: size_t len = iob_len ( iobuf );
61:
62: efirc = snp->Transmit ( snp, 0, len, iobuf->data, NULL, NULL, NULL );
63: return EFIRC_TO_RC ( efirc );
64: }
65:
66: /**
67: * Find a I/O buffer on the list of outstanding Tx buffers and complete it.
68: *
69: * @v snpnetdev SNP network device
70: * @v txbuf Buffer address
71: */
72: static void snpnet_complete ( struct net_device *netdev, void *txbuf ) {
73: struct io_buffer *tmp;
74: struct io_buffer *iobuf;
75:
76: list_for_each_entry_safe ( iobuf, tmp, &netdev->tx_queue, list ) {
77: if ( iobuf->data == txbuf ) {
78: netdev_tx_complete ( netdev, iobuf );
79: break;
80: }
81: }
82: }
83:
84: /**
85: * Poll for received packets
86: *
87: * @v netdev Network device
88: */
89: static void snpnet_poll ( struct net_device *netdev ) {
90: struct snpnet_device *snpnetdev = netdev->priv;
91: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
92: EFI_STATUS efirc;
93: struct io_buffer *iobuf = NULL;
94: UINTN len;
95: void *txbuf;
96:
97: /* Process Tx completions */
98: while ( 1 ) {
99: efirc = snp->GetStatus ( snp, NULL, &txbuf );
100: if ( efirc ) {
101: DBGC ( snp, "SNP %p could not get status %s\n", snp,
102: efi_strerror ( efirc ) );
103: break;
104: }
105:
106: if ( txbuf == NULL )
107: break;
108:
109: snpnet_complete ( netdev, txbuf );
110: }
111:
112: /* Process received packets */
113: while ( 1 ) {
114: /* The spec is not clear if the max packet size refers to the
115: * payload or the entire packet including headers. The Receive
116: * function needs a buffer large enough to contain the headers,
117: * and potentially a 4-byte CRC and 4-byte VLAN tag (?), so add
118: * some breathing room.
119: */
120: len = snp->Mode->MaxPacketSize + ETH_HLEN + 8;
121: iobuf = alloc_iob ( len );
122: if ( iobuf == NULL ) {
123: netdev_rx_err ( netdev, NULL, -ENOMEM );
124: break;
125: }
126:
127: efirc = snp->Receive ( snp, NULL, &len, iobuf->data,
128: NULL, NULL, NULL );
129:
130: /* No packets left? */
131: if ( efirc == EFI_NOT_READY ) {
132: free_iob ( iobuf );
133: break;
134: }
135:
136: /* Other error? */
137: if ( efirc ) {
138: DBGC ( snp, "SNP %p receive packet error: %s "
139: "(len was %zd, is now %zd)\n",
140: snp, efi_strerror ( efirc ), iob_len(iobuf),
141: (size_t)len );
142: netdev_rx_err ( netdev, iobuf, efirc );
143: break;
144: }
145:
146: /* Packet is valid, deliver it */
147: iob_put ( iobuf, len );
148: netdev_rx ( netdev, iob_disown ( iobuf ) );
149: }
150: }
151:
152: /**
153: * Open NIC
154: *
155: * @v netdev Net device
156: * @ret rc Return status code
157: */
158: static int snpnet_open ( struct net_device *netdev ) {
159: struct snpnet_device *snpnetdev = netdev->priv;
160: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
161: EFI_STATUS efirc;
162: UINT32 enableFlags, disableFlags;
163:
164: snpnetdev->close_state = snp->Mode->State;
165: if ( snp->Mode->State != EfiSimpleNetworkInitialized ) {
166: efirc = snp->Initialize ( snp, 0, 0 );
167: if ( efirc ) {
168: DBGC ( snp, "SNP %p could not initialize: %s\n",
169: snp, efi_strerror ( efirc ) );
170: return EFIRC_TO_RC ( efirc );
171: }
172: }
173:
174: /* Use the default MAC address */
175: efirc = snp->StationAddress ( snp, FALSE,
176: (EFI_MAC_ADDRESS *)netdev->ll_addr );
177: if ( efirc ) {
178: DBGC ( snp, "SNP %p could not reset station address: %s\n",
179: snp, efi_strerror ( efirc ) );
180: }
181:
182: /* Set up receive filters to receive unicast and broadcast packets
183: * always. Also, enable either promiscuous multicast (if possible) or
184: * promiscuous operation, in order to catch all multicast packets.
185: */
186: enableFlags = snp->Mode->ReceiveFilterMask &
187: ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
188: EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST );
189: disableFlags = snp->Mode->ReceiveFilterMask &
190: ( EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
191: EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
192: EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST );
193: if ( snp->Mode->ReceiveFilterMask &
194: EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST ) {
195: enableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
196: } else if ( snp->Mode->ReceiveFilterMask &
197: EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS ) {
198: enableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
199: }
200: disableFlags &= ~enableFlags;
201: efirc = snp->ReceiveFilters ( snp, enableFlags, disableFlags,
202: FALSE, 0, NULL );
203: if ( efirc ) {
204: DBGC ( snp, "SNP %p could not set receive filters: %s\n",
205: snp, efi_strerror ( efirc ) );
206: }
207:
208: DBGC ( snp, "SNP %p opened\n", snp );
209: return 0;
210: }
211:
212: /**
213: * Close NIC
214: *
215: * @v netdev Net device
216: */
217: static void snpnet_close ( struct net_device *netdev ) {
218: struct snpnet_device *snpnetdev = netdev->priv;
219: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
220: EFI_STATUS efirc;
221:
222: if ( snpnetdev->close_state != EfiSimpleNetworkInitialized ) {
223: efirc = snp->Shutdown ( snp );
224: if ( efirc ) {
225: DBGC ( snp, "SNP %p could not shut down: %s\n",
226: snp, efi_strerror ( efirc ) );
227: }
228: }
229: }
230:
231: /**
232: * Enable/disable interrupts
233: *
234: * @v netdev Net device
235: * @v enable Interrupts should be enabled
236: */
237: static void snpnet_irq ( struct net_device *netdev, int enable ) {
238: struct snpnet_device *snpnetdev = netdev->priv;
239: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
240:
241: /* On EFI, interrupts are never necessary. (This function is only
242: * required for BIOS PXE.) If interrupts were required, they could be
243: * simulated using a fast timer.
244: */
245: DBGC ( snp, "SNP %p cannot %s interrupts\n",
246: snp, ( enable ? "enable" : "disable" ) );
247: }
248:
249: /** SNP network device operations */
250: static struct net_device_operations snpnet_operations = {
251: .open = snpnet_open,
252: .close = snpnet_close,
253: .transmit = snpnet_transmit,
254: .poll = snpnet_poll,
255: .irq = snpnet_irq,
256: };
257:
258: /**
259: * Probe SNP device
260: *
261: * @v snpdev SNP device
262: * @ret rc Return status code
263: */
264: int snpnet_probe ( struct snp_device *snpdev ) {
265: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpdev->snp;
266: EFI_STATUS efirc;
267: struct net_device *netdev;
268: struct snpnet_device *snpnetdev;
269: int rc;
270:
271: DBGC ( snp, "SNP %p probing...\n", snp );
272:
273: /* Allocate net device */
274: netdev = alloc_etherdev ( sizeof ( struct snpnet_device ) );
275: if ( ! netdev )
276: return -ENOMEM;
277: netdev_init ( netdev, &snpnet_operations );
278: netdev->dev = &snpdev->dev;
279: snpdev->netdev = netdev;
280: snpnetdev = netdev->priv;
281: snpnetdev->snp = snp;
282: snpdev->removal_state = snp->Mode->State;
283:
284: /* Start the interface */
285: if ( snp->Mode->State == EfiSimpleNetworkStopped ) {
286: efirc = snp->Start ( snp );
287: if ( efirc ) {
288: DBGC ( snp, "SNP %p could not start: %s\n", snp,
289: efi_strerror ( efirc ) );
290: rc = EFIRC_TO_RC ( efirc );
291: goto err_start;
292: }
293: }
294:
295: if ( snp->Mode->HwAddressSize > sizeof ( netdev->hw_addr ) ) {
296: DBGC ( snp, "SNP %p hardware address is too large\n", snp );
297: rc = -EINVAL;
298: goto err_hwaddr;
299: }
300: memcpy ( netdev->hw_addr, snp->Mode->PermanentAddress.Addr,
301: snp->Mode->HwAddressSize );
302:
303: /* Register network device */
304: if ( ( rc = register_netdev ( netdev ) ) != 0 )
305: goto err_register;
306:
307: /* Mark as link up; we don't handle link state */
308: netdev_link_up ( netdev );
309:
310: DBGC ( snp, "SNP %p added\n", snp );
311: return 0;
312:
313: err_register:
314: err_hwaddr:
315: if ( snpdev->removal_state == EfiSimpleNetworkStopped )
316: snp->Stop ( snp );
317:
318: err_start:
319: netdev_nullify ( netdev );
320: netdev_put ( netdev );
321: snpdev->netdev = NULL;
322: return rc;
323: }
324:
325: /**
326: * Remove SNP device
327: *
328: * @v snpdev SNP device
329: */
330: void snpnet_remove ( struct snp_device *snpdev ) {
331: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpdev->snp;
332: EFI_STATUS efirc;
333: struct net_device *netdev = snpdev->netdev;
334:
335: if ( snp->Mode->State == EfiSimpleNetworkInitialized &&
336: snpdev->removal_state != EfiSimpleNetworkInitialized ) {
337: DBGC ( snp, "SNP %p shutting down\n", snp );
338: efirc = snp->Shutdown ( snp );
339: if ( efirc ) {
340: DBGC ( snp, "SNP %p could not shut down: %s\n",
341: snp, efi_strerror ( efirc ) );
342: }
343: }
344:
345: if ( snp->Mode->State == EfiSimpleNetworkStarted &&
346: snpdev->removal_state == EfiSimpleNetworkStopped ) {
347: DBGC ( snp, "SNP %p stopping\n", snp );
348: efirc = snp->Stop ( snp );
349: if ( efirc ) {
350: DBGC ( snp, "SNP %p could not be stopped\n", snp );
351: }
352: }
353:
354: /* Unregister net device */
355: unregister_netdev ( netdev );
356:
357: /* Free network device */
358: netdev_nullify ( netdev );
359: netdev_put ( netdev );
360:
361: DBGC ( snp, "SNP %p removed\n", snp );
362: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.