david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Make open() and close() an official part of the netdevice API.

Call netdevice's poll() and transmit() methods only when device is open.
This commit is contained in:
Michael Brown 2007-01-04 04:20:08 +00:00
parent d4894f0127
commit 0c03bb5a9a
6 changed files with 138 additions and 19 deletions

View File

@ -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;

View File

@ -185,6 +185,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
***************************************************************************/
@ -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;

View File

@ -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 );

View File

@ -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 );

View File

@ -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
*
* Removes the network device from the list of network devices.
* @ret rc Return status code
*/
void unregister_netdev ( struct net_device *netdev ) {
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
*
* @v netdev Network device
*/
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 );

View File

@ -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 );
}