[PARPORT] Patch for ppa in 2.2.0pre1 (and hopefully 2.2.0pre2)


campbell@gear.torque.net
Fri, 1 Jan 1999 15:03:55 +0000


To all parallel port ZIP drive owners...

Attached is a patch for the ppa driver for Linux 2.2.0pre1 (and with
any luck Linux 2.2.0pre2 which was released several hours ago).

Also I found a really wierd BIOS setting which significantly affects
the parallel port speed (more on this later). Anyway, on with the
explanation of the changes:

a) Rearanged a few C functions, when compiled with egcc are just as
   efficient as the asm code.
b) Cleaned up the SCSI error handling in the imm driver.
c) Cleaned up the documentation and the configuration scripts
d) Added additional message to ppa driver to suggest using imm if no
   device found. Hopefully this will give people the hint what to do
   when they try to use ppa for a ZIP Plus drive.
e) Added another compile time option for slow parallel ports. Some
   older 386/486 machines require a small delay after some port
   accesses. This delay can slow down the access speed but is
   required for some devices.

Now for the really wierd BIOS setting I was talking about earlier. On
my K6-300 I have the mainboard parallel port and an old 8 bit
parallel port card stuck in an ISA slot. The following is the timing
for transfering 20MB in seconds (lower number is better).

Mainboard parallel port
        EPP 40 sec (30MB/min)
        PS/2 106 sec (11MB/min)
        SPP 133 sec (9MB/min)

Old XT parallel port card (SPP capabale only)
        Pass A 367 sec (3MB/min)
        Pass B 164 sec (7MB/min)
        Pass C 213 sec (6MB/min)

The difference between the three passes is that I changed what
appears to be an unreleated BIOS parameter. My machine has an Award
BIOS, under "Chipset Features Setup" there is a parameter
"8-Bit I/O Recover Time". This parameter was set for the three passes
to 1, 4 and 8 respectively. I would be interested to hear if other
people observe a similar performance jump.

David Campbell

diff -ru 2.2.0/Documentation/Configure.help linux/Documentation/Configure.help
--- 2.2.0/Documentation/Configure.help Mon Dec 28 02:25:51 1998
+++ linux/Documentation/Configure.help Fri Jan 1 14:00:24 1999
@@ -4349,23 +4349,44 @@
   drive: it will be supported automatically if you said Y to the
   generic "SCSI disk support", above.
 
+ The ZIP Plus drive is supported by the imm driver, also more recent
+ parallel port ZIP drives use an imm compatible interface. If the
+ supplied cable with the drive is labeled "AutoDetect" then you will
+ need the imm driver.
+
   This driver is also available as a module which can be inserted in
   and removed from the running kernel whenever you want. To compile
   this driver as a module, say M here and read
   Documentation/modules.txt. The module will be called ppa.o.
 
-EPP FIFO Checking
-CONFIG_SCSI_PPA_HAVE_PEDANTIC
+IOMEGA Parallel Port ZIP drive SCSI support
+CONFIG_SCSI_IMM
+ All "new and improved" parallel port to SCSI interface from Iomega.
+ Please read the comments for the ppa driver for further information
+
+Force the Iomega ZIP drivers to use EPP-16
+CONFIG_SCSI_IZIP_EPP16
   EPP (Enhanced Parallel Port) is a standard for parallel ports which
   allows them to act as expansion buses that can handle up to 64
- peripheral devices. Some parallel port chipsets are slower than
- their motherboard, and so we have to control the state of the
- chipset's FIFO queue every now and then to avoid data loss. This
- will be done if you say Y here.
+ peripheral devices.
+
+ Some parallel port chipsets are slower than their motherboard, and
+ so we have to control the state of the chipset's FIFO queue every
+ now and then to avoid data loss. This will be done if you say Y here.
   
- If your EPP chipset is from the SMC series, you are likely to have
- to say Y here. Generally, saying Y is the safe option and slows
- things down a bit.
+ Generally, saying Y is the safe option and slows things down a bit.
+
+Assume slow parallel port control register
+CONFIG_SCSI_IZIP_SLOW_CTR
+ Some parallel ports are known to have excessive delays between changing
+ the parallel port control register and good data being available on
+ the parallel port data/status register. This option forces a small delay
+ (1.0 usec to be exact) after changing the control register to let things
+ settle out. Enabling this option may result in a big drop in performance
+ but some very old parallel ports (found in 386 vintage machines) will
+ not work properly.
+
+ Generally, saying N is fine.
 
 SCSI Debug host simulator.
 CONFIG_SCSI_DEBUG
diff -ru 2.2.0/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- 2.2.0/drivers/scsi/Config.in Sat Dec 19 01:47:38 1998
+++ linux/drivers/scsi/Config.in Fri Jan 1 10:04:45 1999
@@ -59,11 +59,12 @@
 dep_tristate 'GDT SCSI Disk Array Controller support' CONFIG_SCSI_GDTH $CONFIG_SCSI
 dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
 if [ "$CONFIG_PARPORT" != "n" ]; then
- dep_tristate 'IOMEGA Parallel Port ZIP drive SCSI support' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
- if [ "$CONFIG_SCSI_PPA" != "n" ]; then
- bool ' Pedantic EPP-checking' CONFIG_SCSI_PPA_HAVE_PEDANTIC
+ dep_tristate 'IOMEGA parallel port (ppa - older drives)' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
+ dep_tristate 'IOMEGA parallel port (imm - newer drives)' CONFIG_SCSI_IMM $CONFIG_SCSI $CONFIG_PARPORT
+ if [ "$CONFIG_SCSI_PPA" != "n" -o "$CONFIG_SCSI_IMM" != "n" ]; then
+ bool ' ppa/imm option - Use slow (but safe) EPP-16' CONFIG_SCSI_IZIP_EPP16
+ bool ' ppa/imm option - Assume slow parport control register' CONFIG_SCSI_IZIP_SLOW_CTR
   fi
- dep_tristate 'IOMEGA ZIP Plus drive SCSI support' CONFIG_SCSI_IMM $CONFIG_SCSI $CONFIG_PARPORT
 fi
 if [ "$CONFIG_SCSI_GENERIC_NCR5380" != "n" ]; then
         bool ' Enable NCR53c400 extensions' CONFIG_SCSI_GENERIC_NCR53C400
diff -ru 2.2.0/drivers/scsi/imm.c linux/drivers/scsi/imm.c
--- 2.2.0/drivers/scsi/imm.c Thu Dec 17 04:29:28 1998
+++ linux/drivers/scsi/imm.c Fri Jan 1 14:03:23 1999
@@ -4,8 +4,7 @@
  * (The IMM is the embedded controller in the ZIP Plus drive.)
  *
  * Current Maintainer: David Campbell (Perth, Western Australia)
- * campbell@gear.torque.net
- * dcampbel@p01.as17.honeywell.com.au
+ * campbell@torque.net
  *
  * My unoffical company acronym list is 21 pages long:
  * FLA: Four letter acronym with built in facility for
