1 //==========================================================================
5 // Ethernet device driver for NS DP83816 ethernet controller
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 // Copyright (C) 2003, 2004 Gary Thomas
13 // Copyright (C) 2004 eCosCentric Limited
15 // eCos is free software; you can redistribute it and/or modify it under
16 // the terms of the GNU General Public License as published by the Free
17 // Software Foundation; either version 2 or (at your option) any later version.
19 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
20 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 // You should have received a copy of the GNU General Public License along
25 // with eCos; if not, write to the Free Software Foundation, Inc.,
26 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28 // As a special exception, if other files instantiate templates or use macros
29 // or inline functions from this file, or you compile this file and link it
30 // with other works to produce a work based on this file, this file does not
31 // by itself cause the resulting work to be covered by the GNU General Public
32 // License. However the source code for this file must still be made available
33 // in accordance with section (3) of the GNU General Public License.
35 // This exception does not invalidate any other reasons why a work based on
36 // this file might be covered by the GNU General Public License.
38 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
39 // at http://sources.redhat.com/ecos/ecos-license/
40 // -------------------------------------------
41 //####ECOSGPLCOPYRIGHTEND####
42 //==========================================================================
43 //#####DESCRIPTIONBEGIN####
51 //####DESCRIPTIONEND####
53 //==========================================================================
55 #include <pkgconf/system.h>
56 #include <pkgconf/io_eth_drivers.h>
58 #include <cyg/infra/cyg_type.h>
59 #include <cyg/hal/hal_arch.h>
60 #include <cyg/hal/hal_endian.h>
61 #include <cyg/infra/diag.h>
62 #include <cyg/hal/drv_api.h>
63 #include <cyg/hal/hal_if.h>
64 #include <cyg/io/eth/eth_drv.h>
65 #include <cyg/io/eth/netdev.h>
66 #include <string.h> // memcpy
69 #include CYGDAT_DEVS_ETH_NS_DP83816_INL
75 #ifdef CYGHWR_NS_DP83816_USE_EEPROM
76 static cyg_uint16 dp83816_eeprom_read(struct dp83816_priv_data *dp, int location);
79 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
80 // This ISR is called when the ethernet interrupt occurs
82 dp83816_isr(cyg_vector_t vector, cyg_addrword_t data)
84 struct eth_drv_sc *sc = (struct eth_drv_sc *)data;
85 dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private;
89 cyg_drv_interrupt_mask(dp->interrupt);
90 cyg_drv_interrupt_acknowledge(dp->interrupt);
91 return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR
93 #endif // CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
95 // The deliver function (ex-DSR) handles the ethernet [logical] processing
97 dp83816_deliver(struct eth_drv_sc *sc)
99 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
100 dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private;
105 // Service the interrupt:
107 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
108 // Allow interrupts to happen again
109 cyg_drv_interrupt_unmask(dp->interrupt);
114 dp83816_reset(dp83816_priv_data_t *dp)
121 DP_OUT(dp->base, DP_CR, _CR_RST); // Reset device
124 DP_IN(dp->base, DP_CR, stat);
125 } while (((stat & _CR_RST) != 0) && (--timeout > 0));
127 diag_printf("DP83816 - reset timed out! - stat: %x\n", stat);
132 bdp = dp->rxnext = CYGARC_UNCACHED_ADDRESS(dp->rxd);
134 for (i = 0; i < dp->rxnum; i++, bdp++) {
135 bdp->next = (dp83816_bd_t *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(bdp+1));
136 bdp->stat = CYG_CPU_TO_LE32(BD_INTR | _DP83816_BUFSIZE); // Max buffer
137 bdp->buf = (unsigned char *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(bp));
138 bp += _DP83816_BUFSIZE;
140 bdp--; bdp->next = (dp83816_bd_t *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(dp->rxd));
141 DP_OUT(dp->base, DP_RXCFG, _RXCFG_MXDMA_128 | ((64/32)<<_RXCFG_DRTH_SHIFT));
142 DP_OUT(dp->base, DP_RXDP, CYGARC_PHYSICAL_ADDRESS(dp->rxd));
144 bdp = dp->txfill = dp->txint = CYGARC_UNCACHED_ADDRESS(dp->txd);
146 for (i = 0; i < dp->txnum; i++, bdp++) {
147 bdp->next = (dp83816_bd_t *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(bdp+1));
148 bdp->stat = 0; // Driver owns buffer for now
149 bdp->buf = (unsigned char *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(bp));
150 bp += _DP83816_BUFSIZE;
152 bdp--; bdp->next = (dp83816_bd_t *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(dp->txd));
153 DP_OUT(dp->base, DP_TXCFG, _TXCFG_ATP |
156 ((256/32)<<_TXCFG_FLTH_SHIFT) |
157 ((512/32)<<_TXCFG_DRTH_SHIFT));
158 DP_OUT(dp->base, DP_TXDP, CYGARC_PHYSICAL_ADDRESS(dp->txd));
161 for (i = 0; i < 6; i+=2) {
162 DP_OUT(dp->base, DP_RFCR, i);
163 DP_OUT(dp->base, DP_RFDR, dp->enaddr[i] | (dp->enaddr[i+1]<<8));
165 // Setup up acceptance criteria
166 DP_OUT(dp->base, DP_RFCR, _RFCR_RFEN | _RFCR_AAB | _RFCR_APM);
168 DP_IN(dp->base, DP_ISR, stat); // Clear any current interrupts
169 DP_OUT(dp->base, DP_IMR, 0x00000000); // Disable them all!
170 DP_OUT(dp->base, DP_IER, 0);
175 dp83816_init(struct cyg_netdevtab_entry *tab)
177 struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
178 dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private;
181 unsigned char enaddr[6];
185 CYGHWR_NS_DP83816_PLF_INIT(dp);
187 if (!base) return false; // No device found
189 #ifdef CYGPKG_REDBOOT
190 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
191 esa_ok = flash_get_config(dp->esa_key, enaddr, CONFIG_ESA);
193 #elif defined (CONFIG_ESA)
194 esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
195 dp->esa_key, enaddr, CONFIG_ESA);
197 // Get physical device address
198 // There are two different implementations due to parallel implementations.
199 // Both are included for backward compatibility, but
200 // the CYGHWR_DEVS_ETH_NS_DP83816_USE_EEPROM_ESA implementation is
201 // preferred simply because it is smaller.
202 #if defined(CYGHWR_DEVS_ETH_NS_DP83816_USE_EEPROM_ESA)
205 // Read the ESA from the PMATCH receive filter register, which
206 // will have been initialised from the EEPROM.
209 for (i = 0; i < 6; i+=2) {
210 DP_OUT(dp->base, DP_RFCR, i);
211 DP_IN(dp->base, DP_RFDR, rfcrdat );
212 enaddr[i] = rfcrdat & 0xff;
213 enaddr[i+1] = (rfcrdat>>8) & 0xff;
217 #elif defined(CYGHWR_NS_DP83816_USE_EEPROM)
218 // This define (CYGHWR_NS_DP83816_USE_EEPROM) is deprecated.
222 t = (dp83816_eeprom_read(dp, 0x0006) >> 15)
223 | (dp83816_eeprom_read(dp, 0x0007) << 1);
224 enaddr[0] = t & 0xFF;
226 t = (dp83816_eeprom_read(dp, 0x0007) >> 15)
227 | (dp83816_eeprom_read(dp, 0x0008) << 1);
228 enaddr[2] = t & 0xFF;
230 t = (dp83816_eeprom_read(dp, 0x0008) >> 15)
231 | (dp83816_eeprom_read(dp, 0x0009) << 1);
232 enaddr[4] = t & 0xFF;
239 memcpy(dp->enaddr, enaddr, sizeof(enaddr));
241 // Can't figure out ESA
242 diag_printf("DP83816 - Warning! ESA unknown\n");
247 if (!dp83816_reset(dp)) return false;
250 diag_printf("DP83816 - ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
251 dp->enaddr[0], dp->enaddr[1], dp->enaddr[2],
252 dp->enaddr[3], dp->enaddr[4], dp->enaddr[5] );
255 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
256 cyg_drv_interrupt_create(
258 0, // Priority - unused
259 (cyg_addrword_t)sc, // Data item passed to ISR & DSR
262 &dp->interrupt_handle, // handle to intr obj
263 &dp->interrupt_object ); // space for int obj
265 cyg_drv_interrupt_attach(dp->interrupt_handle);
266 cyg_drv_interrupt_unmask(dp->interrupt);
267 #elif defined(CYGPKG_REDBOOT)
268 cyg_drv_interrupt_unmask(dp->interrupt);
271 // Initialize upper level driver
272 (sc->funs->eth_drv->init)(sc, dp->enaddr);
278 dp83816_stop(struct eth_drv_sc *sc)
280 dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private;
282 DP_OUT(dp->base, DP_IMR, 0x00000000); // Disable interrupts
283 DP_OUT(dp->base, DP_IER, 0);
284 DP_OUT(dp->base, DP_CR, _CR_RXD | _CR_TXD);
288 // This function is called to "start up" the interface. It may be called
289 // multiple times, even when the hardware is already running. It will be
290 // called whenever something "hardware oriented" changes and should leave
291 // the hardware ready to send/receive packets.
294 dp83816_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
296 dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private;
298 DP_OUT(dp->base, DP_IMR, 0xFFFFFFFF); // Enable interrupts
299 DP_OUT(dp->base, DP_IER, 1);
300 DP_OUT(dp->base, DP_CR, _CR_RXE | _CR_TXE);
304 // This routine is called to perform special "control" opertions
307 dp83816_control(struct eth_drv_sc *sc, unsigned long key,
308 void *data, int data_len)
311 case ETH_DRV_SET_MAC_ADDRESS:
321 // This routine is called to see if it is possible to send another packet.
322 // It will return non-zero if a transmit is possible, zero otherwise.
325 dp83816_can_send(struct eth_drv_sc *sc)
327 dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private;
330 return (dp->txnum - dp->txbusy);
334 // This routine is called to send data to the hardware. It is known a-priori
335 // that there is free buffer space (dp->tx_next).
338 dp83816_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
339 int total_len, unsigned long key)
341 struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
348 HAL_DISABLE_INTERRUPTS(ints);
356 if (len < IEEE_8023_MIN_FRAME) len = IEEE_8023_MIN_FRAME;
357 data = (unsigned char *)CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->buf));
361 diag_printf("send sg_len==%d, txbusy=%d, len=%d, total_len=%d\n", sg_len, dp->txbusy, len, total_len);
365 for (i = 0; i < sg_len; i++) {
366 memcpy(data, (unsigned char *)sg_list[i].buf, sg_list[i].len);
367 data += sg_list[i].len;
370 bdp->stat = CYG_CPU_TO_LE32(len | BD_OWN | BD_INTR);
372 bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->next)));
374 // Kick the device, in case it went idle
375 DP_OUT(dp->base, DP_CR, _CR_TXE);
377 cyg_drv_dsr_unlock();
378 HAL_RESTORE_INTERRUPTS(ints);
383 dp83816_TxEvent(struct eth_drv_sc *sc)
385 struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
386 dp83816_bd_t *bdp = dp->txint;
389 while ((CYG_LE32_TO_CPU(bdp->stat) & (BD_OWN|BD_INTR)) == BD_INTR) {
390 // Tell higher level we sent this packet
391 (sc->funs->eth_drv->tx_done)(sc, bdp->key, 0);
392 bdp->stat = 0; // retake buffer
395 bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->next)));
401 // This function is called when a packet has been received. It's job is
402 // to prepare to unload the packet from the hardware. Once the length of
403 // the packet is known, the upper layer of the driver can be told. When
404 // the upper layer is ready to unload the packet, the internal function
405 // 'dp83816_recv' will be called to actually fetch it from the hardware.
408 dp83816_RxEvent(struct eth_drv_sc *sc)
410 struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
411 dp83816_bd_t *bdp = CYGARC_UNCACHED_ADDRESS(dp->rxd);
412 dp83816_bd_t *bdfirst = CYGARC_UNCACHED_ADDRESS(dp->rxd);
418 if ((CYG_LE32_TO_CPU(bdp->stat) & BD_OWN) != 0) {
419 err = CYG_LE32_TO_CPU(bdp->stat) & (BD_RXA|BD_RXO|BD_LONG|BD_RUNT|BD_ISE|BD_CRCE|BD_FAE|BD_COL);
421 diag_printf("RxError: %x\n", err);
423 len = CYG_LE32_TO_CPU(bdp->stat) & BD_LENGTH_MASK;
425 (sc->funs->eth_drv->recv)(sc, len);
426 bdp->stat = CYG_CPU_TO_LE32(BD_INTR | _DP83816_BUFSIZE); // Give back buffer
428 bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->next)));
429 if (bdp == bdfirst) {
436 // This function is called as a result of the "eth_drv_recv()" call above.
437 // It's job is to actually fetch data for a packet from the hardware once
438 // memory buffers have been allocated for the packet. Note that the buffers
439 // may come in pieces, using a scatter-gather list. This allows for more
440 // efficient processing in the upper layers of the stack.
443 dp83816_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
445 struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
446 dp83816_bd_t *bdp = dp->rxnext;
450 data = (unsigned char *)CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->buf));
451 for (i = 0; i < sg_len; i++) {
453 memcpy((void *)sg_list[i].buf, data, sg_list[i].len);
454 data += sg_list[i].len;
459 dp83816_warm_reset(struct eth_drv_sc *sc)
461 struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
466 // Free up any active Tx buffers
467 bdp = CYGARC_UNCACHED_ADDRESS(dp->txd);
468 for (i = 0; i < dp->txnum; i++, bdp++) {
470 (sc->funs->eth_drv->tx_done)(sc, bdp->key, 0);
475 DP_OUT(dp->base, DP_CR, _CR_RXE | _CR_TXE);
479 dp83816_poll(struct eth_drv_sc *sc)
481 struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
482 unsigned long stat, cr_stat;
484 #if defined(CYGPKG_REDBOOT)
485 cyg_drv_interrupt_acknowledge(dp->interrupt);
488 DP_IN(dp->base, DP_ISR, stat);
490 if ((stat & (_ISR_TXDESC|_ISR_TXOK)) != 0) {
493 if ((stat & (_ISR_RXDESC|_ISR_RXOK|_ISR_RXERR)) != 0) {
496 DP_IN(dp->base, DP_CR, cr_stat);
497 if ((stat & (_ISR_HIBERR|_ISR_TXURN|_ISR_RXORN)) != 0) {
499 diag_printf("DP83816 - major error: %x, cmd_stat: %x\n", stat, cr_stat);
501 // Try to reset the device
502 dp83816_warm_reset(sc);
505 if (((cr_stat & _CR_RXE) == 0) ||
506 ((dp->txbusy > 1) && ((cr_stat & _CR_TXE) == 0)))
510 diag_printf("DP83816 went to lunch? - stat: %x/%x, txbusy: %x, bdstat: %x\n", cr_stat, stat, dp->txbusy, dp->txint->stat);
512 // Try to reset the device
513 dp83816_warm_reset(sc);
516 DP_IN(dp->base, DP_ISR, stat);
518 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
519 CYGHWR_NS_DP83816_PLF_INT_CLEAR(dp);
524 dp83816_int_vector(struct eth_drv_sc *sc)
526 struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
527 return dp->interrupt;
530 /* EEPROM Functions */
531 #ifdef CYGHWR_NS_DP83816_USE_EEPROM
533 #define EEPROM_READ(dp, x) DP_IN((dp)->base, DP_MEAR, (x))
534 #define EEPROM_WRITE(dp, x) DP_OUT((dp)->base, DP_MEAR, (x))
535 #define EEPROM_DELAY(dp) CYG_MACRO_START cyg_uint16 t; EEPROM_READ((dp), t); CYG_MACRO_END
537 #define DP83816_EEPROM_ADDR_LEN 6
538 #define DP83816_EE_READ_CMD (6 << DP83816_EEPROM_ADDR_LEN)
541 /* EEPROM data is bit-swapped. */
542 static cyg_uint16 dp83816_eeprom_fixup_data(cyg_uint16 input)
544 cyg_uint16 output = 0;
547 for (i = 0; i < 16; i++) {
548 output = (output << 1) | (input & 0x0001);
554 static cyg_uint16 dp83816_eeprom_command(struct dp83816_priv_data *dp, int cmd, int cmd_len)
558 EEPROM_WRITE(dp, _MEAR_EESEL);
561 cyg_uint32 c = (cmd & (1 << cmd_len)) ? _MEAR_EEDI : 0;
564 EEPROM_WRITE(dp, c | _MEAR_EESEL);
566 EEPROM_WRITE(dp, c | _MEAR_EESEL | _MEAR_EECLK);
571 d |= (t & _MEAR_EEDO) ? 1 : 0;
574 EEPROM_WRITE(dp, _MEAR_EESEL);
580 static cyg_uint16 dp83816_eeprom_read(struct dp83816_priv_data *dp, int loc)
584 d = dp83816_eeprom_command(dp, (loc | DP83816_EE_READ_CMD) << 16,
585 3 + DP83816_EEPROM_ADDR_LEN + 16);
587 return dp83816_eeprom_fixup_data(d);
590 #endif /* CYGHWR_NS_DP83816_USE_EEPROM */