iPXE
legacy.c
Go to the documentation of this file.
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <errno.h>
4 #include <ipxe/if_ether.h>
5 #include <ipxe/netdevice.h>
6 #include <ipxe/ethernet.h>
7 #include <ipxe/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 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
21 
22 struct nic legacy_nic;
23 
24 static int legacy_registered = 0;
25 
26 static int legacy_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
27  struct nic *nic = netdev->priv;
28  struct ethhdr *ethhdr;
29 
30  DBG ( "Transmitting %zd bytes\n", iob_len ( iobuf ) );
31  iob_pad ( iobuf, ETH_ZLEN );
32  ethhdr = iobuf->data;
33  iob_pull ( iobuf, sizeof ( *ethhdr ) );
34  nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest,
35  ntohs ( ethhdr->h_protocol ),
36  iob_len ( iobuf ), iobuf->data );
37  netdev_tx_complete ( netdev, iobuf );
38  return 0;
39 }
40 
41 static void legacy_poll ( struct net_device *netdev ) {
42  struct nic *nic = netdev->priv;
43  struct io_buffer *iobuf;
44 
45  iobuf = alloc_iob ( ETH_FRAME_LEN + 4 /* possible VLAN */
46  + 4 /* possible CRC */ );
47  if ( ! iobuf )
48  return;
49 
50  nic->packet = iobuf->data;
51  if ( nic->nic_op->poll ( nic, 1 ) ) {
52  DBG ( "Received %d bytes\n", nic->packetlen );
53  iob_put ( iobuf, nic->packetlen );
54  netdev_rx ( netdev, iobuf );
55  } else {
56  free_iob ( iobuf );
57  }
58 }
59 
60 static int legacy_open ( struct net_device *netdev __unused ) {
61  /* Nothing to do */
62  return 0;
63 }
64 
65 static void legacy_close ( struct net_device *netdev __unused ) {
66  /* Nothing to do */
67 }
68 
69 static void legacy_irq ( struct net_device *netdev __unused, int enable ) {
70  struct nic *nic = netdev->priv;
71 
72  nic->nic_op->irq ( nic, ( enable ? ENABLE : DISABLE ) );
73 }
74 
76  .open = legacy_open,
77  .close = legacy_close,
78  .transmit = legacy_transmit,
79  .poll = legacy_poll,
80  .irq = legacy_irq,
81 };
82 
83 int legacy_probe ( void *hwdev,
84  void ( * set_drvdata ) ( void *hwdev, void *priv ),
85  struct device *dev,
86  int ( * probe ) ( struct nic *nic, void *hwdev ),
87  void ( * disable ) ( struct nic *nic, void *hwdev ),
88  size_t fake_bss_len ) {
89  struct net_device *netdev;
90  struct nic *nic;
91  int rc;
92 
93  if ( legacy_registered ) {
94  rc = -EBUSY;
95  goto err_registered;
96  }
97 
98  netdev = alloc_etherdev ( 0 );
99  if ( ! netdev ) {
100  rc = -ENOMEM;
101  goto err_alloc;
102  }
104  nic = &legacy_nic;
105  netdev->priv = nic;
106  memset ( nic, 0, sizeof ( *nic ) );
107  set_drvdata ( hwdev, netdev );
108  netdev->dev = dev;
109 
111  nic->irqno = dev->desc.irq;
112 
113  if ( fake_bss_len ) {
115  if ( ! nic->fake_bss ) {
116  rc = -ENOMEM;
117  goto err_fake_bss;
118  }
119  }
121 
122  if ( ! probe ( nic, hwdev ) ) {
123  rc = -ENODEV;
124  goto err_probe;
125  }
126 
127  /* Overwrite the IRQ number. Some legacy devices set
128  * nic->irqno to 0 in the probe routine to indicate that they
129  * don't support interrupts; doing this allows the timer
130  * interrupt to be used instead.
131  */
132  dev->desc.irq = nic->irqno;
133 
134  if ( ( rc = register_netdev ( netdev ) ) != 0 )
135  goto err_register;
136 
137  /* Mark as link up; legacy devices don't handle link state */
139 
140  /* Do not remove this message */
141  printf ( "WARNING: Using legacy NIC wrapper on %s\n",
143 
144  legacy_registered = 1;
145  return 0;
146 
147  err_register:
148  disable ( nic, hwdev );
149  err_probe:
150  if ( fake_bss_len )
152  err_fake_bss:
154  netdev_put ( netdev );
155  err_alloc:
156  err_registered:
157  return rc;
158 }
159 
160 void legacy_remove ( void *hwdev,
161  void * ( * get_drvdata ) ( void *hwdev ),
162  void ( * disable ) ( struct nic *nic, void *hwdev ) ) {
163  struct net_device *netdev = get_drvdata ( hwdev );
164  struct nic *nic = netdev->priv;
165 
167  disable ( nic, hwdev );
168  if ( nic->fake_bss_len )
171  netdev_put ( netdev );
172  legacy_registered = 0;
173 }
174 
175 int dummy_connect ( struct nic *nic __unused ) {
176  return 1;
177 }
178 
179 void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
180  return;
181 }
unsigned char irqno
Definition: nic.h:56
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), size_t fake_bss_len)
Definition: legacy.c:83
uint16_t h_protocol
Protocol ID.
Definition: if_ether.h:37
#define iob_pull(iobuf, len)
Definition: iobuf.h:106
Definition: nic.h:35
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int(* poll)(struct nic *, int retrieve)
Definition: nic.h:70
static void netdev_tx_complete(struct net_device *netdev, struct io_buffer *iobuf)
Complete network transmission.
Definition: netdevice.h:766
#define iob_put(iobuf, len)
Definition: iobuf.h:124
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
void * fake_bss
Definition: nic.h:60
#define EBUSY
Device or resource busy.
Definition: errno.h:338
int(* open)(struct net_device *netdev)
Open network device.
Definition: netdevice.h:222
struct nic legacy_nic
Definition: legacy.c:22
Error codes.
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:152
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static int legacy_transmit(struct net_device *netdev, struct io_buffer *iobuf)
Definition: legacy.c:26
#define ntohs(value)
Definition: byteswap.h:136
void(* irq)(struct nic *, irq_action_t)
Definition: nic.h:73
#define PAGE_SIZE
Page size.
Definition: io.h:27
void(* transmit)(struct nic *, const char *, unsigned int, unsigned int, const char *)
Definition: nic.h:71
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:130
int dummy_connect(struct nic *nic __unused)
Definition: legacy.c:175
static struct net_device_operations legacy_operations
Definition: legacy.c:75
static void netdev_init(struct net_device *netdev, struct net_device_operations *op)
Initialise a network device.
Definition: netdevice.h:518
uint8_t h_dest[ETH_ALEN]
Destination MAC address.
Definition: if_ether.h:33
#define ENOMEM
Not enough space.
Definition: errno.h:534
A hardware device.
Definition: device.h:76
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:575
Ethernet protocol.
unsigned int irq
IRQ.
Definition: device.h:39
#define ETH_FRAME_LEN
Definition: if_ether.h:11
void * priv
Driver private data.
Definition: netdevice.h:431
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
static void netdev_link_up(struct net_device *netdev)
Mark network device as having link up.
Definition: netdevice.h:788
static struct net_device * netdev
Definition: gdbudp.c:52
irq_action_t
Definition: nic.h:34
void unregister_netdev(struct net_device *netdev)
Unregister network device.
Definition: netdevice.c:941
void dummy_irq(struct nic *nic __unused, irq_action_t irq_action __unused)
Definition: legacy.c:179
unsigned int packetlen
Definition: nic.h:54
int register_netdev(struct net_device *netdev)
Register network device.
Definition: netdevice.c:759
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:159
A network device.
Definition: netdevice.h:352
#define ENODEV
No such device.
Definition: errno.h:509
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition: netdevice.h:531
#define ETH_ZLEN
Definition: if_ether.h:10
Definition: nic.h:49
void legacy_remove(void *hwdev, void *(*get_drvdata)(void *hwdev), void(*disable)(struct nic *nic, void *hwdev))
Definition: legacy.c:160
Network device operations.
Definition: netdevice.h:213
void netdev_rx(struct net_device *netdev, struct io_buffer *iobuf)
Add packet to receive queue.
Definition: netdevice.c:548
struct device * dev
Underlying hardware device.
Definition: netdevice.h:364
Network device management.
Definition: nic.h:36
unsigned char * packet
Definition: nic.h:53
unsigned char * node_addr
Definition: nic.h:52
static struct tlan_private * priv
Definition: tlan.c:225
void * data
Start of data.
Definition: iobuf.h:52
void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys()
Definition: malloc.c:722
struct net_device * alloc_etherdev(size_t priv_size)
Allocate Ethernet device.
Definition: ethernet.c:264
struct device_description desc
Device description.
Definition: device.h:82
const char *(* ntoa)(const void *ll_addr)
Transcribe link-layer address.
Definition: netdevice.h:163
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static void legacy_close(struct net_device *netdev __unused)
Definition: legacy.c:65
struct nic_operations * nic_op
Definition: nic.h:50
static void legacy_irq(struct net_device *netdev __unused, int enable)
Definition: legacy.c:69
static void legacy_poll(struct net_device *netdev)
Definition: legacy.c:41
An Ethernet link-layer header.
Definition: if_ether.h:31
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition: netdevice.h:381
static int legacy_registered
Definition: legacy.c:24
void iob_pad(struct io_buffer *iobuf, size_t min_len)
Pad I/O buffer.
Definition: iobpad.c:49
size_t fake_bss_len
Definition: nic.h:61
struct ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:372
void * malloc_phys(size_t size, size_t phys_align)
Allocate memory with specified physical alignment.
Definition: malloc.c:706
void * memset(void *dest, int character, size_t len) __nonnull
A persistent I/O buffer.
Definition: iobuf.h:37
static int legacy_open(struct net_device *netdev __unused)
Definition: legacy.c:60