OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [eth/] [ns/] [dp83902a/] [v2_0/] [src/] [if_dp83902a.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      dev/if_dp83902a.c
4
//
5
//      Ethernet device driver for NS DP83902a ethernet controller
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):    gthomas
54
// Contributors: gthomas, jskov, rsandifo
55
// Date:         2001-06-13
56
// Purpose:      
57
// Description:
58
//
59
// FIXME:        Will fail if pinged with large packets (1520 bytes)
60
//               Add promisc config
61
//               Add SNMP
62
//
63
//####DESCRIPTIONEND####
64
//
65
//==========================================================================
66
 
67
#include <pkgconf/system.h>
68
#include <pkgconf/io_eth_drivers.h>
69
 
70
#include <cyg/infra/cyg_type.h>
71
#include <cyg/hal/hal_arch.h>
72
#include <cyg/infra/diag.h>
73
#include <cyg/hal/drv_api.h>
74
#include <cyg/io/eth/eth_drv.h>
75
#include <cyg/io/eth/netdev.h>
76
 
77
#include <cyg/io/dp83902a.h>
78
 
79
#define __WANT_DEVS
80
#include CYGDAT_DEVS_ETH_NS_DP83902A_INL
81
#undef __WANT_DEVS
82
 
83
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
84
// This ISR is called when the ethernet interrupt occurs
85
static cyg_uint32
86
dp83902a_isr(cyg_vector_t vector, cyg_addrword_t data)
87
{
88
    dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *)data;
89
 
90
    DEBUG_FUNCTION();
91
//    INCR_STAT( interrupts );
92
 
93
    cyg_drv_interrupt_mask(dp->interrupt);
94
    cyg_drv_interrupt_acknowledge(dp->interrupt);
95
    return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
96
}
97
 
98
static void
99
dp83902a_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
100
{
101
    // This conditioning out is necessary because of explicit calls to this
102
    // DSR - which would not ever be called in the case of a polled mode
103
    // usage ie. in RedBoot.
104
#ifdef CYGPKG_IO_ETH_DRIVERS_NET
105
    dp83902a_priv_data_t* dp = (dp83902a_priv_data_t *)data;
106
    struct cyg_netdevtab_entry *ndp = (struct cyg_netdevtab_entry *)(dp->tab);
107
    struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance);
108
 
109
    DEBUG_FUNCTION();
110
 
111
    // but here, it must be a *sc:
112
    eth_drv_dsr( vector, count, (cyg_addrword_t)sc );
113
#else
114
# ifndef CYGPKG_REDBOOT
115
#  error Empty DP83902A ethernet DSR is compiled.  Is this what you want?
116
# endif
117
#endif
118
}
119
#endif // CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
120
 
121
// The deliver function (ex-DSR)  handles the ethernet [logical] processing
122
static void
123
dp83902a_deliver(struct eth_drv_sc *sc)
124
{
125
    dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *)sc->driver_private;
126
 
127
    DEBUG_FUNCTION();
128
 
129
    // Service the interrupt:
130
    dp83902a_poll(sc);
131
    // Allow interrupts to happen again
132
    cyg_drv_interrupt_unmask(dp->interrupt);
133
}
134
 
135
static bool
136
dp83902a_init(struct cyg_netdevtab_entry *tab)
137
{
138
    struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
139
    dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *)sc->driver_private;
140
    cyg_uint8* base;
141
    int i;
142
 
143
    DEBUG_FUNCTION();
144
 
145
    CYGHWR_NS_DP83902A_PLF_INIT(dp);
146
    base = dp->base;
147
    if (!base) return false;  // No device found
148
 
149
    dp->tab = tab;
150
    dp->cr_lock = 0;
151
 
152
    CYGHWR_NS_DP83902A_PLF_RESET(dp);
153
 
154
    DEBUG_LINE();
155
 
156
    // Prepare ESA
157
    DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1);  // Select page 1
