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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [eth/] [cl/] [cs8900a/] [current/] [src/] [if_cs8900a.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      dev/if_cs8900a.c
4
//
5
//      Device driver for Cirrus Logic CS8900A 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 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):    gthomas
43
// Contributors: gthomas, jskov
44
// Date:         2001-11-02
45
// Purpose:      
46
// Description:  Driver for CS8900 ethernet controller
47
//
48
// Note:         Platform can define CYGSEM_DEVS_ETH_CL_CS8900A_NOINTS
49
//               to get a timer thread polling instead of interupt based
50
//               operation.
51
//
52
// Note:         Driver will need some changes to support multiple instances
53
//
54
//####DESCRIPTIONEND####
55
//
56
//==========================================================================
57
 
58
#include <pkgconf/system.h>
59
#ifdef CYGPKG_KERNEL
60
#include <cyg/kernel/kapi.h>
61
#endif
62
#include <pkgconf/io_eth_drivers.h>
63
 
64
#include <cyg/infra/cyg_type.h>
65
#include <cyg/infra/cyg_ass.h>
66
#include <cyg/hal/hal_arch.h>
67
#include <cyg/hal/hal_intr.h>
68
#include <cyg/hal/hal_endian.h>
69
#include <cyg/infra/diag.h>
70
#include <cyg/hal/drv_api.h>
71
#undef __ECOS
72
#define __ECOS
73
#include <cyg/io/eth/eth_drv.h>
74
#include <cyg/io/eth/netdev.h>
75
 
76
#include <cyg/io/cs8900.h>
77
 
78
#define __WANT_DEVS
79
#include CYGDAT_DEVS_ETH_CL_CS8900A_INL
80
#undef __WANT_DEVS
81
 
82
// NOINTS operation only relevant when the NET package is loaded
83
#if !defined(CYGPKG_NET) || !defined(CYGPKG_KERNEL)
84
# undef CYGSEM_DEVS_ETH_CL_CS8900A_NOINTS
85
#endif
86
 
87
#ifdef CYGSEM_DEVS_ETH_CL_CS8900A_NOINTS
88
#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM
89
static char cs8900a_fake_int_stack[STACK_SIZE];
90
static cyg_thread cs8900a_fake_int_thread_data;
91
static cyg_handle_t cs8900a_fake_int_thread_handle;
92
static void cs8900a_fake_int(cyg_addrword_t);
93
#endif
94
 
95
#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
96
extern int cyg_io_eth_net_debug;
97
#endif
98
 
99
static void cs8900a_poll(struct eth_drv_sc *sc);
100
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
101
// This ISR is called when the ethernet interrupt occurs
102
static int
103
cs8900a_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
104
{
105
    cs8900a_priv_data_t* cpd = (cs8900a_priv_data_t *)data;
106
    cyg_drv_interrupt_mask(cpd->interrupt);
107
    cyg_drv_interrupt_acknowledge(cpd->interrupt);
108
    return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
109
}
110
 
111
static void
112
cs8900a_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
113
{
114
    // This conditioning out is necessary because of explicit calls to this
115
    // DSR - which would not ever be called in the case of a polled mode
116
    // usage ie. in RedBoot.
117
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
118
    cs8900a_priv_data_t* cpd = (cs8900a_priv_data_t *)data;
119
    struct cyg_netdevtab_entry *ndp = (struct cyg_netdevtab_entry *)(cpd->tab);
120
    struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance);
121
 
122
    DEBUG_FUNCTION();
123
 
124
    // but here, it must be a *sc:
125
    eth_drv_dsr( vector, count, (cyg_addrword_t)sc );
126
#else
127
# ifndef CYGPKG_REDBOOT
128
#  error Empty CS8900A ethernet DSR is compiled.  Is this what you want?
129
# endif
130
#endif
131
}
132
#endif
133
 
134
// The deliver function (ex-DSR)  handles the ethernet [logical] processing
135
static void
136
cs8900a_deliver(struct eth_drv_sc *sc)
137
{
138
    cs8900a_poll(sc);
139
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
140
    {
141
        cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
142
        // Allow interrupts to happen again
143
        cyg_drv_interrupt_unmask(cpd->interrupt);
144
    }
145
#endif
146
}
147
 
148
static int
149
cs8900a_int_vector(struct eth_drv_sc *sc)
150
{
151
    cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
152
    return (cpd->interrupt);
153
}
154
 
