/* This function checks if parameters are appropriate for DMA, and if they are, it sets up for DMA. If return value is false, caller may use PIO for this transfer. If return value is true, caller must issue a DMA ATA command and then call ata_dma_finish(). */ bool ata_dma_setup(void *addr, unsigned long bytes, bool write) { /* Require cacheline alignment for reads to prevent interference. */ if (!write && ((unsigned long)addr & 15)) return false; /* Writes only need to be word-aligned, but by default DMA * is not used for writing as it appears to be slower. */ #ifdef ATA_DMA_WRITES if (write && ((unsigned long)addr & 3)) return false; #else if (write) return false; #endif #if ATA_MAX_UDMA > 2 if (dma_needs_boost && !dma_boosted) { cpu_boost(true); dma_boosted = true; } #endif if (write) { /* If unflushed, old data may be written to disk */ commit_dcache(); } else { /* Invalidate cache because new data may be present in RAM */ commit_discard_dcache(); } /* Clear pending interrupts so ata_dma_finish() can wait for an interrupt from this transfer */ IDE0_CFG |= IDE_CFG_INTRQ; IDE_DMA_CONTROL |= 2; IDE_DMA_LENGTH = bytes - 4; #if !defined(BOOTLOADER) || defined (HAVE_BOOTLOADER_USB_MODE) if ((unsigned long)addr < DRAM_START) /* Rockbox remaps DRAM to start at 0 */ IDE_DMA_ADDR = (unsigned long)addr + DRAM_START; else #endif IDE_DMA_ADDR = (unsigned long)addr; if (write) IDE_DMA_CONTROL &= ~IDE_DMA_CONTROL_READ; else IDE_DMA_CONTROL |= IDE_DMA_CONTROL_READ; IDE0_CFG |= 0x8000; return true; }
void usb_storage_init_connection(void) { logf("ums: set config"); /* prime rx endpoint. We only need room for commands */ state = WAITING_FOR_COMMAND; #if (CONFIG_CPU == IMX31L || defined(CPU_TCC77X) || defined(CPU_TCC780X) || \ defined(BOOTLOADER) || CONFIG_CPU == DM320) && !defined(CPU_PP502x) static unsigned char _cbw_buffer[MAX_CBW_SIZE] USB_DEVBSS_ATTR __attribute__((aligned(32))); cbw_buffer = (void *)_cbw_buffer; static unsigned char _transfer_buffer[ALLOCATE_BUFFER_SIZE] USB_DEVBSS_ATTR __attribute__((aligned(32))); tb.transfer_buffer = (void *)_transfer_buffer; #ifdef USB_USE_RAMDISK static unsigned char _ramdisk_buffer[RAMDISK_SIZE*SECTOR_SIZE]; ramdisk_buffer = _ramdisk_buffer; #endif #else /* TODO : check if bufsize is at least 32K ? */ size_t bufsize; unsigned char * audio_buffer; audio_buffer = audio_get_buffer(false,&bufsize); #if defined(UNCACHED_ADDR) && CONFIG_CPU != AS3525 cbw_buffer = (void *)UNCACHED_ADDR((unsigned int)(audio_buffer+31) & 0xffffffe0); #else cbw_buffer = (void *)((unsigned int)(audio_buffer+31) & 0xffffffe0); #endif tb.transfer_buffer = cbw_buffer + MAX_CBW_SIZE; commit_discard_dcache(); #ifdef USB_USE_RAMDISK ramdisk_buffer = tb.transfer_buffer + ALLOCATE_BUFFER_SIZE; #endif #endif usb_drv_recv(ep_out, cbw_buffer, MAX_CBW_SIZE); int i; for(i=0;i<storage_num_drives();i++) { locked[i] = false; ejected[i] = !check_disk_present(IF_MD(i)); queue_broadcast(SYS_USB_LUN_LOCKED, (i<<16)+0); } }
static int ceata_rw_multiple_block(bool write, void* buf, uint32_t count, long timeout) { mmc_discard_irq(); uint32_t responsetype; uint32_t cmdtype; uint32_t direction; if (write) { cmdtype = SDCI_CMD_CMD_TYPE_ADTC | SDCI_CMD_CMD_RD_WR; responsetype = SDCI_CMD_RES_TYPE_R1 | SDCI_CMD_RES_BUSY; direction = MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_DIRECTION_WRITE; } else { cmdtype = SDCI_CMD_CMD_TYPE_ADTC; responsetype = SDCI_CMD_RES_TYPE_R1; direction = MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_DIRECTION_READ; } SDCI_DMASIZE = 0x200; SDCI_DMAADDR = buf; SDCI_DMACOUNT = count; SDCI_DCTRL = SDCI_DCTRL_TXFIFORST | SDCI_DCTRL_RXFIFORST; commit_discard_dcache(); PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_CEATA_RW_MULTIPLE_BLOCK) | SDCI_CMD_CMD_TYPE_ADTC | cmdtype | responsetype | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, direction | MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_COUNT(count), NULL, CEATA_COMMAND_TIMEOUT), 4, 0); if (write) SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX; if (semaphore_wait(&mmc_wakeup, timeout) == OBJ_WAIT_TIMEDOUT) { PASS_RC(ceata_cancel_command(), 4, 1); RET_ERR(2); } PASS_RC(mmc_dsta_check_data_success(), 4, 3); if (semaphore_wait(&mmc_comp_wakeup, timeout) == OBJ_WAIT_TIMEDOUT) { PASS_RC(ceata_cancel_command(), 4, 4); RET_ERR(4); } PASS_RC(ceata_check_error(), 4, 5); return 0; }
static int ceata_read_multiple_register(uint32_t addr, void* dest, uint32_t size) { if (size > 0x10) RET_ERR(0); mmc_discard_irq(); SDCI_DMASIZE = size; SDCI_DMACOUNT = 1; SDCI_DMAADDR = dest; SDCI_DCTRL = SDCI_DCTRL_TXFIFORST | SDCI_DCTRL_RXFIFORST; commit_discard_dcache(); PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_CEATA_RW_MULTIPLE_REG) | SDCI_CMD_CMD_TYPE_ADTC | SDCI_CMD_RES_TYPE_R1 | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, MMC_CMD_CEATA_RW_MULTIPLE_REG_DIRECTION_READ | MMC_CMD_CEATA_RW_MULTIPLE_REG_ADDRESS(addr & 0xfc) | MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT(size & 0xfc), NULL, CEATA_COMMAND_TIMEOUT), 2, 1); if (semaphore_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000) == OBJ_WAIT_TIMEDOUT) RET_ERR(2); PASS_RC(mmc_dsta_check_data_success(), 2, 3); return 0; }
static inline void discard_dma_buffer_cache(void) { commit_discard_dcache(); }