[zbin] Fix check for existence of most recent output byte
[ipxe.git] / src / include / nic.h
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2, or (at
5 * your option) any later version.
6 */
7
8 FILE_LICENCE ( GPL2_OR_LATER );
9
10 #ifndef NIC_H
11 #define NIC_H
12
13 #include <stdint.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <byteswap.h>
17 #include <ipxe/pci.h>
18 #include <ipxe/isapnp.h>
19 #include <ipxe/isa.h>
20 #include <ipxe/eisa.h>
21 #include <ipxe/mca.h>
22 #include <ipxe/io.h>
23
24 typedef enum {
25 DISABLE = 0,
26 ENABLE,
27 FORCE
28 } irq_action_t;
29
30 typedef enum duplex {
31 HALF_DUPLEX = 1,
32 FULL_DUPLEX
33 } duplex_t;
34
35 /*
36 * Structure returned from eth_probe and passed to other driver
37 * functions.
38 */
39 struct nic {
40 struct nic_operations *nic_op;
41 int flags; /* driver specific flags */
42 unsigned char *node_addr;
43 unsigned char *packet;
44 unsigned int packetlen;
45 unsigned int ioaddr;
46 unsigned char irqno;
47 unsigned int mbps;
48 duplex_t duplex;
49 void *priv_data; /* driver private data */
50 };
51
52 struct nic_operations {
53 int ( *connect ) ( struct nic * );
54 int ( *poll ) ( struct nic *, int retrieve );
55 void ( *transmit ) ( struct nic *, const char *,
56 unsigned int, unsigned int, const char * );
57 void ( *irq ) ( struct nic *, irq_action_t );
58 };
59
60 extern struct nic nic;
61
62 static inline int eth_poll ( int retrieve ) {
63 return nic.nic_op->poll ( &nic, retrieve );
64 }
65
66 static inline void eth_transmit ( const char *dest, unsigned int type,
67 unsigned int size, const void *packet ) {
68 nic.nic_op->transmit ( &nic, dest, type, size, packet );
69 }
70
71 /*
72 * Function prototypes
73 *
74 */
75 extern int dummy_connect ( struct nic *nic );
76 extern void dummy_irq ( struct nic *nic, irq_action_t irq_action );
77 extern int legacy_probe ( void *hwdev,
78 void ( * set_drvdata ) ( void *hwdev, void *priv ),
79 struct device *dev,
80 int ( * probe ) ( struct nic *nic, void *hwdev ),
81 void ( * disable ) ( struct nic *nic, void *hwdev ));
82 void legacy_remove ( void *hwdev,
83 void * ( * get_drvdata ) ( void *hwdev ),
84 void ( * disable ) ( struct nic *nic, void *hwdev ) );
85
86 #define PCI_DRIVER(_name,_ids,_class) \
87 static inline int \
88 _name ## _pci_legacy_probe ( struct pci_device *pci ); \
89 static inline void \
90 _name ## _pci_legacy_remove ( struct pci_device *pci ); \
91 struct pci_driver _name __pci_driver = { \
92 .ids = _ids, \
93 .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
94 .probe = _name ## _pci_legacy_probe, \
95 .remove = _name ## _pci_legacy_remove, \
96 }; \
97 REQUIRE_OBJECT ( pci );
98
99 static inline void legacy_pci_set_drvdata ( void *hwdev, void *priv ) {
100 pci_set_drvdata ( hwdev, priv );
101 }
102 static inline void * legacy_pci_get_drvdata ( void *hwdev ) {
103 return pci_get_drvdata ( hwdev );
104 }
105
106 #define ISAPNP_DRIVER(_name,_ids) \
107 static inline int \
108 _name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp, \
109 const struct isapnp_device_id *id ); \
110 static inline void \
111 _name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ); \
112 struct isapnp_driver _name __isapnp_driver = { \
113 .ids = _ids, \
114 .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
115 .probe = _name ## _isapnp_legacy_probe, \
116 .remove = _name ## _isapnp_legacy_remove, \
117 }; \
118 REQUIRE_OBJECT ( isapnp );
119
120 static inline void legacy_isapnp_set_drvdata ( void *hwdev, void *priv ) {
121 isapnp_set_drvdata ( hwdev, priv );
122 }
123 static inline void * legacy_isapnp_get_drvdata ( void *hwdev ) {
124 return isapnp_get_drvdata ( hwdev );
125 }
126
127 #define EISA_DRIVER(_name,_ids) \
128 static inline int \
129 _name ## _eisa_legacy_probe ( struct eisa_device *eisa, \
130 const struct eisa_device_id *id ); \
131 static inline void \
132 _name ## _eisa_legacy_remove ( struct eisa_device *eisa ); \
133 struct eisa_driver _name __eisa_driver = { \
134 .ids = _ids, \
135 .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
136 .probe = _name ## _eisa_legacy_probe, \
137 .remove = _name ## _eisa_legacy_remove, \
138 }; \
139 REQUIRE_OBJECT ( eisa );
140
141 static inline void legacy_eisa_set_drvdata ( void *hwdev, void *priv ) {
142 eisa_set_drvdata ( hwdev, priv );
143 }
144 static inline void * legacy_eisa_get_drvdata ( void *hwdev ) {
145 return eisa_get_drvdata ( hwdev );
146 }
147
148 #define MCA_DRIVER(_name,_ids) \
149 static inline int \
150 _name ## _mca_legacy_probe ( struct mca_device *mca, \
151 const struct mca_device_id *id ); \
152 static inline void \
153 _name ## _mca_legacy_remove ( struct mca_device *mca ); \
154 struct mca_driver _name __mca_driver = { \
155 .ids = _ids, \
156 .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
157 .probe = _name ## _mca_legacy_probe, \
158 .remove = _name ## _mca_legacy_remove, \
159 }; \
160 REQUIRE_OBJECT ( mca );
161
162 static inline void legacy_mca_set_drvdata ( void *hwdev, void *priv ) {
163 mca_set_drvdata ( hwdev, priv );
164 }
165 static inline void * legacy_mca_get_drvdata ( void *hwdev ) {
166 return mca_get_drvdata ( hwdev );
167 }
168
169 #define ISA_DRIVER(_name,_probe_addrs,_probe_addr,_vendor_id,_prod_id) \
170 static inline int \
171 _name ## _isa_legacy_probe ( struct isa_device *isa ); \
172 static inline int \
173 _name ## _isa_legacy_probe_at_addr ( struct isa_device *isa ) { \
174 if ( ! _probe_addr ( isa->ioaddr ) ) \
175 return -ENODEV; \
176 return _name ## _isa_legacy_probe ( isa ); \
177 } \
178 static inline void \
179 _name ## _isa_legacy_remove ( struct isa_device *isa ); \
180 static const char _name ## _text[]; \
181 struct isa_driver _name __isa_driver = { \
182 .name = _name ## _text, \
183 .probe_addrs = _probe_addrs, \
184 .addr_count = ( sizeof ( _probe_addrs ) / \
185 sizeof ( _probe_addrs[0] ) ), \
186 .vendor_id = _vendor_id, \
187 .prod_id = _prod_id, \
188 .probe = _name ## _isa_legacy_probe_at_addr, \
189 .remove = _name ## _isa_legacy_remove, \
190 }; \
191 REQUIRE_OBJECT ( isa );
192
193 static inline void legacy_isa_set_drvdata ( void *hwdev, void *priv ) {
194 isa_set_drvdata ( hwdev, priv );
195 }
196 static inline void * legacy_isa_get_drvdata ( void *hwdev ) {
197 return isa_get_drvdata ( hwdev );
198 }
199
200 #undef DRIVER
201 #define DRIVER(_name_text,_unused2,_unused3,_name,_probe,_disable) \
202 static const char _name ## _text[] = _name_text; \
203 static inline int \
204 _name ## _probe ( struct nic *nic, void *hwdev ) { \
205 return _probe ( nic, hwdev ); \
206 } \
207 static inline void \
208 _name ## _disable ( struct nic *nic, void *hwdev ) { \
209 void ( * _unsafe_disable ) () = _disable; \
210 _unsafe_disable ( nic, hwdev ); \
211 } \
212 static inline int \
213 _name ## _pci_legacy_probe ( struct pci_device *pci ) { \
214 return legacy_probe ( pci, legacy_pci_set_drvdata, \
215 &pci->dev, _name ## _probe, \
216 _name ## _disable ); \
217 } \
218 static inline void \
219 _name ## _pci_legacy_remove ( struct pci_device *pci ) { \
220 return legacy_remove ( pci, legacy_pci_get_drvdata, \
221 _name ## _disable ); \
222 } \
223 static inline int \
224 _name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp, \
225 const struct isapnp_device_id *id __unused ) { \
226 return legacy_probe ( isapnp, legacy_isapnp_set_drvdata, \
227 &isapnp->dev, _name ## _probe, \
228 _name ## _disable ); \
229 } \
230 static inline void \
231 _name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ) { \
232 return legacy_remove ( isapnp, legacy_isapnp_get_drvdata, \
233 _name ## _disable ); \
234 } \
235 static inline int \
236 _name ## _eisa_legacy_probe ( struct eisa_device *eisa, \
237 const struct eisa_device_id *id __unused ) { \
238 return legacy_probe ( eisa, legacy_eisa_set_drvdata, \
239 &eisa->dev, _name ## _probe, \
240 _name ## _disable ); \
241 } \
242 static inline void \
243 _name ## _eisa_legacy_remove ( struct eisa_device *eisa ) { \
244 return legacy_remove ( eisa, legacy_eisa_get_drvdata, \
245 _name ## _disable ); \
246 } \
247 static inline int \
248 _name ## _mca_legacy_probe ( struct mca_device *mca, \
249 const struct mca_device_id *id __unused ) { \
250 return legacy_probe ( mca, legacy_mca_set_drvdata, \
251 &mca->dev, _name ## _probe, \
252 _name ## _disable ); \
253 } \
254 static inline void \
255 _name ## _mca_legacy_remove ( struct mca_device *mca ) { \
256 return legacy_remove ( mca, legacy_mca_get_drvdata, \
257 _name ## _disable ); \
258 } \
259 static inline int \
260 _name ## _isa_legacy_probe ( struct isa_device *isa ) { \
261 return legacy_probe ( isa, legacy_isa_set_drvdata, \
262 &isa->dev, _name ## _probe, \
263 _name ## _disable ); \
264 } \
265 static inline void \
266 _name ## _isa_legacy_remove ( struct isa_device *isa ) { \
267 return legacy_remove ( isa, legacy_isa_get_drvdata, \
268 _name ## _disable ); \
269 }
270
271 #endif /* NIC_H */