@@ -31,7 +30,7 @@
 #include "sd.h"
 #include "hosts.h"
 typedef struct {
- struct pardevice *dev; /* Parport device entry */
+ struct pardevice *dev; /* Parport device entry */
     int base; /* Actual port address */
     int mode; /* Transfer mode */
     int host; /* Host number (for proc) */
@@ -65,23 +64,24 @@
 
 #define IMM_BASE(x) imm_hosts[(x)].base
 
-int parbus_base[NO_HOSTS] = {0x03bc, 0x0378, 0x0278, 0x0000};
+int parbus_base[NO_HOSTS] =
+{0x03bc, 0x0378, 0x0278, 0x0000};
 
 void imm_wakeup(void *ref)
 {
     imm_struct *imm_dev = (imm_struct *) ref;
 
     if (!imm_dev->p_busy)
- return;
+ return;
 
     if (parport_claim(imm_dev->dev)) {
- printk("imm: bug in imm_wakeup\n");
- return;
+ printk("imm: bug in imm_wakeup\n");
+ return;
     }
     imm_dev->p_busy = 0;
     imm_dev->base = imm_dev->dev->port->base;
     if (imm_dev->cur_cmd)
- imm_dev->cur_cmd->SCp.phase++;
+ imm_dev->cur_cmd->SCp.phase++;
     return;
 }
 
@@ -97,12 +97,11 @@
 static int imm_pb_claim(int host_no)
 {
     if (parport_claim(imm_hosts[host_no].dev)) {
- imm_hosts[host_no].p_busy = 1;
- return 1;
+ imm_hosts[host_no].p_busy = 1;
+ return 1;
     }
-
     if (imm_hosts[host_no].cur_cmd)
- imm_hosts[host_no].cur_cmd->SCp.phase++;
+ imm_hosts[host_no].cur_cmd->SCp.phase++;
     return 0;
 }
 
@@ -112,40 +111,7 @@
  * Parallel port probing routines *
  ***************************************************************************/
 
-#ifndef MODULE
-/*
- * Command line parameters (for built-in driver):
- *
- * Syntax: imm=base[,mode[,use_sg]]
- *
- * For example: imm=0x378 or imm=0x378,0,3
- *
- */
-
-void imm_setup(char *str, int *ints)
-{
- static int x = 0;
-
- if (x == 0) { /* Disable ALL known ports */
- int i;
-
- for (i = 0; i < NO_HOSTS; i++)
- parbus_base[i] = 0x0000;
- }
- switch (ints[0]) {
- case 3:
- imm_sg = ints[3];
- case 2:
- imm_hosts[x].mode = ints[2];
- parbus_base[x] = ints[1];
- break;
- default:
- printk("IMM: I only use between 2 to 3 parameters.\n");
- break;
- }
- x++;
-}
-#else
+#ifdef MODULE
 Scsi_Host_Template driver_template = IMM;
 #include "scsi_module.c"
 #endif
@@ -162,100 +128,95 @@
     try_again = 0;
 
     if (!pb) {
- printk("imm: parport reports no devices.\n");
- return 0;
+ printk("imm: parport reports no devices.\n");
+ return 0;
     }
-
   retry_entry:
     for (i = 0; pb; i++, pb = pb->next) {
- int modes, ppb;
+ int modes, ppb;
 
- imm_hosts[i].dev =
- parport_register_device(pb, "imm", NULL, imm_wakeup,
- NULL, 0, (void *) &imm_hosts[i]);
+ imm_hosts[i].dev =
+ parport_register_device(pb, "imm", NULL, imm_wakeup,
+ NULL, 0, (void *) &imm_hosts[i]);
 
         if (!imm_hosts[i].dev)
- continue;
+ continue;
 
- /* Claim the bus so it remembers what we do to the control
- * registers. [ CTR and ECP ]
- */
- if (imm_pb_claim(i))
- {
+ /* Claim the bus so it remembers what we do to the control
+ * registers. [ CTR and ECP ]
+ */
+ if (imm_pb_claim(i)) {
             unsigned long now = jiffies;
- while (imm_hosts[i].p_busy)
- {
+ while (imm_hosts[i].p_busy) {
                 schedule(); /* We are safe to schedule here */
- if (time_after(jiffies,now + 3*HZ))
- {
+ if (time_after(jiffies, now + 3 * HZ)) {
                     printk(KERN_ERR "imm%d: failed to claim parport because a "
- "pardevice is owning the port for too longtime!\n",
+ "pardevice is owning the port for too longtime!\n",
                            i);
                     return 0;
                 }
             }
         }
+ ppb = IMM_BASE(i) = imm_hosts[i].dev->port->base;
+ w_ctr(ppb, 0x0c);
+ modes = imm_hosts[i].dev->port->modes;
 
- ppb = IMM_BASE(i) = imm_hosts[i].dev->port->base;
- w_ctr(ppb, 0x0c);
- modes = imm_hosts[i].dev->port->modes;
-
- /* Mode detection works up the chain of speed
- * This avoids a nasty if-then-else-if-... tree
- */
- imm_hosts[i].mode = IMM_NIBBLE;
-
- if (modes & PARPORT_MODE_PCPS2)
- imm_hosts[i].mode = IMM_PS2;
-
- if (modes & PARPORT_MODE_PCECPPS2) {
- w_ecr(ppb, 0x20);
- imm_hosts[i].mode = IMM_PS2;
- }
- if (modes & PARPORT_MODE_PCECPEPP)
- w_ecr(ppb, 0x80);
-
- /* Done configuration */
- imm_pb_release(i);
-
- if (imm_init(i)) {
- parport_unregister_device(imm_hosts[i].dev);
- continue;
- }
- /* now the glue ... */
- switch (imm_hosts[i].mode) {
- case IMM_NIBBLE:
- ports = 3;
- break;
- case IMM_PS2:
- ports = 3;
- break;
- case IMM_EPP_8:
- case IMM_EPP_16:
- case IMM_EPP_32:
- ports = 8;
- break;
- default: /* Never gets here */
- continue;
- }
-
- host->can_queue = IMM_CAN_QUEUE;
- host->sg_tablesize = imm_sg;
- hreg = scsi_register(host, 0);
- hreg->io_port = pb->base;
- hreg->n_io_port = ports;
- hreg->dma_channel = -1;
- hreg->unique_id = i;
- imm_hosts[i].host = hreg->host_no;
- nhosts++;
+ /* Mode detection works up the chain of speed
+ * This avoids a nasty if-then-else-if-... tree
+ */
+ imm_hosts[i].mode = IMM_NIBBLE;
+
+ if (modes & PARPORT_MODE_PCPS2)
+ imm_hosts[i].mode = IMM_PS2;
+
+ if (modes & PARPORT_MODE_PCECPPS2) {
+ w_ecr(ppb, 0x20);
+ imm_hosts[i].mode = IMM_PS2;
+ }
+ if (modes & PARPORT_MODE_PCECPEPP)
+ w_ecr(ppb, 0x80);
+
+ /* Done configuration */
+ imm_pb_release(i);
+
+ if (imm_init(i)) {
+ parport_unregister_device(imm_hosts[i].dev);
+ continue;
+ }
+ /* now the glue ... */
+ switch (imm_hosts[i].mode) {
+ case IMM_NIBBLE:
+ ports = 3;
+ break;
+ case IMM_PS2:
+ ports = 3;
+ break;
+ case IMM_EPP_8:
+ case IMM_EPP_16:
+ case IMM_EPP_32:
+ ports = 8;
+ break;
+ default: /* Never gets here */
+ continue;
+ }
+
+ host->can_queue = IMM_CAN_QUEUE;
+ host->sg_tablesize = imm_sg;
+ hreg = scsi_register(host, 0);
+ hreg->io_port = pb->base;
+ hreg->n_io_port = ports;
+ hreg->dma_channel = -1;
+ hreg->unique_id = i;
+ imm_hosts[i].host = hreg->host_no;
+ nhosts++;
     }
     if (nhosts == 0) {
- if (try_again == 1)
- return 0;
- try_again = 1;
- goto retry_entry;
+ if (try_again == 1)
+ return 0;
+ try_again = 1;
+ goto retry_entry;
     } else
- return 1; /* return number of hosts detected */
+ return 1; /* return number of hosts detected */
 }
 
 /* This is to give the imm driver a way to modify the timings (and other
@@ -265,22 +226,11 @@
  * testing...
  * Also gives a method to use a script to obtain optimum timings (TODO)
  */
-
-static inline int imm_strncmp(const char *a, const char *b, int len)
-{
- int loop;
- for (loop = 0; loop < len; loop++)
- if (a[loop] != b[loop])
- return 1;
-
- return 0;
-}
-
 static inline int imm_proc_write(int hostno, char *buffer, int length)
 {
     unsigned long x;
 
- if ((length > 5) && (imm_strncmp(buffer, "mode=", 5) == 0)) {
+ if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
         x = simple_strtoul(buffer + 5, NULL, 0);
         imm_hosts[hostno].mode = x;
         return length;
@@ -445,42 +395,34 @@
     int i;
 
     if ((r_ecr(ppb) & 0xe0) != 0x80)
- return;
+ return;
 
     for (i = 0; i < 100; i++) {
- if (r_ecr(ppb) & 0x01)
- return;
- udelay(5);
+ if (r_ecr(ppb) & 0x01)
+ return;
+ udelay(5);
     }
     printk("imm: ECP sync failed as data still present in FIFO.\n");
 }
 
-static inline int imm_byte_out(unsigned short base, const char *buffer, int len)
+static int imm_byte_out(unsigned short base, const char *buffer, int len)
 {
     int i;
 
- w_ctr(base, 0x4); /* aimmrently a sane mode */
+ w_ctr(base, 0x4); /* apparently a sane mode */
     for (i = len >> 1; i; i--) {
         w_dtr(base, *buffer++);
         w_ctr(base, 0x5); /* Drop STROBE low */
         w_dtr(base, *buffer++);
         w_ctr(base, 0x0); /* STROBE high + INIT low */
     }
- w_ctr(base, 0x4); /* aimmrently a sane mode */
+ w_ctr(base, 0x4); /* apparently a sane mode */
     return 1; /* All went well - we hope! */
 }
 
-static inline int imm_epp_out(unsigned short base, char *buffer, int len)
+static int imm_nibble_in(unsigned short base, char *buffer, int len)
 {
- int i;
- for (i = len; i; i--)
- w_epp(base, *buffer++);
- return 1;
-}
-
-static inline int imm_nibble_in(unsigned short base, char *buffer, int len)
-{
- unsigned char h, l;
+ unsigned char l;
     int i;
 
     /*
@@ -489,16 +431,15 @@
     w_ctr(base, 0x4);
     for (i = len; i; i--) {
         w_ctr(base, 0x6);
- l = r_str(base);
+ l = (r_str(base) & 0xf0) >> 4;
         w_ctr(base, 0x5);
- h = r_str(base);
+ *buffer++ = (r_str(base) & 0xf0) | l;
         w_ctr(base, 0x4);
- *buffer++ = (h & 0xf0) | ((l & 0xf0) >> 4);
     }
     return 1; /* All went well - we hope! */
 }
 
-static inline int imm_byte_in(unsigned short base, char *buffer, int len)
+static int imm_byte_in(unsigned short base, char *buffer, int len)
 {
     int i;
 
@@ -514,14 +455,6 @@
     return 1; /* All went well - we hope! */
 }
 
-static inline int imm_epp_in(unsigned short base, char *buffer, int len)
-{
- int i;
- for (i = len; i; i--)
- *buffer++ = r_epp(base);
- return 1;
-}
-
 static int imm_out(int host_no, char *buffer, int len)
 {
     int r;
@@ -543,11 +476,21 @@
     case IMM_EPP_32:
     case IMM_EPP_16:
     case IMM_EPP_8:
- epp_reset(ppb);
- w_ctr(ppb, 0x4);
- r = imm_epp_out(ppb, buffer, len);
- w_ctr(ppb, 0xc);
- ecp_sync(ppb);
+ epp_reset(ppb);
+ w_ctr(ppb, 0x4);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ if (!(((long) buffer | len) & 0x01))
+ outsw(ppb + 4, buffer, len >> 1);
+#else
+ if (!(((long) buffer | len) & 0x03))
+ outsl(ppb + 4, buffer, len >> 2);
+#endif
+ else
+ outsb(ppb + 4, buffer, len);
+ w_ctr(ppb, 0xc);
+ r = !(r_str(ppb) & 0x01);
+ w_ctr(ppb, 0xc);
+ ecp_sync(ppb);
         break;
 
     case IMM_NIBBLE:
@@ -595,11 +538,21 @@
     case IMM_EPP_32:
     case IMM_EPP_16:
     case IMM_EPP_8:
- epp_reset(ppb);
- w_ctr(ppb, 0x24);
- r = imm_epp_in(ppb, buffer, len);
- w_ctr(ppb, 0x2c);
- ecp_sync(ppb);
+ epp_reset(ppb);
+ w_ctr(ppb, 0x24);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ if (!(((long) buffer | len) & 0x01))
+ insw(ppb + 4, buffer, len >> 1);
+#else
+ if (!(((long) buffer | len) & 0x03))
+ insl(ppb + 4, buffer, len >> 2);
+#endif
+ else
+ insb(ppb + 4, buffer, len);
+ w_ctr(ppb, 0x2c);
+ r = !(r_str(ppb) & 0x01);
+ w_ctr(ppb, 0x2c);
+ ecp_sync(ppb);
         break;
 
     default:
@@ -756,8 +709,8 @@
 
 #if defined(CONFIG_PARPORT) || defined(CONFIG_PARPORT_MODULE)
     if (imm_pb_claim(host_no))
- while (imm_hosts[host_no].p_busy)
- schedule(); /* We can safe schedule here */
+ while (imm_hosts[host_no].p_busy)
+ schedule(); /* We can safe schedule here */
 #endif
     retv = imm_connect(host_no, 0);
 
@@ -770,7 +723,6 @@
         imm_pb_release(host_no);
         return retv;
     }
-
     imm_pb_release(host_no);
     return 1;
 }
@@ -831,7 +783,7 @@
          * If we have been running for more than a full timer tick
          * then take a rest.
          */
- if (time_after(jiffies,start_jiffies + 1))
+ if (time_after(jiffies, start_jiffies + 1))
             return 0;
 
         /*
@@ -1173,6 +1125,7 @@
 
 int imm_abort(Scsi_Cmnd * cmd)
 {
+ int host_no = cmd->host->unique_id;
     /*
      * There is no method for aborting commands since Iomega
      * have tied the SCSI_MESSAGE line high in the interface
@@ -1181,12 +1134,11 @@
     switch (cmd->SCp.phase) {
     case 0: /* Do not have access to parport */
     case 1: /* Have not connected to interface */
- cmd->result = DID_ABORT;
- cmd->done(cmd);
- return SCSI_ABORT_SUCCESS;
+ imm_hosts[host_no].cur_cmd = NULL; /* Forget the problem */
+ return SUCCESS;
         break;
     default: /* SCSI command sent, can not abort */
- return SCSI_ABORT_BUSY;
+ return FAILED;
         break;
     }
 }
@@ -1203,46 +1155,20 @@
     w_ctr(base, 0x04);
 }
 
