diff options
Diffstat (limited to 'contrib/syslinux-4.02/gpxe/src/drivers/net/legacy.c')
-rw-r--r-- | contrib/syslinux-4.02/gpxe/src/drivers/net/legacy.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/gpxe/src/drivers/net/legacy.c b/contrib/syslinux-4.02/gpxe/src/drivers/net/legacy.c new file mode 100644 index 0000000..79b3580 --- /dev/null +++ b/contrib/syslinux-4.02/gpxe/src/drivers/net/legacy.c @@ -0,0 +1,157 @@ +#include <stdint.h> +#include <stdio.h> +#include <errno.h> +#include <gpxe/if_ether.h> +#include <gpxe/netdevice.h> +#include <gpxe/ethernet.h> +#include <gpxe/iobuf.h> +#include <nic.h> + +/* + * Quick and dirty compatibility layer + * + * This should allow old-API PCI drivers to at least function until + * they are updated. It will not help non-PCI drivers. + * + * No drivers should rely on this code. It will be removed asap. + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +struct nic nic; + +static int legacy_registered = 0; + +static int legacy_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { + struct nic *nic = netdev->priv; + struct ethhdr *ethhdr; + + DBG ( "Transmitting %zd bytes\n", iob_len ( iobuf ) ); + iob_pad ( iobuf, ETH_ZLEN ); + ethhdr = iobuf->data; + iob_pull ( iobuf, sizeof ( *ethhdr ) ); + nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest, + ntohs ( ethhdr->h_protocol ), + iob_len ( iobuf ), iobuf->data ); + netdev_tx_complete ( netdev, iobuf ); + return 0; +} + +static void legacy_poll ( struct net_device *netdev ) { + struct nic *nic = netdev->priv; + struct io_buffer *iobuf; + + iobuf = alloc_iob ( ETH_FRAME_LEN ); + if ( ! iobuf ) + return; + + nic->packet = iobuf->data; + if ( nic->nic_op->poll ( nic, 1 ) ) { + DBG ( "Received %d bytes\n", nic->packetlen ); + iob_put ( iobuf, nic->packetlen ); + netdev_rx ( netdev, iobuf ); + } else { + free_iob ( iobuf ); + } +} + +static int legacy_open ( struct net_device *netdev __unused ) { + /* Nothing to do */ + return 0; +} + +static void legacy_close ( struct net_device *netdev __unused ) { + /* Nothing to do */ +} + +static void legacy_irq ( struct net_device *netdev __unused, int enable ) { + struct nic *nic = netdev->priv; + + nic->nic_op->irq ( nic, ( enable ? ENABLE : DISABLE ) ); +} + +static struct net_device_operations legacy_operations = { + .open = legacy_open, + .close = legacy_close, + .transmit = legacy_transmit, + .poll = legacy_poll, + .irq = legacy_irq, +}; + +int legacy_probe ( void *hwdev, + void ( * set_drvdata ) ( void *hwdev, void *priv ), + struct device *dev, + int ( * probe ) ( struct nic *nic, void *hwdev ), + void ( * disable ) ( struct nic *nic, void *hwdev ) ) { + struct net_device *netdev; + int rc; + + if ( legacy_registered ) + return -EBUSY; + + netdev = alloc_etherdev ( 0 ); + if ( ! netdev ) + return -ENOMEM; + netdev_init ( netdev, &legacy_operations ); + netdev->priv = &nic; + memset ( &nic, 0, sizeof ( nic ) ); + set_drvdata ( hwdev, netdev ); + netdev->dev = dev; + + nic.node_addr = netdev->hw_addr; + nic.irqno = dev->desc.irq; + + if ( ! probe ( &nic, hwdev ) ) { + rc = -ENODEV; + goto err_probe; + } + + /* Overwrite the IRQ number. Some legacy devices set + * nic->irqno to 0 in the probe routine to indicate that they + * don't support interrupts; doing this allows the timer + * interrupt to be used instead. + */ + dev->desc.irq = nic.irqno; + + /* Mark as link up; legacy devices don't handle link state */ + netdev_link_up ( netdev ); + + if ( ( rc = register_netdev ( netdev ) ) != 0 ) + goto err_register; + + /* Do not remove this message */ + printf ( "WARNING: Using legacy NIC wrapper on %s\n", + netdev->ll_protocol->ntoa ( nic.node_addr ) ); + + legacy_registered = 1; + return 0; + + err_register: + disable ( &nic, hwdev ); + err_probe: + netdev_nullify ( netdev ); + netdev_put ( netdev ); + return rc; +} + +void legacy_remove ( void *hwdev, + void * ( * get_drvdata ) ( void *hwdev ), + void ( * disable ) ( struct nic *nic, void *hwdev ) ) { + struct net_device *netdev = get_drvdata ( hwdev ); + struct nic *nic = netdev->priv; + + unregister_netdev ( netdev ); + disable ( nic, hwdev ); + netdev_nullify ( netdev ); + netdev_put ( netdev ); + legacy_registered = 0; +} + +int dummy_connect ( struct nic *nic __unused ) { + return 1; +} + +void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) { + return; +} |