OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [eth/] [amd/] [lancepci/] [current/] [src/] [if_lancepci.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.