/** * This sets up the transmit Descriptor queue in ring or chain mode. * This function is tightly coupled to the platform and operating system * Device is interested only after the descriptors are setup. Therefore this function * is not included in the device driver API. This function should be treated as an * example code to design the descriptor structures for ring mode or chain mode. * This function depends on the pcidev structure for allocation consistent dma-able memory in case * of linux. * This limitation is due to the fact that linux uses pci structure to allocate a dmable memory * - Allocates the memory for the descriptors. * - Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor). * - Initialize the Busy and Next descriptors to first descriptor address. * - Initialize the last descriptor with the endof ring in case of ring mode. * - Initialize the descriptors in chain mode. * @param[in] pointer to synopGMACdevice. * @param[in] pointer to pci_device structure. * @param[in] number of descriptor expected in tx descriptor queue. * @param[in] whether descriptors to be created in RING mode or CHAIN mode. * \return 0 upon success. Error code upon failure. * \note This function fails if allocation fails for required number of descriptors in Ring mode, * but in chain mode * function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from * this function * user should for gmacdev->TxDescCount to see how many descriptors are there in the chain. Should * continue further * only if the number of descriptors in the chain meets the requirements */ s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice *gmacdev, u32 no_of_desc, u32 desc_mode) { s32 i; DmaDesc *bf1; DmaDesc *first_desc = NULL; dma_addr_t dma_addr; gmacdev->TxDescCount = 0; first_desc = (DmaDesc *)plat_alloc_consistent_dmaable_memory(gmacdev, sizeof(DmaDesc) * no_of_desc, &dma_addr); if (first_desc == NULL) { rt_kprintf("Error in Tx Descriptors memory allocation\n"); return -ESYNOPGMACNOMEM; } DEBUG_MES("tx_first_desc_addr = %p\n", first_desc); DEBUG_MES("dmaadr = %p\n", dma_addr); gmacdev->TxDescCount = no_of_desc; gmacdev->TxDesc = first_desc; gmacdev->TxDescDma = dma_addr; for (i = 0; i < gmacdev->TxDescCount; i++) { synopGMAC_tx_desc_init_ring(gmacdev->TxDesc + i, i == gmacdev->TxDescCount - 1); #if SYNOP_TOP_DEBUG rt_kprintf("\n%02d %08x \n", i, (unsigned int)(gmacdev->TxDesc + i)); rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i))->status); rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->length)); rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->buffer1)); rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->buffer2)); rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->data1)); rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->data2)); rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->dummy1)); rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->dummy2)); #endif } gmacdev->TxNext = 0; gmacdev->TxBusy = 0; gmacdev->TxNextDesc = gmacdev->TxDesc; gmacdev->TxBusyDesc = gmacdev->TxDesc; gmacdev->BusyTxDesc = 0; return -ESYNOPGMACNOERR; }
s32 synopGMAC_init_tx_rx_desc_queue(synopGMACdevice *gmacdev) { s32 i; for(i =0; i < gmacdev -> TxDescCount; i++){ synopGMAC_tx_desc_init_ring(gmacdev->TxDesc + i, i == gmacdev->TxDescCount-1); } TR("At line %d\n",__LINE__); for(i =0; i < gmacdev -> RxDescCount; i++){ synopGMAC_rx_desc_init_ring(gmacdev->RxDesc + i, i == gmacdev->RxDescCount-1); } gmacdev->TxNext = 0; gmacdev->TxBusy = 0; gmacdev->RxNext = 0; gmacdev->RxBusy = 0; return -ESYNOPGMACNOERR; }
/** * Get the index and address of Tx desc. * This api is same for both ring mode and chain mode. * This function tracks the tx descriptor the DMA just closed after the transmission of data from this descriptor is * over. This returns the descriptor fields to the caller. * @param[in] pointer to synopGMACdevice. * @param[out] status field of the descriptor. * @param[out] Dma-able buffer1 pointer. * @param[out] length of buffer1 (Max is 2048). * @param[out] virtual pointer for buffer1. * @param[out] Dma-able buffer2 pointer. * @param[out] length of buffer2 (Max is 2048). * @param[out] virtual pointer for buffer2. * @param[out] u32 data indicating whether the descriptor is in ring mode or chain mode. * \return returns present tx descriptor index on success. Negative value if error. */ s32 synopGMAC_get_tx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u32 * Data1, u32 * Buffer2, u32 * Length2, u32 * Data2 ) { u32 txover = gmacdev->TxBusy; DmaDesc *txdesc = gmacdev->TxBusyDesc; if(synopGMAC_is_desc_owned_by_dma(txdesc)) return -1; if(synopGMAC_is_desc_empty(txdesc)) return -1; (gmacdev->BusyTxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now if(Status != 0) *Status = txdesc->status; if(Buffer1 != 0) *Buffer1 = txdesc->buffer1; if(Length1 != 0) *Length1 = (txdesc->length & DescSize1Mask) >> DescSize1Shift; if(Data1 != 0) *Data1 = txdesc->data1; if(Buffer2 != 0) *Buffer2 = txdesc->buffer2; if(Length2 != 0) *Length2 = (txdesc->length & DescSize2Mask) >> DescSize2Shift; if(Data1 != 0) *Data2 = txdesc->data2; gmacdev->TxBusy = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? 0 : txover + 1; if(synopGMAC_is_tx_desc_chained(txdesc)){ gmacdev->TxBusyDesc = (DmaDesc *)txdesc->data2; synopGMAC_tx_desc_init_chain(txdesc); } else{ gmacdev->TxBusyDesc = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? gmacdev->TxDesc : (txdesc + 1); synopGMAC_tx_desc_init_ring(txdesc, synopGMAC_is_last_tx_desc(gmacdev,txdesc)); } TR("(get)%02d %08x %08x %08x %08x %08x %08x %08x\n",txover,(u32)txdesc,txdesc->status,txdesc->length,txdesc->buffer1,txdesc->buffer2,txdesc->data1,txdesc->data2); return txover; }