155
static bool
156
cs8900a_init(struct cyg_netdevtab_entry *tab)
157
{
158
    struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
159
    cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
160
    cyg_addrword_t base = cpd->base;
161
    cyg_uint16 chip_type, chip_rev, chip_status;
162
    cyg_uint16 i;
163
    long timeout = 500000;
164
    cyg_bool esa_configured = false;
165
 
166
    cpd->tab = tab;
167
 
168
    CYGHWR_CL_CS8900A_PLF_INIT(cpd);
169
 
170
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
171
# ifdef CYGSEM_DEVS_ETH_CL_CS8900A_NOINTS
172
    // The olpce2994 target uses 8-bit, non-interrupt driven mode for CS8900A.
173
    cyg_thread_create(1,                 // Priority
174
                      cs8900a_fake_int,  // entry
175
                      (cyg_addrword_t)sc,// entry parameter
176
                      "CS8900 int",      // Name
177
                      &cs8900a_fake_int_stack[0],      // Stack
178
                      STACK_SIZE,                      // Size
179
                      &cs8900a_fake_int_thread_handle, // Handle
180
                      &cs8900a_fake_int_thread_data    // Thread data structure
181
            );
182
    cyg_thread_resume(cs8900a_fake_int_thread_handle);  // Start it
183
# else
184
    // Initialize environment, setup interrupt handler
185
    cyg_drv_interrupt_create(cpd->interrupt,
186
                             cpd->priority,
187
                             (cyg_addrword_t)cpd, //  Data item passed to interrupt handler
188
                             (cyg_ISR_t *)cs8900a_isr,
189
                             (cyg_DSR_t *)cs8900a_dsr,
190
                             &cpd->interrupt_handle,
191
                             &cpd->interrupt_object);
192
    cyg_drv_interrupt_attach(cpd->interrupt_handle);
193
    cyg_drv_interrupt_acknowledge(cpd->interrupt);
194
    cyg_drv_interrupt_unmask(cpd->interrupt);
195
# endif // CYGSEM_DEVS_ETH_CL_CS8900A_NOINTS
196
#endif // CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
197
 
198
    // Read controller ID - the first is a dummy read, since (on some
199
    // platforms) the first access to the controller seems to skip the
200
    // MSB 8 bits.
201
    get_reg(base, PP_ChipID);
202
    chip_type = get_reg(base, PP_ChipID);
203
    chip_rev = get_reg(base, PP_ChipRev);
204
#if DEBUG & 8
205
    diag_printf("CS8900A[%p] - type: 0x%04x, rev: 0x%04x\n", (void *)base, chip_type, chip_rev);
206
#endif
207
    if (chip_type != PP_ChipID_CL) {
208
#if DEBUG & 8
209
        diag_printf("CS8900 - invalid type (0x%04x), must be 0x630e\n", chip_type);
210
#endif
211
        return false;
212
    }
213
 
214
    CYGHWR_CL_CS8900A_PLF_RESET(base);
215
    put_reg(base, PP_SelfCtl, PP_SelfCtl_Reset);  // Reset chip
216
 
217
    CYGHWR_CL_CS8900A_PLF_POST_RESET(base);
218
 
219
    while ((get_reg(base, PP_SelfStat) & PP_SelfStat_InitD) == 0) {
220
        if (--timeout <= 0) {
221
#if DEBUG & 8
222
            diag_printf("CS8900 didn't reset - abort!\n");
223
#endif
224
            return false;
225
        }
226
    }
227
 
228
    chip_status = get_reg(base, PP_SelfStat);
229
#if DEBUG & 8
230
    diag_printf("CS8900 - status: 0x%04x (%sEEPROM present)\n", chip_status,
231
                chip_status & PP_SelfStat_EEPROM ? "" : "no ");
232
#endif
233
 
234
 
235
    // Disable reception whilst finding the ESA
236
    put_reg(base, PP_LineCTL, 0 );
237
    // Find ESA - check possible sources in sequence and stop when
238
    // one provides the ESA:
239
    //   RedBoot option (via provide_esa)
240
    //   Compile-time configuration
241
    //   EEPROM
242
    //   <fail configuration of device>
243
    if (NULL != cpd->provide_esa) {
244
        esa_configured = cpd->provide_esa(cpd);
245
# if DEBUG & 8
246
        if (esa_configured)
247
            diag_printf("Got ESA from RedBoot option\n");
248
# endif
249
    }
250
    if (!esa_configured && cpd->hardwired_esa) {
251
        // ESA is already set in cpd->esa[]
252
#if DEBUG & 8
253
        diag_printf("Got hardcoded ESA\n");
254
#endif
255
        esa_configured = true;
256
    }
257
    if (!esa_configured && (chip_status & PP_SelfStat_EEPROM)) {
258
        // Get ESA from EEPROM - via the PP_IA registers
259
        cyg_uint16 esa_word;
260
        for (i = 0;  i < sizeof(cpd->esa);  i += 2) {
261
#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
262
            esa_word = get_reg(base, PP_IA+i);
263
            cpd->esa[i] = (esa_word & 0xFF);
264
            cpd->esa[i+1] = (esa_word >> 8) & 0xFF;
265
#else
266
            esa_word = get_reg(base, PP_IA+CYG_SWAP16(i));
267
            cpd->esa[i+1] = (esa_word & 0xFF);
268
            cpd->esa[i] = (esa_word >> 8) & 0xFF;
269
#endif
270
        }
271
#if DEBUG & 8
272
        diag_printf("Got EEPROM ESA\n");
273
#endif
274
        esa_configured = true;
275
    }
276
    if (!esa_configured) {
277
# if DEBUG & 8
278
        diag_printf("CS8900 - no EEPROM, static ESA or RedBoot config option.\n");
279
# endif
280
        return false;
281
    }
282
 
283
    // Tell the chip what ESA to use
284
    for (i = 0;  i < sizeof(cpd->esa);  i += 2) {
285
#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
286
        put_reg(base, PP_IA+i, cpd->esa[i] | (cpd->esa[i+1] << 8));
287
#else
288
        put_reg(base, PP_IA+CYG_SWAP16(i), cpd->esa[i+1] | (cpd->esa[i] << 8));
289
#endif
290
    }
291
    // Set logical address mask
292
    for (i = 0;  i < 8;  i += 2) {
293
#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
294
        put_reg(base, PP_LAF+i, 0xFFFF);
295
#else
296
        put_reg(base, PP_LAF+CYG_SWAP16(i), 0xFFFF);
297
#endif
298
    }
299
# if DEBUG & 8
300
    diag_printf("ESA %02x:%02x:%02x:%02x:%02x:%02x\n",
301
                cpd->esa[0], cpd->esa[1], cpd->esa[2],
302
                cpd->esa[3], cpd->esa[4], cpd->esa[5]);
303
# endif
304
 
305
    // Initialize upper level driver
306
    (sc->funs->eth_drv->init)(sc, cpd->esa);
307
 
308
    return true;
309
}
310
 
