#ifdef CONFIG_PARPORT_PC_FIFO /* Safely change the mode bits in the ECR Returns: 0:Success -EBUSY:CouldnotdrainFIFOinsomefiniteamountoftime, modenotchanged!
*/ staticint change_mode(struct parport *p, int m)
{ conststruct parport_pc_private *priv = p->physport->private_data; unsignedchar oecr; int mode;
pr_debug("parport change_mode ECP-ISA to mode 0x%02x\n", m);
if (!priv->ecr) {
printk(KERN_DEBUG "change_mode: but there's no ECR!\n"); return0;
}
/* Bits <7:5> contain the mode. */
oecr = inb(ECONTROL(p));
mode = (oecr >> 5) & 0x7; if (mode == m) return0;
if (mode >= 2 && !(priv->ctr & 0x20)) { /* This mode resets the FIFO, so we may
* have to wait for it to drain first. */ unsignedlong expire = jiffies + p->physport->cad->timeout; int counter; switch (mode) { case ECR_PPF: /* Parallel Port FIFO mode */ case ECR_ECP: /* ECP Parallel Port mode */ /* Busy wait for 200us */ for (counter = 0; counter < 40; counter++) { if (inb(ECONTROL(p)) & 0x01) break; if (signal_pending(current)) break;
udelay(5);
}
/* Poll slowly. */ while (!(inb(ECONTROL(p)) & 0x01)) { if (time_after_eq(jiffies, expire)) /* The FIFO is stuck. */ return -EBUSY;
schedule_timeout_interruptible(
msecs_to_jiffies(10)); if (signal_pending(current)) break;
}
}
}
if (mode >= 2 && m >= 2) { /* We have to go through mode 001 */
oecr &= ~(7 << 5);
oecr |= ECR_PS2 << 5;
ECR_WRITE(p, oecr);
}
/* Set the mode. */
oecr &= ~(7 << 5);
oecr |= m << 5;
ECR_WRITE(p, oecr); return0;
} #endif/* FIFO support */
if (flags & PARPORT_W91284PIC) { unsignedchar status;
size_t left = length;
/* use knowledge about data lines..: *nFaultis0ifthereisatleast1byteintheWarp'sFIFO *pErroris1ifthereare16bytesintheWarp'sFIFO
*/
status = inb(STATUS(port));
while (!(status & 0x08) && got < length) { if (left >= 16 && (status & 0x20) && !(status & 0x08)) { /* can grab 16 bytes from warp fifo */ if (!((long)buf & 0x03))
insl(EPPDATA(port), buf, 4); else
insb(EPPDATA(port), buf, 16);
buf += 16;
got += 16;
left -= 16;
} else { /* grab single byte from the warp fifo */
*((char *)buf) = inb(EPPDATA(port));
buf++;
got++;
left--;
}
status = inb(STATUS(port)); if (status & 0x01) { /* EPP timeout should never occur... */
printk(KERN_DEBUG "%s: EPP timeout occurred while talking to w91284pic (should not have done)\n",
port->name);
clear_epp_timeout(port);
}
} return got;
} if ((length > 1) && ((flags & PARPORT_EPP_FAST_32)
|| flags & PARPORT_EPP_FAST_16
|| flags & PARPORT_EPP_FAST_8)) { if ((flags & PARPORT_EPP_FAST_32)
&& !(((long)buf | length) & 0x03))
insl(EPPDATA(port), buf, (length >> 2)); elseif ((flags & PARPORT_EPP_FAST_16)
&& !(((long)buf | length) & 0x01))
insw(EPPDATA(port), buf, length >> 1); else
insb(EPPDATA(port), buf, length); if (inb(STATUS(port)) & 0x01) {
clear_epp_timeout(port); return -EIO;
} return length;
} for (; got < length; got++) {
*((char *)buf) = inb(EPPDATA(port));
buf++; if (inb(STATUS(port)) & 0x01) { /* EPP timeout */
clear_epp_timeout(port); break;
}
}
return got;
}
static size_t parport_pc_epp_write_data(struct parport *port, constvoid *buf,
size_t length, int flags)
{
size_t written = 0;
/* 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) { unsignedchar byte; unsignedchar ecrval = inb(ECONTROL(port)); int i = 0;
if (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 (need_resched() &&
time_before(jiffies, expire))
schedule();
if (ecrval & 0x01) { /* FIFO is empty. Blast it full. */ constint 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;
} elseif (i++ < poll_for) {
udelay(10);
ecrval = inb(ECONTROL(port)); goto poll;
}
#ifdef HAS_DMA static size_t parport_pc_fifo_write_block_dma(struct parport *port, constvoid *buf, size_t length)
{ int ret = 0; unsignedlong dmaflag;
size_t left = length; conststruct parport_pc_private *priv = port->physport->private_data; struct device *dev = port->physport->dev;
dma_addr_t dma_addr, dma_handle;
size_t maxlen = 0x10000; /* max 64k per DMA transfer */ unsignedlong start = (unsignedlong) buf; unsignedlong end = (unsignedlong) 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 = dma_map_single(dev, (void *)buf, length,
DMA_TO_DEVICE);
} 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) { unsignedlong 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);
/* 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)
dma_unmap_single(dev, dma_handle, length, DMA_TO_DEVICE);
/* Special case: a timeout of zero means we cannot call schedule().
* Also if O_NONBLOCK is set then use the default implementation. */ if (port->physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) 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);
/* Write the data to the FIFO. */
written = parport_pc_fifo_write_block(port, buf, length);
/* Finish up. */ /* For some hardware we don't want to touch the mode until *theFIFOisempty,soallow4secondsforeachposition *inthefifo.
*/
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);
/* Special case: a timeout of zero means we cannot call schedule().
* Also if O_NONBLOCK is set then use the default implementation. */ if (port->physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) 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. */
written = parport_pc_fifo_write_block(port, buf, length);
/* Finish up. */ /* For some hardware we don't want to touch the mode until *theFIFOisempty,soallow4secondsforeachposition *inthefifo.
*/
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 "%s: BUSY timeout (%d) in ecp_write_block_pio\n",
port->name, r);
/* GCC is not inlining extern inline function later overwritten to non-inline,
so we use outlined_ variants here. */ staticconststruct parport_operations parport_pc_ops = {
.write_data = parport_pc_write_data,
.read_data = parport_pc_read_data,
staticstruct superio_struct *find_free_superio(void)
{ int i; for (i = 0; i < NR_SUPERIOS; i++) if (superios[i].io == 0) return &superios[i]; return NULL;
}
if (cr30 & 0x01) { /* the settings can be interrogated later ... */
s = find_free_superio(); if (s == NULL)
pr_info("Super-IO: too many chips!\n"); else {
s->io = (cr60 << 8) | cr61;
s->irq = cr70 & 0x0f;
s->dma = (((cr74 & 0x07) > 3) ?
PARPORT_DMA_NONE : (cr74 & 0x07));
}
}
}
staticvoid decode_winbond(int efer, int key, int devid, int devrev, int oldid)
{ constchar *type = "unknown"; int id, progif = 2;
if (devid == devrev) /* simple heuristics, we happened to read some
non-winbond register */ return;
id = (devid << 8) | devrev;
/* Values are from public data sheets pdf files, I can just
confirm 83977TF is correct :-) */ if (id == 0x9771)
type = "83977F/AF"; elseif (id == 0x9773)
type = "83977TF / SMSC 97w33x/97w34x"; elseif (id == 0x9774)
type = "83977ATF"; elseif ((id & ~0x0f) == 0x5270)
type = "83977CTF / SMSC 97w36x"; elseif ((id & ~0x0f) == 0x52f0)
type = "83977EF / SMSC 97w35x"; elseif ((id & ~0x0f) == 0x5210)
type = "83627"; elseif ((id & ~0x0f) == 0x6010)
type = "83697HF"; elseif ((oldid & 0x0f) == 0x0a) {
type = "83877F";
progif = 1;
} elseif ((oldid & 0x0f) == 0x0b) {
type = "83877AF";
progif = 1;
} elseif ((oldid & 0x0f) == 0x0c) {
type = "83877TF";
progif = 1;
} elseif ((oldid & 0x0f) == 0x0d) {
type = "83877ATF";
progif = 1;
} else
progif = 0;
if (verbose_probing)
pr_info("Winbond chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x oldid=%02x type=%s\n",
efer, key, devid, devrev, oldid, type);
if (progif == 2)
show_parconfig_winbond(efer, key);
}
staticvoid decode_smsc(int efer, int key, int devid, int devrev)
{ constchar *type = "unknown"; void (*func)(int io, int key); int id;
if (devid == devrev) /* simple heuristics, we happened to read some
non-smsc register */ return;
func = NULL;
id = (devid << 8) | devrev;
if (id == 0x0302) {
type = "37c669";
func = show_parconfig_smsc37c669;
} elseif (id == 0x6582)
type = "37c665IR"; elseif (devid == 0x65)
type = "37c665GT"; elseif (devid == 0x66)
type = "37c666GT";
if (verbose_probing)
pr_info("SMSC chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x type=%s\n",
efer, key, devid, devrev, type);
if (func)
func(efer, key);
}
staticvoid winbond_check(int io, int key)
{ int origval, devid, devrev, oldid, x_devid, x_devrev, x_oldid;
staticvoid detect_and_report_it87(void)
{
u16 dev;
u8 origval, r; if (verbose_probing)
printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n"); if (!request_muxed_region(0x2e, 2, __func__)) return;
origval = inb(0x2e); /* Save original value */
outb(0x87, 0x2e);
outb(0x01, 0x2e);
outb(0x55, 0x2e);
outb(0x55, 0x2e);
outb(0x20, 0x2e);
dev = inb(0x2f) << 8;
outb(0x21, 0x2e);
dev |= inb(0x2f); if (dev == 0x8712 || dev == 0x8705 || dev == 0x8715 ||
dev == 0x8716 || dev == 0x8718 || dev == 0x8726) {
pr_info("IT%04X SuperIO detected\n", dev);
outb(0x07, 0x2E); /* Parallel Port */
outb(0x03, 0x2F);
outb(0xF0, 0x2E); /* BOOT 0x80 off */
r = inb(0x2f);
outb(0xF0, 0x2E);
outb(r | 8, 0x2F);
outb(0x02, 0x2E); /* Lock */
outb(0x02, 0x2F);
} else {
outb(origval, 0x2e); /* Oops, sorry to disturb */
}
release_region(0x2e, 2);
} #endif/* CONFIG_PARPORT_PC_SUPERIO */
staticstruct superio_struct *find_superio(struct parport *p)
{ int i; for (i = 0; i < NR_SUPERIOS; i++) if (superios[i].io == p->base) return &superios[i]; return NULL;
}
staticint get_superio_dma(struct parport *p)
{ struct superio_struct *s = find_superio(p); if (s) return s->dma; return PARPORT_DMA_NONE;
}
staticint get_superio_irq(struct parport *p)
{ struct superio_struct *s = find_superio(p); if (s) return s->irq; return PARPORT_IRQ_NONE;
}
/* Do a simple read-write test to make sure the port exists. */
w = 0xc;
outb(w, CONTROL(pb));
/* Is there a control register that we can read from? Some *portsdon'tallowreads,soread_controljustreturnsa *softwarecopy.Someports_do_allowreads,sobypassthe *softwarecopyhere.Inaddition,somebitsaren't
* writable. */
r = inb(CONTROL(pb)); if ((r & 0xf) == w) {
w = 0xe;
outb(w, CONTROL(pb));
r = inb(CONTROL(pb));
outb(0xc, CONTROL(pb)); if ((r & 0xf) == w) return PARPORT_MODE_PCSPP;
}
if (user_specified) /* That didn't work, but the user thinks there's a
* port here. */
pr_info("parport 0x%lx (WARNING): CTR: wrote 0x%02x, read 0x%02x\n",
pb->base, w, r);
/* Try the data register. The data lines aren't tri-stated at
* this stage, so we expect back what we wrote. */
w = 0xaa;
parport_pc_write_data(pb, w);
r = parport_pc_read_data(pb); if (r == w) {
w = 0x55;
parport_pc_write_data(pb, w);
r = parport_pc_read_data(pb); if (r == w) return PARPORT_MODE_PCSPP;
}
if (user_specified) { /* Didn't work, but the user is convinced this is the
* place. */
pr_info("parport 0x%lx (WARNING): DATA: wrote 0x%02x, read 0x%02x\n",
pb->base, w, r);
pr_info("parport 0x%lx: You gave this address, but there is probably no parallel port there!\n",
pb->base);
}
/* It's possible that we can't read the control register or
* the data register. In that case just believe the user. */ if (user_specified) return PARPORT_MODE_PCSPP;
#ifdef CONFIG_PARPORT_PC_FIFO staticint parport_ECP_supported(struct parport *pb)
{ int i; int config, configb; int pword; struct parport_pc_private *priv = pb->private_data; /* Translate ECP intrLine to ISA irq value */ staticconstint intrline[] = { 0, 7, 9, 10, 11, 14, 15, 5 };
/* If there is no ECR, we have no hope of supporting ECP. */ if (!priv->ecr) return0;
/* Find out FIFO depth */
ECR_WRITE(pb, ECR_SPP << 5); /* Reset FIFO */
ECR_WRITE(pb, ECR_TST << 5); /* TEST FIFO */ for (i = 0; i < 1024 && !(inb(ECONTROL(pb)) & 0x02); i++)
outb(0xaa, FIFO(pb));
/* *UsingLGSchipsetitusesECRregister,but *itdoesn'tsupportECPorFIFOMODE
*/ if (i == 1024) {
ECR_WRITE(pb, ECR_SPP << 5); return0;
}
priv->fifo_depth = i; if (verbose_probing)
printk(KERN_DEBUG "0x%lx: FIFO is %d bytes\n", pb->base, i);
/* Find out writeIntrThreshold */
frob_econtrol(pb, 1<<2, 1<<2);
frob_econtrol(pb, 1<<2, 0); for (i = 1; i <= priv->fifo_depth; i++) {
inb(FIFO(pb));
udelay(50); if (inb(ECONTROL(pb)) & (1<<2)) break;
}
if (i <= priv->fifo_depth) { if (verbose_probing)
printk(KERN_DEBUG "0x%lx: writeIntrThreshold is %d\n",
pb->base, i);
} else /* Number of bytes we know we can write if we get an
interrupt. */
i = 0;
priv->writeIntrThreshold = i;
/* Find out readIntrThreshold */
frob_set_mode(pb, ECR_PS2); /* Reset FIFO and enable PS2 */
parport_pc_data_reverse(pb); /* Must be in PS2 mode */
frob_set_mode(pb, ECR_TST); /* Test FIFO */
frob_econtrol(pb, 1<<2, 1<<2);
frob_econtrol(pb, 1<<2, 0); for (i = 1; i <= priv->fifo_depth; i++) {
outb(0xaa, FIFO(pb)); if (inb(ECONTROL(pb)) & (1<<2)) break;
}
if (i <= priv->fifo_depth) { if (verbose_probing)
pr_info("0x%lx: readIntrThreshold is %d\n",
pb->base, i);
} else /* Number of bytes we can read if we get an interrupt. */
i = 0;
if (priv->ecr) { /* store value of ECR */ unsignedchar ecr = inb(ECONTROL(pb)); unsignedchar i; for (i = 0x00; i < 0x80; i += 0x20) {
ECR_WRITE(pb, i); if (clear_epp_timeout(pb)) { /* Phony EPP in ECP. */
bug_present = 1; break;
}
} /* return ECR into the inital state */
ECR_WRITE(pb, ecr);
}
return bug_present;
} staticint intel_bug_present(struct parport *pb)
{ /* Check whether the device is legacy, not PCI or PCMCIA. Only legacy is known to be affected. */ if (pb->dev != NULL) { return0;
}
/* Only if chipset conforms to ECP ISA Interface Standard */ staticint programmable_dma_support(struct parport *p)
{ unsignedchar oecr = inb(ECONTROL(p)); int dma;
frob_set_mode(p, ECR_CNF);
dma = inb(CONFIGB(p)) & 0x07; /* 000: Indicates jumpered 8-bit DMA if read-only.
100: Indicates jumpered 16-bit DMA if read-only. */ if ((dma & 0x03) == 0)
dma = PARPORT_DMA_NONE;
ECR_WRITE(p, oecr); return dma;
}
staticint parport_dma_probe(struct parport *p)
{ conststruct parport_pc_private *priv = p->private_data; if (priv->ecr) /* ask ECP chipset first */
p->dma = programmable_dma_support(p); if (p->dma == PARPORT_DMA_NONE) { /* ask known Super-IO chips proper, although these claimECPcompatible,somedon'treporttheirDMA
conforming to ECP standards */
p->dma = get_superio_dma(p);
}
if (!dev) { /* We need a physical device to attach to, but none was
* provided. Create our own. */
pdev = platform_device_register_simple("parport_pc",
base, NULL, 0); if (IS_ERR(pdev)) return NULL;
dev = &pdev->dev;
ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(24)); if (ret) {
dev_err(dev, "Unable to set coherent dma mask: disabling DMA\n");
dma = PARPORT_DMA_NONE;
}
}
ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); if (!ops) goto out1;
priv = kmalloc(sizeof(struct parport_pc_private), GFP_KERNEL); if (!priv) goto out2;
/* a misnomer, actually - it's allocate and reserve parport number */
p = parport_register_port(base, irq, dma, ops); if (!p) goto out3;
base_res = request_region(base, 3, p->name); if (!base_res) goto out4;
if (base_hi) {
ECR_res = request_region(base_hi, 3, p->name); if (ECR_res)
parport_ECR_present(p);
}
if (base != 0x3bc) {
EPP_res = request_region(base+0x3, 5, p->name); if (EPP_res) if (!parport_EPP_supported(p))
parport_ECPEPP_supported(p);
} if (!parport_SPP_supported(p)) /* No port. */ goto out5; if (priv->ecr)
parport_ECPPS2_supported(p); else
parport_PS2_supported(p);
if (p->dma == PARPORT_DMA_AUTO) {
p->dma = PARPORT_DMA_NONE;
parport_dma_probe(p);
}
} if (p->dma == PARPORT_DMA_AUTO) /* To use DMA, giving the irq
is mandatory (see above) */
p->dma = PARPORT_DMA_NONE;
#ifdef CONFIG_PARPORT_PC_FIFO if (parport_ECP_supported(p) &&
p->dma != PARPORT_DMA_NOFIFO &&
priv->fifo_depth > 0 && p->irq != PARPORT_IRQ_NONE) {
p->modes |= PARPORT_MODE_ECP | PARPORT_MODE_COMPAT; if (p->dma != PARPORT_DMA_NONE)
p->modes |= PARPORT_MODE_DMA;
} else /* We can't use the DMA channel after all. */
p->dma = PARPORT_DMA_NONE; #endif/* Allowed to use FIFO/DMA */
p->modes &= ~mode_mask;
#ifdef CONFIG_PARPORT_PC_FIFO if ((p->modes & PARPORT_MODE_COMPAT) != 0)
p->ops->compat_write_data = parport_pc_compat_write_block_pio; #ifdef CONFIG_PARPORT_1284 if ((p->modes & PARPORT_MODE_ECP) != 0)
p->ops->ecp_write_data = parport_pc_ecp_write_block_pio; #endif if ((p->modes & (PARPORT_MODE_ECP | PARPORT_MODE_COMPAT)) != 0) { if ((p->modes & PARPORT_MODE_DMA) != 0)
pr_cont(", dma %d", p->dma); else
pr_cont(", using FIFO");
} #endif/* Allowed to use FIFO/DMA */
pr_cont(" [");
#define printmode(x) \ do { \ if (p->modes & PARPORT_MODE_##x) \
pr_cont("%s%s", f++ ? "," : "", #x); \
} while (0)
/* If No ECP release the ports grabbed above. */ if (ECR_res && (p->modes & PARPORT_MODE_ECP) == 0) {
release_region(base_hi, 3);
ECR_res = NULL;
} /* Likewise for EEP ports */ if (EPP_res && (p->modes & PARPORT_MODE_EPP) == 0) {
release_region(base+3, 5);
EPP_res = NULL;
} if (p->irq != PARPORT_IRQ_NONE) { if (request_irq(p->irq, parport_irq_handler,
irqflags, p->name, p)) {
pr_warn("%s: irq %d in use, resorting to polled operation\n",
p->name, p->irq);
p->irq = PARPORT_IRQ_NONE;
p->dma = PARPORT_DMA_NONE;
}
#ifdef CONFIG_PARPORT_PC_FIFO #ifdef HAS_DMA if (p->dma != PARPORT_DMA_NONE) { if (request_dma(p->dma, p->name)) {
pr_warn("%s: dma %d in use, resorting to PIO operation\n",
p->name, p->dma);
p->dma = PARPORT_DMA_NONE;
} else {
priv->dma_buf =
dma_alloc_coherent(dev,
PAGE_SIZE,
&priv->dma_handle,
GFP_KERNEL); if (!priv->dma_buf) {
pr_warn("%s: cannot get buffer for DMA, resorting to PIO operation\n",
p->name);
free_dma(p->dma);
p->dma = PARPORT_DMA_NONE;
}
}
} #endif #endif
}
/* Done probing. Now put the port into a sensible start-up state. */ if (priv->ecr) /* *PuttheECPdetectedportinPS2mode. *DothisalsoforportsthathaveECRbutdon'tdoECP.
*/
ECR_WRITE(p, 0x34);
/* Now that we've told the sharing engine about the port, and foundoutitscharacteristics,letthehigh-leveldrivers
know about it. */
spin_lock(&ports_lock);
list_add(&priv->list, &ports_list);
spin_unlock(&ports_lock);
parport_announce_port(p);
return p;
out5: if (ECR_res)
release_region(base_hi, 3); if (EPP_res)
release_region(base+0x3, 5);
release_region(base, 3);
out4:
parport_del_port(p);
out3:
kfree(priv);
out2:
kfree(ops);
out1: if (pdev)
platform_device_unregister(pdev); return NULL;
}
struct parport *parport_pc_probe_port(unsignedlongint base, unsignedlongint base_hi, int irq, int dma, struct device *dev, int irqflags)
{ return __parport_pc_probe_port(base, base_hi, irq, dma,
dev, irqflags, 0, 0);
}
EXPORT_SYMBOL(parport_pc_probe_port);
parport_remove_port(p);
spin_lock(&ports_lock);
list_del_init(&priv->list);
spin_unlock(&ports_lock); #ifdefined(CONFIG_PARPORT_PC_FIFO) && defined(HAS_DMA) if (p->dma != PARPORT_DMA_NONE)
free_dma(p->dma); #endif if (p->irq != PARPORT_IRQ_NONE)
free_irq(p->irq, p);
release_region(p->base, 3); if (p->size > 3)
release_region(p->base + 3, p->size - 3); if (p->modes & PARPORT_MODE_ECP)
release_region(p->base_hi, 3); #ifdefined(CONFIG_PARPORT_PC_FIFO) && defined(HAS_DMA) if (priv->dma_buf)
dma_free_coherent(p->physport->dev, PAGE_SIZE,
priv->dma_buf,
priv->dma_handle); #endif
kfree(p->private_data);
parport_del_port(p);
kfree(ops); /* hope no-one cached it */
}
EXPORT_SYMBOL(parport_pc_unregister_port);
#ifdef CONFIG_PCI
/* ITE support maintained by Rich Liu <richliu@poorman.org> */ staticint sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, int autodma, conststruct parport_pc_via_data *via)
{ short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 };
u32 ite8872set;
u32 ite8872_lpt, ite8872_lpthi;
u8 ite8872_irq, type; int irq; int i;
pr_debug("sio_ite_8872_probe()\n");
/* make sure which one chip */ for (i = 0; i < 5; i++) { if (request_region(inta_addr[i], 32, "it887x")) { int test;
pci_write_config_dword(pdev, 0x60, 0xe5000000 | inta_addr[i]);
pci_write_config_dword(pdev, 0x78, 0x00000000 | inta_addr[i]);
test = inb(inta_addr[i]); if (test != 0xff) break;
release_region(inta_addr[i], 32);
}
} if (i >= 5) {
pr_info("parport_pc: cannot find ITE8872 INTA\n"); return0;
}
type = inb(inta_addr[i] + 0x18);
type &= 0x0f;
switch (type) { case0x2:
pr_info("parport_pc: ITE8871 found (1P)\n");
ite8872set = 0x64200000; break; case0xa:
pr_info("parport_pc: ITE8875 found (1P)\n");
ite8872set = 0x64200000; break; case0xe:
pr_info("parport_pc: ITE8872 found (2S1P)\n");
ite8872set = 0x64e00000; break; case0x6:
pr_info("parport_pc: ITE8873 found (1S)\n");
release_region(inta_addr[i], 32); return0; case0x8:
pr_info("parport_pc: ITE8874 found (2S)\n");
release_region(inta_addr[i], 32); return0; default:
pr_info("parport_pc: unknown ITE887x\n");
pr_info("parport_pc: please mail 'lspci -nvv' output to Rich.Liu@ite.com.tw\n");
release_region(inta_addr[i], 32); return0;
}
pci_read_config_byte(pdev, 0x3c, &ite8872_irq);
pci_read_config_dword(pdev, 0x1c, &ite8872_lpt);
ite8872_lpt &= 0x0000ff00;
pci_read_config_dword(pdev, 0x20, &ite8872_lpthi);
ite8872_lpthi &= 0x0000ff00;
pci_write_config_dword(pdev, 0x6c, 0xe3000000 | ite8872_lpt);
pci_write_config_dword(pdev, 0x70, 0xe3000000 | ite8872_lpthi);
pci_write_config_dword(pdev, 0x80, (ite8872_lpthi<<16) | ite8872_lpt); /* SET SPP&EPP , Parallel Port NO DMA , Enable All Function */ /* SET Parallel IRQ */
pci_write_config_dword(pdev, 0x9c,
ite8872set | (ite8872_irq * 0x11111));
pr_debug("ITE887x: The IRQ is %d\n", ite8872_irq);
pr_debug("ITE887x: The PARALLEL I/O port is 0x%x\n", ite8872_lpt);
pr_debug("ITE887x: The PARALLEL I/O porthi is 0x%x\n", ite8872_lpthi);
/* Let the user (or defaults) steer us away from interrupts */
irq = ite8872_irq; if (autoirq != PARPORT_IRQ_AUTO)
irq = PARPORT_IRQ_NONE;
/* VIA 8231 support by Pavel Fedin <sonic_amiga@rambler.ru>
based on VIA 686a support code by Jeff Garzik <jgarzik@pobox.com> */ staticint parport_init_mode;
/* Data for two known VIA chips */ staticstruct parport_pc_via_data via_686a_data = { 0x51, 0x50, 0x85, 0x02, 0xE2, 0xF0, 0xE6
}; staticstruct parport_pc_via_data via_8231_data = { 0x45, 0x44, 0x50, 0x04, 0xF2, 0xFA, 0xF6
};
staticint sio_via_probe(struct pci_dev *pdev, int autoirq, int autodma, conststruct parport_pc_via_data *via)
{
u8 tmp, tmp2, siofunc;
u8 ppcontrol = 0; int dma, irq; unsigned port1, port2; unsigned have_epp = 0;
printk(KERN_DEBUG "parport_pc: VIA 686A/8231 detected\n");
if (siofunc == VIA_FUNCTION_PARPORT_DISABLE) {
pr_info("parport_pc: VIA parallel port disabled in BIOS\n"); return0;
}
/* Bits 7-4: PnP Routing for Parallel Port IRQ */
pci_read_config_byte(pdev, via->via_pci_parport_irq_reg, &tmp);
irq = ((tmp & VIA_IRQCONTROL_PARALLEL) >> 4);
if (siofunc == VIA_FUNCTION_PARPORT_ECP) { /* Bits 3-2: PnP Routing for Parallel Port DMA */
pci_read_config_byte(pdev, via->via_pci_parport_dma_reg, &tmp);
dma = ((tmp & VIA_DMACONTROL_PARALLEL) >> 2);
} else /* if ECP not enabled, DMA is not enabled, assumed
bogus 'dma' value */
dma = PARPORT_DMA_NONE;
/* Let the user (or defaults) steer us away from interrupts and DMA */ if (autoirq == PARPORT_IRQ_NONE) {
irq = PARPORT_IRQ_NONE;
dma = PARPORT_DMA_NONE;
} if (autodma == PARPORT_DMA_NONE)
dma = PARPORT_DMA_NONE;
/* each element directly indexed from enum list, above
* (but offset by last_sio) */ staticstruct parport_pc_pci { int numports; struct { /* BAR (base address registers) numbers in the config
space header */ int lo; int hi; /* -1 if not there, >6 for offset-method (max BAR is 6) */
} addr[2];
/* Bit field of parport modes to exclude. */ unsignedint mode_mask;
/* If non-zero, sets the bitmask of writable ECR bits. In that
* case additionally bit 0 will be forcibly set on writes. */ unsignedchar ecr_writable;
/* If set, this is called immediately after pci_enable_device. *Ifitreturnsnon-zero,noprobingwilltakeplaceandthe
* ports will not be used. */ int (*preinit_hook) (struct pci_dev *pdev, int autoirq, int autodma);
/* we only need the pnp layer to activate the device, at least for now */ staticstruct pnp_driver parport_pc_pnp_driver = {
.name = "parport_pc",
.id_table = parport_pc_pnp_tbl,
.probe = parport_pc_pnp_probe,
.remove = parport_pc_pnp_remove,
};
staticint parport_pc_platform_probe(struct platform_device *pdev)
{ /* Always succeed, the actual probing is done in
* parport_pc_probe_port(). */ return0;
}
/* This is called by parport_pc_find_nonpci_ports (in asm/parport.h) */ staticint __attribute__((unused))
parport_pc_find_isa_ports(int autoirq, int autodma)
{ int count = 0;
if (parport_pc_probe_port(0x3bc, 0x7bc, autoirq, autodma, NULL, 0))
count++; if (parport_pc_probe_port(0x378, 0x778, autoirq, autodma, NULL, 0))
count++; if (parport_pc_probe_port(0x278, 0x678, autoirq, autodma, NULL, 0))
count++;
return count;
}
/* This function is called by parport_pc_init if the user didn't *specifyanyportstoprobe.Itsjobistofindsomeports.Order *isimportanthere--wewantISAportstoberegisteredfirst, *followedbyPCIcards(forleastsurprise),butbeforethatwewant *todochipset-specifictestsforsomeonboardportsthatweknow *about. * *autoirqisPARPORT_IRQ_NONE,PARPORT_IRQ_AUTO,orPARPORT_IRQ_PROBEONLY *autodmaisPARPORT_DMA_NONEorPARPORT_DMA_AUTO
*/ staticvoid __init parport_pc_find_ports(int autoirq, int autodma)
{ int count = 0, err;
/* Onboard SuperIO chipsets that show themselves on the PCI bus. */
count += parport_pc_init_superio(autoirq, autodma);
/* PnP ports, skip detection if SuperIO already found them */ if (!count) {
err = pnp_register_driver(&parport_pc_pnp_driver); if (!err)
pnp_registered_parport = 1;
}
/* ISA ports and whatever (see asm/parport.h). */
parport_pc_find_nonpci_ports(autoirq, autodma);
err = pci_register_driver(&parport_pc_pci_driver); if (!err)
pci_registered_parport = 1;
}
staticint __init parse_parport_params(void)
{ unsignedint i; int val;
#ifdef CONFIG_PCI if (init_mode)
parport_init_mode_setup(init_mode); #endif
for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++) { if (parport_parse_irq(irq[i], &val)) return1;
irqval[i] = val; if (parport_parse_dma(dma[i], &val)) return1;
dmaval[i] = val;
} if (!io[0]) { /* The user can make us use any IRQs or DMAs we find. */ if (irq[0] && !parport_parse_irq(irq[0], &val)) switch (val) { case PARPORT_IRQ_NONE: case PARPORT_IRQ_AUTO:
irqval[0] = val; break; default:
pr_warn("parport_pc: irq specified without base address. Use 'io=' to specify one\n");
}
if (dma[0] && !parport_parse_dma(dma[0], &val)) switch (val) { case PARPORT_DMA_NONE: case PARPORT_DMA_AUTO:
dmaval[0] = val; break; default:
pr_warn("parport_pc: dma specified without base address. Use 'io=' to specify one\n");
}
} return0;
}
err = platform_driver_register(&parport_pc_platform_driver); if (err) return err;
if (io[0]) { int i; /* Only probe the ports we were given. */
user_specified = 1; for (i = 0; i < PARPORT_PC_MAX_PORTS; i++) { if (!io[i]) break; if (io_hi[i] == PARPORT_IOHI_AUTO)
io_hi[i] = 0x400 + io[i];
parport_pc_probe_port(io[i], io_hi[i],
irqval[i], dmaval[i], NULL, 0);
}
} else
parport_pc_find_ports(irqval[0], dmaval[0]);
return0;
}
staticvoid __exit parport_pc_exit(void)
{ if (pci_registered_parport)
pci_unregister_driver(&parport_pc_pci_driver); if (pnp_registered_parport)
pnp_unregister_driver(&parport_pc_pnp_driver);
platform_driver_unregister(&parport_pc_platform_driver);
while (!list_empty(&ports_list)) { struct parport_pc_private *priv; struct parport *port; struct device *dev;
priv = list_entry(ports_list.next, struct parport_pc_private, list);
port = priv->port;
dev = port->dev;
parport_pc_unregister_port(port); if (dev && dev->bus == &platform_bus_type)
platform_device_unregister(to_platform_device(dev));
}
}
MODULE_AUTHOR("Phil Blundell, Tim Waugh, others");
MODULE_DESCRIPTION("PC-style parallel port driver");
MODULE_LICENSE("GPL");
module_init(parport_pc_init)
module_exit(parport_pc_exit)
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.57Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.