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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [eth/] [davicom/] [dm9000/] [current/] [src/] [if_dm9000.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      if_dm9000.c
4
//
5
//      Davicom DM9000 ethernet driver
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 2003, 2004 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
//#####DESCRIPTIONBEGIN####
40
//
41
// Author(s):    msalter
42
// Contributors: msalter
43
// Date:         2004-03-18
44
// Purpose:      
45
// Description:  hardware driver for Davicom DM9000 NIC
46
// Notes:
47
//
48
//####DESCRIPTIONEND####
49
//
50
//==========================================================================
51
 
52
#include <pkgconf/system.h>
53
#include <pkgconf/io_eth_drivers.h>
54
#include <pkgconf/devs_eth_davicom_dm9000.h>
55
 
56
#include <cyg/infra/cyg_type.h>
57
#include <cyg/infra/cyg_ass.h>
58
#include <cyg/hal/hal_arch.h>
59
#include <cyg/hal/hal_cache.h>
60
#include <cyg/hal/hal_intr.h>
61
#include <cyg/hal/hal_endian.h>
62
#include <cyg/infra/diag.h>
63
#include <cyg/hal/hal_if.h>
64
#include <cyg/hal/drv_api.h>
65
#include <cyg/io/eth/netdev.h>
66
#include <cyg/io/eth/eth_drv.h>
67
 
68
#include <dm9000_info.h>
69
 
70
#ifdef CYGPKG_REDBOOT
71
#include <pkgconf/redboot.h>
72
#include <redboot.h>
73
#include <flash_config.h>
74
#endif
75
 
76
#include CYGDAT_DEVS_ETH_DAVICOM_DM9000_INL
77
 
78
#define DM9000_PKT_MAX 1536
79
 
80
//#define DEBUG
81
//#define DEBUG_DUMP
82
 
83
//
84
// Control and Status register offsets
85
//
86
#define DM_NCR      0x00
87
#define DM_NSR      0x01
88
#define DM_TCR      0x02
89
#define DM_TSRI     0x03
90
#define DM_TSRII    0x04
91
#define DM_RCR      0x05
92
#define DM_RSR      0x06
93
#define DM_ROCR     0x07
94
#define DM_BPTR     0x08
95
#define DM_FCTR     0x09
96
#define DM_FCR      0x0a
97
#define DM_EPCR     0x0b
98
#define DM_EPAR     0x0c
99
#define DM_EPDRL    0x0d
100
#define DM_EPDRH    0x0e
101
#define DM_WCR      0x0f
102
#define DM_PAR      0x10
103
#define DM_MAR      0x16
104
#define DM_GPCR     0x1e
105
#define DM_GPR      0x1f
106
#define DM_TRPAL    0x22
107
#define DM_TRPAH    0x23
108
#define DM_RWPAL    0x24
109
#define DM_RWPAH    0x25
110
#define DM_VIDL     0x28
111
#define DM_VIDH     0x29
112
#define DM_PIDL     0x2a
113
#define DM_PIDH     0x2b
114
#define DM_CHIPR    0x2c
115
#define DM_SMCR     0x2f
116
#define DM_MRCMDX   0xf0
117
#define DM_MRCMD    0xf2
118
#define DM_MDRAL    0xf4
119
#define DM_MDRAH    0xf5
120
#define DM_MWCMDX   0xf6
121
#define DM_MWCMD    0xf8
122
#define DM_MDWAL    0xfa
123
#define DM_MDWAH    0xfb
124
#define DM_TXPLL    0xfc
125
#define DM_TXPLH    0xfd
126
#define DM_ISR      0xfe
127
#define DM_IMR      0xff
128
 
129
// NCR (Network Control Register)
130
#define NCR_EXT_PHY   (1 << 7)     // 1 ==> external PHY, 0 ==> internal
131
#define NCR_WAKEEN    (1 << 6)     // enable wakeup events
132
#define NCR_FCOL      (1 << 4)     // force collision mode (test)
133
#define NCR_FDX       (1 << 3)     // full duplex (read-only for internal phy)
134
#define NCR_LBK_NOR   (0 << 1)     // loopback off
135
#define NCR_LBK_MAC   (1 << 1)     // MAC loopback
136
#define NCR_LBK_PHY   (2 << 1)     // PHY loopback
137
#define NCR_RST       (1 << 0)     // Reset (auto-clears after 10us)
138
 
139
// NSR (Network Status Register)
140
#define NSR_SPEED     (1 << 7)     // 0 = 100Mbps, 1 = 10Mbps
141
#define NSR_LINKST    (1 << 6)     // link status (1 = okay)
142
#define NSR_WAKEST    (1 << 5)     // wake status (clear by read)
143
#define NSR_TX2END    (1 << 3)     // TX packet 2 complete
144
#define NSR_TX1END    (1 << 2)     // TX packet 1 complete
145
#define NSR_RXOV      (1 << 1)     // RX overflow
146
 
147
// TCR (TX Control Register)
148
#define TCR_TJDIS     (1 << 6)     // TX jabber disable
149
#define TCR_EXCECM    (1 << 5)     // 0 = abort after 15 collisions
150
#define TCR_PAD_DIS2  (1 << 4)
151
#define TCR_CRC_DIS2  (1 << 3)
152
#define TCR_PAD_DIS1  (1 << 2)
153
#define TCR_CRC_DIS1  (1 << 1)
154
#define TCR_TXREQ     (1 << 0)
155
 
156
// TSR (TX Status Register)
157
#define TSR_TJTO      (1 << 7)
158
#define TSR_LC        (1 << 6)
159
#define TSR_NC        (1 << 5)
160
#define TSR_LCOL      (1 << 4)
161
#define TSR_COL       (1 << 3)
162
#define TSR_EC        (1 << 2)
163
 
164
// RCR (RX Control Register)
165
#define RCR_WTDIS     (1 << 6)
166
#define RCR_DIS_LONG  (1 << 5)
167
#define RCR_DIS_CRC   (1 << 4)
168
#define RCR_ALL       (1 << 3)
169
#define RCR_RUNT      (1 << 2)
170
#define RCR_PRMSC     (1 << 1)
171
#define RCR_RXEN      (1 << 0)
172
 
173
// RSR (RX Status Register)
174
#define RSR_RF        (1 << 7)
175
#define RSR_MF        (1 << 6)
176
#define RSR_LCS       (1 << 5)
177
#define RSR_RWTO      (1 << 4)
178
#define RSR_PLE       (1 << 3)
179
#define RSR_AE        (1 << 2)
180
#define RSR_CE        (1 << 1)
181
#define RSR_FOE       (1 << 0)
182
 
183
// FCR (Flow Control Register)
184
#define FCR_TXPO      (1 << 7)
185
#define FCR_TXPF      (1 << 6)
186
#define FCR_TXPEN     (1 << 5)
187
#define FCR_BKPA      (1 << 4)
188
#define FCR_BKPM      (1 << 3)
189
#define FCR_RXPS      (1 << 2)
190
#define FCR_RXPCS     (1 << 1)
191
#define FCR_FLCE      (1 << 0)
192
 
193
// EPCR (EEPROM & PHY Control Register)
194
#define EPCR_REEP     (1 << 5)
195
#define EPCR_WEP      (1 << 4)
196
#define EPCR_EPOS     (1 << 3)
197
#define EPCR_ERPRR    (1 << 2)
198
#define EPCR_ERPRW    (1 << 1)
199
#define EPCR_ERRE     (1 << 0)
200
 
201
// WCR (Wakeup Control Register)
202
#define WCR_LINKEN    (1 << 5)
203
#define WCR_SAMPLEEN  (1 << 4)
204
#define WCR_MAGICEN   (1 << 3)
205
#define WCR_LINKST    (1 << 2)
206
#define WCR_SAMPLEST  (1 << 1)
207
#define WCR_MAGIGST   (1 << 0)
208
 
209
// SMCR (Special Mode Control Register)
210
#define SMCR_SM_EN    (1 << 7)
211
#define SMCR_FLC      (1 << 2)
212
#define SMCR_FB1      (1 << 1)
213
#define SMCR_FB0      (1 << 0)
214
 
215
// ISR (Interrupt Status Register)
216
#define ISR_IOMODE_16 (0 << 6)
217
#define ISR_IOMODE_32 (1 << 6)
218
#define ISR_IOMODE_8  (2 << 6)
219
#define ISR_ROOS      (1 << 3)
220
#define ISR_ROS       (1 << 2)
221
#define ISR_PTS       (1 << 1)
222
#define ISR_PRS       (1 << 0)
223
 
224
// IMR (Interrupt Mask Register)
225
#define IMR_PAR       (1 << 7)
226
#define IMR_ROOM      (1 << 3)
227
#define IMR_ROM       (1 << 2)
228
#define IMR_PTM       (1 << 1)
229
#define IMR_PRM       (1 << 0)
230
 
231
/* PHY registers */
232
#define PHY_BMCR      0x00
233
#define PHY_BMSR      0x01
234
#define PHY_ANAR      0x04
235
 
236
/* PHY BMCR (Basic Mode Control Register) */
237
#define PHY_BMCR_AUTO_NEG_EN    (1 << 12)
238
#define PHY_BMCR_AUTO_NEG_START (1 << 12)
239
 
240
/* PHY BMSR (Basic Mode Status Register) */
241
#define PHY_BMSR_AUTO_NEG_COMPLETE (1 << 5)
242
 
243
// Read one datum from 8-bit bus
244
static int read_data_8(struct dm9000 *p, cyg_uint8 *dest)
245
{
246
    HAL_READ_UINT8(p->io_data, *dest);
247
    return 1;
248
}
249
 
250
// Read one datum from 16-bit bus 
251
static int read_data_16(struct dm9000 *p, cyg_uint8 *dest)
252
{
253
    cyg_uint16 val;
254
 
255
    HAL_READ_UINT16(p->io_data, val);
256
    memcpy(dest, &val, 2);
257
    return 2;
258
}
259
 
260
// Read one datum from 32-bit bus 
261
static int read_data_32(struct dm9000 *p, cyg_uint8 *dest)
262
{
263
    cyg_uint32 val;
264
 
265
    HAL_READ_UINT32(p->io_data, val);
266
    memcpy(dest, &val, 4);
267
    return 4;
268
}
269
 
270
 
271
// Write one datum to 8-bit bus
272
static int write_data_8(struct dm9000 *p, cyg_uint8 *src)
273
{
274
    HAL_WRITE_UINT8(p->io_data, *src);
275
    return 1;
276
}
277
 
278
// Write one datum to 16-bit bus 
279
static int write_data_16(struct dm9000 *p, cyg_uint8 *src)
280
{
281
    cyg_uint16 val;
282
 
283
    memcpy(&val, src, 2);
284
    HAL_WRITE_UINT16(p->io_data, val);
285
    return 2;
286
}
287
 
288
// Write one datum to 32-bit bus 
289
static int write_data_32(struct dm9000 *p, cyg_uint8 *src)
290
{
291
    cyg_uint32 val;
292
 
293
    memcpy(&val, src, 4);
294
    HAL_WRITE_UINT32(p->io_data, val);
295
    return 4;
296
}
297
 
298
 
299
 
300
// Return one byte from DM9000 register
301
static cyg_uint8 getreg(struct dm9000 *p, cyg_uint8 reg)
302
{
303
    cyg_uint8 val;
304
    HAL_WRITE_UINT8(p->io_addr, reg);
305
    HAL_READ_UINT8(p->io_data, val);
306
    return val;
307
}
308
 
309
// Write one byte to DM9000 register
310
static void putreg(struct dm9000 *p, cyg_uint8 reg, cyg_uint8 val)
311
{
312
    HAL_WRITE_UINT8(p->io_addr, reg);
313
    HAL_WRITE_UINT8(p->io_data, val);
314
}
315
 
316
// Read a word from EEPROM
317
static cyg_uint16 eeprom_read(struct dm9000 *p, int offset)
318
{
319
    putreg(p, DM_EPAR, offset);
320
    putreg(p, DM_EPCR, EPCR_ERPRR);
321
    while (getreg(p, DM_EPCR) & EPCR_ERRE)
322
        ;
323
    CYGACC_CALL_IF_DELAY_US(8000);
324
    putreg(p, DM_EPCR, 0);
325
    return getreg(p, DM_EPDRL) | (getreg(p, DM_EPDRH) << 8);
326
}
327
 
328
// Write a word to EEPROM
329
static void eeprom_write(struct dm9000 *p, int offset, cyg_uint16 val)
330
{
331
    putreg(p, DM_EPAR, offset);
332
    putreg(p, DM_EPDRH, val >> 8);
333
    putreg(p, DM_EPDRL, val);
334
    putreg(p, DM_EPCR, EPCR_WEP | EPCR_ERPRW);
335
    while (getreg(p, DM_EPCR) & EPCR_ERRE)
336
        ;
337
    CYGACC_CALL_IF_DELAY_US(8000);
338
    putreg(p, DM_EPCR, 0);
339
}
340
 
341
// Reload info from EEPROM
342
static void eeprom_reload(struct dm9000 *p)
343
{
344
    putreg(p, DM_EPCR, EPCR_REEP);
345
    while (getreg(p, DM_EPCR) & EPCR_ERRE)
346
        ;
347
    CYGACC_CALL_IF_DELAY_US(8000);
348
    putreg(p, DM_EPCR, 0);
349
}
350
 
351
 
352
// Read a word from PHY
353
static cyg_uint16 phy_read(struct dm9000 *p, int offset)
354
{
355
    putreg(p, DM_EPAR, 0x40 + offset);
356
    putreg(p, DM_EPCR, EPCR_EPOS | EPCR_ERPRR);
357
    CYGACC_CALL_IF_DELAY_US(200);
358
    putreg(p, DM_EPCR, 0);
359
    return getreg(p, DM_EPDRL) | (getreg(p, DM_EPDRH) << 8);
360
}
361
 
362
// Write a word to PHY
363
static void phy_write(struct dm9000 *p, int offset, cyg_uint16 val)
364
{
365
    putreg(p, DM_EPAR, 0x40 + offset);
366
    putreg(p, DM_EPDRL, val);
367
    putreg(p, DM_EPDRH, val >> 8);
368
    putreg(p, DM_EPCR, EPCR_EPOS | EPCR_ERPRW);
369
    CYGACC_CALL_IF_DELAY_US(500);
370
    putreg(p, DM_EPCR, 0);
371
}
372
 
373
 
374
static void init_phy(struct dm9000 *p)
375
{
376
    int t = 0;
377
    cyg_uint16 r;
378
 
379
    /* power on PHY */
380
    putreg(p, DM_GPCR, 0x01);
381
    putreg(p, DM_GPR,  0x00);
382
 
383
    phy_write(p, PHY_ANAR, 0x1e1); // Advertise 10/100 half/full duplex w/CSMA
384
    phy_write(p, PHY_BMCR, PHY_BMCR_AUTO_NEG_EN | PHY_BMCR_AUTO_NEG_START);
385
 
386
    /* wait for autonegotiation to complete */
387
    do {
388
        CYGACC_CALL_IF_DELAY_US(1000);
389
        r = phy_read(p, PHY_BMSR);
390
    } while (!(r & PHY_BMSR_AUTO_NEG_COMPLETE) && t++ < 2000);
391
}
392
 
393
 
394
static inline void dm9000_reset(struct dm9000 *p)
395
{
396
    putreg(p, DM_NCR, NCR_RST);
397
    CYGACC_CALL_IF_DELAY_US(100);
398
}
399
 
400
static int initialize_nic(struct dm9000 *priv)
401
{
402
    int i;
403
 
404
    dm9000_reset(priv);
405
 
406
    switch (getreg(priv, DM_ISR) >> 6) {
407
    case 0:
408
        priv->read_data = read_data_16;
409
        priv->write_data = write_data_16;
410
        priv->buswidth = 2;
411
        break;
412
    case 1:
413
        priv->read_data = read_data_32;
414
        priv->write_data = write_data_32;
415
        priv->buswidth = 4;
416
        break;
417
    case 2:
418
        priv->read_data = read_data_8;
419
        priv->write_data = write_data_8;
420
        priv->buswidth = 1;
421
        break;
422
    default:
423
        diag_printf("Unknown DM9000 bus i/f.\n");
424
        return 0;
425
    }
426
 
427
    init_phy(priv);
428
 
429
    putreg(priv, DM_TCR, 0);
430
    putreg(priv, DM_BPTR, 0x3f);
431
    putreg(priv, DM_FCTR, 0x38);
432
    putreg(priv, DM_FCR, 0xff);
433
    putreg(priv, DM_SMCR, 0);
434
    putreg(priv, DM_NSR, NSR_WAKEST | NSR_TX1END | NSR_TX2END);
435
    putreg(priv, DM_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);
436
 
437
    // set MAC address
438
    for (i = 0; i < 6; i++)
439
        putreg(priv, DM_PAR + i, priv->mac_address[i]);
440
 
441
    // clear multicast table except for broadcast address
442
    for (i = 0; i < 6; i++)
443
        putreg(priv, DM_MAR + i, 0x00);
444
    putreg(priv, DM_MAR + 6, 0x00);
445
    putreg(priv, DM_MAR + 7, 0x80);
446
 
447
    return 1;
448
}
449
 
450
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
451
static cyg_uint32 dm9000_isr(cyg_vector_t vector, cyg_addrword_t data)
452
{
453
    struct eth_drv_sc *sc = (struct eth_drv_sc *)data;
454
    struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
455
 
456
    cyg_drv_interrupt_mask(priv->interrupt);
457
    cyg_drv_interrupt_acknowledge(priv->interrupt);
458
 
459
    return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR;
460
}
461
#endif
462
 
463
 
464
// ------------------------------------------------------------------------
465
//
466
//  API Function : dm9000_init
467
//
468
// ------------------------------------------------------------------------
469
static bool
470
dm9000_init(struct cyg_netdevtab_entry * ndp)
471
{
472
    struct eth_drv_sc *sc;
473
    struct dm9000 *priv;
474
    int i;
475
    unsigned id;
476
    unsigned short u16tab[64];
477
 
478
    sc = (struct eth_drv_sc *)ndp->device_instance;
479
    priv = (struct dm9000 *)sc->driver_private;
480
 
481
    priv->sc = sc;
482
 
483
#ifdef CYG_HAL_DM9000_PRESENT
484
    if (!CYG_HAL_DM9000_PRESENT())
485
        return 0;
486
#endif
487
 
488
    id = getreg(priv, DM_VIDL);
489
    id |= getreg(priv, DM_VIDH) << 8;
490
    id |= getreg(priv, DM_PIDL) << 16;
491
    id |= getreg(priv, DM_PIDH) << 24;
492
 
493
    if (id != 0x90000A46)
494
        return 0;
495
 
496
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
497
    cyg_drv_interrupt_create(priv->interrupt,
498
                             0,
499
                             (cyg_addrword_t)sc,
500
                             dm9000_isr,
501
                             eth_drv_dsr,
502
                             &priv->interrupt_handle,
503
                             &priv->interrupt_object);
504
    cyg_drv_interrupt_attach(priv->interrupt_handle);
505
    cyg_drv_interrupt_acknowledge(priv->interrupt);
506
    cyg_drv_interrupt_unmask(priv->interrupt);
507
#endif // !CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
508
 
509
    for (i = 0; i < 64; i++)
510
        u16tab[i] = eeprom_read(priv, i);
511
 
512
    u16tab[3] &= ~0xc;
513
    u16tab[3] |= 4;
514
    u16tab[6] &= 0xfe00;
515
    u16tab[6] |= 6;
516
 
517
#if 0
518
    eeprom_write(priv, 6, u16tab[6]);
519
    eeprom_write(priv, 3, u16tab[3]);
520
#endif
521
 
522
    eeprom_reload(priv);
523
 
524
    do {
525
        for (i = 0; i < 64; i++)
526
            u16tab[i] = eeprom_read(priv, i);
527
    } while ((u16tab[0] | u16tab[1] | u16tab[2]) == 0);
528
 
529
    priv->mac_address[0] = u16tab[0];
530
    priv->mac_address[1] = u16tab[0] >> 8;
531
    priv->mac_address[2] = u16tab[1];
532
    priv->mac_address[3] = u16tab[1] >> 8;
533
    priv->mac_address[4] = u16tab[2];
534
    priv->mac_address[5] = u16tab[2] >> 8;
535
 
536
    if (!initialize_nic(priv))
537
        return 0;
538
 
539
    // Initialize upper level driver
540
    (sc->funs->eth_drv->init)(sc, &(priv->mac_address[0]) );
541
    return 1;
542
}
543
 
544
// ------------------------------------------------------------------------
545
//
546
//  API Function : dm9000_start
547
//
548
// ------------------------------------------------------------------------
549
static void
550
dm9000_start( struct eth_drv_sc *sc, unsigned char *enaddr, int flags )
551
{
552
    struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
553
 
554
    // turn on receiver
555
    putreg(priv, DM_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
556
 
557
    // unmask interrupt
558
    putreg(priv, DM_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
559
 
560
    priv->active = 1;
561
}
562
 
563
// ------------------------------------------------------------------------
564
//
565
//  API Function : dm9000_stop
566
//
567
// ------------------------------------------------------------------------
568
static void
569
dm9000_stop( struct eth_drv_sc *sc )
570
{
571
    struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
572
 
573
    // turn on receiver
574
    putreg(priv, DM_RCR, 0);
575
 
576
    // mask interrupts
577
    putreg(priv, DM_IMR, IMR_PAR);
578
 
579
    priv->active = 0;
580
}
581
 
582
 
583
// ------------------------------------------------------------------------
584
//
585
//  API Function : dm9000_recv
586
//
587
// ------------------------------------------------------------------------
588
static void
589
dm9000_recv( struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len )
590
{
591
    struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
592
    struct eth_drv_sg *sg = sg_list;
593
    cyg_uint8   tmpbuf[4];
594
    char *p;
595
    int len, total_len, nread, n, leftover;
596
 
597
    total_len = priv->rxlen;
598
    nread = leftover = 0;
599
 
600
//    diag_printf("dm9000_recv: total_len=%d\n", total_len);
601
 
602
    do {
603
        p = (char *)sg->buf;
604
        len = sg->len;
605
 
606
//      diag_printf("recv: buf=%p len=%d to_read=%d, leftover=%d\n", p, len, total_len - nread, leftover);
607
 
608
        if ((nread + len) > total_len)
609
            len = total_len - nread;
610
 
611
        if (leftover) {
612
            if (leftover <= len) {
613
                memcpy(p, tmpbuf + (sizeof(tmpbuf) - leftover), leftover);
614
                p += leftover;
615
                len -= leftover;
616
                nread += leftover;
617
                leftover = 0;
618
            } else {
619
                memcpy(p, tmpbuf + (sizeof(tmpbuf) - leftover), len);
620
                leftover -= len;
621
                p += len;
622
                nread += len;
623
                len = 0;
624
            }
625
        }
626
 
627
        while (len >= sizeof(tmpbuf)) {
628
            n = priv->read_data(priv, p);
629
            nread += n;
630
            len -= n;
631
            p += n;
632
        }
633
 
634
        while (len > 0) {
635
            n = priv->read_data(priv, tmpbuf);
636
            if (n <= len) {
637
                memcpy(p, tmpbuf, n);
638
                len -= n;
639
                nread += n;
640
                p += n;
641
            } else {
642
                memcpy(p, tmpbuf, len);
643
                nread += len;
644
                leftover = n - len;
645
                len = 0;
646
            }
647
        }
648
 
649
        ++sg;
650
    } while (nread < total_len);
651
 
652
#ifdef DEBUG_DUMP
653
    for (sg = sg_list; sg < (sg_list + sg_len); sg++) {
654
        diag_printf("\n");
655
        diag_dump_buf(sg->buf, sg->len);
656
    }
657
#endif
658
}
659
 
660
// ------------------------------------------------------------------------
661
//
662
//  API Function : dm9000_can_send
663
//
664
// ------------------------------------------------------------------------
665
static int
666
dm9000_can_send(struct eth_drv_sc *sc)
667
{
668
    struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
669
 
670
    if (!priv->active || priv->txbusy || priv->reset_pending)
671
        return 0;
672
 
673
    return 1;
674
}
675
 
676
 
677
// ------------------------------------------------------------------------
678
//
679
//  API Function : dm9000_send
680
//
681
// ------------------------------------------------------------------------
682
static void
683
dm9000_send(struct eth_drv_sc *sc,
684
            struct eth_drv_sg *sg_list, int sg_len,
685
            int total_len, unsigned long key)
686
{
687
    struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
688
    struct eth_drv_sg *sg;
689
    cyg_uint8 tmpbuf[4];
690
    int i, len, n, save_len, tail_extra;
691
    char *p;
692
 
693
#ifdef DEBUG
694
    diag_printf("dm9000_send: NCR[%02x] NSR[%02x] TRPA[%04x]\n",
695
                getreg(priv, DM_NCR), getreg(priv, DM_NSR),
696
                getreg(priv, DM_TRPAL) | (getreg(priv, DM_TRPAH) << 8)
697
        );
698
#endif
699
#ifdef DEBUG_DUMP
700
    for (sg = sg_list; sg < (sg_list + sg_len); sg++) {
701
        diag_printf("\n");
702
        diag_dump_buf(sg->buf, sg->len);
703
    }
704
#endif
705
 
706
    priv->txbusy = 1;
707
 
708
    sg = sg_list;
709
    save_len = total_len;
710
    tail_extra = 0;
711
 
712
    /* Disable all interrupts */
713
    putreg(priv, DM_IMR, IMR_PAR);
714
 
715
    HAL_WRITE_UINT8(priv->io_addr, DM_MWCMD);
716
 
717
    while (total_len > 0) {
718
        len = sg->len;
719
        if (len > total_len)
720
            len = total_len;
721
        p = (char *)sg->buf;
722
 
723
        /* write any left over partial words by combining them with the start
724
         * of this sg block */
725
        if (tail_extra) {
726
            int head_extra = sizeof(tmpbuf) - tail_extra;
727
            memcpy(tmpbuf + tail_extra, p, head_extra);
728
            p += head_extra;
729
            len -= head_extra;
730
            for (i = 0; i < sizeof(tmpbuf) && total_len > 0; i += n) {
731
                n = priv->write_data(priv, tmpbuf + i);
732
                total_len -= n;
733
            }
734
            tail_extra = 0;
735
        }
736
 
737
        /* write out whole words */
738
        while (len >= priv->buswidth) {
739
            n = priv->write_data(priv, p);
740
            len -= n;
741
            total_len -= n;
742
            p += n;
743
        }
744
 
745
        /* if we have some left over partial words... */
746
        if (len > 0) {
747
            /* combine them with the next sg block if available */
748
            if (total_len > len ) {
749
                tail_extra = len;
750
                memcpy(tmpbuf, p, tail_extra);
751
            } else {
752
                /* otherwise just write this last partial word */
753
                n = priv->write_data(priv, p);
754
                total_len -= n;
755
            }
756
        }
757
        sg++;
758
    }
759
 
760
    priv->txkey = key;
761
 
762
    putreg(priv, DM_TXPLL, save_len);
763
    putreg(priv, DM_TXPLH, save_len >> 8);
764
 
765
    putreg(priv, DM_TCR, TCR_TXREQ);
766
 
767
    /* Re-enable interrupt */
768
    putreg(priv, DM_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
769
}
770
 
771
// ------------------------------------------------------------------------
772
//
773
//  API Function : dm9000_poll
774
//
775
// ------------------------------------------------------------------------
776
static void
777
dm9000_poll(struct eth_drv_sc *sc)
778
{
779
    struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
780
    cyg_uint8 status, rxstat;
781
    cyg_uint16 pkt_stat, pkt_len;
782
    int i;
783
 
784
    // mask interrupts
785
    putreg(priv, DM_IMR, IMR_PAR);
786
 
787
    // get and clear staus
788
    status = getreg(priv, DM_ISR);
789
    putreg(priv, DM_ISR, status);
790
 
791
    // check for rx done
792
    if (1 /*status & ISR_PRS*/) {
793
        cyg_uint8 hdr[4]; /* 4 byte Rx pkt hdr */
794
 
795
        getreg(priv, DM_MRCMDX); /* dummy read */
796
 
797
        HAL_READ_UINT8(priv->io_data, rxstat);
798
 
799
        // check for packet ready
800
        if (rxstat == 1) {
801
            HAL_WRITE_UINT8(priv->io_addr, DM_MRCMD);
802
            for (i = 0; i < 4;)
803
                i += priv->read_data(priv, hdr + i);
804
 
805
            pkt_stat = hdr[0] | (hdr[1] << 8);
806
            pkt_len  = hdr[2] | (hdr[3] << 8);
807
 
808
#ifdef DEBUG
809
            diag_printf("pkt_stat=%04x pkt_len=%04x\n", pkt_stat, pkt_len);
810
#endif
811
 
812
            if (pkt_len < 0x40) {
813
                diag_printf("packet too short: %d (0x%04x)\n", pkt_len, pkt_len);
814
                i = 0;
815
                while (i < pkt_len)
816
                    i += priv->read_data(priv, hdr);
817
            } else if (pkt_len > 1536) {
818
                priv->reset_pending = 1;
819
                diag_printf("packet too long: %d (0x%04x)\n", pkt_len, pkt_len);
820
            } else if (pkt_stat & 0xbf00) {
821
                diag_printf("bad packet status: 0x%04x\n", pkt_stat);
822
                i = 0;
823
                while (i < pkt_len)
824
                    i += priv->read_data(priv, hdr);
825
            } else {
826
                // receive packet
827
                priv->rxlen = pkt_len;
828
                (sc->funs->eth_drv->recv)(sc, pkt_len);
829
            }
830
 
831
        } else if (rxstat > 1) {
832
            // this should never happen.
833
            diag_printf("unknown rxstat byte: %d\n", rxstat);
834
            priv->reset_pending = 1;
835
        }
836
    }
837
 
838
 
839
    // check transmit status
840
    if (status & ISR_PTS) {
841
        cyg_uint8 txstat;
842
 
843
        txstat = getreg(priv, DM_NSR);
844
 
845
        if (txstat & (NSR_TX1END | NSR_TX2END)) {
846
            if (txstat & NSR_TX1END)
847
                txstat = getreg(priv, DM_TSRI);
848
            else
849
                txstat = getreg(priv, DM_TSRII);
850
 
851
            if (txstat & TSR_COL) {
852
                // collision
853
            }
854
 
855
            if (getreg(priv, DM_TRPAL) & 3) {
856
                // NIC bug detected. Need to reset.
857
                priv->reset_pending = 1;
858
                diag_printf("NIC collision bug detected!\n");
859
            }
860
 
861
            (sc->funs->eth_drv->tx_done)(sc, priv->txkey, 0);
862
            priv->txbusy = 0;
863
        }
864
    }
865
 
866
    if (priv->reset_pending && !priv->txbusy) {
867
        initialize_nic(priv);
868
 
869
        // turn on receiver
870
        putreg(priv, DM_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
871
 
872
        priv->reset_pending = 0;
873
    }
874
 
875
    // unmask interrupts
876
    putreg(priv, DM_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
877
}
878
 
879
 
880
// ------------------------------------------------------------------------
881
//
882
//  API Function : dm9000_deliver
883
//
884
// ------------------------------------------------------------------------
885
static void
886
dm9000_deliver(struct eth_drv_sc *sc)
887
{
888
    struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
889
 
890
    dm9000_poll(sc);
891
 
892
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
893
    cyg_drv_interrupt_unmask(priv->interrupt);
894
#endif
895
}
896
 
897
// ------------------------------------------------------------------------
898
//
899
//  API Function : dm9000_int_vector
900
//
901
// ------------------------------------------------------------------------
902
static int
903
dm9000_int_vector(struct eth_drv_sc *sc)
904
{
905
    struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
906
 
907
    return priv->interrupt;
908
}
909
 
910
 
911
// ------------------------------------------------------------------------
912
//
913
//  API Function : dm9000_ioctl
914
//
915
// ------------------------------------------------------------------------
916
static int
917
dm9000_ioctl(struct eth_drv_sc *sc, unsigned long key,
918
          void *data, int data_length)
919
{
920
    struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
921
    cyg_uint8 *esa = (cyg_uint8 *)data;
922
    int i;
923
 
924
    switch (key) {
925
#ifdef ETH_DRV_GET_MAC_ADDRESS
926
    case ETH_DRV_GET_MAC_ADDRESS:
927
        memcpy(esa, priv->mac_address, sizeof(priv->mac_address));
928
        return 0;
929
#endif
930
#ifdef ETH_DRV_SET_MAC_ADDRESS
931
    case ETH_DRV_SET_MAC_ADDRESS:
932
        for (i = 0; i < sizeof(priv->mac_address);  i++) {
933
            priv->mac_address[i] = esa[i];
934
            putreg(priv, DM_PAR + i, priv->mac_address[i]);
935
        }
936
#if defined(CYGSEM_DEVS_ETH_DAVICOM_DM9000_WRITE_EEPROM)
937
        for (i = 0; i < sizeof(priv->mac_address) / 2; i++)
938
            eeprom_write(priv, i, priv->mac_address[2*i] | (priv->mac_address[2*i+1] << 8));
939
#else
940
        diag_printf("dm9000: eeprom write disabled\n");
941
#endif
942
        return 0;
943
#endif
944
    }
945
 
946
    return -1;
947
}
948
 
949
// ------------------------------------------------------------------------
950
// EOF if_dm9000.c

powered by: WebSVN 2.1.0

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