void *memcpy_fromio(void *dest, unsigned long src, size_t count) { unsigned long pa = iopa((unsigned long) src); if (is_pci_mem(pa)) idma_pci9_read((u8 *)dest, (u8 *)pa, count, 32, 1); else memcpy(dest, (void *)src, count); return dest; }
unsigned readl(volatile unsigned *addr) { u32 val; unsigned long pa = iopa((unsigned long) addr); if (!is_pci_mem(pa)) return in_le32(addr); idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0); return swab32(val); }
int readw(volatile unsigned short *addr) { u16 val; unsigned long pa = iopa((unsigned long) addr); if (!is_pci_mem(pa)) return in_le16(addr); idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0); return swab16(val); }
int readb(volatile unsigned char *addr) { u8 val; unsigned long pa = iopa((unsigned long) addr); if (!is_pci_mem(pa)) return in_8(addr); idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0); return val; }
/* * Enable (start) the DMA described by the sgl handle. */ static __inline__ void ppc4xx_enable_dma_sgl(sgl_handle_t handle) { sgl_list_info_t *psgl = (sgl_list_info_t *) handle; ppc_dma_ch_t *p_dma_ch; uint32_t sg_command; if (!handle) { printk("ppc4xx_enable_dma_sgl: null handle\n"); return; } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) { printk("ppc4xx_enable_dma_sgl: bad channel in handle %d\n", psgl->dmanr); return; } else if (!psgl->phead) { printk("ppc4xx_enable_dma_sgl: sg list empty\n"); return; } p_dma_ch = &dma_channels[psgl->dmanr]; psgl->ptail->control_count &= ~SG_LINK; /* make this the last dscrptr */ sg_command = mfdcr(DCRN_ASGC); ppc4xx_set_sg_addr(psgl->dmanr, iopa((unsigned long)psgl->phead)); switch (psgl->dmanr) { case 0: sg_command |= SSG0_ENABLE; break; case 1: sg_command |= SSG1_ENABLE; break; case 2: sg_command |= SSG2_ENABLE; break; case 3: sg_command |= SSG3_ENABLE; break; default: printk("ppc4xx_enable_dma_sgl: bad channel: %d\n", psgl->dmanr); } mtdcr(DCRN_ASGC, sg_command); /* start transfer */ }
/* * Add a new sgl descriptor to the end of a scatter/gather list * which was created by alloc_dma_handle(). * * For a memory to memory transfer, both dma addresses must be * valid. For a peripheral to memory transfer, one of the addresses * must be set to NULL, depending on the direction of the transfer: * memory to peripheral: set dst_addr to NULL, * peripheral to memory: set src_addr to NULL. */ static __inline__ int ppc4xx_add_dma_sgl(sgl_handle_t handle, phys_addr_t src_addr, phys_addr_t dst_addr, unsigned int count) { sgl_list_info_t *psgl = (sgl_list_info_t *) handle; ppc_dma_ch_t *p_dma_ch; if (!handle) { printk("ppc4xx_add_dma_sgl: null handle\n"); return DMA_STATUS_BAD_HANDLE; } if (psgl->dmanr >= MAX_PPC4xx_DMA_CHANNELS) { printk("ppc4xx_add_dma_sgl: bad channel: %d\n", psgl->dmanr); return DMA_STATUS_BAD_CHANNEL; } p_dma_ch = &dma_channels[psgl->dmanr]; #ifdef DEBUG_4xxDMA { int error = 0; unsigned int aligned = (unsigned) src_addr | (unsigned) dst_addr | count; switch (p_dma_ch->pwidth) { case PW_8: break; case PW_16: if (aligned & 0x1) error = 1; break; case PW_32: if (aligned & 0x3) error = 1; break; case PW_64: if (aligned & 0x7) error = 1; break; default: printk("ppc4xx_add_dma_sgl: invalid bus width: 0x%x\n", p_dma_ch->pwidth); return DMA_STATUS_GENERAL_ERROR; } if (error) printk ("Alignment warning: ppc4xx_add_dma_sgl src 0x%x dst 0x%x count 0x%x bus width var %d\n", src_addr, dst_addr, count, p_dma_ch->pwidth); } #endif if ((unsigned) (psgl->ptail + 1) >= ((unsigned) psgl + SGL_LIST_SIZE)) { printk("sgl handle out of memory \n"); return DMA_STATUS_OUT_OF_MEMORY; } if (!psgl->ptail) { psgl->phead = (ppc_sgl_t *) ((unsigned) psgl + sizeof (sgl_list_info_t)); psgl->ptail = psgl->phead; } else { psgl->ptail->next = iopa((unsigned long)(psgl->ptail + 1)); psgl->ptail++; } psgl->ptail->control = psgl->control; psgl->ptail->src_addr = src_addr; psgl->ptail->dst_addr = dst_addr; psgl->ptail->control_count = (count >> p_dma_ch->shift) | psgl->sgl_control; psgl->ptail->next = (uint32_t) NULL; return DMA_STATUS_GOOD; }