158
    if (dp->hardwired_esa) {
159
        // Force the NIC to use the specified ESA
160
        for (i = 0; i < 6; i++)
161
            DP_OUT(base, DP_P1_PAR0+i, dp->esa[i]);
162
    } else {
163
        // Use the address from the serial EEPROM
164
        for (i = 0; i < 6; i++)
165
            DP_IN(base, DP_P1_PAR0+i, dp->esa[i]);
166
    }
167
    DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0);  // Select page 0
168
 
169
    diag_printf("DP83902A - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
170
                (dp->hardwired_esa) ? "static" : "eeprom",
171
                dp->esa[0],
172
                dp->esa[1],
173
                dp->esa[2],
174
                dp->esa[3],
175
                dp->esa[4],
176
                dp->esa[5] );
177
 
178
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
179
    cyg_drv_interrupt_create(
180
        dp->interrupt,
181
        0,                  // Priority - unused
182
        (cyg_addrword_t)dp,// Data item passed to ISR & DSR
183
        dp83902a_isr,          // ISR
184
        dp83902a_dsr,          // DSR
185
        &dp->interrupt_handle, // handle to intr obj
186
        &dp->interrupt_object ); // space for int obj
187
 
188
    cyg_drv_interrupt_attach(dp->interrupt_handle);
189
    cyg_drv_interrupt_unmask(dp->interrupt);
190
#endif
191
 
192
    // Initialize upper level driver
193
    (sc->funs->eth_drv->init)(sc, dp->esa);
194
 
195
    return true;
196
}
197
 
198
static void
199
dp83902a_stop(struct eth_drv_sc *sc)
200
{
201
    dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *)sc->driver_private;
202
    cyg_uint8 *base = dp->base;
203
 
204
    DEBUG_FUNCTION();
205
 
206
    CR_UP();
207
    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP);  // Brutal
208
    DP_OUT(base, DP_ISR, 0xFF);               // Clear any pending interrupts
209
    DP_OUT(base, DP_IMR, 0x00);               // Disable all interrupts
210
    CR_DOWN();
211
 
212
    dp->running = false;
213
}
214
 
215
//
216
// This function is called to "start up" the interface.  It may be called
217
// multiple times, even when the hardware is already running.  It will be
218
// called whenever something "hardware oriented" changes and should leave
219
// the hardware ready to send/receive packets.
220
//
221
static void
222
dp83902a_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
223
{
224
    dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *)sc->driver_private;
225
    cyg_uint8 *base = dp->base;
226
    int i;
227
 
228
    DEBUG_FUNCTION();
229
 
230
    CR_UP();
231
    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); // Brutal
232
    DP_OUT(base, DP_DCR, DP_DCR_INIT);
233
    DP_OUT(base, DP_RBCH, 0);                 // Remote byte count
234
    DP_OUT(base, DP_RBCL, 0);
235
    DP_OUT(base, DP_RCR, DP_RCR_MON);     // Accept no packets
236
    DP_OUT(base, DP_TCR, DP_TCR_LOCAL);   // Transmitter [virtually] off
237
    DP_OUT(base, DP_TPSR, dp->tx_buf1);    // Transmitter start page
238
    dp->tx1 = dp->tx2 = 0;
239
    dp->tx_next = dp->tx_buf1;
240
    dp->tx_started = false;
241
    DP_OUT(base, DP_PSTART, dp->rx_buf_start); // Receive ring start page
242
    DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); // Receive ring boundary
243
    DP_OUT(base, DP_PSTOP, dp->rx_buf_end);   // Receive ring end page
244
    dp->rx_next = dp->rx_buf_start-1;
245
    DP_OUT(base, DP_ISR, 0xFF);               // Clear any pending interrupts
246
    DP_OUT(base, DP_IMR, DP_IMR_All);     // Enable all interrupts
247
    DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1);  // Select page 1
248
    DP_OUT(base, DP_P1_CURP, dp->rx_buf_start);   // Current page - next free page for Rx
249
    for (i = 0;  i < ETHER_ADDR_LEN;  i++) {
250
        DP_OUT(base, DP_P1_PAR0+i, enaddr[i]);
251
    }
252
    // Enable and start device
253
    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
254
    DP_OUT(base, DP_TCR, DP_TCR_NORMAL); // Normal transmit operations
