summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Brown2007-01-04 05:20:08 +0100
committerMichael Brown2007-01-04 05:20:08 +0100
commit0c03bb5a9a0649ec7009e334c0e42290af330437 (patch)
treed523c7ba2ae84b0998b7e8121d70a603d6fd087a /src
parentWe *should* use the persistent reference API for our netdev reference, (diff)
downloadipxe-0c03bb5a9a0649ec7009e334c0e42290af330437.tar.gz
ipxe-0c03bb5a9a0649ec7009e334c0e42290af330437.tar.xz
ipxe-0c03bb5a9a0649ec7009e334c0e42290af330437.zip
Make open() and close() an official part of the netdevice API.
Call netdevice's poll() and transmit() methods only when device is open.
Diffstat (limited to 'src')
-rw-r--r--src/drivers/net/legacy.c10
-rw-r--r--src/drivers/net/pnic.c16
-rw-r--r--src/drivers/net/rtl8139.c12
-rw-r--r--src/include/gpxe/netdevice.h33
-rw-r--r--src/net/netdevice.c66
-rw-r--r--src/usr/autoboot.c18
6 files changed, 137 insertions, 18 deletions
diff --git a/src/drivers/net/legacy.c b/src/drivers/net/legacy.c
index b0023b186..0c205aed9 100644
--- a/src/drivers/net/legacy.c
+++ b/src/drivers/net/legacy.c
@@ -56,6 +56,14 @@ static void legacy_poll ( struct net_device *netdev ) {
}
}
+static int legacy_open ( struct net_device *netdev __unused ) {
+ return 0;
+}
+
+static void legacy_close ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+}
+
int legacy_probe ( struct pci_device *pci,
const struct pci_device_id *id __unused,
int ( * probe ) ( struct nic *nic,
@@ -74,6 +82,8 @@ int legacy_probe ( struct pci_device *pci,
memset ( &nic, 0, sizeof ( nic ) );
pci_set_drvdata ( pci, netdev );
+ netdev->open = legacy_open;
+ netdev->close = legacy_close;
netdev->transmit = legacy_transmit;
netdev->poll = legacy_poll;
nic.node_addr = netdev->ll_addr;
diff --git a/src/drivers/net/pnic.c b/src/drivers/net/pnic.c
index ad98c6092..d8f2544e3 100644
--- a/src/drivers/net/pnic.c
+++ b/src/drivers/net/pnic.c
@@ -186,6 +186,20 @@ static void pnic_irq ( struct net_device *netdev, irq_action_t action ) {
#endif
/**************************************************************************
+OPEN - Open network device
+***************************************************************************/
+static int pnic_open ( struct net_device *netdev __unused ) {
+ return 0;
+}
+
+/**************************************************************************
+CLOSE - Close network device
+***************************************************************************/
+static void pnic_close ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+}
+
+/**************************************************************************
DISABLE - Turn off ethernet interface
***************************************************************************/
static void pnic_remove ( struct pci_device *pci ) {
@@ -238,6 +252,8 @@ static int pnic_probe ( struct pci_device *pci,
netdev->ll_addr, ETH_ALEN, NULL );
/* Point to NIC specific routines */
+ netdev->open = pnic_open;
+ netdev->close = pnic_close;
netdev->poll = pnic_poll;
netdev->transmit = pnic_transmit;
diff --git a/src/drivers/net/rtl8139.c b/src/drivers/net/rtl8139.c
index 86c9c8057..4592ed7db 100644
--- a/src/drivers/net/rtl8139.c
+++ b/src/drivers/net/rtl8139.c
@@ -542,8 +542,8 @@ static int rtl_probe ( struct pci_device *pci,
nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
/* Point to NIC specific routines */
- // netdev->open = rtl_open;
- // netdev->close = rtl_close;
+ netdev->open = rtl_open;
+ netdev->close = rtl_close;
netdev->transmit = rtl_transmit;
netdev->poll = rtl_poll;
@@ -558,10 +558,6 @@ static int rtl_probe ( struct pci_device *pci,
goto err;
}
-#warning "Hack alert"
- rtl_open ( netdev );
-
-
return 0;
err:
@@ -584,10 +580,6 @@ static void rtl_remove ( struct pci_device *pci ) {
struct net_device *netdev = pci_get_drvdata ( pci );
struct rtl8139_nic *rtl = netdev->priv;
-
-#warning "Hack alert"
- rtl_close ( netdev );
-
if ( rtl->nvo.nvs )
nvo_unregister ( &rtl->nvo );
unregister_netdev ( netdev );
diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h
index 7551be74d..20df79193 100644
--- a/src/include/gpxe/netdevice.h
+++ b/src/include/gpxe/netdevice.h
@@ -142,6 +142,23 @@ struct net_device {
/** List of persistent reference holders */
struct list_head references;
+ /** Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ *
+ * This method should allocate RX packet buffers and enable
+ * the hardware to start transmitting and receiving packets.
+ */
+ int ( * open ) ( struct net_device *netdev );
+ /** Close network device
+ *
+ * @v netdev Network device
+ *
+ * This method should stop the flow of packets, and free up
+ * any packets that are currently in the device's TX queue.
+ */
+ void ( * close ) ( struct net_device *netdev );
/** Transmit packet
*
* @v netdev Network device
@@ -154,6 +171,9 @@ struct net_device {
* Ownership of the packet buffer is transferred to the @c
* net_device, which must eventually call free_pkb() to
* release the buffer.
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
*/
int ( * transmit ) ( struct net_device *netdev, struct pk_buff *pkb );
/** Poll for received packet
@@ -163,6 +183,9 @@ struct net_device {
* This method should cause the hardware to check for received
* packets. Any received packets should be delivered via
* netdev_rx().
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
*/
void ( * poll ) ( struct net_device *netdev );
@@ -174,6 +197,11 @@ struct net_device {
*/
uint8_t ll_addr[MAX_LL_ADDR_LEN];
+ /** Current device state
+ *
+ * This is the bitwise-OR of zero or more NETDEV_XXX constants.
+ */
+ unsigned int state;
/** Received packet queue */
struct list_head rx_queue;
@@ -181,6 +209,9 @@ struct net_device {
void *priv;
};
+/** Network device is open */
+#define NETDEV_OPEN 0x0001
+
/** Declare a link-layer protocol */
#define __ll_protocol __table ( ll_protocols, 01 )
@@ -209,6 +240,8 @@ extern int netdev_poll ( struct net_device *netdev );
extern struct pk_buff * netdev_rx_dequeue ( struct net_device *netdev );
extern struct net_device * alloc_netdev ( size_t priv_size );
extern int register_netdev ( struct net_device *netdev );
+extern int netdev_open ( struct net_device *netdev );
+extern void netdev_close ( struct net_device *netdev );
extern void unregister_netdev ( struct net_device *netdev );
extern void free_netdev ( struct net_device *netdev );
extern struct net_device * next_netdev ( void );
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 3949d26de..76ff3777b 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -54,6 +54,12 @@ static LIST_HEAD ( net_devices );
int netdev_tx ( struct net_device *netdev, struct pk_buff *pkb ) {
DBG ( "%s transmitting %p+%zx\n", netdev_name ( netdev ),
pkb->data, pkb_len ( pkb ) );
+
+ if ( ! ( netdev->state & NETDEV_OPEN ) ) {
+ free_pkb ( pkb );
+ return -ENETUNREACH;
+ }
+
return netdev->transmit ( netdev, pkb );
}
@@ -100,7 +106,7 @@ int net_tx ( struct pk_buff *pkb, struct net_device *netdev,
* @ret rc Return status code
*/
int net_rx ( struct pk_buff *pkb, struct net_device *netdev,
- uint16_t net_proto, const void *ll_source ) {
+ uint16_t net_proto, const void *ll_source ) {
struct net_protocol *net_protocol;
/* Hand off to network-layer protocol, if any */
@@ -125,7 +131,10 @@ int net_rx ( struct pk_buff *pkb, struct net_device *netdev,
* packets will be added to the RX packet queue via netdev_rx().
*/
int netdev_poll ( struct net_device *netdev ) {
- netdev->poll ( netdev );
+
+ if ( netdev->state & NETDEV_OPEN )
+ netdev->poll ( netdev );
+
return ( ! list_empty ( &netdev->rx_queue ) );
}
@@ -186,15 +195,46 @@ int register_netdev ( struct net_device *netdev ) {
}
/**
- * Unregister network device
+ * Open network device
*
* @v netdev Network device
+ * @ret rc Return status code
+ */
+int netdev_open ( struct net_device *netdev ) {
+ int rc;
+
+ /* Do nothing if device is already open */
+ if ( netdev->state & NETDEV_OPEN )
+ return 0;
+
+ DBG ( "%s opening\n", netdev_name ( netdev ) );
+
+ /* Open the device */
+ if ( ( rc = netdev->open ( netdev ) ) != 0 )
+ return rc;
+
+ /* Mark as opened */
+ netdev->state |= NETDEV_OPEN;
+ return 0;
+}
+
+/**
+ * Close network device
*
- * Removes the network device from the list of network devices.
+ * @v netdev Network device
*/
-void unregister_netdev ( struct net_device *netdev ) {
+void netdev_close ( struct net_device *netdev ) {
struct pk_buff *pkb;
+ /* Do nothing if device is already closed */
+ if ( ! ( netdev->state & NETDEV_OPEN ) )
+ return;
+
+ DBG ( "%s closing\n", netdev_name ( netdev ) );
+
+ /* Close the device */
+ netdev->close ( netdev );
+
/* Discard any packets in the RX queue */
while ( ( pkb = netdev_rx_dequeue ( netdev ) ) ) {
DBG ( "%s discarding %p+%zx\n", netdev_name ( netdev ),
@@ -202,6 +242,22 @@ void unregister_netdev ( struct net_device *netdev ) {
free_pkb ( pkb );
}
+ /* Mark as closed */
+ netdev->state &= ~NETDEV_OPEN;
+}
+
+/**
+ * Unregister network device
+ *
+ * @v netdev Network device
+ *
+ * Removes the network device from the list of network devices.
+ */
+void unregister_netdev ( struct net_device *netdev ) {
+
+ /* Ensure device is closed */
+ netdev_close ( netdev );
+
/* Kill off any persistent references to this device */
forget_references ( &netdev->references );
diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c
index ddfc37819..e67722981 100644
--- a/src/usr/autoboot.c
+++ b/src/usr/autoboot.c
@@ -16,7 +16,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <string.h>
#include <vsprintf.h>
+#include <gpxe/netdevice.h>
#include <gpxe/autoboot.h>
/** @file
@@ -30,11 +32,21 @@ void test_dhcp ( struct net_device *netdev );
void autoboot ( void ) {
struct net_device *netdev;
+ int rc;
netdev = next_netdev ();
- if ( netdev ) {
- test_dhcp ( netdev );
- } else {
+ if ( ! netdev ) {
printf ( "No network device found\n" );
+ return;
+ }
+
+ if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
+ printf ( "Could not open %s: %s\n", netdev_name ( netdev ),
+ strerror ( rc ) );
+ return;
}
+
+ test_dhcp ( netdev );
+
+ netdev_close ( netdev );
}