-int imm_reset(Scsi_Cmnd * cmd, unsigned int x)
+int imm_reset(Scsi_Cmnd * cmd)
 {
     int host_no = cmd->host->unique_id;
 
- /*
- * PHASE1:
- * Bring the interface crashing down on whatever is running
- * hopefully this will kill the request.
- * Bring back up the interface, reset the drive (and anything
- * attached for that manner)
- */
- if (cmd)
- if (cmd->SCp.phase)
- imm_disconnect(cmd->host->unique_id);
+ if (cmd->SCp.phase)
+ imm_disconnect(host_no);
+ imm_hosts[host_no].cur_cmd = NULL; /* Forget the problem */
 
     imm_connect(host_no, CONNECT_NORMAL);
     imm_reset_pulse(IMM_BASE(host_no));
- udelay(1000); /* delay for devices to settle down */
+ udelay(1000); /* device settle delay */
     imm_disconnect(host_no);
- udelay(1000); /* Additional delay to allow devices to settle down */
-
- /*
- * PHASE2:
- * Sanity check for the sake of mid-level driver
- */
- if (!cmd) {
- printk("imm bus reset called for invalid command.\n");
- return SCSI_RESET_NOT_RUNNING;
- }
- /*
- * PHASE3:
- * Flag the current command as having died due to reset
- */
- imm_connect(host_no, CONNECT_NORMAL);
- imm_fail(host_no, DID_RESET);
-
- /* Since the command was already on the timer queue imm_interrupt
- * will be called shortly.
- */
- return SCSI_RESET_PENDING;
+ udelay(1000); /* device settle delay */
+ return SUCCESS;
 }
 
 static int device_check(int host_no)
