summaryrefslogtreecommitdiffstats
path: root/drivers/parport
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-15 01:55:58 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-15 01:55:58 +0000
commit53b3988d474435254a3b053a68bb24ce9e439295 (patch)
treef8da8e40f01f4ad02bbd76b8c9920749b118235f /drivers/parport
parentb0cb48abe83d1a4389ea938bf624f8baa82c5047 (diff)
Merge with 2.3.99-pre9.
Diffstat (limited to 'drivers/parport')
-rw-r--r--drivers/parport/ChangeLog40
-rw-r--r--drivers/parport/daisy.c12
-rw-r--r--drivers/parport/ieee1284.c2
-rw-r--r--drivers/parport/ieee1284_ops.c4
-rw-r--r--drivers/parport/parport_pc.c93
-rw-r--r--drivers/parport/share.c33
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);