summaryrefslogtreecommitdiffstats
path: root/drivers/parport
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-03-02 02:36:47 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-03-02 02:36:47 +0000
commit8624512aa908741ba2795200133eae0d7f4557ea (patch)
treed5d3036fccf2604f4c98dedc11e8adb929d6b52e /drivers/parport
parent7b8f5d6f1d45d9f9de1d26e7d3c32aa5af11b488 (diff)
Merge with 2.3.48.
Diffstat (limited to 'drivers/parport')
-rw-r--r--drivers/parport/daisy.c32
-rw-r--r--drivers/parport/parport_pc.c190
-rw-r--r--drivers/parport/probe.c11
-rw-r--r--drivers/parport/share.c14
4 files changed, 205 insertions, 42 deletions
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c
index 830d9d400..c4003dd27 100644
--- a/drivers/parport/daisy.c
+++ b/drivers/parport/daisy.c
@@ -1,7 +1,7 @@
/*
* IEEE 1284.3 Parallel port daisy chain and multiplexor code
*
- * Copyright (C) 1999 Tim Waugh <tim@cyberelk.demon.co.uk>
+ * Copyright (C) 1999, 2000 Tim Waugh <tim@cyberelk.demon.co.uk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -12,6 +12,7 @@
* 31-01-1999: Make port-cloning transparent.
* 13-02-1999: Move DeviceID technique from parport_probe.
* 13-03-1999: Get DeviceID from non-IEEE 1284.3 devices too.
+ * 22-02-2000: Count devices that are actually detected.
*
*/
@@ -80,9 +81,11 @@ static struct parport *clone_parport (struct parport *real, int muxport)
return extra;
}
-/* Discover the IEEE1284.3 topology on a port -- muxes and daisy chains. */
+/* Discover the IEEE1284.3 topology on a port -- muxes and daisy chains.
+ * Return value is number of devices actually detected. */
int parport_daisy_init (struct parport *port)
{
+ int detected = 0;
char *deviceid;
static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
int num_ports;
@@ -128,7 +131,7 @@ int parport_daisy_init (struct parport *port)
select_port (port);
parport_daisy_deselect_all (port);
- assign_addrs (port);
+ detected += assign_addrs (port);
/* Count the potential legacy device at the end. */
add_dev (numdevs++, port, -1);
@@ -136,25 +139,31 @@ int parport_daisy_init (struct parport *port)
/* Find out the legacy device's IEEE 1284 device ID. */
deviceid = kmalloc (1000, GFP_KERNEL);
if (deviceid) {
- parport_device_id (numdevs - 1, deviceid, 1000);
+ if (parport_device_id (numdevs - 1, deviceid, 1000) > 2)
+ detected++;
+
kfree (deviceid);
}
- return 0;
+ return detected;
}
/* Forget about devices on a physical port. */
void parport_daisy_fini (struct parport *port)
{
struct daisydev *dev, *prev = topology;
- while (prev && prev->port == port)
- prev = topology = topology->next;
+ while (prev && prev->port == port) {
+ topology = topology->next;
+ kfree (prev);
+ prev = topology;
+ }
while (prev) {
dev = prev->next;
if (dev && dev->port == port)
prev->next = dev->next;
+ kfree (dev);
prev = prev->next;
}
@@ -162,7 +171,8 @@ void parport_daisy_fini (struct parport *port)
someone enumerate through all IEEE1284.3 devices in the
topology?. */
if (!topology) numdevs = 0;
- return; }
+ return;
+}
/* Find a device by canonical device number. */
struct pardevice *parport_open (int devnum, const char *name,
@@ -371,7 +381,7 @@ static int assign_addrs (struct parport *port)
| PARPORT_STATUS_ERROR)) {
DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff(%02x)\n",
port->name, s);
- return -ENXIO;
+ return 0;
}
parport_write_data (port, 0x87); udelay (2);
@@ -382,7 +392,7 @@ static int assign_addrs (struct parport *port)
if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff87(%02x)\n",
port->name, s);
- return -ENXIO;
+ return 0;
}
parport_write_data (port, 0x78); udelay (2);
@@ -421,7 +431,7 @@ static int assign_addrs (struct parport *port)
parport_device_id (thisdev, deviceid, 1000);
kfree (deviceid);
- return 0;
+ return numdevs - thisdev;
}
/* Find a device with a particular manufacturer and model string,
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index beb0a68b7..cf0e092bf 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -681,6 +681,7 @@ size_t parport_pc_compat_write_block_pio (struct parport *port,
/* 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);
change_mode (port, ECR_PPF); /* Parallel port FIFO */
port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
@@ -747,6 +748,10 @@ size_t parport_pc_ecp_write_block_pio (struct parport *port,
/* 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);
change_mode (port, ECR_ECP); /* ECP FIFO */
port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
@@ -850,6 +855,10 @@ size_t parport_pc_ecp_read_block_pio (struct parport *port,
/* Set up ECP parallel port mode.*/
parport_pc_data_reverse (port); /* Must be in PS2 mode */
+ parport_pc_frob_control (port,
+ PARPORT_CONTROL_STROBE |
+ PARPORT_CONTROL_AUTOFD,
+ 0);
change_mode (port, ECR_ECP); /* ECP FIFO */
port->ieee1284.phase = IEEE1284_PH_REV_DATA;
@@ -989,7 +998,7 @@ struct parport_operations parport_pc_ops =
/*
* Checks for port existence, all ports support SPP MODE
*/
-static int __maybe_init parport_SPP_supported(struct parport *pb)
+static int __devinit parport_SPP_supported(struct parport *pb)
{
unsigned char r, w;
@@ -1066,7 +1075,7 @@ static int __maybe_init parport_SPP_supported(struct parport *pb)
* two bits of ECR aren't writable, so we check by writing ECR and
* reading it back to see if it's what we expect.
*/
-static int __maybe_init parport_ECR_present(struct parport *pb)
+static int __devinit parport_ECR_present(struct parport *pb)
{
struct parport_pc_private *priv = pb->private_data;
unsigned char r = 0xc;
@@ -1118,7 +1127,7 @@ static int __maybe_init parport_ECR_present(struct parport *pb)
* be misdetected here is rather academic.
*/
-static int __maybe_init parport_PS2_supported(struct parport *pb)
+static int __devinit parport_PS2_supported(struct parport *pb)
{
int ok = 0;
@@ -1146,7 +1155,7 @@ static int __maybe_init parport_PS2_supported(struct parport *pb)
return ok;
}
-static int __maybe_init parport_ECP_supported(struct parport *pb)
+static int __devinit parport_ECP_supported(struct parport *pb)
{
int i;
int config;
@@ -1257,7 +1266,7 @@ static int __maybe_init parport_ECP_supported(struct parport *pb)
return 1;
}
-static int __maybe_init parport_ECPPS2_supported(struct parport *pb)
+static int __devinit parport_ECPPS2_supported(struct parport *pb)
{
const struct parport_pc_private *priv = pb->private_data;
int result;
@@ -1277,7 +1286,7 @@ static int __maybe_init parport_ECPPS2_supported(struct parport *pb)
/* EPP mode detection */
-static int __maybe_init parport_EPP_supported(struct parport *pb)
+static int __devinit parport_EPP_supported(struct parport *pb)
{
const struct parport_pc_private *priv = pb->private_data;
@@ -1320,7 +1329,7 @@ static int __maybe_init parport_EPP_supported(struct parport *pb)
return 1;
}
-static int __maybe_init parport_ECPEPP_supported(struct parport *pb)
+static int __devinit parport_ECPEPP_supported(struct parport *pb)
{
struct parport_pc_private *priv = pb->private_data;
int result;
@@ -1351,18 +1360,18 @@ static int __maybe_init parport_ECPEPP_supported(struct parport *pb)
#else /* No IEEE 1284 support */
/* Don't bother probing for modes we know we won't use. */
-static int __maybe_init parport_PS2_supported(struct parport *pb) { return 0; }
-static int __maybe_init parport_ECP_supported(struct parport *pb) { return 0; }
-static int __maybe_init parport_EPP_supported(struct parport *pb) { return 0; }
-static int __maybe_init parport_ECPEPP_supported(struct parport *pb){return 0;}
-static int __maybe_init parport_ECPPS2_supported(struct parport *pb){return 0;}
+static int __devinit parport_PS2_supported(struct parport *pb) { return 0; }
+static int __devinit parport_ECP_supported(struct parport *pb) { return 0; }
+static int __devinit parport_EPP_supported(struct parport *pb) { return 0; }
+static int __devinit parport_ECPEPP_supported(struct parport *pb){return 0;}
+static int __devinit parport_ECPPS2_supported(struct parport *pb){return 0;}
#endif /* No IEEE 1284 support */
/* --- IRQ detection -------------------------------------- */
/* Only if supports ECP mode */
-static int __maybe_init programmable_irq_support(struct parport *pb)
+static int __devinit programmable_irq_support(struct parport *pb)
{
int irq, intrLine;
unsigned char oecr = inb (ECONTROL (pb));
@@ -1379,7 +1388,7 @@ static int __maybe_init programmable_irq_support(struct parport *pb)
return irq;
}
-static int __maybe_init irq_probe_ECP(struct parport *pb)
+static int __devinit irq_probe_ECP(struct parport *pb)
{
int i;
unsigned long irqs;
@@ -1408,7 +1417,7 @@ static int __maybe_init irq_probe_ECP(struct parport *pb)
* This detection seems that only works in National Semiconductors
* This doesn't work in SMC, LGS, and Winbond
*/
-static int __maybe_init irq_probe_EPP(struct parport *pb)
+static int __devinit irq_probe_EPP(struct parport *pb)
{
#ifndef ADVANCED_DETECT
return PARPORT_IRQ_NONE;
@@ -1448,7 +1457,7 @@ static int __maybe_init irq_probe_EPP(struct parport *pb)
#endif /* Advanced detection */
}
-static int __maybe_init irq_probe_SPP(struct parport *pb)
+static int __devinit irq_probe_SPP(struct parport *pb)
{
/* Don't even try to do this. */
return PARPORT_IRQ_NONE;
@@ -1461,7 +1470,7 @@ static int __maybe_init irq_probe_SPP(struct parport *pb)
* When ECP is available we can autoprobe for IRQs.
* NOTE: If we can autoprobe it, we can register the IRQ.
*/
-static int __maybe_init parport_irq_probe(struct parport *pb)
+static int __devinit parport_irq_probe(struct parport *pb)
{
const struct parport_pc_private *priv = pb->private_data;
@@ -1495,7 +1504,7 @@ out:
/* --- DMA detection -------------------------------------- */
/* Only if supports ECP mode */
-static int __maybe_init programmable_dma_support (struct parport *p)
+static int __devinit programmable_dma_support (struct parport *p)
{
unsigned char oecr = inb (ECONTROL (p));
int dma;
@@ -1510,7 +1519,7 @@ static int __maybe_init programmable_dma_support (struct parport *p)
return dma;
}
-static int __maybe_init parport_dma_probe (struct parport *p)
+static int __devinit parport_dma_probe (struct parport *p)
{
const struct parport_pc_private *priv = p->private_data;
if (priv->ecr)
@@ -1521,7 +1530,7 @@ static int __maybe_init parport_dma_probe (struct parport *p)
/* --- Initialisation code -------------------------------- */
-struct parport *__maybe_init parport_pc_probe_port (unsigned long int base,
+struct parport *__devinit parport_pc_probe_port (unsigned long int base,
unsigned long int base_hi,
int irq, int dma,
struct pci_dev *dev)
@@ -1693,9 +1702,7 @@ struct parport *__maybe_init parport_pc_probe_port (unsigned long int base,
#endif /* CONFIG_PARPORT_PC_FIFO */
}
- /* Done probing. Now put the port into a sensible start-up state.
- * SELECT | INIT also puts IEEE1284-compliant devices into
- * compatibility mode. */
+ /* Done probing. Now put the port into a sensible start-up state. */
if (priv->ecr)
/*
* Put the ECP detected port in PS2 mode.
@@ -1714,9 +1721,143 @@ struct parport *__maybe_init parport_pc_probe_port (unsigned long int base,
return p;
}
+
+static int __devinit sio_via_686a_probe (struct pci_dev *pdev)
+{
+ u8 dma, irq, tmp;
+ unsigned port1, port2, have_eppecp;
+
+ /*
+ * unlock super i/o configuration, set 0x85_1
+ */
+ pci_read_config_byte (pdev, 0x85, &tmp);
+ tmp |= (1 << 1);
+ pci_write_config_byte (pdev, 0x85, tmp);
+
+ /*
+ * Super I/O configuration, index port == 3f0h, data port == 3f1h
+ */
+
+ /* 0xE2_1-0: Parallel Port Mode / Enable */
+ outb (0xE2, 0x3F0);
+ tmp = inb (0x3F1);
+
+ if ((tmp & 0x03) == 0x03) {
+ printk (KERN_INFO "parport_pc: Via 686A parallel port disabled in BIOS\n");
+ return 0;
+ }
+
+ /* 0xE6: Parallel Port I/O Base Address, bits 9-2 */
+ outb (0xE6, 0x3F0);
+ port1 = inb (0x3F1) << 2;
+
+ switch (port1) {
+ case 0x3bc: port2 = 0x7bc; break;
+ case 0x378: port2 = 0x778; break;
+ case 0x278: port2 = 0x678; break;
+ default:
+ printk (KERN_INFO "parport_pc: Via 686A weird parport base 0x%X, ignoring\n",
+ port1);
+ return 0;
+ }
+
+ /* 0xF0_5: EPP+ECP enable */
+ outb (0xF0, 0x3F0);
+ have_eppecp = (inb (0x3F1) & (1 << 5));
+
+ /*
+ * lock super i/o configuration, clear 0x85_1
+ */
+ pci_read_config_byte (pdev, 0x85, &tmp);
+ tmp &= ~(1 << 1);
+ pci_write_config_byte (pdev, 0x85, tmp);
+
+ /*
+ * Get DMA and IRQ from PCI->ISA bridge PCI config registers
+ */
+
+ /* 0x50_3-2: PnP Routing for Parallel Port DRQ */
+ pci_read_config_byte (pdev, 0x50, &dma);
+ dma = ((dma >> 2) & 0x03);
+
+ /* 0x51_7-4: PnP Routing for Parallel Port IRQ */
+ pci_read_config_byte (pdev, 0x51, &irq);
+ irq = ((irq >> 4) & 0x0F);
+
+ /* filter bogus IRQs */
+ switch (irq) {
+ case 0:
+ case 2:
+ case 8:
+ case 13:
+ irq = PARPORT_IRQ_NONE;
+ break;
+
+ default: /* do nothing */
+ break;
+ }
+
+ /* if ECP not enabled, DMA is not enabled, assumed bogus 'dma' value */
+ if (!have_eppecp)
+ dma = PARPORT_DMA_NONE;
+
+ /* finally, do the probe with values obtained */
+ if (parport_pc_probe_port (port1, port2, irq, dma, NULL)) {
+ printk (KERN_INFO "parport_pc: Via 686A parallel port: io=0x%X, irq=%d, dma=%d\n",
+ port1, irq, dma);
+ return 1;
+ }
+
+ printk (KERN_WARNING "parport_pc: Strange, can't probe Via 686A parallel port: io=0x%X, irq=%d, dma=%d\n",
+ port1, irq, dma);
+ return 0;
+}
+
+
+enum parport_pc_sio_types {
+ sio_via_686a = 0, /* Via VT82C686A motherboard Super I/O */
+};
+
+
+/* each element directly indexed from enum list, above */
+static struct parport_pc_superio {
+ int (*probe) (struct pci_dev *pdev);
+} parport_pc_superio_info[] __devinitdata = {
+ { sio_via_686a_probe, },
+};
+
+
+static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = {
+ { 0x1106, 0x0686, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_686a },
+ { 0, }, /* terminate list */
+};
+
+
+static int __devinit parport_pc_init_superio(void)
+{
+ const struct pci_device_id *id;
+ struct pci_dev *pdev;
+
+ pci_for_each_dev(pdev) {
+ id = pci_match_device (parport_pc_pci_tbl, pdev);
+ if (id == NULL)
+ continue;
+
+ return parport_pc_superio_info[id->driver_data].probe (pdev);
+ }
+
+ return 0; /* zero devices found */
+}
+
+
/* Look for PCI parallel port cards. */
static int __init parport_pc_init_pci (int irq, int dma)
{
+#ifndef PCI_VENDOR_ID_AFAVLAB
+#define PCI_VENDOR_ID_AFAVLAB 0x14db
+#define PCI_DEVICE_ID_AFAVLAB_TK9902 0x2120
+#endif
+
struct {
unsigned int vendor;
unsigned int device;
@@ -1800,6 +1941,9 @@ static int __init parport_pc_init_pci (int irq, int dma)
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014,
2, { { 4, -1 }, { 5, -1 }, } },
+ { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_TK9902,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 1, { { 0, 1 }, } },
{ 0, }
};
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index 6772ea6d8..9ab6d97e2 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -150,13 +150,11 @@ ssize_t parport_device_id (int devnum, char *buffer, size_t len)
if (!retval) {
int idlen;
unsigned char length[2];
- mm_segment_t oldfs = get_fs ();
- set_fs (get_ds ());
/* First two bytes are MSB,LSB of inclusive length. */
retval = parport_read (dev->port, length, 2);
- if (retval != 2) goto restore_fs;
+ if (retval != 2) goto end_id;
idlen = (length[0] << 8) + length[1] - 2;
if (idlen < len)
@@ -169,8 +167,8 @@ ssize_t parport_device_id (int devnum, char *buffer, size_t len)
len);
/* Some printer manufacturers mistakenly believe that
- the length field is supposed to be _exclusive_. */
- /* In addition, there are broken devices out there
+ the length field is supposed to be _exclusive_.
+ In addition, there are broken devices out there
that don't even finish off with a semi-colon. */
if (buffer[len - 1] != ';') {
ssize_t diff;
@@ -196,9 +194,8 @@ ssize_t parport_device_id (int devnum, char *buffer, size_t len)
}
}
- restore_fs:
+ end_id:
buffer[len] = '\0';
- set_fs (oldfs);
parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
}
parport_release (dev);
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 8059dfa22..fe5ea143b 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -247,7 +247,19 @@ void parport_announce_port (struct parport *port)
{
#ifdef CONFIG_PARPORT_1284
/* Analyse the IEEE1284.3 topology of the port. */
- parport_daisy_init (port);
+ if (parport_daisy_init (port) == 0) {
+ /* No devices were detected. Perhaps they are in some
+ funny state; let's try to reset them and see if
+ they wake up. */
+ parport_daisy_fini (port);
+ parport_write_control (port, PARPORT_CONTROL_SELECT);
+ udelay (50);
+ parport_write_control (port,
+ PARPORT_CONTROL_SELECT |
+ PARPORT_CONTROL_INIT);
+ udelay (50);
+ parport_daisy_init (port);
+ }
#endif
/* Let drivers know that a new port has arrived. */