patch-2.3.13 linux/drivers/parport/parport_pc.c
Next file: linux/drivers/parport/share.c
Previous file: linux/drivers/parport/parport_mfc3.c
Back to the patch index
Back to the overall index
- Lines: 439
- Date:
Mon Aug 9 11:37:37 1999
- Orig file:
v2.3.12/linux/drivers/parport/parport_pc.c
- Orig date:
Wed Jul 28 14:47:42 1999
diff -u --recursive --new-file v2.3.12/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
@@ -10,7 +10,6 @@
*
* Cleaned up include files - Russell King <linux@arm.uk.linux.org>
* DMA support - Bert De Jonghe <bert@sophis.be>
- * Better EPP probing - Carlos Henrique Bauer <chbauer@acm.org>
*/
/* This driver should work with any hardware that is broadly compatible
@@ -34,6 +33,9 @@
* only in register addresses (eg because your registers are on 32-bit
* word boundaries) then you can alter the constants in parport_pc.h to
* accomodate this.
+ *
+ * Note that the ECP registers may not start at offset 0x400 for PCI cards,
+ * but rather will start at port->base_hi.
*/
#include <linux/config.h>
@@ -74,7 +76,7 @@
outb ((inb (ECONTROL (pb)) & ~m) ^ v, ECONTROL (pb));
}
-#ifdef CONFIG_PARPORT_1284
+#if defined(CONFIG_PARPORT_1284) || defined(CONFIG_PARPORT_PC_FIFO)
/* Safely change the mode bits in the ECR */
static int change_mode(struct parport *p, int m)
{
@@ -179,7 +181,7 @@
return residue;
}
-#endif /* IEEE 1284 support */
+#endif /* IEEE 1284 support or FIFO support */
/*
* Clear TIMEOUT BIT in EPP MODE
@@ -229,12 +231,16 @@
unsigned char __frob_control (struct parport *p, unsigned char mask,
unsigned char val)
{
+ const unsigned char wm = (PARPORT_CONTROL_STROBE |
+ PARPORT_CONTROL_AUTOFD |
+ PARPORT_CONTROL_INIT |
+ PARPORT_CONTROL_SELECT);
struct parport_pc_private *priv = p->physport->private_data;
unsigned char ctr = priv->ctr;
ctr = (ctr & ~mask) ^ val;
ctr &= priv->ctr_writable; /* only write writable bits. */
outb (ctr, CONTROL (p));
- return priv->ctr = ctr; /* update soft copy */
+ return priv->ctr = ctr & wm; /* update soft copy */
}
void parport_pc_write_control(struct parport *p, unsigned char d)
@@ -939,7 +945,6 @@
parport_pc_data_forward,
parport_pc_data_reverse,
- parport_pc_interrupt,
parport_pc_init_state,
parport_pc_save_state,
parport_pc_restore_state,
@@ -966,7 +971,7 @@
/*
* Checks for port existence, all ports support SPP MODE
*/
-static int __init parport_SPP_supported(struct parport *pb)
+static int __maybe_init parport_SPP_supported(struct parport *pb)
{
unsigned char r, w;
@@ -1043,7 +1048,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 __init parport_ECR_present(struct parport *pb)
+static int __maybe_init parport_ECR_present(struct parport *pb)
{
struct parport_pc_private *priv = pb->private_data;
unsigned char r = 0xc;
@@ -1096,7 +1101,7 @@
* be misdetected here is rather academic.
*/
-static int __init parport_PS2_supported(struct parport *pb)
+static int __maybe_init parport_PS2_supported(struct parport *pb)
{
int ok = 0;
@@ -1124,7 +1129,7 @@
return ok;
}
-static int __init parport_ECP_supported(struct parport *pb)
+static int __maybe_init parport_ECP_supported(struct parport *pb)
{
int i;
int config;
@@ -1235,7 +1240,7 @@
return 1;
}
-static int __init parport_ECPPS2_supported(struct parport *pb)
+static int __maybe_init parport_ECPPS2_supported(struct parport *pb)
{
const struct parport_pc_private *priv = pb->private_data;
int result;
@@ -1255,7 +1260,7 @@
/* EPP mode detection */
-static int __init parport_EPP_supported(struct parport *pb)
+static int __maybe_init parport_EPP_supported(struct parport *pb)
{
const struct parport_pc_private *priv = pb->private_data;
@@ -1290,15 +1295,15 @@
pb->modes |= PARPORT_MODE_EPP;
/* Set up access functions to use EPP hardware. */
- parport_pc_ops.epp_read_data = parport_pc_epp_read_data;
- parport_pc_ops.epp_write_data = parport_pc_epp_write_data;
- parport_pc_ops.epp_read_addr = parport_pc_epp_read_addr;
- parport_pc_ops.epp_write_addr = parport_pc_epp_write_addr;
+ pb->ops->epp_read_data = parport_pc_epp_read_data;
+ pb->ops->epp_write_data = parport_pc_epp_write_data;
+ pb->ops->epp_read_addr = parport_pc_epp_read_addr;
+ pb->ops->epp_write_addr = parport_pc_epp_write_addr;
return 1;
}
-static int __init parport_ECPEPP_supported(struct parport *pb)
+static int __maybe_init parport_ECPEPP_supported(struct parport *pb)
{
struct parport_pc_private *priv = pb->private_data;
int result;
@@ -1317,10 +1322,10 @@
if (result) {
/* Set up access functions to use ECP+EPP hardware. */
- parport_pc_ops.epp_read_data = parport_pc_ecpepp_read_data;
- parport_pc_ops.epp_write_data = parport_pc_ecpepp_write_data;
- parport_pc_ops.epp_read_addr = parport_pc_ecpepp_read_addr;
- parport_pc_ops.epp_write_addr = parport_pc_ecpepp_write_addr;
+ pb->ops->epp_read_data = parport_pc_ecpepp_read_data;
+ pb->ops->epp_write_data = parport_pc_ecpepp_write_data;
+ pb->ops->epp_read_addr = parport_pc_ecpepp_read_addr;
+ pb->ops->epp_write_addr = parport_pc_ecpepp_write_addr;
}
return result;
@@ -1329,18 +1334,18 @@
#else /* No IEEE 1284 support */
/* Don't bother probing for modes we know we won't use. */
-static int __init parport_PS2_supported(struct parport *pb) { return 0; }
-static int __init parport_ECP_supported(struct parport *pb) { return 0; }
-static int __init parport_EPP_supported(struct parport *pb) { return 0; }
-static int __init parport_ECPEPP_supported(struct parport *pb) { return 0; }
-static int __init parport_ECPPS2_supported(struct parport *pb) { return 0; }
+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;}
#endif /* No IEEE 1284 support */
/* --- IRQ detection -------------------------------------- */
/* Only if supports ECP mode */
-static int __init programmable_irq_support(struct parport *pb)
+static int __maybe_init programmable_irq_support(struct parport *pb)
{
int irq, intrLine;
unsigned char oecr = inb (ECONTROL (pb));
@@ -1357,7 +1362,7 @@
return irq;
}
-static int __init irq_probe_ECP(struct parport *pb)
+static int __maybe_init irq_probe_ECP(struct parport *pb)
{
int i;
unsigned long irqs;
@@ -1386,7 +1391,7 @@
* This detection seems that only works in National Semiconductors
* This doesn't work in SMC, LGS, and Winbond
*/
-static int __init irq_probe_EPP(struct parport *pb)
+static int __maybe_init irq_probe_EPP(struct parport *pb)
{
#ifndef ADVANCED_DETECT
return PARPORT_IRQ_NONE;
@@ -1426,7 +1431,7 @@
#endif /* Advanced detection */
}
-static int __init irq_probe_SPP(struct parport *pb)
+static int __maybe_init irq_probe_SPP(struct parport *pb)
{
/* Don't even try to do this. */
return PARPORT_IRQ_NONE;
@@ -1439,7 +1444,7 @@
* When ECP is available we can autoprobe for IRQs.
* NOTE: If we can autoprobe it, we can register the IRQ.
*/
-static int __init parport_irq_probe(struct parport *pb)
+static int __maybe_init parport_irq_probe(struct parport *pb)
{
const struct parport_pc_private *priv = pb->private_data;
@@ -1473,7 +1478,7 @@
/* --- DMA detection -------------------------------------- */
/* Only if supports ECP mode */
-static int __init programmable_dma_support (struct parport *p)
+static int __maybe_init programmable_dma_support (struct parport *p)
{
unsigned char oecr = inb (ECONTROL (p));
int dma;
@@ -1488,7 +1493,7 @@
return dma;
}
-static int __init parport_dma_probe (struct parport *p)
+static int __maybe_init parport_dma_probe (struct parport *p)
{
const struct parport_pc_private *priv = p->private_data;
if (priv->ecr)
@@ -1499,27 +1504,27 @@
/* --- Initialisation code -------------------------------- */
-static int __init probe_one_port(unsigned long int base,
- unsigned long int base_hi,
- int irq, int dma)
+struct parport *__maybe_init parport_pc_probe_port (unsigned long int base,
+ unsigned long int base_hi,
+ int irq, int dma)
{
struct parport_pc_private *priv;
struct parport_operations *ops;
struct parport tmp;
struct parport *p = &tmp;
int probedirq = PARPORT_IRQ_NONE;
- if (check_region(base, 3)) return 0;
+ if (check_region(base, 3)) return NULL;
priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL);
if (!priv) {
printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
- return 0;
+ return NULL;
}
ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
if (!ops) {
printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n",
base);
kfree (priv);
- return 0;
+ return NULL;
}
memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations));
priv->ctr = 0xc;
@@ -1531,7 +1536,7 @@
p->base_hi = base_hi;
p->irq = irq;
p->dma = dma;
- p->modes = PARPORT_MODE_PCSPP;
+ p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
p->ops = ops;
p->private_data = priv;
p->physport = p;
@@ -1550,7 +1555,7 @@
if (!parport_SPP_supported (p)) {
/* No port. */
kfree (priv);
- return 0;
+ return NULL;
}
parport_PS2_supported (p);
@@ -1559,7 +1564,7 @@
PARPORT_DMA_NONE, ops))) {
kfree (priv);
kfree (ops);
- return 0;
+ return NULL;
}
p->base_hi = base_hi;
@@ -1591,21 +1596,22 @@
}
if (p->dma == PARPORT_DMA_AUTO)
p->dma = PARPORT_DMA_NONE;
- if (p->dma != PARPORT_DMA_NONE)
- printk(", dma %d", p->dma);
#ifdef CONFIG_PARPORT_PC_FIFO
if (priv->fifo_depth > 0 && p->irq != PARPORT_IRQ_NONE) {
- parport_pc_ops.compat_write_data =
- parport_pc_compat_write_block_pio;
+ p->ops->compat_write_data = parport_pc_compat_write_block_pio;
#ifdef CONFIG_PARPORT_1284
- parport_pc_ops.ecp_write_data =
- parport_pc_ecp_write_block_pio;
+ p->ops->ecp_write_data = parport_pc_ecp_write_block_pio;
#endif /* IEEE 1284 support */
- if (p->dma != PARPORT_DMA_NONE)
+ if (p->dma != PARPORT_DMA_NONE) {
+ printk(", dma %d", p->dma);
p->modes |= PARPORT_MODE_DMA;
- printk(", using FIFO");
+ }
+ else printk(", using FIFO");
}
+ else
+ /* We can't use the DMA channel after all. */
+ p->dma = PARPORT_DMA_NONE;
#endif /* Allowed to use FIFO/DMA */
printk(" [");
@@ -1648,7 +1654,8 @@
p->name, p->dma);
p->dma = PARPORT_DMA_NONE;
} else {
- priv->dma_buf = (char *) __get_dma_pages(GFP_KERNEL, 1);
+ priv->dma_buf =
+ (char *)__get_dma_pages(GFP_KERNEL, 0);
if (! priv->dma_buf) {
printk (KERN_WARNING "%s: "
"cannot get buffer for DMA, "
@@ -1668,7 +1675,7 @@
/*
* Put the ECP detected port in PS2 mode.
*/
- outb (0x24, ECONTROL (p));
+ outb (0x34, ECONTROL (p));
parport_pc_write_data(p, 0);
parport_pc_data_forward (p);
@@ -1684,7 +1691,7 @@
know about it. */
parport_announce_port (p);
- return 1;
+ return p;
}
/* Look for PCI parallel port cards. */
@@ -1746,6 +1753,7 @@
{ 0, }
};
+ struct pci_dev *pcidev;
int count = 0;
int i;
@@ -1753,7 +1761,7 @@
return 0;
for (i = 0; cards[i].vendor; i++) {
- struct pci_dev *pcidev = NULL;
+ pcidev = NULL;
while ((pcidev = pci_find_device (cards[i].vendor,
cards[i].device,
pcidev)) != NULL) {
@@ -1761,24 +1769,58 @@
for (n = 0; n < cards[i].numports; n++) {
unsigned long lo = cards[i].addr[n].lo;
unsigned long hi = cards[i].addr[n].hi;
- unsigned long io_lo = pcidev->base_address[lo];
- unsigned long io_hi = ((hi < 0) ? 0 :
- pcidev->base_address[hi]);
- io_lo &= PCI_BASE_ADDRESS_IO_MASK;
- io_hi &= PCI_BASE_ADDRESS_IO_MASK;
- if (irq == PARPORT_IRQ_AUTO)
- count += probe_one_port (io_lo, io_hi,
- pcidev->irq,
- dma);
- else
- count += probe_one_port (io_lo, io_hi,
- irq, dma);
+ unsigned long io_lo, io_hi;
+ io_lo = pcidev->resource[lo].start;
+ io_hi = ((hi < 0) ? 0 :
+ pcidev->resource[hi].start);
+ if (irq == PARPORT_IRQ_AUTO) {
+ if (parport_pc_probe_port (io_lo,
+ io_hi,
+ pcidev->irq,
+ dma))
+ count++;
+ } else if (parport_pc_probe_port (io_lo, io_hi,
+ irq, dma))
+ count++;
}
}
}
+ /* Look for parallel controllers that we don't know about. */
+ for (pcidev = pci_devices; pcidev; pcidev = pcidev->next) {
+ const int class_noprogif = pcidev->class & ~0xff;
+ if (class_noprogif != (PCI_CLASS_COMMUNICATION_PARALLEL << 8))
+ continue;
+
+ for (i = 0; cards[i].vendor; i++)
+ if ((cards[i].vendor == pcidev->vendor) &&
+ (cards[i].device == pcidev->device))
+ break;
+ if (cards[i].vendor)
+ /* We know about this one. */
+ continue;
+
+ printk (KERN_INFO
+ "Unknown PCI parallel I/O card (%04x/%04x)\n"
+ "Please send 'lspci' output to "
+ "tim@cyberelk.demon.co.uk\n",
+ pcidev->vendor, pcidev->device);
+ }
+
return count;
}
+
+/* Exported symbols. */
+#ifdef CONFIG_PARPORT_PC_PCMCIA
+
+/* parport_cs needs this in order to dyncamically get us to find ports. */
+EXPORT_SYMBOL (parport_pc_probe_port);
+
+#else
+
+EXPORT_NO_SYMBOLS;
+
+#endif
#ifdef MODULE
static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)