From barrowsr at uwm.edu  Tue Jun  1 18:46:04 2010
From: barrowsr at uwm.edu (Robert Thomas Barrows)
Date: Tue, 1 Jun 2010 17:46:04 -0500 (CDT)
Subject: [Linux-parport] Interrupt Sharing on PCIe
In-Reply-To: <2137080358.16124351275431532288.JavaMail.root@mail03.pantherlink.uwm.edu>
Message-ID: <347019252.16126901275432364574.JavaMail.root@mail03.pantherlink.uwm.edu>

If anyone on this list may be able to shed some light on where I am going wrong with this.  Logic seems
sound and the code is (almost) functional. Just don't know what I am missing.

I have have been able to write code to service an interrupt on a machine with a built in parallel port.
This code also runs on a separate machine with a StarTech PEX1P PCIe Parallel Port Card with one key difference.

The PCIe card shares IRQ 16 with some real heavy hitters:
$ cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
edited ...
 16:     103307    8887197  155256881          0   IO-APIC-fasteoi   uhci_hcd:usb3, pata_jmicron, xhci_hcd:usb9, parport0
edited ...

I have tried forcing parport_pc to be IRQ 7 on boot with
options io=0xAF00 irq=7
but it seems the interrupts I generate still remain on IRQ 16, so I ditched that idea.

Then I thought that by setting the "handle" in parport_register_device I would be able to check that handle when an interrupt
happened to determine if it was from my device.

parport_register_device( ... , ... , ... , ... , irq_func irq, 0, void *handle);

Unfortunately it seems all interrupts on IRQ 16 then suddenly have this handle, even if I don't trigger any on the PCIe Parallel Port.
Meaning my interrupt services ALL of those interrupts listed in my /proc/interrupts


The question is am I doing this wrong or am I attempting something that isn't possible?
Is there an alternative solution, that maybe is radically different?

Thank you for your Time 

-Robb





My makefile and code is as follows:

------------Makefile--------------------------------------------

obj-m   := irqCatcher.o

KDIR    := /lib/modules/$(shell uname -r)/build
PWD     := $(shell pwd)

default:
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

clean:
        rm -f *.o *.ko Module.* *.mod.* *~ modules.order

------------Code: irqCatcher.c-----------------------------------

#include <linux/module.h>
#include <linux/parport.h>
#include <linux/init.h>

MODULE_AUTHOR("This Guy");
MODULE_DESCRIPTION("Driver to catch parallel port interupts.");
MODULE_LICENSE("GPL");

static unsigned int irqCatcher_pp_no;
module_param_named(port, irqCatcher_pp_no, int, 0);
MODULE_PARM_DESC(port, "Which parallel port number are we talking to (default is 0)");

static struct pardevice *irqCatcher_pardevice;
static struct parport   *irqCatcher_parport;
int jInts;
int jNullInts;

static void irqCatcher_interrupt(void *handle)
{
  struct parport *local_parport = handle;
  if (local_parport->name != irqCatcher_parport->name) {
    printk("%d Null Interrupts!\n", ++jNullInts);
    return;
  }

  printk("local_parport->name:              %s \n", local_parport->name);
  printk("irqCatcher_pardevice->port->name: %s \n", irqCatcher_pardevice->port->name);
  printk("Interupt Handled %d Times!\n", ++jInts);
}

static int irqCatcher_getport(void)
{
  jInts = 0;
  jNullInts = 0;

  irqCatcher_parport = parport_find_number(irqCatcher_pp_no);

  if (irqCatcher_parport == NULL) {
    printk(KERN_ERR "irqCatcher: no such parport\n");
    return -ENODEV;
  }

  //irqCatcher_pardevice = parport_register_device(irqCatcher_parport, "irqCatcher", NULL, NULL, irqCatcher_interrupt, PARPORT_DEV_EXCL, irqCatcher_parport);
  irqCatcher_pardevice = parport_register_device(irqCatcher_parport, "irqCatcher", NULL, NULL, irqCatcher_interrupt, 0, irqCatcher_parport);
  parport_put_port(irqCatcher_parport);

  if (!irqCatcher_pardevice)
    return -ENODEV;

  if (parport_claim(irqCatcher_pardevice)) {
    parport_unregister_device(irqCatcher_pardevice);
    return -EBUSY;
  }

  printk("getport success!\n");
  return 0;
}

