/** * mu3d_hal_alloc_qmu_mem - allocate gpd and bd memory for all ep * */ void mu3d_hal_alloc_qmu_mem(void) { DEV_UINT32 i, size; TGPD *ptr, *io_ptr; for (i = 1; i <= MAX_QMU_EP; i++) { /* Allocate Rx GPD */ size = (sizeof(TGPD) + AT_GPD_EXT_LEN) * MAX_GPD_NUM; ptr = (TGPD *) kmalloc(size, GFP_KERNEL); memset(ptr, 0, size); io_ptr = (TGPD *) dma_map_single(NULL, ptr, size, DMA_BIDIRECTIONAL); init_gpd_list(USB_RX, i, ptr, io_ptr, MAX_GPD_NUM); Rx_gpd_end[i] = ptr; qmu_printk(K_INFO, "ALLOC RX GPD End [%d] Virtual Mem=%p, DMA addr=%p\n", i, Rx_gpd_end[i], io_ptr); TGPD_CLR_FLAGS_HWO(Rx_gpd_end[i]); Rx_gpd_head[i] = Rx_gpd_last[i] = Rx_gpd_end[i]; qmu_printk(K_INFO, "RQSAR[%d]=%p\n", i, (void *)virt_to_phys(Rx_gpd_end[i])); /* Allocate Tx GPD */ size = (sizeof(TGPD) + AT_GPD_EXT_LEN) * MAX_GPD_NUM; ptr = (TGPD *) kmalloc(size, GFP_KERNEL); memset(ptr, 0, size); io_ptr = (TGPD *) dma_map_single(NULL, ptr, size, DMA_BIDIRECTIONAL); init_gpd_list(USB_TX, i, ptr, io_ptr, MAX_GPD_NUM); Tx_gpd_end[i] = ptr; qmu_printk(K_INFO, "ALLOC TX GPD End [%d] Virtual Mem=%p, DMA addr=%p\n", i, Tx_gpd_end[i], io_ptr); TGPD_CLR_FLAGS_HWO(Tx_gpd_end[i]); Tx_gpd_head[i] = Tx_gpd_last[i] = Tx_gpd_end[i]; qmu_printk(K_INFO, "TQSAR[%d]=%p\n", i, (void *)virt_to_phys(Tx_gpd_end[i])); } }
void _ex_mu3d_hal_alloc_qmu_mem(struct device *dev) { DEV_UINT32 i, size; TGPD *ptr; dma_addr_t io_ptr; dma_addr_t dma_handle; /*TODO: dma_pool_alloc() is an alternative choice once the memory size is a concern */ for ( i=1; i<=MAX_QMU_EP; i++) { /* Allocate Rx GPD */ size = (sizeof(TGPD) + AT_GPD_EXT_LEN) * MAX_GPD_NUM; ptr = (TGPD*)dma_alloc_coherent(dev, size, &dma_handle, GFP_KERNEL); memset(ptr, 0 , size); Rx_gpd_ioptr[i] = io_ptr = dma_handle ; init_gpd_list( USB_RX, i, ptr, io_ptr, MAX_GPD_NUM); Rx_gpd_end[i] = ptr; qmu_printk(K_INFO, "ALLOC RX GPD End [%d] Virtual Mem=%p, DMA addr=%08llx\n", i, Rx_gpd_end[i], (unsigned long long) io_ptr); TGPD_CLR_FLAGS_HWO(Rx_gpd_end[i]); Rx_gpd_head[i] = Rx_gpd_last[i] = Rx_gpd_end[i]; qmu_printk(K_INFO, "RQSAR[%d]=%08llx\n", i, (unsigned long long) mu3d_hal_gpd_virt_to_phys(Rx_gpd_end[i], USB_RX, i)); /* Allocate Tx GPD */ size = (sizeof(TGPD) + AT_GPD_EXT_LEN) * MAX_GPD_NUM; ptr = (TGPD*)dma_alloc_coherent(dev, size, &dma_handle, GFP_KERNEL); memset(ptr, 0 , size); Tx_gpd_ioptr[i] = io_ptr = dma_handle ; init_gpd_list( USB_TX, i, ptr, io_ptr, MAX_GPD_NUM); Tx_gpd_end[i]= ptr; qmu_printk(K_INFO, "ALLOC TX GPD End [%d] Virtual Mem=%p, DMA addr=%08llx\n", i, Tx_gpd_end[i], (unsigned long long) io_ptr); TGPD_CLR_FLAGS_HWO(Tx_gpd_end[i]); Tx_gpd_head[i] = Tx_gpd_last[i] = Tx_gpd_end[i]; qmu_printk(K_INFO, "TQSAR[%d]=%08llx\n", i, (unsigned long long) mu3d_hal_gpd_virt_to_phys(Tx_gpd_end[i], USB_TX, i)); } }
/** * mu3d_hal_prepare_rx_gpd - prepare rx gpd/bd * @args - arg1: gpd address, arg2: data buffer address, arg3: data length, arg4: ep number, arg5: with bd or not, arg6: write hwo bit or not, arg7: write ioc bit or not */ TGPD *mu3d_hal_prepare_rx_gpd(TGPD *gpd, dma_addr_t pBuf, DEV_UINT32 data_len, DEV_UINT8 ep_num, DEV_UINT8 _is_bdp, DEV_UINT8 isHWO, DEV_UINT8 ioc, DEV_UINT8 bps, DEV_UINT32 cMaxPacketSize) { qmu_printk(K_DEBUG, "[RX]" "%s gpd=%p, epnum=%d, len=%d\n", __func__, gpd, ep_num, data_len); /*Set actual data point to "DATA Buffer" */ TGPD_SET_DATA(gpd, pBuf); /*Clear "BDP(Buffer Descriptor Present)" flag */ TGPD_CLR_FORMAT_BDP(gpd); /* * Set "Allow Data Buffer Length" = * 0 (If data length > GPD buffer length, use BDs), * data_len (If data length < GPD buffer length, only use GPD) */ TGPD_SET_DataBUF_LEN(gpd, data_len); /*Set "Transferred Data Length" = 0 */ TGPD_SET_BUF_LEN(gpd, 0); /*Default: bps=false */ TGPD_CLR_FORMAT_BPS(gpd); /*Default: ioc=true */ TGPD_SET_FORMAT_IOC(gpd); /*Get the next GPD */ Rx_gpd_end[ep_num] = get_gpd(USB_RX, ep_num); qmu_printk(K_DEBUG, "[RX]" "Rx_gpd_end[%d]=%p gpd=%p\n", ep_num, Rx_gpd_end[ep_num], gpd); /* BUG_ON(!check_next_gpd(gpd, Rx_gpd_end[ep_num])); */ /*Initialize the new GPD */ memset(Rx_gpd_end[ep_num], 0, sizeof(TGPD) + AT_GPD_EXT_LEN); /*Clear "HWO(Hardware Own)" flag */ TGPD_CLR_FLAGS_HWO(Rx_gpd_end[ep_num]); /*Set Next GDP pointer to the next GPD */ TGPD_SET_NEXT(gpd, virt_to_phys(Rx_gpd_end[ep_num])); /*Default: isHWO=true */ TGPD_SET_CHKSUM(gpd, CHECKSUM_LENGTH); /*Set GPD Checksum */ TGPD_SET_FLAGS_HWO(gpd); /*Set HWO flag */ /* os_printk(K_DEBUG,"Rx gpd info { HWO %d, Next_GPD %x ,DataBufferLength %d, DataBuffer %x, Recived Len %d, Endpoint %d, TGL %d, ZLP %d}\n", */ /* (DEV_UINT32)TGPD_GET_FLAG(gpd), (DEV_UINT32)TGPD_GET_NEXT(gpd), */ /* (DEV_UINT32)TGPD_GET_DataBUF_LEN(gpd), (DEV_UINT32)TGPD_GET_DATA(gpd), */ /* (DEV_UINT32)TGPD_GET_BUF_LEN(gpd), (DEV_UINT32)TGPD_GET_EPaddr(gpd), */ /* (DEV_UINT32)TGPD_GET_TGL(gpd), (DEV_UINT32)TGPD_GET_ZLP(gpd)); */ /*Flush the data of GPD stuct to device */ dma_sync_single_for_device(NULL, virt_to_phys(gpd), sizeof(TGPD) + AT_GPD_EXT_LEN, DMA_TO_DEVICE); return gpd; }
/** * mu3d_hal_prepare_tx_gpd - prepare tx gpd/bd * @args - arg1: gpd address, arg2: data buffer address, arg3: data length, arg4: ep number, arg5: with bd or not, arg6: write hwo bit or not, arg7: write ioc bit or not */ TGPD *mu3d_hal_prepare_tx_gpd(TGPD *gpd, dma_addr_t pBuf, DEV_UINT32 data_len, DEV_UINT8 ep_num, DEV_UINT8 _is_bdp, DEV_UINT8 isHWO, DEV_UINT8 ioc, DEV_UINT8 bps, DEV_UINT8 zlp) { qmu_printk(K_DEBUG, "[TX]" "%s gpd=%p, epnum=%d, len=%d, _is_bdp=%d size(TGPD)=%d\n", __func__, gpd, ep_num, data_len, _is_bdp, sizeof(TGPD)); /*Set actual data point to "DATA Buffer" */ TGPD_SET_DATA(gpd, pBuf); /*Clear "BDP(Buffer Descriptor Present)" flag */ TGPD_CLR_FORMAT_BDP(gpd); /* * "Data Buffer Length" = * 0 (If data length > GPD buffer length, use BDs), * data_len (If data length < GPD buffer length, only use GPD) */ TGPD_SET_BUF_LEN(gpd, data_len); /*"GPD extension length" = 0. Does not use GPD EXT!! */ TGPD_SET_EXT_LEN(gpd, 0); /*Default: zlp=false, except type=ISOC */ TGPD_CLR_FORMAT_ZLP(gpd); /*Default: bps=false */ TGPD_CLR_FORMAT_BPS(gpd); /*Default: ioc=true */ TGPD_SET_FORMAT_IOC(gpd); /*Get the next GPD */ Tx_gpd_end[ep_num] = get_gpd(USB_TX, ep_num); qmu_printk(K_DEBUG, "[TX]" "Tx_gpd_end[%d]=%p\n", ep_num, Tx_gpd_end[ep_num]); /*Initialize the new GPD */ memset(Tx_gpd_end[ep_num], 0, sizeof(TGPD) + AT_GPD_EXT_LEN); /*Clear "HWO(Hardware Own)" flag */ TGPD_CLR_FLAGS_HWO(Tx_gpd_end[ep_num]); /*Set "Next GDP pointer" as the next GPD */ TGPD_SET_NEXT(gpd, virt_to_phys(Tx_gpd_end[ep_num])); /*Default: isHWO=true */ TGPD_SET_CHKSUM(gpd, CHECKSUM_LENGTH); /*Set GPD Checksum */ TGPD_SET_FLAGS_HWO(gpd); /*Set HWO flag */ /*Flush the data of GPD stuct to device */ dma_sync_single_for_device(NULL, virt_to_phys(gpd), sizeof(TGPD) + AT_GPD_EXT_LEN, DMA_TO_DEVICE); return gpd; }
/** * mu3d_hal_prepare_tx_gpd - prepare tx gpd/bd * @args - arg1: gpd address, arg2: data buffer address, arg3: data length, arg4: ep number, arg5: with bd or not, arg6: write hwo bit or not, arg7: write ioc bit or not */ TGPD* _ex_mu3d_hal_prepare_tx_gpd(TGPD* gpd, dma_addr_t pBuf, DEV_UINT32 data_len, DEV_UINT8 ep_num, DEV_UINT8 _is_bdp, DEV_UINT8 isHWO, DEV_UINT8 ioc, DEV_UINT8 bps, DEV_UINT8 zlp) { qmu_printk(K_DEBUG, "[TX]""%s gpd=%p, epnum=%d, len=%d, zlp=%d, size(TGPD)=%lld, pBuf=%08lx\n", __func__, \ gpd, ep_num, data_len, zlp, (u64)sizeof(TGPD), (unsigned long)pBuf); /*Set actual data point to "DATA Buffer"*/ TGPD_SET_DATA(gpd, (unsigned long)pBuf); /*Clear "BDP(Buffer Descriptor Present)" flag*/ TGPD_CLR_FORMAT_BDP(gpd); /* * "Data Buffer Length" = * 0 (If data length > GPD buffer length, use BDs), * data_len (If data length < GPD buffer length, only use GPD) */ TGPD_SET_BUF_LEN(gpd, data_len); /*"GPD extension length" = 0. Does not use GPD EXT!!*/ TGPD_SET_EXT_LEN(gpd, 0); if (zlp) TGPD_SET_FORMAT_ZLP(gpd); else TGPD_CLR_FORMAT_ZLP(gpd); /*Default: bps=false*/ TGPD_CLR_FORMAT_BPS(gpd); /*Default: ioc=true*/ TGPD_SET_FORMAT_IOC(gpd); /*Get the next GPD*/ Tx_gpd_end[ep_num] = get_gpd( USB_TX, ep_num); qmu_printk(K_DEBUG, "[TX]""Tx_gpd_end[%d]=%p\n", ep_num, Tx_gpd_end[ep_num]); /*Initialize the new GPD*/ memset(Tx_gpd_end[ep_num], 0, sizeof(TGPD)+AT_GPD_EXT_LEN); /*Clear "HWO(Hardware Own)" flag*/ TGPD_CLR_FLAGS_HWO(Tx_gpd_end[ep_num]); /*Set "Next GDP pointer" as the next GPD*/ TGPD_SET_NEXT(gpd, (unsigned long)mu3d_hal_gpd_virt_to_phys(Tx_gpd_end[ep_num], USB_TX, ep_num)); /*Default: isHWO=true*/ TGPD_SET_CHKSUM( gpd, CHECKSUM_LENGTH); /*Set GPD Checksum*/ TGPD_SET_FLAGS_HWO(gpd); /*Set HWO flag*/ return gpd; }
/** * mu3d_hal_prepare_rx_gpd - prepare rx gpd/bd * @args - arg1: gpd address, arg2: data buffer address, arg3: data length, arg4: ep number, arg5: with bd or not, arg6: write hwo bit or not, arg7: write ioc bit or not */ TGPD *mu3d_hal_prepare_rx_gpd(TGPD *gpd, dma_addr_t pBuf, DEV_UINT32 data_len, DEV_UINT8 ep_num, DEV_UINT8 _is_bdp, DEV_UINT8 isHWO, DEV_UINT8 ioc, DEV_UINT8 bps, DEV_UINT32 cMaxPacketSize) { DEV_UINT32 offset; DEV_INT32 i; DEV_INT32 bd_num; DEV_UINT32 length; TBD *bd_next; TBD *bd_head; TBD *bd; DEV_UINT8 *pBuffer; /*If data length is less than the GPD buffer size, just use GPD */ if (data_len < GPD_BUF_SIZE) { _is_bdp = 0; } os_printk(K_INFO, "%s gpd=%p, epnum=%d, len=%d, _is_bdp=%d, maxp=%d\n", __func__, gpd, ep_num, data_len, _is_bdp, cMaxPacketSize); if (!_is_bdp) { /*Set actual data point to "DATA Buffer" */ TGPD_SET_DATA(gpd, pBuf); /*Clear "BDP(Buffer Descriptor Present)" flag */ TGPD_CLR_FORMAT_BDP(gpd); } else { /*Get the first BD */ bd_head = (TBD *) get_bd(USB_RX, ep_num); os_printk(K_INFO, "bd_head=x%p\n", bd_head); bd = bd_head; os_memset(bd, 0, sizeof(TBD)); /*Date length for transfer */ length = data_len; /*Point of data buffer */ pBuffer = (DEV_UINT8 *) (pBuf); /*The size of BD buffer */ offset = BD_BUF_SIZE; /*Count how many BD this transfer need. */ bd_num = (!(length % offset)) ? (length / offset) : ((length / offset) + 1); os_printk(K_INFO, "%s bd_num=%d\n", __func__, bd_num); /*Insert data into each BD */ for (i = 0; i < bd_num; i++) { os_printk(K_INFO, "%s bd[%d]=%p\n", __func__, i, bd); if (i == (bd_num - 1)) { TBD_SET_BUF_LEN(bd, 0); /*Set "Transferred Data Length" = 0 */ /*The last one's data buffer lengnth must be precise, or the GPD will never done unless ZLP or short packet. */ /*"Allow Data Buffer Length" = the rest of data length* */ length = (!(length % cMaxPacketSize)) ? (length) : ((length / cMaxPacketSize) + 1) * cMaxPacketSize; TBD_SET_DataBUF_LEN(bd, length); TBD_SET_DATA(bd, pBuffer); /*Store the data pointer to "Data Buffer" */ TBD_SET_FLAGS_EOL(bd); /*Set "EOL" */ TBD_SET_NEXT(bd, 0); /*Set "Next BD pointer" = 0 */ TBD_SET_CHKSUM(bd, CHECKSUM_LENGTH); /*Set "BD Checksum" */ /*Flush the data of BD stuct to device */ dma_sync_single_for_device(NULL, bd_virt_to_phys(bd, USB_RX, ep_num), sizeof(TBD), DMA_BIDIRECTIONAL); break; } else { TBD_SET_BUF_LEN(bd, 0); /*Set "Transferred Data Length" = 0 */ /*"Allow Data Buffer Length" = the MAX BD transfer size */ TBD_SET_DataBUF_LEN(bd, offset); TBD_SET_DATA(bd, pBuffer); /*Store the data pointer to "Data Buffer" */ TBD_CLR_FLAGS_EOL(bd); /*Clear "EOL" */ /*Get the next BD */ bd_next = (TBD *) get_bd(USB_RX, ep_num); os_memset(bd_next, 0, sizeof(TBD)); /*Set "Next BD pointer" as the next BD */ TBD_SET_NEXT(bd, bd_virt_to_phys(bd_next, USB_RX, ep_num)); TBD_SET_CHKSUM(bd, CHECKSUM_LENGTH); /*Set BD Checksum */ /*Flush the data of BD stuct to device */ dma_sync_single_for_device(NULL, bd_virt_to_phys(bd, USB_RX, ep_num), sizeof(TBD), DMA_BIDIRECTIONAL); /*Calculate the left data length */ length -= offset; /*Move to pointer of buffer */ pBuffer += offset; /*Move to next BD */ bd = bd_next; } } /*Set the BD pointer into "BD Pointer" at GPD */ TGPD_SET_DATA(gpd, bd_virt_to_phys(bd_head, USB_RX, ep_num)); /*Set "BDP(Buffer Descriptor Present)" flag */ TGPD_SET_FORMAT_BDP(gpd); } os_printk(K_INFO, "%s GPD data_length=%d\n", __func__, data_len); /* * Set "Allow Data Buffer Length" = * 0 (If data length > GPD buffer length, use BDs), * data_len (If data length < GPD buffer length, only use GPD) */ TGPD_SET_DataBUF_LEN(gpd, data_len); /* TGPD_SET_DataBUF_LEN(gpd, gpd_buf_size); */ /*Set "Transferred Data Length" = 0 */ TGPD_SET_BUF_LEN(gpd, 0); /*Default: bps=false */ if (bps) TGPD_SET_FORMAT_BPS(gpd); else TGPD_CLR_FORMAT_BPS(gpd); /*Default: ioc=true */ if (ioc) TGPD_SET_FORMAT_IOC(gpd); else TGPD_CLR_FORMAT_IOC(gpd); /*Get the next GPD */ Rx_gpd_end[ep_num] = get_gpd(USB_RX, ep_num); os_printk(K_INFO, "%s Rx_gpd_end[%d]=%p\n", __func__, ep_num, Tx_gpd_end[ep_num]); /*Initialize the new GPD */ os_memset(Rx_gpd_end[ep_num], 0, sizeof(TGPD)); /*Clear "HWO(Hardware Own)" flag */ TGPD_CLR_FLAGS_HWO(Rx_gpd_end[ep_num]); /*Set Next GDP pointer to the next GPD */ TGPD_SET_NEXT(gpd, mu3d_hal_gpd_virt_to_phys(Rx_gpd_end[ep_num], USB_RX, ep_num)); /*Default: isHWO=true */ if (isHWO) { TGPD_SET_CHKSUM(gpd, CHECKSUM_LENGTH); /*Set GPD Checksum */ TGPD_SET_FLAGS_HWO(gpd); /*Set HWO flag */ } else { TGPD_CLR_FLAGS_HWO(gpd); TGPD_SET_CHKSUM_HWO(gpd, CHECKSUM_LENGTH); } /* os_printk(K_DEBUG,"Rx gpd info { HWO %d, Next_GPD %x ,DataBufferLength %d, DataBuffer %x, Recived Len %d, Endpoint %d, TGL %d, ZLP %d}\n", */ /* (DEV_UINT32)TGPD_GET_FLAG(gpd), (DEV_UINT32)TGPD_GET_NEXT(gpd), */ /* (DEV_UINT32)TGPD_GET_DataBUF_LEN(gpd), (DEV_UINT32)TGPD_GET_DATA(gpd), */ /* (DEV_UINT32)TGPD_GET_BUF_LEN(gpd), (DEV_UINT32)TGPD_GET_EPaddr(gpd), */ /* (DEV_UINT32)TGPD_GET_TGL(gpd), (DEV_UINT32)TGPD_GET_ZLP(gpd)); */ /*Flush the data of GPD stuct to device */ dma_sync_single_for_device(NULL, mu3d_hal_gpd_virt_to_phys(gpd, USB_RX, ep_num), sizeof(TGPD), DMA_BIDIRECTIONAL); return gpd; }
/** * mu3d_hal_prepare_tx_gpd - prepare tx gpd/bd * @args - arg1: gpd address, arg2: data buffer address, arg3: data length, arg4: ep number, arg5: with bd or not, arg6: write hwo bit or not, arg7: write ioc bit or not */ TGPD *mu3d_hal_prepare_tx_gpd(TGPD *gpd, dma_addr_t pBuf, DEV_UINT32 data_len, DEV_UINT8 ep_num, DEV_UINT8 _is_bdp, DEV_UINT8 isHWO, DEV_UINT8 ioc, DEV_UINT8 bps, DEV_UINT8 zlp) { DEV_UINT32 offset; DEV_INT32 i; DEV_INT32 bd_num; DEV_UINT32 length; TBD *bd_next; TBD *bd_head; TBD *bd; DEV_UINT8 *pBuffer; /*If data length is less than the GPD buffer size, just use GPD */ /* if (data_len <= GPD_BUF_SIZE) { */ /* _is_bdp = 0; */ /* } */ os_printk(K_INFO, "%s gpd=%p, epnum=%d, len=%d, _is_bdp=%d\n", __func__, gpd, ep_num, data_len, _is_bdp); if (!_is_bdp) { /*Set actual data point to "DATA Buffer" */ TGPD_SET_DATA(gpd, pBuf); /*Clear "BDP(Buffer Descriptor Present)" flag */ TGPD_CLR_FORMAT_BDP(gpd); } else { /*Get the first BD */ bd_head = (TBD *) get_bd(USB_TX, ep_num); os_printk(K_INFO, "bd_head=x%p\n", bd_head); bd = bd_head; os_memset(bd, 0, sizeof(TBD)); /*Date length for transfer */ length = data_len; /*Point of data buffer */ pBuffer = (DEV_UINT8 *) (pBuf); /*The size of BD buffer */ offset = BD_BUF_SIZE; /*Count how many BD this transfer need. */ bd_num = (!(length % offset)) ? (length / offset) : ((length / offset) + 1); os_printk(K_INFO, "bd_num=%d\n", bd_num); /*If the size of BD buffer is bigger than the length of actual transfer, use the actual length */ if (offset > length) offset = length; /*Insert data into each BD */ for (i = 0; i < bd_num; i++) { os_printk(K_INFO, "bd[%d]=%p\n", i, bd); if (i == (bd_num - 1)) { /*The last BD */ TBD_SET_EXT_LEN(bd, 0); /*"BD Extension Length" = 0. Does not use BD EXT!! */ TBD_SET_BUF_LEN(bd, length); /*"Data Buffer Length" = the rest of data length */ TBD_SET_DATA(bd, pBuffer); /*Store the data pointer to "Data Buffer" */ TBD_SET_FLAGS_EOL(bd); /*Set "EOL" */ TBD_SET_NEXT(bd, 0); /*Set "Next BD pointer" = 0 */ TBD_SET_CHKSUM(bd, CHECKSUM_LENGTH); /*Set "BD Checksum" */ /*Flush the data of BD stuct to device */ dma_sync_single_for_device(NULL, bd_virt_to_phys(bd, USB_RX, ep_num), sizeof(TBD), DMA_BIDIRECTIONAL); /*There is no data left to be transfered by GPD */ /* data_len=length; */ data_len = 0; /*There is no data left to insert BD */ length = 0; } else { TBD_SET_EXT_LEN(bd, 0); /*"BD Extension length" = 0. Does not use BD EXT!! */ TBD_SET_BUF_LEN(bd, offset); /*"Data Buffer Length" = the MAX BD transfer size */ TBD_SET_DATA(bd, pBuffer); /*Store the data pointer to "Data Buffer" */ TBD_CLR_FLAGS_EOL(bd); /*Clear "EOL" */ /*Get the next BD */ bd_next = (TBD *) get_bd(USB_TX, ep_num); os_memset(bd_next, 0, sizeof(TBD)); /*Set "Next BD pointer" as the next BD */ TBD_SET_NEXT(bd, bd_virt_to_phys(bd_next, USB_TX, ep_num)); TBD_SET_CHKSUM(bd, CHECKSUM_LENGTH); /*Set BD Checksum */ /*Flush the data of BD stuct to device */ dma_sync_single_for_device(NULL, bd_virt_to_phys(bd, USB_RX, ep_num), sizeof(TBD), DMA_BIDIRECTIONAL); /*Calculate the left data length */ length -= offset; /*Move to pointer of buffer */ pBuffer += offset; /*Move to next BD */ bd = bd_next; } } /*Set the BD pointer into "BD Pointer" at GPD */ TGPD_SET_DATA(gpd, bd_virt_to_phys(bd_head, USB_TX, ep_num)); /*Set "BDP(Buffer Descriptor Present)" flag */ TGPD_SET_FORMAT_BDP(gpd); } os_printk(K_INFO, "%s GPD data_length=%d\n", __func__, data_len); /* * "Data Buffer Length" = * 0 (If data length > GPD buffer length, use BDs), * data_len (If data length < GPD buffer length, only use GPD) */ TGPD_SET_BUF_LEN(gpd, data_len); /*"GPD extension length" = 0. Does not use GPD EXT!! */ TGPD_SET_EXT_LEN(gpd, 0); /*Default: zlp=false, except type=ISOC */ if (zlp) TGPD_SET_FORMAT_ZLP(gpd); else TGPD_CLR_FORMAT_ZLP(gpd); /*Default: bps=false */ if (bps) TGPD_SET_FORMAT_BPS(gpd); else TGPD_CLR_FORMAT_BPS(gpd); /*Default: ioc=true */ if (ioc) TGPD_SET_FORMAT_IOC(gpd); else TGPD_CLR_FORMAT_IOC(gpd); /*Get the next GPD */ Tx_gpd_end[ep_num] = get_gpd(USB_TX, ep_num); os_printk(K_INFO, "Tx_gpd_end[%d]=%p\n", ep_num, Tx_gpd_end[ep_num]); /*Initialize the new GPD */ os_memset(Tx_gpd_end[ep_num], 0, sizeof(TGPD)); /*Clear "HWO(Hardware Own)" flag */ TGPD_CLR_FLAGS_HWO(Tx_gpd_end[ep_num]); /*Set "Next GDP pointer" as the next GPD */ TGPD_SET_NEXT(gpd, mu3d_hal_gpd_virt_to_phys(Tx_gpd_end[ep_num], USB_TX, ep_num)); /*Default: isHWO=true */ if (isHWO) { TGPD_SET_CHKSUM(gpd, CHECKSUM_LENGTH); /*Set GPD Checksum */ TGPD_SET_FLAGS_HWO(gpd); /*Set HWO flag */ } else { TGPD_CLR_FLAGS_HWO(gpd); TGPD_SET_CHKSUM_HWO(gpd, CHECKSUM_LENGTH); } /*Flush the data of GPD stuct to device */ dma_sync_single_for_device(NULL, mu3d_hal_gpd_virt_to_phys(gpd, USB_TX, ep_num), sizeof(TGPD), DMA_BIDIRECTIONAL); #if defined(USB_RISC_CACHE_ENABLED) os_flushinvalidateDcache(); #endif return gpd; }
/** * mu3d_hal_alloc_qmu_mem - allocate gpd and bd memory for all ep * */ void mu3d_hal_alloc_qmu_mem(void) { DEV_UINT32 i, size; TGPD *ptr, *io_ptr; TBD *bptr, *io_bptr; for (i = 1; i <= MAX_QMU_EP; i++) { /* Allocate Tx GPD */ size = sizeof(TGPD); size *= MAX_GPD_NUM; ptr = (TGPD *) os_mem_alloc(size); os_memset(ptr, 0, size); io_ptr = (TGPD *) dma_map_single(NULL, ptr, size, DMA_TO_DEVICE); /* io_ptr = (TGPD*)os_ioremap(os_virt_to_phys(ptr),size); */ /* io_ptr = (TGPD*)(os_virt_to_phys(ptr)); */ /* init_gpd_list(USB_RX,i,ptr,io_ptr,MAX_GPD_NUM); */ init_gpd_list(USB_RX, i, ptr, io_ptr, MAX_GPD_NUM); Rx_gpd_end[i] = ptr; os_printk(K_DEBUG, "ALLOC RX GPD End [%d] Virtual Mem=%p, DMA addr=%p\n", i, Rx_gpd_end[i], io_ptr); /* os_memset(Rx_gpd_end[i], 0 , sizeof(TGPD)); */ TGPD_CLR_FLAGS_HWO(Rx_gpd_end[i]); Rx_gpd_head[i] = Rx_gpd_last[i] = Rx_gpd_end[i]; os_printk(K_DEBUG, "RQSAR[%d]=%p\n", i, (void *)mu3d_hal_gpd_virt_to_phys(Rx_gpd_end[i], USB_RX, i)); /* Allocate Rx GPD */ size = sizeof(TGPD); size += AT_GPD_EXT_LEN; size *= MAX_GPD_NUM; ptr = (TGPD *) os_mem_alloc(size); os_memset(ptr, 0, size); io_ptr = (TGPD *) dma_map_single(NULL, ptr, size, DMA_TO_DEVICE); /* io_ptr = (TGPD*)os_ioremap(os_virt_to_phys(ptr),size); */ init_gpd_list(USB_TX, i, ptr, io_ptr, MAX_GPD_NUM); Tx_gpd_end[i] = ptr; os_printk(K_DEBUG, "ALLOC TX GPD End [%d] Virtual Mem=%p, DMA addr=%p\n", i, Tx_gpd_end[i], io_ptr); /* os_memset(Tx_gpd_end[i], 0 , sizeof(TGPD)+AT_GPD_EXT_LEN); */ TGPD_CLR_FLAGS_HWO(Tx_gpd_end[i]); Tx_gpd_head[i] = Tx_gpd_last[i] = Tx_gpd_end[i]; os_printk(K_DEBUG, "TQSAR[%d]=%p\n", i, (void *)mu3d_hal_gpd_virt_to_phys(Tx_gpd_end[i], USB_TX, i)); /* Allocate Tx BD */ size = (sizeof(TBD)); size *= MAX_BD_NUM; bptr = (TBD *) os_mem_alloc(size); os_memset(bptr, 0, size); io_bptr = (TBD *) dma_map_single(NULL, bptr, size, DMA_TO_DEVICE); /* io_bptr = (TBD*)os_ioremap(os_virt_to_phys(bptr),size); */ init_bd_list(USB_RX, i, bptr, io_bptr, MAX_BD_NUM); /* Allocate Rx BD */ size = (sizeof(TBD)); size += AT_BD_EXT_LEN; size *= MAX_BD_NUM; bptr = (TBD *) os_mem_alloc(size); os_memset(bptr, 0, size); io_bptr = (TBD *) dma_map_single(NULL, bptr, size, DMA_TO_DEVICE); /* io_bptr = (TBD*)os_ioremap(os_virt_to_phys(bptr),size); */ init_bd_list(USB_TX, i, bptr, io_bptr, MAX_BD_NUM); } }