311
static void
312
cs8900a_stop(struct eth_drv_sc *sc)
313
{
314
    cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
315
    cyg_addrword_t base = cpd->base;
316
 
317
    put_reg(base, PP_LineCTL, 0);
318
}
319
 
320
// This function is called to "start up" the interface.  It may be called
321
// multiple times, even when the hardware is already running.  It will be
322
// called whenever something "hardware oriented" changes and should leave
323
// the hardware ready to send/receive packets.
324
static void
325
cs8900a_start(struct eth_drv_sc *sc, cyg_uint8 *esa, int flags)
326
{
327
    cyg_uint16 stat;
328
    cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
329
    cyg_addrword_t base = cpd->base;
330
 
331
    put_reg(base, PP_BusCtl, PP_BusCtl_MemoryE);  // Disable interrupts, memory mode
332
    put_reg(base, PP_IntReg, PP_IntReg_IRQ0);  // Only possibility
333
    put_reg(base, PP_RxCFG, PP_RxCFG_RxOK | PP_RxCFG_CRC |
334
                      PP_RxCFG_RUNT | PP_RxCFG_EXTRA);
335
    cpd->rxmode = PP_RxCTL_RxOK | PP_RxCTL_Broadcast | PP_RxCTL_IA;
336
    put_reg(base, PP_RxCTL, cpd->rxmode);
337
    put_reg(base, PP_TxCFG, PP_TxCFG_TxOK | PP_TxCFG_Collision |
338
                      PP_TxCFG_CRS | PP_TxCFG_SQE | PP_TxCFG_Late |
339
                      PP_TxCFG_Jabber | PP_TxCFG_16Collisions);
340
    put_reg(base, PP_BufCFG, PP_BufCFG_TxRDY | PP_BufCFG_TxUE | PP_BufCFG_RxMiss |
341
                       PP_BufCFG_TxCol | PP_BufCFG_Miss | PP_BufCFG_SWI);
342
    put_reg(base, PP_IntReg, PP_IntReg_IRQ0);  // Only possibility
343
    put_reg(base, PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);
344
    // Clear Interrupt Status Queue before enabling interrupts
345
    do {
346
        CS_IN(cpd->base, CS8900A_ISQ, stat);
347
    }  while (stat != 0) ;
348
    cpd->txbusy = false;
349
#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT
350
    put_reg(base, PP_BusCtl, PP_BusCtl_EnableIRQ);
351
#endif
352
}
353
 