@@ -1257,79 +1183,78 @@
 
     old_mode = imm_hosts[host_no].mode;
     for (loop = 0; loop < 8; loop++) {
- /* Attempt to use EPP for Test Unit Ready */
- if ((ppb & 0x0007) == 0x0000)
- imm_hosts[host_no].mode = IMM_EPP_32;
+ /* Attempt to use EPP for Test Unit Ready */
+ if ((ppb & 0x0007) == 0x0000)
+ imm_hosts[host_no].mode = IMM_EPP_32;
 
       second_pass:
- imm_connect(host_no, CONNECT_EPP_MAYBE);
- /* Select SCSI device */
- if (!imm_select(host_no, loop)) {
- imm_disconnect(host_no);
- continue;
- }
- printk("imm: Found device at ID %i, Attempting to use %s\n", loop,
- IMM_MODE_STRING[imm_hosts[host_no].mode]);
-
- /* Send SCSI command */
- status = 1;
- w_ctr(ppb, 0x0c);
- for (l = 0; (l < 3) && (status); l++)
- status = imm_out(host_no, &cmd[l<<1], 2);
-
- if (!status) {
- imm_disconnect(host_no);
- imm_connect(host_no, CONNECT_EPP_MAYBE);
- w_dtr(ppb, 0x40);
- w_ctr(ppb, 0x08);
- udelay(30);
- w_ctr(ppb, 0x0c);
- udelay(1000);
- imm_disconnect(host_no);
- udelay(1000);
- if (imm_hosts[host_no].mode == IMM_EPP_32) {
- imm_hosts[host_no].mode = old_mode;
- goto second_pass;
- }
- printk("imm: Unable to establish communication, aborting driver load.\n");
- return 1;
- }
- w_ctr(ppb, 0x0c);
-
- k = 1000000; /* 1 Second */
- do {
- l = r_str(ppb);
- k--;
- udelay(1);
- } while (!(l & 0x80) && (k));
-
- l &= 0xb8;
-
- if (l != 0xb8) {
- imm_disconnect(host_no);
- imm_connect(host_no, CONNECT_EPP_MAYBE);
+ imm_connect(host_no, CONNECT_EPP_MAYBE);
+ /* Select SCSI device */
+ if (!imm_select(host_no, loop)) {
+ imm_disconnect(host_no);
+ continue;
+ }
+ printk("imm: Found device at ID %i, Attempting to use %s\n", loop,
+ IMM_MODE_STRING[imm_hosts[host_no].mode]);
+
+ /* Send SCSI command */
+ status = 1;
+ w_ctr(ppb, 0x0c);
+ for (l = 0; (l < 3) && (status); l++)
+ status = imm_out(host_no, &cmd[l << 1], 2);
+
+ if (!status) {
+ imm_disconnect(host_no);
+ imm_connect(host_no, CONNECT_EPP_MAYBE);
+ w_dtr(ppb, 0x40);
+ w_ctr(ppb, 0x08);
+ udelay(30);
+ w_ctr(ppb, 0x0c);
+ udelay(1000);
+ imm_disconnect(host_no);
+ udelay(1000);
+ if (imm_hosts[host_no].mode == IMM_EPP_32) {
+ imm_hosts[host_no].mode = old_mode;
+ goto second_pass;
+ }
+ printk("imm: Unable to establish communication, aborting driver load.\n");
+ return 1;
+ }
+ w_ctr(ppb, 0x0c);
+
+ k = 1000000; /* 1 Second */
+ do {
+ l = r_str(ppb);
+ k--;
+ udelay(1);
+ } while (!(l & 0x80) && (k));
+
+ l &= 0xb8;
+
+ if (l != 0xb8) {
+ imm_disconnect(host_no);
+ imm_connect(host_no, CONNECT_EPP_MAYBE);
             imm_reset_pulse(IMM_BASE(host_no));
- udelay(1000);
- imm_disconnect(host_no);
- udelay(1000);
- if (imm_hosts[host_no].mode == IMM_EPP_32) {
- imm_hosts[host_no].mode = old_mode;
- goto second_pass;
- }
- printk("imm: Unable to establish communication, aborting driver load.\n");
- return 1;
- }
- imm_disconnect(host_no);
- printk("imm: Communication established with ID %i using %s\n", loop,
- IMM_MODE_STRING[imm_hosts[host_no].mode]);
- imm_connect(host_no, CONNECT_EPP_MAYBE);
+ udelay(1000);
+ imm_disconnect(host_no);
+ udelay(1000);
+ if (imm_hosts[host_no].mode == IMM_EPP_32) {
+ imm_hosts[host_no].mode = old_mode;
+ goto second_pass;
+ }
+ printk("imm: Unable to establish communication, aborting driver load.\n");
+ return 1;
+ }
+ imm_disconnect(host_no);
+ printk("imm: Communication established with ID %i using %s\n", loop,
+ IMM_MODE_STRING[imm_hosts[host_no].mode]);
+ imm_connect(host_no, CONNECT_EPP_MAYBE);
         imm_reset_pulse(IMM_BASE(host_no));
- udelay(1000);
- imm_disconnect(host_no);
- udelay(1000);
- return 0;
+ udelay(1000);
+ imm_disconnect(host_no);
+ udelay(1000);
+ return 0;
     }
     printk("imm: No devices found, aborting driver load.\n");
     return 1;
 }
