]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/eth/amd/lancepci/v2_0/src/if_lancepci.c
Initial revision
[karo-tx-redboot.git] / packages / devs / eth / amd / lancepci / v2_0 / src / if_lancepci.c
1 //==========================================================================
2 //
3 //      dev/if_lancepci.c
4 //
5 //      Ethernet device driver for AMD PCI Lance (for instance vmWare VLANCE)
6 //      compatible controllers
7 //
8 //==========================================================================
9 //####ECOSGPLCOPYRIGHTBEGIN####
10 // -------------------------------------------
11 // This file is part of eCos, the Embedded Configurable Operating System.
12 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
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 Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
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):    jskov, based on lan91cxx driver by hmt & jskov, iz
55 // Contributors: gthomas, jskov, hmt, iz
56 // Date:         2002-07-17, 2003-01-26
57 // Purpose:
58 // Description:  hardware driver for AMD Lance PCI (and possibly PCnet)
59 //               and wmWare VLANCE ethernet
60 // Notes:        The controller is used in its 16bit mode. That means that
61 //               all addresses are 24bit only - and that all controller
62 //               accessed memory must be within the same 16MB region
63 //               (starting at 0 on older controllers).
64 //
65 //               The KEEP_STATISTICS code is not implemented yet. Look
66 //               for FIXME macro.
67 //
68 //####DESCRIPTIONEND####
69 //
70 //==========================================================================
71 //#####VMWAREDESCRIPTIONBEGIN####
72 //
73 // Notes:        The vmWare VLACNCE virtual controller does not seem to do
74 //               anything about SUSPEND  and seems it must be reinitialized after
75 //               every STOP. In addition it lacks some registers.
76 //
77 //               Sometimes, the driver must wait to let Vmware get a tick, to
78 //               process the chip initialization and control functions!!!
79 //
80 //               That's the reason for not patching the PCnet driver
81 //               but cloning a special one from it.
82 //
83 //
84 //####VMWAREDESCRIPTIONEND####
85 //==========================================================================
86
87 #include <pkgconf/system.h>
88 #include <pkgconf/devs_eth_amd_lancepci.h>
89 #include <pkgconf/io_eth_drivers.h>
90
91 #include <cyg/infra/cyg_type.h>
92 #include <cyg/hal/hal_arch.h>
93 #include <cyg/hal/hal_intr.h>
94 #include <cyg/infra/cyg_ass.h>
95 #include <cyg/infra/diag.h>
96 #include <cyg/hal/drv_api.h>
97 #include <cyg/hal/hal_if.h>             // delays
98 #include <string.h>
99 #include <cyg/io/eth/netdev.h>
100 #include <cyg/io/eth/eth_drv.h>
101 #ifdef CYGPKG_NET
102 #include <pkgconf/net.h>
103 #include <cyg/kernel/kapi.h>
104 #include <net/if.h>                     // Needed for struct ifnet
105 #include <pkgconf/io_eth_drivers.h>
106 #endif
107 #include CYGHWR_MEMORY_LAYOUT_H
108
109 #ifdef CYGPKG_IO_PCI
110 #include <cyg/io/pci.h>
111 #else
112 #error "Need PCI package here"
113 #endif
114
115 #define FIXME 0
116
117 #define _BUF_SIZE 1544
118
119 #ifdef CYGPKG_INFRA_DEBUG
120 // Then we log, OOI, the number of times we get a bad packet number
121 // from the tx done fifo.
122 int lancepci_txfifo_good = 0;
123 int lancepci_txfifo_bad = 0;
124 #endif
125
126 #include "amd_lance.h"
127 #define __WANT_DEVS
128 #include CYGDAT_DEVS_ETH_AMD_LANCEPCI_INL
129 #undef  __WANT_DEVS
130
131 //#define DEBUG 0xff
132
133 #if defined(CYGPKG_REDBOOT)
134
135 static void db_printf( char *fmt, ... )
136 {
137     extern int start_console(void);
138     extern void end_console(int);
139     va_list a;
140     int old_console;
141     va_start( a, fmt );
142     old_console = start_console();
143     diag_vprintf( fmt, a );
144     end_console(old_console);
145     va_end( a );
146 }
147
148 #else
149
150 #define db_printf diag_printf
151
152 #endif
153
154
155 static struct eth_drv_sc *oursc;        //a dummy sc pointer
156
157 static void lancepci_poll(struct eth_drv_sc *sc);
158
159
160 // This ISR is called when the ethernet interrupt occurs
161 static cyg_uint32
162 lancepci_isr(cyg_vector_t vector, cyg_addrword_t data)
163 {
164     struct lancepci_priv_data *cpd = (struct lancepci_priv_data *)data;
165
166     DEBUG_FUNCTION();
167
168     INCR_STAT( interrupts );
169     cpd->event = get_reg(oursc, LANCE_CSR_CSCR);
170     if (cpd->event & LANCE_CSR_CSCR_TINT)
171         cpd->txbusyh=0;                         // take care of HW txbusy flag
172     cyg_drv_interrupt_mask(cpd->interrupt);
173     cyg_drv_interrupt_acknowledge(cpd->interrupt);
174     return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
175 }
176
177 static void
178 lancepci_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
179 {
180     // This conditioning out is necessary because of explicit calls to this
181     // DSR - which would not ever be called in the case of a polled mode
182     // usage ie. in RedBoot.
183 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
184     struct lancepci_priv_data* cpd = (struct lancepci_priv_data *)data;
185     struct cyg_netdevtab_entry *ndp = (struct cyg_netdevtab_entry *)(cpd->ndp);
186     struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance);
187
188     // but here, it must be a *sc:
189     eth_drv_dsr( vector, count, (cyg_addrword_t)sc );
190 #else
191 # ifndef CYGPKG_REDBOOT
192 #  error Empty lancepci ethernet DSR is compiled.  Is this what you want?
193 # endif
194 #endif
195 }
196
197
198 // The deliver function (ex-DSR)  handles the ethernet [logical] processing
199 static void
200 lancepci_deliver(struct eth_drv_sc *sc)
201 {
202     struct lancepci_priv_data *cpd =
203         (struct lancepci_priv_data *)sc->driver_private;
204
205     DEBUG_FUNCTION();
206
207     // Service the interrupt:
208     lancepci_poll(sc);
209     // Allow interrupts to happen again
210     cyg_drv_interrupt_unmask(cpd->interrupt);
211 }
212
213 static int
214 lancepci_int_vector(struct eth_drv_sc *sc)
215 {
216     struct lancepci_priv_data *cpd =
217         (struct lancepci_priv_data *)sc->driver_private;
218
219     return (cpd->interrupt);
220 }
221
222 // ------------------------------------------------------------------------
223 // Memory management
224 //
225 // Simply carve off from the front of the PCI mapped window into real memory
226 static cyg_uint32 lancepci_heap_size;
227 static cyg_uint8 *lancepci_heap_base;
228 static cyg_uint8 *lancepci_heap_free;
229
230 static void*
231 pciwindow_mem_alloc(int size)
232 {
233     void *p_memory;
234     int _size = size;
235
236     CYG_ASSERT(
237         (CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_BASE <= (int)lancepci_heap_free)
238         &&
239         ((CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_BASE +
240           CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_SIZE) > (int)lancepci_heap_free)
241         &&
242         (0 < lancepci_heap_size)
243         &&
244         (CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_SIZE >= lancepci_heap_size)
245         &&
246         (CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_BASE == (int)lancepci_heap_base),
247         "Heap variables corrupted" );
248
249     p_memory = (void *)0;
250     size = (size + 3) & ~3;
251     if ( (lancepci_heap_free+size) < (lancepci_heap_base+lancepci_heap_size) ) {
252         cyg_uint32 *p;
253         p_memory = (void *)lancepci_heap_free;
254         lancepci_heap_free += size;
255         for ( p = (cyg_uint32 *)p_memory; _size > 0; _size -= 4 )
256             *p++ = 0;
257     }
258
259 #if DEBUG & 9
260     db_printf("Allocated %d bytes at 0x%08x\n", size, p_memory);
261 #endif
262
263     return p_memory;
264 }
265
266 static cyg_pci_match_func find_lancepci_match_func;
267
268 static cyg_bool
269 find_lancepci_match_func( cyg_uint16 v, cyg_uint16 d, cyg_uint32 c, void *p )
270 {
271 #if DEBUG & 9
272     db_printf("PCI match vendor 0x%04x device 0x%04x\n", v, d);
273 #endif
274     return (0x1022 == v) && (0x2000 == d);
275 }
276
277 static int
278 pci_init_find_lancepci( void )
279 {
280     cyg_pci_device_id devid;
281     cyg_pci_device dev_info;
282     cyg_uint16 cmd;
283     int device_index;
284     int found_devices = 0;
285
286     DEBUG_FUNCTION();
287
288 #ifdef CYGARC_UNCACHED_ADDRESS
289     CYG_ASSERT( CYGARC_UNCACHED_ADDRESS((CYG_ADDRWORD)CYGMEM_SECTION_pci_window) ==
290                 CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_BASE,
291       "PCI window configured does not match PCI memory section base" );
292 #else
293     CYG_ASSERT( (CYG_ADDRWORD)CYGMEM_SECTION_pci_window ==
294                 CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_BASE,
295       "PCI window configured does not match PCI memory section base" );
296 #endif
297     CYG_ASSERT( CYGMEM_SECTION_pci_window_SIZE ==
298                 CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_SIZE,
299         "PCI window configured does not match PCI memory section size" );
300
301     if (
302 #ifdef CYGARC_UNCACHED_ADDRESS
303          CYGARC_UNCACHED_ADDRESS((CYG_ADDRWORD)CYGMEM_SECTION_pci_window) !=
304 #else
305          (CYG_ADDRWORD)CYGMEM_SECTION_pci_window !=
306 #endif
307          (CYG_ADDRWORD)CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_BASE
308          ||
309          CYGMEM_SECTION_pci_window_SIZE !=
310          CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_SIZE ) {
311 #if DEBUG & 8
312         db_printf("pci_init_find_lancepci(): PCI window misconfigured\n");
313 #endif
314         return 0;
315     }
316
317     // First initialize the heap in PCI window'd memory
318     lancepci_heap_size = CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_SIZE;
319     lancepci_heap_base = (cyg_uint8 *)CYGHWR_AMD_LANCEPCI_PCI_MEM_MAP_BASE;
320     lancepci_heap_free = lancepci_heap_base;
321 #if DEBUG & 9
322     db_printf("pcimem : 0x%08x size: 0x%08x\n", lancepci_heap_base, lancepci_heap_size);
323 #endif
324
325     cyg_pci_init();
326 #if DEBUG & 8
327     db_printf("Finished cyg_pci_init();\n");
328 #endif
329
330     devid = CYG_PCI_NULL_DEVID;
331
332     for (device_index = 0;
333          device_index < CYGNUM_DEVS_ETH_AMD_LANCEPCI_DEV_COUNT;
334          device_index++) {
335         struct lancepci_priv_data* cpd = lancepci_priv_array[device_index];
336
337         cpd->index = device_index;
338
339         // See above for find_lancepci_match_func - it selects any of several
340         // variants.  This is necessary in case we have multiple mixed-type
341         // devices on one board in arbitrary orders.
342         if (cyg_pci_find_matching( &find_lancepci_match_func, NULL, &devid )) {
343 #if DEBUG & 8
344             db_printf("eth%d = lancepci\n", device_index);
345 #endif
346             cyg_pci_get_device_info(devid, &dev_info);
347
348             cpd->interrupt_handle = 0; // Flag not attached.
349             if (cyg_pci_translate_interrupt(&dev_info, &cpd->interrupt)) {
350 #if DEBUG & 8
351                 db_printf(" Wired to HAL vector %d\n", cpd->interrupt);
352 #endif
353                 cyg_drv_interrupt_create(
354                     cpd->interrupt,
355                     1,                  // Priority - unused
356                     (cyg_addrword_t)cpd,// Data item passed to ISR & DSR
357                     lancepci_isr,          // ISR
358                     lancepci_dsr,          // DSR
359                     &cpd->interrupt_handle, // handle to intr obj
360                     &cpd->interrupt_object ); // space for int obj
361
362                 cyg_drv_interrupt_attach(cpd->interrupt_handle);
363
364                 // Don't unmask the interrupt yet, that could get us into a
365                 // race.
366             }
367             else {
368                 cpd->interrupt = 0;
369 #if DEBUG & 8
370                 db_printf(" Does not generate interrupts.\n");
371 #endif
372             }
373
374             if (cyg_pci_configure_device(&dev_info)) {
375 #if DEBUG & 8
376                 int i;
377                 db_printf("Found device on bus %d, devfn 0x%02x:\n",
378                           CYG_PCI_DEV_GET_BUS(devid),
379                           CYG_PCI_DEV_GET_DEVFN(devid));
380
381                 if (dev_info.command & CYG_PCI_CFG_COMMAND_ACTIVE) {
382                     db_printf(" Note that board is active. Probed"
383                               " sizes and CPU addresses invalid!\n");
384                 }
385                 db_printf(" Vendor    0x%04x", dev_info.vendor);
386                 db_printf("\n Device    0x%04x", dev_info.device);
387                 db_printf("\n Command   0x%04x, Status 0x%04x\n",
388                           dev_info.command, dev_info.status);
389
390                 db_printf(" Class/Rev 0x%08x", dev_info.class_rev);
391                 db_printf("\n Header 0x%02x\n", dev_info.header_type);
392
393                 db_printf(" SubVendor 0x%04x, Sub ID 0x%04x\n",
394                           dev_info.header.normal.sub_vendor,
395                           dev_info.header.normal.sub_id);
396
397                 for(i = 0; i < CYG_PCI_MAX_BAR; i++) {
398                     db_printf(" BAR[%d]    0x%08x /", i, dev_info.base_address[i]);
399                     db_printf(" probed size 0x%08x / CPU addr 0x%08x\n",
400                               dev_info.base_size[i], dev_info.base_map[i]);
401                 }
402                 db_printf(" eth%d configured\n", device_index);
403 #endif
404                 found_devices++;
405                 cpd->found = 1;
406                 cpd->active = 0;
407                 cpd->devid = devid;
408                 cpd->base = (unsigned char*) dev_info.base_map[0];
409 #if DEBUG & 8
410                 db_printf(" I/O address = 0x%08x\n", cpd->base);
411 #endif
412
413                 // Don't use cyg_pci_set_device_info since it clears
414                 // some of the fields we want to print out below.
415                 cyg_pci_read_config_uint16(dev_info.devid,
416                                            CYG_PCI_CFG_COMMAND, &cmd);
417                 cmd |= (CYG_PCI_CFG_COMMAND_IO         // enable I/O space
418                         | CYG_PCI_CFG_COMMAND_MEMORY   // enable memory space
419                         | CYG_PCI_CFG_COMMAND_MASTER); // enable bus master
420                 cyg_pci_write_config_uint16(dev_info.devid,
421                                             CYG_PCI_CFG_COMMAND, cmd);
422
423                 // This is the indicator for "uses an interrupt"
424                 if (cpd->interrupt_handle != 0) {
425                     cyg_drv_interrupt_acknowledge(cpd->interrupt);
426                     cyg_drv_interrupt_unmask(cpd->interrupt);
427 #if DEBUG & 8
428                     db_printf(" Enabled interrupt %d\n", cpd->interrupt);
429 #endif
430                 }
431 #if DEBUG & 8
432                 db_printf(" **** Device enabled for I/O and Memory "
433                             "and Bus Master\n");
434 #endif
435             }
436             else {
437                 cpd->found = 0;
438                 cpd->active = 0;
439 #if DEBUG & 8
440                 db_printf("Failed to configure device %d\n", device_index);
441 #endif
442             }
443         }
444         else {
445             cpd->found = 0;
446             cpd->active = 0;
447 #if DEBUG & 8
448             db_printf("eth%d not found\n", device_index);
449 #endif
450         }
451     }
452
453     if (0 == found_devices)
454         return 0;
455
456     return 1;
457 }
458
459
460 static bool
461 amd_lancepci_init(struct cyg_netdevtab_entry *tab)
462 {
463     static int initialized = 0; // only probe PCI et al *once*
464     struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
465     struct lancepci_priv_data *cpd =
466         (struct lancepci_priv_data *)sc->driver_private;
467     cyg_uint16 val;
468     cyg_uint32 b;
469     cyg_uint8* p;
470     cyg_uint8* d;
471     int i;
472
473     DEBUG_FUNCTION();
474
475     if ( 0 == initialized++ ) {
476         // then this is the first time ever:
477         if ( ! pci_init_find_lancepci() ) {
478 #if DEBUG & 8
479             db_printf( "pci_init_find_lancepci failed" );
480 #endif
481             return false;
482         }
483     }
484
485     // If this device is not present, exit
486     if (0 == cpd->found)
487         return 0;
488
489 #if DEBUG & 8
490     db_printf("lancepci at base 0x%08x, EEPROM key 0x%04x\n",
491                 cpd->base, _SU16(cpd->base, LANCE_IO_ID));
492 #endif
493
494 #if 0
495     // FIXME: Doesn't work with non-conforming EEPROMS
496     if (LANCE_IO_ID_KEY != _SU16(cpd->base, LANCE_IO_ID) ) {
497         db_printf("Lance EPROM key not found\n");
498         return false;
499     }
500 #endif
501
502 #if DEBUG & 9
503     db_printf("pcimem : %08x size: %08x\n", lancepci_heap_base, lancepci_heap_size);
504 #endif
505
506     // Prepare ESA
507     if (!cpd->hardwired_esa) {
508         // Don't use the address from the EEPROM for VMware
509         // Use the address that VMware prepares in CSR_PAR registers
510         // if You want to be able to use NAT networking. (iz@elsis.si Feb 27 04)
511         //
512         // p = cpd->base + LANCE_IO_EEPROM;
513         // for (i = 0; i < 6; i++)
514         // cpd->esa[i] = *p++;
515         put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_STOP);
516         for (i = 0;  i < sizeof(cpd->esa);  i += 2) {
517             cyg_uint16 z = get_reg(sc, LANCE_CSR_PAR0+i/2 );
518             cpd->esa[i] =   (cyg_uint8)(0xff & z);
519             cpd->esa[i+1] = (cyg_uint8)(0xff & (z >> 8));
520       }
521
522     }
523 #if DEBUG & 9
524     db_printf("Lance - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
525                 (cpd->hardwired_esa) ? "static" : "eeprom",
526                 cpd->esa[0], cpd->esa[1], cpd->esa[2],
527                 cpd->esa[3], cpd->esa[4], cpd->esa[5] );
528 #endif
529
530
531     // Prepare RX and TX rings
532     p = cpd->rx_ring = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS((cyg_uint32)pciwindow_mem_alloc((1<<cpd->rx_ring_log_cnt)*LANCE_RD_SIZE));
533     memset(cpd->rx_ring,0,(1<<cpd->rx_ring_log_cnt)*LANCE_RD_SIZE);
534
535     d = cpd->rx_buffers = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS((cyg_uint32)pciwindow_mem_alloc(_BUF_SIZE*cpd->rx_ring_cnt));
536     memset(cpd->rx_buffers,0,_BUF_SIZE*cpd->rx_ring_cnt);
537
538     for (i = 0; i < cpd->rx_ring_cnt; i++) {
539         HAL_PCI_CPU_TO_BUS(d, (cyg_uint8 *)b);
540         _SU32(p, LANCE_RD_PTR) = (b & LANCE_RD_PTR_MASK) | LANCE_RD_PTR_OWN;
541         _SU16(p, LANCE_RD_BLEN) = (-_BUF_SIZE);
542         p += LANCE_RD_SIZE;
543         d += _BUF_SIZE;
544     }
545     cpd->rx_ring_next = 0;
546
547     p = cpd->tx_ring = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS((cyg_uint32)pciwindow_mem_alloc((1<<cpd->tx_ring_log_cnt)*LANCE_TD_SIZE));
548     memset(cpd->tx_ring,0,(1<<cpd->tx_ring_log_cnt)*LANCE_TD_SIZE);
549
550     d = cpd->tx_buffers = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS((cyg_uint32)pciwindow_mem_alloc(_BUF_SIZE*cpd->tx_ring_cnt));
551     for (i = 0; i < cpd->tx_ring_cnt; i++) {
552         HAL_PCI_CPU_TO_BUS(d, (cyg_uint8 *)b);
553         _SU32(p, LANCE_RD_PTR) = b & LANCE_TD_PTR_MASK;
554         p += LANCE_TD_SIZE;
555         d += _BUF_SIZE;
556     }
557     cpd->tx_ring_free = cpd->tx_ring_alloc = cpd->tx_ring_owned = 0;
558
559     // Initialization table
560     cpd->init_table = (cyg_uint8*)CYGARC_UNCACHED_ADDRESS((cyg_uint32)pciwindow_mem_alloc(LANCE_IB_SIZE));
561     _SU16(cpd->init_table, LANCE_IB_MODE) = 0x0000;
562     for (i = 0; i < 6; i++)
563         _SU8(cpd->init_table, LANCE_IB_PADR0+i) = cpd->esa[i];
564     for (i = 0; i < 8; i++)
565         _SU8(cpd->init_table, LANCE_IB_LADRF0+i) = 0;
566
567     HAL_PCI_CPU_TO_BUS(cpd->rx_ring, (cyg_uint8 *)b);
568     _SU32(cpd->init_table, LANCE_IB_RDRA) = ((b & LANCE_IB_RDRA_PTR_mask)
569                                         | (cpd->rx_ring_log_cnt << LANCE_IB_RDRA_CNT_shift));
570     HAL_PCI_CPU_TO_BUS(cpd->tx_ring, (cyg_uint8 *)b);
571     _SU32(cpd->init_table, LANCE_IB_TDRA) = ((b & LANCE_IB_TDRA_PTR_mask)
572                                         | (cpd->tx_ring_log_cnt << LANCE_IB_TDRA_CNT_shift));
573
574 #if DEBUG & 9
575     db_printf("Loading up lance controller from table at 0x%08x\n", cpd->init_table);
576     db_printf(" Mode 0x%04x\n", _SU16(cpd->init_table, LANCE_IB_MODE));
577     db_printf(" PADR %02x:%02x:%02x:%02x:%02x:%02x ",
578                 _SU8(cpd->init_table, LANCE_IB_PADR0+0), _SU8(cpd->init_table, LANCE_IB_PADR0+1),
579                 _SU8(cpd->init_table, LANCE_IB_PADR0+2), _SU8(cpd->init_table, LANCE_IB_PADR0+3),
580                 _SU8(cpd->init_table, LANCE_IB_PADR0+4), _SU8(cpd->init_table, LANCE_IB_PADR0+5));
581     db_printf("LADR %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
582                 _SU8(cpd->init_table, LANCE_IB_LADRF0+0), _SU8(cpd->init_table, LANCE_IB_LADRF0+1),
583                 _SU8(cpd->init_table, LANCE_IB_LADRF0+2), _SU8(cpd->init_table, LANCE_IB_LADRF0+3),
584                 _SU8(cpd->init_table, LANCE_IB_LADRF0+4), _SU8(cpd->init_table, LANCE_IB_LADRF0+5),
585                 _SU8(cpd->init_table, LANCE_IB_LADRF0+5), _SU8(cpd->init_table, LANCE_IB_LADRF0+7));
586     db_printf(" RX 0x%08x (len %d) TX 0x%08x (len %d)\n",
587                 _SU32(cpd->init_table, LANCE_IB_RDRA) & 0x1fffffff,
588                 (_SU32(cpd->init_table, LANCE_IB_RDRA) >> LANCE_IB_RDRA_CNT_shift) & 7,
589                 _SU32(cpd->init_table, LANCE_IB_TDRA) & 0x1fffffff,
590                 (_SU32(cpd->init_table, LANCE_IB_TDRA) >> LANCE_IB_TDRA_CNT_shift) & 7);
591 #endif
592
593     // Reset chip
594     HAL_PCI_IO_READ_UINT16(cpd->base+LANCE_IO_RESET, val);
595
596     // Load up chip with buffers.
597     // Note: There is a 16M limit on the addresses used by the driver
598     // since the top 8 bits of the init_table address is appended to
599     // all other addresses used by the controller.
600     HAL_PCI_CPU_TO_BUS(cpd->init_table, (cyg_uint8 *)b);
601     put_reg(sc, LANCE_CSR_IBA0, (b >>  0) & 0xffff);
602     put_reg(sc, LANCE_CSR_IBA1, (b >> 16) & 0xffff);
603     // Disable automatic TX polling (_send will force a poll), pad
604     // XT frames to legal length, mask status interrupts.
605     put_reg(sc, LANCE_CSR_TFC, (LANCE_CSR_TFC_TXDPOLL | LANCE_CSR_TFC_APAD_XMT
606                                 | LANCE_CSR_TFC_MFCOM | LANCE_CSR_TFC_RCVCCOM
607                                 | LANCE_CSR_TFC_TXSTRTM));
608     // Recover after TX FIFO underflow
609     put_reg(sc, LANCE_CSR_IM, LANCE_CSR_IM_DXSUFLO);
610     // Initialize controller - load up init_table
611     put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_INIT);
612     while (0 == (get_reg(sc, LANCE_CSR_CSCR) & LANCE_CSR_CSCR_IDON));
613
614     // Stop controller
615     put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_STOP);
616
617 #if DEBUG & 9
618     db_printf("lancepci controller state is now:\n");
619     db_printf(" Mode 0x%04x  TFC 0x%04x\n", _SU16(cpd->init_table, LANCE_IB_MODE), get_reg(sc, LANCE_CSR_TFC));
620     db_printf(" PADR %04x:%04x:%04x ",
621                 get_reg(sc, LANCE_CSR_PAR0),
622                 get_reg(sc, LANCE_CSR_PAR1),
623                 get_reg(sc, LANCE_CSR_PAR2));
624     db_printf("LADR %04x:%04x:%04x:%04x\n",
625                 get_reg(sc, LANCE_CSR_LAR0),
626                 get_reg(sc, LANCE_CSR_LAR1),
627                 get_reg(sc, LANCE_CSR_LAR2),
628                 get_reg(sc, LANCE_CSR_LAR3));
629     db_printf(" RX 0x%04x%04x (len 0x%04x) TX 0x%04x%04x (len 0x%04x)\n",
630                 get_reg(sc, LANCE_CSR_BARRU), get_reg(sc, LANCE_CSR_BARRL),
631                 get_reg(sc, LANCE_CSR_RRLEN),
632                 get_reg(sc, LANCE_CSR_BATRU), get_reg(sc, LANCE_CSR_BATRL),
633                 get_reg(sc, LANCE_CSR_TRLEN));
634
635     val = get_reg(sc, LANCE_CSR_ID_LO);
636     db_printf("lancepci ID 0x%04x (%s) ",
637                 val,
638                 (0x5003 == val) ? "Am79C973" : (0x7003 == val) ? "Am79C975" :
639                         (0x1003 == val) ? "Am79C900 or wmWare VLANCE" : "Unknown");
640     val = get_reg(sc, LANCE_CSR_ID_HI);
641     db_printf("Part IDU 0x%03x Silicon rev %d\n",
642                 val & 0x0fff, (val >> 12) & 0xf);
643 #endif
644     // and record the net dev pointer
645     cpd->ndp = (void *)tab;
646     cpd->active = 0;
647     oursc=sc;
648
649     // Initialize upper level driver
650     (sc->funs->eth_drv->init)(sc, cpd->esa);
651     cpd->txbusyh=cpd->txbusy=0;
652     cpd->event=0;
653     db_printf("Lancepci driver loaded and Init Done\n");
654     return true;
655 }
656
657 static void
658 lancepci_stop(struct eth_drv_sc *sc)
659 {
660     cyg_uint32 b;
661     struct lancepci_priv_data *cpd =
662         (struct lancepci_priv_data *)sc->driver_private;
663
664     DEBUG_FUNCTION();
665     if (!cpd->active)
666         return;
667     if (cpd->txbusyh) {
668 #if DEBUG & 9
669         db_printf("Lancepci-stop:waiting for tx empty\n");
670 #endif
671         b=100;
672         while (cpd->txbusyh && b) {
673             CYGACC_CALL_IF_DELAY_US(200);
674             b--;
675          }
676     }
677     put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_STOP);
678     cpd->active = 0;
679 #if DEBUG & 9
680     db_printf("Lancepci-stop:done\n");
681 #endif
682 }
683
684 //
685 // This function is called to "start up" the interface.  It may be called
686 // multiple times, even when the hardware is already running.  It will be
687 // called whenever something "hardware oriented" changes and should leave
688 // the hardware ready to send/receive packets.
689 //
690 static void
691 lancepci_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
692 {
693     cyg_uint16 reg;
694     cyg_uint32 b;
695     struct lancepci_priv_data *cpd =
696         (struct lancepci_priv_data *)sc->driver_private;
697 #ifdef CYGPKG_NET
698     struct ifnet *ifp = &sc->sc_arpcom.ac_if;
699 #endif
700     DEBUG_FUNCTION();
701
702     // If device is already active, stop it
703 #if DEBUG & 9
704         db_printf("Lancepci-start:entered\n");
705 #endif
706     if (cpd->active)
707      {
708         if (cpd->txbusyh) {
709 #if DEBUG & 9
710             db_printf("Lancepci-start:waiting for tx empty\n");
711 #endif
712             b=100;
713             while (cpd->txbusyh && b) {
714                 CYGACC_CALL_IF_DELAY_US(200);
715                 b--;
716             }
717         }
718         put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_STOP);
719         cpd->active = 0;
720 #if DEBUG & 9
721         db_printf("Lancepci-start:stopped\n");
722 #endif
723     }
724     CYGACC_CALL_IF_DELAY_US(200);
725
726 #ifdef CYGPKG_NET
727     if (( 0
728 #ifdef ETH_DRV_FLAGS_PROMISC_MODE
729          != (flags & ETH_DRV_FLAGS_PROMISC_MODE)
730 #endif
731         ) || (ifp->if_flags & IFF_PROMISC)
732         ) {
733         // Then we select promiscuous mode.
734         _SU16(cpd->init_table, LANCE_IB_MODE) = 0x0000|LANCE_CSR_MODE_PROM;
735 #if DEBUG & 9
736         db_printf("Promisc MODE!");
737 #endif
738     }
739     else _SU16(cpd->init_table, LANCE_IB_MODE) = 0x0000;
740 #endif
741     cpd->rx_ring_next = 0;
742     cpd->tx_ring_free = cpd->tx_ring_alloc = cpd->tx_ring_owned = 0;
743     // Init the chip again
744     HAL_PCI_CPU_TO_BUS(cpd->init_table, (cyg_uint8 *)b);
745     put_reg(sc, LANCE_CSR_IBA0, (b >>  0) & 0xffff);
746     put_reg(sc, LANCE_CSR_IBA1, (b >> 16) & 0xffff);
747     // Disable automatic TX polling (_send will force a poll), pad
748     // XT frames to legal length, mask status interrupts.
749     put_reg(sc, LANCE_CSR_TFC, (LANCE_CSR_TFC_TXDPOLL | LANCE_CSR_TFC_APAD_XMT
750                                 | LANCE_CSR_TFC_MFCOM | LANCE_CSR_TFC_RCVCCOM
751                                 | LANCE_CSR_TFC_TXSTRTM));
752     // Recover after TX FIFO underflow
753     put_reg(sc, LANCE_CSR_IM, LANCE_CSR_IM_DXSUFLO);
754     // Initialize controller - load up init_table
755     put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_INIT);
756     while (0 == (get_reg(sc, LANCE_CSR_CSCR) & LANCE_CSR_CSCR_IDON));
757         reg=get_reg(sc,LANCE_CSR_CSCR);
758     put_reg(sc, LANCE_CSR_CSCR, (reg|(LANCE_CSR_CSCR_IENA | LANCE_CSR_CSCR_STRT))&~LANCE_CSR_CSCR_INIT);
759 #if DEBUG & 9
760         reg=get_reg(sc,LANCE_CSR_CSCR);
761         db_printf("CSR after start = %4x\n",reg);
762 #endif
763     cpd->active = 1; cpd->txbusy=0; cpd->txbusyh=0;
764     // delay is necessary for Vmware to get a tick !!!
765     CYGACC_CALL_IF_DELAY_US(50000);
766 }
767
768 //
769 // This routine is called to perform special "control" opertions
770 //
771 static int
772 lancepci_control(struct eth_drv_sc *sc, unsigned long key,
773                void *data, int data_length)
774 {
775     cyg_uint8 *esa = (cyg_uint8 *)data;
776     int i, res;
777     cyg_uint16 reg;
778     struct lancepci_priv_data *cpd =
779         (struct lancepci_priv_data *)sc->driver_private;
780
781     DEBUG_FUNCTION();
782
783 #if DEBUG & 9
784         db_printf("Lancepci-control:entered\n");
785 #endif
786     res = 0;                            // expect success
787     switch (key) {
788         case ETH_DRV_SET_MAC_ADDRESS:
789 #if 9 & DEBUG
790             db_printf("PCNET - set ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
791                 esa[0], esa[1], esa[2], esa[3], esa[4], esa[5] );
792 #endif // DEBUG
793             for ( i = 0; i < sizeof(cpd->esa);  i++ )
794                 cpd->esa[i] = esa[i];
795             for (i = 0;  i < sizeof(cpd->esa);  i += 2) {
796                 reg = cpd->esa[i] | (cpd->esa[i+1] << 8);
797                 put_reg(sc, LANCE_CSR_PAR0+i/2, reg );
798             }
799             for (i = 0; i < 6; i++)     // in case of later restart
800                 _SU8(cpd->init_table, LANCE_IB_PADR0+i) = cpd->esa[i];
801             break;
802 #ifdef ETH_DRV_GET_MAC_ADDRESS
803         case ETH_DRV_GET_MAC_ADDRESS:
804             // Extract the MAC address that is in the chip, and tell the
805             // system about it.
806             for (i = 0;  i < sizeof(cpd->esa);  i += 2) {
807                 cyg_uint16 z = get_reg(sc, LANCE_CSR_PAR0+i/2 );
808                 esa[i] =   (cyg_uint8)(0xff & z);
809                 esa[i+1] = (cyg_uint8)(0xff & (z >> 8));
810             }
811             break;
812 #endif
813 #ifdef ETH_DRV_GET_IF_STATS_UD
814         case ETH_DRV_GET_IF_STATS_UD: // UD == UPDATE
815 #endif
816         // drop through
817 #ifdef ETH_DRV_GET_IF_STATS
818         case ETH_DRV_GET_IF_STATS:
819 #endif
820
821 #if defined(ETH_DRV_GET_IF_STATS) || defined (ETH_DRV_GET_IF_STATS_UD)
822         {
823             struct ether_drv_stats *p = (struct ether_drv_stats *)data;
824             // Chipset entry is no longer supported; RFC1573.
825             for ( i = 0; i < SNMP_CHIPSET_LEN; i++ )
826                 p->snmp_chipset[i] = 0;
827
828             // This perhaps should be a config opt, so you can make up your own
829             // description, or supply it from the instantiation.
830             strcpy( p->description, "AMD LancePCI" );
831             // CYG_ASSERT( 48 > strlen(p->description), "Description too long" );
832
833             p->operational = 3;         // LINK UP
834             p->duplex = 2;              // 2 = SIMPLEX
835             p->speed = 10 * 1000000;
836
837 #if FIXME
838 #ifdef KEEP_STATISTICS
839             {
840                 struct amd_lancepci_stats *ps = &(cpd->stats);
841
842                 // Admit to it...
843                 p->supports_dot3        = true;
844
845                 p->tx_good              = ps->tx_good             ;
846                 p->tx_max_collisions    = ps->tx_max_collisions   ;
847                 p->tx_late_collisions   = ps->tx_late_collisions  ;
848                 p->tx_underrun          = ps->tx_underrun         ;
849                 p->tx_carrier_loss      = ps->tx_carrier_loss     ;
850                 p->tx_deferred          = ps->tx_deferred         ;
851                 p->tx_sqetesterrors     = ps->tx_sqetesterrors    ;
852                 p->tx_single_collisions = ps->tx_single_collisions;
853                 p->tx_mult_collisions   = ps->tx_mult_collisions  ;
854                 p->tx_total_collisions  = ps->tx_total_collisions ;
855                 p->rx_good              = ps->rx_good             ;
856                 p->rx_crc_errors        = ps->rx_crc_errors       ;
857                 p->rx_align_errors      = ps->rx_align_errors     ;
858                 p->rx_resource_errors   = ps->rx_resource_errors  ;
859                 p->rx_overrun_errors    = ps->rx_overrun_errors   ;
860                 p->rx_collisions        = ps->rx_collisions       ;
861                 p->rx_short_frames      = ps->rx_short_frames     ;
862                 p->rx_too_long_frames   = ps->rx_too_long_frames  ;
863                 p->rx_symbol_errors     = ps->rx_symbol_errors    ;
864
865                 p->interrupts           = ps->interrupts          ;
866                 p->rx_count             = ps->rx_count            ;
867                 p->rx_deliver           = ps->rx_deliver          ;
868                 p->rx_resource          = ps->rx_resource         ;
869                 p->rx_restart           = ps->rx_restart          ;
870                 p->tx_count             = ps->tx_count            ;
871                 p->tx_complete          = ps->tx_complete         ;
872                 p->tx_dropped           = ps->tx_dropped          ;
873             }
874 #endif // KEEP_STATISTICS
875 #endif // FIXME
876
877             p->tx_queue_len = 1;
878             break;
879         }
880 #endif
881         default:
882             res = 1;
883             break;
884     }
885 #if DEBUG & 9
886     db_printf("Lancepci-control:done\n");
887 #endif
888     CYGACC_CALL_IF_DELAY_US(50000);     // let VMware get a tick
889     return res;
890 }
891
892 //
893 // This routine is called to see if it is possible to send another packet.
894 // It will return non-zero if a transmit is possible, zero otherwise.
895 //
896 static int
897 lancepci_can_send(struct eth_drv_sc *sc)
898 {
899     struct lancepci_priv_data *cpd =
900         (struct lancepci_priv_data *)sc->driver_private;
901
902     DEBUG_FUNCTION();
903
904     return (0 == cpd->txbusy);
905 }
906
907 //
908 // This routine is called to send data to the hardware.
909 static void
910 lancepci_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
911             int total_len, unsigned long key)
912 {
913     struct lancepci_priv_data *cpd =
914         (struct lancepci_priv_data *)sc->driver_private;
915     int i, len, plen, ring_entry;
916
917     cyg_uint8* sdata = NULL;
918     cyg_uint8 *d, *buf, *txd;
919     cyg_uint16 ints;
920     cyg_uint32 b;
921
922     DEBUG_FUNCTION();
923
924     INCR_STAT( tx_count );
925
926     cpd->txbusy = 1; cpd->txbusyh=1;
927     cpd->txkey = key;
928
929     // Find packet length
930     plen = 0;
931     for (i = 0;  i < sg_len;  i++)
932         plen += sg_list[i].len;
933
934     CYG_ASSERT( plen == total_len, "sg data length mismatch" );
935
936     // Get next TX descriptor
937     ring_entry = cpd->tx_ring_free;
938     do {
939         if (cpd->tx_ring_owned == cpd->tx_ring_cnt) {
940             // Is this a dead end? Probably is.
941 #if DEBUG & 1
942             db_printf("%s: Allocation failed! Retrying...\n", __FUNCTION__ );
943 #endif
944             continue;
945         }
946
947         cpd->tx_ring_free++;
948         cpd->tx_ring_owned++;
949         if (cpd->tx_ring_free == cpd->tx_ring_cnt)
950             cpd->tx_ring_free = 0;
951     } while (0);
952
953     txd = cpd->tx_ring + ring_entry*LANCE_TD_SIZE;
954     buf = cpd->tx_buffers + ring_entry*_BUF_SIZE;
955     CYG_ASSERT(0 == (_SU32(txd, LANCE_TD_PTR) & LANCE_TD_PTR_OWN),
956                "TX descriptor not free");
957
958 #if DEBUG & 4
959     db_printf("#####Tx descriptor 0x%08x buffer 0x%08x\n",
960                 txd, buf);
961 #endif
962
963     // Put data into buffer
964     d = buf;
965     for (i = 0;  i < sg_len;  i++) {
966         sdata = (cyg_uint8 *)sg_list[i].buf;
967         len = sg_list[i].len;
968
969         CYG_ASSERT( sdata, "No sg data pointer here" );
970         while(len--)
971             *d++ = *sdata++;
972     }
973     CYG_ASSERT( sdata, "No sg data pointer outside" );
974
975 #if DEBUG & 1
976     db_printf("CSCR %04x\n", get_reg(sc, LANCE_CSR_CSCR));
977 #endif
978     _SU16(txd, LANCE_TD_LEN) = (-plen);
979     _SU16(txd, LANCE_TD_MISC) = 0;
980     HAL_PCI_CPU_TO_BUS(buf, (cyg_uint8 *)b);
981     _SU32(txd, LANCE_TD_PTR) = ((b & LANCE_TD_PTR_MASK)
982                                 | LANCE_TD_PTR_OWN | LANCE_TD_PTR_STP | LANCE_TD_PTR_ENP);
983
984 #if DEBUG & 1
985     db_printf("Last TX: LEN %04x MISC %04x PTR %08x\n",
986                 _SU16(txd, LANCE_TD_LEN),
987                 _SU16(txd, LANCE_TD_MISC),
988                 _SU32(txd, LANCE_TD_PTR));
989 #endif
990
991     // This delay seems to be necessary on some platforms
992     // (Malta 5kc for example).
993     // Why it is needed is not clear, but removing it or
994     // reducing it cause transmission failures in RedBoot (at least).
995     CYGACC_CALL_IF_DELAY_US(100);
996
997
998     // Set transmit demand
999     ints = get_reg(sc, LANCE_CSR_CSCR);
1000     ints &= LANCE_CSR_CSCR_EV_MASK;
1001     ints |= LANCE_CSR_CSCR_TDMD;
1002     put_reg(sc, LANCE_CSR_CSCR, ints);
1003
1004 #if DEBUG & 1
1005     ints = get_reg(sc, LANCE_CSR_CSCR);
1006     db_printf("%s:END: ints at TX: 0x%04x\n", __FUNCTION__, ints);
1007 #endif
1008
1009     // This is another mystery delay like the one above. This one is
1010     // even stranger, since waiting here at the _end_ of the function
1011     // should have no effect.
1012     CYGACC_CALL_IF_DELAY_US(200);
1013 }
1014
1015 static void
1016 lancepci_TxEvent(struct eth_drv_sc *sc, int stat)
1017 {
1018      struct lancepci_priv_data *cpd =
1019         (struct lancepci_priv_data *)sc->driver_private;
1020     int success = 1;
1021     cyg_uint8 *txd;
1022     cyg_uint16 ints;
1023     cyg_uint32 pkt_stat;
1024
1025     DEBUG_FUNCTION();
1026
1027     if (0 == cpd->tx_ring_owned) {
1028 #if DEBUG & 1
1029         db_printf("%s: got TX completion when no outstanding packets\n", __FUNCTION__);
1030 #endif
1031         return;
1032     }
1033
1034     INCR_STAT( tx_complete );
1035
1036     txd = cpd->tx_ring + cpd->tx_ring_alloc*LANCE_TD_SIZE;
1037     pkt_stat = _SU32(txd, LANCE_TD_PTR);
1038     if (pkt_stat & LANCE_TD_PTR_OWN) {
1039 #if DEBUG & 1
1040         db_printf("%s: got TX completion when buffer is still owned\n", __FUNCTION__);
1041 #endif
1042         // first dirty ring entry not freed - wtf?
1043     }
1044
1045     if (pkt_stat & LANCE_TD_PTR_ERR) {
1046         // We had an error. Tell the stack.
1047         success = 0;
1048 #if DEBUG & 1
1049         db_printf("%s: TX failure, retrying...\n", __FUNCTION__);
1050 #endif
1051     }
1052
1053     cpd->tx_ring_alloc++;
1054     if (cpd->tx_ring_alloc == cpd->tx_ring_cnt)
1055         cpd->tx_ring_alloc = 0;
1056     cpd->tx_ring_owned--;
1057
1058 #if FIXME
1059 #ifdef KEEP_STATISTICS
1060     {
1061         cyg_uint16 reg;
1062
1063         reg = get_reg( sc, LANCE_CSR_CSCR );
1064
1065         // Covering each bit in turn...
1066         if ( reg & LANCE_STATUS_TX_UNRN   ) INCR_STAT( tx_underrun );
1067         //if ( reg & LANCE_STATUS_LINK_OK ) INCR_STAT(  );
1068         //if ( reg & LANCE_STATUS_CTR_ROL ) INCR_STAT(  );
1069         //if ( reg & LANCE_STATUS_EXC_DEF ) INCR_STAT(  );
1070         if ( reg & LANCE_STATUS_LOST_CARR ) INCR_STAT( tx_carrier_loss );
1071         if ( reg & LANCE_STATUS_LATCOL    ) INCR_STAT( tx_late_collisions );
1072         //if ( reg & LANCE_STATUS_WAKEUP  ) INCR_STAT(  );
1073         if ( reg & LANCE_STATUS_TX_DEFR   ) INCR_STAT( tx_deferred );
1074         //if ( reg & LANCE_STATUS_LTX_BRD ) INCR_STAT(  );
1075         if ( reg & LANCE_STATUS_SQET      ) INCR_STAT( tx_sqetesterrors );
1076         if ( reg & LANCE_STATUS_16COL     ) INCR_STAT( tx_max_collisions );
1077         //if ( reg & LANCE_STATUS_LTX_MULT) INCR_STAT(  );
1078         if ( reg & LANCE_STATUS_MUL_COL   ) INCR_STAT( tx_mult_collisions );
1079         if ( reg & LANCE_STATUS_SNGL_COL  ) INCR_STAT( tx_single_collisions );
1080         if ( reg & LANCE_STATUS_TX_SUC    ) INCR_STAT( tx_good );
1081
1082         cpd->stats.tx_total_collisions =
1083             cpd->stats.tx_late_collisions +
1084             cpd->stats.tx_max_collisions +
1085             cpd->stats.tx_mult_collisions +
1086             cpd->stats.tx_single_collisions;
1087
1088         // We do not need to look in the Counter Register (LANCE_COUNTER)
1089         // because it just mimics the info we already have above.
1090     }
1091 #endif // KEEP_STATISTICS
1092 #endif // FIXME
1093
1094     // Ack the TX int which clears the packet from the TX completion
1095     // queue.
1096     ints = get_reg(sc, LANCE_CSR_CSCR);
1097     ints |= LANCE_CSR_CSCR_TINT;
1098     put_reg(sc, LANCE_CSR_CSCR, ints);
1099
1100 #if DEBUG & 4
1101     db_printf("#####Tx packet freed 0x%08x\n", txd );
1102 #endif
1103
1104     if ( cpd->txbusy ) {
1105         cpd->txbusy = 0;
1106         (sc->funs->eth_drv->tx_done)(sc, cpd->txkey, success);
1107     }
1108 }
1109
1110
1111 //
1112 // This function is called when a packet has been received.  Its job is
1113 // to prepare to unload the packet from the hardware.  Once the length of
1114 // the packet is known, the upper layer of the driver can be told.  When
1115 // the upper layer is ready to unload the packet, the internal function
1116 // 'lancepci_recv' will be called to actually fetch it from the hardware.
1117 //
1118 static void
1119 lancepci_RxEvent(struct eth_drv_sc *sc)
1120 {
1121     struct lancepci_priv_data *cpd =
1122         (struct lancepci_priv_data *)sc->driver_private;
1123     cyg_uint8 *rxd;
1124     cyg_uint32 rstat;
1125     cyg_uint16 ints, len;
1126
1127     DEBUG_FUNCTION();
1128
1129     ints = get_reg(sc, LANCE_CSR_CSCR);
1130 #if DEBUG & 1
1131     db_printf("RxEvent - CSR: 0x%04x\n", ints);
1132 #endif
1133
1134     while (1) {
1135         // Get state of next (supposedly) full ring entry
1136         cpd->rxpacket = cpd->rx_ring_next;
1137         rxd = cpd->rx_ring + cpd->rxpacket*LANCE_RD_SIZE;
1138         rstat = _SU32(rxd, LANCE_RD_PTR);
1139
1140         // Keep going until we hit an entry that is owned by the
1141         // controller.
1142         if (rstat & LANCE_RD_PTR_OWN) {
1143 #if DEBUG & 1
1144             int i;
1145             for (i = 0; i < cpd->rx_ring_cnt; i++) {
1146                 rxd = cpd->rx_ring + i*LANCE_RD_SIZE;
1147                 rstat = _SU32(rxd, LANCE_RD_PTR);
1148
1149                 if (!(rstat & LANCE_RD_PTR_OWN)) {
1150                     int i;
1151                     cyg_uint32 rstat;
1152                     cyg_uint16 mlen, blen;
1153                     cyg_uint8* rxd;
1154
1155                     db_printf("%s: Inconsistent RX state\n", __FUNCTION__);
1156                     for (i = 0; i < cpd->rx_ring_cnt; i++) {
1157                         rxd = cpd->rx_ring + i*LANCE_RD_SIZE;
1158
1159                         rstat = _SU32(rxd, LANCE_RD_PTR);
1160                         blen = _SU16(rxd, LANCE_RD_BLEN);
1161                         mlen = _SU16(rxd, LANCE_RD_MLEN);
1162                         db_printf(" %02d: 0x%08x:0x%04x:0x%04x\n", i, rstat, blen, mlen);
1163                     }
1164                 }
1165             }
1166 #endif
1167             break;
1168         }
1169
1170 #if DEBUG & 4
1171         db_printf("#####Rx packet at index %d\n", cpd->rxpacket);
1172 #endif
1173
1174         // Increment counts
1175         INCR_STAT( rx_count );
1176         cpd->rx_ring_next++;
1177         if (cpd->rx_ring_next == cpd->rx_ring_cnt) cpd->rx_ring_next = 0;
1178
1179         len = _SU16(rxd, LANCE_RD_MLEN);
1180
1181 #ifdef KEEP_STATISTICS
1182         //if ( rstat & LANCE_RD_PTR_FRAM ) INCR_STAT( rx_frame_errors );
1183         //if ( rstat & LANCE_RD_PTR_OFLO ) INCR_STAT(  );
1184         if ( rstat & LANCE_RD_PTR_CRC ) INCR_STAT( rx_crc_errors );
1185         //if ( rstat & LANCE_RD_PTR_BUFF ) INCR_STAT(  );
1186 #endif // KEEP_STATISTICS
1187
1188         if (0 == (rstat & LANCE_RD_PTR_ERR)) {
1189             // It's OK
1190             INCR_STAT( rx_good );
1191
1192 #if DEBUG & 1
1193             db_printf("RxEvent good rx - stat: 0x%08x, len: 0x%04x\n", rstat, len);
1194 #endif
1195             // Check for bogusly short packets; can happen in promisc
1196             // mode: Asserted against and checked by upper layer
1197             // driver.
1198 #ifdef CYGPKG_NET
1199             if ( len > sizeof( struct ether_header ) )
1200                 // then it is acceptable; offer the data to the network stack
1201 #endif
1202                 (sc->funs->eth_drv->recv)(sc, len);
1203         } else {
1204             // Not OK for one reason or another...
1205 #if DEBUG & 1
1206             db_printf("RxEvent - No RX bit: stat: 0x%08x, len: 0x%04x\n",
1207                         rstat, len);
1208 #endif
1209         }
1210
1211         // Free packet (clear all status flags, and set OWN)
1212         _SU32(rxd, LANCE_RD_PTR) &= LANCE_RD_PTR_MASK;
1213         _SU32(rxd, LANCE_RD_PTR) |= LANCE_RD_PTR_OWN;
1214     }
1215
1216     // Ack RX interrupt set
1217     ints = get_reg(sc, LANCE_CSR_CSCR);
1218     ints &= LANCE_CSR_CSCR_EV_MASK;
1219     ints |= LANCE_CSR_CSCR_RINT;
1220     put_reg(sc, LANCE_CSR_CSCR, ints);
1221 }
1222
1223 //
1224 // This function is called as a result of the "eth_drv_recv()" call above.
1225 // Its job is to actually fetch data for a packet from the hardware once
1226 // memory buffers have been allocated for the packet.  Note that the buffers
1227 // may come in pieces, using a scatter-gather list.  This allows for more
1228 // efficient processing in the upper layers of the stack.
1229 //
1230 static void
1231 lancepci_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
1232 {
1233     struct lancepci_priv_data *cpd =
1234         (struct lancepci_priv_data *)sc->driver_private;
1235     int i, mlen=0, plen;
1236     cyg_uint8 *data, *rxd, *buf;
1237
1238     DEBUG_FUNCTION();
1239
1240     rxd = cpd->rx_ring + cpd->rxpacket*LANCE_RD_SIZE;
1241     buf = cpd->rx_buffers + cpd->rxpacket*_BUF_SIZE;
1242
1243     INCR_STAT( rx_deliver );
1244
1245     plen = _SU16(rxd, LANCE_RD_MLEN);
1246
1247     for (i = 0;  i < sg_len;  i++) {
1248         data = (cyg_uint8*)sg_list[i].buf;
1249         mlen = sg_list[i].len;
1250
1251 #if DEBUG & 1
1252         db_printf("%s : mlen %x, plen %x\n", __FUNCTION__, mlen, plen);
1253 #endif
1254         if (data) {
1255             while (mlen > 0) {
1256                 *data++ = *buf++;
1257                 mlen--;
1258                 plen--;
1259             }
1260         }
1261     }
1262 }
1263
1264 static void
1265 lancepci_poll(struct eth_drv_sc *sc)
1266 {
1267     cyg_uint16 event;
1268     struct lancepci_priv_data *cpd =
1269         (struct lancepci_priv_data *)sc->driver_private;
1270
1271 //  DEBUG_FUNCTION();
1272
1273     while (1) {
1274         // Get the (unmasked) requests
1275         if (cpd->event) {
1276             event=cpd->event;
1277             cpd->event=0;
1278         }
1279         else
1280             event = get_reg(sc, LANCE_CSR_CSCR);
1281         if (!((LANCE_CSR_CSCR_ERR|LANCE_CSR_CSCR_INTR) & event))
1282             break;
1283
1284         if (event & LANCE_CSR_CSCR_RINT) {
1285             lancepci_RxEvent(sc);
1286         }
1287         else if (event & LANCE_CSR_CSCR_TINT) {
1288             cpd->txbusyh=0;             // again , for polled mode
1289             lancepci_TxEvent(sc, event);
1290         }
1291         else if (event & LANCE_CSR_CSCR_MISS) {
1292 #if DEBUG & 1
1293             int i;
1294             cyg_uint32 rstat;
1295             cyg_uint16 mlen, blen;
1296             cyg_uint8* rxd;
1297             struct lancepci_priv_data *cpd =
1298                 (struct lancepci_priv_data *)sc->driver_private;
1299
1300             db_printf("%s: Ran out of RX buffers (%04x)\n", __FUNCTION__, event);
1301             for (i = 0; i < cpd->rx_ring_cnt; i++) {
1302                 rxd = cpd->rx_ring + i*LANCE_TD_SIZE;
1303
1304                 rstat = _SU32(rxd, LANCE_RD_PTR);
1305                 blen = _SU16(rxd, LANCE_RD_BLEN);
1306                 mlen = _SU16(rxd, LANCE_RD_MLEN);
1307                 db_printf(" %02d: 0x%08x:0x%04x:0x%04x\n", i, rstat, blen, mlen);
1308             }
1309 #endif
1310             event &= LANCE_CSR_CSCR_EV_MASK;
1311             event |= LANCE_CSR_CSCR_MISS;
1312             put_reg(sc, LANCE_CSR_CSCR, event);
1313         }
1314         else {
1315 #if DEBUG & 1
1316             db_printf("%s: Unknown interrupt: 0x%04x\n", __FUNCTION__, event);
1317 #endif
1318             put_reg(sc, LANCE_CSR_CSCR, event);
1319         }
1320     }
1321 }
1322
1323 // EOF if_lancepci.c