354
// This routine is called to perform special "control" opertions
355
static int
356
cs8900a_control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length)
357
{
358
    cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
359
    cyg_addrword_t base = cpd->base;
360
    struct eth_drv_mc_list *mc_list = data;
361
    unsigned char *esa = (unsigned char *)data;
362
    int i;
363
 
364
    switch (key) {
365
    case ETH_DRV_SET_MAC_ADDRESS:
366
#if 9 & DEBUG
367
        diag_printf("CS8900A - set ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
368
                esa[0], esa[1], esa[2],
369
                esa[3], esa[4], esa[5] );
370
#if !defined(CYGSEM_DEVS_ETH_CL_CS8900A_WRITE_EEPROM) || !defined(CS8900A_PROGRAM_EEPROM)
371
        diag_printf("*** PERMANENT EEPROM WRITE NOT ENABLED ***\n");
372
#endif
373
#endif // DEBUG
374
 
375
        // We can write the MAC address into the interface info,
376
        // and the chip registers no problem.
377
        for ( i = 0; i < sizeof(cpd->esa);  i++ )
378
            cpd->esa[i] = esa[i];
379
        for (i = 0;  i < sizeof(cpd->esa);  i += 2) {
380
            cyg_uint16 reg = cpd->esa[i] | (cpd->esa[i+1] << 8);
381
            put_reg(cpd->base, PP_IA+i, reg );
382
        }
383
#if defined(CYGSEM_DEVS_ETH_CL_CS8900A_WRITE_EEPROM) && defined(CS8900A_PROGRAM_EEPROM)
384
        if (CS8900A_PROGRAM_EEPROM(cpd))
385
            return 1;
386
        else
387
            return 0;
388
#elif defined(CYGSEM_DEVS_ETH_CL_CS8900A_WRITE_EEPROM) && !defined(CS8900A_PROGRAM_EEPROM)
389
        /* WRITE_EEPROM requested, but no PROGRAM_EEPROM provided */
390
        return 1;
391
#else /* !CYGSEM_DEVS_ETH_CL_CS8900A_WRITE_EEPROM - No need to write EEPROM */
392
        return 0;
393
#endif
394
 
395
#ifdef ETH_DRV_GET_MAC_ADDRESS
396
    case ETH_DRV_GET_MAC_ADDRESS:
397
        // Extract the MAC address that is in the chip, and tell the
398
        // system about it.
399
        for (i = 0;  i < sizeof(cpd->esa);  i += 2) {
400
            unsigned short z = get_reg(cpd->base, PP_IA+i/2 );
401
            esa[i] =   (unsigned char)(0xff & z);
402
            esa[i+1] = (unsigned char)(0xff & (z >> 8));
403
        }
404
        return 0;
405
#endif
406
    case ETH_DRV_SET_MC_LIST:
407
    case ETH_DRV_SET_MC_ALL:
408
        // Note: this code always accepts all multicast addresses if any
409
        // are desired.  It would be possible to accept a subset by adjusting
410
        // the Logical Address Filter (LAF), but that would require scanning
411
        // this list and building a suitable mask.
412
        if (mc_list->len) {
413
            cpd->rxmode |= PP_RxCTL_Multicast;
414
        } else {
415
            cpd->rxmode &= ~PP_RxCTL_Multicast;
416
        }
417
        put_reg(base, PP_RxCTL, cpd->rxmode);  // When is it safe to do this?
418
        return 0;
419
    default:
420
        return 1;
421
        break;
422
    }
423
}
424
 