255
    DP_OUT(base, DP_RCR, DP_RCR_AB);  // Accept broadcast, no errors, no multicast
256
    dp->running = true;
257
    CR_DOWN();
258
}
259
 
260
//
261
// This routine is called to perform special "control" opertions
262
//
263
static int
264
dp83902a_control(struct eth_drv_sc *sc, unsigned long key,
265
               void *data, int data_len)
266
{
267
    switch (key) {
268
    case ETH_DRV_SET_MAC_ADDRESS:
269
        return 0;
270
        break;
271
    default:
272
        return 1;
273
        break;
274
    }
275
}
276
 
277
//
278
// This routine is called to see if it is possible to send another packet.
279
// It will return non-zero if a transmit is possible, zero otherwise.
280
//
281
static int
282
dp83902a_can_send(struct eth_drv_sc *sc)
283
{
284
    dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *)sc->driver_private;
285
 
286
    DEBUG_FUNCTION();
287
 
288
    return ((dp->tx1 == 0) || (dp->tx2 == 0));
289
}
290
 
291
//
292
// This routine is called to start the transmitter.  It is split out from the
293
// data handling routine so it may be called either when data becomes first 
294
// available or when an Tx interrupt occurs
295
//
296
 
297
static void
298
dp83902a_start_xmit(struct eth_drv_sc *sc, int start_page, int len)
299
{
300
    dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *)sc->driver_private;
301
    cyg_uint8 *base = dp->base;
302
 
303
    DEBUG_FUNCTION();
304
 
305
#if DEBUG & 1
306
    diag_printf("Tx pkt %d len %d\n", start_page, len);
307
    if (dp->tx_started)
308
        diag_printf("TX already started?!?\n");
309
#endif
310
 
311
    CR_UP();
312
    DP_OUT(base, DP_ISR, (DP_ISR_TxP | DP_ISR_TxE));
313
    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
314
    DP_OUT(base, DP_TBCL, len & 0xFF);
315
    DP_OUT(base, DP_TBCH, len >> 8);
316
    DP_OUT(base, DP_TPSR, start_page);
317
    DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START);
318
 
319
    CR_DOWN();
320
    dp->tx_started = true;
321
}
322
 
323
//
324
// This routine is called to send data to the hardware.  It is known a-priori
325
// that there is free buffer space (dp->tx_next).
326
//
327
static void
328
dp83902a_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
329
            int total_len, unsigned long key)
330
{
331
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)sc->driver_private;
332
    cyg_uint8 *base = dp->base;
333
    int i, len, start_page, pkt_len;
334
    unsigned char *data;
335
    cyg_uint8 isr;
336
#if DEBUG & 4
337
    int dx;
338
#endif
339
 
340
    DEBUG_FUNCTION();
341
 
342
    pkt_len = total_len;
343
    if (pkt_len < IEEE_8023_MIN_FRAME) pkt_len = IEEE_8023_MIN_FRAME;
344
#ifdef CYGHWR_NS_DP83902A_PLF_16BIT_DATA
345
    // Make length even when using 16 bit transfers
346
    if (pkt_len % 2) pkt_len++;
347
#endif
348
 
349
    start_page = dp->tx_next;
350
    if (dp->tx_next == dp->tx_buf1) {
351
        dp->tx1 = start_page;
352
        dp->tx1_len = pkt_len;
353
        dp->tx1_key = key;
354
        dp->tx_next = dp->tx_buf2;
355
    } else {
356
        dp->tx2 = start_page;
357
        dp->tx2_len = pkt_len;
358
        dp->tx2_key = key;
359
        dp->tx_next = dp->tx_buf1;
360
    }
361
    CR_UP();
362
 
363
#if DEBUG & 5
364
    diag_printf("TX prep page %d len %d\n", start_page, pkt_len);
365
#endif
366
 
367
    DP_OUT(base, DP_ISR, DP_ISR_RDC);  // Clear end of DMA
