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