vserver 2.0 rc7
[linux-2.6.git] / drivers / scsi / atp870u.c
index 27136a2..45b75dd 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/* 
  *  Copyright (C) 1997 Wu Ching Chen
  *  2.1.x update (C) 1998  Krzysztof G. Baranowski
  *  2.5.x update (C) 2002  Red Hat <alan@redhat.com>
@@ -13,8 +13,9 @@
  *                fix disconnect bug  2000/12/21
  *                support atp880 chip lvd u160 2001/05/15
  *                fix prd table bug 2001/09/12 (7.1)
+ *
+ * atp885 support add by ACARD Hao Ping Lian 2005/01/05
  */
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include "atp870u.h"
 
 static struct scsi_host_template atp870u_template;
-static void send_s870(struct Scsi_Host *host);
+static void send_s870(struct atp_unit *dev,unsigned char c);
+static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
+static void tscam_885(void);
 
-
-static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
-                                       struct pt_regs *regs)
+static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
 {
        unsigned long flags;
        unsigned short int tmpcip, id;
-       unsigned char i, j, target_id, lun;
+       unsigned char i, j, c, target_id, lun,cmdp;
        unsigned char *prd;
-       struct scsi_cmnd *workrequ;
-       unsigned int workportu, tmport;
-       unsigned long adrcntu, k;
+       struct scsi_cmnd *workreq;
+       unsigned int workport, tmport, tmport1;
+       unsigned long adrcnt, k;
+#ifdef ED_DBGP
+       unsigned long l;
+#endif
        int errstus;
        struct Scsi_Host *host = dev_id;
        struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
 
-       dev->in_int = 1;
-       workportu = dev->ioport;
-       tmport = workportu;
-
-       if (dev->working != 0) {
-               tmport += 0x1f;
+       for (c = 0; c < 2; c++) {
+               tmport = dev->ioport[c] + 0x1f;
                j = inb(tmport);
-               if ((j & 0x80) == 0) {
-                       dev->in_int = 0;
-                       return IRQ_NONE;
-               }
-
-               tmpcip = dev->pciport;
-               if ((inb(tmpcip) & 0x08) != 0) {
+               if ((j & 0x80) != 0)
+               {                       
+                       goto ch_sel;
+               }
+               dev->in_int[c] = 0;
+       }
+       return IRQ_NONE;
+ch_sel:
+#ifdef ED_DBGP 
+       printk("atp870u_intr_handle enter\n");
+#endif 
+       dev->in_int[c] = 1;
+       cmdp = inb(dev->ioport[c] + 0x10);
+       workport = dev->ioport[c];
+       if (dev->working[c] != 0) {
+               if (dev->dev_id == ATP885_DEVID) {
+                       tmport1 = workport + 0x16;
+                       if ((inb(tmport1) & 0x80) == 0)
+                               outb((inb(tmport1) | 0x80), tmport1);
+               }               
+               tmpcip = dev->pciport[c];
+               if ((inb(tmpcip) & 0x08) != 0)
+               {
                        tmpcip += 0x2;
-                       for (k = 0; k < 1000; k++) {
+                       for (k=0; k < 1000; k++) {
                                if ((inb(tmpcip) & 0x08) == 0) {
                                        goto stop_dma;
                                }
@@ -80,18 +96,24 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
                        }
                }
 stop_dma:
-               tmpcip = dev->pciport;
+               tmpcip = dev->pciport[c];
                outb(0x00, tmpcip);
                tmport -= 0x08;
-
+               
                i = inb(tmport);
+               
+               if (dev->dev_id == ATP885_DEVID) {
+                       tmpcip += 2;
+                       outb(0x06, tmpcip);
+                       tmpcip -= 2;
+               }
 
                tmport -= 0x02;
                target_id = inb(tmport);
                tmport += 0x02;
 
                /*
-                *      Remap wide devices onto id numbers
+                *      Remap wide devices onto id numbers
                 */
 
                if ((target_id & 0x40) != 0) {
@@ -101,332 +123,460 @@ stop_dma:
                }
 
                if ((j & 0x40) != 0) {
-                       if (dev->last_cmd == 0xff) {
-                               dev->last_cmd = target_id;
-                       }
-                       dev->last_cmd |= 0x40;
-               }
-
+                    if (dev->last_cmd[c] == 0xff) {
+                       dev->last_cmd[c] = target_id;
+                    }
+                    dev->last_cmd[c] |= 0x40;
+               }
+               if (dev->dev_id == ATP885_DEVID) 
+                       dev->r1f[c][target_id] |= j;
+#ifdef ED_DBGP
+               printk("atp870u_intr_handle status = %x\n",i);
+#endif 
                if (i == 0x85) {
-                       if ((dev->last_cmd & 0xf0) != 0x40) {
-                               dev->last_cmd = 0xff;
+                       if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+                          dev->last_cmd[c] = 0xff;
+                       }
+                       if (dev->dev_id == ATP885_DEVID) {
+                               tmport -= 0x05;
+                               adrcnt = 0;
+                               ((unsigned char *) &adrcnt)[2] = inb(tmport++);
+                               ((unsigned char *) &adrcnt)[1] = inb(tmport++);
+                               ((unsigned char *) &adrcnt)[0] = inb(tmport);
+                               if (dev->id[c][target_id].last_len != adrcnt)
+                               {
+                                       k = dev->id[c][target_id].last_len;
+                                       k -= adrcnt;
+                                       dev->id[c][target_id].tran_len = k;                        
+                               dev->id[c][target_id].last_len = adrcnt;                           
+                               }
+#ifdef ED_DBGP
+                               printk("tmport = %x dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = %d\n",tmport,dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len);
+#endif         
                        }
+
                        /*
                         *      Flip wide
-                        */
-                       if (dev->wide_idu != 0) {
-                               tmport = workportu + 0x1b;
+                        */                     
+                       if (dev->wide_id[c] != 0) {
+                               tmport = workport + 0x1b;
                                outb(0x01, tmport);
                                while ((inb(tmport) & 0x01) != 0x01) {
                                        outb(0x01, tmport);
                                }
-                       }
+                       }               
                        /*
-                        *      Issue more commands
+                        *      Issue more commands
                         */
-                       spin_lock_irqsave(dev->host->host_lock, flags);
-                       if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) && (dev->in_snd == 0)) {
-                               send_s870(host);
+                       spin_lock_irqsave(dev->host->host_lock, flags);                                          
+                       if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) &&
+                           (dev->in_snd[c] == 0)) {
+#ifdef ED_DBGP
+                               printk("Call sent_s870\n");
+#endif                         
+                               send_s870(dev,c);
                        }
                        spin_unlock_irqrestore(dev->host->host_lock, flags);
                        /*
-                        *      Done
+                        *      Done
                         */
-                       dev->in_int = 0;
-                       goto out;
+                       dev->in_int[c] = 0;
+#ifdef ED_DBGP
+                               printk("Status 0x85 return\n");
+#endif                         
+                       goto handled;
                }
 
                if (i == 0x40) {
-                       dev->last_cmd |= 0x40;
-                       dev->in_int = 0;
-                       goto out;
+                    dev->last_cmd[c] |= 0x40;
+                    dev->in_int[c] = 0;
+                    goto handled;
                }
 
                if (i == 0x21) {
-                       if ((dev->last_cmd & 0xf0) != 0x40) {
-                               dev->last_cmd = 0xff;
+                       if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+                          dev->last_cmd[c] = 0xff;
                        }
                        tmport -= 0x05;
-                       adrcntu = 0;
-                       ((unsigned char *) &adrcntu)[2] = inb(tmport++);
-                       ((unsigned char *) &adrcntu)[1] = inb(tmport++);
-                       ((unsigned char *) &adrcntu)[0] = inb(tmport);
-                       k = dev->id[target_id].last_lenu;
-                       k -= adrcntu;
-                       dev->id[target_id].tran_lenu = k;
-                       dev->id[target_id].last_lenu = adrcntu;
+                       adrcnt = 0;
+                       ((unsigned char *) &adrcnt)[2] = inb(tmport++);
+                       ((unsigned char *) &adrcnt)[1] = inb(tmport++);
+                       ((unsigned char *) &adrcnt)[0] = inb(tmport);
+                       k = dev->id[c][target_id].last_len;
+                       k -= adrcnt;
+                       dev->id[c][target_id].tran_len = k;
+                       dev->id[c][target_id].last_len = adrcnt;
                        tmport -= 0x04;
                        outb(0x41, tmport);
                        tmport += 0x08;
                        outb(0x08, tmport);
-                       dev->in_int = 0;
-                       goto out;
+                       dev->in_int[c] = 0;
+                       goto handled;
+               }
+
+               if (dev->dev_id == ATP885_DEVID) {
+                       if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) {
+                               if ((i == 0x4c) || (i == 0x8c)) 
+                                       i=0x48;
+                               else 
+                                       i=0x49;
+                       }       
+                       
                }
                if ((i == 0x80) || (i == 0x8f)) {
+#ifdef ED_DBGP
+                       printk(KERN_DEBUG "Device reselect\n");
+#endif                 
                        lun = 0;
                        tmport -= 0x07;
-                       j = inb(tmport);
-                       if (j == 0x44 || i == 0x80) {
+                       if (cmdp == 0x44 || i==0x80) {
                                tmport += 0x0d;
                                lun = inb(tmport) & 0x07;
                        } else {
-                               if ((dev->last_cmd & 0xf0) != 0x40) {
-                                       dev->last_cmd = 0xff;
+                               if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+                                  dev->last_cmd[c] = 0xff;
                                }
-                               if (j == 0x41) {
+                               if (cmdp == 0x41) {
+#ifdef ED_DBGP
+                                       printk("cmdp = 0x41\n");
+#endif                                         
                                        tmport += 0x02;
-                                       adrcntu = 0;
-                                       ((unsigned char *) &adrcntu)[2] = inb(tmport++);
-                                       ((unsigned char *) &adrcntu)[1] = inb(tmport++);
-                                       ((unsigned char *) &adrcntu)[0] = inb(tmport);
-                                       k = dev->id[target_id].last_lenu;
-                                       k -= adrcntu;
-                                       dev->id[target_id].tran_lenu = k;
-                                       dev->id[target_id].last_lenu = adrcntu;
+                                       adrcnt = 0;
+                                       ((unsigned char *) &adrcnt)[2] = inb(tmport++);
+                                       ((unsigned char *) &adrcnt)[1] = inb(tmport++);
+                                       ((unsigned char *) &adrcnt)[0] = inb(tmport);
+                                       k = dev->id[c][target_id].last_len;
+                                       k -= adrcnt;
+                                       dev->id[c][target_id].tran_len = k;
+                                       dev->id[c][target_id].last_len = adrcnt;
                                        tmport += 0x04;
                                        outb(0x08, tmport);
-                                       dev->in_int = 0;
-                                       goto out;
+                                       dev->in_int[c] = 0;
+                                       goto handled;
                                } else {
+#ifdef ED_DBGP
+                                       printk("cmdp != 0x41\n");
+#endif                                         
                                        outb(0x46, tmport);
-                                       dev->id[target_id].dirctu = 0x00;
+                                       dev->id[c][target_id].dirct = 0x00;
                                        tmport += 0x02;
                                        outb(0x00, tmport++);
                                        outb(0x00, tmport++);
                                        outb(0x00, tmport++);
                                        tmport += 0x03;
                                        outb(0x08, tmport);
-                                       dev->in_int = 0;
-                                       goto out;
+                                       dev->in_int[c] = 0;
+                                       goto handled;
                                }
                        }
-                       if (dev->last_cmd != 0xff) {
-                               dev->last_cmd |= 0x40;
+                       if (dev->last_cmd[c] != 0xff) {
+                          dev->last_cmd[c] |= 0x40;
                        }
-                       tmport = workportu + 0x10;
-                       outb(0x45, tmport);
-                       tmport += 0x06;
+                       if (dev->dev_id == ATP885_DEVID) {
+                               j = inb(dev->baseport + 0x29) & 0xfe;
+                               outb(j, dev->baseport + 0x29);
+                               tmport = workport + 0x16;
+                       } else {
+                               tmport = workport + 0x10;
+                               outb(0x45, tmport);
+                               tmport += 0x06;                         
+                       }
+                       
                        target_id = inb(tmport);
                        /*
-                        *      Remap wide identifiers
+                        *      Remap wide identifiers
                         */
                        if ((target_id & 0x10) != 0) {
                                target_id = (target_id & 0x07) | 0x08;
                        } else {
                                target_id &= 0x07;
                        }
-                       workrequ = dev->id[target_id].curr_req;
-                       tmport = workportu + 0x0f;
+                       if (dev->dev_id == ATP885_DEVID) {
+                               tmport = workport + 0x10;
+                               outb(0x45, tmport);
+                       }
+                       workreq = dev->id[c][target_id].curr_req;
+#ifdef ED_DBGP                 
+                       printk(KERN_DEBUG "Channel = %d ID = %d LUN = %d CDB",c,workreq->device->id,workreq->device->lun);
+                       for(l=0;l<workreq->cmd_len;l++)
+                       {
+                               printk(KERN_DEBUG " %x",workreq->cmnd[l]);
+                       }
+#endif 
+                       
+                       tmport = workport + 0x0f;
                        outb(lun, tmport);
                        tmport += 0x02;
-                       outb(dev->id[target_id].devspu, tmport++);
-                       adrcntu = dev->id[target_id].tran_lenu;
-                       k = dev->id[target_id].last_lenu;
+                       outb(dev->id[c][target_id].devsp, tmport++);
+                       adrcnt = dev->id[c][target_id].tran_len;
+                       k = dev->id[c][target_id].last_len;
+
                        outb(((unsigned char *) &k)[2], tmport++);
                        outb(((unsigned char *) &k)[1], tmport++);
                        outb(((unsigned char *) &k)[0], tmport++);
+#ifdef ED_DBGP                 
+                       printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k, inb(tmport-1), inb(tmport-2), inb(tmport-3));
+#endif                 
                        /* Remap wide */
                        j = target_id;
                        if (target_id > 7) {
                                j = (j & 0x07) | 0x40;
                        }
                        /* Add direction */
-                       j |= dev->id[target_id].dirctu;
+                       j |= dev->id[c][target_id].dirct;
                        outb(j, tmport++);
-                       outb(0x80, tmport);
-
-                       /* enable 32 bit fifo transfer */
-                       if (dev->deviceid != 0x8081) {
-                               tmport = workportu + 0x3a;
-                               if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
-                                       outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
-                               } else {
-                                       outb((unsigned char) (inb(tmport) & 0xf3), tmport);
+                       outb(0x80,tmport);
+                       
+                       /* enable 32 bit fifo transfer */       
+                       if (dev->dev_id == ATP885_DEVID) {
+                               tmpcip = dev->pciport[c] + 1;
+                               i=inb(tmpcip) & 0xf3;
+                               //j=workreq->cmnd[0];                           
+                               if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+                                  i |= 0x0c;
                                }
-                       } else {
-                               tmport = workportu - 0x05;
-                               if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
+                               outb(i,tmpcip);                                         
+                       } else if ((dev->dev_id == ATP880_DEVID1) ||
+                                  (dev->dev_id == ATP880_DEVID2) ) {
+                               tmport = workport - 0x05;
+                               if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
                                        outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
                                } else {
                                        outb((unsigned char) (inb(tmport) & 0x3f), tmport);
                                }
-                       }
-
-                       tmport = workportu + 0x1b;
+                       } else {                                
+                               tmport = workport + 0x3a;
+                               if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+                                       outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
+                               } else {
+                                       outb((unsigned char) (inb(tmport) & 0xf3), tmport);
+                               }                                                                                                               
+                       }       
+                       tmport = workport + 0x1b;
                        j = 0;
                        id = 1;
                        id = id << target_id;
                        /*
-                        *      Is this a wide device
+                        *      Is this a wide device
                         */