368
    {
369
        // Dummy read. The manual sez something slightly different,
370
        // but the code is extended a bit to do what Hitachi's monitor
371
        // does (i.e., also read data).
372
 
373
        cyg_uint16 tmp;
374
#ifdef CYGHWR_NS_DP83902A_PLF_16BIT_DATA
375
        int len = 2;
376
#else
377
        int len = 1;
378
#endif
379
 
380
        DP_OUT(base, DP_RSAL, 0x100-len);
381
        DP_OUT(base, DP_RSAH, (start_page-1) & 0xff);
382
        DP_OUT(base, DP_RBCL, len);
383
        DP_OUT(base, DP_RBCH, 0);
384
        DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START);
385
        DP_IN_DATA(dp->data, tmp);
386
    }
387
 
388
#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA
389
    // Stall for a bit before continuing to work around random data
390
    // corruption problems on some platforms.
391
    CYGACC_CALL_IF_DELAY_US(1);
392
#endif
393
 
394
    // Send data to device buffer(s)
395
    DP_OUT(base, DP_RSAL, 0);
396
    DP_OUT(base, DP_RSAH, start_page);
397
    DP_OUT(base, DP_RBCL, pkt_len & 0xFF);
398
    DP_OUT(base, DP_RBCH, pkt_len >> 8);
399
    DP_OUT(base, DP_CR, DP_CR_WDMA | DP_CR_START);
400
 
401
    // Put data into buffer
402
    for (i = 0;  i < sg_len;  i++) {
403
        data = (unsigned char *)sg_list[i].buf;
404
        len = sg_list[i].len;
405
#if DEBUG & 4
406
        diag_printf(" sg buf %08x len %08x\n ", data, len);
407
        dx = 0;
408
#endif
409
        while (len > 0) {
410
#ifdef CYGHWR_NS_DP83902A_PLF_16BIT_DATA
411
            cyg_uint16 tmp;
412
            tmp = *data++ << 8;
413
            len -= 2;
414
            if (len >= 0)
415
                tmp |= *data++;
416
            DP_OUT_DATA(dp->data, tmp);
417
#if DEBUG & 4
418
            diag_printf(" %04x", tmp);
419
            if (0 == (++dx % 8)) diag_printf("\n ");
420
#endif
421
#else
422
#if DEBUG & 4
423
            diag_printf(" %02x", *data);
424
            if (0 == (++dx % 16)) diag_printf("\n ");
425
#endif
426
            DP_OUT_DATA(dp->data, *data++);
427
            len--;
428
#endif
429
        }
430
#if DEBUG & 4
431
        diag_printf("\n");
432
#endif
433
    }
434
    if (total_len < pkt_len) {
435
#if DEBUG & 4
436
        diag_printf("  + %d bytes of padding\n", pkt_len - total_len);
437
#endif
438
        // Padding to 802.3 length was required
439
        for (i = total_len;  i < pkt_len;) {
440
#ifdef CYGHWR_NS_DP83902A_PLF_16BIT_DATA
441
            i += 2;
442
#else
443
            i++;
444
#endif
445
            DP_OUT_DATA(dp->data, 0);
446
        }
447
    }
448
 
449
#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA
450
    // After last data write, delay for a bit before accessing the
451
    // device again, or we may get random data corruption in the last
452
    // datum (on some platforms).
453
    CYGACC_CALL_IF_DELAY_US(1);
454
#endif
455
 
456
    // Wait for DMA to complete
457
    do {
458
        DP_IN(base, DP_ISR, isr);
459
    } while ((isr & DP_ISR_RDC) == 0);
460
    // Then disable DMA
461
    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
462
    CR_DOWN();
463
 
464
    // Start transmit if not already going
465
    if (!dp->tx_started) {
466
        if (start_page == dp->tx1) {
467
            dp->tx_int = 1;  // Expecting interrupt from BUF1
468
        } else {
469
            dp->tx_int = 2;  // Expecting interrupt from BUF2
470
        }
471
        dp83902a_start_xmit(sc, start_page, pkt_len);
472
    }
473
}
474
 
