Пример #1
0
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;
    }
}
Пример #2
0
//
// 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

}
Пример #3
0
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
}
Пример #4
0
//
// 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

}
Пример #5
0
//
// 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;
}
Пример #6
0
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

}
Пример #7
0
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();
}
Пример #8
0
/**
*
* 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);
    }
    }

    
}
Пример #9
0
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
}
Пример #10
0
//
// 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);
}
Пример #11
0
// 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;
    }
}
Пример #12
0
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

}
Пример #13
0
/**
*
* 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);

    }
}
Пример #14
0
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();
}
Пример #15
0
//
// 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
}
Пример #16
0
//
// [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;
}
Пример #17
0
/****************************************************************************
 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();
}
Пример #18
0
//
// 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  

}