425
// This routine is called to see if it is possible to send another packet.
426
// It will return non-zero if a transmit is possible, zero otherwise.
427
static int
428
cs8900a_can_send(struct eth_drv_sc *sc)
429
{
430
    cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
431
    cyg_addrword_t base = cpd->base;
432
    cyg_uint16 stat;
433
 
434
    stat = get_reg(base, PP_LineStat);
435
    if ((stat & PP_LineStat_LinkOK) == 0) {
436
        return false;  // Link not connected
437
    }
438
#ifdef CYGPKG_KERNEL
439
    // Horrible hack!
440
    if (cpd->txbusy) {
441
        cyg_tick_count_t now = cyg_current_time();
442
        if ((now - cpd->txstart) > 25) {
443
            // 250ms is more than enough to transmit one frame
444
#if DEBUG & 1
445
            diag_printf("CS8900: Tx interrupt lost\n");
446
#endif
447
            cpd->txbusy = false;
448
            // Free up the buffer (with error indication)
449
            (sc->funs->eth_drv->tx_done)(sc, cpd->txkey, 1);
450
        }
451
    }
452
#endif
453
    return (cpd->txbusy == false);
454
}
455
 
456
// This routine is called to send data to the hardware.
457
static void
458
cs8900a_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
459
            int total_len, unsigned long key)
460
{
461
    cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
462
    cyg_addrword_t base = cpd->base;
463
    int i;
464
    int len;
465
    cyg_uint8 *data;
466
    cyg_uint16 saved_data = 0, *sdata;
467
    cyg_uint16 stat;
468
    bool force_coping_by_byte;
469
    bool odd_byte = false;
470
 
471
    // Mark xmitter busy
472
    cpd->txbusy = true;
473
    cpd->txkey = key;
474
#ifdef CYGPKG_KERNEL
475
    cpd->txstart = cyg_current_time();
476
#endif
477
 
478
    // Start the xmit sequence
479
#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
480
    total_len = CYG_SWAP16(total_len);
481
#endif
482
 
483
#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT
484
    force_coping_by_byte = true;
485
#else
486
    force_coping_by_byte = false;
487
#endif
488
 
489
    // The hardware indicates that there are options as to when the actual
490
    // packet transmission will start wrt moving of data into the transmit
491
    // buffer.  However, impirical results seem to indicate that if the
492
    // packet is large and transmission is allowed to start before the
493
    // entire packet has been pushed into the buffer, the hardware gets
494
    // confused and the packet is lost, along with a "lost" Tx interrupt.
495
    // This may be a case of the copy loop below being interrupted, e.g.
496
    // a system timer interrupt, and the hardware getting unhappy that 
497
    // not all of the data was provided before the transmission should
498
    // have completed (i.e. buffer underrun).
499
    // For now, the solution is to not allow this overlap.
500
    //CS_OUT(cpd->base, CS8900A_TxCMD, PP_TxCmd_TxStart_5)
501
 
502
    // Start only when all data sent to chip
503
    CS_OUT(cpd->base, CS8900A_TxCMD, PP_TxCmd_TxStart_Full);
504
 
505
    CS_OUT(cpd->base, CS8900A_TxLEN, total_len);
506
    // Wait for controller ready signal
507
    {
508
        // add timeout per cs8900a bugzilla report 1000281 */
509
        int timeout = 1000;
510
 
511
        do {
512
            stat = get_reg(base, PP_BusStat);
513
#if DEBUG & 1
514
            if( stat & PP_BusStat_TxBid )
515
                diag_printf( "cs8900a_send: Bid error!\n" );
516
#endif
517
        } while (!(stat & PP_BusStat_TxRDY) && --timeout);
518
 
519
        if( !timeout ) {
520
            // we might as well just return, since if we write the data it will
521
            // just get thrown away
522
            return;
523
        }
524
    }
525
 
526
    // Put data into buffer
527
    for (i = 0;  i < sg_len;  i++) {
528
        data = (cyg_uint8 *)sg_list[i].buf;
529
        len = sg_list[i].len;
530
 
531
        if (len > 0) {
532
            /* Finish the last word. */
533
            if (odd_byte) {
534
// This new byte must get on the bus _after_ the last saved odd byte, it therefore
535
// belongs in the MSB of the CS8900a
536
#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED                            
537
                saved_data |= *data++;
538
#else
539
                saved_data |= ((cyg_uint16)*data++) << 8;
540
#endif
541
                CS_OUT(cpd->base, CS8900A_RTDATA, saved_data);
542
                len--;
543
                odd_byte = false;
544
            }
545
            if (!force_coping_by_byte && ((CYG_ADDRESS)data & 0x1) == 0) {
546
                /* Aligned on 16-bit boundary, so output contiguous words. */
547
                sdata = (cyg_uint16 *)data;
548
                while (len > 1) {
549
                                        // Make sure data get on the bus in Big Endian format
550
#if((CYG_BYTEORDER == CYG_MSBFIRST) && defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED) || \
551
    (CYG_BYTEORDER == CYG_LSBFIRST) && !defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED ))
552
                    CS_OUT(cpd->base, CS8900A_RTDATA, *sdata++);
553
#else
554
                    CS_OUT(cpd->base, CS8900A_RTDATA, CYG_SWAP16(*sdata++));
555
#endif
556
                    len -= sizeof(cyg_uint16);
557
                }
558
                data = (cyg_uint8 *)sdata;
559
            } else {
560
                /* Not 16-bit aligned, so byte copy */
561
                while (len > 1) {
562
                    saved_data = (cyg_uint16)*data++;   // reuse saved_data
563
                                        // Make sure data get on the bus in Big Endian format, the first byte belongs in the
564
                                        // LSB of the CS8900A
565
#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
566
                    saved_data =  ((cyg_uint16)*data++) | (saved_data << 8);
567
#else
568
                    saved_data |= ((cyg_uint16)*data++) << 8;
569
#endif
570
                    CS_OUT(cpd->base, CS8900A_RTDATA, saved_data);
571
                    len -= sizeof(cyg_uint16);
572
                }
573
            }
574
            /* Save last byte, if necessary. */
575
            if (len == 1) {
576
                saved_data = (cyg_uint16)*data;
577
// This _last_ byte must get on the bus _first_, it therefore belongs in the LSB of
578
// the CS8900a
579
#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
580
                saved_data = (saved_data << 8);
581
#endif
582
                odd_byte = true;
583
            }
584
        }