475
//
476
// This function is called when a packet has been received.  It's job is
477
// to prepare to unload the packet from the hardware.  Once the length of
478
// the packet is known, the upper layer of the driver can be told.  When
479
// the upper layer is ready to unload the packet, the internal function
480
// 'dp83902a_recv' will be called to actually fetch it from the hardware.
481
//
482
static void
483
dp83902a_RxEvent(struct eth_drv_sc *sc)
484
{
485
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)sc->driver_private;
486
    cyg_uint8 *base = dp->base;
487
    unsigned char rsr;
488
    unsigned char rcv_hdr[4];
489
    int i, len, pkt, cur;
490
 
491
    DEBUG_FUNCTION();
492
 
493
    DP_IN(base, DP_RSR, rsr);
494
    while (true) {
495
        CR_UP();
496
        // Read incoming packet header
497
        DP_OUT(base, DP_CR, DP_CR_PAGE1 | DP_CR_NODMA | DP_CR_START);
498
        DP_IN(base, DP_P1_CURP, cur);
499
        DP_OUT(base, DP_P1_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
500
        DP_IN(base, DP_BNDRY, pkt);
501
        pkt += 1;
502
        if (pkt == cur) {
503
            CR_DOWN();
504
            break;
505
        }
506
        if (pkt == dp->rx_buf_end) pkt = dp->rx_buf_start;
507
        DP_OUT(base, DP_RBCL, sizeof(rcv_hdr));
508
        DP_OUT(base, DP_RBCH, 0);
509
        DP_OUT(base, DP_RSAL, 0);
510
        DP_OUT(base, DP_RSAH, pkt);
511
        if (dp->rx_next == pkt) {
512
            DP_OUT(base, DP_BNDRY, cur-1); // Update pointer
513
            CR_DOWN();
514
            return;
515
        }
516
        dp->rx_next = pkt;
517
        DP_OUT(base, DP_ISR, DP_ISR_RDC); // Clear end of DMA
518
        DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
519
 
520
        for (i = 0;  i < sizeof(rcv_hdr);) {
521
#ifdef CYGHWR_NS_DP83902A_PLF_16BIT_DATA
522
            cyg_uint16 tmp;
523
            DP_IN_DATA(dp->data, tmp);
524
            rcv_hdr[i++] = (tmp >> 8) & 0xff;
525
            rcv_hdr[i++] = tmp & 0xff;
526
#else
527
            DP_IN_DATA(dp->data, rcv_hdr[i++]);
528
#endif
529
        }
530
        CR_DOWN();
531
 
532
#if DEBUG & 5
533
        diag_printf("rx hdr %02x %02x %02x %02x\n",
534
                    rcv_hdr[0], rcv_hdr[1], rcv_hdr[2], rcv_hdr[3]);
535
#endif
536
        len = ((rcv_hdr[3] << 8) | rcv_hdr[2]) - sizeof(rcv_hdr);
537
        (sc->funs->eth_drv->recv)(sc, len);
538
        DP_OUT(base, DP_BNDRY, rcv_hdr[1]-1); // Update pointer
539
    }
540
}
541
 
542
//
543
// This function is called as a result of the "eth_drv_recv()" call above.
544
// It's job is to actually fetch data for a packet from the hardware once
545
// memory buffers have been allocated for the packet.  Note that the buffers
546
// may come in pieces, using a scatter-gather list.  This allows for more
547
// efficient processing in the upper layers of the stack.
548
//
549
static void
550
dp83902a_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
551
{
552
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)sc->driver_private;
553
    cyg_uint8 *base = dp->base;
554
    int i, mlen, len;
555
    unsigned char *data;
556
    cyg_uint8 saved_char = 0;
557
    bool saved;
558
#if DEBUG & 4
559
    int dx;
560
#endif
561
 
562
    DEBUG_FUNCTION();
563
 
564
    // Compute total packet length
565
    len = 0;
566
    for (i = 0;  i < sg_len;  i++) {
567
        len += sg_list[i].len;
568
    }
569
 
570
#if DEBUG & 5
571
    diag_printf("Rx packet %d length %d\n", dp->rx_next, len);
572
#endif
573
 
574
    CR_UP();
575
 
576
    // Read incoming packet data
577
    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
