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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [devs/] [eth/] [via/] [rhine/] [v2_0/] [src/] [if_rhine.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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