diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-03-02 02:36:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-03-02 02:36:47 +0000 |
commit | 8624512aa908741ba2795200133eae0d7f4557ea (patch) | |
tree | d5d3036fccf2604f4c98dedc11e8adb929d6b52e /drivers/parport | |
parent | 7b8f5d6f1d45d9f9de1d26e7d3c32aa5af11b488 (diff) |
Merge with 2.3.48.
Diffstat (limited to 'drivers/parport')
-rw-r--r-- | drivers/parport/daisy.c | 32 | ||||
-rw-r--r-- | drivers/parport/parport_pc.c | 190 | ||||
-rw-r--r-- | drivers/parport/probe.c | 11 | ||||
-rw-r--r-- | drivers/parport/share.c | 14 |
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. */ |