]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/eth/via/rhine/v2_0/src/if_rhine.c
Initial revision
[karo-tx-redboot.git] / packages / devs / eth / via / rhine / v2_0 / src / if_rhine.c
1 //==========================================================================
2 //
3 //      dev/if_rhine.c
4 //
5 //      Ethernet device driver for VIA RHINE compatible controllers
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 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //####BSDCOPYRIGHTBEGIN####
41 //
42 // -------------------------------------------
43 //
44 // Portions of this software may have been derived from OpenBSD or other sources,
45 // and are covered by the appropriate copyright disclaimers included herein.
46 //
47 // -------------------------------------------
48 //
49 //####BSDCOPYRIGHTEND####
50 //==========================================================================
51 //#####DESCRIPTIONBEGIN####
52 //
53 // Author(s):    jskov, based on pcnet driver
54 // Contributors: gthomas, jskov, hmt
55 // Date:         2001-05-30
56 // Purpose:      
57 // Description:  hardware driver for VIA Rhine ethernet
58 //
59 // FIXME:        Make endian safe
60 //               Make use of virtual addressing for memory shared over PCI
61 //                (see _ADDR_MASK).          
62 //               Link failure not detected for some reason.
63 //
64 //####DESCRIPTIONEND####
65 //
66 //==========================================================================
67
68 #include <pkgconf/system.h>
69 #include <pkgconf/devs_eth_via_rhine.h>
70 #include <pkgconf/io_eth_drivers.h>
71
72 #include <cyg/infra/cyg_type.h>
73 #include <cyg/hal/hal_arch.h>
74 #include <cyg/hal/hal_intr.h>
75 #include <cyg/infra/cyg_ass.h>
76 #include <cyg/infra/diag.h>
77 #include <cyg/hal/drv_api.h>
78 #include <cyg/io/eth/netdev.h>
79 #include <cyg/io/eth/eth_drv.h>
80 #ifdef CYGPKG_NET
81 #include <pkgconf/net.h>
82 #include <cyg/kernel/kapi.h>
83 #include <net/if.h>  /* Needed for struct ifnet */
84 #include <pkgconf/io_eth_drivers.h>
85 #endif
86 #include CYGHWR_MEMORY_LAYOUT_H
87
88 #ifdef CYGPKG_IO_PCI
89 #include <cyg/io/pci.h>
90 #else
91 #error "Need PCI package here"
92 #endif
93
94 #define _BUF_SIZE 1544
95
96 #ifdef CYGPKG_INFRA_DEBUG
97 // Then we log, OOI, the number of times we get a bad packet number
98 // from the tx done fifo.
99 int rhine_txfifo_good = 0;
100 int rhine_txfifo_bad = 0;
101 #endif
102
103 #include "via_rhine.h"
104
105 #define __WANT_DEVS
106 #include CYGDAT_DEVS_ETH_VIA_RHINE_INL
107 #undef  __WANT_DEVS
108
109 static void rhine_poll(struct eth_drv_sc *sc);
110
111 // This ISR is called when the ethernet interrupt occurs
112 static cyg_uint32
113 rhine_isr(cyg_vector_t vector, cyg_addrword_t data)
114 {
115     struct rhine_priv_data *cpd = (struct rhine_priv_data *)data;
116
117     DEBUG_FUNCTION();
118
119     INCR_STAT( interrupts );
120
121     cyg_drv_interrupt_mask(cpd->interrupt);
122     cyg_drv_interrupt_acknowledge(cpd->interrupt);
123     return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
124 }
125
126 static void
127 rhine_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
128 {
129     // This conditioning out is necessary because of explicit calls to this
130     // DSR - which would not ever be called in the case of a polled mode
131     // usage ie. in RedBoot.
132 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
133     struct rhine_priv_data* cpd = (struct rhine_priv_data *)data;
134     struct cyg_netdevtab_entry *ndp = (struct cyg_netdevtab_entry *)(cpd->ndp);
135     struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance);
136
137     // but here, it must be a *sc:
138     eth_drv_dsr( vector, count, (cyg_addrword_t)sc );
139 #else
140 # ifndef CYGPKG_REDBOOT
141 #  error Empty Rhine ethernet DSR is compiled.  Is this what you want?
142 # endif
143 #endif
144 }
145
146 // The deliver function (ex-DSR)  handles the ethernet [logical] processing
147 static void
148 rhine_deliver(struct eth_drv_sc *sc)
149 {
150     struct rhine_priv_data *cpd = (struct rhine_priv_data *)sc->driver_private;
151
152     DEBUG_FUNCTION();
153
154     // Service the interrupt:
155     rhine_poll(sc);
156     // Allow interrupts to happen again
157     cyg_drv_interrupt_unmask(cpd->interrupt);
158 }
159
160 static int
161 rhine_int_vector(struct eth_drv_sc *sc)
162 {
163     struct rhine_priv_data *cpd =
164         (struct rhine_priv_data *)sc->driver_private;
165
166     return (cpd->interrupt);
167 }
168
169 // ------------------------------------------------------------------------
170 // Physical interface
171 #if 0 // fix warning since this isn't actually used
172 static void
173 rhine_write_MII(struct rhine_priv_data *cpd, int id, int reg, cyg_uint16 value)
174 {
175     cyg_uint8 stat;
176     int i = 1000;
177
178     // Wait for a previous access to complete (within reason)
179     do {
180         HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_MIICR, stat);
181     } while ((stat & (RHINE_MIICR_RCMD | RHINE_MIICR_WCMD)) && i-- > 0);
182     
183     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_MIICR, 0);
184     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_PHYADR, id);
185     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_MIIAD, reg);
186     HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_MIIDATA, value);
187     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_MIICR, RHINE_MIICR_WCMD);
188 }
189 #endif
190
191 static int
192 rhine_read_MII(struct rhine_priv_data *cpd, int id, int reg)
193 {
194     int i = 1000;
195     cyg_uint8 stat;
196     cyg_uint16 val;
197
198     // Wait for a previous access to complete (within reason)
199     do {
200         HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_MIICR, stat);
201     } while ((stat & (RHINE_MIICR_RCMD | RHINE_MIICR_WCMD)) && i-- > 0);
202
203     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_MIICR, 0);
204     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_PHYADR, id);
205     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_MIIAD, reg);
206     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_MIICR, RHINE_MIICR_RCMD);
207
208     i = 1000;
209     do {
210         HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_MIICR, stat);
211     } while ((stat & RHINE_MIICR_RCMD) && i-- > 0);
212
213     HAL_PCI_IO_READ_UINT16(cpd->base + RHINE_MIIDATA, val);
214     return val;
215 }
216
217 // ------------------------------------------------------------------------
218 // Memory management
219 //
220 // Simply carve off from the front of the PCI mapped window into real memory
221 static cyg_uint32 rhine_heap_size;
222 static cyg_uint8 *rhine_heap_base;
223 static cyg_uint8 *rhine_heap_free;
224
225 static void*
226 pciwindow_mem_alloc(int size)
227 {
228     void *p_memory;
229     int _size = size;
230
231     CYG_ASSERT(
232         (CYGHWR_VIA_RHINE_PCI_MEM_MAP_BASE <= (int)rhine_heap_free)
233         &&
234         ((CYGHWR_VIA_RHINE_PCI_MEM_MAP_BASE + 
235           CYGHWR_VIA_RHINE_PCI_MEM_MAP_SIZE) > (int)rhine_heap_free)
236         &&
237         (0 < rhine_heap_size)
238         &&
239         (CYGHWR_VIA_RHINE_PCI_MEM_MAP_SIZE >= rhine_heap_size)
240         &&
241         (CYGHWR_VIA_RHINE_PCI_MEM_MAP_BASE == (int)rhine_heap_base),
242         "Heap variables corrupted" );
243
244     p_memory = (void *)0;
245     size = (size + 3) & ~3;
246     if ( (rhine_heap_free+size) < (rhine_heap_base+rhine_heap_size) ) {
247         cyg_uint32 *p;
248         p_memory = (void *)rhine_heap_free;
249         rhine_heap_free += size;
250         for ( p = (cyg_uint32 *)p_memory; _size > 0; _size -= 4 )
251             *p++ = 0;
252     }
253
254 #if DEBUG & 9
255     diag_printf("Allocated %d bytes at %08x\n", size, p_memory);
256 #endif
257
258     return p_memory;
259 }
260
261 static cyg_pci_match_func find_rhine_match_func;
262
263 static cyg_bool
264 find_rhine_match_func( cyg_uint16 v, cyg_uint16 d, cyg_uint32 c, void *p )
265 {
266 #if DEBUG & 9
267     diag_printf("PCI match vendor %04x device %04x\n", v, d);
268 #endif
269     return
270         (0x1106 == v) &&                // vendor: VIA
271         ((0x3065 == d) ||               // device: DL10030A
272          (0x3043 == d));                // device: VT86C100A
273 }
274
275 static int
276 pci_init_find_rhines( void )
277 {
278     cyg_pci_device_id devid;
279     cyg_pci_device dev_info;
280     cyg_uint16 cmd;
281     int device_index;
282     int found_devices = 0;
283
284     DEBUG_FUNCTION();
285
286 #ifdef CYGARC_UNCACHED_ADDRESS
287     CYG_ASSERT( CYGARC_UNCACHED_ADDRESS((CYG_ADDRWORD)CYGMEM_SECTION_pci_window) ==
288                 CYGHWR_VIA_RHINE_PCI_MEM_MAP_BASE,
289       "PCI window configured does not match PCI memory section base" );
290 #else
291     CYG_ASSERT( (CYG_ADDRWORD)CYGMEM_SECTION_pci_window ==
292                 CYGHWR_VIA_RHINE_PCI_MEM_MAP_BASE,
293       "PCI window configured does not match PCI memory section base" );
294 #endif
295     CYG_ASSERT( CYGMEM_SECTION_pci_window_SIZE ==
296                 CYGHWR_VIA_RHINE_PCI_MEM_MAP_SIZE,
297         "PCI window configured does not match PCI memory section size" );
298
299     if (
300 #ifdef CYGARC_UNCACHED_ADDRESS
301          CYGARC_UNCACHED_ADDRESS((CYG_ADDRWORD)CYGMEM_SECTION_pci_window) !=
302 #else
303          (CYG_ADDRWORD)CYGMEM_SECTION_pci_window !=
304 #endif
305          CYGHWR_VIA_RHINE_PCI_MEM_MAP_BASE
306          ||
307          CYGMEM_SECTION_pci_window_SIZE !=
308          CYGHWR_VIA_RHINE_PCI_MEM_MAP_SIZE ) {
309 #if DEBUG & 8
310         diag_printf("pci_init_find_rhines(): PCI window misconfigured\n");
311 #endif
312         return 0;
313     }
314
315     // First initialize the heap in PCI window'd memory
316     rhine_heap_size = CYGHWR_VIA_RHINE_PCI_MEM_MAP_SIZE;
317     rhine_heap_base = (cyg_uint8 *)CYGHWR_VIA_RHINE_PCI_MEM_MAP_BASE;
318     rhine_heap_free = rhine_heap_base;
319
320     cyg_pci_init();
321 #if DEBUG & 8
322     diag_printf("Finished cyg_pci_init();\n");
323 #endif
324
325     devid = CYG_PCI_NULL_DEVID;
326
327     for (device_index = 0; 
328          device_index < CYGNUM_DEVS_ETH_VIA_RHINE_DEV_COUNT;
329          device_index++) {
330         struct rhine_priv_data* cpd = rhine_priv_array[device_index];
331
332         cpd->index = device_index;
333
334         // See above for find_rhine_match_func - it selects any of several
335         // variants.  This is necessary in case we have multiple mixed-type
336         // devices on one board in arbitrary orders.
337         if (cyg_pci_find_matching( &find_rhine_match_func, NULL, &devid )) {
338 #if DEBUG & 8
339             diag_printf("eth%d = rhine\n", device_index);
340 #endif
341             cyg_pci_get_device_info(devid, &dev_info);
342
343             cpd->interrupt_handle = 0; // Flag not attached.
344             if (cyg_pci_translate_interrupt(&dev_info, &cpd->interrupt)) {
345 #if DEBUG & 8
346                 diag_printf(" Wired to HAL vector %d\n", cpd->interrupt);
347 #endif
348                 cyg_drv_interrupt_create(
349                     cpd->interrupt,
350                     1,                  // Priority - unused
351                     (cyg_addrword_t)cpd,// Data item passed to ISR & DSR
352                     rhine_isr,          // ISR
353                     rhine_dsr,          // DSR
354                     &cpd->interrupt_handle, // handle to intr obj
355                     &cpd->interrupt_object ); // space for int obj
356
357                 cyg_drv_interrupt_attach(cpd->interrupt_handle);
358
359                 // Don't unmask the interrupt yet, that could get us into a
360                 // race.
361             }
362             else {
363                 cpd->interrupt = 0;
364 #if DEBUG & 8
365                 diag_printf(" Does not generate interrupts.\n");
366 #endif
367             }
368
369             if (cyg_pci_configure_device(&dev_info)) {
370 #if DEBUG & 8
371                 int i;
372                 diag_printf("Found device on bus %d, devfn 0x%02x:\n",
373                           CYG_PCI_DEV_GET_BUS(devid),
374                           CYG_PCI_DEV_GET_DEVFN(devid));
375
376                 if (dev_info.command & CYG_PCI_CFG_COMMAND_ACTIVE) {
377                     diag_printf(" Note that board is active. Probed"
378                               " sizes and CPU addresses invalid!\n");
379                 }
380                 diag_printf(" Vendor    0x%04x", dev_info.vendor);
381                 diag_printf("\n Device    0x%04x", dev_info.device);
382                 diag_printf("\n Command   0x%04x, Status 0x%04x\n",
383                           dev_info.command, dev_info.status);
384                 
385                 diag_printf(" Class/Rev 0x%08x", dev_info.class_rev);
386                 diag_printf("\n Header 0x%02x\n", dev_info.header_type);
387
388                 diag_printf(" SubVendor 0x%04x, Sub ID 0x%04x\n",
389                           dev_info.header.normal.sub_vendor, 
390                           dev_info.header.normal.sub_id);
391
392                 for(i = 0; i < CYG_PCI_MAX_BAR; i++) {
393                     diag_printf(" BAR[%d]    0x%08x /", i, dev_info.base_address[i]);
394                     diag_printf(" probed size 0x%08x / CPU addr 0x%08x\n",
395                               dev_info.base_size[i], dev_info.base_map[i]);
396                 }
397                 diag_printf(" eth%d configured\n", device_index);
398 #endif
399                 found_devices++;
400                 cpd->found = 1;
401                 cpd->active = 0;
402                 cpd->devid = devid;
403                 cpd->base = (unsigned char*) dev_info.base_map[0];
404 #if DEBUG & 8
405                 diag_printf(" I/O address = 0x%08x\n", cpd->base);
406 #endif
407
408                 // Don't use cyg_pci_set_device_info since it clears
409                 // some of the fields we want to print out below.
410                 cyg_pci_read_config_uint16(dev_info.devid,
411                                            CYG_PCI_CFG_COMMAND, &cmd);
412                 cmd |= (CYG_PCI_CFG_COMMAND_IO         // enable I/O space
413                         | CYG_PCI_CFG_COMMAND_MEMORY   // enable memory space
414                         | CYG_PCI_CFG_COMMAND_MASTER); // enable bus master
415                 cyg_pci_write_config_uint16(dev_info.devid,
416                                             CYG_PCI_CFG_COMMAND, cmd);
417
418                 // Extra init code needed for D-Link controller. This
419                 // is snuffed from the Linux driver and was provided
420                 // by D-Link. I've been unable to find documentation
421                 // for the part.
422                 if (0x3065 == dev_info.device) {
423                     cyg_uint8 tmp;
424
425 #if DEBUG & 8
426                     diag_printf("Pre-reset init code for D-Link.\n");
427 #endif
428                     HAL_PCI_IO_READ_UINT8(cpd->base+RHINE_STICKYHW, tmp);
429                     tmp &= 0xfc;
430                     HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_STICKYHW, tmp);
431                     
432                     HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_WOL_CG_CLR, 0x80);
433                     HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_WOL_CR_CLR, 0xff);
434                     HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_PWR_CSR_CLR, 0xff);
435                 }
436
437                 // Now the PCI part of the device is configured, reset
438                 // it. This should make it safe to enable the
439                 // interrupt
440                 HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_CR1, RHINE_CR1_SRST);
441
442                 // Reload ESA from EEPROM
443                 {
444                     cyg_uint8 tmp;
445                     int i;
446
447 #if DEBUG & 8
448                     diag_printf("Reload ESA from EEPROM...");
449 #endif
450                     HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_EECSR, 0x20);
451                     for (i = 0; i < 150; i++) {
452                         HAL_PCI_IO_READ_UINT8(cpd->base+RHINE_EECSR, tmp);
453                         if (!(tmp & 0x20)) {
454                             break;
455                         }
456                     }
457 #if DEBUG & 8
458                     if (tmp & 0x20)
459                         diag_printf("Timed out\n");
460                     else
461                         diag_printf("Done\n");
462 #endif
463                 }
464
465                 // This is the indicator for "uses an interrupt"
466                 if (cpd->interrupt_handle != 0) {
467                     cyg_drv_interrupt_acknowledge(cpd->interrupt);
468                     cyg_drv_interrupt_unmask(cpd->interrupt);
469 #if DEBUG & 8
470                     diag_printf(" Enabled interrupt %d\n", cpd->interrupt);
471 #endif
472                 }
473 #if DEBUG & 8
474                 diag_printf(" **** Device enabled for I/O and Memory "
475                             "and Bus Master\n");
476 #endif
477             }
478             else {
479                 cpd->found = 0;
480                 cpd->active = 0;
481 #if DEBUG & 8
482                 diag_printf("Failed to configure device %d\n", device_index);
483 #endif
484             }
485         }
486         else {
487             cpd->found = 0;
488             cpd->active = 0;
489 #if DEBUG & 8
490             diag_printf("eth%d not found\n", device_index);
491 #endif
492         }
493     }
494
495     if (0 == found_devices)
496         return 0;
497
498     return 1;
499 }
500
501 static bool 
502 via_rhine_init(struct cyg_netdevtab_entry *tab)
503 {
504     static int initialized = 0; // only probe PCI et al *once*
505     struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
506     struct rhine_priv_data *cpd =
507         (struct rhine_priv_data *)sc->driver_private;
508     cyg_uint8 *d, *p, *p_next;
509     int i;
510     cyg_addrword_t ba;
511
512     DEBUG_FUNCTION();
513
514     if ( 0 == initialized++ ) {
515         // then this is the first time ever:
516         if ( ! pci_init_find_rhines() ) {
517 #if DEBUG & 8
518             diag_printf( "pci_init_find_rhines failed" );
519 #endif
520             return false;
521         }
522     }
523
524     // If this device is not present, exit
525     if (0 == cpd->found)
526         return 0;
527
528 #if DEBUG & 8
529     diag_printf( "Rhine device SC %08x CPD %08x\n", sc, cpd);
530 #endif
531
532     // Look for physical MII device
533     for (i = 0; i < 32; i++) {
534         cyg_uint16 mii_status = rhine_read_MII(cpd, i, MII_BMSR);
535         if (mii_status != 0x0000 && mii_status != 0xffff) {
536             cpd->phys_id = i;
537 #if DEBUG & 8
538             diag_printf("Found MII interface at id %d, status %04x, adv 0x%04x, link 0x%04x\n",
539                         cpd->phys_id, mii_status, rhine_read_MII(cpd,i,4), rhine_read_MII(cpd,i,5));
540 #endif
541             break;
542         }
543     }
544 #if DEBUG & 8
545     if (i == 32)
546         diag_printf("No MII interface found!");
547 #endif
548
549     // Prepare ESA
550     if (cpd->hardwired_esa) {
551         // Force the NIC to use the specified ESA
552         p = cpd->base + RHINE_PAR0;
553         for (i = 0; i < 6; i++)
554             *p++ = cpd->esa[i];
555     } else {
556         // Use the address from the serial EEPROM
557         p = cpd->base + RHINE_PAR0;
558         for (i = 0; i < 6; i++)
559             cpd->esa[i] = *p++;
560     }
561 #if DEBUG & 8
562     diag_printf("RHINE - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
563                 (cpd->hardwired_esa) ? "static" : "eeprom",
564                 cpd->esa[0],
565                 cpd->esa[1],
566                 cpd->esa[2],
567                 cpd->esa[3],
568                 cpd->esa[4],
569                 cpd->esa[5] );
570 #endif
571
572     // Prepare RX and TX rings
573     p = cpd->rx_ring = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS(pciwindow_mem_alloc((1<<cpd->rx_ring_log_cnt)*RHINE_RD_SIZE));
574     d = cpd->rx_buffers = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS(pciwindow_mem_alloc(_BUF_SIZE*cpd->rx_ring_cnt));
575     for (i = 0; i < cpd->rx_ring_cnt; i++) {
576         p_next = p + RHINE_RD_SIZE;
577         HAL_PCI_CPU_TO_BUS((cyg_uint32)d, ba);
578         _SU32(p, RHINE_RDES2) = ba;
579         _SU32(p, RHINE_RDES1) = _BUF_SIZE;
580         HAL_PCI_CPU_TO_BUS((cyg_uint32)p_next, ba);
581         _SU32(p, RHINE_RDES3) = ba;
582         _SU32(p, RHINE_RDES0) = RHINE_RDES0_OWN;
583 #if DEBUG & 8
584         diag_printf("Set RDES at 0x%08lx to 0x%08x 0x%08x 0x%08x 0x%08x\n",
585                     (unsigned long)p,
586                     _SU32(p, RHINE_RDES0), _SU32(p, RHINE_RDES1),
587                     _SU32(p, RHINE_RDES2), _SU32(p, RHINE_RDES3));
588 #endif
589         p = p_next;
590         d += _BUF_SIZE;
591     }
592     // last entry wraps to the first
593     p -= RHINE_RD_SIZE;
594     HAL_PCI_CPU_TO_BUS((cyg_uint32)cpd->rx_ring, ba);
595     _SU32(p, RHINE_RDES3) = ba;
596 #if DEBUG & 8
597     diag_printf("Set RDES at 0x%08lx to 0x%08x 0x%08x 0x%08x 0x%08x\n",
598                 (unsigned long)p,
599                 _SU32(p, RHINE_RDES0), _SU32(p, RHINE_RDES1),
600                 _SU32(p, RHINE_RDES2), _SU32(p, RHINE_RDES3));
601 #endif
602     cpd->rx_ring_next = 0;
603     // CPU to PCI space translation
604     HAL_PCI_CPU_TO_BUS((cyg_uint32)cpd->rx_ring, ba);
605     HAL_PCI_IO_WRITE_UINT32(cpd->base + RHINE_CUR_RX, ba);
606
607     p = cpd->tx_ring = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS(pciwindow_mem_alloc((1<<cpd->tx_ring_log_cnt)*RHINE_TD_SIZE));
608     d = cpd->tx_buffers = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS(pciwindow_mem_alloc(_BUF_SIZE*cpd->tx_ring_cnt));
609     for (i = 0; i < cpd->tx_ring_cnt; i++) {
610
611         _SU32(p, RHINE_TDES0) = 0;
612         _SU32(p, RHINE_TDES1) = (RHINE_TDES1_IC|RHINE_TDES1_EDP|RHINE_TDES1_STP|RHINE_TDES1_C);
613         HAL_PCI_CPU_TO_BUS((cyg_uint32)d, ba);
614         _SU32(p, RHINE_TDES2) = ba;
615         HAL_PCI_CPU_TO_BUS((cyg_uint32)(p + RHINE_TD_SIZE), ba);
616         _SU32(p, RHINE_TDES3) = ba;
617 #if DEBUG & 8
618         diag_printf("Set TDES at 0x%08lx to 0x%08x 0x%08x 0x%08x 0x%08x\n",
619                     (unsigned long)p,
620                     _SU32(p, RHINE_TDES0), _SU32(p, RHINE_TDES1),
621                     _SU32(p, RHINE_TDES2), _SU32(p, RHINE_TDES3));
622 #endif
623         p += RHINE_TD_SIZE;
624         d += _BUF_SIZE;
625     }
626
627     // last entry wraps to the first
628     p -= RHINE_TD_SIZE;
629     HAL_PCI_CPU_TO_BUS((cyg_uint32)cpd->tx_ring, ba);
630     _SU32(p, RHINE_TDES3) = ba;
631 #if DEBUG & 8
632     diag_printf("Set TDES at 0x%08lx to 0x%08x 0x%08x 0x%08x 0x%08x\n",
633                 (unsigned long)p,
634                 _SU32(p, RHINE_TDES0), _SU32(p, RHINE_TDES1),
635                 _SU32(p, RHINE_TDES2), _SU32(p, RHINE_TDES3));
636 #endif
637     cpd->tx_ring_free = cpd->tx_ring_alloc = cpd->tx_ring_owned = 0;
638     HAL_PCI_CPU_TO_BUS((cyg_uint32)cpd->tx_ring, ba);
639     HAL_PCI_IO_WRITE_UINT32(cpd->base + RHINE_CUR_TX, ba);
640
641     cpd->txbusy = 0;
642
643 #if DEBUG & 9
644     {
645         cyg_uint8 tmp1, tmp2;
646         HAL_PCI_IO_READ_UINT8(cpd->base+RHINE_CR0, tmp1); 
647         HAL_PCI_IO_READ_UINT8(cpd->base+RHINE_CR1, tmp2);
648         diag_printf("CR0: %02x  CR1: %02x\n", tmp1, tmp2);
649     }
650 #endif
651
652     // and record the net dev pointer
653     cpd->ndp = (void *)tab;
654
655     // Initialize upper level driver
656     (sc->funs->eth_drv->init)(sc, cpd->esa);
657
658 #if DEBUG & 9
659     diag_printf("Done\n");
660 #endif
661     return true;
662 }
663
664 static void
665 rhine_stop(struct eth_drv_sc *sc)
666 {
667     struct rhine_priv_data *cpd =
668         (struct rhine_priv_data *)sc->driver_private;
669
670     DEBUG_FUNCTION();
671
672     // Stop chip
673     HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_CR0, RHINE_CR0_STOP);
674 }
675
676 //
677 // This function is called to "start up" the interface.  It may be called
678 // multiple times, even when the hardware is already running.  It will be
679 // called whenever something "hardware oriented" changes and should leave
680 // the hardware ready to send/receive packets.
681 //
682 static void
683 rhine_start(struct eth_drv_sc *sc, unsigned char *esa, int flags)
684 {
685 #ifdef CYGPKG_NET
686     struct ifnet *ifp = &sc->sc_arpcom.ac_if;
687 #endif
688     struct rhine_priv_data *cpd =
689         (struct rhine_priv_data *)sc->driver_private;
690
691     DEBUG_FUNCTION();
692     // Disable device
693     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_CR0, RHINE_CR0_STOP);
694     // Ack old interrupts
695     HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_ISR, 0xffff);
696     // Enable interrupts
697     HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_IMR, RHINE_IMR_INIT);
698     // Enable duplex
699     HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_CR1, RHINE_CR1_DPOLL /* | RHINE_CR1_FDX*/);
700     // Accept broadcast, multicast and small packets
701     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_RCR, RHINE_RCR_AB | RHINE_RCR_AM | RHINE_RCR_AR);
702     // Tweak some magic (undocumented) parameters
703     HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_BCR0, RHINE_BCR0_MAGIC_INIT);
704     HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_BCR1, RHINE_BCR1_MAGIC_INIT);
705
706 #if 1 // FIXME
707     HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_TCR, 0x20);
708 #endif
709
710 #ifdef CYGPKG_NET
711     if (( 0
712 #ifdef ETH_DRV_FLAGS_PROMISC_MODE
713          != (flags & ETH_DRV_FLAGS_PROMISC_MODE)
714 #endif
715         ) || (ifp->if_flags & IFF_PROMISC)
716         ) {
717         // Then we select promiscuous mode.
718         cyg_uint8 rcr;
719         HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_RCR, rcr);
720         rcr |= RHINE_RCR_PRO;
721         HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_RCR, rcr);
722     }
723 #endif
724     // Enable device
725     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_CR0, RHINE_CR0_STRT | RHINE_CR0_RXON | RHINE_CR0_TXON);
726 }
727
728 //
729 // This routine is called to perform special "control" opertions
730 //
731 static int
732 rhine_control(struct eth_drv_sc *sc, unsigned long key,
733                void *data, int data_length)
734 {
735     cyg_uint8 *esa = (cyg_uint8 *)data;
736     int i, res;
737     cyg_uint8 reg, old_stat;
738     struct rhine_priv_data *cpd =
739         (struct rhine_priv_data *)sc->driver_private;
740
741     DEBUG_FUNCTION();
742
743     // Stop the controller while accessing (possibly altering) registers
744     HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_CR0, old_stat);
745     reg = old_stat;
746     reg |= RHINE_CR0_STOP;
747     reg &= ~RHINE_CR0_STRT;
748     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_CR0, reg);
749
750     res = 0;                            // expect success
751     switch (key) {
752     case ETH_DRV_SET_MAC_ADDRESS:
753 #if DEBUG & 9
754         diag_printf("RHINE - set ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
755                 esa[0],
756                 esa[1],
757                 esa[2],
758                 esa[3],
759                 esa[4],
760                 esa[5] );
761 #endif // DEBUG
762
763         for ( i = 0; i < sizeof(cpd->esa);  i++ ) {
764             cpd->esa[i] = esa[i];
765             HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_PAR0 + i, esa[i]);
766         }
767         break;
768
769 #ifdef ETH_DRV_GET_MAC_ADDRESS
770     case ETH_DRV_GET_MAC_ADDRESS:
771         // Extract the MAC address that is in the chip, and tell the
772         // system about it.
773         for (i = 0;  i < sizeof(cpd->esa);  i++) {
774             HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_PAR0 + i, esa[i]);
775         }
776         break;
777 #endif
778
779 #ifdef ETH_DRV_GET_IF_STATS_UD
780     case ETH_DRV_GET_IF_STATS_UD: // UD == UPDATE
781 #endif
782         // drop through
783 #ifdef ETH_DRV_GET_IF_STATS
784     case ETH_DRV_GET_IF_STATS:
785 #endif
786
787 #if defined(ETH_DRV_GET_IF_STATS) || defined (ETH_DRV_GET_IF_STATS_UD)
788     {
789         cyg_uint8 reg;
790         struct ether_drv_stats *p = (struct ether_drv_stats *)data;
791         // Chipset entry is no longer supported; RFC1573.
792         for ( i = 0; i < SNMP_CHIPSET_LEN; i++ )
793             p->snmp_chipset[i] = 0;
794
795         // This perhaps should be a config opt, so you can make up your own
796         // description, or supply it from the instantiation.
797         strcpy( p->description, "VIA Rhine" );
798         // CYG_ASSERT( 48 > strlen(p->description), "Description too long" );
799
800         HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_MIISR, reg);
801         if (reg & RHINE_MIISR_LNKFL) {
802             p->operational = 2;         // LINK DOWN
803             p->duplex = 1;              // UNKNOWN
804             p->speed = 0;
805         }
806         else {
807             p->operational = 3;         // LINK UP
808             p->speed = (reg & RHINE_MIISR_SPEED) ? 10 * 1000000 : 100 * 1000000;
809             HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_CR1, reg);
810             if (reg & RHINE_CR1_FDX)
811                 p->duplex = 3;              // 3 = DUPLEX
812             else
813                 p->duplex = 2;              // 2 = SIMPLEX
814         }
815
816 #ifdef KEEP_STATISTICS
817         {
818             struct via_rhine_stats *ps = &(cpd->stats);
819
820             // Admit to it...
821             p->supports_dot3        = true;
822
823             p->tx_good              = ps->tx_good             ;
824             p->tx_max_collisions    = ps->tx_max_collisions   ;
825             p->tx_late_collisions   = ps->tx_late_collisions  ;
826             p->tx_underrun          = ps->tx_underrun         ;
827             p->tx_carrier_loss      = ps->tx_carrier_loss     ;
828             p->tx_deferred          = ps->tx_deferred         ;
829             p->tx_sqetesterrors     = ps->tx_sqetesterrors    ;
830             p->tx_single_collisions = ps->tx_single_collisions;
831             p->tx_mult_collisions   = ps->tx_mult_collisions  ;
832             p->tx_total_collisions  = ps->tx_total_collisions ;
833             p->rx_good              = ps->rx_good             ;
834             p->rx_crc_errors        = ps->rx_crc_errors       ;
835             p->rx_align_errors      = ps->rx_align_errors     ;
836             p->rx_resource_errors   = ps->rx_resource_errors  ;
837             p->rx_overrun_errors    = ps->rx_overrun_errors   ;
838             p->rx_collisions        = ps->rx_collisions       ;
839             p->rx_short_frames      = ps->rx_short_frames     ;
840             p->rx_too_long_frames   = ps->rx_too_long_frames  ;
841             p->rx_symbol_errors     = ps->rx_symbol_errors    ;
842         
843             p->interrupts           = ps->interrupts          ;
844             p->rx_count             = ps->rx_count            ;
845             p->rx_deliver           = ps->rx_deliver          ;
846             p->rx_resource          = ps->rx_resource         ;
847             p->rx_restart           = ps->rx_restart          ;
848             p->tx_count             = ps->tx_count            ;
849             p->tx_complete          = ps->tx_complete         ;
850             p->tx_dropped           = ps->tx_dropped          ;
851         }
852 #endif // KEEP_STATISTICS
853
854         p->tx_queue_len = 1;
855         break;
856     }
857 #endif
858     default:
859         res = 1;
860         break;
861     }
862
863     // Restore controller state
864     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_CR0, old_stat);
865
866     return res;
867 }
868
869 //
870 // This routine is called to see if it is possible to send another packet.
871 // It will return non-zero if a transmit is possible, zero otherwise.
872 //
873 static int
874 rhine_can_send(struct eth_drv_sc *sc)
875 {
876     cyg_uint8 stat;
877     struct rhine_priv_data *cpd =
878         (struct rhine_priv_data *)sc->driver_private;
879
880     DEBUG_FUNCTION();
881
882     // This MII read forces the MIISR to get updated
883     (void) rhine_read_MII(cpd, cpd->phys_id, MII_BMSR);
884     HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_MIISR, stat);
885     if (stat & RHINE_MIISR_LNKFL) {
886 #if DEBUG & 1
887         diag_printf("*** Link failure\n");
888 #endif
889         return false;  // Link not connected
890     }
891
892     return (cpd->txbusy == 0);
893 }
894
895 //
896 // This routine is called to send data to the hardware.
897 static void 
898 rhine_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, 
899             int total_len, unsigned long key)
900 {
901     struct rhine_priv_data *cpd = 
902         (struct rhine_priv_data *)sc->driver_private;
903     int i, len, plen, ring_entry;
904
905     cyg_uint8* sdata = NULL;
906     cyg_uint8 *d, *buf, *txd;
907     cyg_uint16 status;
908     cyg_uint8 cr0;
909
910     DEBUG_FUNCTION();
911
912     INCR_STAT( tx_count );
913
914     // Worry about the engine stopping.
915     HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_CR0, status);
916     if ( 0 == (RHINE_CR0_STRT & status) ) {
917 #if DEBUG & 1
918         diag_printf("%s: ENGINE RESTART: status %04x\n", __FUNCTION__, status);
919 #endif
920         status &= ~RHINE_CR0_STOP;
921         status |= RHINE_CR0_STRT;
922         HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_CR0, status);
923     }
924
925     cpd->txbusy = 1;
926     cpd->txkey = key;
927
928     // Find packet length
929     plen = 0;
930     for (i = 0;  i < sg_len;  i++)
931         plen += sg_list[i].len;
932
933     CYG_ASSERT( plen == total_len, "sg data length mismatch" );
934     
935     // Get next TX descriptor
936     ring_entry = cpd->tx_ring_free;
937     do {
938         if (cpd->tx_ring_owned == cpd->tx_ring_cnt) {
939             // Is this a dead end? Probably is.
940 #if DEBUG & 1
941             diag_printf("%s: Allocation failed! Retrying...\n", __FUNCTION__ );
942 #endif
943             continue;
944         }
945
946         cpd->tx_ring_free++;
947         cpd->tx_ring_owned++;
948         if (cpd->tx_ring_free == cpd->tx_ring_cnt)
949             cpd->tx_ring_free = 0;
950     } while (0);
951
952     txd = cpd->tx_ring + ring_entry*RHINE_TD_SIZE;
953     buf = cpd->tx_buffers + ring_entry*_BUF_SIZE;
954     CYG_ASSERT(0 == (_SU32(txd, RHINE_TDES0) & RHINE_TDES0_OWN),
955                "TX descriptor not free");
956
957 #if DEBUG & 4
958     diag_printf("##Tx descriptor index %d TDES %08x buffer %08x\n", 
959                 ring_entry, txd, buf);
960 #endif
961
962     // Put data into buffer
963     d = buf;
964     for (i = 0;  i < sg_len;  i++) {
965         sdata = (cyg_uint8 *)sg_list[i].buf;
966         len = sg_list[i].len;
967
968         CYG_ASSERT( sdata, "No sg data pointer here" );
969         while(len--)
970             *d++ = *sdata++;
971     }
972     CYG_ASSERT( sdata, "No sg data pointer outside" );
973     
974     // Annoyingly the chip doesn't pad to minimal packet size, so do
975     // that by steam
976     if (plen < 60) {
977         plen = 60;
978 #if DEBUG & 4
979         diag_printf("Padded %d bytes packet to 60 bytes\n", plen);
980 #endif
981     }        
982
983     CYG_ASSERT( (plen & RHINE_TDES1_TLNG_mask) == plen, "packet too long");
984     CYG_ASSERT( (plen & RHINE_TDES1_TLNG_mask) >= 60, "packet too short");
985     _SU32(txd, RHINE_TDES1) &= ~RHINE_TDES1_TLNG_mask;
986     _SU32(txd, RHINE_TDES1) |= plen;
987     _SU32(txd, RHINE_TDES0) = RHINE_TDES0_OWN;
988
989 #if DEBUG & 1 // FIXME
990     diag_printf("Before TX: Desc (@0x%08lx) %08x %08x %08x %08x\n Next (@0x%08lx) %08x %08x %08x %08x\n",
991                 (unsigned long) txd,
992                 _SU32(txd, RHINE_TDES0), _SU32(txd, RHINE_TDES1),
993                 _SU32(txd, RHINE_TDES2), _SU32(txd, RHINE_TDES3),
994                 (  (unsigned long)txd)+0x10,
995                 _SU32(txd, (0x10+RHINE_TDES0)), _SU32(txd, (0x10+RHINE_TDES1)),
996                 _SU32(txd,(0x10+ RHINE_TDES2)), _SU32(txd,(0x10+ RHINE_TDES3)));
997 #endif
998
999     // Ack TX empty int
1000     HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_ISR, RHINE_ISR_PTX);
1001     // Set transmit demand
1002     HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_CR0, cr0);
1003     cr0 |= RHINE_CR0_TDMD;
1004     HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_CR0, cr0);
1005
1006 #if DEBUG & 1
1007     HAL_PCI_IO_READ_UINT16(cpd->base + RHINE_ISR, status);
1008     diag_printf("%s:END: ints at TX: %04x\n", __FUNCTION__, status);
1009 #endif
1010
1011 }
1012
1013 static void
1014 rhine_TxEvent(struct eth_drv_sc *sc, int stat)
1015 {
1016      struct rhine_priv_data *cpd =
1017         (struct rhine_priv_data *)sc->driver_private;
1018     int success = 1;
1019     cyg_uint8 *txd;
1020     cyg_uint8 status;
1021
1022     DEBUG_FUNCTION();
1023
1024     INCR_STAT( tx_complete );
1025
1026     txd = cpd->tx_ring + cpd->tx_ring_alloc*RHINE_TD_SIZE;
1027 #if DEBUG & 4
1028     diag_printf("##Tx packet %d freed %08x %08x!\n", cpd->tx_ring_alloc, txd, _SU32(txd, RHINE_TDES0) );
1029 #endif
1030     if ((_SU32(txd, RHINE_TDES0) & RHINE_TDES0_OWN)) {
1031 #if DEBUG & 1
1032         diag_printf("%s: got TX completion when buffer is still owned\n", __FUNCTION__);
1033 #endif
1034         // first dirty ring entry not freed - wtf?
1035     }
1036     cpd->tx_ring_alloc++;
1037     if (cpd->tx_ring_alloc == cpd->tx_ring_cnt)
1038         cpd->tx_ring_alloc = 0;
1039     cpd->tx_ring_owned--;
1040
1041 #ifdef KEEP_STATISTICS
1042     {
1043         cyg_uint32 reg = _SU32(txd, RHINE_TDES0);
1044         int collisions;
1045
1046         // Covering each bit in turn...
1047         if ( reg & RHINE_TDES0_TXOK ) INCR_STAT( tx_good );
1048         if ( reg & RHINE_TDES0_CRS ) INCR_STAT( tx_carrier_loss );
1049         if ( reg & RHINE_TDES0_OWC ) INCR_STAT( tx_late_collisions );
1050         if ( reg & RHINE_TDES0_ABT ) INCR_STAT( tx_max_collisions );
1051
1052         if ( reg & RHINE_TDES0_DFR ) INCR_STAT( tx_deferred );
1053
1054         collisions = ((reg & RHINE_TDES0_NCR_mask) >> RHINE_TDES0_NCR_shift);
1055         if (1 == collisions)
1056             INCR_STAT( tx_single_collisions );
1057         else if (1 < collisions)
1058             INCR_STAT( tx_mult_collisions );
1059
1060         cpd->stats.tx_total_collisions = 
1061             cpd->stats.tx_late_collisions + 
1062             cpd->stats.tx_max_collisions + 
1063             cpd->stats.tx_mult_collisions + 
1064             cpd->stats.tx_single_collisions;
1065     }
1066 #endif // KEEP_STATISTICS
1067
1068     // We do not really care about Tx failure.  Ethernet is not a reliable
1069     // medium.  But we do care about the TX engine stopping.
1070     HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_CR0, status);
1071     if ( 0 == (RHINE_CR0_STRT & status) ) {
1072 #if DEBUG & 1
1073         diag_printf("%s: ENGINE RESTART: status %04x\n", __FUNCTION__, status);
1074 #endif
1075         status &= ~RHINE_CR0_STOP;
1076         status |= RHINE_CR0_STRT;
1077         HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_CR0, status);
1078         success = 0; // And treat this as an error...
1079     }
1080
1081     if ( cpd->txbusy ) {
1082         cpd->txbusy = 0;
1083         (sc->funs->eth_drv->tx_done)(sc, cpd->txkey, success);
1084     }
1085
1086     // Ack TX interrupt set
1087     HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_ISR, RHINE_ISR_PTX);
1088 }
1089
1090 //
1091 // This function is called when a packet has been received.  Its job is
1092 // to prepare to unload the packet from the hardware.  Once the length of
1093 // the packet is known, the upper layer of the driver can be told.  When
1094 // the upper layer is ready to unload the packet, the internal function
1095 // 'rhine_recv' will be called to actually fetch it from the hardware.
1096 //
1097 static void
1098 rhine_RxEvent(struct eth_drv_sc *sc)
1099 {
1100     struct rhine_priv_data *cpd = 
1101         (struct rhine_priv_data *)sc->driver_private;
1102     cyg_uint8 *rxd;
1103     cyg_uint32 rstat;
1104     cyg_uint16 ints, len, mask;
1105
1106     DEBUG_FUNCTION();
1107
1108     HAL_PCI_IO_READ_UINT16(cpd->base + RHINE_ISR, ints);
1109 #if DEBUG & 1
1110     diag_printf("RxEvent - CSR: 0x%04x\n", ints);
1111 #endif
1112     if ( 0 == (RHINE_ISR_PRX & ints) )
1113         // Then there's no RX event pending
1114         return;
1115
1116     // Mask interrupt
1117     HAL_PCI_IO_READ_UINT16(cpd->base + RHINE_IMR, mask);
1118     mask &= ~RHINE_IMR_PRX;
1119     HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_IMR, mask);
1120
1121     while (1) {
1122         // Get state of next (supposedly) full ring entry
1123         cpd->rxpacket = cpd->rx_ring_next;
1124         rxd = cpd->rx_ring + cpd->rxpacket*RHINE_RD_SIZE;
1125         rstat = _SU32(rxd, RHINE_RDES0);
1126
1127         // Keep going until we hit an entry that is owned by the
1128         // controller.
1129         if (rstat & RHINE_RDES0_OWN) {
1130 #ifdef CYGDBG_USE_ASSERTS
1131             // Sanity check of queue
1132             int i;
1133             for (i = 0; i < cpd->rx_ring_cnt; i++) {
1134                 rxd = cpd->rx_ring + i*RHINE_RD_SIZE;
1135                 rstat = _SU32(rxd, RHINE_RDES0);
1136
1137                 if (!(rstat & RHINE_RDES0_OWN)) {
1138                     int i;
1139                     cyg_uint32 rstat;
1140                     cyg_uint8* rxd;
1141
1142                     diag_printf("####Rx %s Inconsistent RX state - next was %d\n", 
1143                                 __FUNCTION__, cpd->rx_ring_next);
1144                     for (i = 0; i < cpd->rx_ring_cnt; i++) {
1145                         rxd = cpd->rx_ring + i*RHINE_RD_SIZE;
1146                         rstat = _SU32(rxd, RHINE_RDES0);
1147                         diag_printf("#### %02d: 0x%08x\n", i, rstat);
1148                     }
1149                 }
1150                 break;
1151             }
1152 #endif
1153             break;
1154         }
1155
1156 #if DEBUG & 4
1157         diag_printf("##Rx packet %d RDES %08x stat %08x\n", 
1158                     cpd->rxpacket, rxd, rstat);
1159 #endif
1160
1161         // Increment counts
1162         INCR_STAT( rx_count );
1163         cpd->rx_ring_next++;
1164         if (cpd->rx_ring_next == cpd->rx_ring_cnt) cpd->rx_ring_next = 0;
1165
1166         len = (rstat & RHINE_RDES0_FLNG_mask) >> RHINE_RDES0_FLNG_shift;
1167
1168 #ifdef KEEP_STATISTICS
1169         if ( rstat & RHINE_RDES0_CRC ) INCR_STAT( rx_crc_errors );
1170         if ( rstat & RHINE_RDES0_FAE ) INCR_STAT( rx_align_errors );
1171         if ( rstat & RHINE_RDES0_LONG ) INCR_STAT( rx_too_long_frames );
1172 #endif // KEEP_STATISTICS
1173
1174         if (RHINE_RDES0_RXOK & rstat) {
1175             // It's OK
1176             INCR_STAT( rx_good );
1177
1178 #if DEBUG & 1
1179             diag_printf("RxEvent good rx - stat: 0x%08x, len: 0x%04x\n", rstat, len);
1180             {
1181                     unsigned char *buf = cpd->rx_buffers + cpd->rxpacket*_BUF_SIZE;
1182
1183                     int i;
1184                     diag_printf("RDES: %08x %08x %08x %08x\n", 
1185                                 _SU32(rxd, RHINE_RDES0), _SU32(rxd, RHINE_RDES1),
1186                                 _SU32(rxd, RHINE_RDES2), _SU32(rxd, RHINE_RDES3));
1187
1188                     diag_printf("Packet data at %p\n", buf);
1189                     for (i=0;i<len;i++) diag_printf("%02x ", buf[i]);
1190                     diag_printf("\n");
1191             }
1192 #endif
1193             // Check for bogusly short packets; can happen in promisc
1194             // mode: Asserted against and checked by upper layer
1195             // driver.
1196 #ifdef CYGPKG_NET
1197             if ( len > sizeof( struct ether_header ) )
1198                 // then it is acceptable; offer the data to the network stack
1199 #endif
1200                 (sc->funs->eth_drv->recv)(sc, len);
1201         } else {
1202             // Not OK for one reason or another...
1203 #if DEBUG & 1
1204             diag_printf("RxEvent - No RX bit: stat: 0x%08x, len: 0x%04x\n",
1205                         rstat, len);
1206 #endif
1207         }
1208
1209         // Free packet (clear all status flags, and set OWN)
1210         _SU32(rxd, RHINE_RDES0) = RHINE_RDES0_OWN;
1211     }
1212
1213     // Ack RX int
1214     HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_ISR, RHINE_ISR_PRX);
1215     // And reenable the interrupt
1216     HAL_PCI_IO_READ_UINT16(cpd->base + RHINE_IMR, mask);
1217     mask |= RHINE_IMR_PRX;
1218     HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_IMR, mask);
1219 }
1220
1221 //
1222 // This function is called as a result of the "eth_drv_recv()" call above.
1223 // Its job is to actually fetch data for a packet from the hardware once
1224 // memory buffers have been allocated for the packet.  Note that the buffers
1225 // may come in pieces, using a scatter-gather list.  This allows for more
1226 // efficient processing in the upper layers of the stack.
1227 //
1228 static void
1229 rhine_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
1230 {
1231     struct rhine_priv_data *cpd = 
1232         (struct rhine_priv_data *)sc->driver_private;
1233     int i, mlen=0, plen;
1234     cyg_uint8 *data, *rxd, *buf;
1235
1236     DEBUG_FUNCTION();
1237
1238     rxd = cpd->rx_ring + cpd->rxpacket*RHINE_RD_SIZE;
1239     buf = cpd->rx_buffers + cpd->rxpacket*_BUF_SIZE;
1240
1241     INCR_STAT( rx_deliver );
1242
1243     plen = (_SU32(rxd, RHINE_RDES0) & RHINE_RDES0_FLNG_mask) >> RHINE_RDES0_FLNG_shift;
1244
1245     for (i = 0;  i < sg_len;  i++) {
1246         data = (cyg_uint8*)sg_list[i].buf;
1247         mlen = sg_list[i].len;
1248
1249 #if DEBUG & 1
1250         diag_printf("%s : mlen %x, plen %x\n", __FUNCTION__, mlen, plen);
1251 #endif
1252         if (data) {
1253             while (mlen > 0) {
1254                 *data++ = *buf++;
1255                 mlen--;
1256                 plen--;
1257             }
1258         }
1259     }
1260 }
1261
1262 static void
1263 rhine_poll(struct eth_drv_sc *sc)
1264 {
1265     struct rhine_priv_data *cpd = 
1266         (struct rhine_priv_data *)sc->driver_private;
1267     cyg_uint16 event, mask;
1268     static volatile bool locked = false;
1269
1270 //    DEBUG_FUNCTION();
1271
1272     while (1) {
1273         // Get the (unmasked) requests
1274         HAL_PCI_IO_READ_UINT16(cpd->base + RHINE_ISR, event);
1275         HAL_PCI_IO_READ_UINT16(cpd->base + RHINE_IMR, mask);
1276
1277         event &= mask;
1278
1279         if (0 == event)
1280             break;
1281
1282         if (event & RHINE_ISR_PRX) {
1283             rhine_RxEvent(sc);
1284         }
1285         else if (event & RHINE_ISR_PTX) {
1286             rhine_TxEvent(sc, event);
1287         } 
1288         else if (event & RHINE_ISR_RU) {
1289 #if DEBUG & 1
1290             int i;
1291             cyg_uint32 rstat;
1292             cyg_uint8* rxd;
1293             struct rhine_priv_data *cpd = 
1294                 (struct rhine_priv_data *)sc->driver_private;
1295
1296             diag_printf("%s: Ran out of RX buffers (%04x)\n", __FUNCTION__, event);
1297             for (i = 0; i < cpd->rx_ring_cnt; i++) {
1298                 rxd = cpd->rx_ring + i*RHINE_RD_SIZE;
1299                 
1300                 rstat = _SU32(rxd, RHINE_RDES0);
1301                 diag_printf(" %02d: 0x%08x\n", i, rstat);
1302             }
1303 #endif
1304             HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_ISR, RHINE_ISR_RU);
1305         }
1306         else {
1307 #if DEBUG & 1
1308             diag_printf("%s: Unknown interrupt: 0x%04x\n", __FUNCTION__, event);
1309 #endif
1310             // Clear unhandled interrupts and hope for the best
1311             // This should never happen though, since we only enable
1312             // the sources we handle.
1313             HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_ISR, event);
1314         }
1315     }
1316
1317     locked = false;
1318 }
1319 // EOF if_rhine.c