Use net_device_operations structure and netdev_nullify() to allow for
[people/sha0/gpxe.git] / src / drivers / net / legacy.c
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 struct nic nic;
21
22 static int legacy_registered = 0;
23
24 static int legacy_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
25         struct nic *nic = netdev->priv;
26         struct ethhdr *ethhdr;
27
28         DBG ( "Transmitting %d bytes\n", iob_len ( iobuf ) );
29         iob_pad ( iobuf, ETH_ZLEN );
30         ethhdr = iobuf->data;
31         iob_pull ( iobuf, sizeof ( *ethhdr ) );
32         nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest,
33                                 ntohs ( ethhdr->h_protocol ),
34                                 iob_len ( iobuf ), iobuf->data );
35         netdev_tx_complete ( netdev, iobuf );
36         return 0;
37 }
38
39 static void legacy_poll ( struct net_device *netdev ) {
40         struct nic *nic = netdev->priv;
41         struct io_buffer *iobuf;
42
43         iobuf = alloc_iob ( ETH_FRAME_LEN );
44         if ( ! iobuf )
45                 return;
46
47         nic->packet = iobuf->data;
48         if ( nic->nic_op->poll ( nic, 1 ) ) {
49                 DBG ( "Received %d bytes\n", nic->packetlen );
50                 iob_put ( iobuf, nic->packetlen );
51                 netdev_rx ( netdev, iobuf );
52         } else {
53                 free_iob ( iobuf );
54         }
55 }
56
57 static int legacy_open ( struct net_device *netdev __unused ) {
58         /* Nothing to do */
59         return 0;
60 }
61
62 static void legacy_close ( struct net_device *netdev __unused ) {
63         /* Nothing to do */
64 }
65
66 static void legacy_irq ( struct net_device *netdev __unused, int enable ) {
67         struct nic *nic = netdev->priv;
68
69         nic->nic_op->irq ( nic, ( enable ? ENABLE : DISABLE ) );
70 }
71
72 static struct net_device_operations legacy_operations = {
73         .open           = legacy_open,
74         .close          = legacy_close,
75         .transmit       = legacy_transmit,
76         .poll           = legacy_poll,
77         .irq            = legacy_irq,
78 };
79
80 int legacy_probe ( void *hwdev,
81                    void ( * set_drvdata ) ( void *hwdev, void *priv ),
82                    struct device *dev,
83                    int ( * probe ) ( struct nic *nic, void *hwdev ),
84                    void ( * disable ) ( struct nic *nic, void *hwdev ) ) {
85         struct net_device *netdev;
86         int rc;
87
88         if ( legacy_registered )
89                 return -EBUSY;
90         
91         netdev = alloc_etherdev ( 0 );
92         if ( ! netdev )
93                 return -ENOMEM;
94         netdev_init ( netdev, &legacy_operations );
95         netdev->priv = &nic;
96         memset ( &nic, 0, sizeof ( nic ) );
97         set_drvdata ( hwdev, netdev );
98         netdev->dev = dev;
99
100         nic.node_addr = netdev->ll_addr;
101
102         if ( ! probe ( &nic, hwdev ) ) {
103                 rc = -ENODEV;
104                 goto err_probe;
105         }
106
107         if ( ( rc = register_netdev ( netdev ) ) != 0 )
108                 goto err_register;
109
110         /* Do not remove this message */
111         printf ( "WARNING: Using legacy NIC wrapper on %s\n",
112                  ethernet_protocol.ntoa ( nic.node_addr ) );
113
114         legacy_registered = 1;
115         return 0;
116
117  err_register:
118         disable ( &nic, hwdev );
119  err_probe:
120         netdev_nullify ( netdev );
121         netdev_put ( netdev );
122         return rc;
123 }
124
125 void legacy_remove ( void *hwdev,
126                      void * ( * get_drvdata ) ( void *hwdev ),
127                      void ( * disable ) ( struct nic *nic, void *hwdev ) ) {
128         struct net_device *netdev = get_drvdata ( hwdev );
129         struct nic *nic = netdev->priv;
130
131         unregister_netdev ( netdev );
132         disable ( nic, hwdev );
133         netdev_nullify ( netdev );
134         netdev_put ( netdev );
135         legacy_registered = 0;
136 }
137
138 int dummy_connect ( struct nic *nic __unused ) {
139         return 1;
140 }
141
142 void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
143         return;
144 }