Adding debian version 3.70~pre8+dfsg-1.
[syslinux-debian/hramrach.git] / gpxe / src / net / netdevice.c
blob6875b3bae9b71a5c04f76586011ce97a54c357bb
1 /*
2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <byteswap.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <gpxe/if_ether.h>
26 #include <gpxe/iobuf.h>
27 #include <gpxe/tables.h>
28 #include <gpxe/process.h>
29 #include <gpxe/init.h>
30 #include <gpxe/device.h>
31 #include <gpxe/netdevice.h>
33 /** @file
35 * Network device management
39 /** Registered network-layer protocols */
40 static struct net_protocol net_protocols[0]
41 __table_start ( struct net_protocol, net_protocols );
42 static struct net_protocol net_protocols_end[0]
43 __table_end ( struct net_protocol, net_protocols );
45 /** List of network devices */
46 struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
48 /**
49 * Transmit raw packet via network device
51 * @v netdev Network device
52 * @v iobuf I/O buffer
53 * @ret rc Return status code
55 * Transmits the packet via the specified network device. This
56 * function takes ownership of the I/O buffer.
58 int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
59 int rc;
61 DBGC ( netdev, "NETDEV %p transmitting %p (%p+%zx)\n",
62 netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
64 list_add_tail ( &iobuf->list, &netdev->tx_queue );
66 if ( ! ( netdev->state & NETDEV_OPEN ) ) {
67 rc = -ENETUNREACH;
68 goto err;
71 if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
72 goto err;
74 return 0;
76 err:
77 netdev_tx_complete_err ( netdev, iobuf, rc );
78 return rc;
81 /**
82 * Complete network transmission
84 * @v netdev Network device
85 * @v iobuf I/O buffer
86 * @v rc Packet status code
88 * The packet must currently be in the network device's TX queue.
90 void netdev_tx_complete_err ( struct net_device *netdev,
91 struct io_buffer *iobuf, int rc ) {
93 /* Update statistics counter */
94 if ( rc == 0 ) {
95 netdev->stats.tx_ok++;
96 DBGC ( netdev, "NETDEV %p transmission %p complete\n",
97 netdev, iobuf );
98 } else {
99 netdev->stats.tx_err++;
100 DBGC ( netdev, "NETDEV %p transmission %p failed: %s\n",
101 netdev, iobuf, strerror ( rc ) );
104 /* Catch data corruption as early as possible */
105 assert ( iobuf->list.next != NULL );
106 assert ( iobuf->list.prev != NULL );
108 /* Dequeue and free I/O buffer */
109 list_del ( &iobuf->list );
110 free_iob ( iobuf );
114 * Complete network transmission
116 * @v netdev Network device
117 * @v rc Packet status code
119 * Completes the oldest outstanding packet in the TX queue.
121 void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
122 struct io_buffer *iobuf;
124 list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
125 netdev_tx_complete_err ( netdev, iobuf, rc );
126 return;
131 * Flush device's transmit queue
133 * @v netdev Network device
135 static void netdev_tx_flush ( struct net_device *netdev ) {
137 /* Discard any packets in the TX queue */
138 while ( ! list_empty ( &netdev->tx_queue ) ) {
139 netdev_tx_complete_next_err ( netdev, -ECANCELED );
144 * Add packet to receive queue
146 * @v netdev Network device
147 * @v iobuf I/O buffer, or NULL
149 * The packet is added to the network device's RX queue. This
150 * function takes ownership of the I/O buffer.
152 void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
154 DBGC ( netdev, "NETDEV %p received %p (%p+%zx)\n",
155 netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
157 /* Enqueue packet */
158 list_add_tail ( &iobuf->list, &netdev->rx_queue );
160 /* Update statistics counter */
161 netdev->stats.rx_ok++;
165 * Discard received packet
167 * @v netdev Network device
168 * @v iobuf I/O buffer, or NULL
169 * @v rc Packet status code
171 * The packet is discarded and an RX error is recorded. This function
172 * takes ownership of the I/O buffer. @c iobuf may be NULL if, for
173 * example, the net device wishes to report an error due to being
174 * unable to allocate an I/O buffer.
176 void netdev_rx_err ( struct net_device *netdev,
177 struct io_buffer *iobuf, int rc ) {
179 DBGC ( netdev, "NETDEV %p failed to receive %p: %s\n",
180 netdev, iobuf, strerror ( rc ) );
182 /* Discard packet */
183 free_iob ( iobuf );
185 /* Update statistics counter */
186 netdev->stats.rx_err++;
190 * Poll for completed and received packets on network device
192 * @v netdev Network device
194 * Polls the network device for completed transmissions and received
195 * packets. Any received packets will be added to the RX packet queue
196 * via netdev_rx().
198 void netdev_poll ( struct net_device *netdev ) {
200 if ( netdev->state & NETDEV_OPEN )
201 netdev->op->poll ( netdev );
205 * Remove packet from device's receive queue
207 * @v netdev Network device
208 * @ret iobuf I/O buffer, or NULL
210 * Removes the first packet from the device's RX queue and returns it.
211 * Ownership of the packet is transferred to the caller.
213 struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
214 struct io_buffer *iobuf;
216 list_for_each_entry ( iobuf, &netdev->rx_queue, list ) {
217 list_del ( &iobuf->list );
218 return iobuf;
220 return NULL;
224 * Flush device's receive queue
226 * @v netdev Network device
228 static void netdev_rx_flush ( struct net_device *netdev ) {
229 struct io_buffer *iobuf;
231 /* Discard any packets in the RX queue */
232 while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
233 netdev_rx_err ( netdev, iobuf, -ECANCELED );
238 * Free network device
240 * @v refcnt Network device reference counter
242 static void free_netdev ( struct refcnt *refcnt ) {
243 struct net_device *netdev =
244 container_of ( refcnt, struct net_device, refcnt );
246 netdev_tx_flush ( netdev );
247 netdev_rx_flush ( netdev );
248 free ( netdev );
252 * Allocate network device
254 * @v priv_size Size of private data area (net_device::priv)
255 * @ret netdev Network device, or NULL
257 * Allocates space for a network device and its private data area.
259 struct net_device * alloc_netdev ( size_t priv_size ) {
260 struct net_device *netdev;
261 size_t total_len;
263 total_len = ( sizeof ( *netdev ) + priv_size );
264 netdev = zalloc ( total_len );
265 if ( netdev ) {
266 netdev->refcnt.free = free_netdev;
267 INIT_LIST_HEAD ( &netdev->tx_queue );
268 INIT_LIST_HEAD ( &netdev->rx_queue );
269 settings_init ( netdev_settings ( netdev ),
270 &netdev_settings_operations, &netdev->refcnt,
271 netdev->name );
272 netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
274 return netdev;
278 * Register network device
280 * @v netdev Network device
281 * @ret rc Return status code
283 * Gives the network device a name and adds it to the list of network
284 * devices.
286 int register_netdev ( struct net_device *netdev ) {
287 static unsigned int ifindex = 0;
288 int rc;
290 /* Create device name */
291 snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
292 ifindex++ );
294 /* Register per-netdev configuration settings */
295 if ( ( rc = register_settings ( netdev_settings ( netdev ),
296 NULL ) ) != 0 ) {
297 DBGC ( netdev, "NETDEV %p could not register settings: %s\n",
298 netdev, strerror ( rc ) );
299 return rc;
302 /* Add to device list */
303 netdev_get ( netdev );
304 list_add_tail ( &netdev->list, &net_devices );
305 DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
306 netdev, netdev->name, netdev->dev->name,
307 netdev_hwaddr ( netdev ) );
309 return 0;
313 * Open network device
315 * @v netdev Network device
316 * @ret rc Return status code
318 int netdev_open ( struct net_device *netdev ) {
319 int rc;
321 /* Do nothing if device is already open */
322 if ( netdev->state & NETDEV_OPEN )
323 return 0;
325 DBGC ( netdev, "NETDEV %p opening\n", netdev );
327 /* Open the device */
328 if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
329 return rc;
331 /* Mark as opened */
332 netdev->state |= NETDEV_OPEN;
333 return 0;
337 * Close network device
339 * @v netdev Network device
341 void netdev_close ( struct net_device *netdev ) {
343 /* Do nothing if device is already closed */
344 if ( ! ( netdev->state & NETDEV_OPEN ) )
345 return;
347 DBGC ( netdev, "NETDEV %p closing\n", netdev );
349 /* Close the device */
350 netdev->op->close ( netdev );
352 /* Flush TX and RX queues */
353 netdev_tx_flush ( netdev );
354 netdev_rx_flush ( netdev );
356 /* Mark as closed */
357 netdev->state &= ~NETDEV_OPEN;
361 * Unregister network device
363 * @v netdev Network device
365 * Removes the network device from the list of network devices.
367 void unregister_netdev ( struct net_device *netdev ) {
369 /* Ensure device is closed */
370 netdev_close ( netdev );
372 /* Unregister per-netdev configuration settings */
373 unregister_settings ( netdev_settings ( netdev ) );
375 /* Remove from device list */
376 list_del ( &netdev->list );
377 netdev_put ( netdev );
378 DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
381 /** Enable or disable interrupts
383 * @v netdev Network device
384 * @v enable Interrupts should be enabled
386 void netdev_irq ( struct net_device *netdev, int enable ) {
387 netdev->op->irq ( netdev, enable );
391 * Get network device by name
393 * @v name Network device name
394 * @ret netdev Network device, or NULL
396 struct net_device * find_netdev ( const char *name ) {
397 struct net_device *netdev;
399 list_for_each_entry ( netdev, &net_devices, list ) {
400 if ( strcmp ( netdev->name, name ) == 0 )
401 return netdev;
404 return NULL;
408 * Get network device by PCI bus:dev.fn address
410 * @v bus_type Bus type
411 * @v location Bus location
412 * @ret netdev Network device, or NULL
414 struct net_device * find_netdev_by_location ( unsigned int bus_type,
415 unsigned int location ) {
416 struct net_device *netdev;
418 list_for_each_entry ( netdev, &net_devices, list ) {
419 if ( ( netdev->dev->desc.bus_type == bus_type ) &&
420 ( netdev->dev->desc.location == location ) )
421 return netdev;
424 return NULL;
428 * Transmit network-layer packet
430 * @v iobuf I/O buffer
431 * @v netdev Network device
432 * @v net_protocol Network-layer protocol
433 * @v ll_dest Destination link-layer address
434 * @ret rc Return status code
436 * Prepends link-layer headers to the I/O buffer and transmits the
437 * packet via the specified network device. This function takes
438 * ownership of the I/O buffer.
440 int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
441 struct net_protocol *net_protocol, const void *ll_dest ) {
443 /* Force a poll on the netdevice to (potentially) clear any
444 * backed-up TX completions. This is needed on some network
445 * devices to avoid excessive losses due to small TX ring
446 * sizes.
448 netdev_poll ( netdev );
450 return netdev->ll_protocol->tx ( iobuf, netdev, net_protocol, ll_dest );
454 * Process received network-layer packet
456 * @v iobuf I/O buffer
457 * @v netdev Network device
458 * @v net_proto Network-layer protocol, in network-byte order
459 * @v ll_source Source link-layer address
460 * @ret rc Return status code
462 int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
463 uint16_t net_proto, const void *ll_source ) {
464 struct net_protocol *net_protocol;
466 /* Hand off to network-layer protocol, if any */
467 for ( net_protocol = net_protocols ; net_protocol < net_protocols_end ;
468 net_protocol++ ) {
469 if ( net_protocol->net_proto == net_proto ) {
470 return net_protocol->rx ( iobuf, netdev, ll_source );
473 free_iob ( iobuf );
474 return 0;
478 * Single-step the network stack
480 * @v process Network stack process
482 * This polls all interfaces for received packets, and processes
483 * packets from the RX queue.
485 static void net_step ( struct process *process __unused ) {
486 struct net_device *netdev;
487 struct io_buffer *iobuf;
489 /* Poll and process each network device */
490 list_for_each_entry ( netdev, &net_devices, list ) {
492 /* Poll for new packets */
493 netdev_poll ( netdev );
495 /* Process at most one received packet. Give priority
496 * to getting packets out of the NIC over processing
497 * the received packets, because we advertise a window
498 * that assumes that we can receive packets from the
499 * NIC faster than they arrive.
501 if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
502 DBGC ( netdev, "NETDEV %p processing %p (%p+%zx)\n",
503 netdev, iobuf, iobuf->data,
504 iob_len ( iobuf ) );
505 netdev->ll_protocol->rx ( iobuf, netdev );
510 /** Networking stack process */
511 struct process net_process __permanent_process = {
512 .step = net_step,