patch-2.3.48 linux/drivers/parport/parport_pc.c
Next file: linux/drivers/parport/probe.c
Previous file: linux/drivers/parport/daisy.c
Back to the patch index
Back to the overall index
- Lines: 346
- Date:
Sat Feb 26 20:34:34 2000
- Orig file:
v2.3.47/linux/drivers/parport/parport_pc.c
- Orig date:
Sun Feb 20 21:12:39 2000
diff -u --recursive --new-file v2.3.47/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
@@ -681,6 +681,7 @@
/* 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 @@
/* 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 @@
/* 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 @@
/*
* 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 @@
* 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 @@
* 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 @@
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 @@
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 @@
/* 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 @@
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 @@
#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 @@
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 @@
* 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 @@
#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 @@
* 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 @@
/* --- 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 @@
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 @@
/* --- 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 @@
#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 @@
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 @@
{ 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, }
};
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)