578
    DP_OUT(base, DP_RBCL, len & 0xFF);
579
    DP_OUT(base, DP_RBCH, len >> 8);
580
    DP_OUT(base, DP_RSAL, 4);           // Past header
581
    DP_OUT(base, DP_RSAH, dp->rx_next);
582
    DP_OUT(base, DP_ISR, DP_ISR_RDC); // Clear end of DMA
583
    DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
584
 
585
    saved = false;
586
    for (i = 0;  i < sg_len;  i++) {
587
        data = (unsigned char *)sg_list[i].buf;
588
        if (data) {
589
            mlen = sg_list[i].len;
590
#if DEBUG & 4
591
            diag_printf(" sg buf %08x len %08x \n", data, mlen);
592
            dx = 0;
593
#endif
594
            while (0 < mlen) {
595
                // Saved byte from previous loop?
596
                if (saved) {
597
                    *data++ = saved_char;
598
                    mlen--;
599
                    saved = false;
600
                    continue;
601
                }
602
 
603
#ifdef CYGHWR_NS_DP83902A_PLF_16BIT_DATA
604
                {
605
                    cyg_uint16 tmp;
606
                    DP_IN_DATA(dp->data, tmp);
607
#if DEBUG & 4
608
                    diag_printf(" %04x", tmp);
609
                    if (0 == (++dx % 8)) diag_printf("\n ");
610
#endif
611
                    *data++ = (tmp >> 8) & 0xff;
612
                    mlen--;
613
                    if (0 == mlen) {
614
                        saved_char = tmp & 0xff;
615
                        saved = true;
616
                    } else {
617
                        *data++ = tmp & 0xff;
618
                        mlen--;
619
                    }
620
                }
621
#else
622
                {
623
                    cyg_uint8 tmp;
624
                    DP_IN_DATA(dp->data, tmp);
625
#if DEBUG & 4
626
                    diag_printf(" %02x", tmp);
627
                    if (0 == (++dx % 16)) diag_printf("\n ");
628
#endif
629
                    *data++ = tmp;;
630
                    mlen--;
631
                }
632
#endif
633
            }
634
#if DEBUG & 4
635
            diag_printf("\n");
636
#endif
637
        }
638
    }
639
    CR_DOWN();
640
}
641
 
642
static void
643
dp83902a_TxEvent(struct eth_drv_sc *sc)
644
{
645
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)sc->driver_private;
646
    cyg_uint8 *base = dp->base;
647
    unsigned char tsr;
648
    unsigned long key;
649
 
650
    DEBUG_FUNCTION();
651
 
652
    DP_IN(base, DP_TSR, tsr);
653
    if (dp->tx_int == 1) {
654
        key = dp->tx1_key;
655
        dp->tx1 = 0;
656
    } else {
657
        key = dp->tx2_key;
658
        dp->tx2 = 0;
659
    }
660
    // Start next packet if one is ready
661
    dp->tx_started = false;
662
    if (dp->tx1) {
663
        dp83902a_start_xmit(sc, dp->tx1, dp->tx1_len);
664
        dp->tx_int = 1;
665
    } else if (dp->tx2) {
666
        dp83902a_start_xmit(sc, dp->tx2, dp->tx2_len);
667
        dp->tx_int = 2;
668
    } else {
669
        dp->tx_int = 0;
670
    }
671
    // Tell higher level we sent this packet
672
    (sc->funs->eth_drv->tx_done)(sc, key, 0);
673
}
674
 
675
// Read the tally counters to clear them.  Called in response to a CNT
676
// interrupt.
677
static void
678
dp83902a_ClearCounters(struct eth_drv_sc *sc)
679
{
680
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)sc->driver_private;
681
    cyg_uint8 *base = dp->base;
682
    cyg_uint8 cnt1, cnt2, cnt3;
683
 
684
    DP_IN(base, DP_FER, cnt1);
685
    DP_IN(base, DP_CER, cnt2);
686
    DP_IN(base, DP_MISSED, cnt3);
687
    DP_OUT(base, DP_ISR, DP_ISR_CNT);
688
}
689
 
