Legacy drivers cannot cope with multiple active devices.
[people/xl0/gpxe.git] / src / drivers / net / legacy.c
1 #include <stdint.h>
2 #include <errno.h>
3 #include <gpxe/if_ether.h>
4 #include <gpxe/netdevice.h>
5 #include <gpxe/ethernet.h>
6 #include <gpxe/pkbuff.h>
7 #include <nic.h>
8
9 /*
10  * Quick and dirty compatibility layer
11  *
12  * This should allow old-API PCI drivers to at least function until
13  * they are updated.  It will not help non-PCI drivers.
14  *
15  * No drivers should rely on this code.  It will be removed asap.
16  *
17  */
18
19 struct nic nic;
20
21 static int legacy_registered = 0;
22
23 static int legacy_transmit ( struct net_device *netdev, struct pk_buff *pkb ) {
24         struct nic *nic = netdev->priv;
25         struct ethhdr *ethhdr = pkb->data;
26         int pad_len;
27
28         pad_len = ( ETH_ZLEN - pkb_len ( pkb ) );
29         if ( pad_len > 0 )
30                 memset ( pkb_put ( pkb, pad_len ), 0, pad_len );
31         pkb_pull ( pkb, sizeof ( *ethhdr ) );
32         nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest,
33                                 ntohs ( ethhdr->h_protocol ),
34                                 pkb_len ( pkb ), pkb->data );
35         free_pkb ( pkb );
36         return 0;
37 }
38
39 static void legacy_poll ( struct net_device *netdev ) {
40         struct nic *nic = netdev->priv;
41         struct pk_buff *pkb;
42
43         pkb = alloc_pkb ( ETH_FRAME_LEN );
44         if ( ! pkb )
45                 return;
46
47         nic->packet = pkb->data;
48         if ( nic->nic_op->poll ( nic, 1 ) ) {
49                 pkb_put ( pkb, nic->packetlen );
50                 netdev_rx ( netdev, pkb );
51         } else {
52                 free_pkb ( pkb );
53         }
54 }
55
56 int legacy_probe ( struct pci_device *pci,
57                    const struct pci_device_id *id __unused,
58                    int ( * probe ) ( struct nic *nic,
59                                      struct pci_device *pci ),
60                    void ( * disable ) ( struct nic *nic ) ) {
61         struct net_device *netdev;
62         int rc;
63
64         if ( legacy_registered )
65                 return -EBUSY;
66         
67         netdev = alloc_etherdev ( 0 );
68         if ( ! netdev )
69                 return -ENOMEM;
70         netdev->priv = &nic;
71         memset ( &nic, 0, sizeof ( nic ) );
72         pci_set_drvdata ( pci, netdev );
73
74         netdev->transmit = legacy_transmit;
75         netdev->poll = legacy_poll;
76         nic.node_addr = netdev->ll_addr;
77
78         if ( ! probe ( &nic, pci ) ) {
79                 free_netdev ( netdev );
80                 return -ENODEV;
81         }
82
83         if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
84                 disable ( &nic );
85                 free_netdev ( netdev );
86                 return rc;
87         }
88
89         /* Do not remove this message */
90         printf ( "WARNING: Using legacy NIC wrapper\n" );
91
92         legacy_registered = 1;
93         return 0;
94 }
95
96 void legacy_remove ( struct pci_device *pci,
97                      void ( * disable ) ( struct nic *nic ) ) {
98         struct net_device *netdev = pci_get_drvdata ( pci );
99         struct nic *nic = netdev->priv;
100
101         unregister_netdev ( netdev );
102         disable ( nic );
103         free_netdev ( netdev );
104         legacy_registered = 0;
105 }
106
107 void pci_fill_nic ( struct nic *nic, struct pci_device *pci ) {
108         nic->ioaddr = pci->ioaddr;
109         nic->irqno = pci->irq;
110 }
111
112 int dummy_connect ( struct nic *nic __unused ) {
113         return 1;
114 }
115
116 void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
117         return;
118 }
119
120 REQUIRE_OBJECT ( pci );