]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/eth/mips/atlas/v2_0/src/if_atlas.c
Initial revision
[karo-tx-redboot.git] / packages / devs / eth / mips / atlas / v2_0 / src / if_atlas.c
1 //==========================================================================
2 //
3 //      dev/if_atlas.c
4 //
5 //      Ethernet device driver for MIPS Atlas using Philips SAA9730
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2003 Nick Garnett <nickg@calivar.com>
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 //
37 // Alternative licenses for eCos may be arranged by contacting the copyright
38 // holders.
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //####BSDCOPYRIGHTBEGIN####
42 //
43 // -------------------------------------------
44 //
45 // Portions of this software may have been derived from OpenBSD or other sources,
46 // and are covered by the appropriate copyright disclaimers included herein.
47 //
48 // -------------------------------------------
49 //
50 //####BSDCOPYRIGHTEND####
51 //==========================================================================
52 //#####DESCRIPTIONBEGIN####
53 //
54 // Author(s):    msalter
55 // Contributors: msalter, nickg
56 // Date:         2000-12-06
57 // Purpose:      
58 // Description:  hardware driver for SAA9730 ethernet
59 //              
60 //
61 //####DESCRIPTIONEND####
62 //
63 //==========================================================================
64
65 // Ethernet device driver for MIPS Atlas
66 // Based on SAA9730
67
68 #include <pkgconf/system.h>
69 #include <pkgconf/devs_eth_mips_atlas.h>
70 #include <pkgconf/io_eth_drivers.h>
71
72 #ifdef CYGPKG_NET
73 #include <pkgconf/net.h>
74 #include <cyg/kernel/kapi.h>
75 #endif
76 #include <cyg/infra/cyg_type.h>
77 #include <cyg/hal/hal_arch.h>
78 #include <cyg/hal/hal_endian.h>
79 #include <cyg/hal/hal_intr.h>
80 #include <cyg/hal/hal_cache.h>
81 #include <cyg/hal/hal_if.h>
82 #include <cyg/infra/diag.h>
83 #include <cyg/hal/drv_api.h>
84 #include <cyg/io/eth/netdev.h>
85 #include <cyg/io/eth/eth_drv.h>
86
87 #ifdef CYGPKG_IO_PCI
88 #include <cyg/io/pci.h>
89 // So we can check the validity of the PCI window against the MLTs opinion,
90 // and thereby what the malloc heap consumes willy-nilly:
91 #include CYGHWR_MEMORY_LAYOUT_H
92 #else
93 #error "Need PCI package here"
94 #endif
95
96 #ifndef CYGSEM_MIPS_ATLAS_SET_ESA
97 #ifdef CYGPKG_REDBOOT
98 #include <pkgconf/redboot.h>
99 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
100 #include <redboot.h>
101 #include <flash_config.h>
102 RedBoot_config_option("Network hardware address [MAC]",
103                       atlas_esa,
104                       ALWAYS_ENABLED, true,
105                       CONFIG_ESA, 0
106     );
107 #endif
108 #endif
109 #endif
110
111 // SAA9730 LAN definitions
112 #include "saa9730.h"
113
114 // Exported statistics and the like
115 #include <cyg/io/eth/eth_drv_stats.h>
116
117 #ifndef CYGPKG_REDBOOT
118 //#define DEBUG
119 #endif
120 #define db_printf diag_printf
121
122 #define ETHER_ADDR_LEN 6
123
124 static unsigned poll_count = 0;  // for bug workaround
125 static void __tx_poll(struct eth_drv_sc *sc);
126
127 struct saa9730_priv_data {
128     int                 active;
129     cyg_uint32          vector;
130     cyg_handle_t        interrupt_handle;
131     cyg_interrupt       interrupt_object;
132     cyg_uint32          devid;             // PCI device id
133     cyg_uint32          base;              // PCI memory map base
134     void                *ndp;
135
136     // index of next RX buffer
137     cyg_uint8           next_rx_bindex;
138
139     // index of next packet within RX buffer
140     cyg_uint8           next_rx_pindex;
141
142     // index of next TX buffer
143     cyg_uint8           next_tx_bindex;
144
145     // index of next packet within TX buffer
146     cyg_uint8           next_tx_pindex; 
147
148     cyg_uint32          *tx_buffer[SAA9730_BUFFERS][SAA9730_TXPKTS_PER_BUFFER];
149     cyg_uint32          *rx_buffer[SAA9730_BUFFERS][SAA9730_RXPKTS_PER_BUFFER];
150
151     int                 tx_busy;
152     unsigned long       tx_key[SAA9730_BUFFERS][SAA9730_TXPKTS_PER_BUFFER];
153     int                 tx_used[SAA9730_BUFFERS];
154
155 } saa9730_priv_data;
156
157 ETH_DRV_SC(atlas_sc,
158            &saa9730_priv_data, // Driver specific data
159            "eth0",             // Name for this interface
160            saa9730_start,
161            saa9730_stop,
162            saa9730_control,
163            saa9730_can_send,
164            saa9730_send,
165            saa9730_recv,
166            saa9730_deliver,     // "pseudoDSR" called from fast net thread
167            saa9730_poll,
168            saa9730_int_vector);
169
170 NETDEVTAB_ENTRY(atlas_netdev, 
171                 "atlas", 
172                 atlas_saa9730_init, 
173                 &atlas_sc);
174
175 #ifdef CYGSEM_MIPS_ATLAS_SET_ESA
176 static unsigned char enaddr[] = CYGDAT_MIPS_ATLAS_ESA;
177 #else
178 static unsigned char enaddr[ETHER_ADDR_LEN];
179 #endif
180
181 static void saa9730_poll(struct eth_drv_sc *sc);
182
183 // This ISR is called when the ethernet interrupt occurs
184 static int
185 saa9730_isr(cyg_vector_t vector, cyg_addrword_t data)
186 {
187     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)data;
188     unsigned long __base = spd->base;    
189
190 #ifndef CYGPKG_REDBOOT    
191     SAA9730_EVM_IER_SW &= ~(SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
192     SAA9730_EVM_ISR = SAA9730_EVM_LAN_INT;
193     cyg_drv_interrupt_mask(vector);
194 #endif
195 #ifdef DEBUG
196     db_printf("saa9730_isr\n");
197 #endif
198     return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
199 }
200
201 #ifndef CYGPKG_REDBOOT
202 static 
203 void saa9730_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
204 {
205     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)data;
206     struct cyg_netdevtab_entry *ndp = (struct cyg_netdevtab_entry *)(spd->ndp);
207     struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance);
208 #ifdef DEBUG
209     db_printf("saa9730_dsr\n");    
210 #endif
211
212     eth_drv_dsr(vector, count, (cyg_addrword_t)sc);
213 }
214 #endif
215
216 static int
217 saa9730_int_vector(struct eth_drv_sc *sc)
218 {
219     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
220
221     return spd->vector;
222 }
223
224 static void
225 __init_buffers(struct saa9730_priv_data *spd)
226 {
227     extern char cyg_io_atlas_2kbuffers[];
228     cyg_uint32 *bufp = (cyg_uint32 *)CYGARC_UNCACHED_ADDRESS((unsigned)cyg_io_atlas_2kbuffers);
229     int i, j;
230
231     for (i = 0; i < SAA9730_BUFFERS; i++) {
232         for (j = 0; j < SAA9730_RXPKTS_PER_BUFFER; j++) {
233             memset(bufp, 0, 2048);
234             spd->rx_buffer[i][j]   = bufp;
235             bufp += SAA9730_PACKET_SIZE/sizeof(*bufp);
236         }
237     }
238     for (i = 0; i < SAA9730_BUFFERS; i++) {
239         for (j = 0; j < SAA9730_TXPKTS_PER_BUFFER; j++) {
240             memset(bufp, 0, 2048);
241             *bufp = CYG_CPU_TO_LE32(TX_EMPTY);
242             spd->tx_buffer[i][j] = bufp;
243             bufp += SAA9730_PACKET_SIZE/sizeof(*bufp);
244         }
245     }
246
247     spd->next_rx_pindex = 0;
248     spd->next_rx_bindex = 0;
249     spd->next_tx_pindex = 0;
250     spd->next_tx_bindex = 0;
251 }
252
253 static void
254 __select_buffer(struct saa9730_priv_data *spd, int buf_nr)
255 {
256     unsigned long __base = spd->base;
257     cyg_uint32 *p;
258     int i;
259
260     // Enable RX buffer
261     for (i = 0; i < SAA9730_RXPKTS_PER_BUFFER; i++) {
262         p = spd->rx_buffer[buf_nr][i];
263         *p = CYG_CPU_TO_LE32(RX_READY);
264     }
265
266     if (buf_nr)
267         SAA9730_OK2USE |= SAA9730_OK2USE_RXB;
268     else
269         SAA9730_OK2USE |= SAA9730_OK2USE_RXA;
270
271 }
272
273 static void
274 __init_cam(struct saa9730_priv_data *spd)
275 {
276     unsigned long __base = spd->base;
277     cyg_uint32 abuf[3];  // room for 2 copies of mac address
278     int i,j,cam_offset;
279
280     // make 2 contiguous copies of mac addr
281     memcpy((char *)abuf, enaddr, 6);
282     memcpy((char *)abuf + 6, enaddr, 6);
283
284     // Setting up the address compare regs is weird because you have
285     // to access by word addresses even though addresses don't have
286     // an integral number of words.
287     cam_offset = 0;
288     for (i = 0; i < SAA9730_CAM_ENTRIES; i++) {
289         for (j = 0; j < 3; j++, cam_offset++) {
290             SAA9730_CAMADR = cam_offset;
291             SAA9730_CAMDAT = CYG_CPU_TO_BE32(abuf[j]);
292         }
293     }
294 }
295
296 static void
297 __stop_dma(struct saa9730_priv_data *spd)
298 {
299     unsigned long __base = spd->base;
300
301     // Stop DMA
302     SAA9730_DMACTL &= ~(SAA9730_DMACTL_ENRX | SAA9730_DMACTL_ENTX);
303
304     // Stop tx/rx
305     SAA9730_TXCTL &= ~SAA9730_TXCTL_ENTX;
306     SAA9730_RXCTL &= ~SAA9730_RXCTL_ENRX;
307
308     // Set DMA and MAC reset bits
309     SAA9730_DMATST |= SAA9730_DMATST_RESET;
310     SAA9730_MACCTL |= SAA9730_MACCTL_RESET;
311 }
312
313
314 static void
315 __init_dma(struct saa9730_priv_data *spd)
316 {
317     unsigned long __base = spd->base;
318
319     __stop_dma(spd);
320
321     // reset DMA engine
322     SAA9730_DMATST |= SAA9730_DMATST_RESET;
323
324     // setup buffers
325     SAA9730_TXBUFA = CYGARC_PHYSICAL_ADDRESS((unsigned long)spd->tx_buffer[0][0]);
326     SAA9730_TXBUFB = CYGARC_PHYSICAL_ADDRESS((unsigned long)spd->tx_buffer[1][0]);
327     SAA9730_RXBUFA = CYGARC_PHYSICAL_ADDRESS((unsigned long)spd->rx_buffer[0][0]);
328     SAA9730_RXBUFB = CYGARC_PHYSICAL_ADDRESS((unsigned long)spd->rx_buffer[1][0]);
329
330     SAA9730_PKTCNT = ((SAA9730_TXPKTS_PER_BUFFER << 24) |
331                       (SAA9730_TXPKTS_PER_BUFFER << 16) |
332                       (SAA9730_RXPKTS_PER_BUFFER <<  8) |
333                       (SAA9730_RXPKTS_PER_BUFFER <<  0));
334
335     SAA9730_OK2USE = 0;
336
337     __select_buffer(spd, 0);
338
339     // initialize DMA control register
340     SAA9730_DMACTL = SAA9730_DMACTL_BLKINT |
341                      SAA9730_DMACTL_MAXXFER_ANY |
342                      SAA9730_DMACTL_ENDIAN_LITTLE;
343
344     SAA9730_DMACTL |= SAA9730_DMACTL_RXINT;
345     SAA9730_DMACTL |= (1<<SAA9730_DMACTL_RXINTCNT_SHIFT);
346     SAA9730_DMACTL &= ~SAA9730_DMACTL_BLKINT;
347
348 #ifndef CYGPKG_REDBOOT
349     SAA9730_DMACTL |= SAA9730_DMACTL_TXINT;
350 #endif
351     
352     SAA9730_TIMOUT = 200;
353
354     // accept broadcast packets */
355     SAA9730_CAMCTL = SAA9730_CAMCTL_BROADCAST |
356                      SAA9730_CAMCTL_COMPARE;
357
358     SAA9730_TXCTL = 0;
359     SAA9730_RXCTL |= SAA9730_RXCTL_STRIPCRC;
360
361     SAA9730_CAMENA = 1;
362
363 }
364
365 static void
366 __check_mii(struct saa9730_priv_data *spd)
367 {
368     unsigned long __base = spd->base;
369     cyg_uint32 opmode;
370
371 #ifdef DEBUG
372     db_printf("__check_mii\n");    
373 #endif
374     
375     // spin till station is not busy
376     while (SAA9730_MDCTL & SAA9730_MDCTL_BUSY)
377         ;
378
379     // set PHY address = 'STATUS'
380     SAA9730_MDCTL = SAA9730_MDCTL_BUSY |
381                     (PHY_ADDRESS << SAA9730_MDCTL_PHY_SHIFT)  |
382                     PHY_STATUS;
383
384     // spin till station is not busy
385     while (SAA9730_MDCTL & SAA9730_MDCTL_BUSY)
386         ;
387
388     hal_delay_us(1000);
389
390     // check the link status
391     if (SAA9730_MDDATA & PHY_STATUS_LINK_UP) {
392
393         SAA9730_MDCTL = SAA9730_MDCTL_BUSY |
394                         (PHY_ADDRESS << SAA9730_MDCTL_PHY_SHIFT)  |
395                         PHY_REG31;
396
397         // spin till station is not busy
398         while (SAA9730_MDCTL & SAA9730_MDCTL_BUSY)
399             ;
400
401         hal_delay_us(1000);
402
403         opmode = (SAA9730_MDDATA & PHY_REG31_OPMODE_MSK) >> PHY_REG31_OPMODE_SHIFT;
404
405 #ifdef DEBUG
406         db_printf("MII mode %d\n", opmode);
407 #endif
408
409         if ((opmode == OPMODE_10BASET_FULLDUPLEX) ||
410             (opmode == OPMODE_100BASEX_FULLDUPLEX))
411             SAA9730_MACCTL = SAA9730_MACCTL_CONMODE_FORCE_MII | SAA9730_MACCTL_FULLDUP;
412         else
413             SAA9730_MACCTL = SAA9730_MACCTL_CONMODE_FORCE_MII;
414     }
415 #ifdef DEBUG
416     else
417         db_printf("Link is down\n");
418 #endif
419 }
420
421
422 static void
423 saa9730_reset(struct saa9730_priv_data *spd)
424 {
425     unsigned long __base = spd->base;
426
427     __init_buffers(spd);
428
429     __base = spd->base;
430     
431     // Stop DMA
432     SAA9730_DMACTL &= ~(SAA9730_DMACTL_ENRX | SAA9730_DMACTL_ENTX);
433
434     // Stop tx/rx
435     SAA9730_TXCTL &= ~SAA9730_TXCTL_ENTX;
436     SAA9730_RXCTL &= ~SAA9730_RXCTL_ENRX;
437
438     // Set DMA and MAC reset bits
439     SAA9730_DMATST |= SAA9730_DMATST_RESET;
440     SAA9730_MACCTL |= SAA9730_MACCTL_RESET;
441
442     __init_cam(spd);
443     __init_dma(spd);
444     __check_mii(spd);
445
446     spd->tx_busy = 0;
447 }
448
449
450 static bool 
451 atlas_saa9730_init(struct cyg_netdevtab_entry *tab)
452 {
453     static int initialized = 0; // only probe PCI et al *once*
454     struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
455     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
456
457 #ifdef DEBUG
458     db_printf("atlas_saa9730_init\n");
459 #endif
460
461     if (0 == initialized) {
462         cyg_pci_device_id devid;
463         cyg_pci_device dev_info;
464
465         cyg_pci_init();
466
467         devid = CYG_PCI_NULL_DEVID;
468
469         if (cyg_pci_find_device(CYG_PCI_VENDOR_PHILIPS, 0x9730, &devid) ) {
470
471             spd->devid = devid;
472
473             cyg_pci_get_device_info(devid, &dev_info);
474
475             if (!cyg_pci_configure_device(&dev_info)) {
476 #ifdef DEBUG
477                 db_printf("Failed to configure eth device\n");
478 #endif
479                 return false;
480             }
481
482             //  Philips SAA9730 implements only one function memory mapped
483             //  into a single contigous memory region.
484             //
485             //  According to spec. the BAR#1 is to be used for memory mapped IO.
486             spd->base = dev_info.base_map[1];
487
488             // FIXME! All IO units share an interrupt
489             spd->vector = CYGNUM_HAL_INTERRUPT_INTB;
490
491             // Setup timing stuff
492             cyg_hal_plf_pci_cfg_write_byte(CYG_PCI_DEV_GET_BUS(devid),
493                                            CYG_PCI_DEV_GET_DEVFN(devid),
494                                            CYG_PCI_CFG_LATENCY_TIMER, 0x20);
495             cyg_hal_plf_pci_cfg_write_byte(CYG_PCI_DEV_GET_BUS(devid),
496                                            CYG_PCI_DEV_GET_DEVFN(devid),
497                                            CYG_PCI_CFG_MIN_GNT, 9);
498             cyg_hal_plf_pci_cfg_write_byte(CYG_PCI_DEV_GET_BUS(devid),
499                                            CYG_PCI_DEV_GET_DEVFN(devid),
500                                            CYG_PCI_CFG_MAX_LAT, 24);
501             
502 #ifdef DEBUG
503             db_printf("eth0 found: bus[%d] dev[%d] base[%x] vector[%d]\n",
504                       CYG_PCI_DEV_GET_BUS(devid),
505                       CYG_PCI_DEV_GET_DEV(CYG_PCI_DEV_GET_DEVFN(devid)),
506                       spd->base, spd->vector);
507 #endif
508
509             spd->ndp = tab;
510             
511 #ifndef CYGPKG_REDBOOT
512             cyg_drv_interrupt_create(
513                     spd->vector,
514                     0,                  // Priority - unused
515                     (CYG_ADDRWORD)spd,  // Data item passed to ISR & DSR
516                     saa9730_isr,            // ISR
517                     saa9730_dsr,            // DSR
518                     &spd->interrupt_handle, // handle to intr obj
519                     &spd->interrupt_object ); // space for int obj
520
521             cyg_drv_interrupt_attach(spd->interrupt_handle);
522             cyg_drv_interrupt_acknowledge(spd->vector);
523             cyg_drv_interrupt_unmask(spd->vector);
524 #endif
525             {
526                 // When in Redboot we want to get RX interrupts. These
527                 // will be picked up by the default interrupt handler and
528                 // checked for ^C.
529                 unsigned long __base = spd->base;
530                 SAA9730_EVM_IER_SW |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);                
531                 SAA9730_EVM_IER |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
532                 SAA9730_EVM_ISR |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
533             }
534
535 #ifdef DEBUG
536             db_printf(" **** Device enabled for I/O and Memory and Bus Master\n");
537 #endif
538
539         } else {
540 #ifdef DEBUG
541             db_printf("eth0 not found\n");
542 #endif
543         }
544
545         saa9730_stop(sc);
546         
547         spd->active = 0;
548
549         initialized = 1;
550     }
551
552     // Fetch hardware address
553 #if defined(CYGPKG_REDBOOT) && \
554     defined(CYGSEM_REDBOOT_FLASH_CONFIG) && \
555     !defined(CYGSEM_MIPS_ATLAS_SET_ESA)
556     flash_get_config("atlas_esa", enaddr, CONFIG_ESA);
557 #else
558 #define CONFIG_ESA     6
559     CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET,
560                                  "atlas_esa", enaddr, CONFIG_ESA );
561 #ifdef DEBUG
562     db_printf("ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
563               enaddr[0],enaddr[1],enaddr[2],enaddr[3],enaddr[4],enaddr[5]);
564 #endif
565 #endif
566
567     saa9730_reset(spd);
568
569     // Initialize upper level driver
570     (sc->funs->eth_drv->init)(sc, enaddr);
571
572     return true;
573 }
574
575 static void
576 saa9730_stop(struct eth_drv_sc *sc)
577 {
578     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
579     unsigned long __base = spd->base;
580
581     // Stop DMA
582     SAA9730_DMACTL &= ~(SAA9730_DMACTL_ENRX | SAA9730_DMACTL_ENTX);
583
584     // Stop tx/rx
585     SAA9730_TXCTL &= ~SAA9730_TXCTL_ENTX;
586     SAA9730_RXCTL &= ~SAA9730_RXCTL_ENRX;
587
588     // Set DMA and MAC reset bits
589     SAA9730_DMATST |= SAA9730_DMATST_RESET;
590     SAA9730_MACCTL |= SAA9730_MACCTL_RESET;
591
592     spd->active = 0;
593 }
594
595 static void
596 __do_start(struct saa9730_priv_data *spd)
597 {
598     unsigned long __base = spd->base;
599     int i;
600
601     spd->active = 1;
602     spd->tx_busy = 0;
603
604     for (i = 0; i < SAA9730_BUFFERS; i++)
605         spd->tx_used[i] = 0;
606
607     // for tx, turn on MAC first
608     SAA9730_TXCTL |= SAA9730_TXCTL_ENTX;
609     SAA9730_DMACTL |= SAA9730_DMACTL_ENTX;
610
611     // for rx, turn on DMA first
612     SAA9730_DMACTL |= SAA9730_DMACTL_ENRX;
613     SAA9730_RXCTL |= SAA9730_RXCTL_ENRX;
614
615     __select_buffer(spd, spd->next_rx_bindex);    
616 }
617
618 //
619 // This function is called to "start up" the interface.  It may be called
620 // multiple times, even when the hardware is already running.  It will be
621 // called whenever something "hardware oriented" changes and should leave
622 // the hardware ready to send/receive packets.
623 //
624 static void
625 saa9730_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
626 {
627     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
628
629     if (spd->active)
630         saa9730_stop(sc);
631
632     __do_start(spd);
633 }
634
635 //
636 // This routine is called to perform special "control" opertions
637 //
638 static int
639 saa9730_control(struct eth_drv_sc *sc, unsigned long key,
640                void *data, int data_length)
641 {
642     switch (key) {
643     case ETH_DRV_SET_MAC_ADDRESS:
644         return 0;
645         break;
646     default:
647         return 1;
648         break;
649     }
650 }
651
652 //
653 // This routine is called to see if it is possible to send another packet.
654 // It will return non-zero if a transmit is possible, zero otherwise.
655 //
656 static int
657 saa9730_can_send(struct eth_drv_sc *sc)
658 {
659     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
660     unsigned long __base = spd->base;
661
662     __tx_poll(sc);
663
664     if (spd->next_tx_bindex == 0  && (SAA9730_OK2USE & SAA9730_OK2USE_TXA))
665         return 0;
666
667     if (spd->next_tx_bindex == 1  && (SAA9730_OK2USE & SAA9730_OK2USE_TXB))
668         return 0;
669
670     return 1;
671 }
672
673
674 static int tx_poll_count;
675
676 //
677 // This routine is called to send data to the hardware.
678 static void 
679 saa9730_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, 
680             int total_len, unsigned long key)
681 {
682     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
683     unsigned long __base = spd->base;
684     int bindex, pindex;
685     cyg_uint32 pktlen = total_len;
686     cyg_uint8  *pktdata, *to_p;
687     volatile cyg_uint32 *pktstat ;
688     struct eth_drv_sg *last_sg;
689
690 #ifdef DEBUG
691     db_printf("saa9730_send: %d sg's, %d bytes, KEY %x\n",
692               sg_len, total_len, key );
693 #endif
694
695     if (!spd->active)
696         return;
697
698     bindex = spd->next_tx_bindex;
699     pindex = spd->next_tx_pindex;
700
701     spd->next_tx_pindex++;
702     if (spd->next_tx_pindex >= SAA9730_TXPKTS_PER_BUFFER) {
703         spd->next_tx_pindex = 0;
704         spd->next_tx_bindex ^= 1;
705     }
706
707     pktstat = spd->tx_buffer[bindex][pindex];
708         
709     if (bindex == 0 && (SAA9730_OK2USE & SAA9730_OK2USE_TXA))
710         return;
711
712     if (bindex == 1 && (SAA9730_OK2USE & SAA9730_OK2USE_TXB))
713         return;
714
715     spd->tx_key[bindex][pindex] = key;
716     spd->tx_used[bindex] += 1;
717
718     pktdata = (cyg_uint8 *)((unsigned)pktstat + 4);
719
720     // Copy from the sglist into the tx buffer
721     to_p = pktdata;
722
723     for (last_sg = &sg_list[sg_len]; sg_list < last_sg; sg_list++) {
724         cyg_uint8 *from_p;
725         int l;
726             
727         from_p = (cyg_uint8 *)(sg_list->buf);
728         l = sg_list->len;
729
730         if (l > total_len)
731             l = total_len;
732
733         memcpy((unsigned char *)to_p, from_p, l);
734         to_p += l;
735         total_len -= l;
736
737         if (total_len < 0) 
738             break; // Should exit via sg_last normally
739     }
740
741     // pad to minimum size
742     if (pktlen < SAA9730_MIN_PACKET_SIZE) {
743         memset(to_p, 0, SAA9730_MIN_PACKET_SIZE-pktlen);
744         pktlen = SAA9730_MIN_PACKET_SIZE;
745     }
746
747     // Set transmit status WORD for hardware (LAN-DMA-ENGINE)
748     *pktstat = CYG_CPU_TO_LE32(TX_READY | pktlen);
749
750     // start hardware
751     if (bindex == 0)
752         SAA9730_OK2USE |= SAA9730_OK2USE_TXA;
753     else 
754         SAA9730_OK2USE |= SAA9730_OK2USE_TXB;
755
756     if (!spd->tx_busy) {
757         tx_poll_count = 0;
758         spd->tx_busy = bindex + 1;
759     }
760 }
761
762
763 static void
764 __check_rxstate(struct saa9730_priv_data *spd)
765 {
766     unsigned long __base = spd->base;
767     cyg_uint32  status, flag, size;
768     cyg_uint32  *pkt;
769     int         i, j;
770
771 #ifdef DEBUG
772     db_printf("__check_rxstate\n");        
773 #endif
774
775 #ifdef CYGPKG_REDBOOT
776     // Clear SAA9730 LAN interrupt and re-enable interrupts.
777     SAA9730_EVM_ISR = SAA9730_EVM_LAN_INT;
778     SAA9730_EVM_IER_SW |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
779 #endif
780     
781     if ((SAA9730_DBGRXS & SAA9730_DBGRXS_RXDII_MASK) == SAA9730_DBGRXS_RXDII_ERROR) {
782         // re-init driver and controller
783 #ifdef DEBUG
784         db_printf("DBGRXS: reset\n");
785 #endif
786         saa9730_reset(spd);
787         __do_start(spd);
788         return;
789     }
790
791     // Check RX packet status
792     for (i = 0; i < SAA9730_BUFFERS; i++) {
793         for (j = 1; j < SAA9730_RXPKTS_PER_BUFFER; j++) {
794             pkt = spd->rx_buffer[i][j];
795             status = CYG_LE32_TO_CPU(*pkt);
796             size   = status & RXPACKET_STATUS_SIZE_MASK;
797             flag   = status & RXPACKET_STATUS_FLAG_MASK;
798             if (flag == RX_INVALID_STAT || size > 1514 || *(pkt - 1)) {
799                 // re-init driver and controller
800 #ifdef DEBUG
801                 db_printf("rxpkt: reset\n");
802 #endif
803                 saa9730_reset(spd);
804                 __do_start(spd);
805                 return;
806             }
807         }
808     }
809 }
810
811
812 static void
813 __tx_poll(struct eth_drv_sc *sc)
814 {
815     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
816     int                  bindex, pindex;
817     volatile cyg_uint32 *pktstat;
818     cyg_uint32 status;
819
820     if (!spd->tx_busy)
821         return;
822
823     bindex = spd->tx_busy - 1;
824     pindex = spd->tx_used[bindex] - 1;  // watch last pkt in buffer
825
826     pktstat = spd->tx_buffer[bindex][pindex];
827
828     status = CYG_LE32_TO_CPU(*pktstat);
829     if ((status & TXPACKET_STATUS_FLAG_MASK) != TX_HWDONE) {
830
831         hal_delay_us(1000);
832
833         if (++tx_poll_count > 1000) {
834             // reset
835
836             for (pindex = 0; pindex < spd->tx_used[bindex]; pindex++)
837                 (sc->funs->eth_drv->tx_done)(sc, spd->tx_key[bindex][pindex], 1);
838
839             bindex ^= 1;
840
841             for (pindex = 0; pindex < spd->tx_used[bindex]; pindex++)
842                 (sc->funs->eth_drv->tx_done)(sc, spd->tx_key[bindex][pindex], 1);
843
844             saa9730_reset(spd);
845             __do_start(spd);
846         }
847         return;
848     }
849
850     for (pindex = 0; pindex < spd->tx_used[bindex]; pindex++) {
851         /* Check for error. */
852         pktstat = spd->tx_buffer[bindex][pindex];
853         status = CYG_LE32_TO_CPU(*pktstat);
854
855         if (status & TXPACKET_STATUS_ERROR) {
856             if (status & TXPACKET_STATUS_EXDEFER)
857                 db_printf("tx deferred\n");
858
859             if (status & TXPACKET_STATUS_LATECOLLERR)
860                 db_printf("tx late collision\n");
861
862             if (status & TXPACKET_STATUS_LOSTCARRIER)
863                 db_printf("tx no carrier\n");
864
865             if (status & TXPACKET_STATUS_UNDERRUN)
866                 db_printf("tx underrun\n");
867
868             if (status & TXPACKET_STATUS_SQERR)
869                 db_printf("tx sq\n");
870         }
871         /* free the space */
872         *pktstat = CYG_CPU_TO_LE32(TX_EMPTY);
873
874         (sc->funs->eth_drv->tx_done)(sc, spd->tx_key[bindex][pindex], 1 /* status */);
875     }
876
877     tx_poll_count = 0;
878     spd->tx_used[bindex] = 0;
879     
880     bindex ^= 1;
881     if (spd->tx_used[bindex])
882         spd->tx_busy = bindex + 1;
883     else
884         spd->tx_busy = 0;
885 }
886
887
888 static void
889 __rx_poll(struct eth_drv_sc *sc)
890 {
891     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
892     int                  bindex, pindex, done;
893     volatile cyg_uint32 *pkt;
894     cyg_uint32           status, pktlen; 
895
896 #ifdef DEBUG
897     db_printf("__rx_poll\n");
898 #endif
899     if (!spd->active)
900         return;
901
902     done = 0;
903     while (!done) {
904         // index of next packet buffer
905         bindex = spd->next_rx_bindex;
906
907         // index of next packet within buffer
908         pindex = spd->next_rx_pindex;
909
910         pkt = spd->rx_buffer[bindex][pindex];
911
912         // stop now if no more packets
913         if (((status = CYG_LE32_TO_CPU(*pkt)) & RXPACKET_STATUS_FLAG_MASK) == RX_READY)
914             break;
915 #ifdef DEBUG
916         db_printf("__rx_poll pkt %08x status %08x\n",pkt,status);
917 #endif
918         // if this is the first packet in a buffer, switch the SAA9730 to
919         // use the next buffer for subsequent incoming packets.
920         if (pindex == 0)
921             __select_buffer(spd, bindex == 0);
922             
923         // check for good packet
924         if (status & RXPACKET_STATUS_GOOD) {
925
926             pktlen = status & RXPACKET_STATUS_SIZE_MASK ;
927
928             if (pktlen > 0) {
929                 (sc->funs->eth_drv->recv)(sc, pktlen);
930                 // done = 1;
931             }
932         }
933 #ifdef DEBUG
934         else
935             db_printf("rx bad: %08x %08x\n",pkt,status);
936 #endif
937         
938         /* go to next packet in sequence */
939         spd->next_rx_pindex++;
940         if (spd->next_rx_pindex >= SAA9730_RXPKTS_PER_BUFFER) {
941             spd->next_rx_pindex = 0;
942             spd->next_rx_bindex++;
943             if (spd->next_rx_bindex >= SAA9730_BUFFERS) 
944                 spd->next_rx_bindex = 0;
945         }
946     }
947
948     if (((poll_count++) % 100) == 0)
949         __check_rxstate(spd);
950 }
951
952
953 static void
954 saa9730_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
955 {
956     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
957     volatile cyg_uint32 *pkt;
958     cyg_uint32          pktlen, status;
959     struct eth_drv_sg   *last_sg;
960
961     if (!spd->active)
962         return;
963
964     pkt = spd->rx_buffer[spd->next_rx_bindex][spd->next_rx_pindex];
965
966     status = CYG_LE32_TO_CPU(*pkt);
967     if (status & RXPACKET_STATUS_GOOD) {
968         // packet is good
969         pktlen = status & RXPACKET_STATUS_SIZE_MASK;
970
971         if (pktlen > 0) {
972             int total_len;
973             cyg_uint8 *from_p;
974
975             // check we have memory to copy into; we would be called even if
976             // caller was out of memory in order to maintain our state.
977             if (0 == sg_len || 0 == sg_list)
978                 return; // caller was out of mbufs
979
980             total_len = pktlen;
981             from_p = (cyg_uint8 *)((unsigned)pkt + 4);
982
983             for (last_sg = &sg_list[sg_len]; sg_list < last_sg; sg_list++) {
984                 cyg_uint8 *to_p;
985                 int l;
986             
987                 to_p = (cyg_uint8 *)(sg_list->buf);
988                 l = sg_list->len;
989
990                 if (0 >= l || 0 == to_p)
991                     return; // caller was out of mbufs
992
993                 if (l > total_len)
994                     l = total_len;
995
996                 memcpy(to_p, (unsigned char *)from_p, l);
997                 from_p += l;
998                 total_len -= l;
999             }
1000         }
1001     }
1002 }
1003
1004 static inline void
1005 __do_deliver(struct eth_drv_sc *sc)
1006 {
1007     // First pass any rx data up the stack
1008     __rx_poll(sc);
1009
1010     // Then scan for completed Txen and inform the stack
1011     __tx_poll(sc);
1012 }
1013
1014 static void
1015 saa9730_poll(struct eth_drv_sc *sc)
1016 {
1017     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
1018
1019 #ifndef CYGPKG_REDBOOT
1020     cyg_drv_interrupt_mask(spd->vector);
1021 #endif
1022
1023     (void)saa9730_isr(spd->vector, (cyg_addrword_t)spd);
1024
1025     __do_deliver(sc);
1026
1027     cyg_drv_interrupt_acknowledge(spd->vector);
1028
1029 #ifndef CYGPKG_REDBOOT
1030     cyg_drv_interrupt_unmask(spd->vector);
1031 #endif    
1032 }
1033
1034
1035 // The deliver function (ex-DSR)  handles the ethernet [logical] processing
1036 static void
1037 saa9730_deliver(struct eth_drv_sc *sc)
1038 {
1039     struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
1040     unsigned long __base = spd->base;    
1041
1042     if (spd->active)
1043         __do_deliver(sc);
1044
1045     cyg_drv_interrupt_acknowledge(spd->vector);
1046
1047 #ifndef CYGPKG_REDBOOT
1048     // Clear SAA9730 LAN interrupt and re-enable interrupts.
1049     SAA9730_EVM_IER_SW |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
1050     cyg_drv_interrupt_unmask(spd->vector);
1051 #endif    
1052 }
1053
1054