176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdint.h> 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h> 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <errno.h> 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/if_ether.h> 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/netdevice.h> 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/ethernet.h> 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/iobuf.h> 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <nic.h> 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Quick and dirty compatibility layer 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This should allow old-API PCI drivers to at least function until 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * they are updated. It will not help non-PCI drivers. 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * No drivers should rely on this code. It will be removed asap. 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2076d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER ); 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct nic nic; 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int legacy_registered = 0; 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int legacy_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct nic *nic = netdev->priv; 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct ethhdr *ethhdr; 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ( "Transmitting %zd bytes\n", iob_len ( iobuf ) ); 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman iob_pad ( iobuf, ETH_ZLEN ); 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ethhdr = iobuf->data; 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman iob_pull ( iobuf, sizeof ( *ethhdr ) ); 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest, 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ntohs ( ethhdr->h_protocol ), 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman iob_len ( iobuf ), iobuf->data ); 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev_tx_complete ( netdev, iobuf ); 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void legacy_poll ( struct net_device *netdev ) { 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct nic *nic = netdev->priv; 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct io_buffer *iobuf; 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman iobuf = alloc_iob ( ETH_FRAME_LEN ); 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! iobuf ) 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->packet = iobuf->data; 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( nic->nic_op->poll ( nic, 1 ) ) { 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ( "Received %d bytes\n", nic->packetlen ); 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman iob_put ( iobuf, nic->packetlen ); 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev_rx ( netdev, iobuf ); 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman free_iob ( iobuf ); 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int legacy_open ( struct net_device *netdev __unused ) { 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Nothing to do */ 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void legacy_close ( struct net_device *netdev __unused ) { 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Nothing to do */ 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void legacy_irq ( struct net_device *netdev __unused, int enable ) { 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct nic *nic = netdev->priv; 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->nic_op->irq ( nic, ( enable ? ENABLE : DISABLE ) ); 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct net_device_operations legacy_operations = { 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .open = legacy_open, 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .close = legacy_close, 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .transmit = legacy_transmit, 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .poll = legacy_poll, 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .irq = legacy_irq, 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint legacy_probe ( void *hwdev, 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman void ( * set_drvdata ) ( void *hwdev, void *priv ), 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct device *dev, 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int ( * probe ) ( struct nic *nic, void *hwdev ), 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman void ( * disable ) ( struct nic *nic, void *hwdev ) ) { 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct net_device *netdev; 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rc; 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( legacy_registered ) 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -EBUSY; 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev = alloc_etherdev ( 0 ); 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! netdev ) 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -ENOMEM; 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev_init ( netdev, &legacy_operations ); 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev->priv = &nic; 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset ( &nic, 0, sizeof ( nic ) ); 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman set_drvdata ( hwdev, netdev ); 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev->dev = dev; 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic.node_addr = netdev->hw_addr; 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic.irqno = dev->desc.irq; 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! probe ( &nic, hwdev ) ) { 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rc = -ENODEV; 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto err_probe; 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Overwrite the IRQ number. Some legacy devices set 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * nic->irqno to 0 in the probe routine to indicate that they 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * don't support interrupts; doing this allows the timer 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * interrupt to be used instead. 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dev->desc.irq = nic.irqno; 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Mark as link up; legacy devices don't handle link state */ 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev_link_up ( netdev ); 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( rc = register_netdev ( netdev ) ) != 0 ) 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto err_register; 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Do not remove this message */ 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "WARNING: Using legacy NIC wrapper on %s\n", 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev->ll_protocol->ntoa ( nic.node_addr ) ); 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman legacy_registered = 1; 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman err_register: 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman disable ( &nic, hwdev ); 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman err_probe: 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev_nullify ( netdev ); 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev_put ( netdev ); 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return rc; 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid legacy_remove ( void *hwdev, 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman void * ( * get_drvdata ) ( void *hwdev ), 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman void ( * disable ) ( struct nic *nic, void *hwdev ) ) { 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct net_device *netdev = get_drvdata ( hwdev ); 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct nic *nic = netdev->priv; 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unregister_netdev ( netdev ); 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman disable ( nic, hwdev ); 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev_nullify ( netdev ); 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman netdev_put ( netdev ); 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman legacy_registered = 0; 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint dummy_connect ( struct nic *nic __unused ) { 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) { 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 158