fb4612bc9ae552e311d4843ab05f7695e4f05e3b
[people/xl0/gpxe-arm.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->transmit ( netdev, iobuf ) ) != 0 )
72                 goto err;
73
74         return 0;
75
76  err:
77         DBGC ( netdev, "NETDEV %p transmission %p failed: %s\n",
78                netdev, iobuf, strerror ( rc ) );
79         netdev_tx_complete ( netdev, iobuf );
80         return rc;
81 }
82
83 /**
84  * Complete network transmission
85  *
86  * @v netdev            Network device
87  * @v iobuf             I/O buffer
88  *
89  * The packet must currently be in the network device's TX queue.
90  */
91 void netdev_tx_complete ( struct net_device *netdev, struct io_buffer *iobuf ) {
92         DBGC ( netdev, "NETDEV %p transmission %p complete\n", netdev, iobuf );
93
94         /* Catch data corruption as early as possible */
95         assert ( iobuf->list.next != NULL );
96         assert ( iobuf->list.prev != NULL );
97
98         /* Dequeue and free I/O buffer */
99         list_del ( &iobuf->list );
100         free_iob ( iobuf );
101
102         /* Update statistics counter */
103         netdev->stats.tx_count++;
104 }
105
106 /**
107  * Complete network transmission
108  *
109  * @v netdev            Network device
110  *
111  * Completes the oldest outstanding packet in the TX queue.
112  */
113 void netdev_tx_complete_next ( struct net_device *netdev ) {
114         struct io_buffer *iobuf;
115
116         list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
117                 netdev_tx_complete ( netdev, iobuf );
118                 return;
119         }
120 }
121
122 /**
123  * Flush device's transmit queue
124  *
125  * @v netdev            Network device
126  */
127 static void netdev_tx_flush ( struct net_device *netdev ) {
128
129         /* Discard any packets in the TX queue */
130         while ( ! list_empty ( &netdev->tx_queue ) ) {
131                 netdev_tx_complete_next ( netdev );
132         }
133 }
134
135 /**
136  * Add packet to receive queue
137  *
138  * @v netdev            Network device
139  * @v iobuf             I/O buffer
140  *
141  * The packet is added to the network device's RX queue.  This
142  * function takes ownership of the I/O buffer.
143  */
144 void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
145         DBGC ( netdev, "NETDEV %p received %p (%p+%zx)\n",
146                netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
147
148         /* Enqueue packet */
149         list_add_tail ( &iobuf->list, &netdev->rx_queue );
150
151         /* Update statistics counter */
152         netdev->stats.rx_count++;
153 }
154
155 /**
156  * Poll for packet on network device
157  *
158  * @v netdev            Network device
159  * @v rx_quota          Maximum number of packets to receive
160  * @ret True            There are packets present in the receive queue
161  * @ret False           There are no packets present in the receive queue
162  *
163  * Polls the network device for received packets.  Any received
164  * packets will be added to the RX packet queue via netdev_rx().
165  */
166 int netdev_poll ( struct net_device *netdev, unsigned int rx_quota ) {
167
168         if ( netdev->state & NETDEV_OPEN )
169                 netdev->poll ( netdev, rx_quota );
170
171         return ( ! list_empty ( &netdev->rx_queue ) );
172 }
173
174 /**
175  * Remove packet from device's receive queue
176  *
177  * @v netdev            Network device
178  * @ret iobuf           I/O buffer, or NULL
179  *
180  * Removes the first packet from the device's RX queue and returns it.
181  * Ownership of the packet is transferred to the caller.
182  */
183 struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
184         struct io_buffer *iobuf;
185
186         list_for_each_entry ( iobuf, &netdev->rx_queue, list ) {
187                 list_del ( &iobuf->list );
188                 return iobuf;
189         }
190         return NULL;
191 }
192
193 /**
194  * Flush device's receive queue
195  *
196  * @v netdev            Network device
197  */
198 static void netdev_rx_flush ( struct net_device *netdev ) {
199         struct io_buffer *iobuf;
200
201         /* Discard any packets in the RX queue */
202         while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
203                 DBGC ( netdev, "NETDEV %p discarding received %p\n",
204                        netdev, iobuf );
205                 free_iob ( iobuf );
206         }
207 }
208
209 /**
210  * Free network device
211  *
212  * @v refcnt            Network device reference counter
213  */
214 static void free_netdev ( struct refcnt *refcnt ) {
215         struct net_device *netdev =
216                 container_of ( refcnt, struct net_device, refcnt );
217         
218         netdev_tx_flush ( netdev );
219         netdev_rx_flush ( netdev );
220         free ( netdev );
221 }
222
223 /**
224  * Allocate network device
225  *
226  * @v priv_size         Size of private data area (net_device::priv)
227  * @ret netdev          Network device, or NULL
228  *
229  * Allocates space for a network device and its private data area.
230  */
231 struct net_device * alloc_netdev ( size_t priv_size ) {
232         struct net_device *netdev;
233         size_t total_len;
234
235         total_len = ( sizeof ( *netdev ) + priv_size );
236         netdev = malloc ( total_len );
237         if ( netdev ) {
238                 memset ( netdev, 0, total_len );
239                 netdev->refcnt.free = free_netdev;
240                 INIT_LIST_HEAD ( &netdev->tx_queue );
241                 INIT_LIST_HEAD ( &netdev->rx_queue );
242                 netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
243         }
244         return netdev;
245 }
246
247 /**
248  * Register network device
249  *
250  * @v netdev            Network device
251  * @ret rc              Return status code
252  *
253  * Gives the network device a name and adds it to the list of network
254  * devices.
255  */
256 int register_netdev ( struct net_device *netdev ) {
257         static unsigned int ifindex = 0;
258
259         /* Create device name */
260         snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
261                    ifindex++ );
262
263         /* Add to device list */
264         netdev_get ( netdev );
265         list_add_tail ( &netdev->list, &net_devices );
266         DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
267                netdev, netdev->name, netdev->dev->name,
268                netdev_hwaddr ( netdev ) );
269
270         return 0;
271 }
272
273 /**
274  * Open network device
275  *
276  * @v netdev            Network device
277  * @ret rc              Return status code
278  */
279 int netdev_open ( struct net_device *netdev ) {
280         int rc;
281
282         /* Do nothing if device is already open */
283         if ( netdev->state & NETDEV_OPEN )
284                 return 0;
285
286         DBGC ( netdev, "NETDEV %p opening\n", netdev );
287
288         /* Open the device */
289         if ( ( rc = netdev->open ( netdev ) ) != 0 )
290                 return rc;
291
292         /* Mark as opened */
293         netdev->state |= NETDEV_OPEN;
294         return 0;
295 }
296
297 /**
298  * Close network device
299  *
300  * @v netdev            Network device
301  */
302 void netdev_close ( struct net_device *netdev ) {
303
304         /* Do nothing if device is already closed */
305         if ( ! ( netdev->state & NETDEV_OPEN ) )
306                 return;
307
308         DBGC ( netdev, "NETDEV %p closing\n", netdev );
309
310         /* Close the device */
311         netdev->close ( netdev );
312
313         /* Flush TX and RX queues */
314         netdev_tx_flush ( netdev );
315         netdev_rx_flush ( netdev );
316
317         /* Mark as closed */
318         netdev->state &= ~NETDEV_OPEN;
319 }
320
321 /**
322  * Unregister network device
323  *
324  * @v netdev            Network device
325  *
326  * Removes the network device from the list of network devices.
327  */
328 void unregister_netdev ( struct net_device *netdev ) {
329
330         /* Ensure device is closed */
331         netdev_close ( netdev );
332
333         /* Remove from device list */
334         list_del ( &netdev->list );
335         netdev_put ( netdev );
336         DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
337 }
338
339 /**
340  * Get network device by name
341  *
342  * @v name              Network device name
343  * @ret netdev          Network device, or NULL
344  */
345 struct net_device * find_netdev ( const char *name ) {
346         struct net_device *netdev;
347
348         list_for_each_entry ( netdev, &net_devices, list ) {
349                 if ( strcmp ( netdev->name, name ) == 0 )
350                         return netdev;
351         }
352
353         return NULL;
354 }
355
356 /**
357  * Get network device by PCI bus:dev.fn address
358  *
359  * @v bus_type          Bus type
360  * @v location          Bus location
361  * @ret netdev          Network device, or NULL
362  */
363 struct net_device * find_netdev_by_location ( unsigned int bus_type,
364                                               unsigned int location ) {
365         struct net_device *netdev;
366
367         list_for_each_entry ( netdev, &net_devices, list ) {
368                 if ( ( netdev->dev->desc.bus_type == bus_type ) &&
369                      ( netdev->dev->desc.location == location ) )
370                         return netdev;
371         }
372
373         return NULL;    
374 }
375
376 /**
377  * Transmit network-layer packet
378  *
379  * @v iobuf             I/O buffer
380  * @v netdev            Network device
381  * @v net_protocol      Network-layer protocol
382  * @v ll_dest           Destination link-layer address
383  * @ret rc              Return status code
384  *
385  * Prepends link-layer headers to the I/O buffer and transmits the
386  * packet via the specified network device.  This function takes
387  * ownership of the I/O buffer.
388  */
389 int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
390              struct net_protocol *net_protocol, const void *ll_dest ) {
391         return netdev->ll_protocol->tx ( iobuf, netdev, net_protocol, ll_dest );
392 }
393
394 /**
395  * Process received network-layer packet
396  *
397  * @v iobuf             I/O buffer
398  * @v netdev            Network device
399  * @v net_proto         Network-layer protocol, in network-byte order
400  * @v ll_source         Source link-layer address
401  * @ret rc              Return status code
402  */
403 int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
404              uint16_t net_proto, const void *ll_source ) {
405         struct net_protocol *net_protocol;
406
407         /* Hand off to network-layer protocol, if any */
408         for ( net_protocol = net_protocols ; net_protocol < net_protocols_end ;
409               net_protocol++ ) {
410                 if ( net_protocol->net_proto == net_proto ) {
411                         return net_protocol->rx ( iobuf, netdev, ll_source );
412                 }
413         }
414         free_iob ( iobuf );
415         return 0;
416 }
417
418 /**
419  * Single-step the network stack
420  *
421  * @v process           Network stack process
422  *
423  * This polls all interfaces for received packets, and processes
424  * packets from the RX queue.
425  */
426 static void net_step ( struct process *process __unused ) {
427         struct net_device *netdev;
428         struct io_buffer *iobuf;
429
430         /* Poll and process each network device */
431         list_for_each_entry ( netdev, &net_devices, list ) {
432
433                 /* Poll for new packets */
434                 netdev_poll ( netdev, -1U );
435
436                 /* Process at most one received packet.  Give priority
437                  * to getting packets out of the NIC over processing
438                  * the received packets, because we advertise a window
439                  * that assumes that we can receive packets from the
440                  * NIC faster than they arrive.
441                  */
442                 if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
443                         DBGC ( netdev, "NETDEV %p processing %p\n",
444                                netdev, iobuf );
445                         netdev->ll_protocol->rx ( iobuf, netdev );
446                 }
447         }
448 }
449
450 /** Networking stack process */
451 struct process net_process __permanent_process = {
452         .step = net_step,
453 };