-
diff -ru 2.2.0/drivers/scsi/imm.h linux/drivers/scsi/imm.h
--- 2.2.0/drivers/scsi/imm.h Tue Dec 29 06:10:43 1998
+++ linux/drivers/scsi/imm.h Fri Jan 1 11:43:03 1999
@@ -1,7 +1,8 @@
+
 /* Driver for the Iomega MatchMaker parallel port SCSI HBA embedded in
  * the Iomega ZIP Plus drive
  *
- * (c) 1998 David Campbell campbell@torque.net
+ * (c) 1998 David Campbell campbell@torque.net
  *
  * Please note that I live in Perth, Western Australia. GMT+0800
  */
@@ -9,13 +10,13 @@
 #ifndef _IMM_H
 #define _IMM_H
 
-#define IMM_VERSION "2.00"
+#define IMM_VERSION "2.03 (for Linux 2.0.0)"
 
 /*
  * 10 Apr 1998 (Good Friday) - Received EN144302 by email from Iomega.
  * Scarry thing is the level of support from one of their managers.
  * The onus is now on us (the developers) to shut up and start coding.
- * 11Apr98 [ 0.10 ]
+ * 11Apr98 [ 0.10 ]
  *
  * --- SNIP ---
  *
@@ -24,35 +25,40 @@
  * Removing "Phase" debug messages.
  *
  * PS: Took four hours of coding after I bought a drive.
- * ANZAC Day (Aus "War Veterans Holiday") 25Apr98 [ 0.14 ]
+ * ANZAC Day (Aus "War Veterans Holiday") 25Apr98 [ 0.14 ]
  *
  * Ten minutes later after a few fixes.... (LITERALLY!!!)
  * Have mounted disk, copied file, dismounted disk, remount disk, diff file
  * ----- It actually works!!! -----
- * 25Apr98 [ 0.15 ]
+ * 25Apr98 [ 0.15 ]
  *
  * Twenty minutes of mucking around, rearanged the IEEE negotiate mechanism.
  * Now have byte mode working (only EPP and ECP to go now... :=)
- * 26Apr98 [ 0.16 ]
+ * 26Apr98 [ 0.16 ]
  *
  * Thirty minutes of further coding results in EPP working on my machine.
- * 27Apr98 [ 0.17 ]
+ * 27Apr98 [ 0.17 ]
  *
  * Due to work commitments and inability to get a "true" ECP mode functioning
  * I have decided to code the parport support into imm.
- * 09Jun98 [ 0.18 ]
+ * 09Jun98 [ 0.18 ]
  *
  * Driver is now out of beta testing.
  * Support for parport has been added.
  * Now distributed with the ppa driver.
- * 12Jun98 [ 2.00 ]
+ * 12Jun98 [ 2.00 ]
  *
  * Err.. It appears that imm-2.00 was broken....
- * 18Junn98 [ 2.01 ]
+ * 18Jun98 [ 2.01 ]
  *
  * Patch applied to sync this against the Linux 2.1.x kernel code
  * Included qboot_zip.sh
- * 21Jun98 [ 2.02 ]
+ * 21Jun98 [ 2.02 ]
+ *
+ * Other clean ups include the follow changes:
+ * CONFIG_SCSI_PPA_HAVE_PEDANTIC => CONFIG_SCSI_IZIP_EPP16
+ * added CONFIG_SCSI_IZIP_SLOW_CTR option
+ * [2.03]
  */
 /* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
 
@@ -92,7 +98,11 @@
     "PS/2",
     "EPP 8 bit",
     "EPP 16 bit",
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ "EPP 16 bit",
+#else
     "EPP 32 bit",
+#endif
     "Unknown"};
 
 /* This is a global option */
@@ -110,21 +120,24 @@
 #define CONNECT_EPP_MAYBE 1
 #define CONNECT_NORMAL 0
 
-#define inb_x inb
-#define r_dtr(x) (unsigned char)inb_x((x))
-#define r_str(x) (unsigned char)inb_x((x)+1)
-#define r_ctr(x) (unsigned char)inb_x((x)+2)
-#define r_epp(x) (unsigned char)inb_x((x)+4)
-#define r_fifo(x) (unsigned char)inb_x((x)+0x400)
-#define r_ecr(x) (unsigned char)inb_x((x)+0x402)
-
-#define outb_x outb
-#define w_dtr(x,y) outb_x(y, (x))
-#define w_str(x,y) outb_x(y, (x)+1)
-#define w_ctr(x,y) outb_x(y, (x)+2)
-#define w_epp(x,y) outb_x(y, (x)+4)
-#define w_fifo(x,y) outb_x(y, (x)+0x400)
-#define w_ecr(x,y) outb_x(y, (x)+0x402)
+#define r_dtr(x) (unsigned char)inb((x))
+#define r_str(x) (unsigned char)inb((x)+1)
+#define r_ctr(x) (unsigned char)inb((x)+2)
+#define r_epp(x) (unsigned char)inb((x)+4)
+#define r_fifo(x) (unsigned char)inb((x)+0x400)
+#define r_ecr(x) (unsigned char)inb((x)+0x402)
+
+#define w_dtr(x,y) outb(y, (x))
+#define w_str(x,y) outb(y, (x)+1)
+#define w_epp(x,y) outb(y, (x)+4)
+#define w_fifo(x,y) outb(y, (x)+0x400)
+#define w_ecr(x,y) outb(y, (x)+0x402)
+
+#ifdef CONFIG_SCSI_IZIP_SLOW_CTR
+#define w_ctr(x,y) outb_p(y, (x)+2)
+#else
+#define w_ctr(x,y) outb(y, (x)+2)
+#endif
 
 static int imm_engine(imm_struct *, Scsi_Cmnd *);
 static int imm_in(int, char *, int);
@@ -144,23 +157,25 @@
 int imm_command(Scsi_Cmnd *);
 int imm_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
 int imm_abort(Scsi_Cmnd *);
-int imm_reset(Scsi_Cmnd *, unsigned int);
+int imm_reset(Scsi_Cmnd *);
 int imm_proc_info(char *, char **, off_t, int, int, int);
 int imm_biosparam(Disk *, kdev_t, int *);
 
