Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
Arquivo: dma.c Projeto: 1x23/unifi-gpl
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;
}
Exemplo n.º 3
0
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;
}