/* DMA read derek */ static size_t parport_pc_fifo_read_block_dma (struct parport *port, const void *buf, size_t length) { int ret = 0; int counter = 0; unsigned long dmaflag; size_t left = length; const struct parport_pc_private *priv = port->physport->private_data; dma_addr_t dma_addr, dma_handle; size_t maxlen = 0x10000; /* max 64k per DMA transfer */ unsigned long start = (unsigned long) buf; unsigned long end = (unsigned long) buf + length - 1; if (end < MAX_DMA_ADDRESS) { /* If it would cross a 64k boundary, cap it at the end. */ if ((start ^ end) & ~0xffffUL) maxlen = 0x10000 - (start & 0xffff); dma_addr = dma_handle = pci_map_single(priv->dev, (void *)buf, length, PCI_DMA_FROMDEVICE); } else { /* above 16 MB we use a bounce buffer as ISA-DMA is not possible */ maxlen = PAGE_SIZE; /* sizeof(priv->dma_buf) */ dma_addr = priv->dma_handle; dma_handle = 0; } printk("derek: ecp_read_block_dma maxlen = %d \n", maxlen); port = port->physport; /* We don't want to be interrupted every character. */ parport_pc_disable_irq (port); frob_econtrol (port, (1<<4), (1<<4)); /* nErrIntrEn */ /* Reverse mode. */ parport_pc_data_reverse (port); /* Must be in PS2 mode */ while (left) { long expire = jiffies + port->physport->cad->timeout; size_t count = left; if (count > maxlen) count = maxlen; // if (!dma_handle) /* bounce buffer ! */ // memcpy(priv->dma_buf, buf, count); dmaflag = claim_dma_lock(); disable_dma(port->dma); clear_dma_ff(port->dma); set_dma_mode(port->dma, DMA_MODE_READ); set_dma_addr(port->dma, dma_addr); set_dma_count(port->dma, count); //derek enable_dma(port->dma); // release_dma_lock(dmaflag); /* Set DMA mode */ frob_econtrol (port, 1<<3, 1<<3); /* Clear serviceIntr */ frob_econtrol (port, 1<<2, 0); enable_dma(port->dma); release_dma_lock(dmaflag); /* assume DMA will be successful */ left -= count; buf += count; if (dma_handle) dma_addr += count; /* Wait for interrupt. */ false_alarm: ret = parport_wait_event (port, HZ); if (ret < 0) break; ret = 0; if (!time_before (jiffies, expire)) { /* Timed out. */ printk (KERN_DEBUG "DMA read timed out\n"); printk (KERN_DEBUG "DMA read schedule %d\n", counter); break; } /* Is serviceIntr set? */ if (!(inb (ECONTROL (port)) & (1<<2))) { if (current->need_resched){ schedule (); } counter++; goto false_alarm; } dmaflag = claim_dma_lock(); disable_dma(port->dma); clear_dma_ff(port->dma); count = get_dma_residue(port->dma); release_dma_lock(dmaflag); if (current->need_resched) /* Can't yield the port. */ schedule (); /* Anyone else waiting for the port? */ if (port->waithead) { printk (KERN_DEBUG "Somebody wants the port\n"); break; } /* update for possible DMA residue ! */ buf -= count; left += count; if (dma_handle) dma_addr -= count; printk (KERN_DEBUG "DMA read schedule %d\n", counter); } /* Maybe got here through break, so adjust for DMA residue! */ dmaflag = claim_dma_lock(); disable_dma(port->dma); clear_dma_ff(port->dma); left += get_dma_residue(port->dma); release_dma_lock(dmaflag); if (!dma_handle) /* bounce buffer ! */ { printk("derek: in ecp_read_block_dma\n"); memcpy(&buf, priv->dma_buf, length); } /* derek */ /* Turn off DMA mode */ frob_econtrol (port, 1<<3, 0); if (dma_handle) pci_unmap_single(priv->dev, dma_handle, length, PCI_DMA_FROMDEVICE); printk("derek: in ecp_read_block_dma left = %d \n", left); printk("derek: in ecp_read_block_dma length = %d \n", length); return length - left; }