585
    }
586
    if (odd_byte) {
587
        CS_OUT(cpd->base, CS8900A_RTDATA, saved_data);
588
    }
589
}
590
 
591
// This function is called when a packet has been received.  It's job is
592
// to prepare to unload the packet from the hardware.  Once the length of
593
// the packet is known, the upper layer of the driver can be told.  When
594
// the upper layer is ready to unload the packet, the internal function
595
// 'cs8900a_recv' will be called to actually fetch it from the hardware.
596
static void
597
cs8900a_RxEvent(struct eth_drv_sc *sc, int stat)
598
{
599
    cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
600
    cyg_addrword_t base = cpd->base;
601
    cyg_uint16 len;
602
 
603
    if(stat & PP_RxCFG_RxOK) {
604
        // Only start reading a message if one has been received
605
#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT
606
        CS_IN(base, CS8900A_RTDATA, stat);
607
        CS_IN(base, CS8900A_RTDATA, len);
608
#else
609
        // From AN181 Using the Crystal CS8900A in 8-bit mode.
610
        // Note: it is very important to read the RxStatus and RxLength high
611
        // order byte first.
612
        stat = *(volatile CYG_BYTE *)(base + CS8900A_RTDATA + 1) << 8;
613
        stat |= *(volatile CYG_BYTE *)(base + CS8900A_RTDATA);
614
        len = *(volatile CYG_BYTE *)(base + CS8900A_RTDATA + 1) << 8;
615
        len |= *(volatile CYG_BYTE *)(base + CS8900A_RTDATA);
616
#endif
617
 
618
#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
619
        len = CYG_SWAP16(len);
620
#endif
621
 
622
        CYG_ASSERT(len > 0, "Zero length ethernet frame received");
623
 
624
#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
625
        if (cyg_io_eth_net_debug) {
626
            diag_printf("RxEvent - stat: %x, len: %d\n", stat, len);
627
        }
628
#endif
629
        (sc->funs->eth_drv->recv)(sc, len);
630
    }
631
}
632
 
