1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <gpxe/if_ether.h>
#include <gpxe/netdevice.h>
#include <gpxe/ethernet.h>
#include <gpxe/iobuf.h>
#include <nic.h>
/*
* Quick and dirty compatibility layer
*
* This should allow old-API PCI drivers to at least function until
* they are updated. It will not help non-PCI drivers.
*
* No drivers should rely on this code. It will be removed asap.
*
*/
struct nic nic;
static int legacy_registered = 0;
static int legacy_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
struct nic *nic = netdev->priv;
struct ethhdr *ethhdr;
DBG ( "Transmitting %d bytes\n", iob_len ( iobuf ) );
iob_pad ( iobuf, ETH_ZLEN );
ethhdr = iobuf->data;
iob_pull ( iobuf, sizeof ( *ethhdr ) );
nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest,
ntohs ( ethhdr->h_protocol ),
iob_len ( iobuf ), iobuf->data );
netdev_tx_complete ( netdev, iobuf );
return 0;
}
static void legacy_poll ( struct net_device *netdev, unsigned int rx_quota ) {
struct nic *nic = netdev->priv;
struct io_buffer *iobuf;
if ( ! rx_quota )
return;
iobuf = alloc_iob ( ETH_FRAME_LEN );
if ( ! iobuf )
return;
nic->packet = iobuf->data;
if ( nic->nic_op->poll ( nic, 1 ) ) {
DBG ( "Received %d bytes\n", nic->packetlen );
iob_put ( iobuf, nic->packetlen );
netdev_rx ( netdev, iobuf );
} else {
free_iob ( iobuf );
}
}
static int legacy_open ( struct net_device *netdev ) {
struct nic *nic = netdev->priv;
nic->nic_op->irq ( nic, ENABLE );
return 0;
}
static void legacy_close ( struct net_device *netdev ) {
struct nic *nic = netdev->priv;
nic->nic_op->irq ( nic, DISABLE );
}
int legacy_probe ( void *hwdev,
void ( * set_drvdata ) ( void *hwdev, void *priv ),
struct device *dev,
int ( * probe ) ( struct nic *nic, void *hwdev ),
void ( * disable ) ( struct nic *nic, void *hwdev ) ) {
struct net_device *netdev;
int rc;
if ( legacy_registered )
return -EBUSY;
netdev = alloc_etherdev ( 0 );
if ( ! netdev )
return -ENOMEM;
netdev->priv = &nic;
memset ( &nic, 0, sizeof ( nic ) );
set_drvdata ( hwdev, netdev );
netdev->dev = dev;
netdev->open = legacy_open;
netdev->close = legacy_close;
netdev->transmit = legacy_transmit;
netdev->poll = legacy_poll;
nic.node_addr = netdev->ll_addr;
if ( ! probe ( &nic, hwdev ) ) {
netdev_put ( netdev );
return -ENODEV;
}
if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
disable ( &nic, hwdev );
netdev_put ( netdev );
return rc;
}
/* Do not remove this message */
printf ( "WARNING: Using legacy NIC wrapper on %s\n",
ethernet_protocol.ntoa ( nic.node_addr ) );
legacy_registered = 1;
return 0;
}
void legacy_remove ( void *hwdev,
void * ( * get_drvdata ) ( void *hwdev ),
void ( * disable ) ( struct nic *nic, void *hwdev ) ) {
struct net_device *netdev = get_drvdata ( hwdev );
struct nic *nic = netdev->priv;
unregister_netdev ( netdev );
disable ( nic, hwdev );
netdev_put ( netdev );
legacy_registered = 0;
}
int dummy_connect ( struct nic *nic __unused ) {
return 1;
}
void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
return;
}
|