-#define IMM { proc_dir: &proc_scsi_imm, \
- proc_info: imm_proc_info, \
- name: "Iomega ZIP Plus drive", \
- detect: imm_detect, \
- release: imm_release, \
- command: imm_command, \
- queuecommand: imm_queuecommand, \
- abort: imm_abort, \
- reset: imm_reset, \
- bios_param: imm_biosparam, \
- this_id: 7, \
- sg_tablesize: SG_ALL, \
- cmd_per_lun: 1, \
- use_clustering: ENABLE_CLUSTERING\
+#define IMM { proc_dir: &proc_scsi_imm, \
+ proc_info: imm_proc_info, \
+ name: "Iomega VPI2 (imm) interface",\
+ detect: imm_detect, \
+ release: imm_release, \
+ command: imm_command, \
+ queuecommand: imm_queuecommand, \
+ eh_abort_handler: imm_abort, \
+ eh_device_reset_handler: NULL, \
+ eh_bus_reset_handler: imm_reset, \
+ eh_host_reset_handler: imm_reset, \
+ bios_param: imm_biosparam, \
+ this_id: 7, \
+ sg_tablesize: SG_ALL, \
+ cmd_per_lun: 1, \
+ use_clustering: ENABLE_CLUSTERING \
 }
 #endif /* _IMM_H */
diff -ru 2.2.0/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c
--- 2.2.0/drivers/scsi/ppa.c Tue Dec 29 03:06:11 1998
+++ linux/drivers/scsi/ppa.c Fri Jan 1 14:03:32 1999
@@ -7,8 +7,7 @@
  * under the terms of the GNU Public License.
  *
  * Current Maintainer: David Campbell (Perth, Western Australia, GMT+0800)
- * campbell@gear.torque.net
- * dcampbel@p01.as17.honeywell.com.au
+ * campbell@torque.net
  */
 
 #include <linux/config.h>
@@ -68,7 +67,6 @@
         printk("ppa: bug in ppa_wakeup\n");
         return;
     }
-
     ppa_dev->p_busy = 0;
     ppa_dev->base = ppa_dev->dev->port->base;
     if (ppa_dev->cur_cmd)
@@ -91,7 +89,6 @@
         ppa_hosts[host_no].p_busy = 1;
         return 1;
     }
-
     if (ppa_hosts[host_no].cur_cmd)
         ppa_hosts[host_no].cur_cmd->SCp.phase++;
     return 0;
@@ -133,30 +130,26 @@
 
         ppa_hosts[i].dev =
             parport_register_device(pb, "ppa", NULL, ppa_wakeup,
- NULL, 0, (void *) &ppa_hosts[i]);
+ NULL, 0, (void *) &ppa_hosts[i]);
 
         if (!ppa_hosts[i].dev)
- continue;
+ continue;
 
         /* Claim the bus so it remembers what we do to the control
          * registers. [ CTR and ECP ]
          */