static int __init irqCatcher_init(void)
{
  int err;
  printk("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");

  err = irqCatcher_getport();
  if (err)
    return err;

  printk("Init Complete!\n");
  parport_write_data(irqCatcher_pardevice->port, 0xFF);
  msleep(1);
  parport_write_data(irqCatcher_pardevice->port, 0x00);
  msleep(1);
  parport_write_data(irqCatcher_pardevice->port, 0xFF);
  msleep(1);
  parport_write_data(irqCatcher_pardevice->port, 0x00);
  msleep(1);
  return 0;
}

static void __exit irqCatcher_exit(void)
{
  parport_release(irqCatcher_pardevice);
  parport_unregister_device(irqCatcher_pardevice);
  printk("Device removed!\n");
  printk("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
}

module_init(irqCatcher_init);
module_exit(irqCatcher_exit);




From bbeky at cfa.harvard.edu  Wed Jun 23 19:19:35 2010
From: bbeky at cfa.harvard.edu (=?UTF-8?Q?Bence_B=C3=A9ky?=)
Date: Wed, 23 Jun 2010 19:19:35 -0400
Subject: [Linux-parport] USB - parallel port converter with individual bit
	control
Message-ID: <AANLkTinhQseTAokhsnXAg11A_5x4C9vHPfb1HTL7vheB@mail.gmail.com>

Hi,

I need help to control home-brew equipment via an USB - parallel port
converter. Any ideas or recommendations are welcome.

In detail: We have a bunch of remote controlled telescopes with
control electronics that we have developed ourselves. Most of the
functionality -- stepper motor driving, ramping, end position sensor
handling -- is implemented in the control computers via parallel port,
and we use every bit available. Also we extensively use hardware
interrupts to react to input bit changes real-time. We would, however,
like to get rid of PCI parallel port cards as it is not clear whether
we can still get spare parts (such cards, computers with PCI ports,
parallel port surcharge isolators etc) in five years from now. Using
USB adapters seems like a good idea.

The main problem is that one cannot find out what chip a certain USB
parallel port converter product uses without buying it. I bought three
of them, one has MosChip 9710:7705, that does not seem to be supported
at all; the other two have 067b:2305 PL2305, that is supported by
usblp but only in IEEE1284 mode. The datasheet of PL2305, rev1.1
2002-08-01 mentions vendor-specific commands that supposedly support
the operation we want, but is not specific about it. This section is
removed from the datasheet in rev1.2 2006-09-26.

I also found that there is a driver for Lucent USS720, that uses that
chip in register mode and creates a parport device.

Any of the following would solve our problems with more or less work:

 - is anyone aware of a driver for PL2305 that uses
parport_register_port and thus creates /dev/parport? device,

 - does anyone have a datasheet (maybe rev1.1E 2006-06-31) or
documentation or specification of PL2305 "vendor-specific device
requests" or any information that would clarify that PL2305 in fact
does not support what we want,

 - does anyone have any information about commercially available USB -
parallel port devices that sport Lucent USS720, or any other chip that
is capable of what we are looking for,

 - does anyone have experience with USB based industrial I/O devices
that we could use?

I didn't find relevant information in the linux-parport archives or on
any forums. Your help is very much appreciated.

Thank you,

Bence B?ky
HAT project
Harvard--Smithsonian Center for Astrophysics


From se_aatif at yahoo.com  Thu Jun 24 00:59:12 2010
From: se_aatif at yahoo.com (AatiF Farooq)
Date: Wed, 23 Jun 2010 21:59:12 -0700 (PDT)
Subject: [Linux-parport] Interrupt calling problem in linux
Message-ID: <996762.9788.qm@web59704.mail.ac4.yahoo.com>

Sir,
??? ??? i m the student of?MCS and working on my final project.
my project is?
Hard disk data recovery in linux.

i was assumed?that i?will access the hard disk in linux using interrupt call function like in windows we include? ?' bios.h '?? and??? ' dos.h ' and?send the interrupt number in 

int86???? function using a C Language program

but in linux i did not found any ??? ' dos.h '???? file. 
i?m a new to linux and i dont know much about it

i want to ask you how to?call the interrupts using C Language program in linux
if you know about any website that having detail about my problem then tell me that site.
or give me some hint how to start.


thank you

???Aatif Farooq????
MCS 2008-10???????????? 
+923136103896???????????


      
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-parport/attachments/20100623/7a51ee33/attachment.html>

From fbriere at fbriere.net  Fri Jun 25 20:23:43 2010
From: fbriere at fbriere.net (=?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Bri=C3=A8re?=)
Date: Fri, 25 Jun 2010 20:23:43 -0400
Subject: [Linux-parport] [PATCH] parport/serial: add support for
	Timedia/SUNIX cards to parport_serial
Message-ID: <1277511823-6973-1-git-send-email-fbriere@fbriere.net>

Timedia/SUNIX PCI cards with both serial and parallel ports are
currently supported by 8250_pci and parport_pc individually.  Moving
that support into parport_serial allows using both types of ports at the
same time.

Note that we assume all such cards belong to the serial PCI class.

This was successfully tested with a SUNIX 4079T.

Signed-off-by: Fr?d?ric Bri?re <fbriere at fbriere.net>
---
(I elected to avoid duplicating the same serial info 18 times, and
cheated a little bit instead.  Let me know if this was a bad idea.)

 drivers/parport/parport_pc.c     |   54 -----------------------------
 drivers/parport/parport_serial.c |   69 +++++++++++++++++++++++++++++++++++++-
 drivers/pci/quirks.c             |   23 ++++++++++++
 drivers/serial/8250_pci.c        |   10 ++++-
 4 files changed, 99 insertions(+), 57 deletions(-)

diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 0950fa4..e5d1d2f 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2866,24 +2866,6 @@ enum parport_pc_pci_cards {
 	lava_parallel_dual_b,
 	boca_ioppar,
 	plx_9050,
-	timedia_4078a,
-	timedia_4079h,
-	timedia_4085h,
-	timedia_4088a,
-	timedia_4089a,
-	timedia_4095a,
-	timedia_4096a,
-	timedia_4078u,
-	timedia_4079a,
-	timedia_4085u,
-	timedia_4079r,
-	timedia_4079s,
-	timedia_4079d,
-	timedia_4079e,
-	timedia_4079f,
-	timedia_9079a,
-	timedia_9079b,
-	timedia_9079c,
 	timedia_4006a,
 	timedia_4014,
 	timedia_4008a,
@@ -2942,24 +2924,6 @@ static struct parport_pc_pci {
 	/* lava_parallel_dual_b */	{ 1, { { 0, -1 }, } },
 	/* boca_ioppar */		{ 1, { { 0, -1 }, } },
 	/* plx_9050 */			{ 2, { { 4, -1 }, { 5, -1 }, } },
-	/* timedia_4078a */		{ 1, { { 2, -1 }, } },
-	/* timedia_4079h */             { 1, { { 2, 3 }, } },
-	/* timedia_4085h */             { 2, { { 2, -1 }, { 4, -1 }, } },
-	/* timedia_4088a */             { 2, { { 2, 3 }, { 4, 5 }, } },
-	/* timedia_4089a */             { 2, { { 2, 3 }, { 4, 5 }, } },
-	/* timedia_4095a */             { 2, { { 2, 3 }, { 4, 5 }, } },
-	/* timedia_4096a */             { 2, { { 2, 3 }, { 4, 5 }, } },
-	/* timedia_4078u */             { 1, { { 2, -1 }, } },
-	/* timedia_4079a */             { 1, { { 2, 3 }, } },
-	/* timedia_4085u */             { 2, { { 2, -1 }, { 4, -1 }, } },
-	/* timedia_4079r */             { 1, { { 2, 3 }, } },
-	/* timedia_4079s */             { 1, { { 2, 3 }, } },
-	/* timedia_4079d */             { 1, { { 2, 3 }, } },
-	/* timedia_4079e */             { 1, { { 2, 3 }, } },
-	/* timedia_4079f */             { 1, { { 2, 3 }, } },
-	/* timedia_9079a */             { 1, { { 2, 3 }, } },
-	/* timedia_9079b */             { 1, { { 2, 3 }, } },
-	/* timedia_9079c */             { 1, { { 2, 3 }, } },
 	/* timedia_4006a */             { 1, { { 0, -1 }, } },
 	/* timedia_4014  */             { 2, { { 0, -1 }, { 2, -1 }, } },
 	/* timedia_4008a */             { 1, { { 0, 1 }, } },
@@ -3021,24 +2985,6 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
 	{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
 	  PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014, 0, 0, plx_9050 },
 	/* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
-	{ 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
-	{ 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
-	{ 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
-	{ 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
-	{ 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
-	{ 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
-	{ 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
-	{ 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
-	{ 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
-	{ 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
-	{ 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
-	{ 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
-	{ 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
-	{ 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
-	{ 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
-	{ 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
-	{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
-	{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
 	{ 0x1409, 0x7268, 0x1409, 0x0101, 0, 0, timedia_4006a },
 	{ 0x1409, 0x7268, 0x1409, 0x0102, 0, 0, timedia_4014 },
 	{ 0x1409, 0x7268, 0x1409, 0x0103, 0, 0, timedia_4008a },
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 40e208d..83510d3 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -41,6 +41,25 @@ enum parport_pc_pci_cards {
 	siig_2p1s_20x,
 	siig_1s1p_20x,
 	siig_2s1p_20x,
+	/* These entries must come last */
+	timedia_4078a,
+	timedia_4079h,
+	timedia_4085h,
+	timedia_4088a,
+	timedia_4089a,
+	timedia_4095a,
+	timedia_4096a,
+	timedia_4078u,
+	timedia_4079a,
+	timedia_4085u,
+	timedia_4079r,
+	timedia_4079s,
+	timedia_4079d,
+	timedia_4079e,
+	timedia_4079f,
+	timedia_9079a,
+	timedia_9079b,
+	timedia_9079c,
 };
 
 /* each element directly indexed from enum list, above */
@@ -105,6 +124,24 @@ static struct parport_pc_pci cards[] __devinitdata = {
 	/* siig_2p1s_20x */		{ 2, { { 1, 2 }, { 3, 4 }, } },
 	/* siig_1s1p_20x */		{ 1, { { 1, 2 }, } },
 	/* siig_2s1p_20x */		{ 1, { { 2, 3 }, } },
+	/* timedia_4078a */		{ 1, { { 2, -1 }, } },
+	/* timedia_4079h */             { 1, { { 2, 3 }, } },
+	/* timedia_4085h */             { 2, { { 2, -1 }, { 4, -1 }, } },
+	/* timedia_4088a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+	/* timedia_4089a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+	/* timedia_4095a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+	/* timedia_4096a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+	/* timedia_4078u */             { 1, { { 2, -1 }, } },
+	/* timedia_4079a */             { 1, { { 2, 3 }, } },
+	/* timedia_4085u */             { 2, { { 2, -1 }, { 4, -1 }, } },
+	/* timedia_4079r */             { 1, { { 2, 3 }, } },
+	/* timedia_4079s */             { 1, { { 2, 3 }, } },
+	/* timedia_4079d */             { 1, { { 2, 3 }, } },
+	/* timedia_4079e */             { 1, { { 2, 3 }, } },
+	/* timedia_4079f */             { 1, { { 2, 3 }, } },
+	/* timedia_9079a */             { 1, { { 2, 3 }, } },
+	/* timedia_9079b */             { 1, { { 2, 3 }, } },
+	/* timedia_9079c */             { 1, { { 2, 3 }, } },
 };
 
 static struct pci_device_id parport_serial_pci_tbl[] = {
@@ -176,6 +213,25 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	/* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
+	{ 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
+	{ 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
+	{ 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
+	{ 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
+	{ 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
+	{ 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
+	{ 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
+	{ 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
+	{ 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
+	{ 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
+	{ 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
+	{ 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
+	{ 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
+	{ 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
+	{ 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
+	{ 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
+	{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
+	{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
 
 	{ 0, } /* terminate list */
 };
@@ -267,6 +323,13 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
 		.base_baud	= 921600,
 		.uart_offset	= 8,
 	},
+	/* All Timedia/SUNIX cards share this entry */
+	[timedia_4078a] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
 };
 
 struct parport_serial_private {
@@ -283,8 +346,12 @@ static int __devinit serial_register (struct pci_dev *dev,
 	struct parport_serial_private *priv = pci_get_drvdata (dev);
 	struct pciserial_board *board;
 	struct serial_private *serial;
+	int idx = id->driver_data;
+
+	if (idx > timedia_4078a)
+		idx = timedia_4078a;
 
-	board = &pci_parport_serial_boards[id->driver_data];
+	board = &pci_parport_serial_boards[idx];
 	serial = pciserial_init_ports(dev, board);
 
 	if (IS_ERR(serial))
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 477345d..2d62b83 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1800,6 +1800,29 @@ static void __devinit quirk_netmos(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);
 
+/*
+ * There are nearly 70 different Timedia/SUNIX PCI serial devices, some of
+ * which also feature a parallel port.  Instead of listing them individually,
+ * 8250_pci merely grabs them all.
+ *
+ * Devices with a parallel port can be identified by their subdevice ID
+ * matching xx[7-9]x.  We thus mark them as class OTHER, so that they will be
+ * ignored by 8250_pci, and claimed by parport_serial instead.
+ */
+static void __devinit quirk_timedia(struct pci_dev *dev)
+{
+	/* 0,2,3,5,6: serial only -- 7,8,9: serial + parallel */
+	if ((dev->subsystem_device & 0x00f0) >= 0x70) {
+		dev_info(&dev->dev, "Timedia %04x; "
+			"changing class SERIAL to OTHER (use parport_serial)\n",
+			dev->subsystem_device);
+		dev->class = (PCI_CLASS_COMMUNICATION_OTHER << 8) |
+		    (dev->class & 0xff);
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
+		quirk_timedia);
+
 static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
 {
 	u16 command, pmcsr;
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 746a446..c294532 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -1347,7 +1347,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.setup		= titan_400l_800l_setup,
 	},
 	/*
-	 * Timedia cards
+	 * Timedia cards - these may be called via parport_serial
 	 */
 	{
 		.vendor		= PCI_VENDOR_ID_TIMEDIA,
@@ -3195,8 +3195,14 @@ static struct pci_device_id serial_pci_tbl[] = {
 	{	PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_oxsemi },
+
+	/*
+	 * Timedia serial cards - class will be forced to OTHER if a
+	 * parallel port is present, to leave them for parport_serial.
+	 */
 	{	PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
-		PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0,
+		PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID,
+		PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00,
 		pbn_b0_bt_1_921600 },
 
 	/*
-- 
1.7.1



