static void fec_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total_len, unsigned long key) { struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private; volatile struct fec_bd *txbd, *txfirst; volatile char *bp; int i, txindex, cache_state; // Find a free buffer txbd = txfirst = qi->txbd; while (txbd->ctrl & FEC_BD_Tx_Ready) { // This buffer is busy, move to next one if (txbd->ctrl & FEC_BD_Tx_Wrap) { txbd = qi->tbase; } else { txbd++; } if (txbd == txfirst) { #ifdef CYGPKG_NET panic ("No free xmit buffers"); #else os_printf("FEC Ethernet: No free xmit buffers\n"); #endif } } // Set up buffer bp = txbd->buffer; for (i = 0; i < sg_len; i++) { memcpy((void *)bp, (void *)sg_list[i].buf, sg_list[i].len); bp += sg_list[i].len; } txbd->length = total_len; txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd); qi->txkey[txindex] = key; // Note: the MPC860 does not seem to snoop/invalidate the data cache properly! HAL_DCACHE_IS_ENABLED(cache_state); if (cache_state) { HAL_DCACHE_FLUSH(txbd->buffer, txbd->length); // Make sure no stale data } // Send it on it's way txbd->ctrl |= FEC_BD_Tx_Ready | FEC_BD_Tx_Last | FEC_BD_Tx_TC; #ifndef FEC_USE_EPPC_BD if (cache_state) { HAL_DCACHE_FLUSH(fec_eth_txring, sizeof(fec_eth_txring)); // Make sure no stale data } #endif qi->txactive++; qi->fec->TxUpdate = 0x01000000; // Any write tells machine to look for work set_led(LED_TxACTIVE); // Remember the next buffer to try if (txbd->ctrl & FEC_BD_Tx_Wrap) { qi->txbd = qi->tbase; } else { qi->txbd = txbd+1; } }
// // This function is called when a packet has been received. It's job is // to prepare to unload the packet from the hardware. Once the length of // the packet is known, the upper layer of the driver can be told. When // the upper layer is ready to unload the packet, the internal function // 'fcc_eth_recv' will be called to actually fetch it from the hardware. // static void fcc_eth_RxEvent(struct eth_drv_sc *sc) { struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private; struct fcc_bd *rxbd; int cache_state; HAL_DCACHE_IS_ENABLED(cache_state); #ifndef FCC_BDs_NONCACHED if (cache_state) { HAL_DCACHE_INVALIDATE(fcc_eth_rxring, 8*CYGNUM_DEVS_ETH_POWERPC_FCC_RxNUM); } #endif rxbd = qi->rnext; while ((rxbd->ctrl & FCC_BD_Rx_Empty) == 0) { qi->rxbd = rxbd; // Save for callback // This is the right way of doing it, but dcbi has a bug ... // if (cache_state) { // HAL_DCACHE_INVALIDATE(rxbd->buffer, rxbd->length); // } if ((rxbd->ctrl & FCC_BD_Rx_ERRORS) == 0) { (sc->funs->eth_drv->recv)(sc, rxbd->length); #if 1 // Coherent caches? if (cache_state) { HAL_DCACHE_FLUSH(rxbd->buffer, rxbd->length); } #endif } // Reset control flags to known [empty] state, clearing error bits if (rxbd->ctrl & FCC_BD_Rx_Wrap) { rxbd->ctrl = FCC_BD_Rx_Empty | FCC_BD_Rx_Int | FCC_BD_Rx_Wrap; rxbd = qi->rbase; } else { rxbd->ctrl = FCC_BD_Rx_Empty | FCC_BD_Rx_Int; rxbd++; } } // Remember where we left off qi->rnext = (struct fcc_bd *)rxbd; // Make sure no stale data #ifndef FCC_BDs_NONCACHED if (cache_state) { HAL_DCACHE_FLUSH(fcc_eth_rxring, 8*CYGNUM_DEVS_ETH_POWERPC_FCC_RxNUM); } #endif }
static void cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 ch) { volatile struct cp_bufdesc *bd; struct port_info *info = (struct port_info *)__ch_data; volatile t_Scc_Pram *uart_pram = (volatile t_Scc_Pram *)((char *)IMM + info->pram); int cache_state; /* tx buffer descriptor */ bd = (struct cp_bufdesc *)((char *)IMM + uart_pram->tbptr); while (bd->ctrl & _BD_CTL_Ready) ; // Wait for buffer free if (bd->ctrl & _BD_CTL_Int) { // This buffer has just completed interrupt output. Reset bits bd->ctrl &= ~_BD_CTL_Int; } bd->length = 1; bd->buffer[0] = ch; // Flush cache if necessary - buffer may be in cacheable memory HAL_DCACHE_IS_ENABLED(cache_state); if (cache_state) { HAL_DCACHE_FLUSH(bd->buffer, 1); } bd->ctrl |= _BD_CTL_Ready; while (bd->ctrl & _BD_CTL_Ready) ; // Wait for buffer free }
// // This function is called when a packet has been received. It's job is // to prepare to unload the packet from the hardware. Once the length of // the packet is known, the upper layer of the driver can be told. When // the upper layer is ready to unload the packet, the internal function // 'fec_eth_recv' will be called to actually fetch it from the hardware. // static void fec_eth_RxEvent(struct eth_drv_sc *sc) { struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private; struct fec_bd *rxbd; int cache_state; HAL_DCACHE_IS_ENABLED(cache_state); #ifndef FEC_BDs_NONCACHED if (cache_state) { HAL_DCACHE_INVALIDATE(fec_eth_rxring, 8*CYGNUM_DEVS_ETH_POWERPC_QUICC2_RxNUM); } #endif rxbd = qi->rnext; while ((rxbd->ctrl & FEC_BD_Rx_Empty) == 0) { qi->rxbd = rxbd; // Save for callback // This is the right way of doing it, but dcbi has a bug ... // if (cache_state) { // HAL_DCACHE_INVALIDATE(rxbd->buffer, rxbd->length); // } (sc->funs->eth_drv->recv)(sc, rxbd->length); if (cache_state) { HAL_DCACHE_FLUSH(rxbd->buffer, rxbd->length); } rxbd->ctrl |= FEC_BD_Rx_Empty; if (rxbd->ctrl & FEC_BD_Rx_Wrap) { rxbd = qi->rbase; } else { rxbd++; } } // Remember where we left off qi->rnext = (struct fec_bd *)rxbd; // Make sure no stale data #ifndef FEC_BDs_NONCACHED if (cache_state) { HAL_DCACHE_FLUSH(fec_eth_rxring, 8*CYGNUM_DEVS_ETH_POWERPC_QUICC2_RxNUM); } #endif }
// // This routine is called to send data to the hardware. static void quicc_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total_len, unsigned long key) { struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private; volatile struct cp_bufdesc *txbd, *txfirst; volatile char *bp; int i, txindex, cache_state; unsigned int ctrl; // Find a free buffer txbd = txfirst = qi->txbd; while (txbd->ctrl & QUICC_BD_CTL_Ready) { // This buffer is busy, move to next one if (txbd->ctrl & QUICC_BD_CTL_Wrap) { txbd = qi->tbase; } else { txbd++; } if (txbd == txfirst) { #ifdef CYGPKG_NET panic ("No free xmit buffers"); #else diag_printf("QUICC Ethernet: No free xmit buffers\n"); #endif } } // Remember the next buffer to try if (txbd->ctrl & QUICC_BD_CTL_Wrap) { qi->txbd = qi->tbase; } else { qi->txbd = txbd+1; } txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd); qi->txkey[txindex] = key; // Set up buffer txbd->length = total_len; bp = txbd->buffer; for (i = 0; i < sg_len; i++) { memcpy((void *)bp, (void *)sg_list[i].buf, sg_list[i].len); bp += sg_list[i].len; } // Note: the MBX860 does not seem to snoop/invalidate the data cache properly! HAL_DCACHE_IS_ENABLED(cache_state); if (cache_state) { HAL_DCACHE_FLUSH(txbd->buffer, txbd->length); // Make sure no stale data } // Send it on it's way ctrl = txbd->ctrl & ~QUICC_BD_TX_PAD; if (txbd->length < IEEE_8023_MIN_FRAME) { ctrl |= QUICC_BD_TX_PAD; } txbd->ctrl = ctrl | QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int | QUICC_BD_TX_LAST | QUICC_BD_TX_TC; }
static void fcc_eth_TxEvent(struct eth_drv_sc *sc, int stat) { struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private; struct fcc_bd *txbd; int txindex; #ifndef FCC_BDs_NONCACHED int cache_state; #endif #ifndef FCC_BDs_NONCACHED // Make sure no stale data HAL_DCACHE_IS_ENABLED(cache_state); if (cache_state) { HAL_DCACHE_INVALIDATE(fcc_eth_txring, 8*CYGNUM_DEVS_ETH_POWERPC_FCC_TxNUM); } #endif txbd = qi->tnext; // Note: TC field is used to indicate the buffer has/had data in it while ( (txbd->ctrl & (FCC_BD_Tx_TC | FCC_BD_Tx_Ready)) == FCC_BD_Tx_TC ) { if ((txbd->ctrl & FCC_BD_Tx_ERRORS) != 0) { #if 0 diag_printf("FCC Tx error BD: %x/%x- ", txbd, txbd->ctrl); if ((txbd->ctrl & FCC_BD_Tx_LC) != 0) diag_printf("Late Collision/"); if ((txbd->ctrl & FCC_BD_Tx_RL) != 0) diag_printf("Retry limit/"); // if ((txbd->ctrl & FCC_BD_Tx_RC) != 0) diag_printf("Late Collision/"); if ((txbd->ctrl & FCC_BD_Tx_UN) != 0) diag_printf("Underrun/"); if ((txbd->ctrl & FCC_BD_Tx_CSL) != 0) diag_printf("Carrier Lost/"); diag_printf("\n"); #endif } txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd); (sc->funs->eth_drv->tx_done)(sc, qi->txkey[txindex], 0); txbd->ctrl &= ~FCC_BD_Tx_TC; if (txbd->ctrl & FCC_BD_Tx_Wrap) { txbd = qi->tbase; } else { txbd++; } } // Remember where we left off qi->tnext = (struct fcc_bd *)txbd; // Make sure no stale data #ifndef FCC_BDs_NONCACHED if (cache_state) { HAL_DCACHE_FLUSH(fcc_eth_txring, 8*CYGNUM_DEVS_ETH_POWERPC_FCC_TxNUM); } #endif }
static void flush_dcache(void *__p, int __nbytes) { CYGARC_HAL_SAVE_GP(); #ifdef HAL_DCACHE_FLUSH HAL_DCACHE_FLUSH( __p , __nbytes ); #elif defined(HAL_DCACHE_INVALIDATE) HAL_DCACHE_INVALIDATE(); #endif CYGARC_HAL_RESTORE_GP(); }
/** * * QSPI bus transfer function in poll mode without IRQ. * * @param qspi_bus - QSPI bus handle * @param count - Number of bytes to transmit. * @param tx_data - Pointer to TX buffer. * @param rx_data - Pointer to RX buffer. * * @return none * *****************************************************************************/ static void qspi_xc7z_transfer_polled(cyg_qspi_xc7z_device_t *dev, cyg_uint32 count, const cyg_uint8 *tx_data, cyg_uint8 *rx_data) { entry_debug(); cyg_uint32 val; cyg_uint32 data; cyg_qspi_xc7z_bus_t *qspi_bus = (cyg_qspi_xc7z_bus_t *)dev->qspi_device.spi_bus; // Set tx buf pointer and counter if (NULL != tx_data) HAL_DCACHE_STORE(tx_data, count); // Set rx buf pointer and counter if (NULL != rx_data) HAL_DCACHE_FLUSH(rx_data, count); while(qspi_bus->us_rx_bytes) { /* if ((qspi_bus->us_tx_bytes) && ((qspi_bus->uc_tx_instr != XQSPIPS_FLASH_OPCODE_FAST_READ) || (qspi_bus->uc_tx_instr != XQSPIPS_FLASH_OPCODE_DUAL_READ) || (qspi_bus->uc_tx_instr != XQSPIPS_FLASH_OPCODE_QUAD_READ))) {*/ qspi_xc7z_fill_tx_fifo(qspi_bus, count); // } HAL_READ_UINT32(qspi_bus->base + XQSPIPS_CR_OFFSET, val); val |= XQSPIPS_CR_MANSTRT_MASK | XQSPIPS_CR_SSFORCE_MASK; HAL_WRITE_UINT32(qspi_bus->base + XQSPIPS_CR_OFFSET, val); /* Read out the data from the RX FIFO */ HAL_READ_UINT32(qspi_bus->base + XQSPIPS_SR_OFFSET, val); while ((val & XQSPIPS_IXR_RXNEMPTY_MASK) && (qspi_bus->us_rx_bytes > 0) ) { HAL_READ_UINT32(qspi_bus->base + XQSPIPS_RXD_OFFSET, data); if (qspi_bus->lp_rx_buf != NULL) { if (qspi_bus->us_rx_bytes < 4) qspi_xc7z_copy_read_data(qspi_bus, data, qspi_bus->us_rx_bytes); else qspi_xc7z_copy_read_data(qspi_bus, data, 4); } else { qspi_bus->us_rx_bytes -= (qspi_bus->us_rx_bytes < 4) ? qspi_bus->us_rx_bytes : 4; } HAL_READ_UINT32(qspi_bus->base + XQSPIPS_SR_OFFSET, val); } } }
static void fec_eth_TxEvent(struct eth_drv_sc *sc) { struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private; volatile struct fec_bd *txbd; int key, txindex, cache_state; HAL_DCACHE_IS_ENABLED(cache_state); #ifndef FEC_USE_EPPC_BD if (cache_state) { HAL_DCACHE_FLUSH(fec_eth_txring, sizeof(fec_eth_txring)); // Make sure no stale data } #endif txbd = qi->tnext; // Note: TC field is used to indicate the buffer has/had data in it while ((txbd->ctrl & (FEC_BD_Tx_Ready|FEC_BD_Tx_TC)) == FEC_BD_Tx_TC) { txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd); if ((key = qi->txkey[txindex]) != 0) { qi->txkey[txindex] = 0; (sc->funs->eth_drv->tx_done)(sc, key, 0); } if (--qi->txactive == 0) { clear_led(LED_TxACTIVE); } txbd->ctrl &= ~FEC_BD_Tx_TC; if (txbd->ctrl & FEC_BD_Tx_Wrap) { txbd = qi->tbase; } else { txbd++; } } // Remember where we left off qi->tnext = (struct fec_bd *)txbd; #ifndef FEC_USE_EPPC_BD if (cache_state) { HAL_DCACHE_FLUSH(fec_eth_txring, sizeof(fec_eth_txring)); // Make sure no stale data } #endif }
// // This function is called as a result of the "eth_drv_recv()" call above. // It's job is to actually fetch data for a packet from the hardware once // memory buffers have been allocated for the packet. Note that the buffers // may come in pieces, using a scatter-gather list. This allows for more // efficient processing in the upper layers of the stack. // static void tsec_eth_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len) { struct tsec_eth_info *qi = (struct tsec_eth_info *) sc->driver_private; unsigned char *bp; int i; bp = (unsigned char *) qi->rxbd->buffer; #if CACHE() int cache_state; // Note: the MPC8xx does not seem to snoop/invalidate the data cache properly! HAL_DCACHE_IS_ENABLED(cache_state); if (cache_state) { HAL_DCACHE_INVALIDATE(qi->rxbd->buffer, qi->rxbd->length); // Make sure no stale data } #endif for (i = 0; i < sg_len; i++) { if (sg_list[i].buf != 0) { memcpy((void *) sg_list[i].buf, bp, sg_list[i].len); bp += sg_list[i].len; // //debug: // if(index_in_memory_area + sg_list[i].len < 1024 * 1024 ) // { // stopper ++; // memcpy(memory_area + index_in_memory_area, bp, sg_list[i].len); // index_in_memory_area += sg_list[i].len; // if(stopper == 20) // os_printf("break!\n"); // } // else // os_printf("break!\n"); } } qi->rxbd->ctrl |= FEC_BD_Rx_Empty; qi->rxbd->length = 0; #if CACHE() if (cache_state) { HAL_DCACHE_FLUSH(qi->rxbd, sizeof(*qi->rxbd)); } #endif // clear_led(LED_RxACTIVE); }
// Force the current transmit buffer to be sent static void mpc8xxx_sxx_serial_flush(mpc8xxx_sxx_serial_info *smc_chan) { volatile struct cp_bufdesc *txbd = smc_chan->txbd; int cache_state; HAL_DCACHE_IS_ENABLED(cache_state); if (cache_state) { HAL_DCACHE_FLUSH(txbd->buffer, smc_chan->txsize); } if ((txbd->length > 0) && ((txbd->ctrl & (_BD_CTL_Ready|_BD_CTL_Int)) == 0)) { txbd->ctrl |= _BD_CTL_Ready|_BD_CTL_Int; // Signal buffer ready if (txbd->ctrl & _BD_CTL_Wrap) { txbd = smc_chan->tbase; } else { txbd++; } smc_chan->txbd = txbd; } }
static void fec_eth_TxEvent(struct eth_drv_sc *sc, int stat) { struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private; struct fec_bd *txbd; int txindex, cache_state; // Make sure no stale data HAL_DCACHE_IS_ENABLED(cache_state); #ifndef FEC_BDs_NONCACHED if (cache_state) { HAL_DCACHE_INVALIDATE(fec_eth_txring, 8*CYGNUM_DEVS_ETH_POWERPC_QUICC2_TxNUM); } #endif txbd = qi->tnext; // Note: TC field is used to indicate the buffer has/had data in it while ( (txbd->ctrl & (FEC_BD_Tx_TC | FEC_BD_Tx_Ready)) == FEC_BD_Tx_TC ) { txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd); (sc->funs->eth_drv->tx_done)(sc, qi->txkey[txindex], 0); txbd->ctrl &= ~FEC_BD_Tx_TC; if (txbd->ctrl & FEC_BD_Tx_Wrap) { txbd = qi->tbase; } else { txbd++; } } // Remember where we left off qi->tnext = (struct fec_bd *)txbd; // Make sure no stale data #ifndef FEC_BDs_NONCACHED if (cache_state) { HAL_DCACHE_FLUSH(fec_eth_txring, 8*CYGNUM_DEVS_ETH_POWERPC_QUICC2_TxNUM); } #endif }
/** * * QSPI bus transfer with IRQ function. * * @param qspi_bus - QSPI bus handle * @param count - Number of bytes to transmit. * @param tx_data - Pointer to TX buffer. * @param rx_data - Pointer to RX buffer. * * @return none * *****************************************************************************/ static void qspi_xc7z_transfer(cyg_qspi_xc7z_device_t *dev, cyg_uint32 count, const cyg_uint8 *tx_data, cyg_uint8 *rx_data) { entry_debug(); cyg_qspi_xc7z_bus_t *qspi_bus = (cyg_qspi_xc7z_bus_t *)dev->qspi_device.spi_bus; cyg_uint32 val; // Enable device HAL_WRITE_UINT32(qspi_bus->base + XQSPIPS_ER_OFFSET, XQSPIPS_ER_ENABLE_MASK); // Enable manual start HAL_READ_UINT32(qspi_bus->base + XQSPIPS_CR_OFFSET, val); val |= XQSPIPS_CR_MANSTRTEN_MASK | XQSPIPS_CR_SSFORCE_MASK; HAL_WRITE_UINT32(qspi_bus->base + XQSPIPS_CR_OFFSET, val); // Set tx buf pointer and counter if (NULL != tx_data) HAL_DCACHE_STORE(tx_data, count); // Set rx buf pointer and counter if (NULL != rx_data) HAL_DCACHE_FLUSH(rx_data, count); // Send first instruction if(qspi_bus->uc_tx_instr == 0) qspi_xc7z_send_instruction(qspi_bus); { if ((qspi_bus->us_tx_bytes) && ((qspi_bus->uc_tx_instr != XQSPIPS_FLASH_OPCODE_FAST_READ) || (qspi_bus->uc_tx_instr != XQSPIPS_FLASH_OPCODE_DUAL_READ) || (qspi_bus->uc_tx_instr != XQSPIPS_FLASH_OPCODE_QUAD_READ) )) qspi_xc7z_fill_tx_fifo(qspi_bus,count); // Enable the QSPI int events we are interested in HAL_WRITE_UINT32(qspi_bus->base + XQSPIPS_IER_OFFSET, XQSPIPS_IXR_TXOW_MASK | XQSPIPS_IXR_MODF_MASK); HAL_READ_UINT32(qspi_bus->base + XQSPIPS_CR_OFFSET, val); val |= XQSPIPS_CR_MANSTRT_MASK; HAL_WRITE_UINT32(qspi_bus->base + XQSPIPS_CR_OFFSET, val); cyg_drv_mutex_lock(&qspi_bus->transfer_mx); { qspi_bus->transfer_end = false; // Unmask the SPI int cyg_drv_interrupt_unmask(qspi_bus->interrupt_number); // Wait for its completion cyg_drv_dsr_lock(); { while (!qspi_bus->transfer_end) cyg_drv_cond_wait(&qspi_bus->transfer_cond); } cyg_drv_dsr_unlock(); } cyg_drv_mutex_unlock(&qspi_bus->transfer_mx); } }
static void cyg_hal_sxx_putc(void* __ch_data, cyg_uint8 ch) { volatile struct cp_bufdesc *bd, *first; EPPC *eppc = eppc_base(); struct port_info *info = (struct port_info *)__ch_data; volatile struct smc_uart_pram *uart_pram = (volatile struct smc_uart_pram *)((char *)eppc + info->pram); volatile struct smc_regs *regs = (volatile struct smc_regs *)((char *)eppc + info->regs); int timeout; int cache_state; CYGARC_HAL_SAVE_GP(); /* tx buffer descriptor */ bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbptr); // Scan for a free buffer first = bd; while (bd->ctrl & QUICC_BD_CTL_Ready) { if (bd->ctrl & QUICC_BD_CTL_Wrap) { bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase); } else { bd++; } if (bd == first) break; } while (bd->ctrl & QUICC_BD_CTL_Ready) ; // Wait for buffer free if (bd->ctrl & QUICC_BD_CTL_Int) { // This buffer has just completed interrupt output. Reset bits bd->ctrl &= ~QUICC_BD_CTL_Int; bd->length = 0; } bd->length = 1; bd->buffer[0] = ch; bd->ctrl |= QUICC_BD_CTL_Ready; // Flush cache if necessary - buffer may be in cacheable memory HAL_DCACHE_IS_ENABLED(cache_state); if (cache_state) { HAL_DCACHE_FLUSH(bd->buffer, 1); } #ifdef CYGDBG_DIAG_BUF enable_diag_uart = 0; #endif // CYGDBG_DIAG_BUF timeout = 0; while (bd->ctrl & QUICC_BD_CTL_Ready) { // Wait until buffer free if (++timeout == 0x7FFFF) { // A really long time! #ifdef CYGDBG_DIAG_BUF diag_printf("bd fail? bd: %x, ctrl: %x, tx state: %x\n", bd, bd->ctrl, uart_pram->tstate); #endif // CYGDBG_DIAG_BUF regs->smc_smcmr &= ~QUICC_SMCMR_TEN; // Disable transmitter bd->ctrl &= ~QUICC_BD_CTL_Ready; regs->smc_smcmr |= QUICC_SMCMR_TEN; // Enable transmitter bd->ctrl |= QUICC_BD_CTL_Ready; timeout = 0; #ifdef CYGDBG_DIAG_BUF diag_printf("bd retry? bd: %x, ctrl: %x, tx state: %x\n", bd, bd->ctrl, uart_pram->tstate); first = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase); while (true) { diag_printf("bd: %x, ctrl: %x, length: %x\n", first, first->ctrl, first->length); if (first->ctrl & QUICC_BD_CTL_Wrap) break; first++; } #endif // CYGDBG_DIAG_BUF } } while (bd->ctrl & QUICC_BD_CTL_Ready) ; // Wait until buffer free bd->length = 0; #ifdef CYGDBG_DIAG_BUF enable_diag_uart = 1; #endif // CYGDBG_DIAG_BUF CYGARC_HAL_RESTORE_GP(); }
// // This routine is called to send data to the hardware. static void tsec_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total_len, unsigned long key) { struct tsec_eth_info *qi = (struct tsec_eth_info *) sc->driver_private; volatile struct tsec_bd *txbd; volatile unsigned char *bp; int i, txindex; volatile struct mpq_tsec *tsec = (volatile struct mpq_tsec *) ((unsigned char *) CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1); #if CACHE() int cache_state; HAL_DCACHE_IS_ENABLED(cache_state); #endif /* if the next buffer isn't free, we're broken */ txbd = qi->txbd; // while ((tsec->tstat & TSTAT_THLT)==0) // { // /* wait for ring to halt to be able to robustly read the tbptr */ // } // if(qi->txbd != tsec->tbptr) // { // printf("wtf\n"); // } //trust the software, not set it to the value pointed by the HW // txbd = tsec->tbptr; // why the "#&¤"#¤&"#&¤" do we fail to keep track of txbd in software??? :-) #if CACHE() if (cache_state) { /* avoid any naggig doubt that a txbd could cross a cache line and flush each bd */ HAL_DCACHE_INVALIDATE(txbd, sizeof(*txbd)); } #endif CYG_ASSERT((txbd->ctrl & FEC_BD_Tx_Ready)==0, "TX buffer not ready when it was expected to be"); // Set up buffer bp = txbd->buffer; for (i = 0; i < sg_len; i++) { memcpy((void *) bp, (void *) sg_list[i].buf, sg_list[i].len); bp += sg_list[i].len; } txbd->length = total_len; txindex = ((unsigned long) txbd - (unsigned long) qi->tbase) / sizeof(*txbd); qi->txkey[txindex] = key; #if CACHE() // Note: the MPC8xx does not seem to snoop/invalidate the data cache properly! HAL_DCACHE_IS_ENABLED(cache_state); if (cache_state) { HAL_DCACHE_FLUSH(txbd->buffer, txbd->length); // Make sure no stale data } #endif txbd->ctrl |= FEC_BD_Tx_Ready | FEC_BD_Tx_Last | FEC_BD_Tx_TC; #if CACHE() if (cache_state) { /* and off it goes to the hardware! */ HAL_DCACHE_FLUSH(txbd, sizeof(*txbd));; } #endif /* clear halt condition, send it on it's way */ tsec->tstat = TSTAT_THLT; /* for debug purposes we wait for the frame to be on it's way */ // for (;;) // { //#if CACHE() // if (cache_state) // { // /* and off it goes to the hardware! */ // HAL_DCACHE_FLUSH(txbd, sizeof(*txbd));; // } //#endif // if ((txbd->ctrl&FEC_BD_Tx_Ready)==0) // { // /* it's been sent */ // break; // } // } // Remember the next buffer to try if (txbd->ctrl & FEC_BD_Tx_Wrap) { qi->txbd = qi->tbase; } else { qi->txbd = txbd + 1; } #if CACHE() HAL_DCACHE_FLUSH(qi, sizeof(*qi)); #endif }
// // [re]Initialize the ethernet controller // Done separately since shutting down the device requires a // full reconfiguration when re-enabling. // when static bool tsec_eth_reset(struct eth_drv_sc *sc, unsigned char *enaddr, int flags) { struct tsec_eth_info *qi = (struct tsec_eth_info *) sc->driver_private; volatile struct mpq_tsec *tsec = (volatile struct mpq_tsec *) ((unsigned char *) CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1); volatile struct tsec_bd *rxbd, *txbd; unsigned char *RxBUF, *TxBUF; cyg_uint32 int_state; int i = 0; HAL_DISABLE_INTERRUPTS(int_state); /** * MAC configuration -> MPC8313 User Manual, Chapter 15.6.2.2 * */ // Shut down ethernet controller, in case it is already running // Disable WWR, because of the errata eTSEC5 tsec->dmactrl &= ~(DMACTRL_GRS| DMACTRL_GTS | DMACTRL_WWR); //asm("sync"); tsec->dmactrl |= (DMACTRL_GRS| DMACTRL_GTS); /* FIX??? when should this be enabled?? memory interface snooping */ tsec->dmactrl |= (DMACTRL_TDSEN | DMACTRL_TBDSEN); tsec->attr |= ATTR_RDSEN | ATTR_RBDSEN; /* we clear halt upon transmit rather than let the hw poll */ tsec->dmactrl |= DMACTRL_WOP; while ((tsec->ievent & (IEVENT_GRSC| IEVENT_GTSC)) != (IEVENT_GRSC | IEVENT_GTSC)) { HAL_DELAY_US(1000); if (++i >= 100) { // os_printf("ETH Controller DMA stop failed, return from tsec_eth_reset\n"); HAL_RESTORE_INTERRUPTS(int_state); return false; } } //clear the graceful stop events tsec->ievent = IEVENT_GRSC | IEVENT_GTSC; tsec->dmactrl &= ~(DMACTRL_GRS| DMACTRL_GTS); /* Reset MAC for at least 3 TX clock cycle*/ tsec->maccfg1 = MACCFG1_SOFT_RESET; HAL_DELAY_US(1000); /* this should be long enought !! */ /* Clear soft reset */ tsec->maccfg1 = (MACCFG1_RXFLOW| MACCFG1_TXFLOW); txbd = tsec_eth_txring; rxbd = tsec_eth_rxring; /* Init Rx / Tx ring base */ qi->tbase = qi->txbd = txbd; qi->rbase = qi->rxbd = qi->rnext = rxbd; RxBUF = &tsec_eth_rxbufs[0]; TxBUF = &tsec_eth_txbufs[0]; /* Initialize Rx BDs */ for (i = 0; i < CYGNUM_DEVS_ETH_POWERPC_TSEC_RxNUM; i++) { rxbd->length = 0; rxbd->buffer = RxBUF; // interrupts are triggered once every 2 packages rxbd->ctrl = FEC_BD_Rx_Empty | ((i % 1 == 0) ? FEC_BD_Rx_Intr : 0); RxBUF += CYGNUM_DEVS_ETH_POWERPC_TSEC_BUFSIZE_RX; rxbd++; } rxbd--; rxbd->ctrl |= FEC_BD_Rx_Wrap; // Last buffer #if CACHE() HAL_DCACHE_FLUSH(tsec_eth_rxbufs, sizeof(tsec_eth_rxbufs)); HAL_DCACHE_FLUSH(tsec_eth_rxring, sizeof(tsec_eth_rxring)); #endif /* Initialize Tx BDs */ for (i = 0; i < CYGNUM_DEVS_ETH_POWERPC_TSEC_TxNUM; i++) { txbd->length = 0; txbd->buffer = TxBUF; // let interrupts happen every frame txbd->ctrl = FEC_BD_Tx_Intr; TxBUF += CYGNUM_DEVS_ETH_POWERPC_TSEC_BUFSIZE_TX; txbd++; } txbd--; txbd->ctrl |= FEC_BD_Tx_Wrap; // Last buffer #if CACHE() HAL_DCACHE_FLUSH(tsec_eth_txbufs, sizeof(tsec_eth_txbufs)); HAL_DCACHE_FLUSH(tsec_eth_txring, sizeof(tsec_eth_txring)); #endif /* Initialize shared PRAM */ tsec->rbase = tsec->rbptr = (cyg_uint32) (qi->rbase); tsec->tbase = tsec->tbptr = (cyg_uint32) (qi->tbase); /* Init default value */ tsec->maccfg2 = 0x00007000 | MACCFG2_IF_MODE_NIBBLE | MACCFG2_PAD_CRC | ((flags & RESET_FULL_DUPLEX) ? MACCFG2_FULL_DUPLEX : 0x0); tsec->ecntrl = ECNTRL_STEN | ECNTRL_RMM | ((flags & RESET_100MB) ? ECNTRL_R100M : 0); /* Disables all interrupts */ tsec->ievent = IEVENT_CLEAR_ALL; /* Init mask */ tsec->imask = IMASK_CLEAR_ALL; /* Size of receive buffers */ tsec->mrblr = CYGNUM_DEVS_ETH_POWERPC_TSEC_BUFSIZE_RX; /* Minimum size, 64 bytes */ tsec->minflr = 0x00000040; /* Rx / Tx control */ tsec->rctrl = 0x00000000; /* CC: TODO, double check what to do for VLAN tag */ tsec->tctrl = 0x00000000; //tsec->tctrl = 0x4; //related with DMACTRL_TOD /* Largest possible ethernet frame */ tsec->maxfrm = IEEE_8023_MAX_FRAME; //tsec->attr //tsec->fifo_tx_thr //tsec->fifo_tx_starve //tsec->fifo_tx_starve_shutoff // Group address hash tsec->gaddr[0] = 0; tsec->gaddr[1] = 0; tsec->gaddr[2] = 0; tsec->gaddr[3] = 0; tsec->gaddr[4] = 0; tsec->gaddr[5] = 0; tsec->gaddr[6] = 0; tsec->gaddr[7] = 0; tsec->igaddr[0] = 0; tsec->igaddr[1] = 0; tsec->igaddr[2] = 0; tsec->igaddr[3] = 0; tsec->igaddr[4] = 0; tsec->igaddr[5] = 0; tsec->igaddr[6] = 0; tsec->igaddr[7] = 0; // Init MIB memset((void *) &(tsec->rmon), 1, sizeof(struct rmon_tsec)); tsec->rmon.cam1 = 0xFFFFFFFF; tsec->rmon.cam2 = 0xFFFFFFFF; /* Device physical address */ tsec->macstnaddr1 = (cyg_uint32) ((cyg_uint32) enaddr[5] << 24 | (cyg_uint32) enaddr[4] << 16 | (cyg_uint32) enaddr[3] << 8 | (cyg_uint32) enaddr[2]); tsec->macstnaddr2 = (cyg_uint32) ((cyg_uint32) enaddr[1] << 24 | (cyg_uint32) enaddr[0] << 16); tsec->tstat = TSTAT_TXF; tsec->rstat = RSTAT_QHLT | RSTAT_RXF; tsec->dmactrl &= ~(DMACTRL_GRS| DMACTRL_GTS); /* Enable Tx / Rx */ tsec->maccfg1 |= (MACCFG1_RXEN| MACCFG1_TXEN); /* Umask interrupt */ #ifdef _TSEC_USE_INTS tsec->imask = IMASK_DEFAULT; #endif // //debug: // index_in_memory_area = 0; // stopper = 0; HAL_RESTORE_INTERRUPTS(int_state); return true; }
/**************************************************************************** Function: TskFunc_dacMode Description: This routine is the dual DAC mode example function. Inputs: none Returns: none ****************************************************************************/ void TskFunc_dacMode (void) { unsigned int p6228RegBaseAddr[4]; /* for all 4 VIM sites */ P6228_REG_ADDR p6228Regs[4]; /* for all 4 VIM sites */ P6228_BOARD_PARAMS p6228BoardParams[4]; /* for all 4 VIM sites */ P6228_DAC_PARAMS p6228DACParams[4]; /* for all 4 VIM sites */ unsigned int moduleId; int referenceClock; int cntr; volatile unsigned int flagDmaComplete[2]; volatile unsigned int loopCount = LOOP_COUNT; volatile unsigned int valid; puts ("[dacMode] Entry\n"); /* Turn all led's off */ P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED_ALL); /* turn on "running" indicator */ P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); /* Initialize the address resources for all the VIM sites: * Access Type = Power Pc * Base address = 0, for Power PC */ P4205VimInit(P4205_PPC_ACCESS, 0, p4205VimResource); puts ("[dacMode] Initialization\n"); /* Reset and Release All VIM sites */ P4205_RESET_VIM_ALL(P4205_BOARD_CNTL_STATUS); BaseboardDelayuS(10); P4205_RELEASE_VIM_ALL(P4205_BOARD_CNTL_STATUS); /* Detect if a VIM module is installed */ if( (P4205_MODULE_PRESENT_VIM(P4205_BOARD_CNTL_STATUS, TOP_VIM_ID)) \ == P4205_FALSE ) { /* Vim module is either not installed OR not seated properly */ P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED0); P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); puts("[dacMode] failed to locate a Vim module.\n"); TASK_EXIT(); } /* Initialize the DMA complete flags to zero */ flagDmaComplete[0] = 0; flagDmaComplete[1] = 0; /* get VIM base address, check module, allocate data table ----------- */ /* assign the 6228 register base addresses for VIM sites */ p6228RegBaseAddr[TOP_VIM_ID] = \ ((p4205VimResource[TOP_VIM_ID]).VimAccessBase) + \ P6228_CONTROL_ACCESS_SPACE; p6228RegBaseAddr[BOT_VIM_ID] = \ ((p4205VimResource[BOT_VIM_ID]).VimAccessBase) + \ P6228_CONTROL_ACCESS_SPACE; /* get module id; if module is not a 6228, indicate error */ moduleId = VIMGetModuleId((unsigned int *) p6228RegBaseAddr[TOP_VIM_ID]); if( moduleId != P6228_MODULE_ID ) { P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED0); P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); puts ("[dacMode] failed to locate the 6228.\n"); TASK_EXIT(); } /* Allocate system memory for top_dataTable buffer */ if( (top_dataTable = (int *)malloc((TABLE_SIZE*sizeof(int)) + \ HAL_DCACHE_LINE_SIZE)) \ == NULL ) { /* Failure in allocating memory from heap - check heap size */ P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED0); P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); puts("Unable to allocate memory for top_dataTable.\n"); TASK_EXIT(); } /* Align top_dataTable buffer for proper cache operations */ top_dataTable = (int *)(((int)top_dataTable + (HAL_DCACHE_LINE_SIZE-1)) & \ (~(HAL_DCACHE_LINE_SIZE-1))); /* Allocate system memory for bot_dataTable buffer */ if( (bot_dataTable = (int *)malloc((TABLE_SIZE*sizeof(int)) + \ HAL_DCACHE_LINE_SIZE)) \ == NULL ) { /* Failure in allocating memory from heap - check heap size */ P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED0); P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); puts("Unable to allocate memory for bot_dataTable.\n"); TASK_EXIT(); } /* Align bot_dataTable buffer for proper cache operations */ bot_dataTable = (int *)(((int)bot_dataTable + (HAL_DCACHE_LINE_SIZE-1)) & \ (~(HAL_DCACHE_LINE_SIZE-1))); /* Initialize the 6228 using library routines ----------------------- */ /* Initialize 6228 register address table */ P6228InitRegAddr (p6228RegBaseAddr[TOP_VIM_ID], &p6228Regs[TOP_VIM_ID]); P6228InitRegAddr (p6228RegBaseAddr[BOT_VIM_ID], &p6228Regs[BOT_VIM_ID]); /* Reset board registers to default values */ P6228ResetRegs (&p6228Regs[TOP_VIM_ID]); P6228ResetRegs (&p6228Regs[BOT_VIM_ID]); /* Set 6228 board parameter table to default values */ P6228SetBoardDefaults (&p6228BoardParams[TOP_VIM_ID]); P6228SetBoardDefaults (&p6228BoardParams[BOT_VIM_ID]); /* Set 6228 DAC parameter table to default values */ P6228SetDACDefaults (&p6228DACParams[TOP_VIM_ID]); P6228SetDACDefaults (&p6228DACParams[BOT_VIM_ID]); /* Modifications to default board parameters. ------------------------- * * Note: when board parameters are for registers addressable by VIM nodes * A or C (depending on installed location of the 6228), only TOP_VIM_ID * parameters are set. */ /* make the 6228 a sync master and terminate the sync bus */ p6228BoardParams[TOP_VIM_ID].syncControl = P6228_SYNC_BUS_MASTER; p6228BoardParams[TOP_VIM_ID].syncTermination = P6228_TERMINATED; /* set clock parameters based on use of internal or external clock */ if (CLOCK_SOURCE == INTERNAL) { p6228BoardParams[TOP_VIM_ID].clockSelect = P6228_ONBOARD_CLOCK; /* default */ p6228BoardParams[TOP_VIM_ID].onboardOscDisable = P6228_OSC_ENABLE; /* default */ referenceClock = INT_REF_CLOCK; } else /* using an external clock */ { p6228BoardParams[TOP_VIM_ID].clockSelect = P6228_EXT_CLOCK; p6228BoardParams[TOP_VIM_ID].onboardOscDisable = P6228_OSC_DISABLE; referenceClock = EXT_REF_CLOCK; } /* select FIFO clock source by selecting either P6228_DAC_CLK_SELECT or * P6228_DAC_CLK_BYPASS. * * When P6228_DAC_CLK_SELECT is chosen, the FIFO clock is from the * PLLLOCK pin on the DAC5686. A clock is present only when the * DAC5686's PLL is disabled and is not in dual clock mode. * * When P6228_DAC_CLK_BYPASS is selected, the FIFO clock is the VIM clock * supplied to the two DAC5686's on the 6228. */ p6228BoardParams[TOP_VIM_ID].DACClkSel = P6228_DAC_CLK_SELECT; p6228BoardParams[TOP_VIM_ID].DACPllVdd = P6228_PLL_VDD_DISABLE; p6228BoardParams[BOT_VIM_ID].DACClkSel = P6228_DAC_CLK_SELECT; p6228BoardParams[BOT_VIM_ID].DACPllVdd = P6228_PLL_VDD_DISABLE; /* packing mode - the program default packing mode is the ReadyFlow * default, P6228_PACK_MODE_CHANNEL_PACK. This can be changed using the * PACK_MODE define at the top of the program. The 6228 Packing Modes * do not specify if this data is real or complex. This information is * needed to generate the data table and the DATA_TYPE define is provided * with the PACK_MODE define above. */ p6228BoardParams[TOP_VIM_ID].packMode = PACK_MODE; p6228BoardParams[BOT_VIM_ID].packMode = PACK_MODE; /* Modifications to default DAC parameters. ------------------------ */ /* DAC full bypass mode - to use the DAC5686 in full bypass mode, the * DAC5686 must also be set to dual clock mode (P6228_DAC_DUAL_CLOCK). * The internal PLL must be disabled and the DAC Clock from the PLLLOCK * pin cannot be used. These are both board parameters. Parameters for * the DAC6586 at both VIM sites are set identically. */ p6228DACParams[TOP_VIM_ID].bypassMode = P6228_DAC_FULL_BYPASS_DISABLE; if (p6228DACParams[TOP_VIM_ID].bypassMode == P6228_DAC_FULL_BYPASS_ENABLE) { /* set for dual clock mode */ p6228DACParams[TOP_VIM_ID].dualClockMode = P6228_DAC_DUAL_CLOCK; /* set board parameters */ p6228BoardParams[TOP_VIM_ID].DACClkSel = P6228_DAC_CLK_BYPASS; p6228BoardParams[TOP_VIM_ID].DACPllVdd = P6228_PLL_VDD_DISABLE; } p6228DACParams[BOT_VIM_ID].bypassMode = P6228_DAC_FULL_BYPASS_DISABLE; if (p6228DACParams[BOT_VIM_ID].bypassMode == P6228_DAC_FULL_BYPASS_ENABLE) { /* set for dual clock mode */ p6228DACParams[BOT_VIM_ID].dualClockMode = P6228_DAC_DUAL_CLOCK; /* set board parameters */ p6228BoardParams[BOT_VIM_ID].DACClkSel = P6228_DAC_CLK_BYPASS; p6228BoardParams[BOT_VIM_ID].DACPllVdd = P6228_PLL_VDD_DISABLE; } /* if not in full bypass mode, we can choose between the PLL clock or * an internal divided clock for the DAC5686. The choice will determine * what clock we can use for the FIFO. */ else { if (p6228BoardParams[TOP_VIM_ID].DACPllVdd == P6228_PLL_VDD_ENABLE) { /* just to make sure we've bypassed the DAC clock when the PLL * is enabled. */ p6228BoardParams[TOP_VIM_ID].DACClkSel = P6228_DAC_CLK_BYPASS; /* select PLL divider ratio to X 1, X 2, X 4 or X 8 */ p6228DACParams[TOP_VIM_ID].pllDividerRatio = P6228_DAC_PLL_DIVIDER_RATIO_X_1; } if (p6228BoardParams[BOT_VIM_ID].DACPllVdd == P6228_PLL_VDD_ENABLE) { /* just to make sure we've bypassed the DAC clock when the PLL * is enabled. */ p6228BoardParams[BOT_VIM_ID].DACClkSel = P6228_DAC_CLK_BYPASS; /* select PLL divider ratio to X 1, X 2, X 4 or X 8 */ p6228DACParams[BOT_VIM_ID].pllDividerRatio = P6228_DAC_PLL_DIVIDER_RATIO_X_1; } /* if the PLL is disabled, we can select the VIM clock or the clock on * the DAC6586 PLLLOCK pin. By selecting FIR filter, the FIFO clock * will be the VIM clock divided by 2, 4, 8 or 16. */ p6228DACParams[TOP_VIM_ID].filterSelect = P6228_DAC_INTERP_FIR_FILTER_X_2; p6228DACParams[BOT_VIM_ID].filterSelect = P6228_DAC_INTERP_FIR_FILTER_X_2; } /* allow NCO sync */ p6228DACParams[TOP_VIM_ID].phstrSync = P6228_DAC_PHSTR_SYNC_ENABLED; p6228DACParams[BOT_VIM_ID].phstrSync = P6228_DAC_PHSTR_SYNC_ENABLED; /* nominally set gain */ p6228DACParams[TOP_VIM_ID].dacAGain = 0xFFF; p6228DACParams[TOP_VIM_ID].dacBGain = 0xFFF; p6228DACParams[BOT_VIM_ID].dacAGain = 0xFFF; p6228DACParams[BOT_VIM_ID].dacBGain = 0xFFF; /* our data table will always be two's compliment in this program */ p6228DACParams[TOP_VIM_ID].inputMode = P6228_DAC_DATA_IN_TWOS_COMPLIMENT; p6228DACParams[BOT_VIM_ID].inputMode = P6228_DAC_DATA_IN_TWOS_COMPLIMENT; /* Set up 6228 for program operation ------------------------------- */ /* Initialize Board Registers */ P6228InitBoardRegs(&p6228BoardParams[TOP_VIM_ID], &p6228Regs[TOP_VIM_ID]); P6228InitBoardRegs(&p6228BoardParams[BOT_VIM_ID], &p6228Regs[BOT_VIM_ID]); /* Initialize DAC Registers */ P6228InitDACRegs(referenceClock, &p6228DACParams[TOP_VIM_ID], &p6228BoardParams[TOP_VIM_ID], &p6228Regs[TOP_VIM_ID]); displayDACRegs(&p6228Regs[TOP_VIM_ID]); P6228InitDACRegs(referenceClock, &p6228DACParams[BOT_VIM_ID], &p6228BoardParams[BOT_VIM_ID], &p6228Regs[BOT_VIM_ID]); displayDACRegs(&p6228Regs[BOT_VIM_ID]); /* generate data table */ if (DAC_DATA_TYPE == DC_DAC_DATA) { /* set both halfs of every table word with a DC value */ for (cntr = 0; cntr < TABLE_SIZE; cntr++) top_dataTable [cntr] = 0x80008000; } else /* DAC_DATA_TYPE == AC_DAC_DATA */ { /* Calculate data tables - TABLE_SIZE, DATA_TYPE, DATA_SIZE and * PACK_MODE are defines at the top of the program. */ if (tableGen (top_dataTable, TABLE_SIZE, DATA_TYPE, DATA_SIZE, PACK_MODE) == 1) { P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED0); P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); puts ("[dacMode] invalid data table parameters specified.\n"); TASK_EXIT(); } } memcpy (bot_dataTable, top_dataTable, TABLE_SIZE*sizeof(int)); /* Set up BiFIFO --------------------------------------------------- */ /* check that the clock set up is valid */ if (P6228CalcBifoClock (&p6228BoardParams[TOP_VIM_ID], &p6228DACParams[TOP_VIM_ID], referenceClock) == -1) { P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED0); P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); puts ("[dacMode] Invalid clock set up.\n"); TASK_EXIT(); } if (P6228CalcBifoClock (&p6228BoardParams[BOT_VIM_ID], &p6228DACParams[BOT_VIM_ID], referenceClock) == -1) { P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED0); P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); puts ("[dacMode] Invalid clock set up.\n"); TASK_EXIT(); } /* Verify clock is valid for both VIM sites before flushing the BiFIFOs. */ do { valid = P6228_VALID_CLOCK_CHECK_REG(p6228Regs[TOP_VIM_ID].interruptStatus); BaseboardDelayuS(1); } while (!valid); do { valid = P6228_VALID_CLOCK_CHECK_REG(p6228Regs[BOT_VIM_ID].interruptStatus); BaseboardDelayuS(1); } while (!valid); /* Flush the Bifo, and program BIFO thresholds. */ P4205FlushVimBifo(p4205VimResource, /* Vim Resource base */ TOP_VIM_ID, /* Vim interface Id */ BIFOSIZE, /* BIFO Size */ BIFOSIZE-10, /* Output almost-full level */ 512, /* Output almost-empty level */ BIFOSIZE-10, /* Input almost-full level */ 512); /* Input almost-empty level */ P4205FlushVimBifo(p4205VimResource, /* Vim Resource base */ BOT_VIM_ID, /* Vim interface Id */ BIFOSIZE, /* BIFO Size */ BIFOSIZE-10, /* Output almost-full level */ 512, /* Output almost-empty level */ BIFOSIZE-10, /* Input almost-full level */ 512); /* Input almost-empty level */ /* Flush data to memory buffer and send first buffer of data */ /* Flush the cache before data transmit */ HAL_DCACHE_FLUSH(top_dataTable, (TABLE_SIZE*sizeof(int))); HAL_DCACHE_FLUSH(bot_dataTable, (TABLE_SIZE*sizeof(int))); /* if the DAC5686 is in PLL mode, check for PLL lock */ if (p6228BoardParams[TOP_VIM_ID].DACClkSel == P6228_DAC_CLK_BYPASS) { if (P6228_GET_DAC_CTRL_PLL_LOCK(p6228Regs[TOP_VIM_ID].dacControlStatus) == P6228_PLL_UNLOCKED) { P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED0); P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); puts ("[dacMode] DAC6586 PLL not locked.\n"); TASK_EXIT(); } } if (p6228BoardParams[BOT_VIM_ID].DACClkSel == P6228_DAC_CLK_BYPASS) { if (P6228_GET_DAC_CTRL_PLL_LOCK(p6228Regs[BOT_VIM_ID].dacControlStatus) == P6228_PLL_UNLOCKED) { P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED0); P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); puts ("[dacMode] DAC6586 PLL not locked.\n"); TASK_EXIT(); } } /* generate a sync signal to sync the DAC5686 */ if (!P6228SyncGenerate (&p6228Regs[TOP_VIM_ID])) { P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED0); P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); puts ("[dacMode] sync line held reset by another process.\n"); TASK_EXIT(); } /* Disable interrupts */ PLX9656DmaToPciIntDisable((p4205VimResource[TOP_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(TOP_VIM_ID%2)); PLX9656DmaToPciIntDisable((p4205VimResource[BOT_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(BOT_VIM_ID%2)); PLX9656DmaDoneIntDisable((p4205VimResource[TOP_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(TOP_VIM_ID%2)); PLX9656DmaDoneIntDisable((p4205VimResource[BOT_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(BOT_VIM_ID%2)); /* Pre-initialize DMA configuration parameters for data acquistion */ /* Abort any existing transfers */ PLX9656DmaAbort((p4205VimResource[TOP_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(TOP_VIM_ID%2)); PLX9656DmaAbort((p4205VimResource[BOT_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(BOT_VIM_ID%2)); /* Write DMA register values for Top Vim site */ PLX9656DmaSetup((p4205VimResource[TOP_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(TOP_VIM_ID%2), (PLX9656_DMAMODE_LCL_BUS_WIDTH_32_BIT | /* Mode */ PLX9656_DMAMODE_TA_READY_ENABLE | PLX9656_DMAMODE_LCL_BURST_ENABLE | PLX9656_DMAMODE_DONE_INT_DISABLE | PLX9656_DMAMODE_LCL_ADDR_CONSTANT | PLX9656_DMAMODE_DEMAND_MODE_DISABLE), (unsigned int) top_dataTable, /* PCI address */ (p4205VimResource[TOP_VIM_ID]).bifo, /* Local address */ (TABLE_SIZE*sizeof(int)), /* Transfer size */ (PLX9656_DMADPR_DESCRIPT_LOC_LCL | /* Descriptor */ PLX9656_DMADPR_END_OF_CHAIN_DISABLE | PLX9656_DMADPR_TERM_COUNT_INT_ENABLE | PLX9656_DMADPR_XFER_DIR_PCI2LCL)); PLX9656DmaSetup((p4205VimResource[BOT_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(BOT_VIM_ID%2), (PLX9656_DMAMODE_LCL_BUS_WIDTH_32_BIT | /* Mode */ PLX9656_DMAMODE_TA_READY_ENABLE | PLX9656_DMAMODE_LCL_BURST_ENABLE | PLX9656_DMAMODE_DONE_INT_DISABLE | PLX9656_DMAMODE_LCL_ADDR_CONSTANT | PLX9656_DMAMODE_DEMAND_MODE_DISABLE), (unsigned int) bot_dataTable, /* PCI address */ (p4205VimResource[BOT_VIM_ID]).bifo, /* Local address */ (TABLE_SIZE*sizeof(int)), /* Transfer size */ (PLX9656_DMADPR_DESCRIPT_LOC_LCL | /* Descriptor */ PLX9656_DMADPR_END_OF_CHAIN_DISABLE | PLX9656_DMADPR_TERM_COUNT_INT_ENABLE | PLX9656_DMADPR_XFER_DIR_PCI2LCL)); /* Start Top and Bottom VIM DMAs */ PLX9656_DMA_START((p4205VimResource[TOP_VIM_ID]).Plx9656Base, \ PLX9656_DMA_CH(TOP_VIM_ID%2)); PLX9656_DMA_START((p4205VimResource[BOT_VIM_ID]).Plx9656Base, \ PLX9656_DMA_CH(BOT_VIM_ID%2)); /* Wait until done */ while( !PLX9656_DMA_DONE((p4205VimResource[TOP_VIM_ID]).Plx9656Base, \ PLX9656_DMA_CH(TOP_VIM_ID%2)) ) ; while( !PLX9656_DMA_DONE((p4205VimResource[BOT_VIM_ID]).Plx9656Base, \ PLX9656_DMA_CH(BOT_VIM_ID%2)) ) ; /* Change to DMA Demand mode, and Enable DMA Done Interrupt */ PLX9656_DMA_SET_MODE((p4205VimResource[TOP_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(TOP_VIM_ID%2), (PLX9656_DMAMODE_LCL_BUS_WIDTH_32_BIT | /* Mode */ PLX9656_DMAMODE_TA_READY_ENABLE | PLX9656_DMAMODE_LCL_BURST_ENABLE | PLX9656_DMAMODE_DONE_INT_ENABLE | PLX9656_DMAMODE_LCL_ADDR_CONSTANT | PLX9656_DMAMODE_DEMAND_MODE_ENABLE)); PLX9656_DMA_SET_MODE((p4205VimResource[BOT_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(BOT_VIM_ID%2), (PLX9656_DMAMODE_LCL_BUS_WIDTH_32_BIT | /* Mode */ PLX9656_DMAMODE_TA_READY_ENABLE | PLX9656_DMAMODE_LCL_BURST_ENABLE | PLX9656_DMAMODE_DONE_INT_ENABLE | PLX9656_DMAMODE_LCL_ADDR_CONSTANT | PLX9656_DMAMODE_DEMAND_MODE_ENABLE)); /* Initialize interrupts ----------------------------------------- */ /* Note that the top and bottom VIM channels SHARE the SAME interrupt */ /* Clear any pending interrupt conditions */ PLX9656DmaIntClear((p4205VimResource[TOP_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(TOP_VIM_ID%2)); PLX9656DmaIntClear((p4205VimResource[BOT_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(BOT_VIM_ID%2)); /* Map PLX DMA complete interrupt handler into the dispatcher. The * PLXDmaDone_isr() interrupt handler will handle BOTH channels. */ cyg_drv_interrupt_create(P4205_GTMPP_INTVEC( \ (p4205VimResource[TOP_VIM_ID]). \ GT64260MPP.gppNum_Plx9656Int), // Interrupt vector 1, // priority - not used (cyg_addrword_t)flagDmaComplete, // User Data (cyg_ISR_t *)PLXDmaDone_isr, // Isr NULL, // No DSR &plxDma_hIntr, // Interrupt Handle &plxDma_oIntr); // Interrupt Object /* Attach the interrupt */ cyg_drv_interrupt_attach(plxDma_hIntr); /* Enable DMA Complete interrupt */ PLX9656DmaToPciIntEnable((p4205VimResource[TOP_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(TOP_VIM_ID%2)); PLX9656DmaDoneIntEnable((p4205VimResource[TOP_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(TOP_VIM_ID%2)); PLX9656DmaToPciIntEnable((p4205VimResource[BOT_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(BOT_VIM_ID%2)); PLX9656DmaDoneIntEnable((p4205VimResource[BOT_VIM_ID]).Plx9656Base, PLX9656_DMA_CH(BOT_VIM_ID%2)); /* Enable PLX9656 interrupt. Top and bottom VIMs are connected to the * same GPP pin. */ cyg_drv_interrupt_unmask(P4205_GTMPP_INTVEC( \ (p4205VimResource[TOP_VIM_ID]). \ GT64260MPP.gppNum_Plx9656Int)); /* Enable Direct BIFO Write Access for Demand mode */ P4205_VIM_DMA_RQST_BIFO_WRITE(p4205VimResource, TOP_VIM_ID); P4205_VIM_DMA_RQST_BIFO_WRITE(p4205VimResource, BOT_VIM_ID); /* main loop --------------------------------------------------- */ /* Turn third green LED to indicate main loop entry */ P4205_LED_ON(P4205_BOARD_CNTL_STATUS, P4205_FP_LED3); /* enable FIFO reads */ P6228_ENABLE_FIFO_READ(p6228Regs[TOP_VIM_ID].syncGateGenerator); P6228_REG_READ(p6228Regs[TOP_VIM_ID].syncGateGenerator); /* dummy read */ P6228_ENABLE_FIFO_READ(p6228Regs[BOT_VIM_ID].syncGateGenerator); P6228_REG_READ(p6228Regs[BOT_VIM_ID].syncGateGenerator); /* dummy read */ puts ("[dacMode] Running\n"); while (loopCount--) { /* Indicate activity */ P4205_LED_TOGGLE(P4205_BOARD_CNTL_STATUS, P4205_FP_LED3); /* Start Top VIM DMA */ PLX9656_DMA_START((p4205VimResource[TOP_VIM_ID]).Plx9656Base, \ PLX9656_DMA_CH(TOP_VIM_ID%2)); /* Start Bottom VIM DMA */ PLX9656_DMA_START((p4205VimResource[BOT_VIM_ID]).Plx9656Base, \ PLX9656_DMA_CH(BOT_VIM_ID%2)); /* Wait for DMAs to complete (flags set in ISR) */ while( !(flagDmaComplete[0]) && !(flagDmaComplete[1]) ) ; /* clear DMA complete flags */ flagDmaComplete[0] = 0; flagDmaComplete[1] = 0; } /* end if main loop */ /* turn off "running" and "activity" indicators */ P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED1); P4205_LED_OFF(P4205_BOARD_CNTL_STATUS, P4205_FP_LED3); free(top_dataTable); free(bot_dataTable); puts ("[dacMode] program done."); TASK_EXIT(); }
// // This routine is called to send data to the hardware. static void fcc_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total_len, unsigned long key) { struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private; struct fcc_bd *txbd, *txfirst; volatile char *bp; int i, txindex; int cache_state; HAL_DCACHE_IS_ENABLED(cache_state); #ifndef FCC_BDs_NONCACHED if (cache_state) { HAL_DCACHE_INVALIDATE(fcc_eth_txring, 8*CYGNUM_DEVS_ETH_POWERPC_FCC_TxNUM); } #endif // Find a free buffer txbd = txfirst = qi->txbd; while (txbd->ctrl & FCC_BD_Tx_Ready) { // This buffer is busy, move to next one if (txbd->ctrl & FCC_BD_Tx_Wrap) { txbd = qi->tbase; } else { txbd++; } if (txbd == txfirst) { #ifdef CYGPKG_NET panic ("No free xmit buffers"); #else os_printf("FCC Ethernet: No free xmit buffers\n"); #endif } } // Remember the next buffer to try if (txbd->ctrl & FCC_BD_Tx_Wrap) { qi->txbd = qi->tbase; } else { qi->txbd = txbd+1; } txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd); qi->txkey[txindex] = key; // Set up buffer txbd->length = total_len; bp = txbd->buffer; for (i = 0; i < sg_len; i++) { memcpy((void *)bp, (void *)sg_list[i].buf, sg_list[i].len); bp += sg_list[i].len; } // Make sure no stale data buffer ... if (cache_state) { HAL_DCACHE_FLUSH(txbd->buffer, txbd->length); } // Send it on it's way txbd->ctrl |= FCC_BD_Tx_Ready | FCC_BD_Tx_Last | FCC_BD_Tx_TC; #ifndef FCC_BDs_NONCACHED if (cache_state) { HAL_DCACHE_FLUSH(fcc_eth_txring, 8*CYGNUM_DEVS_ETH_POWERPC_FCC_TxNUM); } #endif }