- if (ppa_pb_claim(i))
- {
+ if (ppa_pb_claim(i)) {
             unsigned long now = jiffies;
- while (ppa_hosts[i].p_busy)
- {
+ while (ppa_hosts[i].p_busy) {
                 schedule(); /* We are safe to schedule here */
- if (time_after(jiffies,now + 3*HZ))
- {
+ if (time_after(jiffies, now + 3 * HZ)) {
                     printk(KERN_ERR "ppa%d: failed to claim parport because a "
- "pardevice is owning the port for too longtime!\n",
+ "pardevice is owning the port for too longtime!\n",
                            i);
                     return 0;
                 }
             }
         }
-
         ppb = PPA_BASE(i) = ppa_hosts[i].dev->port->base;
         w_ctr(ppb, 0x0c);
         modes = ppa_hosts[i].dev->port->modes;
@@ -211,8 +204,15 @@
         nhosts++;
     }
     if (nhosts == 0) {
- if (try_again == 1)
+ if (try_again == 1) {
+ printk("WARNING - no ppa compatible devices found.\n");
+ printk(" As of 31/Aug/1998 Iomega started shipping parallel\n");
+ printk(" port ZIP drives with a different interface which is\n");
+ printk(" supported by the imm (ZIP Plus) driver. If the\n");
+ printk(" cable is marked with \"AutoDetect\", this is what has\n");
+ printk(" happened.\n");
             return 0;
+ }
         try_again = 1;
         goto retry_entry;
     } else
@@ -227,21 +227,11 @@
  * Also gives a method to use a script to obtain optimum timings (TODO)
  */
 
-static inline int ppa_strncmp(const char *a, const char *b, int len)
-{
- int loop;
- for (loop = 0; loop < len; loop++)
- if (a[loop] != b[loop])
- return 1;
-
- return 0;
-}
-
 static inline int ppa_proc_write(int hostno, char *buffer, int length)
 {
     unsigned long x;
 
- if ((length > 5) && (ppa_strncmp(buffer, "mode=", 5) == 0)) {
+ if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
         x = simple_strtoul(buffer + 5, NULL, 0);
         ppa_hosts[hostno].mode = x;
         return length;
@@ -360,245 +350,42 @@
     printk("ppa: ECP sync failed as data still present in FIFO.\n");
 }
 
-/*
- * Here is the asm code for the SPP/PS2 protocols for the i386.
- * This has been optimised for speed on 386/486 machines. There will
- * be very little improvement on the current 586+ machines as it is the
- * IO statements which will limit throughput.
- */
-#ifdef __i386__
-#define BYTE_OUT(reg) \
- " movb " #reg ",%%al\n" \
- " outb %%al,(%%dx)\n" \
- " addl $2,%%edx\n" \
- " movb $0x0e,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " movb $0x0c,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " subl $2,%%edx\n"
-
-static inline int ppa_byte_out(unsigned short base, char *buffer, unsigned int len)
+static int ppa_byte_out(unsigned short base, const char *buffer, int len)
 {
- /*
- * %eax scratch
- * %ebx Data to transfer
- * %ecx Counter (Don't touch!!)
- * %edx Port
- * %esi Source buffer (mem pointer)
- *
- * In case you are wondering what the last line of the asm does...
- * <output allocation> : <input allocation> : <trashed registers>
- */
- register int d0;
-
- asm("shr $2,%%ecx\n" \
- " jz .no_more_bulk_bo\n" \
- " .p2align 4,,7\n" \
- "".loop_bulk_bo:\n" \
- " movl (%%esi),%%ebx\n" \
- BYTE_OUT(%%bl) \
- BYTE_OUT(%%bh) \
- " rorl $16,%%ebx\n" \
- BYTE_OUT(%%bl) \
- BYTE_OUT(%%bh) \
- " addl $4,%%esi\n" \
- " loop .loop_bulk_bo\n" \
- " .p2align 4,,7\n" \
- ".no_more_bulk_bo:" \
- : "=S"(buffer), "=c"(d0)
- : "1"(len), "d"(base), "0"(buffer)
- : "eax", "ebx");
-
- asm("andl $3,%%ecx\n" \
- " jz .no_more_loose_bo\n" \
- " .p2align 4,,7\n" \
- ".loop_loose_bo:\n" \
- BYTE_OUT((%%esi)) \
- " incl %%esi\n" \
- " loop .loop_loose_bo\n" \
- ".no_more_loose_bo:\n" \
- : "=c"(d0)
- : "0"(len), "d"(base), "S"(buffer)
- : "eax", "ebx");
- return 1; /* All went well - we hope! */
-}
-
-#define BYTE_IN(reg) \
- " inb (%%dx),%%al\n" \
- " movb %%al," #reg "\n" \
- " addl $2,%%edx\n" \
- " movb $0x27,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " movb $0x25,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " subl $2,%%edx\n"
-
-static inline int ppa_byte_in(unsigned short base, char *buffer, int len)
-{
- /*
- * %eax scratch
- * %ebx Data to transfer
- * %ecx Counter (Don't touch!!)
- * %edx Port
- * %esi Source buffer (mem pointer)
- *
- * In case you are wondering what the last line of the asm does...
- * <output allocation> : <input allocation> : <trashed registers>
- */
- register int d0;
-
- asm("shr $2,%%ecx\n" \
- " jz .no_more_bulk_bi\n" \
- " .p2align 4,,7\n" \
- ".loop_bulk_bi:\n" \
- BYTE_IN(%%bl) \
- BYTE_IN(%%bh) \
- " rorl $16,%%ebx\n" \
- BYTE_IN(%%bl) \
- BYTE_IN(%%bh) \
- " rorl $16,%%ebx\n" \
- " movl %%ebx,(%%esi)\n" \
- " addl $4,%%esi\n" \
- " loop .loop_bulk_bi\n" \
- " .p2align 4,,7\n" \
- ".no_more_bulk_bi:" \
- : "=S"(buffer), "=c"(d0)
- : "1"(len), "d"(base), "0"(buffer)
- : "eax", "ebx");
-
- asm("andl $3,%%ecx\n" \
- " jz .no_more_loose_bi\n" \
- " .p2align 4,,7\n" \
- ".loop_loose_bi:\n" \
- BYTE_IN((%%esi)) \
- " incl %%esi\n" \
- " loop .loop_loose_bi\n" \
- ".no_more_loose_bi:\n" \
- : "=c"(d0)
- : "0"(len), "d"(base), "S"(buffer)
- : "eax", "ebx");
- return 1; /* All went well - we hope! */
-}
-
-#define NIBBLE_IN(reg) \
- " incl %%edx\n" \
- " movb $0x04,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " decl %%edx\n" \
- " inb (%%dx),%%al\n" \
- " andb $0xf0,%%al\n" \
- " movb %%al," #reg "\n" \
- " incl %%edx\n" \

- " movb $0x06,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " decl %%edx\n" \
- " inb (%%dx),%%al\n" \
- " shrb $4,%%al\n" \
- " orb %%al," #reg "\n"
-
-static inline int ppa_nibble_in(unsigned short str_p, char *buffer, int len)
-{
- /*
- * %eax scratch
- * %ebx Data to transfer
- * %ecx Counter (Don't touch!!)
- * %edx Port
- * %esi Source buffer (mem pointer)
- *
- * In case you are wondering what the last line of the asm does...
- * <output allocation> : <input allocation> : <trashed registers>
- */
- register int d0;
-
- asm("shr $2,%%ecx\n" \
- " jz .no_more_bulk_ni\n" \
- " .p2align 4,,7\n" \
- ".loop_bulk_ni:\n" \
- NIBBLE_IN(%%bl) \
- NIBBLE_IN(%%bh) \
- " rorl $16,%%ebx\n" \
- NIBBLE_IN(%%bl) \
- NIBBLE_IN(%%bh) \
- " rorl $16,%%ebx\n" \
- " movl %%ebx,(%%esi)\n" \
- " addl $4,%%esi\n" \
- " loop .loop_bulk_ni\n" \
- " .p2align 4,,7\n" \
- ".no_more_bulk_ni:" \
- : "=S"(buffer), "=c"(d0)
- : "1"(len), "d"(str_p), "0"(buffer)
- : "eax", "ebx");
-
- asm("andl $3,%%ecx\n" \
- " jz .no_more_loose_ni\n" \
- " .p2align 4,,7\n" \
- ".loop_loose_ni:\n" \
- NIBBLE_IN((%%esi)) \
- " incl %%esi\n" \
- " loop .loop_loose_ni\n" \
- ".no_more_loose_ni:\n" \
- : "=c"(d0)
- : "0"(len), "d"(str_p), "S"(buffer)
- : "eax", "ebx");
- return 1; /* All went well - we hope! */
-}
-#else /* Old style C routines */
-
-static inline int ppa_byte_out(unsigned short base, const char *buffer, int len)
-{
- unsigned sht ctr_p = base + 2;
     int i;
 
     for (i = len; i; i--) {
- outb(*buffer++, base);
- outb(0xe, ctr_p);
- outb(0xc, ctr_p);
+ w_dtr(base, *buffer++);
+ w_ctr(base, 0xe);
+ w_ctr(base, 0xc);
     }
     return 1; /* All went well - we hope! */
 }
 
-static inline int ppa_byte_in(unsigned short base, char *buffer, int len)
+static int ppa_byte_in(unsigned short base, char *buffer, int len)
 {
- unsigned short ctr_p = base + 2;
     int i;
 
     for (i = len; i; i--) {
- *buffer++ = inb(base);
- outb(0x27, ctr_p);
- outb(0x25, ctr_p);
+ *buffer++ = r_dtr(base);
+ w_ctr(base, 0x27);
+ w_ctr(base, 0x25);
     }
     return 1; /* All went well - we hope! */
 }
 
-static inline int ppa_nibble_in(unsigned short str_p, char *buffer, int len)
+static int ppa_nibble_in(unsigned short base, char *buffer, int len)
 {
- unsigned short ctr_p = str_p + 1;
- unsigned char h, l;
- int i;
+ for (; len; len--) {
+ unsigned char h;
 
- for (i = len; i; i--) {
- outb(0x4, ctr_p);
- h = inb(str_p);
- outb(0x6, ctr_p);
- l = inb(str_p);
- *buffer++ = (h & 0xf0) | ((l & 0xf0) >> 4);
+ w_ctr(base, 0x4);
+ h = r_str(base) & 0xf0;;
+ w_ctr(base, 0x6);
+ *buffer++ = h | ((r_str(base) & 0xf0) >> 4);
     }
     return 1; /* All went well - we hope! */
 }
-#endif
-
-static inline int ppa_epp_out(unsigned short epp_p, unsigned short str_p, const char *buffer, int len)
-{
- int i;
- for (i = len; i; i--) {
- outb(*buffer++, epp_p);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
- if (inb(str_p) & 0x01)
- return 0;
-#endif
- }
- return 1;
-}
 
 static int ppa_out(int host_no, char *buffer, int len)
 {
@@ -623,16 +410,17 @@
     case PPA_EPP_8:
         epp_reset(ppb);
         w_ctr(ppb, 0x4);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
- r = ppa_epp_out(ppb + 4, ppb + 1, buffer, len);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ if (!(((long) buffer | len) & 0x01))
+ outsw(ppb + 4, buffer, len >> 1);
 #else
         if (!(((long) buffer | len) & 0x03))
             outsl(ppb + 4, buffer, len >> 2);
+#endif
         else
             outsb(ppb + 4, buffer, len);
         wctr(ppb, 0xc);
         r = !(r_str(ppb) & 0x01);
-#endif
         w_ctr(ppb, 0xc);
         ecp_sync(ppb);
         break;
@@ -644,19 +432,6 @@
     return r;
 }
 
-static inline int ppa_epp_in(int epp_p, int str_p, char *buffer, int len)
-{
- int i;
- for (i = len; i; i--) {
- *buffer++ = inb(epp_p);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
- if (inb(str_p) & 0x01)
- return 0;
-#endif
- }
- return 1;
-}
-
 static int ppa_in(int host_no, char *buffer, int len)
 {
     int r;
@@ -671,7 +446,7 @@
     switch (ppa_hosts[host_no].mode) {
     case PPA_NIBBLE:
         /* 4 bit input, with a loop */
- r = ppa_nibble_in(ppb + 1, buffer, len);
+ r = ppa_nibble_in(ppb, buffer, len);
         w_ctr(ppb, 0xc);
         break;
 
@@ -688,16 +463,17 @@
     case PPA_EPP_8:
         epp_reset(ppb);
         w_ctr(ppb, 0x24);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
- r = ppa_epp_in(ppb + 4, ppb + 1, buffer, len);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ if (!(((long) buffer | len) & 0x01))
+ insw(ppb + 4, buffer, len >> 1);
 #else
         if (!(((long) buffer | len) & 0x03))
             insl(ppb + 4, buffer, len >> 2);
+#endif
         else
             insb(ppb + 4, buffer, len);
         w_ctr(ppb, 0x2c);
         r = !(r_str(ppb) & 0x01);
-#endif
         w_ctr(ppb, 0x2c);
         ecp_sync(ppb);
         break;
@@ -885,7 +661,7 @@
          * If we have been running for more than a full timer tick
          * then take a rest.
          */
- if (time_after(jiffies,start_jiffies + 1))
+ if (time_after(jiffies, start_jiffies + 1))
             return 0;
 
         if (((r & 0xc0) != 0xc0) || (cmd->SCp.this_residual <= 0)) {
@@ -1059,8 +835,7 @@
             if ((r_str(ppb) & 0x08) == 0x00)
                 retv--;
 
- if (retv)
- {
+ if (retv) {
                 if ((jiffies - tmp->jstart) > (1 * HZ)) {
                     printk("ppa: Parallel port cable is unplugged!!\n");
                     ppa_fail(host_no, DID_BUS_BUSY);
diff -ru 2.2.0/drivers/scsi/ppa.h linux/drivers/scsi/ppa.h
--- 2.2.0/drivers/scsi/ppa.h Tue Dec 29 06:10:42 1998
+++ linux/drivers/scsi/ppa.h Fri Jan 1 11:42:57 1999
@@ -2,15 +2,15 @@
  * the Iomega ZIP drive
  *
  * (c) 1996 Grant R. Guenther grant@torque.net
- * David Campbell campbell@torque.net
+ * David Campbell campbell@torque.net
  *
- * All comments to David.
+ * All comments to David.
  */
 
 #ifndef _PPA_H
 #define _PPA_H
 
-#define PPA_VERSION "2.01"
+#define PPA_VERSION "2.03 (for Linux 2.0.0)"
 
 /*
  * this driver has been hacked by Matteo Frigo (athena@theory.lcs.mit.edu)
@@ -26,21 +26,31 @@
  *
  * Corrected ppa.h for 2.1.x kernels (>=2.1.85)
  * Modified "Nat Semi Kludge" for extended chipsets
- * [1.41]
+ * [1.41]
  *
  * Fixed id_probe for EPP 1.9 chipsets (misdetected as EPP 1.7)
- * [1.42]
+ * [1.42]
  *
  * Development solely for 2.1.x kernels from now on!
- * [2.00]
+ * [2.00]
  *
  * Hack and slash at the init code (EPP device check routine)
  * Added INSANE option.
- * [2.01]
+ * [2.01]
  *
  * Patch applied to sync against the 2.1.x kernel code
  * Included qboot_zip.sh
- * [2.02]
+ * [2.02]
+ *
+ * Cleaned up the mess left by someone else trying to fix the
+ * asm section to keep egcc happy. The asm section no longer
+ * exists, the nibble code is *almost* as fast as the asm code
+ * providing it is compiled with egcc.
+ *
+ * Other clean ups include the follow changes:
+ * CONFIG_SCSI_PPA_HAVE_PEDANTIC => CONFIG_SCSI_IZIP_EPP16
+ * added CONFIG_SCSI_IZIP_SLOW_CTR option
+ * [2.03]
  */
 /* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
 
@@ -80,7 +90,11 @@
     "PS/2",
     "EPP 8 bit",
     "EPP 16 bit",
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ "EPP 16 bit",
+#else
     "EPP 32 bit",
+#endif
     "Unknown"};
 
 /* This is a global option */
@@ -98,23 +112,6 @@
 #define CONNECT_EPP_MAYBE 1
 #define CONNECT_NORMAL 0
 
-/* INSANE code */
-#define PPA_INSANE 0
-#if PPA_INSANE > 0
-#define r_dtr(x) (unsigned char)inb_p((x))
-#define r_str(x) (unsigned char)inb_p((x)+1)
-#define r_ctr(x) (unsigned char)inb_p((x)+2)
-#define r_epp(x) (unsigned char)inb_p((x)+4)
-#define r_fifo(x) (unsigned char)inb_p((x)+0x400)
-#define r_ecr(x) (unsigned char)inb_p((x)+0x402)
-
-#define w_dtr(x,y) outb_p(y, (x))
-#define w_str(x,y) outb_p(y, (x)+1)
-#define w_ctr(x,y) outb_p(y, (x)+2)
-#define w_epp(x,y) outb_p(y, (x)+4)
-#define w_fifo(x,y) outb_p(y, (x)+0x400)
-#define w_ecr(x,y) outb_p(y, (x)+0x402)
-#else /* PPA_INSANE */
 #define r_dtr(x) (unsigned char)inb((x))
 #define r_str(x) (unsigned char)inb((x)+1)
 #define r_ctr(x) (unsigned char)inb((x)+2)
@@ -124,11 +121,15 @@
 
 #define w_dtr(x,y) outb(y, (x))
 #define w_str(x,y) outb(y, (x)+1)
-#define w_ctr(x,y) outb(y, (x)+2)
 #define w_epp(x,y) outb(y, (x)+4)
 #define w_fifo(x,y) outb(y, (x)+0x400)
 #define w_ecr(x,y) outb(y, (x)+0x402)
-#endif /* PPA_INSANE */
+
+#ifdef CONFIG_SCSI_IZIP_SLOW_CTR
+#define w_ctr(x,y) outb_p(y, (x)+2)
+#else
+#define w_ctr(x,y) outb(y, (x)+2)
+#endif
 
 static int ppa_engine(ppa_struct *, Scsi_Cmnd *);
 static int ppa_in(int, char *, int);
@@ -154,7 +155,7 @@
 
 #define PPA { proc_dir: &proc_scsi_ppa, \
                 proc_info: ppa_proc_info, \
- name: "Iomega parport ZIP drive",\
+ name: "Iomega VPI0 (ppa) interface",\
                 detect: ppa_detect, \
                 release: ppa_release, \
                 command: ppa_command, \

-- 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 2.0b3 on Fri 01 Jan 1999 - 08:40:02 EST