Make open() and close() an official part of the netdevice API.
[people/dverkamp/gpxe.git] / src / drivers / net / legacy.c
1 #include <stdint.h>
2 #include <errno.h>
3 #include <vsprintf.h>
4 #include <gpxe/if_ether.h>
5 #include <gpxe/netdevice.h>
6 #include <gpxe/ethernet.h>
7 #include <gpxe/pkbuff.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 struct nic nic;
21
22 static int legacy_registered = 0;
23
24 static int legacy_transmit ( struct net_device *netdev, struct pk_buff *pkb ) {
25         struct nic *nic = netdev->priv;
26         struct ethhdr *ethhdr = pkb->data;
27         int pad_len;
28
29         DBG ( "Transmitting %d bytes\n", pkb_len ( pkb ) );
30         pad_len = ( ETH_ZLEN - pkb_len ( pkb ) );
31         if ( pad_len > 0 )
32                 memset ( pkb_put ( pkb, pad_len ), 0, pad_len );
33         pkb_pull ( pkb, sizeof ( *ethhdr ) );
34         nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest,
35                                 ntohs ( ethhdr->h_protocol ),
36                                 pkb_len ( pkb ), pkb->data );
37         free_pkb ( pkb );
38         return 0;
39 }
40
41 static void legacy_poll ( struct net_device *netdev ) {
42         struct nic *nic = netdev->priv;
43         struct pk_buff *pkb;
44
45         pkb = alloc_pkb ( ETH_FRAME_LEN );
46         if ( ! pkb )
47                 return;
48
49         nic->packet = pkb->data;
50         if ( nic->nic_op->poll ( nic, 1 ) ) {
51                 DBG ( "Received %d bytes\n", nic->packetlen );
52                 pkb_put ( pkb, nic->packetlen );
53                 netdev_rx ( netdev, pkb );
54         } else {
55                 free_pkb ( pkb );
56         }
57 }
58
59 static int legacy_open ( struct net_device *netdev __unused ) {
60         return 0;
61 }
62
63 static void legacy_close ( struct net_device *netdev __unused ) {
64         /* Nothing to do */
65 }
66
67 int legacy_probe ( struct pci_device *pci,
68                    const struct pci_device_id *id __unused,
69                    int ( * probe ) ( struct nic *nic,
70                                      struct pci_device *pci ),
71                    void ( * disable ) ( struct nic *nic ) ) {
72         struct net_device *netdev;
73         int rc;
74
75         if ( legacy_registered )
76                 return -EBUSY;
77         
78         netdev = alloc_etherdev ( 0 );
79         if ( ! netdev )
80                 return -ENOMEM;
81         netdev->priv = &nic;
82         memset ( &nic, 0, sizeof ( nic ) );
83         pci_set_drvdata ( pci, netdev );
84
85         netdev->open = legacy_open;
86         netdev->close = legacy_close;
87         netdev->transmit = legacy_transmit;
88         netdev->poll = legacy_poll;
89         nic.node_addr = netdev->ll_addr;
90
91         if ( ! probe ( &nic, pci ) ) {
92                 free_netdev ( netdev );
93                 return -ENODEV;
94         }
95
96         if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
97                 disable ( &nic );
98                 free_netdev ( netdev );
99                 return rc;
100         }
101
102         /* Do not remove this message */
103         printf ( "WARNING: Using legacy NIC wrapper on %s\n",
104                  ethernet_protocol.ntoa ( nic.node_addr ) );
105
106         legacy_registered = 1;
107         return 0;
108 }
109
110 void legacy_remove ( struct pci_device *pci,
111                      void ( * disable ) ( struct nic *nic ) ) {
112         struct net_device *netdev = pci_get_drvdata ( pci );
113         struct nic *nic = netdev->priv;
114
115         unregister_netdev ( netdev );
116         disable ( nic );
117         free_netdev ( netdev );
118         legacy_registered = 0;
119 }
120
121 void pci_fill_nic ( struct nic *nic, struct pci_device *pci ) {
122         nic->ioaddr = pci->ioaddr;
123         nic->irqno = pci->irq;
124 }
125
126 int dummy_connect ( struct nic *nic __unused ) {
127         return 1;
128 }
129
130 void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
131         return;
132 }
133
134 REQUIRE_OBJECT ( pci );