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.
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>
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 );
49 * Transmit raw packet via network device
51 * @v netdev Network device
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 ) {
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 ) ) {
71 if ( ( rc = netdev->transmit ( netdev, iobuf ) ) != 0 )
77 DBGC ( netdev, "NETDEV %p transmission %p failed: %s\n",
78 netdev, iobuf, strerror ( rc ) );
79 netdev_tx_complete ( netdev, iobuf );
84 * Complete network transmission
86 * @v netdev Network device
89 * The packet must currently be in the network device's TX queue.
91 void netdev_tx_complete ( struct net_device *netdev, struct io_buffer *iobuf ) {
92 DBGC ( netdev, "NETDEV %p transmission %p complete\n", netdev, iobuf );
94 /* Catch data corruption as early as possible */
95 assert ( iobuf->list.next != NULL );
96 assert ( iobuf->list.prev != NULL );
98 /* Dequeue and free I/O buffer */
99 list_del ( &iobuf->list );
102 /* Update statistics counter */
103 netdev->stats.tx_count++;
107 * Complete network transmission
109 * @v netdev Network device
111 * Completes the oldest outstanding packet in the TX queue.
113 void netdev_tx_complete_next ( struct net_device *netdev ) {
114 struct io_buffer *iobuf;
116 list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
117 netdev_tx_complete ( netdev, iobuf );
123 * Flush device's transmit queue
125 * @v netdev Network device
127 static void netdev_tx_flush ( struct net_device *netdev ) {
129 /* Discard any packets in the TX queue */
130 while ( ! list_empty ( &netdev->tx_queue ) ) {
131 netdev_tx_complete_next ( netdev );
136 * Add packet to receive queue
138 * @v netdev Network device
139 * @v iobuf I/O buffer
141 * The packet is added to the network device's RX queue. This
142 * function takes ownership of the I/O buffer.
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 ) );
149 list_add_tail ( &iobuf->list, &netdev->rx_queue );
151 /* Update statistics counter */
152 netdev->stats.rx_count++;
156 * Poll for packet on network device
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
163 * Polls the network device for received packets. Any received
164 * packets will be added to the RX packet queue via netdev_rx().
166 int netdev_poll ( struct net_device *netdev, unsigned int rx_quota ) {
168 if ( netdev->state & NETDEV_OPEN )
169 netdev->poll ( netdev, rx_quota );
171 return ( ! list_empty ( &netdev->rx_queue ) );
175 * Remove packet from device's receive queue
177 * @v netdev Network device
178 * @ret iobuf I/O buffer, or NULL
180 * Removes the first packet from the device's RX queue and returns it.
181 * Ownership of the packet is transferred to the caller.
183 struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
184 struct io_buffer *iobuf;
186 list_for_each_entry ( iobuf, &netdev->rx_queue, list ) {
187 list_del ( &iobuf->list );
194 * Flush device's receive queue
196 * @v netdev Network device
198 static void netdev_rx_flush ( struct net_device *netdev ) {
199 struct io_buffer *iobuf;
201 /* Discard any packets in the RX queue */
202 while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
203 DBGC ( netdev, "NETDEV %p discarding received %p\n",
210 * Free network device
212 * @v refcnt Network device reference counter
214 static void free_netdev ( struct refcnt *refcnt ) {
215 struct net_device *netdev =
216 container_of ( refcnt, struct net_device, refcnt );
218 netdev_tx_flush ( netdev );
219 netdev_rx_flush ( netdev );
224 * Allocate network device
226 * @v priv_size Size of private data area (net_device::priv)
227 * @ret netdev Network device, or NULL
229 * Allocates space for a network device and its private data area.
231 struct net_device * alloc_netdev ( size_t priv_size ) {
232 struct net_device *netdev;
235 total_len = ( sizeof ( *netdev ) + priv_size );
236 netdev = malloc ( total_len );
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 ) );
248 * Register network device
250 * @v netdev Network device
251 * @ret rc Return status code
253 * Gives the network device a name and adds it to the list of network
256 int register_netdev ( struct net_device *netdev ) {
257 static unsigned int ifindex = 0;
259 /* Create device name */
260 snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
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 ) );
274 * Open network device
276 * @v netdev Network device
277 * @ret rc Return status code
279 int netdev_open ( struct net_device *netdev ) {
282 /* Do nothing if device is already open */
283 if ( netdev->state & NETDEV_OPEN )
286 DBGC ( netdev, "NETDEV %p opening\n", netdev );
288 /* Open the device */
289 if ( ( rc = netdev->open ( netdev ) ) != 0 )
293 netdev->state |= NETDEV_OPEN;
298 * Close network device
300 * @v netdev Network device
302 void netdev_close ( struct net_device *netdev ) {
304 /* Do nothing if device is already closed */
305 if ( ! ( netdev->state & NETDEV_OPEN ) )
308 DBGC ( netdev, "NETDEV %p closing\n", netdev );
310 /* Close the device */
311 netdev->close ( netdev );
313 /* Flush TX and RX queues */
314 netdev_tx_flush ( netdev );
315 netdev_rx_flush ( netdev );
318 netdev->state &= ~NETDEV_OPEN;
322 * Unregister network device
324 * @v netdev Network device
326 * Removes the network device from the list of network devices.
328 void unregister_netdev ( struct net_device *netdev ) {
330 /* Ensure device is closed */
331 netdev_close ( netdev );
333 /* Remove from device list */
334 list_del ( &netdev->list );
335 netdev_put ( netdev );
336 DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
340 * Get network device by name
342 * @v name Network device name
343 * @ret netdev Network device, or NULL
345 struct net_device * find_netdev ( const char *name ) {
346 struct net_device *netdev;
348 list_for_each_entry ( netdev, &net_devices, list ) {
349 if ( strcmp ( netdev->name, name ) == 0 )
357 * Get network device by PCI bus:dev.fn address
359 * @v bus_type Bus type
360 * @v location Bus location
361 * @ret netdev Network device, or NULL
363 struct net_device * find_netdev_by_location ( unsigned int bus_type,
364 unsigned int location ) {
365 struct net_device *netdev;
367 list_for_each_entry ( netdev, &net_devices, list ) {
368 if ( ( netdev->dev->desc.bus_type == bus_type ) &&
369 ( netdev->dev->desc.location == location ) )
377 * Transmit network-layer packet
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
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.
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 );
395 * Process received network-layer packet
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
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;
407 /* Hand off to network-layer protocol, if any */
408 for ( net_protocol = net_protocols ; net_protocol < net_protocols_end ;
410 if ( net_protocol->net_proto == net_proto ) {
411 return net_protocol->rx ( iobuf, netdev, ll_source );
419 * Single-step the network stack
421 * @v process Network stack process
423 * This polls all interfaces for received packets, and processes
424 * packets from the RX queue.
426 static void net_step ( struct process *process __unused ) {
427 struct net_device *netdev;
428 struct io_buffer *iobuf;
430 /* Poll and process each network device */
431 list_for_each_entry ( netdev, &net_devices, list ) {
433 /* Poll for new packets */
434 netdev_poll ( netdev, -1U );
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.
442 if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
443 DBGC ( netdev, "NETDEV %p processing %p\n",
445 netdev->ll_protocol->rx ( iobuf, netdev );
450 /** Networking stack process */
451 static struct process net_process = {
455 /** Initialise the networking stack process */
456 static void init_net ( void ) {
457 process_add ( &net_process );
460 INIT_FN ( INIT_PROCESS, init_net, NULL, NULL );