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
->op
->transmit ( netdev
, iobuf
) ) != 0 )
77 netdev_tx_complete_err ( netdev
, iobuf
, rc
);
82 * Complete network transmission
84 * @v netdev Network device
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 */
95 netdev
->stats
.tx_ok
++;
96 DBGC ( netdev
, "NETDEV %p transmission %p complete\n",
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
);
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
);
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
) );
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
) );
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
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
);
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
);
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
;
263 total_len
= ( sizeof ( *netdev
) + priv_size
);
264 netdev
= zalloc ( total_len
);
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
) );
275 * Register network device
277 * @v netdev Network device
278 * @ret rc Return status code
280 * Gives the network device a name and adds it to the list of network
283 int register_netdev ( struct net_device
*netdev
) {
284 static unsigned int ifindex
= 0;
286 /* Create device name */
287 snprintf ( netdev
->name
, sizeof ( netdev
->name
), "net%d",
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
) );
301 * Open network device
303 * @v netdev Network device
304 * @ret rc Return status code
306 int netdev_open ( struct net_device
*netdev
) {
309 /* Do nothing if device is already open */
310 if ( netdev
->state
& NETDEV_OPEN
)
313 DBGC ( netdev
, "NETDEV %p opening\n", netdev
);
315 /* Open the device */
316 if ( ( rc
= netdev
->op
->open ( netdev
) ) != 0 )
320 netdev
->state
|= NETDEV_OPEN
;
325 * Close network device
327 * @v netdev Network device
329 void netdev_close ( struct net_device
*netdev
) {
331 /* Do nothing if device is already closed */
332 if ( ! ( netdev
->state
& NETDEV_OPEN
) )
335 DBGC ( netdev
, "NETDEV %p closing\n", netdev
);
337 /* Close the device */
338 netdev
->op
->close ( netdev
);
340 /* Flush TX and RX queues */
341 netdev_tx_flush ( netdev
);
342 netdev_rx_flush ( netdev
);
345 netdev
->state
&= ~NETDEV_OPEN
;
349 * Unregister network device
351 * @v netdev Network device
353 * Removes the network device from the list of network devices.
355 void unregister_netdev ( struct net_device
*netdev
) {
357 /* Ensure device is closed */
358 netdev_close ( netdev
);
360 /* Remove from device list */
361 list_del ( &netdev
->list
);
362 netdev_put ( netdev
);
363 DBGC ( netdev
, "NETDEV %p unregistered\n", netdev
);
366 /** Enable or disable interrupts
368 * @v netdev Network device
369 * @v enable Interrupts should be enabled
371 void netdev_irq ( struct net_device
*netdev
, int enable
) {
372 netdev
->op
->irq ( netdev
, enable
);
376 * Get network device by name
378 * @v name Network device name
379 * @ret netdev Network device, or NULL
381 struct net_device
* find_netdev ( const char *name
) {
382 struct net_device
*netdev
;
384 list_for_each_entry ( netdev
, &net_devices
, list
) {
385 if ( strcmp ( netdev
->name
, name
) == 0 )
393 * Get network device by PCI bus:dev.fn address
395 * @v bus_type Bus type
396 * @v location Bus location
397 * @ret netdev Network device, or NULL
399 struct net_device
* find_netdev_by_location ( unsigned int bus_type
,
400 unsigned int location
) {
401 struct net_device
*netdev
;
403 list_for_each_entry ( netdev
, &net_devices
, list
) {
404 if ( ( netdev
->dev
->desc
.bus_type
== bus_type
) &&
405 ( netdev
->dev
->desc
.location
== location
) )
413 * Transmit network-layer packet
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
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.
425 int net_tx ( struct io_buffer
*iobuf
, struct net_device
*netdev
,
426 struct net_protocol
*net_protocol
, const void *ll_dest
) {
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
433 netdev_poll ( netdev
);
435 return netdev
->ll_protocol
->tx ( iobuf
, netdev
, net_protocol
, ll_dest
);
439 * Process received network-layer packet
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
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
;
451 /* Hand off to network-layer protocol, if any */
452 for ( net_protocol
= net_protocols
; net_protocol
< net_protocols_end
;
454 if ( net_protocol
->net_proto
== net_proto
) {
455 return net_protocol
->rx ( iobuf
, netdev
, ll_source
);
463 * Single-step the network stack
465 * @v process Network stack process
467 * This polls all interfaces for received packets, and processes
468 * packets from the RX queue.
470 static void net_step ( struct process
*process __unused
) {
471 struct net_device
*netdev
;
472 struct io_buffer
*iobuf
;
474 /* Poll and process each network device */
475 list_for_each_entry ( netdev
, &net_devices
, list
) {
477 /* Poll for new packets */
478 netdev_poll ( netdev
);
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.
486 if ( ( iobuf
= netdev_rx_dequeue ( netdev
) ) ) {
487 DBGC ( netdev
, "NETDEV %p processing %p (%p+%zx)\n",
488 netdev
, iobuf
, iobuf
->data
,
490 netdev
->ll_protocol
->rx ( iobuf
, netdev
);
495 /** Networking stack process */
496 struct process net_process __permanent_process
= {