f2778e880963942758da14b726327c48086d0cfa
[people/sha0/gpxe.git] / src / net / netdevice.c
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
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>
32
33 /** @file
34  *
35  * Network device management
36  *
37  */
38
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 );
44
45 /** List of network devices */
46 struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
47
48 /**
49  * Transmit raw packet via network device
50  *
51  * @v netdev            Network device
52  * @v iobuf             I/O buffer
53  * @ret rc              Return status code
54  *
55  * Transmits the packet via the specified network device.  This
56  * function takes ownership of the I/O buffer.
57  */
58 int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
59         int rc;
60
61         DBGC ( netdev, "NETDEV %p transmitting %p (%p+%zx)\n",
62                netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
63
64         list_add_tail ( &iobuf->list, &netdev->tx_queue );
65
66         if ( ! ( netdev->state & NETDEV_OPEN ) ) {
67                 rc = -ENETUNREACH;
68                 goto err;
69         }
70                 
71         if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
72                 goto err;
73
74         return 0;
75
76  err:
77         netdev_tx_complete_err ( netdev, iobuf, rc );
78         return rc;
79 }
80
81 /**
82  * Complete network transmission
83  *
84  * @v netdev            Network device
85  * @v iobuf             I/O buffer
86  * @v rc                Packet status code
87  *
88  * The packet must currently be in the network device's TX queue.
89  */
90 void netdev_tx_complete_err ( struct net_device *netdev,
91                               struct io_buffer *iobuf, int rc ) {
92
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 ) );
102         }
103
104         /* Catch data corruption as early as possible */
105         assert ( iobuf->list.next != NULL );
106         assert ( iobuf->list.prev != NULL );
107
108         /* Dequeue and free I/O buffer */
109         list_del ( &iobuf->list );
110         free_iob ( iobuf );
111 }
112
113 /**
114  * Complete network transmission
115  *
116  * @v netdev            Network device
117  * @v rc                Packet status code
118  *
119  * Completes the oldest outstanding packet in the TX queue.
120  */
121 void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
122         struct io_buffer *iobuf;
123
124         list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
125                 netdev_tx_complete_err ( netdev, iobuf, rc );
126                 return;
127         }
128 }
129
130 /**
131  * Flush device's transmit queue
132  *
133  * @v netdev            Network device
134  */
135 static void netdev_tx_flush ( struct net_device *netdev ) {
136
137         /* Discard any packets in the TX queue */
138         while ( ! list_empty ( &netdev->tx_queue ) ) {
139                 netdev_tx_complete_next_err ( netdev, -ECANCELED );
140         }
141 }
142
143 /**
144  * Add packet to receive queue
145  *
146  * @v netdev            Network device
147  * @v iobuf             I/O buffer, or NULL
148  *
149  * The packet is added to the network device's RX queue.  This
150  * function takes ownership of the I/O buffer.
151  */
152 void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
153
154         DBGC ( netdev, "NETDEV %p received %p (%p+%zx)\n",
155                netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
156
157         /* Enqueue packet */
158         list_add_tail ( &iobuf->list, &netdev->rx_queue );
159
160         /* Update statistics counter */
161         netdev->stats.rx_ok++;
162 }
163
164 /**
165  * Discard received packet
166  *
167  * @v netdev            Network device
168  * @v iobuf             I/O buffer, or NULL
169  * @v rc                Packet status code
170  *
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.
175  */
176 void netdev_rx_err ( struct net_device *netdev,
177                      struct io_buffer *iobuf, int rc ) {
178
179         DBGC ( netdev, "NETDEV %p failed to receive %p: %s\n",
180                netdev, iobuf, strerror ( rc ) );
181
182         /* Discard packet */
183         free_iob ( iobuf );
184
185         /* Update statistics counter */
186         netdev->stats.rx_err++;
187 }
188
189 /**
190  * Poll for completed and received packets on network device
191  *
192  * @v netdev            Network device
193  *
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().
197  */
198 void netdev_poll ( struct net_device *netdev ) {
199
200         if ( netdev->state & NETDEV_OPEN )
201                 netdev->op->poll ( netdev );
202 }
203
204 /**
205  * Remove packet from device's receive queue
206  *
207  * @v netdev            Network device
208  * @ret iobuf           I/O buffer, or NULL
209  *
210  * Removes the first packet from the device's RX queue and returns it.
211  * Ownership of the packet is transferred to the caller.
212  */
213 struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
214         struct io_buffer *iobuf;
215
216         list_for_each_entry ( iobuf, &netdev->rx_queue, list ) {
217                 list_del ( &iobuf->list );
218                 return iobuf;
219         }
220         return NULL;
221 }
222
223 /**
224  * Flush device's receive queue
225  *
226  * @v netdev            Network device
227  */
228 static void netdev_rx_flush ( struct net_device *netdev ) {
229         struct io_buffer *iobuf;
230
231         /* Discard any packets in the RX queue */
232         while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
233                 netdev_rx_err ( netdev, iobuf, -ECANCELED );
234         }
235 }
236
237 /**
238  * Free network device
239  *
240  * @v refcnt            Network device reference counter
241  */
242 static void free_netdev ( struct refcnt *refcnt ) {
243         struct net_device *netdev =
244                 container_of ( refcnt, struct net_device, refcnt );
245         
246         netdev_tx_flush ( netdev );
247         netdev_rx_flush ( netdev );
248         free ( netdev );
249 }
250
251 /**
252  * Allocate network device
253  *
254  * @v priv_size         Size of private data area (net_device::priv)
255  * @ret netdev          Network device, or NULL
256  *
257  * Allocates space for a network device and its private data area.
258  */
259 struct net_device * alloc_netdev ( size_t priv_size ) {
260         struct net_device *netdev;
261         size_t total_len;
262
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                 netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
270         }
271         return netdev;
272 }
273
274 /**
275  * Register network device
276  *
277  * @v netdev            Network device
278  * @ret rc              Return status code
279  *
280  * Gives the network device a name and adds it to the list of network
281  * devices.
282  */
283 int register_netdev ( struct net_device *netdev ) {
284         static unsigned int ifindex = 0;
285
286         /* Create device name */
287         snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
288                    ifindex++ );
289
290         /* Add to device list */
291         netdev_get ( netdev );
292         list_add_tail ( &netdev->list, &net_devices );
293         DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
294                netdev, netdev->name, netdev->dev->name,
295                netdev_hwaddr ( netdev ) );
296
297         return 0;
298 }
299
300 /**
301  * Open network device
302  *
303  * @v netdev            Network device
304  * @ret rc              Return status code
305  */
306 int netdev_open ( struct net_device *netdev ) {
307         int rc;
308
309         /* Do nothing if device is already open */
310         if ( netdev->state & NETDEV_OPEN )
311                 return 0;
312
313         DBGC ( netdev, "NETDEV %p opening\n", netdev );
314
315         /* Open the device */
316         if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
317                 return rc;
318
319         /* Mark as opened */
320         netdev->state |= NETDEV_OPEN;
321         return 0;
322 }
323
324 /**
325  * Close network device
326  *
327  * @v netdev            Network device
328  */
329 void netdev_close ( struct net_device *netdev ) {
330
331         /* Do nothing if device is already closed */
332         if ( ! ( netdev->state & NETDEV_OPEN ) )
333                 return;
334
335         DBGC ( netdev, "NETDEV %p closing\n", netdev );
336
337         /* Close the device */
338         netdev->op->close ( netdev );
339
340         /* Flush TX and RX queues */
341         netdev_tx_flush ( netdev );
342         netdev_rx_flush ( netdev );
343
344         /* Mark as closed */
345         netdev->state &= ~NETDEV_OPEN;
346 }
347
348 /**
349  * Unregister network device
350  *
351  * @v netdev            Network device
352  *
353  * Removes the network device from the list of network devices.
354  */
355 void unregister_netdev ( struct net_device *netdev ) {
356
357         /* Ensure device is closed */
358         netdev_close ( netdev );
359
360         /* Remove from device list */
361         list_del ( &netdev->list );
362         netdev_put ( netdev );
363         DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
364 }
365
366 /** Enable or disable interrupts
367  *
368  * @v netdev            Network device
369  * @v enable            Interrupts should be enabled
370  */
371 void netdev_irq ( struct net_device *netdev, int enable ) {
372         netdev->op->irq ( netdev, enable );
373 }
374
375 /**
376  * Get network device by name
377  *
378  * @v name              Network device name
379  * @ret netdev          Network device, or NULL
380  */
381 struct net_device * find_netdev ( const char *name ) {
382         struct net_device *netdev;
383
384         list_for_each_entry ( netdev, &net_devices, list ) {
385                 if ( strcmp ( netdev->name, name ) == 0 )
386                         return netdev;
387         }
388
389         return NULL;
390 }
391
392 /**
393  * Get network device by PCI bus:dev.fn address
394  *
395  * @v bus_type          Bus type
396  * @v location          Bus location
397  * @ret netdev          Network device, or NULL
398  */
399 struct net_device * find_netdev_by_location ( unsigned int bus_type,
400                                               unsigned int location ) {
401         struct net_device *netdev;
402
403         list_for_each_entry ( netdev, &net_devices, list ) {
404                 if ( ( netdev->dev->desc.bus_type == bus_type ) &&
405                      ( netdev->dev->desc.location == location ) )
406                         return netdev;
407         }
408
409         return NULL;    
410 }
411
412 /**
413  * Transmit network-layer packet
414  *
415  * @v iobuf             I/O buffer
416  * @v netdev            Network device
417  * @v net_protocol      Network-layer protocol
418  * @v ll_dest           Destination link-layer address
419  * @ret rc              Return status code
420  *
421  * Prepends link-layer headers to the I/O buffer and transmits the
422  * packet via the specified network device.  This function takes
423  * ownership of the I/O buffer.
424  */
425 int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
426              struct net_protocol *net_protocol, const void *ll_dest ) {
427
428         /* Force a poll on the netdevice to (potentially) clear any
429          * backed-up TX completions.  This is needed on some network
430          * devices to avoid excessive losses due to small TX ring
431          * sizes.
432          */
433         netdev_poll ( netdev );
434
435         return netdev->ll_protocol->tx ( iobuf, netdev, net_protocol, ll_dest );
436 }
437
438 /**
439  * Process received network-layer packet
440  *
441  * @v iobuf             I/O buffer
442  * @v netdev            Network device
443  * @v net_proto         Network-layer protocol, in network-byte order
444  * @v ll_source         Source link-layer address
445  * @ret rc              Return status code
446  */
447 int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
448              uint16_t net_proto, const void *ll_source ) {
449         struct net_protocol *net_protocol;
450
451         /* Hand off to network-layer protocol, if any */
452         for ( net_protocol = net_protocols ; net_protocol < net_protocols_end ;
453               net_protocol++ ) {
454                 if ( net_protocol->net_proto == net_proto ) {
455                         return net_protocol->rx ( iobuf, netdev, ll_source );
456                 }
457         }
458         free_iob ( iobuf );
459         return 0;
460 }
461
462 /**
463  * Single-step the network stack
464  *
465  * @v process           Network stack process
466  *
467  * This polls all interfaces for received packets, and processes
468  * packets from the RX queue.
469  */
470 static void net_step ( struct process *process __unused ) {
471         struct net_device *netdev;
472         struct io_buffer *iobuf;
473
474         /* Poll and process each network device */
475         list_for_each_entry ( netdev, &net_devices, list ) {
476
477                 /* Poll for new packets */
478                 netdev_poll ( netdev );
479
480                 /* Process at most one received packet.  Give priority
481                  * to getting packets out of the NIC over processing
482                  * the received packets, because we advertise a window
483                  * that assumes that we can receive packets from the
484                  * NIC faster than they arrive.
485                  */
486                 if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
487                         DBGC ( netdev, "NETDEV %p processing %p (%p+%zx)\n",
488                                netdev, iobuf, iobuf->data,
489                                iob_len ( iobuf ) );
490                         netdev->ll_protocol->rx ( iobuf, netdev );
491                 }
492         }
493 }
494
495 /** Networking stack process */
496 struct process net_process __permanent_process = {
497         .step = net_step,
498 };