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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [eth/] [mips/] [atlas/] [current/] [src/] [if_atlas.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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