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