diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-15 01:55:58 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-15 01:55:58 +0000 |
commit | 53b3988d474435254a3b053a68bb24ce9e439295 (patch) | |
tree | f8da8e40f01f4ad02bbd76b8c9920749b118235f /drivers/parport | |
parent | b0cb48abe83d1a4389ea938bf624f8baa82c5047 (diff) |
Merge with 2.3.99-pre9.
Diffstat (limited to 'drivers/parport')
-rw-r--r-- | drivers/parport/ChangeLog | 40 | ||||
-rw-r--r-- | drivers/parport/daisy.c | 12 | ||||
-rw-r--r-- | drivers/parport/ieee1284.c | 2 | ||||
-rw-r--r-- | drivers/parport/ieee1284_ops.c | 4 | ||||
-rw-r--r-- | drivers/parport/parport_pc.c | 93 | ||||
-rw-r--r-- | drivers/parport/share.c | 33 |
6 files changed, 140 insertions, 44 deletions
diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog index 1e09974c9..97b7c53c9 100644 --- a/drivers/parport/ChangeLog +++ b/drivers/parport/ChangeLog @@ -1,3 +1,43 @@ +2000-05-16 Tim Waugh <twaugh@redhat.com> + + * share.c (parport_claim): Fix SMP race. + +2000-05-15 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de> + + * parport_pc.c (parport_pc_compat_write_block_pio): Check for + timeouts. + (parport_pc_ecp_write_block_pio): Likewise. + (parport_pc_ecp_read_block_pio): Likewise. + +2000-05-02 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de> + + * parport_pc.c: PCI SYBA patch and verbose PCI detection. + +2000-05-02 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de> + + * parport_pc.c (decode_smsc): Fix SMSC 665/666 identification. + +2000-04-28 Tim Waugh <twaugh@redhat.com> + + * ieee1284.c: Short function descriptions can't be multiline. + + * daisy.c: Short function descriptions can't be multiline. + +2000-04-19 Tim Waugh <twaugh@redhat.com> + + * parport_pc.c (parport_pc_fifo_write_block_dma): Make maxlen + calculation a bit clearer. + + * ieee1284.c (parport_negotiate): Turn on data line drivers. + + * ieee1284_ops.c (parport_ieee1284_read_byte): Turn off data line + drivers. + (parport_ieee1284_write_compat): Turn on data line drivers. + + * daisy.c (assign_addrs): Turn on data line drivers. + (cpp_mux): Likewise. + (cpp_daisy): Likewise. + 2000-04-04 Tim Waugh <twaugh@redhat.com> * parport_pc.c: Add support for another PCI card. diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c index ead3443b4..b99d5a344 100644 --- a/drivers/parport/daisy.c +++ b/drivers/parport/daisy.c @@ -252,8 +252,7 @@ void parport_close (struct pardevice *dev) } /** - * parport_device_num - convert device coordinates into a - * canonical device number + * parport_device_num - convert device coordinates * @parport: parallel port number * @mux: multiplexor port number (-1 for no multiplexor) * @daisy: daisy chain address (-1 for no daisy chain address) @@ -279,8 +278,7 @@ int parport_device_num (int parport, int mux, int daisy) } /** - * parport_device_coords - convert a canonical device number into - * device coordinates + * parport_device_coords - convert canonical device number * @devnum: device number * @parport: pointer to storage for parallel port number * @mux: pointer to storage for multiplexor port number @@ -325,6 +323,7 @@ static int cpp_daisy (struct parport *port, int cmd) { unsigned char s; + parport_data_forward (port); parport_write_data (port, 0xaa); udelay (2); parport_write_data (port, 0x55); udelay (2); parport_write_data (port, 0x00); udelay (2); @@ -373,6 +372,7 @@ static int cpp_mux (struct parport *port, int cmd) unsigned char s; int rc; + parport_data_forward (port); parport_write_data (port, 0xaa); udelay (2); parport_write_data (port, 0x55); udelay (2); parport_write_data (port, 0xf0); udelay (2); @@ -430,6 +430,7 @@ static int assign_addrs (struct parport *port) int thisdev = numdevs; char *deviceid; + parport_data_forward (port); parport_write_data (port, 0xaa); udelay (2); parport_write_data (port, 0x55); udelay (2); parport_write_data (port, 0x00); udelay (2); @@ -502,8 +503,7 @@ static int assign_addrs (struct parport *port) 'from' itself is skipped. */ /** - * parport_find_device - find a device with a specified - * manufacturer and model string + * parport_find_device - find a specific device * @mfg: required manufacturer string * @mdl: required model string * @from: previous device number found in search, or %NULL for diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c index f25c50abd..11f98bea0 100644 --- a/drivers/parport/ieee1284.c +++ b/drivers/parport/ieee1284.c @@ -380,6 +380,7 @@ int parport_negotiate (struct parport *port, int mode) udelay(1); /* Event 0: Set data */ + parport_data_forward (port); parport_write_data (port, m); udelay (400); /* Shouldn't need to wait this long. */ @@ -734,7 +735,6 @@ ssize_t parport_read (struct parport *port, void *buffer, size_t len) /** * parport_set_timeout - set the inactivity timeout for a device - * on a port * @dev: device on a port * @inactivity: inactivity timeout (in jiffies) * diff --git a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c index a3b76ffbc..cf5c5fb03 100644 --- a/drivers/parport/ieee1284_ops.c +++ b/drivers/parport/ieee1284_ops.c @@ -57,6 +57,7 @@ size_t parport_ieee1284_write_compat (struct parport *port, port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; parport_write_control (port, ctl); + parport_data_forward (port); while (count < len) { long expire = jiffies + dev->timeout; long wait = (HZ + 99) / 100; @@ -268,6 +269,9 @@ size_t parport_ieee1284_read_byte (struct parport *port, break; } + /* Event 14: Place data bus in high impedance state. */ + parport_data_reverse (port); + /* Event 7: Set nAutoFd low. */ parport_frob_control (port, PARPORT_CONTROL_AUTOFD, diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 09255a3c1..a759b2d74 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -704,6 +704,7 @@ size_t parport_pc_compat_write_block_pio (struct parport *port, int flags) { size_t written; + int r; /* Special case: a timeout of zero means we cannot call schedule(). */ if (!port->physport->cad->timeout) @@ -745,9 +746,14 @@ size_t parport_pc_compat_write_block_pio (struct parport *port, frob_econtrol (port, 0xe0, ECR_PS2 << 5); } - parport_wait_peripheral (port, - PARPORT_STATUS_BUSY, - PARPORT_STATUS_BUSY); + 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; @@ -760,6 +766,7 @@ size_t parport_pc_ecp_write_block_pio (struct parport *port, int flags) { size_t written; + int r; /* Special case: a timeout of zero means we cannot call schedule(). */ if (!port->physport->cad->timeout) @@ -772,9 +779,12 @@ size_t parport_pc_ecp_write_block_pio (struct parport *port, parport_frob_control (port, PARPORT_CONTROL_INIT, 0); /* Event 40: PError goes high. */ - parport_wait_peripheral (port, - PARPORT_STATUS_PAPEROUT, - PARPORT_STATUS_PAPEROUT); + 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.*/ @@ -818,18 +828,30 @@ size_t parport_pc_ecp_write_block_pio (struct parport *port, parport_pc_data_reverse (port); /* Must be in PS2 mode */ udelay (5); parport_frob_control (port, PARPORT_CONTROL_INIT, 0); - parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 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); - parport_wait_peripheral (port, - PARPORT_STATUS_PAPEROUT, - PARPORT_STATUS_PAPEROUT); + 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); } - parport_wait_peripheral (port, - PARPORT_STATUS_BUSY, - PARPORT_STATUS_BUSY); + 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); + port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; return written; @@ -840,6 +862,7 @@ size_t parport_pc_ecp_read_block_pio (struct parport *port, { size_t left = length; size_t fifofull; + int r; const int fifo = FIFO(port); const struct parport_pc_private *priv = port->physport->private_data; const int fifo_depth = priv->fifo_depth; @@ -882,7 +905,10 @@ size_t parport_pc_ecp_read_block_pio (struct parport *port, 0); /* Event 40: PError goes low */ - parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0); + r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0); + if (r) + printk (KERN_DEBUG "%s: PE timeout Event 40 (%d) " + "in ecp_read_block_pio\n", port->name, r); } /* Set up ECP FIFO mode.*/ @@ -961,9 +987,14 @@ size_t parport_pc_ecp_read_block_pio (struct parport *port, /* Go to forward idle mode to shut the peripheral up. */ parport_frob_control (port, PARPORT_CONTROL_INIT, 0); - parport_wait_peripheral (port, - PARPORT_STATUS_PAPEROUT, - PARPORT_STATUS_PAPEROUT); + r = parport_wait_peripheral (port, + PARPORT_STATUS_PAPEROUT, + PARPORT_STATUS_PAPEROUT); + if (r) + printk (KERN_DEBUG + "%s: PE timeout FWDIDLE (%d) in ecp_read_block_pio\n", + port->name, r); + port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; /* Finish up. */ @@ -1218,7 +1249,7 @@ static void __devinit decode_smsc(int efer, int key, int devid, int devrev) if (devid == devrev) /* simple heuristics, we happened to read some - non-winbond register */ + non-smsc register */ return; func=NULL; @@ -1228,8 +1259,8 @@ static void __devinit decode_smsc(int efer, int key, int devid, int devrev) if (id==0x0302) {type="37c669"; func=show_parconfig_smsc37c669;} else if (id==0x6582) type="37c665IR"; - else if ((id==0x6502) && (key==0x44)) type="37c665GT"; - else if ((id==0x6502) && (key==0x55)) type="37c666GT"; + else if (devid==0x65) type="37c665GT"; + else if (devid==0x66) type="37c666GT"; if(type==NULL) printk("SMSC unknown chip type\n"); @@ -2263,6 +2294,7 @@ enum parport_pc_pci_cards { plx_9050, afavlab_tk9902, timedia_1889, + syba_2p_epp, }; @@ -2270,9 +2302,11 @@ enum parport_pc_pci_cards { * (but offset by last_sio) */ static struct parport_pc_pci { int numports; - struct { + struct { /* BAR (base address registers) numbers in the config + space header */ int lo; - int hi; /* -ve if not there */ + int hi; /* -1 if not there, >6 for offset-method (max + BAR is 6) */ } addr[4]; } cards[] __devinitdata = { /* siig_1s1p_10x_550 */ { 1, { { 3, 4 }, } }, @@ -2301,6 +2335,9 @@ static struct parport_pc_pci { /* plx_9050 */ { 2, { { 4, -1 }, { 5, -1 }, } }, /* afavlab_tk9902 */ { 1, { { 0, 1 }, } }, /* timedia_1889 */ { 1, { { 2, -1 }, } }, + /* SYBA uses fixed offsets in + a 1K io window */ + /* syba_2p_epp */ { 2, { { 0, 0x078 }, { 0, 0x178 }, } }, }; static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = { @@ -2360,7 +2397,8 @@ static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, afavlab_tk9902 }, { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, timedia_1889 }, - { 0, }, /* terminate list */ + { 0x1592, 0x0782, PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_2p_epp }, + { 0, } /* terminate list */ }; MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl); @@ -2384,9 +2422,16 @@ static int __devinit parport_pc_pci_probe (struct pci_dev *dev, unsigned long io_lo, io_hi; io_lo = pci_resource_start (dev, lo); io_hi = 0; - if (hi >= 0) + if ((hi >= 0) && (hi <= 6)) io_hi = pci_resource_start (dev, hi); + else if (hi > 6) + io_lo += hi; /* Reinterpret the meaning of + "hi" as an offset (see SYBA + def.) */ /* TODO: test if sharing interrupts works */ + printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, " + "I/O at %#lx(%#lx)\n", parport_pc_pci_tbl[i].vendor, + parport_pc_pci_tbl[i].device, io_lo, io_hi); if (parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, dev)) count++; diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 63a185029..c85addc56 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -602,6 +602,7 @@ parport_register_device(struct parport *port, const char *name, void parport_unregister_device(struct pardevice *dev) { struct parport *port; + unsigned long flags; #ifdef PARPORT_PARANOID if (dev == NULL) { @@ -614,11 +615,14 @@ void parport_unregister_device(struct pardevice *dev) port = dev->port->physport; + read_lock_irqsave (&port->cad_lock, flags); if (port->cad == dev) { + read_unlock_irqrestore (&port->cad_lock, flags); printk(KERN_DEBUG "%s: %s forgot to release port\n", port->name, dev->name); parport_release (dev); } + read_unlock_irqrestore (&port->cad_lock, flags); spin_lock(&port->pardevice_lock); if (dev->next) @@ -663,14 +667,17 @@ int parport_claim(struct pardevice *dev) struct parport *port = dev->port->physport; unsigned long flags; + read_lock_irqsave (&port->cad_lock, flags); if (port->cad == dev) { + read_unlock_irqrestore (&port->cad_lock, flags); printk(KERN_INFO "%s: %s already owner\n", dev->port->name,dev->name); return 0; } + read_unlock_irqrestore (&port->cad_lock, flags); -try_again: /* Preempt any current device */ + write_lock_irqsave (&port->cad_lock, flags); if ((oldcad = port->cad) != NULL) { if (oldcad->preempt) { if (oldcad->preempt(oldcad->private)) @@ -680,7 +687,9 @@ try_again: goto blocked; if (port->cad != oldcad) { - printk(KERN_WARNING + /* I think we'll actually deadlock rather than + get here, but just in case.. */ + printk(KERN_WARNING "%s: %s released port when preempted!\n", port->name, oldcad->name); if (port->cad) @@ -707,9 +716,7 @@ try_again: } /* Now we do the change of devices */ - write_lock_irqsave(&port->cad_lock, flags); port->cad = dev; - write_unlock_irqrestore(&port->cad_lock, flags); #ifdef CONFIG_PARPORT_1284 /* If it's a mux port, select it. */ @@ -729,6 +736,7 @@ try_again: /* Restore control registers */ port->ops->restore_state(port, dev->state); + write_unlock_irqrestore(&port->cad_lock, flags); dev->time = jiffies; return 0; @@ -736,13 +744,10 @@ blocked: /* If this is the first time we tried to claim the port, register an interest. This is only allowed for devices sleeping in parport_claim_or_block(), or those with a wakeup function. */ + + /* The cad_lock is still held for writing here */ if (dev->waiting & 2 || dev->wakeup) { - spin_lock_irqsave (&port->waitlist_lock, flags); - if (port->cad == NULL) { - /* The port got released in the meantime. */ - spin_unlock_irqrestore (&port->waitlist_lock, flags); - goto try_again; - } + spin_lock (&port->waitlist_lock); if (test_and_set_bit(0, &dev->waiting) == 0) { /* First add ourselves to the end of the wait list. */ dev->waitnext = NULL; @@ -753,8 +758,9 @@ blocked: } else port->waithead = port->waittail = dev; } - spin_unlock_irqrestore (&port->waitlist_lock, flags); + spin_unlock (&port->waitlist_lock); } + write_unlock_irqrestore (&port->cad_lock, flags); return -EAGAIN; } @@ -826,7 +832,9 @@ void parport_release(struct pardevice *dev) unsigned long flags; /* Make sure that dev is the current device */ + write_lock_irqsave(&port->cad_lock, flags); if (port->cad != dev) { + write_unlock_irqrestore (&port->cad_lock, flags); printk(KERN_WARNING "%s: %s tried to release parport " "when not owner\n", port->name, dev->name); return; @@ -846,7 +854,6 @@ void parport_release(struct pardevice *dev) } #endif - write_lock_irqsave(&port->cad_lock, flags); port->cad = NULL; write_unlock_irqrestore(&port->cad_lock, flags); @@ -863,7 +870,7 @@ void parport_release(struct pardevice *dev) return; } else if (pd->wakeup) { pd->wakeup(pd->private); - if (dev->port->cad) + if (dev->port->cad) /* racy but no matter */ return; } else { printk(KERN_ERR "%s: don't know how to wake %s\n", port->name, pd->name); |