1 //==========================================================================
5 // Ethernet device driver for PowerPC PPC405 boards
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) 2002, 2003, 2005 Gary Thomas
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
45 // Contributors: gthomas
48 // Description: hardware driver for PPC405
51 //####DESCRIPTIONEND####
53 //==========================================================================
55 // Ethernet device driver for PPC405
57 #include <pkgconf/system.h>
58 #include <pkgconf/devs_eth_powerpc_ppc405.h>
59 #include <pkgconf/io_eth_drivers.h>
62 #include <pkgconf/net.h>
65 #include <cyg/infra/cyg_type.h>
66 #include <cyg/infra/diag.h>
68 #include <cyg/hal/hal_arch.h>
69 #include <cyg/hal/hal_cache.h>
70 #include <cyg/hal/hal_intr.h>
71 #include <cyg/hal/drv_api.h>
72 #include <cyg/hal/hal_if.h>
73 #include <cyg/hal/ppc_regs.h>
75 #include <cyg/io/eth/netdev.h>
76 #include <cyg/io/eth/eth_drv.h>
77 #include <cyg/io/eth_phy.h>
80 // PHY access functions
82 static void ppc405_eth_phy_init(void);
83 static void ppc405_eth_phy_put_reg(int reg, int phy, unsigned short data);
84 static bool ppc405_eth_phy_get_reg(int reg, int phy, unsigned short *val);
86 #include "ppc405_enet.h"
87 #include CYGDAT_DEVS_PPC405_ETH_INL
89 #define os_printf diag_printf
91 // For fetching the ESA from RedBoot
92 #include <cyg/hal/hal_if.h>
97 static void ppc405_eth_int(struct eth_drv_sc *data);
99 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
101 static cyg_interrupt ppc405_emac_interrupt;
102 static cyg_handle_t ppc405_emac_interrupt_handle;
103 static cyg_interrupt ppc405_mal_txeob_interrupt;
104 static cyg_handle_t ppc405_mal_txeob_interrupt_handle;
105 static cyg_interrupt ppc405_mal_rxeob_interrupt;
106 static cyg_handle_t ppc405_mal_rxeob_interrupt_handle;
107 static cyg_interrupt ppc405_mal_txde_interrupt;
108 static cyg_handle_t ppc405_mal_txde_interrupt_handle;
109 static cyg_interrupt ppc405_mal_rxde_interrupt;
110 static cyg_handle_t ppc405_mal_rxde_interrupt_handle;
111 static cyg_interrupt ppc405_mal_serr_interrupt;
112 static cyg_handle_t ppc405_mal_serr_interrupt_handle;
114 #define EMAC_INTERRUPT_HANDLER(_int_,_hdlr_) \
115 cyg_drv_interrupt_create(_int_, \
117 (cyg_addrword_t)sc, /* Data item passed to interrupt handler */ \
118 (cyg_ISR_t *)ppc405_eth_isr, \
119 (cyg_DSR_t *)eth_drv_dsr, \
120 &ppc405_##_hdlr_##_interrupt_handle, \
121 &ppc405_##_hdlr_##_interrupt); \
122 cyg_drv_interrupt_attach(ppc405_##_hdlr_##_interrupt_handle); \
123 cyg_drv_interrupt_acknowledge(_int_); \
124 cyg_drv_interrupt_unmask(_int_);
126 // This ISR is called when the ethernet interrupt occurs
128 ppc405_eth_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
130 struct eth_drv_sc *sc = (struct eth_drv_sc *)data;
131 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
133 cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_MAL_SERR);
134 cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_MAL_TX_EOB);
135 cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_MAL_RX_EOB);
136 cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_MAL_TX_DE);
137 cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_MAL_RX_DE);
138 cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_EMAC0);
140 return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR
144 // Deliver function (ex-DSR) handles the ethernet [logical] processing
146 ppc405_eth_deliver(struct eth_drv_sc *sc)
148 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
149 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
153 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
154 // Allow interrupts to happen again
155 HAL_DISABLE_INTERRUPTS(old_ints);
156 cyg_drv_interrupt_acknowledge(qi->ints);
157 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_MAL_SERR);
158 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_MAL_TX_EOB);
159 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_MAL_RX_EOB);
160 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_MAL_TX_DE);
161 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_MAL_RX_DE);
162 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EMAC0);
163 HAL_RESTORE_INTERRUPTS(old_ints);
171 ppc405_eth_phy_init(void)
173 // Set up MII hardware - nothing to do on this platform
177 ppc405_eth_phy_put_reg(int reg, int phy, unsigned short data)
179 unsigned long reg_val;
181 reg_val = EMAC0_STACR_STAC_WRITE | EMAC0_STACR_OPBC_66;
182 reg_val |= (phy << EMAC0_STACR_PCDA_SHIFT) | reg;
183 reg_val |= (data << EMAC0_STACR_PHYD_SHIFT);
185 os_printf("PHY PUT - reg: %d, phy: %d, val: %04x [%08x]\n", reg, phy, data, reg_val);
187 while ((EMAC0_STACR & EMAC0_STACR_OC) == 0) ; // Wait for MII free
188 EMAC0_STACR = reg_val;
189 while ((EMAC0_STACR & EMAC0_STACR_OC) == 0) ; // Wait for MII complete
193 ppc405_eth_phy_get_reg(int reg, int phy, unsigned short *val)
195 unsigned long reg_val;
197 reg_val = EMAC0_STACR_STAC_READ | EMAC0_STACR_OPBC_66;
198 reg_val |= (phy << EMAC0_STACR_PCDA_SHIFT) | reg;
200 os_printf("PHY GET - reg: %d, phy: %d [%08x] = ", reg, phy, reg_val);
202 while ((EMAC0_STACR & EMAC0_STACR_OC) == 0) ; // Wait for MII free
203 EMAC0_STACR = reg_val;
204 while ((EMAC0_STACR & EMAC0_STACR_OC) == 0) ; // Wait for MII complete
205 if ((EMAC0_STACR & EMAC0_STACR_PHYE) == 0) {
206 // Operation completed with no error
207 *val = (EMAC0_STACR & EMAC0_STACR_PHYD) >> EMAC0_STACR_PHYD_SHIFT;
209 os_printf("%04x\n", *val);
215 os_printf("***ERROR***\n");
222 // [re]Initialize the ethernet controller
223 // Done separately since shutting down the device requires a
224 // full reconfiguration when re-enabling.
227 ppc405_eth_reset(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
229 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
230 volatile mal_bd_t *rxbd, *RxBD, *txbd, *TxBD;
231 unsigned char *RxBUF, *TxBUF;
233 unsigned long mal_status, mode;
234 unsigned short phy_state = 0;
236 // Ignore unless device is idle/stopped
237 if ((EMAC0_MR0 & (EMAC0_MR0_RXI|EMAC0_MR0_TXI)) != (EMAC0_MR0_RXI|EMAC0_MR0_TXI)) {
241 // Make sure interrupts are off while we mess with the device
242 HAL_DISABLE_INTERRUPTS(int_state);
244 // Reset EMAC controller
245 EMAC0_MR0 |= EMAC0_MR0_SRST;
247 while ((EMAC0_MR0 & EMAC0_MR0_SRST) != 0) {
249 os_printf("PPC405 Ethernet does not reset\n");
250 HAL_RESTORE_INTERRUPTS(int_state);
255 TxBD = qi->txbd_table;
256 txbd = (mal_bd_t *)CYGARC_UNCACHED_ADDRESS(TxBD);
257 RxBD = qi->rxbd_table;
258 rxbd = (mal_bd_t *)CYGARC_UNCACHED_ADDRESS(RxBD);
259 qi->tbase = qi->txbd = qi->tnext = txbd;
260 qi->rbase = qi->rxbd = qi->rnext = rxbd;
266 // setup buffer descriptors
267 for (i = 0; i < CYGNUM_DEVS_ETH_POWERPC_PPC405_RxNUM; i++) {
269 rxbd->buffer = (unsigned long)RxBUF;
270 rxbd->status = MAL_BD_R | MAL_BD_I;
271 RxBUF += CYGNUM_DEVS_ETH_POWERPC_PPC405_BUFSIZE;
275 rxbd->status |= MAL_BD_W; // Last buffer
276 for (i = 0; i < CYGNUM_DEVS_ETH_POWERPC_PPC405_TxNUM; i++) {
278 txbd->buffer = (unsigned long)TxBUF;
280 TxBUF += CYGNUM_DEVS_ETH_POWERPC_PPC405_BUFSIZE;
284 txbd->status |= MAL_BD_W; // Last buffer
286 // Tell memory access layer where the buffer descriptors are
287 CYGARC_MTDCR(MAL0_TXCARR, MAL_CASR_C0|MAL_CASR_C1); // Disable/reset channel #0 & #1
288 CYGARC_MTDCR(MAL0_RXCARR, MAL_CASR_C0); // Disable/reset channel #0
289 CYGARC_MTDCR(MAL0_CFG, MAL_CFG_SR);
291 CYGARC_MFDCR(MAL0_CFG, mal_status);
292 while ((mal_status & MAL_CFG_SR) != 0) {
294 os_printf("PPC405 MAL does not reset\n");
295 HAL_RESTORE_INTERRUPTS(int_state);
299 CYGARC_MTDCR(MAL0_CFG, MAL_CFG_PLBB | MAL_CFG_OPBBL | MAL_CFG_LEA | MAL_CFG_PLBT_DEFAULT);
300 CYGARC_MTDCR(MAL0_TXCTP0R, TxBD);
301 CYGARC_MTDCR(MAL0_RXCTP0R, RxBD);
302 CYGARC_MTDCR(MAL0_RXBS0, (CYGNUM_DEVS_ETH_POWERPC_PPC405_BUFSIZE/16)); // Receive buffer size
304 // Set device physical address (ESA)
305 EMAC0_IAHR = (enaddr[0]<<8) | (enaddr[1]<<0);
306 EMAC0_IALR = (enaddr[2]<<24) | (enaddr[3]<<16) | (enaddr[4]<<8) | (enaddr[5]<<0);
309 if (!_eth_phy_init(qi->phy)) {
312 phy_state = _eth_phy_state(qi->phy);
313 os_printf("PPC405 ETH: ");
314 mode = EMAC0_MR1_RFS_4096 | EMAC0_MR1_TFS_2048 | EMAC0_MR1_TR0_MULTI | EMAC0_MR1_APP;
315 if ((phy_state & ETH_PHY_STAT_LINK) != 0) {
316 if ((phy_state & ETH_PHY_STAT_100MB) != 0) {
317 // Link can handle 100Mb
318 mode |= EMAC0_MR1_MF_100MB;
320 if ((phy_state & ETH_PHY_STAT_FDX) != 0) {
321 mode |= EMAC0_MR1_FDE | EMAC0_MR1_EIFC | EMAC0_MR1_IST;
322 os_printf("/Full Duplex");
325 // Assume 10Mb, half duplex
326 mode |= EMAC0_MR1_MF_10MB;
330 os_printf("/***NO LINK***");
336 // Configure receiver
337 EMAC0_RMR = EMAC0_RMR_IAE | EMAC0_RMR_BAE | EMAC0_RMR_RRP | EMAC0_RMR_RFP;
339 // Transmit threshold to 256 bytes
340 EMAC0_TRTR = ((256/EMAC0_TRTR_TRT_SCALE)-1) << EMAC0_TRTR_TRT_SHIFT;
342 // Receive FIFO watermarks
343 EMAC0_RWMR = (0x1F<<EMAC0_RWMR_RLWM_SHIFT) | (0x10<<EMAC0_RWMR_RHWM_SHIFT);
349 CYGARC_MTDCR(MAL0_TXCASR, MAL_CASR_C0);
350 CYGARC_MTDCR(MAL0_RXCASR, MAL_CASR_C0);
352 // Reset all interrupts
353 EMAC0_ISR = 0xFFFFFFFF;
354 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
359 EMAC0_MR0 |= (EMAC0_MR0_RXE|EMAC0_MR0_TXE);
361 // Restore interrupts
362 HAL_RESTORE_INTERRUPTS(int_state);
367 // Initialize the interface - performed at system startup
368 // This function must set up the interface, including arranging to
369 // handle interrupts, etc, so that it may be "started" cheaply later.
373 ppc405_eth_init(struct cyg_netdevtab_entry *tab)
375 struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
376 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
378 unsigned char enaddr[6];
380 ppc405_eth_stop(sc); // Make sure it's not running yet
382 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
383 // Set up to handle interrupts
384 EMAC_INTERRUPT_HANDLER(CYGNUM_HAL_INTERRUPT_MAL_SERR, mal_serr);
385 EMAC_INTERRUPT_HANDLER(CYGNUM_HAL_INTERRUPT_MAL_TX_EOB, mal_txeob);
386 EMAC_INTERRUPT_HANDLER(CYGNUM_HAL_INTERRUPT_MAL_RX_EOB, mal_rxeob);
387 EMAC_INTERRUPT_HANDLER(CYGNUM_HAL_INTERRUPT_MAL_TX_DE, mal_txde);
388 EMAC_INTERRUPT_HANDLER(CYGNUM_HAL_INTERRUPT_MAL_RX_DE, mal_rxde);
389 EMAC_INTERRUPT_HANDLER(CYGNUM_HAL_INTERRUPT_EMAC0, emac);
392 // Get physical device address
393 #ifdef CYGPKG_REDBOOT
394 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
395 esa_ok = flash_get_config(qi->esa_key, enaddr, CONFIG_ESA);
400 esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
401 qi->esa_key, enaddr, CONFIG_ESA);
404 // Can't figure out ESA
405 os_printf("PPC405_ETH - Warning! ESA unknown\n");
406 memcpy(&enaddr, qi->enaddr, sizeof(enaddr));
408 memcpy(qi->cfg_enaddr, enaddr, sizeof(enaddr));
410 // Configure the device
411 if (!ppc405_eth_reset(sc, enaddr, 0)) {
415 // Initialize upper level driver
416 (sc->funs->eth_drv->init)(sc, (unsigned char *)&enaddr);
422 // This function is called to shut down the interface.
425 ppc405_eth_stop(struct eth_drv_sc *sc)
427 EMAC0_MR0 &= ~(EMAC0_MR0_RXE|EMAC0_MR0_TXE);
431 // This function is called to "start up" the interface. It may be called
432 // multiple times, even when the hardware is already running. It will be
433 // called whenever something "hardware oriented" changes and should leave
434 // the hardware ready to send/receive packets.
437 ppc405_eth_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
439 EMAC0_MR0 |= (EMAC0_MR0_RXE|EMAC0_MR0_TXE);
443 // This function is called for low level "control" operations
446 ppc405_eth_control(struct eth_drv_sc *sc, unsigned long key,
447 void *data, int length)
449 os_printf("%s.%d\n", __FUNCTION__, __LINE__);
452 #ifdef ETH_DRV_SET_MC_ALL
453 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
454 volatile struct ppc405 *ppc405 = qi->ppc405;
458 case ETH_DRV_SET_MAC_ADDRESS:
461 #ifdef ETH_DRV_SET_MC_ALL
462 case ETH_DRV_SET_MC_ALL:
463 case ETH_DRV_SET_MC_LIST:
464 ppc405->RxControl &= ~RxControl_PROM;
465 ppc405->hash[0] = 0xFFFFFFFF;
466 ppc405->hash[1] = 0xFFFFFFFF;
478 // This function is called to see if another packet can be sent.
479 // It should return the number of packets which can be handled.
480 // Zero should be returned if the interface is busy and can not send any more.
483 ppc405_eth_can_send(struct eth_drv_sc *sc)
485 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
487 return (qi->txactive < CYGNUM_DEVS_ETH_POWERPC_PPC405_TxNUM);
491 // This routine is called to send data to the hardware.
494 ppc405_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
495 int total_len, unsigned long key)
497 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
498 volatile mal_bd_t *txbd;
502 // Find a free buffer
505 bp = (volatile char *)CYGARC_UNCACHED_ADDRESS(txbd->buffer);
506 for (i = 0; i < sg_len; i++) {
507 memcpy((void *)bp, (void *)sg_list[i].buf, sg_list[i].len);
508 bp += sg_list[i].len;
510 txbd->length = total_len;
511 txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd);
512 qi->txkey[txindex] = key;
513 // Send it on it's way
514 txbd->status = (txbd->status & MAL_BD_W) | MAL_BD_R | MAL_BD_L | MAL_BD_I |
515 MAL_BD_TX_GFCS | MAL_BD_TX_GPAD;
517 EMAC0_TMR0 = EMAC0_TMR0_GNP0; // Start channel 0
518 // Remember the next buffer to try
519 if (txbd->status & MAL_BD_W) {
520 qi->txbd = qi->tbase;
527 // This function is called when a packet has been received. It's job is
528 // to prepare to unload the packet from the hardware. Once the length of
529 // the packet is known, the upper layer of the driver can be told. When
530 // the upper layer is ready to unload the packet, the internal function
531 // 'ppc405_eth_recv' will be called to actually fetch it from the hardware.
534 ppc405_eth_RxEvent(struct eth_drv_sc *sc)
536 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
537 volatile mal_bd_t *rxbd, *rxfirst;
539 rxbd = rxfirst = qi->rnext;
540 while ((rxbd->status & MAL_BD_R) == 0) {
541 qi->rxbd = rxbd; // Save for callback
542 (sc->funs->eth_drv->recv)(sc, rxbd->length-4); // Adjust for FCS
543 if (rxbd->status & MAL_BD_W) {
549 // Remember where we left off
550 qi->rnext = (mal_bd_t *)rxbd;
554 // This function is called as a result of the "eth_drv_recv()" call above.
555 // It's job is to actually fetch data for a packet from the hardware once
556 // memory buffers have been allocated for the packet. Note that the buffers
557 // may come in pieces, using a scatter-gather list. This allows for more
558 // efficient processing in the upper layers of the stack.
561 ppc405_eth_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
563 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
567 bp = (unsigned char *)CYGARC_UNCACHED_ADDRESS(qi->rxbd->buffer);
568 for (i = 0; i < sg_len; i++) {
569 if (sg_list[i].buf != 0) {
570 memcpy((void *)sg_list[i].buf, bp, sg_list[i].len);
571 bp += sg_list[i].len;
574 qi->rxbd->status = (qi->rxbd->status & (MAL_BD_W|MAL_BD_I)) | MAL_BD_R;
578 ppc405_eth_TxEvent(struct eth_drv_sc *sc)
580 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
581 volatile mal_bd_t *txbd;
585 while ((txbd->status & (MAL_BD_R|MAL_BD_I)) == MAL_BD_I) {
586 txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd);
587 if ((key = qi->txkey[txindex]) != 0) {
588 qi->txkey[txindex] = 0;
589 (sc->funs->eth_drv->tx_done)(sc, key, 0);
592 txbd->status &= MAL_BD_W; // Only preserve wrap bit
593 if ((txbd->status & MAL_BD_W) != 0) {
598 if (txbd == qi->tnext) {
599 break; // Went through whole list
602 // Remember where we left off
603 qi->tnext = (mal_bd_t *)txbd;
607 // Interrupt processing
609 int dump_mal0_esr = 0;
612 ppc405_eth_int(struct eth_drv_sc *sc)
614 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
615 unsigned long event, tx_event, rx_event, tx_deir, rx_deir;
616 bool need_reset = false;
618 CYGARC_MFDCR(MAL0_TXEOBISR, tx_event);
620 ppc405_eth_TxEvent(sc);
621 CYGARC_MTDCR(MAL0_TXEOBISR, tx_event);
623 CYGARC_MFDCR(MAL0_RXEOBISR, rx_event);
625 ppc405_eth_RxEvent(sc);
626 CYGARC_MTDCR(MAL0_RXEOBISR, rx_event);
628 if ((event = EMAC0_ISR) != 0) {
629 if ((event & ~(EMAC0_ISR_SE0|EMAC0_ISR_SE1)) != 0) {
630 // Error other than signal quality
631 os_printf("EMAC0_ISR: %x\n", event);
632 if ((event & (EMAC0_ISR_TE0|EMAC0_ISR_TE1)) != 0) {
633 // Some problem with transmit - should be easily recoverable
634 CYGARC_MTDCR(MAL0_TXCASR, MAL_CASR_C0);
635 qi->tnext = qi->tbase;
637 if ((event & (EMAC0_ISR_OVR|EMAC0_ISR_BP|EMAC0_ISR_RP|EMAC0_ISR_ALE|EMAC0_ISR_BFCS)) != 0) {
638 // Rx errors - reset device
642 EMAC0_ISR = event; // Reset the bits we handled
644 CYGARC_MFDCR(MAL0_ESR, event);
645 if ((event & MAL_ESR_INT_MASK) != 0) {
646 CYGARC_MFDCR(MAL0_TXDEIR, tx_deir);
647 CYGARC_MFDCR(MAL0_RXDEIR, rx_deir);
649 os_printf("MAL0_ESR: %x, Tx: %x, Rx: %x\n", event, tx_deir, rx_deir);
650 os_printf("Tx buffer headers\n");
651 diag_dump_buf((void *)qi->tbase, qi->txnum*sizeof(mal_bd_t));
652 os_printf("Rx buffer headers\n");
653 diag_dump_buf((void *)qi->rbase, qi->rxnum*sizeof(mal_bd_t));
656 // Fix Tx descriptor problems
657 CYGARC_MTDCR(MAL0_TXDEIR, tx_deir); // Clear interrupt indicator
658 CYGARC_MTDCR(MAL0_TXCASR, MAL_CASR_C0);
659 qi->tnext = qi->tbase;
662 // Fix Rx descriptor problems
663 CYGARC_MTDCR(MAL0_RXDEIR, rx_deir); // Clear interrupt indicator
664 CYGARC_MTDCR(MAL0_RXCASR, MAL_CASR_C0);
665 qi->rnext = qi->rbase;
667 CYGARC_MTDCR(MAL0_ESR, event); // Clear events just handled
670 // Something has gone awry - try resetting the device
671 os_printf("\n... PPC405 ethernet - hard reset after failure\n");
673 if (!ppc405_eth_reset(sc, qi->cfg_enaddr, 0)) {
674 os_printf("!! Failed? !!\n");
683 ppc405_eth_int_vector(struct eth_drv_sc *sc)
685 struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
686 return qi->int_vector;