/** * This sets up the receive 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 in ring mode or chain mode. * This function depends on the pcidev structure for allocation of 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 rx 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->RxDescCount 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_rx_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->RxDescCount = 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 Rx Descriptor Memory allocation in Ring mode\n"); return -ESYNOPGMACNOMEM; } DEBUG_MES("rx_first_desc_addr = %p\n", first_desc); DEBUG_MES("dmaadr = %p\n", dma_addr); gmacdev->RxDescCount = no_of_desc; gmacdev->RxDesc = (DmaDesc *)first_desc; gmacdev->RxDescDma = dma_addr; for(i =0; i < gmacdev->RxDescCount; i++){ synopGMAC_rx_desc_init_ring(gmacdev->RxDesc + i, i == gmacdev->RxDescCount-1); } gmacdev->RxNext = 0; gmacdev->RxBusy = 0; gmacdev->RxNextDesc = gmacdev->RxDesc; gmacdev->RxBusyDesc = gmacdev->RxDesc; gmacdev->BusyRxDesc = 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 back the descriptor from DMA after data has been received. * When the DMA indicates that the data is received (interrupt is generated), this function should be * called to get the descriptor and hence the data buffers received. With successful return from this * function caller gets the descriptor fields for processing. check the parameters to understand the * fields returned.` * @param[in] pointer to synopGMACdevice. * @param[out] pointer to hold the status of DMA. * @param[out] Dma-able buffer1 pointer. * @param[out] pointer to hold length of buffer1 (Max is 2048). * @param[out] virtual pointer for buffer1. * @param[out] Dma-able buffer2 pointer. * @param[out] pointer to hold length of buffer2 (Max is 2048). * @param[out] virtual pointer for buffer2. * \return returns present rx descriptor index on success. Negative value if error. */ s32 synopGMAC_get_rx_qptr(synopGMACdevice *gmacdev, u32 *Status, u32 *Buffer1, u32 *Length1, u32 *Data1, u32 *Buffer2, u32 *Length2, u32 *Data2) { u32 rxnext = gmacdev->RxBusy; // index of descriptor the DMA just completed. May be useful when data is spread over multiple buffers/descriptors DmaDesc *rxdesc = gmacdev->RxBusyDesc; if(synopGMAC_is_desc_owned_by_dma(rxdesc)) return -1; if(synopGMAC_is_desc_empty(rxdesc)) return -1; if(Status != 0) *Status = rxdesc->status;// send the status of this descriptor if(Length1 != 0) *Length1 = (rxdesc->length & DescSize1Mask) >> DescSize1Shift; if(Buffer1 != 0) *Buffer1 = rxdesc->buffer1; if(Data1 != 0) *Data1 = rxdesc->data1; if(Length2 != 0) *Length2 = (rxdesc->length & DescSize2Mask) >> DescSize2Shift; if(Buffer2 != 0) *Buffer2 = rxdesc->buffer2; if(Data1 != 0) *Data2 = rxdesc->data2; gmacdev->RxBusy = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? 0 : rxnext + 1; if(synopGMAC_is_rx_desc_chained(rxdesc)){ gmacdev->RxBusyDesc = (DmaDesc *)rxdesc->data2; synopGMAC_rx_desc_init_chain(rxdesc); // synopGMAC_desc_init_chain(rxdesc, synopGMAC_is_last_rx_desc(gmacdev,rxdesc),0,0); } else{ gmacdev->RxBusyDesc = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); synopGMAC_rx_desc_init_ring(rxdesc, synopGMAC_is_last_rx_desc(gmacdev,rxdesc)); // synopGMAC_rx_desc_recycle(rxdesc, synopGMAC_is_last_rx_desc(gmacdev,rxdesc)); } TR("%02d %08x %08x %08x %08x %08x %08x %08x\n",rxnext,(u32)rxdesc,rxdesc->status,rxdesc->length,rxdesc->buffer1,rxdesc->buffer2,rxdesc->data1,rxdesc->data2); (gmacdev->BusyRxDesc)--; //This returns one descriptor to processor. So busy count will be decremented by one return(rxnext); }