static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) { dma_t *dma = (dma_t *)dev_id; unsigned int status = 0, no_buffer = dma->sg == NULL; do { switch (dma->state) { case state_prog_a: iomd_get_next_sg(&dma->cur_sg, dma); iomd_setup_dma_a(&dma->cur_sg, dma); dma->state = state_wait_a; case state_wait_a: status = iomd_readb(dma->dma_base + ST); switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) { case DMA_ST_OFL|DMA_ST_INT: iomd_get_next_sg(&dma->cur_sg, dma); iomd_setup_dma_a(&dma->cur_sg, dma); break; case DMA_ST_INT: iomd_get_next_sg(&dma->cur_sg, dma); iomd_setup_dma_b(&dma->cur_sg, dma); dma->state = state_wait_b; break; case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB: iomd_setup_dma_b(&dma->cur_sg, dma); dma->state = state_wait_b; break; } break; case state_wait_b: status = iomd_readb(dma->dma_base + ST); switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) { case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB: iomd_get_next_sg(&dma->cur_sg, dma); iomd_setup_dma_b(&dma->cur_sg, dma); break; case DMA_ST_INT|DMA_ST_AB: iomd_get_next_sg(&dma->cur_sg, dma); iomd_setup_dma_a(&dma->cur_sg, dma); dma->state = state_wait_a; break; case DMA_ST_OFL|DMA_ST_INT: iomd_setup_dma_a(&dma->cur_sg, dma); dma->state = state_wait_a; break; } break; } } while (dma->sg && (status & DMA_ST_INT)); if (no_buffer) disable_irq(irq); }
static irqreturn_t iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) { dma_t *dma = (dma_t *)dev_id; unsigned long base = dma->dma_base; do { unsigned int status; status = iomd_readb(base + ST); if (!(status & DMA_ST_INT)) return IRQ_HANDLED; if ((dma->state ^ status) & DMA_ST_AB) iomd_get_next_sg(&dma->cur_sg, dma); switch (status & (DMA_ST_OFL | DMA_ST_AB)) { case DMA_ST_OFL: /* OIA */ case DMA_ST_AB: /* .IB */ iomd_writel(dma->cur_sg.dma_address, base + CURA); iomd_writel(dma->cur_sg.length, base + ENDA); dma->state = DMA_ST_AB; break; case DMA_ST_OFL | DMA_ST_AB: /* OIB */ case 0: /* .IA */ iomd_writel(dma->cur_sg.dma_address, base + CURB); iomd_writel(dma->cur_sg.length, base + ENDB); dma->state = 0; break; } if (status & DMA_ST_OFL && dma->cur_sg.length == (DMA_END_S|DMA_END_L)) break; } while (1); dma->state = ~DMA_ST_AB; disable_irq(irq); return IRQ_HANDLED; }
static irqreturn_t iomd_dma_handle(int irq, void *dev_id) { struct iomd_dma *idma = dev_id; unsigned long base = idma->base; do { unsigned int status; status = iomd_readb(base + ST); if (!(status & DMA_ST_INT)) return IRQ_HANDLED; if ((idma->state ^ status) & DMA_ST_AB) iomd_get_next_sg(&idma->cur_sg, idma); switch (status & (DMA_ST_OFL | DMA_ST_AB)) { case DMA_ST_OFL: case DMA_ST_AB: iomd_writel(idma->cur_sg.dma_address, base + CURA); iomd_writel(idma->cur_sg.length, base + ENDA); idma->state = DMA_ST_AB; break; case DMA_ST_OFL | DMA_ST_AB: case 0: iomd_writel(idma->cur_sg.dma_address, base + CURB); iomd_writel(idma->cur_sg.length, base + ENDB); idma->state = 0; break; } if (status & DMA_ST_OFL && idma->cur_sg.length == (DMA_END_S|DMA_END_L)) break; } while (1); idma->state = ~DMA_ST_AB; disable_irq(irq); return IRQ_HANDLED; }