-                       if ((id & dev->wide_idu) != 0) {
+                       if ((id & dev->wide_id[c]) != 0) {
                                j |= 0x01;
                        }
                        outb(j, tmport);
                        while ((inb(tmport) & 0x01) != j) {
-                               outb(j, tmport);
+                               outb(j,tmport);
                        }
-
-                       if (dev->id[target_id].last_lenu == 0) {
-                               tmport = workportu + 0x18;
+                       if (dev->id[c][target_id].last_len == 0) {
+                               tmport = workport + 0x18;
                                outb(0x08, tmport);
-                               dev->in_int = 0;
-                               goto out;
+                               dev->in_int[c] = 0;
+#ifdef ED_DBGP
+                               printk("dev->id[c][target_id].last_len = 0\n");
+#endif                                 
+                               goto handled;
                        }
-                       prd = dev->id[target_id].prd_posu;
-                       while (adrcntu != 0) {
-                               id = ((unsigned short int *) (prd))[2];
+#ifdef ED_DBGP
+                       printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
+#endif                 
+                       prd = dev->id[c][target_id].prd_pos;
+                       while (adrcnt != 0) {
+                               id = ((unsigned short int *)prd)[2];
                                if (id == 0) {
                                        k = 0x10000;
                                } else {
                                        k = id;
                                }
-                               if (k > adrcntu) {
-                                       ((unsigned short int *) (prd))[2] = (unsigned short int)
-                                           (k - adrcntu);
-                                       ((unsigned long *) (prd))[0] += adrcntu;
-                                       adrcntu = 0;
-                                       dev->id[target_id].prd_posu = prd;
+                               if (k > adrcnt) {
+                                       ((unsigned short int *)prd)[2] = (unsigned short int)
+                                           (k - adrcnt);
+                                       ((unsigned long *)prd)[0] += adrcnt;
+                                       adrcnt = 0;
+                                       dev->id[c][target_id].prd_pos = prd;
                                } else {
-                                       adrcntu -= k;
-                                       dev->id[target_id].prdaddru += 0x08;
+                                       adrcnt -= k;
+                                       dev->id[c][target_id].prdaddr += 0x08;
                                        prd += 0x08;
-                                       if (adrcntu == 0) {
-                                               dev->id[target_id].prd_posu = prd;
+                                       if (adrcnt == 0) {
+                                               dev->id[c][target_id].prd_pos = prd;
                                        }
-                               }
+                               }                               
                        }
-                       tmpcip = dev->pciport + 0x04;
-                       outl(dev->id[target_id].prdaddru, tmpcip);
-                       tmpcip -= 0x02;
-                       outb(0x06, tmpcip);
-                       outb(0x00, tmpcip);
-                       tmpcip -= 0x02;
-                       tmport = workportu + 0x18;
+                       tmpcip = dev->pciport[c] + 0x04;
+                       outl(dev->id[c][target_id].prdaddr, tmpcip);
+#ifdef ED_DBGP
+                       printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr);
+#endif
+                       if (dev->dev_id == ATP885_DEVID) {
+                               tmpcip -= 0x04;
+                       } else {
+                               tmpcip -= 0x02;
+                               outb(0x06, tmpcip);
+                               outb(0x00, tmpcip);
+                               tmpcip -= 0x02;
+                       }
+                       tmport = workport + 0x18;
                        /*
-                        *      Check transfer direction
+                        *      Check transfer direction
                         */
-                       if (dev->id[target_id].dirctu != 0) {
+                       if (dev->id[c][target_id].dirct != 0) {
                                outb(0x08, tmport);
                                outb(0x01, tmpcip);
-                               dev->in_int = 0;
-                               goto out;
+                               dev->in_int[c] = 0;
+#ifdef ED_DBGP
+                               printk("status 0x80 return dirct != 0\n");
+#endif                         
+                               goto handled;
                        }
                        outb(0x08, tmport);
                        outb(0x09, tmpcip);
-                       dev->in_int = 0;
-                       goto out;
+                       dev->in_int[c] = 0;
+#ifdef ED_DBGP
+                       printk("status 0x80 return dirct = 0\n");
+#endif                 
+                       goto handled;
                }
 
                /*
-                *      Current scsi request on this target
+                *      Current scsi request on this target
                 */
 
-               workrequ = dev->id[target_id].curr_req;
+               workreq = dev->id[c][target_id].curr_req;
 
                if (i == 0x42) {
-                       if ((dev->last_cmd & 0xf0) != 0x40) {
-                               dev->last_cmd = 0xff;
+                       if ((dev->last_cmd[c] & 0xf0) != 0x40)
+                       {
+                          dev->last_cmd[c] = 0xff;
                        }
                        errstus = 0x02;
-                       workrequ->result = errstus;
+                       workreq->result = errstus;
                        goto go_42;
                }
                if (i == 0x16) {
-                       if ((dev->last_cmd & 0xf0) != 0x40) {
-                               dev->last_cmd = 0xff;
+                       if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+                          dev->last_cmd[c] = 0xff;
                        }
                        errstus = 0;
                        tmport -= 0x08;
                        errstus = inb(tmport);
-                       workrequ->result = errstus;
+                       if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) {
+                          printk(KERN_WARNING "AEC67162 CRC ERROR !\n");
+                          errstus = 0x02;
+                       }
+                       workreq->result = errstus;
 go_42:
+                       if (dev->dev_id == ATP885_DEVID) {              
+                               j = inb(dev->baseport + 0x29) | 0x01;
+                               outb(j, dev->baseport + 0x29);
+                       }
                        /*
-                        *      Complete the command
+                        *      Complete the command
                         */
-                        
-                       if (workrequ->use_sg) {
+                       if (workreq->use_sg) {
                                pci_unmap_sg(dev->pdev,
-                                       (struct scatterlist *)workrequ->buffer,
-                                       workrequ->use_sg,
-                                       workrequ->sc_data_direction);
-                       } else if (workrequ->request_bufflen &&
-                                       workrequ->sc_data_direction != DMA_NONE) {
+                                       (struct scatterlist *)workreq->buffer,
+                                       workreq->use_sg,
+                                       workreq->sc_data_direction);
+                       } else if (workreq->request_bufflen &&
+                                       workreq->sc_data_direction != DMA_NONE) {
                                pci_unmap_single(dev->pdev,
-                                       workrequ->SCp.dma_handle,
-                                       workrequ->request_bufflen,
-                                       workrequ->sc_data_direction);
-                       }
+                                       workreq->SCp.dma_handle,
+                                       workreq->request_bufflen,
+                                       workreq->sc_data_direction);
+                       }                       
                        spin_lock_irqsave(dev->host->host_lock, flags);
-                       (*workrequ->scsi_done) (workrequ);
-
+                       (*workreq->scsi_done) (workreq);
+#ifdef ED_DBGP
+                          printk("workreq->scsi_done\n");
+#endif 
                        /*
-                        *      Clear it off the queue
+                        *      Clear it off the queue
                         */
-                       dev->id[target_id].curr_req = NULL;
-                       dev->working--;
+                       dev->id[c][target_id].curr_req = NULL;
+                       dev->working[c]--;
                        spin_unlock_irqrestore(dev->host->host_lock, flags);
                        /*
                         *      Take it back wide
                         */
-                       if (dev->wide_idu != 0) {
-                               tmport = workportu + 0x1b;
+                       if (dev->wide_id[c] != 0) {
+                               tmport = workport + 0x1b;
                                outb(0x01, tmport);
                                while ((inb(tmport) & 0x01) != 0x01) {
                                        outb(0x01, tmport);
-                               }
-                       }
+                               }       
+                       } 
                        /*
-                        *      If there is stuff to send and nothing going then send it
+                        *      If there is stuff to send and nothing going then send it
                         */
                        spin_lock_irqsave(dev->host->host_lock, flags);
-                       if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) && (dev->in_snd == 0)) {
-                               send_s870(host);
+                       if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) &&
+                           (dev->in_snd[c] == 0)) {
+#ifdef ED_DBGP
+                          printk("Call sent_s870(scsi_done)\n");
+#endif                            
+                          send_s870(dev,c);
                        }
                        spin_unlock_irqrestore(dev->host->host_lock, flags);
-                       dev->in_int = 0;
-                       goto out;
+                       dev->in_int[c] = 0;
+                       goto handled;
                }
-               if ((dev->last_cmd & 0xf0) != 0x40) {
-                       dev->last_cmd = 0xff;
+               if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+                  dev->last_cmd[c] = 0xff;
                }
                if (i == 0x4f) {
                        i = 0x89;
                }
                i &= 0x0f;
                if (i == 0x09) {
-                       tmpcip = tmpcip + 4;
-                       outl(dev->id[target_id].prdaddru, tmpcip);
+                       tmpcip += 4;
+                       outl(dev->id[c][target_id].prdaddr, tmpcip);
                        tmpcip = tmpcip - 2;
                        outb(0x06, tmpcip);
                        outb(0x00, tmpcip);
                        tmpcip = tmpcip - 2;
-                       tmport = workportu + 0x10;
+                       tmport = workport + 0x10;
                        outb(0x41, tmport);
-                       dev->id[target_id].dirctu = 0x00;
-                       tmport += 0x08;
+                       if (dev->dev_id == ATP885_DEVID) {
+                               tmport += 2;
+                               k = dev->id[c][target_id].last_len;
+                               outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
+                               outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
+                               outb((unsigned char) (((unsigned char *) (&k))[0]), tmport);
+                               dev->id[c][target_id].dirct = 0x00;
+                               tmport += 0x04;
+                       } else {
+                               dev->id[c][target_id].dirct = 0x00;
+                               tmport += 0x08;                         
+                       }
                        outb(0x08, tmport);
                        outb(0x09, tmpcip);
-                       dev->in_int = 0;
-                       goto out;
+                       dev->in_int[c] = 0;
+                       goto handled;
                }
                if (i == 0x08) {
-                       tmpcip = tmpcip + 4;
-                       outl(dev->id[target_id].prdaddru, tmpcip);
+                       tmpcip += 4;
+                       outl(dev->id[c][target_id].prdaddr, tmpcip);
                        tmpcip = tmpcip - 2;
                        outb(0x06, tmpcip);
                        outb(0x00, tmpcip);
                        tmpcip = tmpcip - 2;
-                       tmport = workportu + 0x10;
+                       tmport = workport + 0x10;
                        outb(0x41, tmport);
-                       tmport += 0x05;
+                       if (dev->dev_id == ATP885_DEVID) {              
+                               tmport += 2;
+                               k = dev->id[c][target_id].last_len;
+                               outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
+                               outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
+                               outb((unsigned char) (((unsigned char *) (&k))[0]), tmport++);
+                       } else {
+                               tmport += 5;
+                       }
                        outb((unsigned char) (inb(tmport) | 0x20), tmport);
-                       dev->id[target_id].dirctu = 0x20;
+                       dev->id[c][target_id].dirct = 0x20;
                        tmport += 0x03;
                        outb(0x08, tmport);
                        outb(0x01, tmpcip);
-                       dev->in_int = 0;
-                       goto out;
+                       dev->in_int[c] = 0;
+                       goto handled;
                }
                tmport -= 0x07;
                if (i == 0x0a) {
@@ -434,25 +584,29 @@ go_42:
                } else {
                        outb(0x46, tmport);
                }
-               dev->id[target_id].dirctu = 0x00;
+               dev->id[c][target_id].dirct = 0x00;
                tmport += 0x02;
                outb(0x00, tmport++);
                outb(0x00, tmport++);
                outb(0x00, tmport++);
                tmport += 0x03;
                outb(0x08, tmport);
-               dev->in_int = 0;
-               goto out;
+               dev->in_int[c] = 0;
+               goto handled;
        } else {
-//              tmport = workportu + 0x17;
-//              inb(tmport);
-//              dev->working = 0;
-               dev->in_int = 0;
+//             tmport = workport + 0x17;
+//             inb(tmport);
+//             dev->working[c] = 0;
+               dev->in_int[c] = 0;
+               goto handled;
        }
-out:
+       
+handled:
+#ifdef ED_DBGP
+       printk("atp870u_intr_handle exit\n");
+#endif                 
        return IRQ_HANDLED;
 }
-
 /**
  *     atp870u_queuecommand    -       Queue SCSI command
  *     @req_p: request block
@@ -460,24 +614,31 @@ out:
  *
  *     Queue a command to the ATP queue. Called with the host lock held.
  */