633
// This function is called as a result of the "eth_drv_recv()" call above.
634
// It's job is to actually fetch data for a packet from the hardware once
635
// memory buffers have been allocated for the packet.  Note that the buffers
636
// may come in pieces, using a scatter-gather list.  This allows for more
637
// efficient processing in the upper layers of the stack.
638
static void
639
cs8900a_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
640
{
641
    cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
642
    cyg_addrword_t base = cpd->base;
643
    int i, mlen;
644
    cyg_uint16 *data, val;
645
    cyg_uint8 *cp, cval;
646
 
647
    for (i = 0;  i < sg_len;  i++) {
648
        data = (cyg_uint16 *)sg_list[i].buf;
649
        mlen = sg_list[i].len;
650
        while (mlen >= sizeof(*data)) {
651
            CS_IN(base, CS8900A_RTDATA, val);
652
            if (data) {
653
#if((CYG_BYTEORDER == CYG_MSBFIRST) && defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED) || \
654
    (CYG_BYTEORDER == CYG_LSBFIRST) && !defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED ))
655
                *data++ = val;
656
#else
657
                *data++ = CYG_SWAP16(val);
658
#endif
659
            }
660
            mlen -= sizeof(*data);
661
        }
662
        if (mlen) {
663
            CS_IN(base, CS8900A_RTDATA, val);
664
#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED 
665
            // last odd byte will be in the LSB
666
            cval = (cyg_uint8)(val);
667
#elif(CYG_BYTEORDER == CYG_MSBFIRST)
668
            // last odd byte will be in the MSB
669
            cval = (cyg_uint8)(val >> 8);
670
#endif
671
            cval &= 0xff;
672
            if ((cp = (cyg_uint8 *)data) != 0) {
673
                *cp = cval;
674
            }
675
        }
676
    }
677
}
678
 
679
static void
680
cs8900a_TxEvent(struct eth_drv_sc *sc, int stat)
681
{
682
    cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
683
    cyg_addrword_t base = cpd->base;
684
 
685
    stat = get_reg(base, PP_TER);
686
#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
687
    if (cyg_io_eth_net_debug) {
688
        diag_printf("Tx event: %x\n", stat);
689
    }
690
#endif
691
    cpd->txbusy = false;
692
    (sc->funs->eth_drv->tx_done)(sc, cpd->txkey, 0);
693
}
694
 
695
static void
696
cs8900a_BufEvent(struct eth_drv_sc *sc, int stat)
697
{
698
    if (stat & PP_BufCFG_RxMiss) {
699
    }
700
    if (stat & PP_BufCFG_TxUE) {
701
    }
702
}
703
 
704
static void
705
cs8900a_poll(struct eth_drv_sc *sc)
706
{
707
    cyg_uint16 event;
708
    cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
709
    cyg_addrword_t base = cpd->base;
710
 
711
    CS_IN(base, CS8900A_ISQ, event);
712
    while (event != 0) {
713
        switch (event & ISQ_EventMask) {
714
        case ISQ_RxEvent:
715
            cs8900a_RxEvent(sc, event);
716
            break;
717
        case ISQ_TxEvent:
718
            cs8900a_TxEvent(sc, event);
719
            break;
720
        case ISQ_BufEvent:
721
            cs8900a_BufEvent(sc, event);
722
            break;
723
        case ISQ_RxMissEvent:
724
            // Receive miss counter has overflowed
725
            break;
726
        case ISQ_TxColEvent:
727
            // Transmit collision counter has overflowed
728
            break;
729
        default:
730
#if DEBUG & 1
731
            diag_printf("%s: Unknown event: %x\n", __FUNCTION__, event);
732
#endif
733
            break;
734
        }
735
        CS_IN(base, CS8900A_ISQ, event);
736
    }
737
 
738
    CYGHWR_CL_CS8900A_PLF_INT_CLEAR(cpd);
739
}
740
 
741
#ifdef CYGSEM_DEVS_ETH_CL_CS8900A_NOINTS
742
void
743
cs8900a_fake_int(cyg_addrword_t param)
744
{
745
    struct eth_drv_sc *sc = (struct eth_drv_sc *) param;
746
    int s;
747
 
748
#if DEBUG & 1
749
    diag_printf("cs8900a_fake_int()\n");
750
#endif
751
 
752
    while (true) {
753
        cyg_thread_delay(5);
754
        s = splnet();
755
        cs8900a_poll(sc);
756
        splx(s);
757
    }
758
}
759
#endif

powered by: WebSVN 2.1.0

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