Home | History | Annotate | Download | only in net
      1 #include <stdint.h>
      2 #include <stdio.h>
      3 #include <errno.h>
      4 #include <gpxe/if_ether.h>
      5 #include <gpxe/netdevice.h>
      6 #include <gpxe/ethernet.h>
      7 #include <gpxe/iobuf.h>
      8 #include <nic.h>
      9 
     10 /*
     11  * Quick and dirty compatibility layer
     12  *
     13  * This should allow old-API PCI drivers to at least function until
     14  * they are updated.  It will not help non-PCI drivers.
     15  *
     16  * No drivers should rely on this code.  It will be removed asap.
     17  *
     18  */
     19 
     20 FILE_LICENCE ( GPL2_OR_LATER );
     21 
     22 struct nic nic;
     23 
     24 static int legacy_registered = 0;
     25 
     26 static int legacy_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
     27 	struct nic *nic = netdev->priv;
     28 	struct ethhdr *ethhdr;
     29 
     30 	DBG ( "Transmitting %zd bytes\n", iob_len ( iobuf ) );
     31 	iob_pad ( iobuf, ETH_ZLEN );
     32 	ethhdr = iobuf->data;
     33 	iob_pull ( iobuf, sizeof ( *ethhdr ) );
     34 	nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest,
     35 				ntohs ( ethhdr->h_protocol ),
     36 				iob_len ( iobuf ), iobuf->data );
     37 	netdev_tx_complete ( netdev, iobuf );
     38 	return 0;
     39 }
     40 
     41 static void legacy_poll ( struct net_device *netdev ) {
     42 	struct nic *nic = netdev->priv;
     43 	struct io_buffer *iobuf;
     44 
     45 	iobuf = alloc_iob ( ETH_FRAME_LEN );
     46 	if ( ! iobuf )
     47 		return;
     48 
     49 	nic->packet = iobuf->data;
     50 	if ( nic->nic_op->poll ( nic, 1 ) ) {
     51 		DBG ( "Received %d bytes\n", nic->packetlen );
     52 		iob_put ( iobuf, nic->packetlen );
     53 		netdev_rx ( netdev, iobuf );
     54 	} else {
     55 		free_iob ( iobuf );
     56 	}
     57 }
     58 
     59 static int legacy_open ( struct net_device *netdev __unused ) {
     60 	/* Nothing to do */
     61 	return 0;
     62 }
     63 
     64 static void legacy_close ( struct net_device *netdev __unused ) {
     65 	/* Nothing to do */
     66 }
     67 
     68 static void legacy_irq ( struct net_device *netdev __unused, int enable ) {
     69 	struct nic *nic = netdev->priv;
     70 
     71 	nic->nic_op->irq ( nic, ( enable ? ENABLE : DISABLE ) );
     72 }
     73 
     74 static struct net_device_operations legacy_operations = {
     75 	.open		= legacy_open,
     76 	.close		= legacy_close,
     77 	.transmit	= legacy_transmit,
     78 	.poll		= legacy_poll,
     79 	.irq   		= legacy_irq,
     80 };
     81 
     82 int legacy_probe ( void *hwdev,
     83 		   void ( * set_drvdata ) ( void *hwdev, void *priv ),
     84 		   struct device *dev,
     85 		   int ( * probe ) ( struct nic *nic, void *hwdev ),
     86 		   void ( * disable ) ( struct nic *nic, void *hwdev ) ) {
     87 	struct net_device *netdev;
     88 	int rc;
     89 
     90 	if ( legacy_registered )
     91 		return -EBUSY;
     92 
     93 	netdev = alloc_etherdev ( 0 );
     94 	if ( ! netdev )
     95 		return -ENOMEM;
     96 	netdev_init ( netdev, &legacy_operations );
     97 	netdev->priv = &nic;
     98 	memset ( &nic, 0, sizeof ( nic ) );
     99 	set_drvdata ( hwdev, netdev );
    100 	netdev->dev = dev;
    101 
    102 	nic.node_addr = netdev->hw_addr;
    103 	nic.irqno = dev->desc.irq;
    104 
    105 	if ( ! probe ( &nic, hwdev ) ) {
    106 		rc = -ENODEV;
    107 		goto err_probe;
    108 	}
    109 
    110 	/* Overwrite the IRQ number.  Some legacy devices set
    111 	 * nic->irqno to 0 in the probe routine to indicate that they
    112 	 * don't support interrupts; doing this allows the timer
    113 	 * interrupt to be used instead.
    114 	 */
    115 	dev->desc.irq = nic.irqno;
    116 
    117 	/* Mark as link up; legacy devices don't handle link state */
    118 	netdev_link_up ( netdev );
    119 
    120 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
    121 		goto err_register;
    122 
    123 	/* Do not remove this message */
    124 	printf ( "WARNING: Using legacy NIC wrapper on %s\n",
    125 		 netdev->ll_protocol->ntoa ( nic.node_addr ) );
    126 
    127 	legacy_registered = 1;
    128 	return 0;
    129 
    130  err_register:
    131 	disable ( &nic, hwdev );
    132  err_probe:
    133 	netdev_nullify ( netdev );
    134 	netdev_put ( netdev );
    135 	return rc;
    136 }
    137 
    138 void legacy_remove ( void *hwdev,
    139 		     void * ( * get_drvdata ) ( void *hwdev ),
    140 		     void ( * disable ) ( struct nic *nic, void *hwdev ) ) {
    141 	struct net_device *netdev = get_drvdata ( hwdev );
    142 	struct nic *nic = netdev->priv;
    143 
    144 	unregister_netdev ( netdev );
    145 	disable ( nic, hwdev );
    146 	netdev_nullify ( netdev );
    147 	netdev_put ( netdev );
    148 	legacy_registered = 0;
    149 }
    150 
    151 int dummy_connect ( struct nic *nic __unused ) {
    152 	return 1;
    153 }
    154 
    155 void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
    156 	return;
    157 }
    158