-static int atp870u_queuecommand(struct scsi_cmnd *req_p,
-               void (*done) (struct scsi_cmnd *))
+static int atp870u_queuecommand(struct scsi_cmnd * req_p, 
+                        void (*done) (struct scsi_cmnd *))
 {
-       unsigned short int m;
-       unsigned int tmport;
-       struct Scsi_Host *host;
+       unsigned char c;
+       unsigned int tmport,m;  
        struct atp_unit *dev;
+       struct Scsi_Host *host;
 
-       if (req_p->device->channel != 0) {
+       c = req_p->device->channel;     
+       req_p->sense_buffer[0]=0;
+       req_p->resid = 0;
+       if (req_p->device->channel > 1) {
                req_p->result = 0x00040000;
                done(req_p);
+#ifdef ED_DBGP         
+               printk("atp870u_queuecommand : req_p->device->channel > 1\n");  
+#endif                 
                return 0;
-       };
+       }
 
        host = req_p->device->host;
        dev = (struct atp_unit *)&host->hostdata;
-       
+               
+
+               
        m = 1;
        m = m << req_p->device->id;
 
@@ -485,44 +646,60 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p,
         *      Fake a timeout for missing targets
         */
 
-       if ((m & dev->active_idu) == 0) {
+       if ((m & dev->active_id[c]) == 0) {
                req_p->result = 0x00040000;
                done(req_p);
                return 0;
        }
+
        if (done) {
                req_p->scsi_done = done;
        } else {
-               printk(KERN_WARNING "atp870u_queuecommand: done can't be NULL\n");
+#ifdef ED_DBGP         
+               printk( "atp870u_queuecommand: done can't be NULL\n");
+#endif         
                req_p->result = 0;
                done(req_p);
                return 0;
        }
+       
        /*
-        *      Count new command
+        *      Count new command
         */
-
-       dev->quendu++;
-       if (dev->quendu >= qcnt) {
-               dev->quendu = 0;
+       dev->quend[c]++;
+       if (dev->quend[c] >= qcnt) {
+               dev->quend[c] = 0;
        }
+       
        /*
-        *      Check queue state
+        *      Check queue state
         */
-       if (dev->quhdu == dev->quendu) {
-               if (dev->quendu == 0) {
-                       dev->quendu = qcnt;
-               }
-               dev->quendu--;
+       if (dev->quhd[c] == dev->quend[c]) {
+               if (dev->quend[c] == 0) {
+                       dev->quend[c] = qcnt;
+               }
+#ifdef ED_DBGP         
+               printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
+#endif         
+               dev->quend[c]--;
                req_p->result = 0x00020000;
-               done(req_p);
+               done(req_p);    
                return 0;
        }
-       dev->querequ[dev->quendu] = req_p;
-       tmport = dev->ioport + 0x1c;
-       if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) {
-               send_s870(host);
-       }
+       dev->quereq[c][dev->quend[c]] = req_p;
+       tmport = dev->ioport[c] + 0x1c;
+#ifdef ED_DBGP 
+       printk("dev->ioport[c] = %x inb(tmport) = %x dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",dev->ioport[c],inb(tmport),c,dev->in_int[c],c,dev->in_snd[c]);
+#endif
+       if ((inb(tmport) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) {
+#ifdef ED_DBGP
+               printk("Call sent_s870(atp870u_queuecommand)\n");
+#endif         
+               send_s870(dev,c);
+       }
+#ifdef ED_DBGP 
+       printk("atp870u_queuecommand : exit\n");
+#endif 
        return 0;
 }
 
@@ -535,194 +712,242 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p,
  *
  *     Caller holds the host lock.
  */
-static void send_s870(struct Scsi_Host *host)
+static void send_s870(struct atp_unit *dev,unsigned char c)
 {
        unsigned int tmport;
-       struct scsi_cmnd *workrequ;
-       unsigned int i;
-       unsigned char j, target_id;
+       struct scsi_cmnd *workreq;
+       unsigned int i;//,k;
+       unsigned char  j, target_id;
        unsigned char *prd;
        unsigned short int tmpcip, w;
-       unsigned long l;
-       dma_addr_t bttl;
-       unsigned int workportu;
+       unsigned long l, bttl = 0;
+       unsigned int workport;
        struct scatterlist *sgpnt;
-       struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
-       int sg_count;
+       unsigned long  sg_count;
 
-       if (dev->in_snd != 0) {
-               return;
-       }
-       dev->in_snd = 1;
-       if ((dev->last_cmd != 0xff) && ((dev->last_cmd & 0x40) != 0)) {
-               dev->last_cmd &= 0x0f;
-               workrequ = dev->id[dev->last_cmd].curr_req;
-               if (workrequ != NULL) { /* check NULL pointer */
-                       goto cmd_subp;
-               }
-               dev->last_cmd = 0xff;
-               if (dev->quhdu == dev->quendu) {
-                       dev->in_snd = 0;
-                       return;
-               }
-       }
-       if ((dev->last_cmd != 0xff) && (dev->working != 0)) {
-               dev->in_snd = 0;
+       if (dev->in_snd[c] != 0) {
+#ifdef ED_DBGP         
+               printk("cmnd in_snd\n");
+#endif
                return;
        }
-       dev->working++;
-       j = dev->quhdu;
-       dev->quhdu++;
-       if (dev->quhdu >= qcnt) {
-               dev->quhdu = 0;
-       }
-       workrequ = dev->querequ[dev->quhdu];
-       if (dev->id[workrequ->device->id].curr_req == 0) {
-               dev->id[workrequ->device->id].curr_req = workrequ;
-               dev->last_cmd = workrequ->device->id;
+#ifdef ED_DBGP
+       printk("Sent_s870 enter\n");
+#endif
+       dev->in_snd[c] = 1;
+       if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
+               dev->last_cmd[c] &= 0x0f;
+               workreq = dev->id[c][dev->last_cmd[c]].curr_req;
+               if (workreq != NULL) {  /* check NULL pointer */
+                  goto cmd_subp;
+               }
+               dev->last_cmd[c] = 0xff;        
+               if (dev->quhd[c] == dev->quend[c]) {
+                       dev->in_snd[c] = 0;
+                       return ;
+               }
+       }
+       if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
+               dev->in_snd[c] = 0;
+               return ;
+       }
+       dev->working[c]++;
+       j = dev->quhd[c];
+       dev->quhd[c]++;
+       if (dev->quhd[c] >= qcnt) {
+               dev->quhd[c] = 0;
+       }
+       workreq = dev->quereq[c][dev->quhd[c]];
+       if (dev->id[c][workreq->device->id].curr_req == 0) {    
+               dev->id[c][workreq->device->id].curr_req = workreq;
+               dev->last_cmd[c] = workreq->device->id;
                goto cmd_subp;
-       }
-       dev->quhdu = j;
-       dev->working--;
-       dev->in_snd = 0;
+       }       
+       dev->quhd[c] = j;
+       dev->working[c]--;
+       dev->in_snd[c] = 0;
        return;
 cmd_subp:
-       workportu = dev->ioport;
-       tmport = workportu + 0x1f;
+       workport = dev->ioport[c];
+       tmport = workport + 0x1f;
        if ((inb(tmport) & 0xb0) != 0) {
                goto abortsnd;
        }
-       tmport = workportu + 0x1c;
+       tmport = workport + 0x1c;
        if (inb(tmport) == 0) {
                goto oktosend;
        }
 abortsnd:
-       dev->last_cmd |= 0x40;
-       dev->in_snd = 0;
+#ifdef ED_DBGP
+       printk("Abort to Send\n");
+#endif
+       dev->last_cmd[c] |= 0x40;
+       dev->in_snd[c] = 0;
        return;
 oktosend:
-       memcpy(&dev->ata_cdbu[0], &workrequ->cmnd[0], workrequ->cmd_len);
-       if (dev->ata_cdbu[0] == READ_CAPACITY) {
-               if (workrequ->request_bufflen > 8) {
-                       workrequ->request_bufflen = 0x08;
+#ifdef ED_DBGP
+       printk("OK to Send\n");
+       printk("CDB");
+       for(i=0;i<workreq->cmd_len;i++) {
+               printk(" %x",workreq->cmnd[i]);
+       }
+       printk("\nChannel = %d ID = %d LUN = %d\n",c,workreq->device->id,workreq->device->lun);
+#endif 
+       if (dev->dev_id == ATP885_DEVID) {
+               j = inb(dev->baseport + 0x29) & 0xfe;
+               outb(j, dev->baseport + 0x29);
+               dev->r1f[c][workreq->device->id] = 0;
+       }
+       
+       if (workreq->cmnd[0] == READ_CAPACITY) {
+               if (workreq->request_bufflen > 8) {
+                       workreq->request_bufflen = 0x08;
                }
        }
-       if (dev->ata_cdbu[0] == 0x00) {
-               workrequ->request_bufflen = 0;
+       if (workreq->cmnd[0] == 0x00) {
+               workreq->request_bufflen = 0;
        }
 
-       tmport = workportu + 0x1b;
+       tmport = workport + 0x1b;
        j = 0;
-       target_id = workrequ->device->id;
+       target_id = workreq->device->id;
 
        /*
-        *      Wide ?
+        *      Wide ?
         */
        w = 1;
        w = w << target_id;
-       if ((w & dev->wide_idu) != 0) {
+       if ((w & dev->wide_id[c]) != 0) {
                j |= 0x01;
        }
        outb(j, tmport);
        while ((inb(tmport) & 0x01) != j) {
-               outb(j, tmport);
+               outb(j,tmport);
+#ifdef ED_DBGP
+               printk("send_s870 while loop 1\n");
+#endif
        }
-
        /*
-        *      Write the command
+        *      Write the command
         */
 
-       tmport = workportu;
-       outb(workrequ->cmd_len, tmport++);
+       tmport = workport;
+       outb(workreq->cmd_len, tmport++);
        outb(0x2c, tmport++);
-       outb(0xcf, tmport++);
-       for (i = 0; i < workrequ->cmd_len; i++) {
-               outb(dev->ata_cdbu[i], tmport++);
+       if (dev->dev_id == ATP885_DEVID) {
+               outb(0x7f, tmport++);
+       } else {
+               outb(0xcf, tmport++);   
+       }       
+       for (i = 0; i < workreq->cmd_len; i++) {
+               outb(workreq->cmnd[i], tmport++);
        }
-       tmport = workportu + 0x0f;
-       outb(workrequ->device->lun, tmport);
+       tmport = workport + 0x0f;
+       outb(workreq->device->lun, tmport);
        tmport += 0x02;
        /*
-        *      Write the target
+        *      Write the target
         */
-       outb(dev->id[target_id].devspu, tmport++);
-
+       outb(dev->id[c][target_id].devsp, tmport++);     
+#ifdef ED_DBGP 
+       printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp);
+#endif
        /*
-        *      Figure out the transfer size
+        *      Figure out the transfer size
         */
-       if (workrequ->use_sg) {
+       if (workreq->use_sg) {
+#ifdef ED_DBGP
+               printk("Using SGL\n");
+#endif         
                l = 0;
-               sgpnt = (struct scatterlist *) workrequ->request_buffer;
-               sg_count = pci_map_sg(dev->pdev, sgpnt, workrequ->use_sg,
-                               workrequ->sc_data_direction);
-               for (i = 0; i < workrequ->use_sg; i++) {
-                       if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER) {
+               
+               sgpnt = (struct scatterlist *) workreq->request_buffer;
+               sg_count = pci_map_sg(dev->pdev, sgpnt, workreq->use_sg,
+                               workreq->sc_data_direction);            
+               
+               for (i = 0; i < workreq->use_sg; i++) {
+                       if (sgpnt[i].length == 0 || workreq->use_sg > ATP870U_SCATTER) {
                                panic("Foooooooood fight!");
                        }
                        l += sgpnt[i].length;
                }
-       } else if(workrequ->request_bufflen && workrequ->sc_data_direction != PCI_DMA_NONE) {
-               workrequ->SCp.dma_handle = pci_map_single(dev->pdev,
-                               workrequ->request_buffer,
-                               workrequ->request_bufflen,
-                               workrequ->sc_data_direction);
-               l = workrequ->request_bufflen;
-       }
-       else l = 0;
+#ifdef ED_DBGP         
+               printk( "send_s870: workreq->use_sg %d, sg_count %d l %8ld\n", workreq->use_sg, sg_count, l);
+#endif
+       } else if(workreq->request_bufflen && workreq->sc_data_direction != PCI_DMA_NONE) {
+#ifdef ED_DBGP
+               printk("Not using SGL\n");
+#endif                                 
+               workreq->SCp.dma_handle = pci_map_single(dev->pdev, workreq->request_buffer,
+                               workreq->request_bufflen,
+                               workreq->sc_data_direction);            
+               l = workreq->request_bufflen;
+#ifdef ED_DBGP         
+               printk( "send_s870: workreq->use_sg %d, l %8ld\n", workreq->use_sg, l);
+#endif
+       } else l = 0;
        /*
-        *      Write transfer size
+        *      Write transfer size
         */
        outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
        outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
        outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
-       j = target_id;
-       dev->id[j].last_lenu = l;
-       dev->id[j].tran_lenu = 0;
+       j = target_id;  
+       dev->id[c][j].last_len = l;
+       dev->id[c][j].tran_len = 0;
+#ifdef ED_DBGP 
+       printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
+#endif 
        /*
-        *      Flip the wide bits
+        *      Flip the wide bits
         */
        if ((j & 0x08) != 0) {
                j = (j & 0x07) | 0x40;
        }
        /*
-        *      Check transfer direction
+        *      Check transfer direction
         */
-       if (workrequ->sc_data_direction == DMA_TO_DEVICE) {
+       if (workreq->sc_data_direction == DMA_TO_DEVICE) {
                outb((unsigned char) (j | 0x20), tmport++);
        } else {
                outb(j, tmport++);
        }
        outb((unsigned char) (inb(tmport) | 0x80), tmport);
        outb(0x80, tmport);
-       tmport = workportu + 0x1c;
-       dev->id[target_id].dirctu = 0;
+       tmport = workport + 0x1c;
+       dev->id[c][target_id].dirct = 0;
        if (l == 0) {
                if (inb(tmport) == 0) {
-                       tmport = workportu + 0x18;
+                       tmport = workport + 0x18;
+#ifdef ED_DBGP
+                       printk("change SCSI_CMD_REG 0x08\n");   
+#endif                         
                        outb(0x08, tmport);
                } else {
-                       dev->last_cmd |= 0x40;
+                       dev->last_cmd[c] |= 0x40;
                }
-               dev->in_snd = 0;
+               dev->in_snd[c] = 0;
                return;
        }
-       tmpcip = dev->pciport;
-       prd = dev->id[target_id].prd_tableu;
-       dev->id[target_id].prd_posu = prd;
+       tmpcip = dev->pciport[c];
+       prd = dev->id[c][target_id].prd_table;
+       dev->id[c][target_id].prd_pos = prd;
 
        /*
-        *      Now write the request list. Either as scatter/gather or as
-        *      a linear chain.
+        *      Now write the request list. Either as scatter/gather or as
+        *      a linear chain.
         */
 
-       if (workrequ->use_sg) {
-               sgpnt = (struct scatterlist *) workrequ->request_buffer;
+       if (workreq->use_sg) {
+               sgpnt = (struct scatterlist *) workreq->request_buffer;
                i = 0;
-               for (j = 0; j < workrequ->use_sg; j++) {
+               for (j = 0; j < workreq->use_sg; j++) {
                        bttl = sg_dma_address(&sgpnt[j]);
-                       l = sg_dma_len(&sgpnt[j]);
-                       while (l > 0x10000) {
+                       l=sg_dma_len(&sgpnt[j]);
+#ifdef ED_DBGP         
+               printk("1. bttl %x, l %x\n",bttl, l);
+#endif                 
+               while (l > 0x10000) {
                                (((u16 *) (prd))[i + 3]) = 0x0000;
                                (((u16 *) (prd))[i + 2]) = 0x0000;
                                (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
@@ -733,73 +958,105 @@ oktosend:
                        (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
                        (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
                        (((u16 *) (prd))[i + 3]) = 0;
-                       i += 0x04;
+                       i += 0x04;                      
                }
-               (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
+               (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000); 
+#ifdef ED_DBGP         
+               printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
+               printk("2. bttl %x, l %x\n",bttl, l);
+#endif                 
        } else {
                /*
-                *      For a linear request write a chain of blocks
-                */
-               bttl = workrequ->SCp.dma_handle;
-               l = workrequ->request_bufflen;
+                *      For a linear request write a chain of blocks
+                */        
+               bttl = workreq->SCp.dma_handle;
+               l = workreq->request_bufflen;
                i = 0;
+#ifdef ED_DBGP         
+               printk("3. bttl %x, l %x\n",bttl, l);
+#endif                 
                while (l > 0x10000) {
-                       (((u16 *) (prd))[i + 3]) = 0x0000;
-                       (((u16 *) (prd))[i + 2]) = 0x0000;
-                       (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
-                       l -= 0x10000;
-                       bttl += 0x10000;
-                       i += 0x04;
-               }
-               (((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000);
-               (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
-               (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
+                               (((u16 *) (prd))[i + 3]) = 0x0000;
+                               (((u16 *) (prd))[i + 2]) = 0x0000;
+                               (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
+                               l -= 0x10000;
+                               bttl += 0x10000;
+                               i += 0x04;
+                       }
+                       (((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000);
+                       (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
+                       (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);          
+#ifdef ED_DBGP         
+               printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
+               printk("4. bttl %x, l %x\n",bttl, l);
+#endif                 
+               
        }
-       tmpcip = tmpcip + 4;
-       dev->id[target_id].prdaddru = dev->id[target_id].prd_phys;
-       outl(dev->id[target_id].prd_phys, tmpcip);
+       tmpcip += 4;
+#ifdef ED_DBGP         
+       printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id);
+#endif 
+       outl(dev->id[c][target_id].prdaddr, tmpcip);
        tmpcip = tmpcip - 2;
        outb(0x06, tmpcip);
        outb(0x00, tmpcip);
-       tmpcip = tmpcip - 2;
-
-       if (dev->deviceid != 0x8081) {
-               tmport = workportu + 0x3a;
-               if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
-                       outb((inb(tmport) & 0xf3) | 0x08, tmport);
-               } else {
-                       outb(inb(tmport) & 0xf3, tmport);
-               }
-       } else {
-               tmport = workportu - 0x05;
-               if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
+       if (dev->dev_id == ATP885_DEVID) {
+               tmpcip--;
+               j=inb(tmpcip) & 0xf3;
+               if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) ||
+               (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+                       j |= 0x0c;
+               }
+               outb(j,tmpcip);
+               tmpcip--;               
+       } else if ((dev->dev_id == ATP880_DEVID1) ||
+                  (dev->dev_id == ATP880_DEVID2)) {
+               tmpcip =tmpcip -2;      
+               tmport = workport - 0x05;
+               if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
                        outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
                } else {
                        outb((unsigned char) (inb(tmport) & 0x3f), tmport);
-               }
-       }
-       tmport = workportu + 0x1c;
+               }               
+       } else {                
+               tmpcip =tmpcip -2;
+               tmport = workport + 0x3a;
+               if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+                       outb((inb(tmport) & 0xf3) | 0x08, tmport);
+               } else {
+                       outb(inb(tmport) & 0xf3, tmport);
+               }               
+       }       
+       tmport = workport + 0x1c;
 
-       if (workrequ->sc_data_direction == DMA_TO_DEVICE) {
-               dev->id[target_id].dirctu = 0x20;
+       if(workreq->sc_data_direction == DMA_TO_DEVICE) {
+               dev->id[c][target_id].dirct = 0x20;
                if (inb(tmport) == 0) {
-                       tmport = workportu + 0x18;
+                       tmport = workport + 0x18;
                        outb(0x08, tmport);
                        outb(0x01, tmpcip);
+#ifdef ED_DBGP         
+               printk( "start DMA(to target)\n");
+#endif                         
                } else {
-                       dev->last_cmd |= 0x40;
+                       dev->last_cmd[c] |= 0x40;
                }
-               dev->in_snd = 0;
+               dev->in_snd[c] = 0;
                return;
        }
-       if (inb(tmport) == 0) {
-               tmport = workportu + 0x18;
+       if (inb(tmport) == 0) {         
+               tmport = workport + 0x18;
                outb(0x08, tmport);
                outb(0x09, tmpcip);
+#ifdef ED_DBGP         
+               printk( "start DMA(to host)\n");
+#endif                 
        } else {
-               dev->last_cmd |= 0x40;
+               dev->last_cmd[c] |= 0x40;
        }
-       dev->in_snd = 0;
+       dev->in_snd[c] = 0;
+       return;
+
 }
 
 static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
@@ -808,7 +1065,7 @@ static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
        unsigned short int i, k;
        unsigned char j;
 
-       tmport = dev->ioport + 0x1c;
+       tmport = dev->ioport[0] + 0x1c;
        outw(*val, tmport);
 FUN_D7:
        for (i = 0; i < 10; i++) {      /* stable >= bus settle delay(400 ns)  */
@@ -863,24 +1120,24 @@ static void tscam(struct Scsi_Host *host)
        }
  */
 
-       tmport = dev->ioport + 1;
+       tmport = dev->ioport[0] + 1;
        outb(0x08, tmport++);
        outb(0x7f, tmport);
-       tmport = dev->ioport + 0x11;
+       tmport = dev->ioport[0] + 0x11;
        outb(0x20, tmport);
 
        if ((dev->scam_on & 0x40) == 0) {
                return;
        }
        m = 1;
-       m <<= dev->host_idu;
+       m <<= dev->host_id[0];
        j = 16;
-       if (dev->chip_veru < 4) {
+       if (dev->chip_ver < 4) {
                m |= 0xff00;
                j = 8;
        }
        assignid_map = m;
-       tmport = dev->ioport + 0x02;
+       tmport = dev->ioport[0] + 0x02;
        outb(0x02, tmport++);   /* 2*2=4ms,3EH 2/32*3E=3.9ms */
        outb(0, tmport++);
        outb(0, tmport++);
@@ -895,7 +1152,7 @@ static void tscam(struct Scsi_Host *host)
                if ((m & assignid_map) != 0) {
                        continue;
                }
-               tmport = dev->ioport + 0x0f;
+               tmport = dev->ioport[0] + 0x0f;
                outb(0, tmport++);
                tmport += 0x02;
                outb(0, tmport++);
@@ -907,40 +1164,41 @@ static void tscam(struct Scsi_Host *host)
                        k = i;
                }
                outb(k, tmport++);
-               tmport = dev->ioport + 0x1b;
-               if (dev->chip_veru == 4) {
+               tmport = dev->ioport[0] + 0x1b;
+               if (dev->chip_ver == 4) {
                        outb(0x01, tmport);
                } else {
                        outb(0x00, tmport);
                }
 wait_rdyok:
-               tmport = dev->ioport + 0x18;
+               tmport = dev->ioport[0] + 0x18;
                outb(0x09, tmport);
                tmport += 0x07;
 
-               while ((inb(tmport) & 0x80) == 0x00);
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
                tmport -= 0x08;
                k = inb(tmport);
                if (k != 0x16) {
                        if ((k == 0x85) || (k == 0x42)) {
                                continue;
                        }
-                       tmport = dev->ioport + 0x10;
+                       tmport = dev->ioport[0] + 0x10;
                        outb(0x41, tmport);
                        goto wait_rdyok;
                }
                assignid_map |= m;
 
        }
-       tmport = dev->ioport + 0x02;
+       tmport = dev->ioport[0] + 0x02;
        outb(0x7f, tmport);
-       tmport = dev->ioport + 0x1b;
+       tmport = dev->ioport[0] + 0x1b;
        outb(0x02, tmport);
 
        outb(0, 0x80);
 
        val = 0x0080;           /* bsy  */
-       tmport = dev->ioport + 0x1c;
+       tmport = dev->ioport[0] + 0x1c;
        outw(val, tmport);
        val |= 0x0040;          /* sel  */
        outw(val, tmport);
@@ -984,12 +1242,13 @@ TCM_SYNC:
        if ((inb(tmport) & 0x80) == 0x00) {     /* bsy ? */
                outw(0, tmport--);
                outb(0, tmport);
-               tmport = dev->ioport + 0x15;
+               tmport = dev->ioport[0] + 0x15;
                outb(0, tmport);
                tmport += 0x03;
                outb(0x09, tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0);
+               while ((inb(tmport) & 0x80) == 0)
+                       cpu_relax();
                tmport -= 0x08;
                inb(tmport);
                return;
@@ -1085,7 +1344,7 @@ G2Q_QUIN:         /* k=binID#,       */
 
 }
 
-static void is870(struct Scsi_Host *host, unsigned int wkport)
+static void is870(struct atp_unit *dev, unsigned int wkport)
 {
        unsigned int tmport;
        unsigned char i, j, k, rmb, n;
@@ -1097,26 +1356,25 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
        static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
        static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
        static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
-       struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
-
+       
        tmport = wkport + 0x3a;
        outb((unsigned char) (inb(tmport) | 0x10), tmport);
 
        for (i = 0; i < 16; i++) {
-               if ((dev->chip_veru != 4) && (i > 7)) {
+               if ((dev->chip_ver != 4) && (i > 7)) {
                        break;
                }
                m = 1;
                m = m << i;
-               if ((m & dev->active_idu) != 0) {
+               if ((m & dev->active_id[0]) != 0) {
                        continue;
                }
-               if (i == dev->host_idu) {
-                       printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_idu);
+               if (i == dev->host_id[0]) {
+                       printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
                        continue;
                }
                tmport = wkport + 0x1b;
-               if (dev->chip_veru == 4) {
+               if (dev->chip_ver == 4) {
                        outb(0x01, tmport);
                } else {
                        outb(0x00, tmport);
@@ -1133,7 +1391,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
                tmport += 0x06;
                outb(0, tmport);
                tmport += 0x02;
-               outb(dev->id[i].devspu, tmport++);
+               outb(dev->id[0][i].devsp, tmport++);
                outb(0, tmport++);
                outb(satn[6], tmport++);
                outb(satn[7], tmport++);
@@ -1146,13 +1404,17 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
                outb(satn[8], tmport);
                tmport += 0x07;
 
-               while ((inb(tmport) & 0x80) == 0x00);
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+
                tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+               if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
                        continue;
-               }
-               while (inb(tmport) != 0x8e);
-               dev->active_idu |= m;
+
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+
+               dev->active_id[0] |= m;
 
                tmport = wkport + 0x10;
                outb(0x30, tmport);
@@ -1163,7 +1425,8 @@ phase_cmd:
                tmport = wkport + 0x18;
                outb(0x08, tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
                tmport -= 0x08;
                j = inb(tmport);
                if (j != 0x16) {
@@ -1182,23 +1445,28 @@ sel_ok:
                tmport += 0x07;
                outb(0, tmport);
                tmport += 0x02;
-               outb(dev->id[i].devspu, tmport++);
+               outb(dev->id[0][i].devsp, tmport++);
                outb(0, tmport++);
                outb(inqd[6], tmport++);
                outb(inqd[7], tmport++);
                tmport += 0x03;
                outb(inqd[8], tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+               if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
                        continue;
-               }
-               while (inb(tmport) != 0x8e);
+
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+                       
                tmport = wkport + 0x1b;
-               if (dev->chip_veru == 4) {
+               if (dev->chip_ver == 4)
                        outb(0x00, tmport);
-               }
+
                tmport = wkport + 0x18;
                outb(0x08, tmport);
                tmport += 0x07;
@@ -1228,7 +1496,10 @@ rd_inq_data:
                tmport += 0x03;
                outb(0x08, tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                tmport -= 0x08;
                if (inb(tmport) != 0x16) {
                        goto sel_ok;
@@ -1236,16 +1507,16 @@ rd_inq_data:
 inq_ok:
                mbuf[36] = 0;
                printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
-               dev->id[i].devtypeu = mbuf[0];
+               dev->id[0][i].devtype = mbuf[0];
                rmb = mbuf[1];
                n = mbuf[7];
-               if (dev->chip_veru != 4) {
+               if (dev->chip_ver != 4) {
                        goto not_wide;
                }
                if ((mbuf[7] & 0x60) == 0) {
                        goto not_wide;
                }
-               if ((dev->global_map & 0x20) == 0) {
+               if ((dev->global_map[0] & 0x20) == 0) {
                        goto not_wide;
                }
                tmport = wkport + 0x1b;
@@ -1260,7 +1531,7 @@ inq_ok:
                tmport += 0x06;
                outb(0, tmport);
                tmport += 0x02;
-               outb(dev->id[i].devspu, tmport++);
+               outb(dev->id[0][i].devsp, tmport++);
                outb(0, tmport++);
                outb(satn[6], tmport++);
                outb(satn[7], tmport++);
@@ -1268,12 +1539,16 @@ inq_ok:
                outb(satn[8], tmport);
                tmport += 0x07;
 
-               while ((inb(tmport) & 0x80) == 0x00);
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+               if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
                        continue;
-               }
-               while (inb(tmport) != 0x8e);
+
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+                       
 try_wide:
                j = 0;
                tmport = wkport + 0x14;
@@ -1290,7 +1565,10 @@ try_wide:
                        }
                }
                tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
+               
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                j = inb(tmport) & 0x0f;
                if (j == 0x0f) {
                        goto widep_in;
@@ -1363,7 +1641,10 @@ widep_cmd:
                tmport += 0x04;
                outb(0x08, tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
+               
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+
                tmport -= 0x08;
                j = inb(tmport);
                if (j != 0x16) {
@@ -1386,16 +1667,16 @@ widep_cmd:
                }
                m = 1;
                m = m << i;
-               dev->wide_idu |= m;
+               dev->wide_id[0] |= m;
 not_wide:
-               if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) {
+               if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
                        goto set_sync;
                }
                continue;
 set_sync:
                tmport = wkport + 0x1b;
                j = 0;
-               if ((m & dev->wide_idu) != 0) {
+               if ((m & dev->wide_id[0]) != 0) {
                        j |= 0x01;
                }
                outb(j, tmport);
@@ -1409,7 +1690,7 @@ set_sync:
                tmport += 0x06;
                outb(0, tmport);
                tmport += 0x02;
-               outb(dev->id[i].devspu, tmport++);
+               outb(dev->id[0][i].devsp, tmport++);
                outb(0, tmport++);
                outb(satn[6], tmport++);
                outb(satn[7], tmport++);
@@ -1417,12 +1698,16 @@ set_sync:
                outb(satn[8], tmport);
                tmport += 0x07;
 
-               while ((inb(tmport) & 0x80) == 0x00);
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+               if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
                        continue;
-               }
-               while (inb(tmport) != 0x8e);
+
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+                       
 try_sync:
                j = 0;
                tmport = wkport + 0x14;
@@ -1434,10 +1719,10 @@ try_sync:
                while ((inb(tmport) & 0x80) == 0) {
                        if ((inb(tmport) & 0x01) != 0) {
                                tmport -= 0x06;
-                               if ((m & dev->wide_idu) != 0) {
+                               if ((m & dev->wide_id[0]) != 0) {
                                        outb(synw[j++], tmport);
                                } else {
-                                       if ((m & dev->ultra_map) != 0) {
+                                       if ((m & dev->ultra_map[0]) != 0) {
                                                outb(synu[j++], tmport);
                                        } else {
                                                outb(synn[j++], tmport);
@@ -1447,7 +1732,10 @@ try_sync:
                        }
                }
                tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
+               
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                j = inb(tmport) & 0x0f;
                if (j == 0x0f) {
                        goto phase_ins;
@@ -1505,7 +1793,10 @@ phase_ins1:
                        goto phase_ins1;
                }
                tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                j = inb(tmport);
                if (j == 0x85) {
                        goto tar_dcons;
@@ -1530,7 +1821,10 @@ tar_dcons:
                tmport += 0x04;
                outb(0x08, tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
+               
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                tmport -= 0x08;
                j = inb(tmport);
                if (j != 0x16) {
@@ -1551,7 +1845,7 @@ tar_dcons:
                if (mbuf[4] > 0x0c) {
                        mbuf[4] = 0x0c;
                }
-               dev->id[i].devspu = mbuf[4];
+               dev->id[0][i].devsp = mbuf[4];
                if ((mbuf[3] < 0x0d) && (rmb == 0)) {
                        j = 0xa0;
                        goto set_syn_ok;
@@ -1570,13 +1864,13 @@ tar_dcons:
                }
                j = 0x60;
 set_syn_ok:
-               dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
+               dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
        }
        tmport = wkport + 0x3a;
        outb((unsigned char) (inb(tmport) & 0xef), tmport);
 }
 
-static void is880(struct Scsi_Host *host, unsigned int wkport)
+static void is880(struct atp_unit *dev, unsigned int wkport)
 {
        unsigned int tmport;
        unsigned char i, j, k, rmb, n, lvdmode;
@@ -1590,18 +1884,17 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
        unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
        static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
        static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
-       struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
 
        lvdmode = inb(wkport + 0x3f) & 0x40;
 
        for (i = 0; i < 16; i++) {
                m = 1;
                m = m << i;
-               if ((m & dev->active_idu) != 0) {
+               if ((m & dev->active_id[0]) != 0) {
                        continue;
                }
-               if (i == dev->host_idu) {
-                       printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_idu);
+               if (i == dev->host_id[0]) {
+                       printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
                        continue;
                }
                tmport = wkport + 0x5b;
@@ -1618,7 +1911,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
                tmport += 0x06;
                outb(0, tmport);
                tmport += 0x02;
-               outb(dev->id[i].devspu, tmport++);
+               outb(dev->id[0][i].devsp, tmport++);
                outb(0, tmport++);
                outb(satn[6], tmport++);
                outb(satn[7], tmport++);
@@ -1631,13 +1924,17 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
                outb(satn[8], tmport);
                tmport += 0x07;
 
-               while ((inb(tmport) & 0x80) == 0x00);
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+
                tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+               if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
                        continue;
-               }
-               while (inb(tmport) != 0x8e);
-               dev->active_idu |= m;
+
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+                       
+               dev->active_id[0] |= m;
 
                tmport = wkport + 0x50;
                outb(0x30, tmport);
@@ -1648,7 +1945,10 @@ phase_cmd:
                tmport = wkport + 0x58;
                outb(0x08, tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
+               
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+
                tmport -= 0x08;
                j = inb(tmport);
                if (j != 0x16) {
@@ -1667,19 +1967,24 @@ sel_ok:
                tmport += 0x07;
                outb(0, tmport);
                tmport += 0x02;
-               outb(dev->id[i].devspu, tmport++);
+               outb(dev->id[0][i].devsp, tmport++);
                outb(0, tmport++);
                outb(inqd[6], tmport++);
                outb(inqd[7], tmport++);
                tmport += 0x03;
                outb(inqd[8], tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
+               
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+               if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
                        continue;
-               }
-               while (inb(tmport) != 0x8e);
+
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+                       
                tmport = wkport + 0x5b;
                outb(0x00, tmport);
                tmport = wkport + 0x58;
@@ -1711,27 +2016,29 @@ rd_inq_data:
                tmport += 0x03;
                outb(0x08, tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                tmport -= 0x08;
-               if (inb(tmport) != 0x16) {
+               if (inb(tmport) != 0x16)
                        goto sel_ok;
-               }
+
 inq_ok:
                mbuf[36] = 0;
                printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
-               dev->id[i].devtypeu = mbuf[0];
+               dev->id[0][i].devtype = mbuf[0];
                rmb = mbuf[1];
                n = mbuf[7];
                if ((mbuf[7] & 0x60) == 0) {
                        goto not_wide;
                }
-               if ((i < 8) && ((dev->global_map & 0x20) == 0)) {
+               if ((i < 8) && ((dev->global_map[0] & 0x20) == 0)) {
                        goto not_wide;
                }
                if (lvdmode == 0) {
                        goto chg_wide;
                }
-               if (dev->sp[i] != 0x04) // force u2
+               if (dev->sp[0][i] != 0x04)      // force u2
                {
                        goto chg_wide;
                }
@@ -1748,7 +2055,7 @@ inq_ok:
                tmport += 0x06;
                outb(0, tmport);
                tmport += 0x02;
-               outb(dev->id[i].devspu, tmport++);
+               outb(dev->id[0][i].devsp, tmport++);
                outb(0, tmport++);
                outb(satn[6], tmport++);
                outb(satn[7], tmport++);
@@ -1756,12 +2063,17 @@ inq_ok:
                outb(satn[8], tmport);
                tmport += 0x07;
 
-               while ((inb(tmport) & 0x80) == 0x00);
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+
                tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+
+               if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
                        continue;
-               }
-               while (inb(tmport) != 0x8e);
+
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+
 try_u3:
                j = 0;
                tmport = wkport + 0x54;
@@ -1778,7 +2090,10 @@ try_u3:
                        }
                }
                tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                j = inb(tmport) & 0x0f;
                if (j == 0x0f) {
                        goto u3p_in;
@@ -1851,7 +2166,10 @@ u3p_cmd:
                tmport += 0x04;
                outb(0x08, tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
+               
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                tmport -= 0x08;
                j = inb(tmport);
                if (j != 0x16) {
@@ -1872,8 +2190,8 @@ u3p_cmd:
                if (mbuf[3] == 0x09) {
                        m = 1;
                        m = m << i;
-                       dev->wide_idu |= m;
-                       dev->id[i].devspu = 0xce;
+                       dev->wide_id[0] |= m;
+                       dev->id[0][i].devsp = 0xce;
                        continue;
                }
 chg_wide:
@@ -1889,7 +2207,7 @@ chg_wide:
                tmport += 0x06;
                outb(0, tmport);
                tmport += 0x02;
-               outb(dev->id[i].devspu, tmport++);
+               outb(dev->id[0][i].devsp, tmport++);
                outb(0, tmport++);
                outb(satn[6], tmport++);
                outb(satn[7], tmport++);
@@ -1897,12 +2215,16 @@ chg_wide:
                outb(satn[8], tmport);
                tmport += 0x07;
 
-               while ((inb(tmport) & 0x80) == 0x00);
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+               if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
                        continue;
-               }
-               while (inb(tmport) != 0x8e);
+
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+                       
 try_wide:
                j = 0;
                tmport = wkport + 0x54;
@@ -1919,7 +2241,9 @@ try_wide:
                        }
                }
                tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+                       
                j = inb(tmport) & 0x0f;
                if (j == 0x0f) {
                        goto widep_in;
@@ -1992,7 +2316,10 @@ widep_cmd:
                tmport += 0x04;
                outb(0x08, tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+
                tmport -= 0x08;
                j = inb(tmport);
                if (j != 0x16) {
@@ -2015,29 +2342,29 @@ widep_cmd:
                }
                m = 1;
                m = m << i;
-               dev->wide_idu |= m;
+               dev->wide_id[0] |= m;
 not_wide:
-               if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) {
+               if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
                        m = 1;
                        m = m << i;
-                       if ((dev->async & m) != 0) {
+                       if ((dev->async[0] & m) != 0) {
                                goto set_sync;
                        }
                }
                continue;
 set_sync:
-               if (dev->sp[i] == 0x02) {
+               if (dev->sp[0][i] == 0x02) {
                        synu[4] = 0x0c;
                        synuw[4] = 0x0c;
                } else {
-                       if (dev->sp[i] >= 0x03) {
+                       if (dev->sp[0][i] >= 0x03) {
                                synu[4] = 0x0a;
                                synuw[4] = 0x0a;
                        }
                }
                tmport = wkport + 0x5b;
                j = 0;
-               if ((m & dev->wide_idu) != 0) {
+               if ((m & dev->wide_id[0]) != 0) {
                        j |= 0x01;
                }
                outb(j, tmport);
@@ -2051,7 +2378,7 @@ set_sync:
                tmport += 0x06;
                outb(0, tmport);
                tmport += 0x02;
-               outb(dev->id[i].devspu, tmport++);
+               outb(dev->id[0][i].devsp, tmport++);
                outb(0, tmport++);
                outb(satn[6], tmport++);
                outb(satn[7], tmport++);
@@ -2059,12 +2386,16 @@ set_sync:
                outb(satn[8], tmport);
                tmport += 0x07;
 
-               while ((inb(tmport) & 0x80) == 0x00);
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+
                tmport -= 0x08;
                if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
                        continue;
                }
-               while (inb(tmport) != 0x8e);
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+
 try_sync:
                j = 0;
                tmport = wkport + 0x54;
@@ -2076,14 +2407,14 @@ try_sync:
                while ((inb(tmport) & 0x80) == 0) {
                        if ((inb(tmport) & 0x01) != 0) {
                                tmport -= 0x06;
-                               if ((m & dev->wide_idu) != 0) {
-                                       if ((m & dev->ultra_map) != 0) {
+                               if ((m & dev->wide_id[0]) != 0) {
+                                       if ((m & dev->ultra_map[0]) != 0) {
                                                outb(synuw[j++], tmport);
                                        } else {
                                                outb(synw[j++], tmport);
                                        }
                                } else {
-                                       if ((m & dev->ultra_map) != 0) {
+                                       if ((m & dev->ultra_map[0]) != 0) {
                                                outb(synu[j++], tmport);
                                        } else {
                                                outb(synn[j++], tmport);
@@ -2093,7 +2424,10 @@ try_sync:
                        }
                }
                tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+
                j = inb(tmport) & 0x0f;
                if (j == 0x0f) {
                        goto phase_ins;
@@ -2151,7 +2485,10 @@ phase_ins1:
                        goto phase_ins1;
                }
                tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+
                j = inb(tmport);
                if (j == 0x85) {
                        goto tar_dcons;
@@ -2176,7 +2513,10 @@ tar_dcons:
                tmport += 0x04;
                outb(0x08, tmport);
                tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+
                tmport -= 0x08;
                j = inb(tmport);
                if (j != 0x16) {
@@ -2197,7 +2537,7 @@ tar_dcons:
                if (mbuf[4] > 0x0e) {
                        mbuf[4] = 0x0e;
                }
-               dev->id[i].devspu = mbuf[4];
+               dev->id[0][i].devsp = mbuf[4];
                if (mbuf[3] < 0x0c) {
                        j = 0xb0;
                        goto set_syn_ok;
@@ -2220,249 +2560,179 @@ tar_dcons:
                }
                j = 0x60;
 set_syn_ok:
-               dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
+               dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
        }
 }
 
 static void atp870u_free_tables(struct Scsi_Host *host)
 {
        struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
-       int k;
-
-       for (k = 0; k < 16; k++) {
-               if (!atp_dev->id[k].prd_tableu)
-                       continue;
-               pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[k].prd_tableu,
-                                       atp_dev->id[k].prd_phys);
-               atp_dev->id[k].prd_tableu = NULL;
+       int j, k;
+       for (j=0; j < 2; j++) {
+               for (k = 0; k < 16; k++) {
+                       if (!atp_dev->id[j][k].prd_table)
+                               continue;
+                       pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prdaddr);
+                       atp_dev->id[j][k].prd_table = NULL;
+               }
        }
 }
 
 static int atp870u_init_tables(struct Scsi_Host *host)
 {
-       struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
-       int k, i;
-
-       for (i = k = 0; k < 16; k++) {
-               dev->id[k].prd_tableu = pci_alloc_consistent(dev->pdev, 1024, &dev->id[k].prd_phys);
-               if (!dev->id[k].prd_tableu) {
-                       atp870u_free_tables(host);
-                       return -ENOMEM;
-               }
-               dev->id[k].devspu = 0x20;
-               dev->id[k].devtypeu = 0;
-               dev->id[k].curr_req = NULL;
-       }
-       dev->active_idu = 0;
-       dev->wide_idu = 0;
-       dev->host_idu = 0x07;
-       dev->quhdu = 0;
-       dev->quendu = 0;
-       dev->chip_veru = 0;
-       dev->last_cmd = 0xff;
-       dev->in_snd = 0;
-       dev->in_int = 0;
-       for (k = 0; k < qcnt; k++) {
-               dev->querequ[k] = NULL;
-       }
-       for (k = 0; k < 16; k++) {
-               dev->id[k].curr_req = NULL;
-               dev->sp[k] = 0x04;
+       struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
+       int c,k;
+       for(c=0;c < 2;c++) {
+               for(k=0;k<16;k++) {
+                               atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prdaddr));
+                               if (!atp_dev->id[c][k].prd_table) {
+                                       printk("atp870u_init_tables fail\n");
+                               atp870u_free_tables(host);
+                               return -ENOMEM;
+                       }
+                       atp_dev->id[c][k].devsp=0x20;
+                       atp_dev->id[c][k].devtype = 0x7f;
+                       atp_dev->id[c][k].curr_req = NULL;                         
+               }
+                               
+               atp_dev->active_id[c] = 0;
+               atp_dev->wide_id[c] = 0;
+               atp_dev->host_id[c] = 0x07;
+               atp_dev->quhd[c] = 0;
+               atp_dev->quend[c] = 0;
+               atp_dev->last_cmd[c] = 0xff;
+               atp_dev->in_snd[c] = 0;
+               atp_dev->in_int[c] = 0;
+               
+               for (k = 0; k < qcnt; k++) {
+                         atp_dev->quereq[c][k] = NULL;
+               }                          
+               for (k = 0; k < 16; k++) {
+                          atp_dev->id[c][k].curr_req = NULL;
+                          atp_dev->sp[c][k] = 0x04;
+               }                  
        }
        return 0;
 }
 
 /* return non-zero on detection */
-static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-       unsigned char k, m;
+       unsigned char k, m, c;
        unsigned long flags;
-       unsigned int base_io, error, tmport;
+       unsigned int base_io, tmport, error,n;
        unsigned char host_id;
-       unsigned short n;
-       struct Scsi_Host *shpnt;
+       struct Scsi_Host *shpnt = NULL;
        struct atp_unit atp_dev, *p;
-       static int count;
-
-       if (pci_enable_device(dev))
+       unsigned char setupdata[2][16];
+       int count = 0;
+       
+       if (pci_enable_device(pdev))
                return -EIO;
 
-       if (pci_set_dma_mask(dev, 0xFFFFFFFFUL)) {
-               printk(KERN_ERR "atp870u: 32bit DMA mask required but not available.\n");
-               return -EIO;
-       }
-       
+        if (!pci_set_dma_mask(pdev, 0xFFFFFFFFUL)) {
+                printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
+        } else {
+                printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
+                return -EIO;
+        }
+
        memset(&atp_dev, 0, sizeof atp_dev);
        /*
         * It's probably easier to weed out some revisions like
         * this than via the PCI device table
         */
        if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
-               error = pci_read_config_byte(dev, PCI_CLASS_REVISION, &atp_dev.chip_veru);
-               if (atp_dev.chip_veru < 2)
+               error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
+               if (atp_dev.chip_ver < 2)
                        return -EIO;
        }
 
        switch (ent->device) {
-       case 0x8081:
        case PCI_DEVICE_ID_ARTOP_AEC7612UW:
        case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
-               atp_dev.chip_veru = 0x04;
+       case ATP880_DEVID1:     
+       case ATP880_DEVID2:     
+       case ATP885_DEVID:      
+               atp_dev.chip_ver = 0x04;
        default:
                break;
        }
+       base_io = pci_resource_start(pdev, 0);
+       base_io &= 0xfffffff8;
+       
+       if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
+               error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
+               pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
 
-       base_io = pci_resource_start(dev, 0);
-
-       if (ent->device != 0x8081) {
-               error = pci_read_config_byte(dev, 0x49, &host_id);
-               base_io &= 0xfffffff8;
+               host_id = inb(base_io + 0x39);
+               host_id >>= 0x04;
 
-               printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d "
-                       "IO:%x, IRQ:%d.\n", count, base_io, dev->irq);
+               printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
+                       "    IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
+               atp_dev.ioport[0] = base_io + 0x40;
+               atp_dev.pciport[0] = base_io + 0x28;
+               atp_dev.dev_id = ent->device;
+               atp_dev.host_id[0] = host_id;
 
-               atp_dev.unit = count;   
-               atp_dev.ioport = base_io;
-               atp_dev.pciport = base_io + 0x20;
-               atp_dev.deviceid = ent->device;
-               host_id &= 0x07;
-               atp_dev.host_idu = host_id;
                tmport = base_io + 0x22;
                atp_dev.scam_on = inb(tmport);
-               tmport += 0x0b;
-               atp_dev.global_map = inb(tmport++);
-               atp_dev.ultra_map = inw(tmport);
+               tmport += 0x13;
+               atp_dev.global_map[0] = inb(tmport);
+               tmport += 0x07;
+               atp_dev.ultra_map[0] = inw(tmport);
 
-               if (atp_dev.ultra_map == 0) {
-                       atp_dev.scam_on = 0x00;
-                       atp_dev.global_map = 0x20;
-                       atp_dev.ultra_map = 0xffff;
-               }
+               n = 0x3f09;
+next_fblk_880:
+               if (n >= 0x4000)
+                       goto flash_ok_880;
 
-               shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
-               if (!shpnt)
-                       return -ENOMEM;
+               m = 0;
+               outw(n, base_io + 0x34);
+               n += 0x0002;
+               if (inb(base_io + 0x30) == 0xff)
+                       goto flash_ok_880;
 
-               p = (struct atp_unit *)&shpnt->hostdata;
-               
-               atp_dev.host = shpnt;
-               atp_dev.pdev = dev;
-               pci_set_drvdata(dev, p);
-               memcpy(p, &atp_dev, sizeof atp_dev);
-               if (atp870u_init_tables(shpnt) < 0)
-                       goto unregister;
-
-               if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
-                       printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq);
-                       goto free_tables;
-               }
-
-               spin_lock_irqsave(shpnt->host_lock, flags);
-               if (atp_dev.chip_veru > 0x07) { /* check if atp876 chip then enable terminator */
-                       tmport = base_io + 0x3e;
-                       outb(0x00, tmport);
-               }
-               tmport = base_io + 0x3a;
-               k = (inb(tmport) & 0xf3) | 0x10;
-               outb(k, tmport);
-               outb((k & 0xdf), tmport);
-               mdelay(32);
-               outb(k, tmport);
-               mdelay(32);
-               tmport = base_io;
-               outb((host_id | 0x08), tmport);
-               tmport += 0x18;
-               outb(0, tmport);
-               tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0)
-                       mdelay(1);
-
-               tmport -= 0x08;
-               inb(tmport);
-               tmport = base_io + 1;
-               outb(8, tmport++);
-               outb(0x7f, tmport);
-               tmport = base_io + 0x11;
-               outb(0x20, tmport);
-
-               tscam(shpnt);
-               is870(shpnt, base_io);
-               tmport = base_io + 0x3a;
-               outb((inb(tmport) & 0xef), tmport);
-               tmport++;
-               outb((inb(tmport) | 0x20), tmport);
-       } else {
-               base_io &= 0xfffffff8;
-               host_id = inb(base_io + 0x39);
-               host_id >>= 0x04;
-
-               printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
-                       "    IO:%x, IRQ:%d.\n", count, base_io, dev->irq);
-               atp_dev.ioport = base_io + 0x40;
-               atp_dev.pciport = base_io + 0x28;
-               atp_dev.deviceid = ent->device;
-               atp_dev.host_idu = host_id;
-
-               tmport = base_io + 0x22;
-               atp_dev.scam_on = inb(tmport);
-               tmport += 0x13;
-               atp_dev.global_map = inb(tmport);
-               tmport += 0x07;
-               atp_dev.ultra_map = inw(tmport);
-
-               n = 0x3f09;
-next_fblk:
-               if (n >= 0x4000)
-                       goto flash_ok;
-
-               m = 0;
-               outw(n, base_io + 0x34);
-               n += 0x0002;
-               if (inb(base_io + 0x30) == 0xff)
-                       goto flash_ok;
-
-               atp_dev.sp[m++] = inb(base_io + 0x30);
-               atp_dev.sp[m++] = inb(base_io + 0x31);
-               atp_dev.sp[m++] = inb(base_io + 0x32);
-               atp_dev.sp[m++] = inb(base_io + 0x33);
+               atp_dev.sp[0][m++] = inb(base_io + 0x30);
+               atp_dev.sp[0][m++] = inb(base_io + 0x31);
+               atp_dev.sp[0][m++] = inb(base_io + 0x32);
+               atp_dev.sp[0][m++] = inb(base_io + 0x33);
                outw(n, base_io + 0x34);
                n += 0x0002;
-               atp_dev.sp[m++] = inb(base_io + 0x30);
-               atp_dev.sp[m++] = inb(base_io + 0x31);
-               atp_dev.sp[m++] = inb(base_io + 0x32);
-               atp_dev.sp[m++] = inb(base_io + 0x33);
+               atp_dev.sp[0][m++] = inb(base_io + 0x30);
+               atp_dev.sp[0][m++] = inb(base_io + 0x31);
+               atp_dev.sp[0][m++] = inb(base_io + 0x32);
+               atp_dev.sp[0][m++] = inb(base_io + 0x33);
                outw(n, base_io + 0x34);
                n += 0x0002;
-               atp_dev.sp[m++] = inb(base_io + 0x30);
-               atp_dev.sp[m++] = inb(base_io + 0x31);
-               atp_dev.sp[m++] = inb(base_io + 0x32);
-               atp_dev.sp[m++] = inb(base_io + 0x33);
+               atp_dev.sp[0][m++] = inb(base_io + 0x30);
+               atp_dev.sp[0][m++] = inb(base_io + 0x31);
+               atp_dev.sp[0][m++] = inb(base_io + 0x32);
+               atp_dev.sp[0][m++] = inb(base_io + 0x33);
                outw(n, base_io + 0x34);
                n += 0x0002;
-               atp_dev.sp[m++] = inb(base_io + 0x30);
-               atp_dev.sp[m++] = inb(base_io + 0x31);
-               atp_dev.sp[m++] = inb(base_io + 0x32);
-               atp_dev.sp[m++] = inb(base_io + 0x33);
+               atp_dev.sp[0][m++] = inb(base_io + 0x30);
+               atp_dev.sp[0][m++] = inb(base_io + 0x31);
+               atp_dev.sp[0][m++] = inb(base_io + 0x32);
+               atp_dev.sp[0][m++] = inb(base_io + 0x33);
                n += 0x0018;
-               goto next_fblk;
-flash_ok:
+               goto next_fblk_880;
+flash_ok_880:
                outw(0, base_io + 0x34);
-               atp_dev.ultra_map = 0;
-               atp_dev.async = 0;
+               atp_dev.ultra_map[0] = 0;
+               atp_dev.async[0] = 0;
                for (k = 0; k < 16; k++) {
                        n = 1;
                        n = n << k;
-                       if (atp_dev.sp[k] > 1) {
-                               atp_dev.ultra_map |= n;
+                       if (atp_dev.sp[0][k] > 1) {
+                               atp_dev.ultra_map[0] |= n;
                        } else {
-                               if (atp_dev.sp[k] == 0)
-                                       atp_dev.async |= n;
+                               if (atp_dev.sp[0][k] == 0)
+                                       atp_dev.async[0] |= n;
                        }
                }
-               atp_dev.async = ~(atp_dev.async);
-               outb(atp_dev.global_map, base_io + 0x35);
+               atp_dev.async[0] = ~(atp_dev.async[0]);
+               outb(atp_dev.global_map[0], base_io + 0x35);
  
                shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
                if (!shpnt)
@@ -2471,16 +2741,16 @@ flash_ok:
                p = (struct atp_unit *)&shpnt->hostdata;
 
                atp_dev.host = shpnt;
-               atp_dev.pdev = dev;
-               pci_set_drvdata(dev, p);
+               atp_dev.pdev = pdev;
+               pci_set_drvdata(pdev, p);
                memcpy(p, &atp_dev, sizeof atp_dev);
                if (atp870u_init_tables(shpnt) < 0) {
                        printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
                        goto unregister;
                }
 
-               if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
-                       printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq);
+               if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp880i", shpnt)) {
+                       printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
                        goto free_tables;
                }
 
@@ -2513,50 +2783,314 @@ flash_ok:
                outb(0x20, tmport);
 
                tscam(shpnt);
-               is880(shpnt, base_io);
+               is880(p, base_io);
                tmport = base_io + 0x38;
                outb(0xb0, tmport);
-       }
-
-       if (p->chip_veru == 4)
                shpnt->max_id = 16;
-
-       shpnt->this_id = host_id;
-       shpnt->unique_id = base_io;
-       shpnt->io_port = base_io;
-       if (ent->device == 0x8081) {
+               shpnt->this_id = host_id;
+               shpnt->unique_id = base_io;
+               shpnt->io_port = base_io;
                shpnt->n_io_port = 0x60;        /* Number of bytes of I/O space used */
+               shpnt->irq = pdev->irq;                 
+       } else if (ent->device == ATP885_DEVID) {       
+                       printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD Host Adapter:  IO:%x, IRQ:%d.\n"
+                              , base_io, pdev->irq);
+               
+               atp_dev.pdev = pdev;    
+               atp_dev.dev_id  = ent->device;
+               atp_dev.baseport = base_io;
+               atp_dev.ioport[0] = base_io + 0x80;
+               atp_dev.ioport[1] = base_io + 0xc0;
+               atp_dev.pciport[0] = base_io + 0x40;
+               atp_dev.pciport[1] = base_io + 0x50;
+                               
+               shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
+               if (!shpnt)
+                       return -ENOMEM;
+               
+               p = (struct atp_unit *)&shpnt->hostdata;
+               
+               atp_dev.host = shpnt;
+               atp_dev.pdev = pdev;
+               pci_set_drvdata(pdev, p);
+               memcpy(p, &atp_dev, sizeof(struct atp_unit));
+               if (atp870u_init_tables(shpnt) < 0)
+                       goto unregister;
+                       
+#ifdef ED_DBGP         
+       printk("request_irq() shpnt %p hostdata %p\n", shpnt, p);
+#endif         
+               if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
+                               printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
+                       goto free_tables;
+               }
+               
+               spin_lock_irqsave(shpnt->host_lock, flags);                                             
+                               
+               c=inb(base_io + 0x29);
+               outb((c | 0x04),base_io + 0x29);
+               
+               n=0x1f80;
+next_fblk_885:
+               if (n >= 0x2000) {
+                  goto flash_ok_885;
+               }
+               outw(n,base_io + 0x3c);
+               if (inl(base_io + 0x38) == 0xffffffff) {
+                  goto flash_ok_885;
+               }
+               for (m=0; m < 2; m++) {
+                   p->global_map[m]= 0;
+                   for (k=0; k < 4; k++) {
+                       outw(n++,base_io + 0x3c);
+                       ((unsigned long *)&setupdata[m][0])[k]=inl(base_io + 0x38);
+                   }
+                   for (k=0; k < 4; k++) {
+                       outw(n++,base_io + 0x3c);
+                       ((unsigned long *)&p->sp[m][0])[k]=inl(base_io + 0x38);
+                   }
+                   n += 8;
+               }
+               goto next_fblk_885;
+flash_ok_885:
+#ifdef ED_DBGP
+               printk( "Flash Read OK\n");
+#endif 
+               c=inb(base_io + 0x29);
+               outb((c & 0xfb),base_io + 0x29);
+               for (c=0;c < 2;c++) {
+                   p->ultra_map[c]=0;
+                   p->async[c] = 0;
+                   for (k=0; k < 16; k++) {
+                       n=1;
+                       n = n << k;
+                       if (p->sp[c][k] > 1) {
+                          p->ultra_map[c] |= n;
+                       } else {
+                          if (p->sp[c][k] == 0) {
+                             p->async[c] |= n;
+                          }
+                       }
+                   }
+                   p->async[c] = ~(p->async[c]);
+
+                   if (p->global_map[c] == 0) {
+                      k=setupdata[c][1];
+                      if ((k & 0x40) != 0)
+                         p->global_map[c] |= 0x20;
+                      k &= 0x07;
+                      p->global_map[c] |= k;
+                      if ((setupdata[c][2] & 0x04) != 0)
+                         p->global_map[c] |= 0x08;
+                      p->host_id[c] = setupdata[c][0] & 0x07;
+                   }
+               }
+
+               k = inb(base_io + 0x28) & 0x8f;
+               k |= 0x10;
+               outb(k, base_io + 0x28);
+               outb(0x80, base_io + 0x41);
+               outb(0x80, base_io + 0x51);
+               mdelay(100);
+               outb(0, base_io + 0x41);
+               outb(0, base_io + 0x51);
+               mdelay(1000);
+               inb(base_io + 0x9b);
+               inb(base_io + 0x97);
+               inb(base_io + 0xdb);
+               inb(base_io + 0xd7);
+               tmport = base_io + 0x80;
+               k=p->host_id[0];
+               if (k > 7)
+                  k = (k & 0x07) | 0x40;
+               k |= 0x08;
+               outb(k, tmport);
+               tmport += 0x18;
+               outb(0, tmport);
+               tmport += 0x07;
+
+               while ((inb(tmport) & 0x80) == 0)
+                       cpu_relax();
+       
+               tmport -= 0x08;
+               inb(tmport);
+               tmport = base_io + 0x81;
+               outb(8, tmport++);
+               outb(0x7f, tmport);
+               tmport = base_io + 0x91;
+               outb(0x20, tmport);
+
+               tmport = base_io + 0xc0;
+               k=p->host_id[1];
+               if (k > 7)
+                  k = (k & 0x07) | 0x40;
+               k |= 0x08;
+               outb(k, tmport);
+               tmport += 0x18;
+               outb(0, tmport);
+               tmport += 0x07;
+
+               while ((inb(tmport) & 0x80) == 0)
+                       cpu_relax();
+
+               tmport -= 0x08;
+               inb(tmport);
+               tmport = base_io + 0xc1;
+               outb(8, tmport++);
+               outb(0x7f, tmport);
+               tmport = base_io + 0xd1;
+               outb(0x20, tmport);
+
+               tscam_885();
+               printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
+               is885(p, base_io + 0x80, 0);
+               printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
+               is885(p, base_io + 0xc0, 1);
+
+               k = inb(base_io + 0x28) & 0xcf;
+               k |= 0xc0;
+               outb(k, base_io + 0x28);
+               k = inb(base_io + 0x1f) | 0x80;
+               outb(k, base_io + 0x1f);
+               k = inb(base_io + 0x29) | 0x01;
+               outb(k, base_io + 0x29);
+#ifdef ED_DBGP
+               //printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
+#endif         
+               shpnt->max_id = 16;
+               shpnt->max_lun = (p->global_map[0] & 0x07) + 1;
+               shpnt->max_channel = 1;
+               shpnt->this_id = p->host_id[0];
+               shpnt->unique_id = base_io;
+               shpnt->io_port = base_io;
+               shpnt->n_io_port = 0xff;        /* Number of bytes of I/O space used */
+               shpnt->irq = pdev->irq;
+                               
        } else {
+               error = pci_read_config_byte(pdev, 0x49, &host_id);
+
+               printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
+                       "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
+
+               atp_dev.ioport[0] = base_io;
+               atp_dev.pciport[0] = base_io + 0x20;
+               atp_dev.dev_id = ent->device;
+               host_id &= 0x07;
+               atp_dev.host_id[0] = host_id;
+               tmport = base_io + 0x22;
+               atp_dev.scam_on = inb(tmport);
+               tmport += 0x0b;
+               atp_dev.global_map[0] = inb(tmport++);
+               atp_dev.ultra_map[0] = inw(tmport);
+
+               if (atp_dev.ultra_map[0] == 0) {
+                       atp_dev.scam_on = 0x00;
+                       atp_dev.global_map[0] = 0x20;
+                       atp_dev.ultra_map[0] = 0xffff;
+               }
+
+               shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
+               if (!shpnt)
+                       return -ENOMEM;
+
+               p = (struct atp_unit *)&shpnt->hostdata;
+               
+               atp_dev.host = shpnt;
+               atp_dev.pdev = pdev;
+               pci_set_drvdata(pdev, p);
+               memcpy(p, &atp_dev, sizeof atp_dev);
+               if (atp870u_init_tables(shpnt) < 0)
+                       goto unregister;
+
+               if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870i", shpnt)) {
+                       printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
+                       goto free_tables;
+               }
+
+               spin_lock_irqsave(shpnt->host_lock, flags);
+               if (atp_dev.chip_ver > 0x07) {  /* check if atp876 chip then enable terminator */
+                       tmport = base_io + 0x3e;
+                       outb(0x00, tmport);
+               }
+               tmport = base_io + 0x3a;
+               k = (inb(tmport) & 0xf3) | 0x10;
+               outb(k, tmport);
+               outb((k & 0xdf), tmport);
+               mdelay(32);
+               outb(k, tmport);
+               mdelay(32);
+               tmport = base_io;
+               outb((host_id | 0x08), tmport);
+               tmport += 0x18;
+               outb(0, tmport);
+               tmport += 0x07;
+               while ((inb(tmport) & 0x80) == 0)
+                       mdelay(1);
+
+               tmport -= 0x08;
+               inb(tmport);
+               tmport = base_io + 1;
+               outb(8, tmport++);
+               outb(0x7f, tmport);
+               tmport = base_io + 0x11;
+               outb(0x20, tmport);
+
+               tscam(shpnt);
+               is870(p, base_io);
+               tmport = base_io + 0x3a;
+               outb((inb(tmport) & 0xef), tmport);
+               tmport++;
+               outb((inb(tmport) | 0x20), tmport);
+               if (atp_dev.chip_ver == 4)
+                       shpnt->max_id = 16;
+               else            
+                       shpnt->max_id = 7;
+               shpnt->this_id = host_id;
+               shpnt->unique_id = base_io;
+               shpnt->io_port = base_io;
                shpnt->n_io_port = 0x40;        /* Number of bytes of I/O space used */
-       }
-       shpnt->irq = dev->irq;
-       spin_unlock_irqrestore(shpnt->host_lock, flags);
-       if (ent->device == 0x8081) {
-               if (!request_region(base_io, 0x60, "atp870u"))
-                       goto request_io_fail;
-       } else {
-               if (!request_region(base_io, 0x40, "atp870u"))
-                       goto request_io_fail;
-       }
+               shpnt->irq = pdev->irq;         
+       } 
+               spin_unlock_irqrestore(shpnt->host_lock, flags);
+               if(ent->device==ATP885_DEVID) {
+                       if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */
+                               goto request_io_fail;
+               } else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
+                       if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */
+                               goto request_io_fail;
+               } else {
+                       if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */
+                               goto request_io_fail;
+               }                               
+               count++;
+               if (scsi_add_host(shpnt, &pdev->dev))
+                       goto scsi_add_fail;
+               scsi_scan_host(shpnt);
+#ifdef ED_DBGP                 
+               printk("atp870u_prob : exit\n");
+#endif         
+               return 0;
 
-       count++;
-       if (scsi_add_host(shpnt, &dev->dev))
-               goto scsi_add_fail;
-       scsi_scan_host(shpnt);
-       return 0;
-  
 scsi_add_fail:
-       if (ent->device == 0x8081)
+       printk("atp870u_prob:scsi_add_fail\n");
+       if(ent->device==ATP885_DEVID) {
+               release_region(base_io, 0xff);
+       } else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
                release_region(base_io, 0x60);
-       else
+       } else {
                release_region(base_io, 0x40);
+       }
 request_io_fail:
-       free_irq(dev->irq, shpnt);
+       printk("atp870u_prob:request_io_fail\n");
+       free_irq(pdev->irq, shpnt);
 free_tables:
+       printk("atp870u_prob:free_table\n");
        atp870u_free_tables(shpnt);
 unregister:
+       printk("atp870u_prob:unregister\n");
        scsi_host_put(shpnt);
-       return -1;
+       return -1;              
 }
 
 /* The abort command does not leave the device in a clean state where
@@ -2565,40 +3099,40 @@ unregister:
 
 static int atp870u_abort(struct scsi_cmnd * SCpnt)
 {
-       unsigned char j, k;
+       unsigned char  j, k, c;
        struct scsi_cmnd *workrequ;
        unsigned int tmport;
-       struct atp_unit *dev = (struct atp_unit *)&SCpnt->device->host->hostdata;
+       struct atp_unit *dev;   
+       struct Scsi_Host *host;
+       host = SCpnt->device->host;
 
-       printk(KERN_DEBUG "working=%x last_cmd=%x ", dev->working, dev->last_cmd);
-       printk(" quhdu=%x quendu=%x ", dev->quhdu, dev->quendu);
-       tmport = dev->ioport;
-       for (j = 0; j < 0x17; j++) {
+       dev = (struct atp_unit *)&host->hostdata;
+       c=SCpnt->device->channel;
+       printk(" atp870u: abort Channel = %x \n", c);
+       printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
+       printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
+       tmport = dev->ioport[c];
+       for (j = 0; j < 0x18; j++) {
                printk(" r%2x=%2x", j, inb(tmport++));
        }
-       tmport += 0x05;
+       tmport += 0x04;
        printk(" r1c=%2x", inb(tmport));
        tmport += 0x03;
-       printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd);
-       tmport = dev->pciport;
-       printk(" r20=%2x", inb(tmport));
+       printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd[c]);
+       tmport= dev->pciport[c];
+       printk(" d00=%2x", inb(tmport));
        tmport += 0x02;
-       printk(" r22=%2x", inb(tmport));
-       tmport = dev->ioport + 0x3a;
-       printk(" r3a=%2x \n", inb(tmport));
-       tmport = dev->ioport + 0x3b;
-       printk(" r3b=%2x \n", inb(tmport));
-       for (j = 0; j < 16; j++) {
-               if (dev->id[j].curr_req != NULL) {
-                       workrequ = dev->id[j].curr_req;
-                       printk("\n que cdb= ");
-                       for (k = 0; k < workrequ->cmd_len; k++) {
-                               printk(" %2x ", workrequ->cmnd[k]);
-                       }
-                       printk(" last_lenu= %lx ", dev->id[j].last_lenu);
+       printk(" d02=%2x", inb(tmport));
+       for(j=0;j<16;j++) {
+          if (dev->id[c][j].curr_req != NULL) {
+               workrequ = dev->id[c][j].curr_req;
+               printk("\n que cdb= ");
+               for (k=0; k < workrequ->cmd_len; k++) {
+                   printk(" %2x ",workrequ->cmnd[k]);
                }
+               printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
+          }
        }
-       /* Sort of - the thing handles itself */
        return SUCCESS;
 }
 
@@ -2612,20 +3146,19 @@ static const char *atp870u_info(struct Scsi_Host *notused)
 }
 
 #define BLS buffer + len + size
-static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
-               char **start, off_t offset, int length, int inout)
+int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, 
+                     char **start, off_t offset, int length, int inout)
 {
        static u8 buff[512];
        int size = 0;
        int len = 0;
        off_t begin = 0;
        off_t pos = 0;
-
-       if (inout)
-               return -ENOSYS;
-       if (offset == 0) {
+       
+       if (inout)      
+               return -EINVAL;
+       if (offset == 0)
                memset(buff, 0, sizeof(buff));
-       }
        size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
        len += size;
        pos = begin + len;
@@ -2637,7 +3170,7 @@ static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
        size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
        len += size;
        pos = begin + len;
-
+       
        *start = buffer + (offset - begin);     /* Start of wanted data */
        len -= (offset - begin);        /* Start slop */
        if (len > length) {
@@ -2646,15 +3179,15 @@ static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
        return (len);
 }
 
-static int atp870u_biosparam(struct scsi_device *sdev,
-               struct block_device *dev, sector_t capacity, int *ip)
+
+static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
+                       sector_t capacity, int *ip)
 {
        int heads, sectors, cylinders;
 
        heads = 64;
        sectors = 32;
        cylinders = (unsigned long)capacity / (heads * sectors);
-
        if (cylinders > 1024) {
                heads = 255;
                sectors = 63;
@@ -2667,39 +3200,46 @@ static int atp870u_biosparam(struct scsi_device *sdev,
        return 0;
 }
 
-static void atp870u_remove(struct pci_dev *pdev)
-{
-       struct atp_unit *atp_dev = pci_get_drvdata(pdev);
-       struct Scsi_Host *pshost = atp_dev->host;
-
+static void atp870u_remove (struct pci_dev *pdev)
+{      
+       struct atp_unit *devext = pci_get_drvdata(pdev);
+       struct Scsi_Host *pshost = devext->host;
+       
+       
        scsi_remove_host(pshost);
+       printk(KERN_INFO "free_irq : %d\n",pshost->irq);
        free_irq(pshost->irq, pshost);
        release_region(pshost->io_port, pshost->n_io_port);
+       printk(KERN_INFO "atp870u_free_tables : %p\n",pshost);
        atp870u_free_tables(pshost);
+       printk(KERN_INFO "scsi_host_put : %p\n",pshost);
        scsi_host_put(pshost);
-       pci_set_drvdata(pdev, NULL);
+       printk(KERN_INFO "pci_set_drvdata : %p\n",pdev);
+       pci_set_drvdata(pdev, NULL);    
 }
-
 MODULE_LICENSE("GPL");
 
 static struct scsi_host_template atp870u_template = {
-       .module                 = THIS_MODULE,
-       .name                   = "atp870u",
-       .proc_name              = "atp870u",
-       .proc_info              = atp870u_proc_info,
-       .info                   = atp870u_info,
-       .queuecommand           = atp870u_queuecommand,
-       .eh_abort_handler       = atp870u_abort,
-       .bios_param             = atp870u_biosparam,
-       .can_queue              = qcnt,
-       .this_id                = 7,
-       .sg_tablesize           = ATP870U_SCATTER,
-       .cmd_per_lun            = ATP870U_CMDLUN,
-       .use_clustering         = ENABLE_CLUSTERING,
+     .module                   = THIS_MODULE,
+     .name                     = "atp870u"             /* name */,
+     .proc_name                        = "atp870u",
+     .proc_info                        = atp870u_proc_info,
+     .info                     = atp870u_info          /* info */,
+     .queuecommand             = atp870u_queuecommand  /* queuecommand */,
+     .eh_abort_handler         = atp870u_abort         /* abort */,
+     .bios_param               = atp870u_biosparam     /* biosparm */,
+     .can_queue                = qcnt                  /* can_queue */,
+     .this_id                  = 7                     /* SCSI ID */,
+     .sg_tablesize             = ATP870U_SCATTER       /*SG_ALL*/ /*SG_NONE*/,
+     .cmd_per_lun              = ATP870U_CMDLUN                /* commands per lun */,
+     .use_clustering           = ENABLE_CLUSTERING,
+     .max_sectors              = ATP870U_MAX_SECTORS,
 };
 
 static struct pci_device_id atp870u_id_table[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, 0x8081)                         },
+       { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)                   },
+       { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)                          },
+       { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)                          },
        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
@@ -2712,7 +3252,7 @@ static struct pci_device_id atp870u_id_table[] = {
 
 MODULE_DEVICE_TABLE(pci, atp870u_id_table);
 
-static struct pci_driver atp870u_driver = {    
+static struct pci_driver atp870u_driver = {
        .id_table       = atp870u_id_table,
        .name           = "atp870u",
        .probe          = atp870u_probe,
@@ -2721,14 +3261,710 @@ static struct pci_driver atp870u_driver = {
 
 static int __init atp870u_init(void)
 {
-       return pci_module_init(&atp870u_driver);
+#ifdef ED_DBGP 
+       printk("atp870u_init: Entry\n");
+#endif 
+       return pci_register_driver(&atp870u_driver);
 }
 
 static void __exit atp870u_exit(void)
 {
+#ifdef ED_DBGP 
+       printk("atp870u_exit: Entry\n");
+#endif
        pci_unregister_driver(&atp870u_driver);
 }
 
+static void tscam_885(void)
+{
+       unsigned char i;
+
+       for (i = 0; i < 0x2; i++) {
+               mdelay(300);
+       }
+       return;
+}
+
+
+
+static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
+{
+       unsigned int tmport;
+       unsigned char i, j, k, rmb, n, lvdmode;
+       unsigned short int m;
+       static unsigned char mbuf[512];
+       static unsigned char satn[9] =  {0, 0, 0, 0, 0, 0, 0, 6, 6};
+       static unsigned char inqd[9] =  {0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
+       static unsigned char synn[6] =  {0x80, 1, 3, 1, 0x19, 0x0e};
+       unsigned char synu[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
+       static unsigned char synw[6] =  {0x80, 1, 3, 1, 0x19, 0x0e};
+       unsigned char synuw[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
+       static unsigned char wide[6] =  {0x80, 1, 2, 3, 1, 0};
+       static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
+
+       lvdmode=inb(wkport + 0x1b) >> 7;
+
+       for (i = 0; i < 16; i++) {
+               m = 1;
+               m = m << i;
+               if ((m & dev->active_id[c]) != 0) {
+                       continue;
+               }
+               if (i == dev->host_id[c]) {
+                       printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
+                       continue;
+               }
+               tmport = wkport + 0x1b;
+               outb(0x01, tmport);
+               tmport = wkport + 0x01;
+               outb(0x08, tmport++);
+               outb(0x7f, tmport++);
+               outb(satn[0], tmport++);
+               outb(satn[1], tmport++);
+               outb(satn[2], tmport++);
+               outb(satn[3], tmport++);
+               outb(satn[4], tmport++);
+               outb(satn[5], tmport++);
+               tmport += 0x06;
+               outb(0, tmport);
+               tmport += 0x02;
+               outb(dev->id[c][i].devsp, tmport++);
+               
+               outb(0, tmport++);
+               outb(satn[6], tmport++);
+               outb(satn[7], tmport++);
+               j = i;
+               if ((j & 0x08) != 0) {
+                       j = (j & 0x07) | 0x40;
+               }
+               outb(j, tmport);
+               tmport += 0x03;
+               outb(satn[8], tmport);
+               tmport += 0x07;
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               tmport -= 0x08;
+               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+                       continue;
+               }
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+               dev->active_id[c] |= m;
+
+               tmport = wkport + 0x10;
+               outb(0x30, tmport);
+               tmport = wkport + 0x14;
+               outb(0x00, tmport);
+
+phase_cmd:
+               tmport = wkport + 0x18;
+               outb(0x08, tmport);
+               tmport += 0x07;
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               tmport -= 0x08;
+               j = inb(tmport);
+               if (j != 0x16) {
+                       tmport = wkport + 0x10;
+                       outb(0x41, tmport);
+                       goto phase_cmd;
+               }
+sel_ok:
+               tmport = wkport + 0x03;
+               outb(inqd[0], tmport++);
+               outb(inqd[1], tmport++);
+               outb(inqd[2], tmport++);
+               outb(inqd[3], tmport++);
+               outb(inqd[4], tmport++);
+               outb(inqd[5], tmport);
+               tmport += 0x07;
+               outb(0, tmport);
+               tmport += 0x02;
+               outb(dev->id[c][i].devsp, tmport++);
+               outb(0, tmport++);
+               outb(inqd[6], tmport++);
+               outb(inqd[7], tmport++);
+               tmport += 0x03;
+               outb(inqd[8], tmport);
+               tmport += 0x07;
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               tmport -= 0x08;
+               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+                       continue;
+               }
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+               tmport = wkport + 0x1b;
+               outb(0x00, tmport);
+               tmport = wkport + 0x18;
+               outb(0x08, tmport);
+               tmport += 0x07;
+               j = 0;
+rd_inq_data:
+               k = inb(tmport);
+               if ((k & 0x01) != 0) {
+                       tmport -= 0x06;
+                       mbuf[j++] = inb(tmport);
+                       tmport += 0x06;
+                       goto rd_inq_data;
+               }
+               if ((k & 0x80) == 0) {
+                       goto rd_inq_data;
+               }
+               tmport -= 0x08;
+               j = inb(tmport);
+               if (j == 0x16) {
+                       goto inq_ok;
+               }
+               tmport = wkport + 0x10;
+               outb(0x46, tmport);
+               tmport += 0x02;
+               outb(0, tmport++);
+               outb(0, tmport++);
+               outb(0, tmport++);
+               tmport += 0x03;
+               outb(0x08, tmport);
+               tmport += 0x07;
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               tmport -= 0x08;
+               if (inb(tmport) != 0x16) {
+                       goto sel_ok;
+               }
+inq_ok:
+               mbuf[36] = 0;
+               printk( KERN_INFO"         ID: %2d  %s\n", i, &mbuf[8]);
+               dev->id[c][i].devtype = mbuf[0];
+               rmb = mbuf[1];
+               n = mbuf[7];
+               if ((mbuf[7] & 0x60) == 0) {
+                       goto not_wide;
+               }
+               if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) {
+                       goto not_wide;
+               }
+               if (lvdmode == 0) {
+                  goto chg_wide;
+               }
+               if (dev->sp[c][i] != 0x04) {    // force u2
+                  goto chg_wide;
+               }
+
+               tmport = wkport + 0x1b;
+               outb(0x01, tmport);
+               tmport = wkport + 0x03;
+               outb(satn[0], tmport++);
+               outb(satn[1], tmport++);
+               outb(satn[2], tmport++);
+               outb(satn[3], tmport++);
+               outb(satn[4], tmport++);
+               outb(satn[5], tmport++);
+               tmport += 0x06;
+               outb(0, tmport);
+               tmport += 0x02;
+               outb(dev->id[c][i].devsp, tmport++);
+               outb(0, tmport++);
+               outb(satn[6], tmport++);
+               outb(satn[7], tmport++);
+               tmport += 0x03;
+               outb(satn[8], tmport);
+               tmport += 0x07;
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               tmport -= 0x08;
+               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+                       continue;
+               }
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+try_u3:
+               j = 0;
+               tmport = wkport + 0x14;
+               outb(0x09, tmport);
+               tmport += 0x04;
+               outb(0x20, tmport);
+               tmport += 0x07;
+
+               while ((inb(tmport) & 0x80) == 0) {
+                       if ((inb(tmport) & 0x01) != 0) {
+                               tmport -= 0x06;
+                               outb(u3[j++], tmport);
+                               tmport += 0x06;
+                       }
+                       cpu_relax();
+               }
+               tmport -= 0x08;
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               j = inb(tmport) & 0x0f;
+               if (j == 0x0f) {
+                       goto u3p_in;
+               }
+               if (j == 0x0a) {
+                       goto u3p_cmd;
+               }
+               if (j == 0x0e) {
+                       goto try_u3;
+               }
+               continue;
+u3p_out:
+               tmport = wkport + 0x18;
+               outb(0x20, tmport);
+               tmport += 0x07;
+               while ((inb(tmport) & 0x80) == 0) {
+                       if ((inb(tmport) & 0x01) != 0) {
+                               tmport -= 0x06;
+                               outb(0, tmport);
+                               tmport += 0x06;
+                       }
+                       cpu_relax();
+               }
+               tmport -= 0x08;
+               j = inb(tmport) & 0x0f;
+               if (j == 0x0f) {
+                       goto u3p_in;
+               }
+               if (j == 0x0a) {
+                       goto u3p_cmd;
+               }
+               if (j == 0x0e) {
+                       goto u3p_out;
+               }
+               continue;
+u3p_in:
+               tmport = wkport + 0x14;
+               outb(0x09, tmport);
+               tmport += 0x04;
+               outb(0x20, tmport);
+               tmport += 0x07;
+               k = 0;
+u3p_in1:
+               j = inb(tmport);
+               if ((j & 0x01) != 0) {
+                       tmport -= 0x06;
+                       mbuf[k++] = inb(tmport);
+                       tmport += 0x06;
+                       goto u3p_in1;
+               }
+               if ((j & 0x80) == 0x00) {
+                       goto u3p_in1;
+               }
+               tmport -= 0x08;
+               j = inb(tmport) & 0x0f;
+               if (j == 0x0f) {
+                       goto u3p_in;
+               }
+               if (j == 0x0a) {
+                       goto u3p_cmd;
+               }
+               if (j == 0x0e) {
+                       goto u3p_out;
+               }
+               continue;
+u3p_cmd:
+               tmport = wkport + 0x10;
+               outb(0x30, tmport);
+               tmport = wkport + 0x14;
+               outb(0x00, tmport);
+               tmport += 0x04;
+               outb(0x08, tmport);
+               tmport += 0x07;
+               while ((inb(tmport) & 0x80) == 0x00);
+               tmport -= 0x08;
+               j = inb(tmport);
+               if (j != 0x16) {
+                       if (j == 0x4e) {
+                               goto u3p_out;
+                       }
+                       continue;
+               }
+               if (mbuf[0] != 0x01) {
+                       goto chg_wide;
+               }
+               if (mbuf[1] != 0x06) {
+                       goto chg_wide;
+               }
+               if (mbuf[2] != 0x04) {
+                       goto chg_wide;
+               }
+               if (mbuf[3] == 0x09) {
+                       m = 1;
+                       m = m << i;
+                       dev->wide_id[c] |= m;
+                       dev->id[c][i].devsp = 0xce;
+#ifdef ED_DBGP            
+                       printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
+#endif
+                       continue;
+               }
+chg_wide:
+               tmport = wkport + 0x1b;
+               outb(0x01, tmport);
+               tmport = wkport + 0x03;
+               outb(satn[0], tmport++);
+               outb(satn[1], tmport++);
+               outb(satn[2], tmport++);
+               outb(satn[3], tmport++);
+               outb(satn[4], tmport++);
+               outb(satn[5], tmport++);
+               tmport += 0x06;
+               outb(0, tmport);
+               tmport += 0x02;
+               outb(dev->id[c][i].devsp, tmport++);
+               outb(0, tmport++);
+               outb(satn[6], tmport++);
+               outb(satn[7], tmport++);
+               tmport += 0x03;
+               outb(satn[8], tmport);
+               tmport += 0x07;
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               tmport -= 0x08;
+               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+                       continue;
+               }
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+try_wide:
+               j = 0;
+               tmport = wkport + 0x14;
+               outb(0x05, tmport);
+               tmport += 0x04;
+               outb(0x20, tmport);
+               tmport += 0x07;
+
+               while ((inb(tmport) & 0x80) == 0) {
+                       if ((inb(tmport) & 0x01) != 0) {
+                               tmport -= 0x06;
+                               outb(wide[j++], tmport);
+                               tmport += 0x06;
+                       }
+                       cpu_relax();
+               }
+               tmport -= 0x08;
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               j = inb(tmport) & 0x0f;
+               if (j == 0x0f) {
+                       goto widep_in;
+               }
+               if (j == 0x0a) {
+                       goto widep_cmd;
+               }
+               if (j == 0x0e) {
+                       goto try_wide;
+               }
+               continue;
+widep_out:
+               tmport = wkport + 0x18;
+               outb(0x20, tmport);
+               tmport += 0x07;
+               while ((inb(tmport) & 0x80) == 0) {
+                       if ((inb(tmport) & 0x01) != 0) {
+                               tmport -= 0x06;
+                               outb(0, tmport);
+                               tmport += 0x06;
+                       }
+                       cpu_relax();
+               }
+               tmport -= 0x08;
+               j = inb(tmport) & 0x0f;
+               if (j == 0x0f) {
+                       goto widep_in;
+               }
+               if (j == 0x0a) {
+                       goto widep_cmd;
+               }
+               if (j == 0x0e) {
+                       goto widep_out;
+               }
+               continue;
+widep_in:
+               tmport = wkport + 0x14;
+               outb(0xff, tmport);
+               tmport += 0x04;
+               outb(0x20, tmport);
+               tmport += 0x07;
+               k = 0;
+widep_in1:
+               j = inb(tmport);
+               if ((j & 0x01) != 0) {
+                       tmport -= 0x06;
+                       mbuf[k++] = inb(tmport);
+                       tmport += 0x06;
+                       goto widep_in1;
+               }
+               if ((j & 0x80) == 0x00) {
+                       goto widep_in1;
+               }
+               tmport -= 0x08;
+               j = inb(tmport) & 0x0f;
+               if (j == 0x0f) {
+                       goto widep_in;
+               }
+               if (j == 0x0a) {
+                       goto widep_cmd;
+               }
+               if (j == 0x0e) {
+                       goto widep_out;
+               }
+               continue;
+widep_cmd:
+               tmport = wkport + 0x10;
+               outb(0x30, tmport);
+               tmport = wkport + 0x14;
+               outb(0x00, tmport);
+               tmport += 0x04;
+               outb(0x08, tmport);
+               tmport += 0x07;
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               tmport -= 0x08;
+               j = inb(tmport);
+               if (j != 0x16) {
+                       if (j == 0x4e) {
+                               goto widep_out;
+                       }
+                       continue;
+               }
+               if (mbuf[0] != 0x01) {
+                       goto not_wide;
+               }
+               if (mbuf[1] != 0x02) {
+                       goto not_wide;
+               }
+               if (mbuf[2] != 0x03) {
+                       goto not_wide;
+               }
+               if (mbuf[3] != 0x01) {
+                       goto not_wide;
+               }
+               m = 1;
+               m = m << i;
+               dev->wide_id[c] |= m;
+not_wide:
+               if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) ||
+                   ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
+                       m = 1;
+                       m = m << i;
+                       if ((dev->async[c] & m) != 0) {
+                          goto set_sync;
+                       }
+               }
+               continue;
+set_sync:
+               if (dev->sp[c][i] == 0x02) {
+                  synu[4]=0x0c;
+                  synuw[4]=0x0c;
+               } else {
+                  if (dev->sp[c][i] >= 0x03) {
+                     synu[4]=0x0a;
+                     synuw[4]=0x0a;
+                  }
+               }
+               tmport = wkport + 0x1b;
+               j = 0;
+               if ((m & dev->wide_id[c]) != 0) {
+                       j |= 0x01;
+               }
+               outb(j, tmport);
+               tmport = wkport + 0x03;
+               outb(satn[0], tmport++);
+               outb(satn[1], tmport++);
+               outb(satn[2], tmport++);
+               outb(satn[3], tmport++);
+               outb(satn[4], tmport++);
+               outb(satn[5], tmport++);
+               tmport += 0x06;
+               outb(0, tmport);
+               tmport += 0x02;
+               outb(dev->id[c][i].devsp, tmport++);
+               outb(0, tmport++);
+               outb(satn[6], tmport++);
+               outb(satn[7], tmport++);
+               tmport += 0x03;
+               outb(satn[8], tmport);
+               tmport += 0x07;
+
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               tmport -= 0x08;
+               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+                       continue;
+               }
+               while (inb(tmport) != 0x8e)
+                       cpu_relax();
+try_sync:
+               j = 0;
+               tmport = wkport + 0x14;
+               outb(0x06, tmport);
+               tmport += 0x04;
+               outb(0x20, tmport);
+               tmport += 0x07;
+
+               while ((inb(tmport) & 0x80) == 0) {
+                       if ((inb(tmport) & 0x01) != 0) {
+                               tmport -= 0x06;
+                               if ((m & dev->wide_id[c]) != 0) {
+                                       if ((m & dev->ultra_map[c]) != 0) {
+                                               outb(synuw[j++], tmport);
+                                       } else {
+                                               outb(synw[j++], tmport);
+                                       }
+                               } else {
+                                       if ((m & dev->ultra_map[c]) != 0) {
+                                               outb(synu[j++], tmport);
+                                       } else {
+                                               outb(synn[j++], tmport);
+                                       }
+                               }
+                               tmport += 0x06;
+                       }
+               }
+               tmport -= 0x08;
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               j = inb(tmport) & 0x0f;
+               if (j == 0x0f) {
+                       goto phase_ins;
+               }
+               if (j == 0x0a) {
+                       goto phase_cmds;
+               }
+               if (j == 0x0e) {
+                       goto try_sync;
+               }
+               continue;
+phase_outs:
+               tmport = wkport + 0x18;
+               outb(0x20, tmport);
+               tmport += 0x07;
+               while ((inb(tmport) & 0x80) == 0x00) {
+                       if ((inb(tmport) & 0x01) != 0x00) {
+                               tmport -= 0x06;
+                               outb(0x00, tmport);
+                               tmport += 0x06;
+                       }
+                       cpu_relax();
+               }
+               tmport -= 0x08;
+               j = inb(tmport);
+               if (j == 0x85) {
+                       goto tar_dcons;
+               }
+               j &= 0x0f;
+               if (j == 0x0f) {
+                       goto phase_ins;
+               }
+               if (j == 0x0a) {
+                       goto phase_cmds;
+               }
+               if (j == 0x0e) {
+                       goto phase_outs;
+               }
+               continue;
+phase_ins:
+               tmport = wkport + 0x14;
+               outb(0x06, tmport);
+               tmport += 0x04;
+               outb(0x20, tmport);
+               tmport += 0x07;
+               k = 0;
+phase_ins1:
+               j = inb(tmport);
+               if ((j & 0x01) != 0x00) {
+                       tmport -= 0x06;
+                       mbuf[k++] = inb(tmport);
+                       tmport += 0x06;
+                       goto phase_ins1;
+               }
+               if ((j & 0x80) == 0x00) {
+                       goto phase_ins1;
+               }
+               tmport -= 0x08;
+               while ((inb(tmport) & 0x80) == 0x00);
+               j = inb(tmport);
+               if (j == 0x85) {
+                       goto tar_dcons;
+               }
+               j &= 0x0f;
+               if (j == 0x0f) {
+                       goto phase_ins;
+               }
+               if (j == 0x0a) {
+                       goto phase_cmds;
+               }
+               if (j == 0x0e) {
+                       goto phase_outs;
+               }
+               continue;
+phase_cmds:
+               tmport = wkport + 0x10;
+               outb(0x30, tmport);
+tar_dcons:
+               tmport = wkport + 0x14;
+               outb(0x00, tmport);
+               tmport += 0x04;
+               outb(0x08, tmport);
+               tmport += 0x07;
+               while ((inb(tmport) & 0x80) == 0x00)
+                       cpu_relax();
+               tmport -= 0x08;
+               j = inb(tmport);
+               if (j != 0x16) {
+                       continue;
+               }
+               if (mbuf[0] != 0x01) {
+                       continue;
+               }
+               if (mbuf[1] != 0x03) {
+                       continue;
+               }
+               if (mbuf[4] == 0x00) {
+                       continue;
+               }
+               if (mbuf[3] > 0x64) {
+                       continue;
+               }
+               if (mbuf[4] > 0x0e) {
+                       mbuf[4] = 0x0e;
+               }
+               dev->id[c][i].devsp = mbuf[4];
+               if (mbuf[3] < 0x0c){
+                       j = 0xb0;
+                       goto set_syn_ok;
+               }
+               if ((mbuf[3] < 0x0d) && (rmb == 0)) {
+                       j = 0xa0;
+                       goto set_syn_ok;
+               }
+               if (mbuf[3] < 0x1a) {
+                       j = 0x20;
+                       goto set_syn_ok;
+               }
+               if (mbuf[3] < 0x33) {
+                       j = 0x40;
+                       goto set_syn_ok;
+               }
+               if (mbuf[3] < 0x4c) {
+                       j = 0x50;
+                       goto set_syn_ok;
+               }
+               j = 0x60;
+             set_syn_ok:
+               dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
+#ifdef ED_DBGP         
+               printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
+#endif
+       }
+       tmport = wkport + 0x16;
+       outb(0x80, tmport);
+}
+
 module_init(atp870u_init);
 module_exit(atp870u_exit);