0f4822529cb88b56cbb2b99c6e92814309591415
[people/indolent/gpxe.git/.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 #ifndef NIC_H
9 #define NIC_H
10
11 #include <stdint.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <errno.h>
15 #include <byteswap.h>
16 #include <gpxe/pci.h>
17 #include <gpxe/isapnp.h>
18 #include <gpxe/isa.h>
19 #include <gpxe/eisa.h>
20 #include <gpxe/mca.h>
21 #include "dhcp.h"
22
23 typedef enum {
24         DISABLE = 0,
25         ENABLE,
26         FORCE
27 } irq_action_t;
28
29 typedef enum duplex {
30         HALF_DUPLEX = 1,
31         FULL_DUPLEX
32 } duplex_t;
33
34 /*
35  *      Structure returned from eth_probe and passed to other driver
36  *      functions.
37  */
38 struct nic {
39         struct nic_operations   *nic_op;
40         int                     flags;  /* driver specific flags */
41         unsigned char           *node_addr;
42         unsigned char           *packet;
43         unsigned int            packetlen;
44         unsigned int            ioaddr;
45         unsigned char           irqno;
46         unsigned int            mbps;
47         duplex_t                duplex;
48         struct dhcp_dev_id      dhcp_dev_id;
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                                      const struct pci_device_id *id );    \
90         static inline void                                                \
91         _name ## _pci_legacy_remove ( struct pci_device *pci );           \
92         struct pci_driver _name __pci_driver = {                          \
93                 .ids = _ids,                                              \
94                 .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ),         \
95                 .probe = _name ## _pci_legacy_probe,                      \
96                 .remove = _name ## _pci_legacy_remove,                    \
97         };                                                                \
98         REQUIRE_OBJECT ( pci );
99
100 static inline void legacy_pci_set_drvdata ( void *hwdev, void *priv ) {
101         pci_set_drvdata ( hwdev, priv );
102 }
103 static inline void * legacy_pci_get_drvdata ( void *hwdev ) {
104         return pci_get_drvdata ( hwdev );
105 }
106
107 #define ISAPNP_DRIVER(_name,_ids)                                         \
108         static inline int                                                 \
109         _name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp,     \
110                                         const struct isapnp_device_id *id ); \
111         static inline void                                                \
112         _name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp );  \
113         struct isapnp_driver _name __isapnp_driver = {                    \
114                 .ids = _ids,                                              \
115                 .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ),         \
116                 .probe = _name ## _isapnp_legacy_probe,                   \
117                 .remove = _name ## _isapnp_legacy_remove,                 \
118         };                                                                \
119         REQUIRE_OBJECT ( isapnp );
120
121 static inline void legacy_isapnp_set_drvdata ( void *hwdev, void *priv ) {
122         isapnp_set_drvdata ( hwdev, priv );
123 }
124 static inline void * legacy_isapnp_get_drvdata ( void *hwdev ) {
125         return isapnp_get_drvdata ( hwdev );
126 }
127
128 #define EISA_DRIVER(_name,_ids)                                           \
129         static inline int                                                 \
130         _name ## _eisa_legacy_probe ( struct eisa_device *eisa,           \
131                                       const struct eisa_device_id *id );  \
132         static inline void                                                \
133         _name ## _eisa_legacy_remove ( struct eisa_device *eisa );        \
134         struct eisa_driver _name __eisa_driver = {                        \
135                 .ids = _ids,                                              \
136                 .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ),         \
137                 .probe = _name ## _eisa_legacy_probe,                     \
138                 .remove = _name ## _eisa_legacy_remove,                   \
139         };                                                                \
140         REQUIRE_OBJECT ( eisa );
141
142 static inline void legacy_eisa_set_drvdata ( void *hwdev, void *priv ) {
143         eisa_set_drvdata ( hwdev, priv );
144 }
145 static inline void * legacy_eisa_get_drvdata ( void *hwdev ) {
146         return eisa_get_drvdata ( hwdev );
147 }
148
149 #define MCA_DRIVER(_name,_ids)                                            \
150         static inline int                                                 \
151         _name ## _mca_legacy_probe ( struct mca_device *mca,              \
152                                      const struct mca_device_id *id );    \
153         static inline void                                                \
154         _name ## _mca_legacy_remove ( struct mca_device *mca );           \
155         struct mca_driver _name __mca_driver = {                          \
156                 .ids = _ids,                                              \
157                 .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ),         \
158                 .probe = _name ## _mca_legacy_probe,                      \
159                 .remove = _name ## _mca_legacy_remove,                    \
160         };                                                                \
161         REQUIRE_OBJECT ( mca );
162
163 static inline void legacy_mca_set_drvdata ( void *hwdev, void *priv ) {
164         mca_set_drvdata ( hwdev, priv );
165 }
166 static inline void * legacy_mca_get_drvdata ( void *hwdev ) {
167         return mca_get_drvdata ( hwdev );
168 }
169
170 #define ISA_DRIVER(_name,_probe_addrs,_probe_addr,_vendor_id,_prod_id)    \
171         static inline int                                                 \
172         _name ## _isa_legacy_probe ( struct isa_device *isa );            \
173         static inline int                                                 \
174         _name ## _isa_legacy_probe_at_addr ( struct isa_device *isa ) {   \
175                 if ( ! _probe_addr ( isa->ioaddr ) )                      \
176                         return -ENODEV;                                   \
177                 return _name ## _isa_legacy_probe ( isa );                \
178         }                                                                 \
179         static inline void                                                \
180         _name ## _isa_legacy_remove ( struct isa_device *isa );           \
181         static const char _name ## _text[];                               \
182         struct isa_driver _name __isa_driver = {                          \
183                 .name = _name ## _text,                                   \
184                 .probe_addrs = _probe_addrs,                              \
185                 .addr_count = ( sizeof ( _probe_addrs ) /                 \
186                                 sizeof ( _probe_addrs[0] ) ),             \
187                 .vendor_id = _vendor_id,                                  \
188                 .prod_id = _prod_id,                                      \
189                 .probe = _name ## _isa_legacy_probe_at_addr,              \
190                 .remove = _name ## _isa_legacy_remove,                    \
191         };                                                                \
192         REQUIRE_OBJECT ( isa );
193
194 static inline void legacy_isa_set_drvdata ( void *hwdev, void *priv ) {
195         isa_set_drvdata ( hwdev, priv );
196 }
197 static inline void * legacy_isa_get_drvdata ( void *hwdev ) {
198         return isa_get_drvdata ( hwdev );
199 }
200
201 #undef DRIVER
202 #define DRIVER(_name_text,_unused2,_unused3,_name,_probe,_disable)        \
203         static const char _name ## _text[] = _name_text;                  \
204         static inline int                                                 \
205         _name ## _probe ( struct nic *nic, void *hwdev ) {                \
206                 return _probe ( nic, hwdev );                             \
207         }                                                                 \
208         static inline void                                                \
209         _name ## _disable ( struct nic *nic, void *hwdev ) {              \
210                 void ( * _unsafe_disable ) () = _disable;                 \
211                 _unsafe_disable ( nic, hwdev );                           \
212         }                                                                 \
213         static inline int                                                 \
214         _name ## _pci_legacy_probe ( struct pci_device *pci,              \
215                             const struct pci_device_id *id __unused ) {   \
216                 return legacy_probe ( pci, legacy_pci_set_drvdata,        \
217                                       &pci->dev, _name ## _probe,         \
218                                       _name ## _disable );                \
219         }                                                                 \
220         static inline void                                                \
221         _name ## _pci_legacy_remove ( struct pci_device *pci ) {          \
222                 return legacy_remove ( pci, legacy_pci_get_drvdata,       \
223                                        _name ## _disable );               \
224         }                                                                 \
225         static inline int                                                 \
226         _name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp,     \
227                          const struct isapnp_device_id *id __unused ) {   \
228                 return legacy_probe ( isapnp, legacy_isapnp_set_drvdata,  \
229                                       &isapnp->dev, _name ## _probe,      \
230                                       _name ## _disable );                \
231         }                                                                 \
232         static inline void                                                \
233         _name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ) { \
234                 return legacy_remove ( isapnp, legacy_isapnp_get_drvdata, \
235                                        _name ## _disable );               \
236         }                                                                 \
237         static inline int                                                 \
238         _name ## _eisa_legacy_probe ( struct eisa_device *eisa,           \
239                              const struct eisa_device_id *id __unused ) { \
240                 return legacy_probe ( eisa, legacy_eisa_set_drvdata,      \
241                                       &eisa->dev, _name ## _probe,        \
242                                       _name ## _disable );                \
243         }                                                                 \
244         static inline void                                                \
245         _name ## _eisa_legacy_remove ( struct eisa_device *eisa ) {       \
246                 return legacy_remove ( eisa, legacy_eisa_get_drvdata,     \
247                                        _name ## _disable );               \
248         }                                                                 \
249         static inline int                                                 \
250         _name ## _mca_legacy_probe ( struct mca_device *mca,              \
251                               const struct mca_device_id *id __unused ) { \
252                 return legacy_probe ( mca, legacy_mca_set_drvdata,        \
253                                       &mca->dev, _name ## _probe,         \
254                                       _name ## _disable );                \
255         }                                                                 \
256         static inline void                                                \
257         _name ## _mca_legacy_remove ( struct mca_device *mca ) {          \
258                 return legacy_remove ( mca, legacy_mca_get_drvdata,       \
259                                        _name ## _disable );               \
260         }                                                                 \
261         static inline int                                                 \
262         _name ## _isa_legacy_probe ( struct isa_device *isa ) {           \
263                 return legacy_probe ( isa, legacy_isa_set_drvdata,        \
264                                       &isa->dev, _name ## _probe,         \
265                                       _name ## _disable );                \
266         }                                                                 \
267         static inline void                                                \
268         _name ## _isa_legacy_remove ( struct isa_device *isa ) {          \
269                 return legacy_remove ( isa, legacy_isa_get_drvdata,       \
270                                        _name ## _disable );               \
271         }
272
273 static inline void pci_fill_nic ( struct nic *nic, struct pci_device *pci ) {
274         nic->ioaddr = pci->ioaddr;
275         nic->irqno = pci->irq;
276 }
277
278 static inline void isapnp_fill_nic ( struct nic *nic,
279                                      struct isapnp_device *isapnp ) {
280         nic->ioaddr = isapnp->ioaddr;
281         nic->irqno = isapnp->irqno;
282 }
283
284 static inline void eisa_fill_nic ( struct nic *nic,
285                                    struct eisa_device *eisa ) {
286         nic->ioaddr = eisa->ioaddr;
287         nic->irqno = 0;
288 }
289
290 static inline void mca_fill_nic ( struct nic *nic,
291                                   struct mca_device *mca __unused ) {
292         /* ioaddr and irqno must be read in a device-dependent way
293          * from the POS registers
294          */
295         nic->ioaddr = 0;
296         nic->irqno = 0;
297 }
298
299 static inline void isa_fill_nic ( struct nic *nic, struct isa_device *isa ) {
300         nic->ioaddr = isa->ioaddr;
301         nic->irqno = 0;
302 }
303
304 #endif  /* NIC_H */