690
// Deal with an overflow condition.  This code follows the procedure set
691
// out in section 7.0 of the datasheet.
692
static void
693
dp83902a_Overflow(struct eth_drv_sc *sc)
694
{
695
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)sc->driver_private;
696
    cyg_uint8 *base = dp->base;
697
    cyg_uint8 isr;
698
 
699
    // Issue a stop command and wait 1.6ms for it to complete.
700
    CR_UP();
701
    DP_OUT(base, DP_CR, DP_CR_STOP | DP_CR_NODMA);
702
    CYGACC_CALL_IF_DELAY_US(1600);
703
 
704
    // Clear the remote byte counter registers.
705
    DP_OUT(base, DP_RBCL, 0);
706
    DP_OUT(base, DP_RBCH, 0);
707
 
708
    // Enter loopback mode while we clear the buffer.
709
    DP_OUT(base, DP_TCR, DP_TCR_LOCAL);
710
    DP_OUT(base, DP_CR, DP_CR_START | DP_CR_NODMA);
711
    CR_DOWN();
712
 
713
    // Read in as many packets as we can and acknowledge any and receive
714
    // interrupts.  Since the buffer has overflowed, a receive event of
715
    // some kind will have occured.
716
    dp83902a_RxEvent(sc);
717
    DP_OUT(base, DP_ISR, DP_ISR_RxP|DP_ISR_RxE);
718
 
719
    // Clear the overflow condition and leave loopback mode.
720
    DP_OUT(base, DP_ISR, DP_ISR_OFLW);
721
    DP_OUT(base, DP_TCR, DP_TCR_NORMAL);
722
 
723
    // If a transmit command was issued, but no transmit event has occured,
724
    // restart it here.
725
    DP_IN(base, DP_ISR, isr);
726
    if (dp->tx_started && !(isr & (DP_ISR_TxP|DP_ISR_TxE))) {
727
        CR_UP();
728
        DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START);
729
        CR_DOWN();
730
    }
731
}
732
 
733
static void
734
dp83902a_poll(struct eth_drv_sc *sc)
735
{
736
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)sc->driver_private;
737
    cyg_uint8 *base = dp->base;
738
    unsigned char isr;
739
 
740
//    DEBUG_FUNCTION();
741
 
742
    CR_UP();
743
    DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0 | DP_CR_START);
744
    CR_DOWN();
745
    DP_IN(base, DP_ISR, isr);
746
    while (0 != isr) {
747
        // The CNT interrupt triggers when the MSB of one of the error
748
        // counters is set.  We don't much care about these counters, but
749
        // we should read their values to reset them.
750
        if (isr & DP_ISR_CNT) {
751
            dp83902a_ClearCounters(sc);
752
        }
753
        // Check for overflow.  It's a special case, since there's a
754
        // particular procedure that must be followed to get back into
755
        // a running state.
756
        if (isr & DP_ISR_OFLW) {
757
            dp83902a_Overflow(sc);
758
        } else {
759
            // Other kinds of interrupts can be acknowledged simply by
760
            // clearing the relevant bits of the ISR.  Do that now, then
761
            // handle the interrupts we care about.
762
            DP_OUT(base, DP_ISR, isr);      // Clear set bits
763
            if (!dp->running) break;        // Is this necessary?
764
            // Check for tx_started on TX event since these may happen
765
            // spuriously it seems.
766
            if (isr & (DP_ISR_TxP|DP_ISR_TxE) && dp->tx_started) {
767
                dp83902a_TxEvent(sc);
768
            }
769
            if (isr & (DP_ISR_RxP|DP_ISR_RxE)) {
770
                dp83902a_RxEvent(sc);
771
            }
772
        }
773
        DP_IN(base, DP_ISR, isr);
774
    }
775
 
776
    CYGHWR_NS_DP83902A_PLF_INT_CLEAR(dp);
777
}
778
 
779
static int
780
dp83902a_int_vector(struct eth_drv_sc *sc)
781
{
782
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)sc->driver_private;
783
    return dp->interrupt;
784
}

powered by: WebSVN 2.1.0

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