882a38e59fb3c939349d9dfbe9d5f127993fccbc
[people/pcmattman/gpxe.git] / src / drivers / net / skel.c
1 /**************************************************************************
2 Etherboot -  BOOTP/TFTP Bootstrap Program
3 Skeleton NIC driver for Etherboot
4 ***************************************************************************/
5
6 /*
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2, or (at
10  * your option) any later version.
11  */
12
13 /* to get some global routines like printf */
14 #include "etherboot.h"
15 /* to get the interface to the body of the program */
16 #include "nic.h"
17 /* Drag in support for whichever bus(es) we want for this NIC */
18 #include <gpxe/pci.h>
19 #include "isa.h"
20 #include "eisa.h"
21 #include "isapnp.h"
22 #include "mca.h"
23
24 /*
25  * NIC specific static variables go here.  Try to avoid using static
26  * variables wherever possible.  In particular, the I/O address can
27  * always be accessed via nic->ioaddr.
28  */
29
30 /*
31  * If you have large static variables (e.g. transmit and receive
32  * buffers), you should place them together in a single structure and
33  * mark the structure as "shared".  This enables this space to be
34  * shared between drivers in multi-driver images, which can easily
35  * reduce the runtime size by 50%.
36  *
37  */
38 #define SKEL_RX_BUFS    1
39 #define SKEL_TX_BUFS    1
40 #define SKEL_RX_BUFSIZE 0
41 #define SKEL_TX_BUFSIZE 0
42 struct skel_rx_desc {};
43 struct skel_tx_desc {};
44 struct {
45         struct skel_rx_desc     rxd[SKEL_RX_BUFS];
46         unsigned char           rxb[SKEL_RX_BUFS][SKEL_RX_BUFSIZE];
47         struct skel_tx_desc     txd[SKEL_TX_BUFS];
48         unsigned char           txb[SKEL_TX_BUFS][SKEL_TX_BUFSIZE];
49 } skel_bufs __shared;
50
51 /*
52  * Don't forget to remove "__unused" from all the function parameters!
53  *
54  */
55
56 /**************************************************************************
57  * CONNECT - Connect to the network
58  **************************************************************************
59 */
60 static int skel_connect ( struct nic *nic __unused ) {
61         /*
62          * Connect to the network.  For most NICs, this will probably
63          * be a no-op.  For wireless NICs, this should be the point at
64          * which you attempt to join to an access point.
65          *
66          * Return 0 if the connection failed (e.g. no cable plugged
67          * in), 1 for success.
68          *
69          */
70         return 1;
71 }
72
73 /**************************************************************************
74  * TRANSMIT - Transmit a frame
75  **************************************************************************
76 */
77 static void skel_transmit ( struct nic *nic __unused,
78                             const char *dest __unused,
79                             unsigned int type __unused,
80                             unsigned int size __unused,
81                             const char *packet __unused ) {
82         /* Transmit packet to dest MAC address.  You will need to
83          * construct the link-layer header (dest MAC, source MAC,
84          * type).
85          */
86         /*
87            unsigned int nstype = htons ( type );
88            memcpy ( <tx_buffer>, dest, ETH_ALEN );
89            memcpy ( <tx_buffer> + ETH_ALEN, nic->node_addr, ETH_ALEN );
90            memcpy ( <tx_buffer> + 2 * ETH_ALEN, &nstype, 2 );
91            memcpy ( <tx_buffer> + ETH_HLEN, data, size );
92            <transmit_data> ( <tx_buffer>, size + ETH_HLEN );
93          */
94 }
95
96 /**************************************************************************
97  * POLL - Wait for a frame
98  **************************************************************************
99 */
100 static int skel_poll ( struct nic *nic __unused, int retrieve __unused ) {
101         /* Work out whether or not there's an ethernet packet ready to
102          * read.  Return 0 if not.
103          */
104         /* 
105            if ( ! <packet_ready> ) return 0;
106         */
107
108         /* retrieve==0 indicates that we are just checking for the
109          * presence of a packet but don't want to read it just yet.
110          */
111         /*
112            if ( ! retrieve ) return 1;
113         */
114
115         /* Copy data to nic->packet.  Data should include the
116          * link-layer header (dest MAC, source MAC, type).
117          * Store length of data in nic->packetlen.
118          * Return true to indicate a packet has been read.
119          */
120         /* 
121            nic->packetlen = <packet_length>;
122            memcpy ( nic->packet, <packet_data>, <packet_length> );
123            return 1;
124         */
125
126         return 0;       /* Remove this line once this method is implemented */
127 }
128
129 /**************************************************************************
130  * IRQ - handle interrupts
131  **************************************************************************
132 */
133 static void skel_irq ( struct nic *nic __unused, irq_action_t action ) {
134         /* This routine is somewhat optional.  Etherboot itself
135          * doesn't use interrupts, but they are required under some
136          * circumstances when we're acting as a PXE stack.
137          *
138          * If you don't implement this routine, the only effect will
139          * be that your driver cannot be used via Etherboot's UNDI
140          * API.  This won't affect programs that use only the UDP
141          * portion of the PXE API, such as pxelinux.
142          */
143        
144         switch ( action ) {
145         case DISABLE :
146         case ENABLE :
147                 /* Set receive interrupt enabled/disabled state */
148                 /*
149                   outb ( action == ENABLE ? IntrMaskEnabled : IntrMaskDisabled,
150                          nic->ioaddr + IntrMaskRegister );
151                  */
152                 break;
153         case FORCE :
154                 /* Force NIC to generate a receive interrupt */
155                 /*
156                   outb ( ForceInterrupt, nic->ioaddr + IntrForceRegister );
157                  */
158                 break;
159         }
160 }
161
162 /**************************************************************************
163  * OPERATIONS TABLE - Pointers to all the above methods
164  **************************************************************************
165  */
166 static struct nic_operations skel_operations = {
167         .connect        = skel_connect,
168         .transmit       = skel_transmit,
169         .poll           = skel_poll,
170         .irq            = skel_irq,
171 };
172
173 /**************************************************************************
174  * PROBE - Look for an adapter
175  *
176  * You need to define a probe routine and a disable routine for each
177  * bus type that your driver supports, together with tables that
178  * enable Etherboot to identify that your driver should be used for a
179  * particular device.
180  *
181  * Delete whichever of the following sections you don't need.  For
182  * example, most PCI devices will only need the PCI probing section;
183  * ISAPnP, EISA, etc. can all be deleted.
184  *
185  * Some devices will need custom bus logic.  The ISA 3c509 is a good
186  * example of this; it has a contention-resolution mechanism that is
187  * similar to ISAPnP, but not close enough to use the generic ISAPnP
188  * code.  Look at 3c509.c to see how it works.
189  *
190  **************************************************************************
191  */
192
193 /**************************************************************************
194  * PCI PROBE and DISABLE
195  **************************************************************************
196  */
197 static int skel_pci_probe ( struct nic *nic, struct pci_device *pci ) {
198
199         pci_fill_nic ( nic, pci );
200
201         /* Test for physical presence of NIC */
202         /*
203            if ( ! my_tests ) {
204                 DBG ( "Could not find NIC: my explanation\n" );
205                 return 0;
206            }
207         */
208
209         /* point to NIC specific routines */
210         nic->nic_op = &skel_operations;
211         return 1;
212 }
213
214 static void skel_pci_disable ( struct nic *nic __unused,
215                                struct pci_device *pci __unused ) {
216         /* Reset the card to its initial state, disable DMA and
217          * interrupts
218          */
219 }
220
221 static struct pci_device_id skel_pci_nics[] = {
222 PCI_ROM ( 0x0000, 0x0000, "skel-pci", "Skeleton PCI Adapter" ),
223 };
224
225 PCI_DRIVER ( skel_pci_driver, skel_pci_nics, PCI_NO_CLASS );
226
227 DRIVER ( "SKEL/PCI", nic_driver, pci_driver, skel_pci_driver,
228          skel_pci_probe, skel_pci_disable );
229
230 /**************************************************************************
231  * EISA PROBE and DISABLE
232  **************************************************************************
233  */
234 static int skel_eisa_probe ( struct nic *nic, struct eisa_device *eisa ) {
235
236         eisa_fill_nic ( nic, eisa );
237         enable_eisa_device ( eisa );
238         nic->irqno = 0; /* No standard way to get irq from EISA cards */
239
240         /* Test for physical presence of NIC */
241         /*
242            if ( ! my_tests ) {
243                 DBG ( "Could not find NIC: my explanation\n" );
244                 return 0;
245            }
246         */
247
248         /* point to NIC specific routines */
249         nic->nic_op = &skel_operations;
250         return 1;
251 }
252
253 static void skel_eisa_disable ( struct nic *nic __unused,
254                                 struct eisa_device *eisa ) {
255         /* Reset the card to its initial state, disable DMA and
256          * interrupts
257          */
258         disable_eisa_device ( eisa );
259 }
260
261 static struct eisa_id skel_eisa_nics[] = {
262         { "Skeleton EISA Adapter", EISA_VENDOR('S','K','L'), 0x0000 },
263 };
264
265 EISA_DRIVER ( skel_eisa_driver, skel_eisa_nics );
266
267 DRIVER ( "SKEL/EISA", nic_driver, eisa_driver, skel_eisa_driver,
268          skel_eisa_probe, skel_eisa_disable );
269
270 ISA_ROM ( "skel-eisa", "Skeleton EISA Adapter" );
271
272 /**************************************************************************
273  * ISAPnP PROBE and DISABLE
274  **************************************************************************
275  */
276 static int skel_isapnp_probe ( struct nic *nic,
277                                struct isapnp_device *isapnp ) {
278
279         isapnp_fill_nic ( nic, isapnp );
280         activate_isapnp_device ( isapnp );
281
282         /* Test for physical presence of NIC */
283         /*
284            if ( ! my_tests ) {
285                 DBG ( "Could not find NIC: my explanation\n" );
286                 return 0;
287            }
288         */
289
290         /* point to NIC specific routines */
291         nic->nic_op = &skel_operations;
292         return 1;
293 }
294
295 static void skel_isapnp_disable ( struct nic *nic __unused,
296                                   struct isapnp_device *isapnp ) {
297         /* Reset the card to its initial state, disable DMA and
298          * interrupts
299          */
300         deactivate_isapnp_device ( isapnp );
301 }
302
303 static struct isapnp_id skel_isapnp_nics[] = {
304         { "Skeleton ISAPnP Adapter", ISAPNP_VENDOR('S','K','L'), 0x0000 },
305 };
306
307 ISAPNP_DRIVER ( skel_isapnp_driver, skel_isapnp_nics );
308
309 DRIVER ( "SKEL/ISAPnP", nic_driver, isapnp_driver, skel_isapnp_driver,
310          skel_isapnp_probe, skel_isapnp_disable );
311
312 ISA_ROM ( "skel-isapnp", "Skeleton ISAPnP Adapter" );
313
314 /**************************************************************************
315  * MCA PROBE and DISABLE
316  **************************************************************************
317  */
318 static int skel_mca_probe ( struct nic *nic,
319                             struct mca_device *mca ) {
320
321         mca_fill_nic ( nic, mca );
322
323         /* MCA parameters are available in the mca->pos[] array */
324         /*
325            nic->ioaddr = ( mca->pos[xxx] << 8 ) + mca->pos[yyy];
326            nic->irqno = mca->pos[zzz] & 0x0f;
327         */
328
329         /* Test for physical presence of NIC */
330         /*
331            if ( ! my_tests ) {
332                 DBG ( "Could not find NIC: my explanation\n" );
333                 return 0;
334            }
335         */
336
337         /* point to NIC specific routines */
338         nic->nic_op = &skel_operations;
339         return 1;
340 }
341
342 static void skel_mca_disable ( struct nic *nic __unused,
343                                struct mca_device *mca __unused ) {
344         /* Reset the card to its initial state, disable DMA and
345          * interrupts
346          */
347 }
348
349 static struct mca_id skel_mca_nics[] = {
350         { "Skeleton MCA Adapter", 0x0000 },
351 };
352
353 MCA_DRIVER ( skel_mca_driver, skel_mca_nics );
354
355 DRIVER ( "SKEL/MCA", nic_driver, mca_driver, skel_mca_driver,
356          skel_mca_probe, skel_mca_disable );
357
358 ISA_ROM ( "skel-mca", "Skeleton MCA Adapter" );
359
360 /**************************************************************************
361  * ISA PROBE and DISABLE
362  *
363  * The "classical" ISA probe is split into two stages: trying a list
364  * of I/O addresses to see if there's anything listening, and then
365  * using that I/O address to fill in the information in the nic
366  * structure.
367  *
368  * The list of probe addresses defined in skel_isa_probe_addrs[] will
369  * be passed to skel_isa_probe_addr().  If skel_isa_probe_addr()
370  * returns true, a struct isa_device will be created with isa->ioaddr
371  * set to the working I/O address, and skel_isa_probe() will be
372  * called.
373  *
374  * There is a standard mechanism for overriding the probe address list
375  * using ISA_PROBE_ADDRS.  Do not implement any custom code to
376  * override the probe address list.
377  *
378  **************************************************************************
379  */
380 static int skel_isa_probe_addr ( isa_probe_addr_t ioaddr __unused ) {
381         return 0;
382 }
383
384 static int skel_isa_probe ( struct nic *nic, struct isa_device *isa ) {
385
386         isa_fill_nic ( nic, isa );
387         nic->irqno = 0; /* No standard way to get IRQ for ISA */
388
389         /* Test for physical presence of NIC */
390         /*
391            if ( ! my_tests ) {
392                 DBG ( "Could not find NIC: my explanation\n" );
393                 return 0;
394            }
395         */
396
397         /* point to NIC specific routines */
398         nic->nic_op = &skel_operations;
399         return 1;
400 }
401
402 static void skel_isa_disable ( struct nic *nic __unused,
403                               struct isa_device *isa __unused ) {
404         /* Reset the card to its initial state, disable DMA and
405          * interrupts
406          */
407 }
408
409 static isa_probe_addr_t skel_isa_probe_addrs[] = {
410         /*
411            0x200, 0x240,
412         */
413 };
414
415 ISA_DRIVER ( skel_isa_driver, skel_isa_probe_addrs, skel_isa_probe_addr,
416                      ISA_VENDOR('S','K','L'), 0x0000 );
417
418 DRIVER ( "SKEL/ISA", nic_driver, isa_driver, skel_isa_driver,
419          skel_isa_probe, skel_isa_disable );
420
421 ISA_ROM ( "skel-isa", "Skeleton ISA Adapter" );
422