📄 parport_pc.c
字号:
clear_epp_timeout (port); break; } } return got;}static size_t parport_pc_epp_write_addr (struct parport *port, const void *buf, size_t length, int flags){ size_t written = 0; if ((flags & PARPORT_EPP_FAST) && (length > 1)) { outsb (EPPADDR (port), buf, length); if (inb (STATUS (port)) & 0x01) { clear_epp_timeout (port); return -EIO; } return length; } for (; written < length; written++) { outb (*((char*)buf)++, EPPADDR (port)); if (inb (STATUS (port)) & 0x01) { clear_epp_timeout (port); break; } } return written;}static size_t parport_pc_ecpepp_read_data (struct parport *port, void *buf, size_t length, int flags){ size_t got; frob_set_mode (port, ECR_EPP); parport_pc_data_reverse (port); parport_pc_write_control (port, 0x4); got = parport_pc_epp_read_data (port, buf, length, flags); frob_set_mode (port, ECR_PS2); return got;}static size_t parport_pc_ecpepp_write_data (struct parport *port, const void *buf, size_t length, int flags){ size_t written; frob_set_mode (port, ECR_EPP); parport_pc_write_control (port, 0x4); parport_pc_data_forward (port); written = parport_pc_epp_write_data (port, buf, length, flags); frob_set_mode (port, ECR_PS2); return written;}static size_t parport_pc_ecpepp_read_addr (struct parport *port, void *buf, size_t length, int flags){ size_t got; frob_set_mode (port, ECR_EPP); parport_pc_data_reverse (port); parport_pc_write_control (port, 0x4); got = parport_pc_epp_read_addr (port, buf, length, flags); frob_set_mode (port, ECR_PS2); return got;}static size_t parport_pc_ecpepp_write_addr (struct parport *port, const void *buf, size_t length, int flags){ size_t written; frob_set_mode (port, ECR_EPP); parport_pc_write_control (port, 0x4); parport_pc_data_forward (port); written = parport_pc_epp_write_addr (port, buf, length, flags); frob_set_mode (port, ECR_PS2); return written;}#endif /* IEEE 1284 support */#ifdef CONFIG_PARPORT_PC_FIFOstatic size_t parport_pc_fifo_write_block_pio (struct parport *port, const void *buf, size_t length){ int ret = 0; const unsigned char *bufp = buf; size_t left = length; long expire = jiffies + port->physport->cad->timeout; const int fifo = FIFO (port); int poll_for = 8; /* 80 usecs */ const struct parport_pc_private *priv = port->physport->private_data; const int fifo_depth = priv->fifo_depth; port = port->physport; /* We don't want to be interrupted every character. */ parport_pc_disable_irq (port); /* set nErrIntrEn and serviceIntr */ frob_econtrol (port, (1<<4) | (1<<2), (1<<4) | (1<<2)); /* Forward mode. */ parport_pc_data_forward (port); /* Must be in PS2 mode */ while (left) { unsigned char byte; unsigned char ecrval = inb (ECONTROL (port)); int i = 0; if (current->need_resched && time_before (jiffies, expire)) /* Can't yield the port. */ schedule (); /* Anyone else waiting for the port? */ if (port->waithead) { printk (KERN_DEBUG "Somebody wants the port\n"); break; } if (ecrval & 0x02) { /* FIFO is full. Wait for interrupt. */ /* Clear serviceIntr */ ECR_WRITE (port, ecrval & ~(1<<2)); false_alarm: ret = parport_wait_event (port, HZ); if (ret < 0) break; ret = 0; if (!time_before (jiffies, expire)) { /* Timed out. */ printk (KERN_DEBUG "FIFO write timed out\n"); break; } ecrval = inb (ECONTROL (port)); if (!(ecrval & (1<<2))) { if (current->need_resched && time_before (jiffies, expire)) schedule (); goto false_alarm; } continue; } /* Can't fail now. */ expire = jiffies + port->cad->timeout; poll: if (signal_pending (current)) break; if (ecrval & 0x01) { /* FIFO is empty. Blast it full. */ const int n = left < fifo_depth ? left : fifo_depth; outsb (fifo, bufp, n); bufp += n; left -= n; /* Adjust the poll time. */ if (i < (poll_for - 2)) poll_for--; continue; } else if (i++ < poll_for) { udelay (10); ecrval = inb (ECONTROL (port)); goto poll; } /* Half-full (call me an optimist) */ byte = *bufp++; outb (byte, fifo); left--; }dump_parport_state ("leave fifo_write_block_pio", port); return length - left;}static size_t parport_pc_fifo_write_block_dma (struct parport *port, const void *buf, size_t length){ int ret = 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;dump_parport_state ("enter fifo_write_block_dma", port); 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_TODEVICE); } 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; } port = port->physport; /* We don't want to be interrupted every character. */ parport_pc_disable_irq (port); /* set nErrIntrEn and serviceIntr */ frob_econtrol (port, (1<<4) | (1<<2), (1<<4) | (1<<2)); /* Forward mode. */ parport_pc_data_forward (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_WRITE); set_dma_addr(port->dma, dma_addr); set_dma_count(port->dma, count); /* 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 write timed out\n"); break; } /* Is serviceIntr set? */ if (!(inb (ECONTROL (port)) & (1<<2))) { if (current->need_resched) schedule (); 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; } /* 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); /* Turn off DMA mode */ frob_econtrol (port, 1<<3, 0); if (dma_handle) pci_unmap_single(priv->dev, dma_handle, length, PCI_DMA_TODEVICE);dump_parport_state ("leave fifo_write_block_dma", port); return length - left;}/* Parallel Port FIFO mode (ECP chipsets) */size_t parport_pc_compat_write_block_pio (struct parport *port, const void *buf, size_t length, int flags){ size_t written; int r; long int expire; const struct parport_pc_private *priv = port->physport->private_data; /* Special case: a timeout of zero means we cannot call schedule(). */ if (!port->physport->cad->timeout) return parport_ieee1284_write_compat (port, buf, length, flags); /* Set up parallel port FIFO mode.*/ parport_pc_data_forward (port); /* Must be in PS2 mode */ parport_pc_frob_control (port, PARPORT_CONTROL_STROBE, 0); r = change_mode (port, ECR_PPF); /* Parallel port FIFO */ if (r) printk (KERN_DEBUG "%s: Warning change_mode ECR_PPF failed\n", port->name); port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; /* Write the data to the FIFO. */ if (port->dma != PARPORT_DMA_NONE) written = parport_pc_fifo_write_block_dma (port, buf, length); else written = parport_pc_fifo_write_block_pio (port, buf, length); /* Finish up. */ /* For some hardware we don't want to touch the mode until * the FIFO is empty, so allow 4 seconds for each position * in the fifo. */ expire = jiffies + (priv->fifo_depth * HZ * 4); do { /* Wait for the FIFO to empty */ r = change_mode (port, ECR_PS2); if (r != -EBUSY) { break; } } while (time_before (jiffies, expire)); if (r == -EBUSY) { printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name); /* Prevent further data transfer. */ frob_set_mode (port, ECR_TST); /* Adjust for the contents of the FIFO. */ for (written -= priv->fifo_depth; ; written++) { if (inb (ECONTROL (port)) & 0x2) { /* Full up. */ break; } outb (0, FIFO (port)); } /* Reset the FIFO and return to PS2 mode. */ frob_set_mode (port, ECR_PS2); } r = parport_wait_peripheral (port, PARPORT_STATUS_BUSY, PARPORT_STATUS_BUSY); if (r) printk (KERN_DEBUG "%s: BUSY timeout (%d) in compat_write_block_pio\n", port->name, r); port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; return written;}/* ECP */#ifdef CONFIG_PARPORT_1284size_t parport_pc_ecp_write_block_pio (struct parport *port, const void *buf, size_t length, int flags){ size_t written; int r; long int expire; const struct parport_pc_private *priv = port->physport->private_data; /* Special case: a timeout of zero means we cannot call schedule(). */ if (!port->physport->cad->timeout) return parport_ieee1284_ecp_write_data (port, buf, length, flags); /* Switch to forward mode if necessary. */ if (port->physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) { /* Event 47: Set nInit high. */ parport_frob_control (port, PARPORT_CONTROL_INIT | PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_INIT | PARPORT_CONTROL_AUTOFD); /* Event 49: PError goes high. */ r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, PARPORT_STATUS_PAPEROUT); if (r) { printk (KERN_DEBUG "%s: PError timeout (%d) " "in ecp_write_block_pio\n", port->name, r); } } /* Set up ECP parallel port mode.*/ parport_pc_data_forward (port); /* Must be in PS2 mode */ parport_pc_frob_control (port, PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD, 0); r = change_mode (port, ECR_ECP); /* ECP FIFO */ if (r) printk (KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n", port->name); port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; /* Write the data to the FIFO. */ if (port->dma != PARPORT_DMA_NONE) written = parport_pc_fifo_write_block_dma (port, buf, length); else written = parport_pc_fifo_write_block_pio (port, buf, length); /* Finish up. */ /* For some hardware we don't want to touch the mode until * the FIFO is empty, so allow 4 seconds for each position * in the fifo. */ expire = jiffies + (priv->fifo_depth * (HZ * 4)); do { /* Wait for the FIFO to empty */ r = change_mode (port, ECR_PS2); if (r != -EBUSY) { break; } } while (time_before (jiffies, expire)); if (r == -EBUSY) { printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name); /* Prevent further data transfer. */ frob_set_mode (port, ECR_TST); /* Adjust for the contents of the FIFO. */ for (written -= priv->fifo_depth; ; written++) { if (inb (ECONTROL (port)) & 0x2) { /* Full up. */ break; } outb (0, FIFO (port)); } /* Reset the FIFO and return to PS2 mode. */ frob_set_mode (port, ECR_PS2); /* Host transfer recovery. */ parport_pc_data_reverse (port); /* Must be in PS2 mode */ udelay (5); parport_frob_control (port, PARPORT_CONTROL_INIT, 0); r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0); if (r) printk (KERN_DEBUG "%s: PE,1 timeout (%d) " "in ecp_write_block_pio\n", port->name, r); parport_frob_control (port, PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT); r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, PARPORT_STATUS_PAPEROUT); if (r) printk (KERN_DEBUG "%s: PE,2 timeout (%d) " "in ecp_write_block_pio\n", port->name, r); } r = parport_wait_peripheral (port, PARPORT_STATUS_BUSY, PARPORT_STATUS_BUSY); if(r) printk (KERN_DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -