[PARPORT] Patch-2.3.51: superio#3

From: Gunther Mayer (gunther.mayer@braunschweig.netsurf.de)
Date: Sun Mar 12 2000 - 14:39:10 EST

  • Next message: Mohan P: "Re: [PARPORT] still parport probs"

    Hi,
    this patch adds more chip IDs (Natsemi, SMSC, Winbond)
    and includes a fix for false positives. It reports currently the
    LPT configuration of some selected chips. Often other chip
    types of the same or other vendors are very similar, so don't
    fear this growing without bounds :-)

    Feel free to test and report.
    Regards, Gunther

    diff -ur linux-2.3.51-orig/drivers/parport/init.c linux/drivers/parport/init.c
    --- linux-2.3.51-orig/drivers/parport/init.c Wed Jan 26 21:45:20 2000
    +++ linux/drivers/parport/init.c Sat Mar 11 22:05:30 2000
    @@ -121,6 +121,7 @@
     #ifdef CONFIG_SYSCTL
             parport_default_proc_register ();
     #endif
    + printk("parport - Parallel Port Manager for Linux module V0.90 loaded.\n");
             return 0;
     }
     
    diff -ur linux-2.3.51-orig/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
    --- linux-2.3.51-orig/drivers/parport/parport_pc.c Sat Mar 11 16:30:03 2000
    +++ linux/drivers/parport/parport_pc.c Sun Mar 12 19:41:13 2000
    @@ -1015,7 +1015,144 @@
             parport_ieee1284_read_byte,
     };
     
    -/* Super-IO chipset detection, Winbond, SMSC */
    +/* Super-IO chipset detection, Winbond, SMSC, National Semiconductor (EXPERIMENTAL)
    +
    + Once upon a time there were single purpose chips or even dicrete TTL logic (e.g.
    + the parallel port) on ISA add-on cards. The register interface and functionality
    + was dictated by compatibilty to the de facto IBM PC-Standard. Many manufacturers
    + built these and some even improved functionality (e.g. serial FIFO) only to become
    + itself a de facto standard (e.g. 16550A compatible). Others introduced their own
    + hardware bugs or flaws, unfortunately.
    +
    + Soon some of these were integrated on a single chip. These Multi I/O chips
    + were jumper-configurable for IO, IRQ, etc. The Winbond 83757,777,778 is a popular example.
    + Configuration was error prone and uncomfortable for the user.
    +
    + The Super I/O chips were destined for mainboard integration and are fully software
    + configurable (although many can start with default compatible settings). Many aspects can
    + be configured by the BIOS, but the quality of support depends on the BIOS vendor.
    +
    + The configuration had to be done via IO accesses and there was no common method
    + (like ISA PnP) at these days. So vendors invented their own method: choose two
    + ports that don't conflict with legacy systems and use these as index and data register.
    + The ports chosen were e.g. Read-Only in legacy systems (e.g. 3F0, 370, ...), or otherwise
    + chosen (26E, 398, ...). (Note: the same applies to onboard integrated chipsets of these days
    + (e.g. Opti, Eteq, UMC, SiS, C&T, these used port 0x22,34,24, etc).
    + The configuration regoster layout was proprietary but since some years is oriented
    + on the ISA PnP standard (called mainboard PnP). Some newer chips have real ISAPnP modes.
    + Optionally you have to write a magic sequence of bytes to "open" and "close" configuration
    + mode.
    +
    + To protect against accidential access you can "lock" and hide the configuration by setting
    + some bits, or you can relocate the configuration register pair at your will. If this
    + is done by your BIOS there is no way to detect these...
    +
    + Astonishing it seems possible to identify these parts despite there was no cooperative
    + effort by the manufacturers and many BIOSes do not lock access or relocate:-)
    +
    + This probe currently does it's best being untested on most parts !!!
    + Currently it probes for ALL chips, although you should stop after having detected ONE super I/O
    + chipset. This shall help to identify false detections (negative and positive) and further
    + finetune the routines ...
    +
    + The parallel port suffered in early days by vendor dependend hardware flaws and features,
    + so it is necessary to identify these chips to improve quality of bug reports and further
    + developing. Now you can identify your chip without opening your case! And you are even
    + given further information on configuration aspects that could not be derived by other means.
    +
    + The right forum to discuss issues with this code is the Parport Mailing List on
    + <linux-parport@torque.net> 03/04/2000 gm.
    +
    + Another effect for your comfort is improved autodetection of IO/IRQ/DMA and mode of your
    + parallel port. Some missing piece of this effort that needs further investigation is
    + support for EPP-BIOS (Enhanced Parallel Port) as this should help here too.
    +
    + Notes:
    + (1) EPP-BIOS has nothing to to with EPP-mode, either IEEE1284(EPP1.9) or pre-IEEE1284(1.7),
    + Of course this BIOS supports IEEE1284-ECP mode in most cases.
    + (2) ECP is used with two different meanings:
    + a) ECP as IEEE1284-ECP mode.
    + A physical/electrical transfer protocol over the parallel port as defined by IEEE1284.
    + You can speak ECP mode even over a SPP (Standard Paralllel Port), although slower in
    + comparison to some chipsets that support this in hardware.
    + b) ECP as a ISA-ECP.
    + A register set standard for the ISA bus, as defined by Microsoft et al.
    + Of course ISA-ECP supports the IEEE1284-ECP mode :-)
    + This defines how to let your hardware speak ECP natively.
    +
    + Offtopic:
    + As another side effect other drivers could benefit from this detections as you can get
    + plenty of information about FDC, Serial Port, Infrared Support, Power Management (Legacy,
    + APM and ACPI), KBC, X-Bus, etc. Some newer chips integrate Hardware Monitoring, a watchdog
    + or even a smart card reader interface...
    + Hint: People with buggy APM-BIOS could use this to soft power off their machine directly by
    + fiddling with the right bits (don't ask, I never tried). This is the right place to dive into
    + SMM/SMI BIOS/chipset interactions for the adventureous hacker, too :-)
    + */
    +
    +
    +void show_parconfig_winbond_877(int io, int key, int oldid)
    +{
    + int cr0,cr3,cr4,cr5,cr9,cr17,cr23,cr26,cr27,cr31=0,cr32=0;
    + int efir,efdr;
    + char *modes[]= { "reserved",
    + "EPP+SPP",
    + "ECP",
    + "ECP+EPP"};
    + if(io==0x3f0) {
    + outb(key,io);
    + outb(key,io);
    + efir=io;
    + efdr=io+1;
    + } else { /* 0x250 */
    + outb(key,io);
    + efir=io+1;
    + efdr=io+2;
    + }
    +#define sreg(cr,x) { outb(x,efir); cr=inb(efdr); }
    + sreg(cr0,0);
    + sreg(cr3,3);
    + sreg(cr4,4);
    + sreg(cr5,5);
    + sreg(cr9,9);
    + sreg(cr17,0x17);
    + sreg(cr23,0x23);
    + sreg(cr26,0x26);
    + sreg(cr27,0x27);
    + if(oldid>0x0b) {
    + sreg(cr31,0x31);
    + sreg(cr32,0x32);
    + }
    +#undef sreg
    + outb(0xaa,io);
    +
    + printk("Winbond 83877xx LPT Config cr0=%02x cr3=%02x"
    + "cr4=%02x cr5=%02x cr9=%02x cr17=%02x cr23=%02x"
    + " cr26=%02x cr27=%02x cr31=%02x",
    + cr0,cr3,cr4,cr5,cr9,cr17,cr23,cr26,cr27,cr31);
    +
    + printk ("W83877 LPT Config: io=0x%04x, irq=%c, dma=%c, "
    + "fifo threshold=%d\n", cr23*4,
    + (cr27 &0x0f) ? 'A'-1+(cr27 &0x0f): '-',
    + (cr26 &0x0f) ? 'A'-1+(cr26 &0x0f): '-', cr5 & 0x0f);
    + printk("W83877 LPT Config: enabled=%s power=%s\n",
    + (cr23*4 >=0x100) ?"yes":"no", (cr4 & 0x80) ? "yes" : "no");
    + printk("W83877 LPT Config: Port mode=%s, EPP version =%s\n",
    + (cr9 & 0x80 ) ? modes[(cr0>>2) & 0x03] :
    + (((cr0>>2) & 0x03)?"non parallel": "SPP"),
    + (cr3 & 0x10) ? "1.7" : "1.9");
    + printk("W83877 LPT Config: IRQ line is totem pole in %s",
    + cr17 & 0x10 ? "all modes": "SPP mode/open drain in ECP/EPP");
    + printk("W83877 LPT Config: IRQ %ss AckIntEnable Bit\n",
    + cr17 &0x04 ? "ignore" : "obey");
    +
    + if(oldid>0x0b) {
    + if( cr31 &0x04) printk("W83877 in serial PCI-IRQ mode\n");
    + printk("W83877 Power Management=%sabled,"
    + "LPT auto power management=%sabled\n",
    + (cr32&0x80) ? "en": "dis", (cr32&0x08)? "en": "dis");
    + }
    +}
     
     static void show_parconfig_smsc37c669(int io, int key)
     {
    @@ -1056,7 +1193,7 @@
                    (cr23*4 >=0x100) ?"yes":"no", (cr1 & 4) ? "yes" : "no");
             printk("SMSC LPT Config: Port mode=%s, EPP version =%s\n",
                    (cr1 & 0x08 ) ? "Standard mode only (SPP)" : modes[cr4 & 0x03],
    - (cr4 & 40) ? "1.7" : "1.9");
    + (cr4 & 0x40) ? "1.7" : "1.9");
     
             /* Heuristics ! BIOS setup for this mainboard device limits
                the choices to standard settings, i.e. io-address and IRQ
    @@ -1152,6 +1289,68 @@
             }
     }
     
    +void show_parconfig_pc87306(int io)
    +{ int a=0,i=0,cr0,cr1,cr3,cr4,cr7,cr18,cr19,cr1b;
    +
    +#define sreg(cr,x) { outb(x,io); cr=inb(io+1); }
    + sreg(cr0,0);
    + sreg(cr1,1)
    + sreg(cr3,3);
    + sreg(cr4,4);
    + sreg(cr7,7);
    + sreg(cr18,0x18);
    + sreg(cr19,0x19);
    + sreg(cr1b,0x1b);
    +#undef sreg
    +
    + switch (cr1&0x03) {
    + case 0x00:
    + a=0x378; i=5;
    + if(cr1b & 0x20 ) i=7; /* see datasheet NOTE 1 */
    + break;
    + case 0x01:
    + a=0x3bc; i=7;
    + if(cr1b&0x40) a=cr19*4; /* see datasheet NOTE 2 */
    + break;
    + case 0x02: a=0x278; i=5; break;
    + case 0x03: a=0; break; /* reserved */
    + }
    +
    + if(cr1b & 0x10) { /* this overrides address dependent irq selection */
    + if(cr1b & 0x20 )
    + i=7;
    + else
    + i=5;
    + }
    +
    + printk("PC87306 LPT enabled=%s io=0x%04x irq=%d dmaLine=PDRQ%d (see ECPcnfgDMA)\n",
    + cr0&1? "yes":"no", a,i,cr18&0x08 ? 1:0);
    + /* This chip is EPP XOR ECP. Can select between 2 DMA Lines, but wiring up to vendor */
    + printk("PC87306 EPP=%s%s ECP=%s Bidir=%s\n",
    + cr4&0x01?"yes":"no" , cr4&0x01 ? ( cr4&0x02 ? "(1.9)": "(1.7)") : "",
    + cr4&0x04?"yes":"no" , cr3&0x80?"yes":"no");
    + printk("PC83706 IRQ polarity=%s, IRQ line=%s, ECPcnfgDMA=%d\n EPPtimeoutIRQ=%s",
    + cr4&0x10 ? "highLevel/negativePulse": "inverted(huh!?)",
    + cr4&0x20 ? "totem pole":"open drain", cr18&0x03,
    + cr7&0x04 ? "enabled":"masked");
    +
    + /* set the hints for the normal autodetect code */
    + if(cr0 & 0x01) { /* the settings can be interrogated later ... */
    + while((superios[i].io!= 0) && (i<NR_SUPERIOS))
    + i++;
    + if(i==NR_SUPERIOS)
    + printk("Super-IO: too many chips!\n");
    + else {
    + superios[i].io = a;
    + superios[i].irq = i;
    + superios[i].dma = PARPORT_DMA_NONE;
    + /* arbitrary wiring. Hopefully BIOS sets ECPcnfgDMA correctly */
    + }
    + }
    +
    +}
    +
    +
     static void decode_winbond(int efer, int key, int devid, int devrev, int oldid)
     {
             char *type=NULL;
    @@ -1168,46 +1367,70 @@
     
             /* Values are from public data sheets pdf files, I can just
                confirm 83977TF is correct :-) */
    - if (id == 0x9773) type="83977TF";
    + if (id == 0x9773) type="83977TF / SMSC 97w33x/97x34x";
    + else if (id == 0x9771) type="83977F/AF";
             else if (id == 0x9774) type="83977ATF";
             else if ((id & ~0x0f) == 0x5270) type="83977CTF / SMSC 97w36x";
    - else if ((id & ~0x0f) == 0x52f0) type="83977EF / SMSC 97x35x";
    + else if ((id & ~0x0f) == 0x52f0) type="83977EF / SMSC 97w35x";
             else if ((id & ~0x0f) == 0x5210) type="83627";
             else if ((id & ~0x0f) == 0x6010) type="83697HF";
    + else if ((oldid &0x0f ) == 0x0a) { type="83877F"; progif=1;}
    + else if ((oldid &0x0f ) == 0x0b) { type="83877AF"; progif=1;}
             else if ((oldid &0x0f ) == 0x0c) { type="83877TF"; progif=1;}
             else if ((oldid &0x0f ) == 0x0d) { type="83877ATF"; progif=1;}
             else progif=0;
     
             if(type==NULL)
                     printk("Winbond unknown chip type\n");
    - else
    + else {
                      printk("Winbond chip type %s\n",type);
    -
    - if(progif==2)
    - show_parconfig_winbond(efer,key);
    + if(progif==2)
    + show_parconfig_winbond(efer,key);
    + else /* progif==1 */
    + show_parconfig_winbond_877(efer,key,oldid);
    + }
             return;
     }
     
    -static void decode_smsc(int efer, int key, int devid, int devrev)
    +static void decode_smsc(int efer, int key, int oldid, int oldrev, int id, int rev)
     {
             char *type=NULL;
    - void (*func)(int io, int key);
    - int id;
    + void (*func)(int io, int key)=NULL;
    + int idrev,oldidrev;
     
    - if (devid == devrev)
    + if ((oldid == oldrev) && (id == rev))
                     /* simple heuristics, we happened to read some
    - non-winbond register */
    + non-smsc register */
                     return;
     
    - func=NULL;
    - printk("SMSC chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x\n",
    - efer,key,devid,devrev);
    - id=(devid<<8) | devrev;
    -
    - if (id==0x0302) {type="37c669"; func=show_parconfig_smsc37c669;}
    - else if (id==0x6582) type="37c665IR";
    - else if ((id==0x6502) && (key==0x44)) type="37c665GT";
    - else if ((id==0x6502) && (key==0x55)) type="37c666GT";
    + printk("SMSC chip at EFER=0x%x key=0x%02x id=%02x rev=%02x\n"
    + "oldid=0x%02x oldrev=0x%02x\n",
    + efer,key,id,rev,oldid,oldrev);
    + oldidrev=(oldid<<8) | oldrev;
    + idrev=(id<<8)|rev;
    +
    + if (oldidrev==0x0302) {type="37c669"; func=show_parconfig_smsc37c669;}
    + else if (oldid==0x40) type="37c669FR";
    + else if (oldidrev==0x6582) type="37c665IR";
    + else if ((oldidrev==0x6502) && (key==0x44)) type="37c665GT";
    + else if ((oldidrev==0x6502) && (key==0x55)) type="37c666GT";
    + else if (oldid==0x28) type="37n869"; /* "n" notifies notebook ? */
    + else if (oldid==0x29) type="37n769";
    + else if (oldid==0x78) type="FDC37c78"; /* Floppy disk only */
    + else if (idrev==0x0201) type="37c93x";
    + else if (idrev==0x0301) type="37c83xFR";
    + else if (idrev==0x3001) type="37c93xAPM";
    + else if (id==0x09) type="37n958";
    + else if (id==0x09) type="37n971";
    + else if (id==0x0a) type="37n972";
    + else if (id==0x40) type="37c67";
    + else if (id==0x42) type="37m70 / 37b80";
    + else if (id==0x43) type="37b77";
    + else if (id==0x44) type="37b78";
    + else if (id==0x47) type="37m60";
    + else if (id==0x48) type="37c68";
    + else if (id==0x4c) type="37b72";
    + else if (id==0x4d) type="37m81";
     
             if(type==NULL)
                     printk("SMSC unknown chip type\n");
    @@ -1221,7 +1444,15 @@
     
     static void winbond_check(int io, int key)
     {
    - int devid,devrev,oldid;
    + int devid,devrev,oldid,x_devid,x_devrev,x_oldid;
    +
    + /* first probe without key */
    + outb(0x20,io);
    + x_devid=inb(io+1);
    + outb(0x21,io);
    + x_devrev=inb(io+1);
    + outb(0x09,io);
    + x_oldid=inb(io+1);
     
             outb(key,io);
             outb(key,io); /* Write Magic Sequence to EFER, extended
    @@ -1234,12 +1465,23 @@
             oldid=inb(io+1);
             outb(0xaa,io); /* Magic Seal */
     
    + if( (x_devid==devid) && (x_devrev==devrev) && (x_oldid==oldid))
    + return; /* protection against false positives */
    +
             decode_winbond(io,key,devid,devrev,oldid);
     }
     
    -static void winbond_check2(int io,int key)
    +static void winbond_check1(int io,int key)
     {
    - int devid,devrev,oldid;
    + int devid,devrev,oldid,x_devid,x_devrev,x_oldid;
    +
    + /* do a probe without the key */
    + outb(0x20,io+2);
    + x_devid=inb(io+2);
    + outb(0x21,io+1);
    + x_devrev=inb(io+2);
    + outb(0x09,io+1);
    + x_oldid=inb(io+2);
     
             outb(key,io); /* Write Magic Byte to EFER, extended
                                  funtion enable register */
    @@ -1251,25 +1493,119 @@
             oldid=inb(io+2);
             outb(0xaa,io); /* Magic Seal */
     
    + if( (x_devid==devid) && (x_devrev==devrev) && (x_oldid==oldid))
    + return; /* protection against false positives */
    +
             decode_winbond(io,key,devid,devrev,oldid);
     }
     
     static void smsc_check(int io, int key)
     {
    - int devid,devrev;
    + int id,rev,oldid,oldrev,x_id,x_rev,x_oldid,x_oldrev;
     
    + /* do a probe without the key */
    + outb(0x0d,io);
    + x_oldid=inb(io+1);
    + outb(0x0e,io);
    + x_oldrev=inb(io+1);
    + outb(0x20,io);
    + x_id=inb(io+1);
    + outb(0x21,io);
    + x_rev=inb(io+1);
    +
             outb(key,io);
             outb(key,io); /* Write Magic Sequence to EFER, extended
                                  funtion enable register */
             outb(0x0d,io); /* Write EFIR, extended function index register */
    - devid=inb(io+1); /* Read EFDR, extended function data register */
    + oldid=inb(io+1); /* Read EFDR, extended function data register */
             outb(0x0e,io);
    - devrev=inb(io+1);
    + oldrev=inb(io+1);
    + outb(0x20,io);
    + id=inb(io+1);
    + outb(0x21,io);
    + rev=inb(io+1);
             outb(0xaa,io); /* Magic Seal */
     
    - decode_smsc(io,key,devid,devrev);
    + if( (x_id==id) && (x_oldrev==oldrev) && (x_oldid==oldid) && (x_rev==rev))
    + return; /* protection against false positives */
    +
    + decode_smsc(io,key,oldid,oldrev,id,rev);
     }
     
    +static void ns_check(int io) /* No key !? */
    +{
    + int id,cr8,cr21,cr27,r;
    + char *type=NULL;
    + void (*func)(int io)=NULL;
    +
    + outb(0x20,io); /* Write EFIR, extended function index register */
    + r=inb(io);
    + if (r!=0x20) return; /* read back, all bits must be writable */
    + id=inb(io+1);
    + outb(0x21,io); /* ID for PnP chips */
    + cr21=inb(io+1);
    + outb(0x27,io); /* chip revision */
    + cr27=inb(io+1);
    + outb(0x08,io); /* ID for older chips */
    + cr8=inb(io+1);
    +
    + if ((id == cr21) && (id==cr8))
    + /* simple heuristics, we happened to read some
    + non-NS register */
    + return;
    +
    + printk("National Semiconductor chip at EFER=0x%x id=0x%02x cr21=0x%02x cr27=0x%02x cr8=0x%02x",
    + io,id,cr21,cr27,cr8);
    + switch(id) {
    + case 0xc0: type="PC87307"; break;
    + case 0xcf: type="PC97307"; break;
    + case 0xd0: type="PC87317"; break;
    + case 0xdf: type="PC97317"; break;
    + case 0xe0: type="PC87309"; break;
    + case 0xe1: type="PC87360"; break;
    + case 0xe2: type="PC87351"; break;
    + case 0xe4: type="PC87364"; break;
    + case 0xe8: type="PC87363"; break;
    + case 0xe9: type="PC87366"; break;
    + }
    + if(id==0) {
    + switch(cr8&0xf0) { /* bits 0-2/3 for Revision */
    + case 0x10: type="PC87332"; break;
    + case 0x30: type="PC87303"; break;
    + case 0x50: type="PC87334"; break;
    + case 0x70: type="PC87306"; func=show_parconfig_pc87306; break;
    + case 0xb0: type="PC87338"; break;
    + }
    + }
    +
    + if(type)
    + printk("National Semiconductor chip type %s\n",type);
    + else
    + printk("National Semiconductor unknown chip type\n");
    + if(func) (func)(io);
    +
    +}
    +
    +static void ns_check94(int io)
    +{
    + int r;
    + char *type="unknown";
    +
    + outb(0xff,io);
    + r=inb(io);
    +
    + if(r==0xff)
    + return;
    +
    + if(r==0x07) type="perhaps PC87322"; /* Bits 3-7 read back as zero */
    + if(r==0x03) type="perhaps PC87311/312"; /* Bits 2-7 read back as zero */
    +
    + printk("National Semiconductor chip at EFER=0x%x readback=0x%02x type %s\n"
    + ,io,r,type);
    +}
    +
    +
    +
     
     static void detect_and_report_winbond (void)
     {
    @@ -1278,10 +1614,10 @@
             winbond_check(0x3f0,0x87);
             winbond_check(0x370,0x87);
             winbond_check(0x2e ,0x87);
    - winbond_check(0x4e ,0x87);
    + winbond_check(0x4e ,0x87);
             winbond_check(0x3f0,0x86);
    - winbond_check2(0x250,0x88);
    - winbond_check2(0x250,0x89);
    + winbond_check1(0x250,0x88);
    + winbond_check1(0x250,0x89);
     }
     
     static void detect_and_report_smsc (void)
    @@ -1293,6 +1629,20 @@
             smsc_check(0x370,0x44);
     }
     
    +static void detect_and_report_natsemi (void)
    +{
    + printk("National Semiconductor Super-IO detection,now testing port 2E,4E,15C,26E,398 ...\n");
    + ns_check(0x2e);
    + ns_check(0x4e); /* PC8736x */
    + ns_check(0x15c);
    + ns_check(0x26e);
    + ns_check(0x398); /* PC8733x /8731x !? */
    + ns_check94(0x26e); /* these port were used until 1994 ? */
    + ns_check94(0x398);
    + /* ns_check_87310(0x3f3); their first Super IO. */
    +}
    +
    +
     static int get_superio_dma (struct parport *p)
     {
             int i=0;
    @@ -2379,7 +2729,7 @@
     MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
     MODULE_PARM_DESC(dma, "DMA channel");
     MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
    -MODULE_PARM_DESC(superio, "Enable Super-IO chipset probe");
    +MODULE_PARM_DESC(superio, "Enable Super-IO chipset probe (Experimental!)");
     MODULE_PARM(superio, "i");
     
     int init_module(void)
    @@ -2388,8 +2738,10 @@
                the irq values. */
             unsigned int i, n;
             if (superio) {
    + printk("Super I/O ISA chipset probe is experimental, so don't trust it blindly.\n");
                     detect_and_report_winbond ();
                     detect_and_report_smsc ();
    + detect_and_report_natsemi();
             }
             for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++);
             if (i) {

    -- To unsubscribe, send mail to: linux-parport-request@torque.net --
    -- with the single word "unsubscribe" in the body of the message. --



    This archive was generated by hypermail 2b29 : Sun Mar 12 2000 - 14:49:07 EST