update atp870u driver to 0.78 from D-Link source
authorDobrica Pavlinusic <dpavlin@brr.lan>
Mon, 14 May 2007 04:51:09 +0000 (23:51 -0500)
committerDobrica Pavlinusic <dpavlin@brr.lan>
Mon, 14 May 2007 04:51:09 +0000 (23:51 -0500)
drivers/scsi/atp870u.c
drivers/scsi/atp870u.h
drivers/scsi/hosts.h

index 1648276..2b86981 100644 (file)
-/* $Id: atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $
- *  linux/kernel/atp870u.c
+/* $Id: atp870u.c,v 1.4 2005/12/12 06:25:19 axl Exp $
+ *  linux/kernel/atp86x.c
  *
- *  Copyright (C) 1997 Wu Ching Chen
- *  2.1.x update (C) 1998  Krzysztof G. Baranowski
+ *  Copyright (C) 2003-04      ACARD
+ *  Modified by Jason Wu from aec6285.c to support ATP865 chip
  *
- * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes
+ *  0.10       2003/12/19
+ *              1. Modify atp86x_detect()
  *
- * Wu Ching Chen : NULL pointer fixes  2000/06/02
- *                support atp876 chip
- *                enable 32 bit fifo transfer
- *                support cdrom & remove device run ultra speed
- *                fix disconnect bug  2000/12/21
- *                support atp880 chip lvd u160 2001/05/15
- *                fix prd table bug 2001/09/12 (7.1)
+ *  0.11        2003/12/19
+ *              1. Change file name from AEC6885.X to atp86x.c and .h
+ *              2. Change routine name from aec6285 to atp86x
+ *  0.12       2003/12/19
+ *              1. Modify atp86x_detect()
+ *                 (1) 865: init chip registers.
+ *  0.13        2003/12/22 
+ *              1. Modify atp86x_detect() 
+ *                 (1) is865: scan device
+ *  0.14        2003/12/22 
+ *              1. Modify is865() 
+ *                 (1) display the correct debug message of idenfity device command
+ *  0.15        2003/12/22
+ *              1. Modify is865() 
+ *                 (1) display more correct debug message of idenfity device command
+ *                 (2) display "UDMA xxx" after inquiry string..
+ *              2. Modify atp86x_release()
+ *                 (1) If 865, release region is different to 867.
+ *  0.16        2003/12/22
+ *              1. disable "DETECT_DEBUG" and "IS865_DEBUG"
+ *              2. Modify atp86x_queuecommand()
+ *                 (1) S860Io(): 
+ *  0.17        2003/12/23
+ *              1. S860IO(): display more debug messages
+ *              2. BuildSrb& RAID05: don't change ..
+ *              3. Noiocmd: don't change ..
+ *              4. SendSCSI: second argument: baseioaddress[0]= channel 0, baseioaddress[1] = channel 1
+ *  0.18        2003/12/23
+ *              1. atp86x_intr_handle
+ *  0.20        2003/12/23
+ *              1. Change version string.
+ *              2. atp86x_abort: change nothing..
+ *  0.30        2003/12/23
+ *              1. atp86x_reset:
+ *  0.40        2003/12/23
+ *              1. S3init: change name to ATP867init
+ *              2. ATP865init: init the ATP865 chip.
+ *              3. ATP865init: should send 3x6 software reset first.
+ *  0.50        2003/12/26
+ *              1. Define ATP865 chip number= 0x0008,0x0009 and ATP867=0x000A
+ *              2. ATP865: If chip version <= A3, should run UDMA100 only.
+ *              3. Print out not supported commands...
+ *                 (1) IO commands: 0x28,0x2a,0x08,0x0a,0x2b,0x0b,0x35,0x2f,0x1b
+ *                 (2) No IO commands: 0x1a, 0x12, 0x25, 0x03
+ *                 (3) Always status good: 0x00, 0x15, 0x55, 0x1e, 0x04
+ *                 (4) Always status check condition:  All others.
+ *                     Sense key : 05/20/00 not supported commands?
+ *
+ *  0.60        2003/12/27
+ *              1. Inquiry EVPD support:
+ *                 (1) Other pages: return 05/24/00 
+ *              2. ISR: Error handling: Sense key table implementation.
+ *                 (1) CRC Error: print out the debug message for release mode
+ *                 (2) Media Error: read/write/verify commands
+ *                 (3) Abort command:
+ *                 (4) Invalid address: read/write/seek/verify commands
+ *              3. Bad sector: sense key with bad sector LBA info   
+ *              4. Command 0x2E support!
+ *              5. Sense key should be enough for each HDD.( [8] for each card [16] for each buffer)
+ *
+ *  0.70        2004/1/14
+ *              1. IXP425: Big Endian problem
+ *                 (1) Inquiry: First 8 bytes should be filled in byte-unit. -> DONE
+ *                 (2) Read Capacity: block length should be filled in byte-unit. ->DONE
+ *                 (3) Read Capacity: Capacity Wrong! (identify command should get capacity in byte-unit)->DONE
+ *              2. IXP425: Big Endian problem
+ *                 (1) RAID05: use byte-unit to fill PRD table. -> DONE
+ *                 (2) Send SCSI: IDE command and PCI control should be seperated.
+ *                     -> Sendnorm: UCHAR for blkno, UCHAR pcicmd, UCHAR cmd. -> DONE
+ *                 (3) BuildSrb: Transfer counter should be set in byte-unit. -> DONE
+ *    
+ *  0.71        2004/1/14
+ *              1. IXP425: Test if allocate memory use GFP_ATOMIC parameter.
+ *              2. IXP42X_DEBUG_MSG = ON
+ *
+ *  0.72        2004/1/14
+ *              1. IXP425: Test if allocate memory use GFP_ATOMIC|GFP_DMA parameter.
+ *              2. IXP42X_DEBUG_MSG = OFF
+ *
+ *  0.73        2004/1/14
+ *              1. IXP425: Send SCSI: IDE command and PCI control should be seperated.
+ *                     -> Sendbigd: USHORT for blkno, UCHAR pcicmd, UCHAR cmd. ->DONE
+ *              2. IXP425: Is865 Bug: Inquiry command: first 8 bytes not modified.
+ *              3. IXP425: is867 Bug: 
+ *                 Read Capacity: Capacity Wrong! (identify command should get capacity in byte-unit)->DONE 
+ *  0.74        2004/1/14
+ *              1. Function get_disk_err_LBA: Bug! Bad sector LBA error for 48-bit LBA mode.  
+ *                 HOB problem -> DONE
+ *
+ *  0.75        2004/1/15
+ *              1.IXP425: Try to allocate memory by pci_alloc_consistent() and pci_free_consistent
+ *
+ *  0.76        2004/1/15
+ *              1.ATP867: PowerOn: I2C delay too long? 
+ *                        Remove I2C_ENABLE
+ *  0.77        2004/1/15
+ *              1. IXP425: Big-Endian: Mode sense problem: #define MODESENSE_DEBUG -> DONE
+ *
+ *  0.78        2004/1/15
+ *              1. IXP42X_DEBUG -> IXP42X_SUPPORT
+ *              2. Queue count: enlarge to max 128 queues per card.
+ *
+ * Pending issues
+ *              1. Inquiry EVPD page 80 : serial number support. 
+ *              2. Invalid address check: for Read/Write/seek/verify commands.  
+ *              3. Reassign block command support.
+ *              4. Abort: function not implement
+ *              5. Reset: function should be well tested 
+ *              6. Sendbigd: Should clear HOB first. 
+ *              7. Save Flags? Cli? Restore Flags? -> Protect sections that prevent the queue function fails.
+ *              8. ATP867: PowerOn: WD HDD -> UDMA 133?? Bugs? 
+ *                         ata66? is66? iswd? If the first driver=133, the next drive will become 133?
+ *              9. Mode select (6) not supported.
  */
 
+#define DEBUG_UDMA    // Always set to indicate the UDMA mode for HDDs
+#define IXP42X_SUPPORT  // IXP Big-Endian problem fixed
+//#define MODESENSE_DEBUG
+//#define I2C_ENABLE           
+//#define IXP42X_DEBUG_MSG
+//#define DETECT_DEBUG
+//#define IS865_DEBUG
+//#define QUEUECOMMAND_DEBUG
+//#define INTR_DEBUG
+//#define RESET_DEBUG
+//#define DEBUG_SENSEKEY
+
 #include <linux/module.h>
 
 #include <linux/kernel.h>
 
 #include<linux/stat.h>
 
-void mydlyu(unsigned int);
-
-/*
- *   static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $";
- */
-
-static unsigned char admaxu = 1;
-static unsigned short int sync_idu;
-
-static unsigned int irqnumu[2] = {0, 0};
+#define UCHAR   unsigned char
+#define USHORT  unsigned short
+#define ULONG   unsigned long
+#define PUCHAR   unsigned char *
+#define PUSHORT   unsigned short *
+#define PULONG   unsigned long *
+
+
+#define Inpb(x,y)      inb((x + y))
+#define Outpb(x,y,z)   outb(z, (x + y))
+#define Inpw(x,y)     inw((x + y))
+#define Outpw(x,y,z)  outw(z, (x + y))
+#define Inpl(x,y)      inl((x + y))
+#define Outpl(x,y,z)   outl(z, (x + y))
+
+static unsigned char admaxu = 3;
+static unsigned int irqnumu[4] = {0, 0, 0, 0};
+
+struct hw_lu_ext {
+#ifdef IXP42X_SUPPORT
+    dma_addr_t prdaddr;
+#else  
+    ULONG   prdaddr;
+#endif    
+
+    PUCHAR  prd;
+    ULONG   wslba;
+    USHORT  wsblkno;
+};
 
-struct atp_unit
+struct hw_device_ext {
+    struct hw_lu_ext lsrb[4][qcnt1];
+    struct hw_lu_ext *Cplsrb[4];
+    struct hw_lu_ext *plsrb[4][qcnt1];
+    struct pci_dev *pdev;
+    
+    ULONG   BaseIoAddress[4];
+    ULONG   BaseIoAddresm[4];
+    ULONG   irq,in_int;
+    Scsi_Cmnd * CSrb[4];
+    Scsi_Cmnd * QSrb[4][qcnt1];
+    ULONG   cap[8];
+    ULONG   que_hd[4],que_end[4],bigdrv[8];
+    USHORT  active_id;
+    UCHAR   devtype[8];
+    UCHAR   dskerr[8];
+    UCHAR   hd_status[8];
+    UCHAR   page0[16];
+    UCHAR   page1[24];
+    UCHAR   page1c[24];
+    UCHAR   sensd[8][16];
+    ULONG   dskerr_LBA[8];
+//    UCHAR   sensda[14];
+//    UCHAR   sensdok[14];
+//    UCHAR   inqdat[8][38];
+       UCHAR   inqdat[8][56];  //axl+
+// add for smart read  =================//
+       Scsi_Cmnd               SmartSrb;
+       ULONG                                   SmartReadID;
+       struct timer_list               AdapterTimer;
+       UCHAR                                   FG_TimerStop;
+       UCHAR                                   FG_SmartRead;
+//======================================//
+       UCHAR   dev_id,chipver,ata66;
+    UCHAR   host_id,c_mask;
+
+//axl+
+    ULONG   SamwiseBaseIoAddress;
+    UCHAR   SamwiseHDSelect;
+//axl end    
+};
+// add for smart read  =================//
+USHORT         smart_buf[256];
+void   smart_timer(ULONG para);
+//======================================//
+
+static struct Scsi_Host *a867host[4] = {NULL, NULL, NULL, NULL};
+static struct hw_device_ext dev_ext[4];
+
+int S860Io(struct hw_device_ext * devext, Scsi_Cmnd * Srb);
+int BuildSrb(struct hw_device_ext * devext, struct hw_lu_ext * srbp, Scsi_Cmnd * Srb);
+int Raid05(struct hw_device_ext * devext, struct hw_lu_ext * srbp, Scsi_Cmnd * Srb);
+int SendScsi(struct hw_device_ext * devext, Scsi_Cmnd * Srb, ULONG Ch);
+#ifdef IXP42X_SUPPORT
+void Sendnorm(ULONG baseIoAddress, ULONG baseIoAddresm, ULONG wklba, UCHAR wkblkno, UCHAR pcicmd, UCHAR cmd);
+void Sendbigd(ULONG baseIoAddress, ULONG baseIoAddresm, ULONG wklba, USHORT wkblkno, UCHAR pcicmd, UCHAR cmd);
+#else
+void Sendnorm(ULONG baseIoAddress, ULONG baseIoAddresm, ULONG wklba, USHORT wkblkno, USHORT cmd);
+void Sendbigd(ULONG baseIoAddress, ULONG baseIoAddresm, ULONG wklba, USHORT wkblkno, USHORT cmd);
+#endif
+void Noiocmd(struct hw_device_ext * devext, Scsi_Cmnd * Srb);
+#ifdef I2C_ENABLE
+int i2cwrite(ULONG baseIoAddress, UCHAR Rindex, UCHAR Rval);
+int i2cread(ULONG baseIoAddress, UCHAR Rindex, PUCHAR Rval);
+#endif
+void ATP867init(struct hw_device_ext * devext);
+void ATP865init(struct hw_device_ext * devext);
+int fill_sensekey_buf(struct hw_device_ext * devext, UCHAR tid);
+
+
+int get_disk_err_LBA(struct hw_device_ext * devext, UCHAR tid)
 {
-       unsigned long ioport;
-       unsigned long irq;
-       unsigned long pciport;
-       unsigned char last_cmd;
-       unsigned char in_snd;
-       unsigned char in_int;
-       unsigned char quhdu;
-       unsigned char quendu;
-       unsigned char scam_on;
-       unsigned char global_map;
-       unsigned char chip_veru;
-       unsigned char host_idu;
-       int working;
-       unsigned short wide_idu;
-       unsigned short active_idu;
-       unsigned short ultra_map;
-       unsigned short async;
-       unsigned short deviceid;
-       unsigned char ata_cdbu[16];
-       unsigned char sp[16];
-       Scsi_Cmnd *querequ[qcnt];
-       struct atp_id
+       ULONG  baseIoAddress= devext->BaseIoAddress[tid>>1];
+       ULONG  baseIoAddress2= devext->BaseIoAddress[(tid>>1)+2];
+       UCHAR  tmp;
+       
+        if (devext->bigdrv[tid] == 0)  
+        {
+               // if 28-bit LBA
+               // 1x3 =  
+               // 1x4 = 
+               // 1x5 = 
+               // 1x6 = 
+               tmp = Inpb(baseIoAddress,0x3);
+               devext->dskerr_LBA[tid] = tmp;  
+#ifdef DEBUG_SENSEKEY
+               printk("28-bit LBA 1X3 = %2X",tmp);
+#endif 
+               tmp = Inpb(baseIoAddress,0x4);
+               devext->dskerr_LBA[tid] |= (tmp<<8);            
+#ifdef DEBUG_SENSEKEY
+               printk("1X4 = %2X",tmp);
+#endif 
+               tmp = Inpb(baseIoAddress,0x5);
+               devext->dskerr_LBA[tid] |= (tmp<<16);                   
+#ifdef DEBUG_SENSEKEY
+               printk("1X5 = %2X",tmp);
+#endif 
+               tmp = Inpb(baseIoAddress,0x6);
+               devext->dskerr_LBA[tid] |= ((tmp<<24) & 0x0F);
+#ifdef DEBUG_SENSEKEY
+               printk("1X6 = %2X \n",tmp);
+#endif                 
+       }
+       else
        {
-               unsigned char dirctu;
-               unsigned char devspu;
-               unsigned char devtypeu;
-               unsigned long prdaddru;
-               unsigned long tran_lenu;
-               unsigned long last_lenu;
-               unsigned char *prd_posu;
-               unsigned char *prd_tableu;
-               Scsi_Cmnd *curr_req;
-       } id[16];
-};
-
-static struct Scsi_Host *atp_host[2] = {NULL, NULL};
-static struct atp_unit atp_unit[2];
+               // HOB=0: 1X3=LBA(7:0)   1X4= LBA(15:8) 1X5=LBA(23:16)
+               // HOB=1: 1X3=LBA(31:24) 1X4=LBA(39:32) 1X5=LBA(47:40)
+               outb(0x00, baseIoAddress2+2);
+#ifdef DEBUG_SENSEKEY
+               printk("48-bit Error LBA HOB = 0\n",tmp);
+#endif                 
+               tmp = Inpb(baseIoAddress,0x3);
+               devext->dskerr_LBA[tid] = tmp;                  
+#ifdef DEBUG_SENSEKEY
+               printk("1X3 = %2X",tmp);
+#endif 
+               tmp = Inpb(baseIoAddress,0x4);
+               devext->dskerr_LBA[tid] |= (tmp<<8);                            
+#ifdef DEBUG_SENSEKEY
+               printk("1X4 = %2X",tmp);
+#endif 
+               tmp = Inpb(baseIoAddress,0x5);
+               devext->dskerr_LBA[tid] |= (tmp<<16);                           
+#ifdef DEBUG_SENSEKEY
+               printk("1X5 = %2X\n",tmp);
+#endif 
+               outb(0x80, baseIoAddress2+2);
+#ifdef DEBUG_SENSEKEY
+               printk("48-bit Error LBA HOB = 1\n",tmp);
+#endif                 
+               tmp = Inpb(baseIoAddress,0x3);
+               devext->dskerr_LBA[tid] |= (tmp<<24);           
+#ifdef DEBUG_SENSEKEY
+               printk("2nd 1X3 = %2X",tmp);
+#endif                 
+               tmp = Inpb(baseIoAddress,0x4);
+#ifdef DEBUG_SENSEKEY
+               printk("2nd 1X4 = %2X",tmp);
+#endif 
+               tmp = Inpb(baseIoAddress,0x5);
+#ifdef DEBUG_SENSEKEY
+               printk("2nd 1X5 = %2X\n",tmp);
+#endif 
+               outb(0x00, baseIoAddress2+2);
+               tmp = Inpb(baseIoAddress,0x6);          
+       }
+#ifdef DEBUG_SENSEKEY
+       printk("1X6 = %2X LBA=%8lX\n",tmp,devext->dskerr_LBA[tid]);
+#endif                         
+       return 0;
+}
 
-static void atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
+static void atp86x_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
 {
-       unsigned long flags;
-       unsigned short int tmpcip, id;
-       unsigned char i, j, h, target_id, lun;
-       unsigned char *prd;
-       Scsi_Cmnd *workrequ;
-       unsigned int workportu, tmport;
-       unsigned long adrcntu, k;
-       int errstus;
-       struct atp_unit *dev = dev_id;
-
-       for (h = 0; h < 2; h++) {
-               if (irq == irqnumu[h]) {
-                       goto irq_numok;
-               }
-       }
-       return;
+     struct hw_device_ext *devext = dev_id;
+     ULONG  flags;
+     ULONG  baseIoAddress;
+     ULONG  baseIoAddresm;
+//     ULONG  lba;
+     Scsi_Cmnd * CSrb;
+     ULONG  Ch, x;
+     UCHAR  TargetId,intn;
+     UCHAR  i,h,k;
+#ifdef I2C_ENABLE     
+     UCHAR  l;
+#endif     
+       unsigned short  Value16;
+       unsigned char*  pData;
+       
+       pData = &smart_buf[0];
+       
+     for (h = 0; h < 4; h++) {
+            if (irq == irqnumu[h]) {
+                    goto irq_numok;
+            }
+     }
+     return;
 irq_numok:
-       dev->in_int = 1;
-       workportu = dev->ioport;
-       tmport = workportu;
-
-       if (dev->working != 0)
+     devext->in_int++;
+    if (devext->dev_id == ATP867_DEVID1)
+    {
+       baseIoAddress = devext->BaseIoAddress[0];
+#ifdef I2C_ENABLE      
+       if ((Inpb(baseIoAddress,0x2a) & devext->c_mask) != 0)
+       {
+               i=Inpb(baseIoAddress,0x2a) & devext->c_mask;
+               for (k=0; k < 4; k++)
+               {
+                       if ((i & 0x10) != 0)
+                       {
+                               baseIoAddress = devext->BaseIoAddress[k];
+                               i2cread(baseIoAddress,0x41,&l);
+                               i2cread(baseIoAddress,0x42,&l);
+                               i2cread(baseIoAddress,0x40,&l);
+                               i2cread(baseIoAddress,0x41,&l);
+                               i2cread(baseIoAddress,0x42,&l);
+                               Outpb(baseIoAddress,0x43,0x20);
+                       }
+                       i >>= 1;
+               }
+               baseIoAddress = devext->BaseIoAddress[0];
+       }
+#endif         
+       intn=Inpb(baseIoAddress,0x2a) & 0x0f;
+//check_irq:
+       for (Ch=0 ;Ch < 4; Ch++)
+       {
+               i=1;
+               i <<= Ch;
+               if ((intn & i) != 0)
+               {
+                       baseIoAddress = devext->BaseIoAddress[Ch];
+                       baseIoAddresm = devext->BaseIoAddresm[Ch];
+                       intn &= ~i;
+                       if (devext->CSrb[Ch] != 0)
+                       {
+                               CSrb=devext->CSrb[Ch];
+                               goto do_irq3;
+                       }
+                       else
+                       {
+                               Inpb(baseIoAddress,7);
+                               Outpb(baseIoAddresm,2,0x06);
+                       }
+               }
+       }
+    }
+    else
+    {
+       for (Ch=0 ;Ch < 2; Ch++)
+       {       
+       // ATP865
+               baseIoAddress = devext->BaseIoAddresm[Ch];
+               intn=Inpb(baseIoAddress,2) & 0x06;
+#ifdef INTR_DEBUG
+               printk("865INTR:Ch = %2lX intn = %2X \n",Ch,intn);
+#endif                         
+//check_irq:
+               if ((intn & 0x04) != 0)
+               {
+                       baseIoAddress = devext->BaseIoAddress[Ch];
+                       baseIoAddresm = devext->BaseIoAddresm[Ch];
+                       
+                       if (devext->CSrb[Ch] != 0)
+                       {
+                               CSrb=devext->CSrb[Ch];
+                               goto do_irq3;
+                       }
+                       else
+                       {
+                               Inpb(baseIoAddress,7);
+                               Outpb(baseIoAddresm,2,0x06);
+                       }
+               }
+       }       
+    } 
+    devext->in_int--;
+    return; 
+     
+do_irq3:
+#ifdef INTR_DEBUG
+   printk("86XINTR:do_irq3: target = %2X \n",CSrb->target);
+#endif          
+   TargetId=CSrb->target;
+   Outpb(baseIoAddresm,0,0);
+   i=Inpb(baseIoAddress,7);
+   Outpb(baseIoAddresm,2,0x06);
+   i &= 0xf9;
+// add for smart read  =================//
+   if (CSrb->cmnd[0] == 0xB0)
+   {
+//printk("Smart Read Interrupt,status:%02X",i);
+       if ((i == 0x58) || (i == 0x48))
        {
-               tmport += 0x1f;
-               j = inb(tmport);
-               if ((j & 0x80) == 0)
-               {
-                       dev->in_int = 0;
-                       return;
-               }
-
-               tmpcip = dev->pciport;
-               if ((inb(tmpcip) & 0x08) != 0)
-               {
-                       tmpcip += 0x2;
-                       for (k=0; k < 1000; k++)
-                       {
-                               if ((inb(tmpcip) & 0x08) == 0)
-                               {
-                                       goto stop_dma;
-                               }
-                               if ((inb(tmpcip) & 0x01) == 0)
-                               {
-                                       goto stop_dma;
-                               }
-                       }
-               }
-stop_dma:
-               tmpcip = dev->pciport;
-               outb(0x00, tmpcip);
-               tmport -= 0x08;
-
-               i = inb(tmport);
-
-               tmport -= 0x02;
-               target_id = inb(tmport);
-               tmport += 0x02;
-
-               /*
-                *      Remap wide devices onto id numbers
-                */
-
-               if ((target_id & 0x40) != 0) {
-                       target_id = (target_id & 0x07) | 0x08;
-               } else {
-                       target_id &= 0x07;
-               }
-
-               if ((j & 0x40) != 0)
-               {
-                    if (dev->last_cmd == 0xff)
-                    {
-                       dev->last_cmd = target_id;
-                    }
-                    dev->last_cmd |= 0x40;
-               }
-
-               if (i == 0x85)
-               {
-                       if ((dev->last_cmd & 0xf0) != 0x40)
-                       {
-                          dev->last_cmd = 0xff;
-                       }
-                       /*
-                        *      Flip wide
-                        */
-                       if (dev->wide_idu != 0)
-                       {
-                               tmport = workportu + 0x1b;
-                               outb(0x01,tmport);
-                               while ((inb(tmport) & 0x01) != 0x01)
-                               {
-                                  outb(0x01,tmport);
-                               }
-                       }
-                       /*
-                        *      Issue more commands
-                        */
-                       if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) &&
-                           (dev->in_snd == 0))
-                       {
-                               send_s870(h);
-                       }
-                       /*
-                        *      Done
-                        */
-                       dev->in_int = 0;
-                       return;
-               }
-
-               if (i == 0x40)
-               {
-                    dev->last_cmd |= 0x40;
-                    dev->in_int = 0;
-                    return;
-               }
-
-               if (i == 0x21)
-               {
-                       if ((dev->last_cmd & 0xf0) != 0x40)
-                       {
-                          dev->last_cmd = 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;
-                       tmport -= 0x04;
-                       outb(0x41, tmport);
-                       tmport += 0x08;
-                       outb(0x08, tmport);
-                       dev->in_int = 0;
-                       return;
-               }
-               if ((i == 0x80) || (i == 0x8f))
-               {
-                       lun = 0;
-                       tmport -= 0x07;
-                       j = inb(tmport);
-                       if (j == 0x44 || i==0x80) {
-                               tmport += 0x0d;
-                               lun = inb(tmport) & 0x07;
-                       } else {
-                               if ((dev->last_cmd & 0xf0) != 0x40)
-                               {
-                                  dev->last_cmd = 0xff;
-                               }
-                               if (j == 0x41)
-                               {
-                                       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;
-                                       tmport += 0x04;
-                                       outb(0x08, tmport);
-                                       dev->in_int = 0;
-                                       return;
-                               }
-                               else
-                               {
-                                       outb(0x46, tmport);
-                                       dev->id[target_id].dirctu = 0x00;
-                                       tmport += 0x02;
-                                       outb(0x00, tmport++);
-                                       outb(0x00, tmport++);
-                                       outb(0x00, tmport++);
-                                       tmport += 0x03;
-                                       outb(0x08, tmport);
-                                       dev->in_int = 0;
-                                       return;
-                               }
-                       }
-                       if (dev->last_cmd != 0xff)
-                       {
-                          dev->last_cmd |= 0x40;
-                       }
-                       tmport = workportu + 0x10;
-                       outb(0x45, tmport);
-                       tmport += 0x06;
-                       target_id = inb(tmport);
-                       /*
-                        *      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;
-                       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(((unsigned char *) &k)[2], tmport++);
-                       outb(((unsigned char *) &k)[1], tmport++);
-                       outb(((unsigned char *) &k)[0], tmport++);
-                       /* Remap wide */
-                       j = target_id;
-                       if (target_id > 7) {
-                               j = (j & 0x07) | 0x40;
-                       }
-                       /* Add direction */
-                       j |= dev->id[target_id].dirctu;
-                       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);
-                          }
-                       }
-                       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((unsigned char)((inb(tmport) & 0x3f) | 0xc0),tmport);
-                          }
-                          else
-                          {
-                             outb((unsigned char)(inb(tmport) & 0x3f),tmport);
-                          }
-                       }
-
-                       tmport = workportu + 0x1b;
-                       j = 0;
-                       id = 1;
-                       id = id << target_id;
-                       /*
-                        *      Is this a wide device
-                        */
-                       if ((id & dev->wide_idu) != 0) {
-                               j |= 0x01;
-                       }
-                       outb(j, tmport);
-                       while ((inb(tmport) & 0x01) != j)
-                       {
-                          outb(j,tmport);
-                       }
-
-                       if (dev->id[target_id].last_lenu == 0) {
-                               tmport = workportu + 0x18;
-                               outb(0x08, tmport);
-                               dev->in_int = 0;
-                               return;
-                       }
-                       prd = dev->id[target_id].prd_posu;
-                       while (adrcntu != 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;
-                               } else {
-                                       adrcntu -= k;
-                                       dev->id[target_id].prdaddru += 0x08;
-                                       prd += 0x08;
-                                       if (adrcntu == 0) {
-                                               dev->id[target_id].prd_posu = 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;
-                       /*
-                        *      Check transfer direction
-                        */
-                       if (dev->id[target_id].dirctu != 0) {
-                               outb(0x08, tmport);
-                               outb(0x01, tmpcip);
-                               dev->in_int = 0;
-                               return;
-                       }
-                       outb(0x08, tmport);
-                       outb(0x09, tmpcip);
-                       dev->in_int = 0;
-                       return;
-               }
-
-               /*
-                *      Current scsi request on this target
-                */
-
-               workrequ = dev->id[target_id].curr_req;
-
-               if (i == 0x42) {
-                       if ((dev->last_cmd & 0xf0) != 0x40)
-                       {
-                          dev->last_cmd = 0xff;
-                       }
-                       errstus = 0x02;
-                       workrequ->result = errstus;
-                       goto go_42;
-               }
-               if (i == 0x16)
+               for (x = 0 ; x < 256 ; x++)
                {
-                       if ((dev->last_cmd & 0xf0) != 0x40)
-                       {
-                          dev->last_cmd = 0xff;
-                       }
-                       errstus = 0;
-                       tmport -= 0x08;
-                       errstus = inb(tmport);
-                       workrequ->result = errstus;
-go_42:
-                       /*
-                        *      Complete the command
-                        */
-                       spin_lock_irqsave(&io_request_lock, flags);
-                       (*workrequ->scsi_done) (workrequ);
-
-                       /*
-                        *      Clear it off the queue
-                        */
-                       dev->id[target_id].curr_req = 0;
-                       dev->working--;
-                       spin_unlock_irqrestore(&io_request_lock, flags);
-                       /*
-                        *      Take it back wide
-                        */
-                       if (dev->wide_idu != 0) {
-                               tmport = workportu + 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 (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) &&
-                           (dev->in_snd == 0))
-                       {
-                          send_s870(h);
-                       }
-                       dev->in_int = 0;
-                       return;
+                       Value16 = Inpw(baseIoAddress,0);
+                       *(pData+(x<<1))         = (unsigned char)Value16;
+                       *(pData+(x<<1)+1)       = (unsigned char)(Value16>>8);
                }
-               if ((dev->last_cmd & 0xf0) != 0x40)
-               {
-                  dev->last_cmd = 0xff;
-               }
-               if (i == 0x4f) {
-                       i = 0x89;
-               }
-               i &= 0x0f;
-               if (i == 0x09) {
-                       tmpcip = tmpcip + 4;
-                       outl(dev->id[target_id].prdaddru, tmpcip);
-                       tmpcip = tmpcip - 2;
-                       outb(0x06, tmpcip);
-                       outb(0x00, tmpcip);
-                       tmpcip = tmpcip - 2;
-                       tmport = workportu + 0x10;
-                       outb(0x41, tmport);
-                       dev->id[target_id].dirctu = 0x00;
-                       tmport += 0x08;
-                       outb(0x08, tmport);
-                       outb(0x09, tmpcip);
-                       dev->in_int = 0;
-                       return;
-               }
-               if (i == 0x08) {
-                       tmpcip = tmpcip + 4;
-                       outl(dev->id[target_id].prdaddru, tmpcip);
-                       tmpcip = tmpcip - 2;
-                       outb(0x06, tmpcip);
-                       outb(0x00, tmpcip);
-                       tmpcip = tmpcip - 2;
-                       tmport = workportu + 0x10;
-                       outb(0x41, tmport);
-                       tmport += 0x05;
-                       outb((unsigned char) (inb(tmport) | 0x20), tmport);
-                       dev->id[target_id].dirctu = 0x20;
-                       tmport += 0x03;
-                       outb(0x08, tmport);
-                       outb(0x01, tmpcip);
-                       dev->in_int = 0;
-                       return;
-               }
-               tmport -= 0x07;
-               if (i == 0x0a) {
-                       outb(0x30, tmport);
-               } else {
-                       outb(0x46, tmport);
-               }
-               dev->id[target_id].dirctu = 0x00;
-               tmport += 0x02;
-               outb(0x00, tmport++);
-               outb(0x00, tmport++);
-               outb(0x00, tmport++);
-               tmport += 0x03;
-               outb(0x08, tmport);
-               dev->in_int = 0;
-               return;
-       } else {
-//             tmport = workportu + 0x17;
-//             inb(tmport);
-//             dev->working = 0;
-               dev->in_int = 0;
-               return;
+               CSrb->result = 0x00;
        }
+       else
+       {
+               devext->hd_status[TargetId]=0x51;
+               CSrb->result=0x02;
+               devext->dskerr[TargetId]=0xB0; // 0B/00/00 aborted command
+       }
+       i = Inpb(baseIoAddress,7);
+//printk(",status:%02X\n",i);
+       devext->FG_SmartRead = 0;
+       goto interrupt_keep_going;
+   }
+//======================================//
+   if ((i != 0x50) && (i != 0x40))
+   {
+      k=Inpb(baseIoAddress,1);         
+//#ifdef DEBUG_SENSEKEY      
+      printk("\nATP86X: Ch %2lX ID %2X Error: status=%2X error reg=%2X\n",Ch,TargetId,i,k);
+//#endif      
+      if (k& 0x80)
+      {
+#ifdef DEBUG_SENSEKEY                  
+               printk("ATP86X: CRC Error:");
+#endif              
+               devext->dskerr[TargetId]=0x48;  // 04/08/03 CRC Error
+      }
+      else if (k&0x54)
+      {
+#ifdef DEBUG_SENSEKEY                  
+               printk("ATP86X: Media Error:");
+#endif              
+       if (CSrb->cmnd[0]==0x0A || CSrb->cmnd[0]==0x2A || CSrb->cmnd[0]==0x2E)
+       {
+               devext->dskerr[TargetId]=0x3C;  // 03/0C/00 Write Error
+// Get Error LBA here and fill into dskerr_LBA[TargetId]  48-bit or 28-bit
+                get_disk_err_LBA(devext,TargetId);
+       }
+       else if (CSrb->cmnd[0]==0x08 || CSrb->cmnd[0]==0x28 || CSrb->cmnd[0]==0x2F || 
+                CSrb->cmnd[0]==0x0B || CSrb->cmnd[0]==0x2B )
+       {
+               devext->dskerr[TargetId]=0x31;  // 03/11/00 Read Error                  
+// Get Error LBA here and fill into dskerr_LBA[TargetId]  48-bit or 28-bit
+                get_disk_err_LBA(devext,TargetId);
+       }
+       else devext->dskerr[TargetId]=0xB0; // 0B/00/00 aborted command         
+      }
+      else 
+      {
+//             devext->dskerr[TargetId]=0x51;
+               devext->dskerr[TargetId]=0xB0; // 0B/00/00 aborted command
+      }
+#ifdef DEBUG_SENSEKEY                  
+      printk("CDB=");
+      for (i=0;i<CSrb->cmd_len;i++ )
+       printk("%2X ",CSrb->cmnd[i]);
+      printk("\n");      
+#endif      
+      devext->hd_status[TargetId]=0x51;
+      CSrb->result=0x02;
+   }
+   else
+   {
+      CSrb->result = 0x00;
+   }
+// add for smart read  =================//
+interrupt_keep_going:
+//======================================//
+
+   spin_lock_irqsave(&io_request_lock, flags);
+   (*CSrb->scsi_done) (CSrb);
+   devext->CSrb[Ch]=0;
+   if (devext->que_hd[Ch] != devext->que_end[Ch])
+   {
+      if ((devext->que_hd[Ch] += 1) > qcnt1 - 1)
+      {
+        devext->que_hd[Ch]=0;
+      }
+      devext->CSrb[Ch]=devext->QSrb[Ch][devext->que_hd[Ch]];
+      devext->Cplsrb[Ch]=devext->plsrb[Ch][devext->que_hd[Ch]];
+      SendScsi(devext,devext->CSrb[Ch],Ch);
+   }
+   spin_unlock_irqrestore(&io_request_lock, flags);
+   devext->in_int--;
+   return;
 }
 
-int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done) (Scsi_Cmnd *))
+int atp86x_queuecommand(Scsi_Cmnd * req_p, void (*done) (Scsi_Cmnd *))
 {
-       unsigned char h;
-       unsigned long flags;
-       unsigned short int m;
-       unsigned int tmport;
-       struct atp_unit *dev;
+       UCHAR h;
+       ULONG flags,Ch;
+       struct hw_device_ext *devext;
 
        for (h = 0; h <= admaxu; h++) {
-               if (req_p->host == atp_host[h]) {
+               if (req_p->host == a867host[h]) {
                        goto host_ok;
                }
        }
        return 0;
 host_ok:
-       if (req_p->channel != 0) {
-               req_p->result = 0x00040000;
+       if (!done) {
+               printk(KERN_WARNING "atp86x_queuecommand: done can't be NULL\n");
+               req_p->result = 0;
                done(req_p);
                return 0;
        }
-       dev = &atp_unit[h];
-       m = 1;
-       m = m << req_p->target;
-
-       /*
-        *      Fake a timeout for missing targets
-        */
-
-       if ((m & dev->active_idu) == 0) {
+       if (req_p->channel != 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");
-               req_p->result = 0;
-               done(req_p);
-               return 0;
-       }
-       /*
-        *      Count new command
-        */
        save_flags(flags);
        cli();
-       dev->quendu++;
-       if (dev->quendu >= qcnt) {
-               dev->quendu = 0;
+       devext = &dev_ext[h];
+       req_p->scsi_done = done;
+
+       if (!S860Io(devext,req_p))
+       {
+          restore_flags(flags);
+          return 0;
        }
-       /*
-        *      Check queue state
-        */
-       if (dev->quhdu == dev->quendu) {
-               if (dev->quendu == 0) {
-                       dev->quendu = qcnt;
-               }
-               dev->quendu--;
-               req_p->result = 0x00020000;
-               done(req_p);
-               restore_flags(flags);
-               return 0;
+       if (devext->in_int == 0)
+       {
+          Ch = (ULONG)(req_p->target >> 1);
+          if ((devext->CSrb[Ch] == 0) &&
+              (devext->que_hd[Ch] != devext->que_end[Ch]))
+          {
+             if ( devext->que_hd[Ch] == qcnt1 - 1 )
+             {
+                devext->que_hd[Ch]=0;
+             }
+             else
+             {
+                devext->que_hd[Ch]++;
+             }
+             devext->CSrb[Ch]=devext->QSrb[Ch][devext->que_hd[Ch]];
+             devext->Cplsrb[Ch]=devext->plsrb[Ch][devext->que_hd[Ch]];
+             SendScsi(devext,devext->CSrb[Ch],Ch);
+          }
        }
-       dev->querequ[dev->quendu] = req_p;
-       tmport = dev->ioport + 0x1c;
        restore_flags(flags);
-       if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) {
-               send_s870(h);
-       }
        return 0;
 }
 
-void mydlyu(unsigned int dlycnt)
+int S860Io(struct hw_device_ext * devext, Scsi_Cmnd * Srb)
 {
-       unsigned int i;
-       for (i = 0; i < dlycnt; i++) {
-               inb(0x80);
-       }
+    struct hw_lu_ext *srbp;
+    UCHAR i,j,t;
+#ifdef QUEUECOMMAND_DEBUG      
+       printk("S860IO: Srb->lun= %2X devext->dev_id= %2X\n",Srb->lun,devext->dev_id);
+#endif
+    if ( Srb->lun > 0 )
+    {
+       Srb->result = 0x00040000;
+       Srb->scsi_done(Srb);
+       return FALSE;
+    }
+    t = Srb->target;
+    if (devext->dev_id == ATP867_DEVID1)
+    {
+       if ((t > 7) || (devext->cap[t] == 0))
+       {
+                       Srb->result = 0x00040000;
+                       Srb->scsi_done(Srb);
+                       return FALSE;
+               }
+    }
+    else
+    {
+#ifdef QUEUECOMMAND_DEBUG      
+       printk("S860IO: t= %2X devext->cap[t]= %8lX\n",t,devext->cap[t]);
+#endif
+       if ((t > 4) || (devext->cap[t] == 0))
+       {
+                       Srb->result = 0x00040000;
+                       Srb->scsi_done(Srb);
+                       return FALSE;
+               }       
+    }
+#ifdef QUEUECOMMAND_DEBUG      
+       printk("S860IO: Srb->cmnd[0] = %2X hd_status[t]= %2X\n",Srb->cmnd[0],devext->hd_status[t]);
+#endif    
+    j=Srb->cmnd[0];
+    if ((j == 0x28) || (j == 0x2a) || (j == 0x2e)|| (j == 0x08) ||
+       (j == 0x0a) || (j == 0x2b) || (j == 0x0b) ||
+       (j == 0x35) || (j == 0x2f) || (j == 0x1b))
+    {
+       if (devext->hd_status[t] == 0x7f)
+       {
+         Srb->result = 0x02;
+         Srb->scsi_done(Srb);
+         return FALSE;
+       }
+
+       i = t >> 1;
+       if ((devext->que_end[i] += 1) > qcnt1 - 1)
+       {
+         devext->que_end[i]=0;
+       }
+       devext->QSrb[i][devext->que_end[i]]=Srb;
+       srbp=devext->plsrb[i][devext->que_end[i]];
+       BuildSrb(devext, srbp ,Srb);
+       return TRUE;
+    }
+    else
+    {
+       Noiocmd(devext,Srb);
+       Srb->scsi_done(Srb);
+    }
+    return FALSE;
 }
 
-void send_s870(unsigned char h)
+int BuildSrb(struct hw_device_ext * devext, struct hw_lu_ext * srbp, Scsi_Cmnd * Srb)
 {
-       unsigned int tmport;
-       Scsi_Cmnd *workrequ;
-       unsigned long flags;
-       unsigned int i;
-       unsigned char j, target_id;
-       unsigned char *prd;
-       unsigned short int tmpcip, w;
-       unsigned long l, bttl;
-       unsigned int workportu;
-       struct scatterlist *sgpnt;
-       struct atp_unit *dev = &atp_unit[h];
 
-       save_flags(flags);
-       cli();
-       if (dev->in_snd != 0) {
-               restore_flags(flags);
-               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;
-                  restore_flags(flags);
-                  return ;
-               }
-       }
-       if ((dev->last_cmd != 0xff) && (dev->working != 0))
-       {
-            dev->in_snd = 0;
-            restore_flags(flags);
-            return ;
-       }
-       dev->working++;
-       j = dev->quhdu;
-       dev->quhdu++;
-       if (dev->quhdu >= qcnt) {
-               dev->quhdu = 0;
-       }
-       workrequ = dev->querequ[dev->quhdu];
-       if (dev->id[workrequ->target].curr_req == 0) {
-               dev->id[workrequ->target].curr_req = workrequ;
-               dev->last_cmd = workrequ->target;
-               goto cmd_subp;
-       }
-       dev->quhdu = j;
-       dev->working--;
-       dev->in_snd = 0;
-       restore_flags(flags);
-       return;
-cmd_subp:
-       workportu = dev->ioport;
-       tmport = workportu + 0x1f;
-       if ((inb(tmport) & 0xb0) != 0) {
-               goto abortsnd;
-       }
-       tmport = workportu + 0x1c;
-       if (inb(tmport) == 0) {
-               goto oktosend;
-       }
-abortsnd:
-       dev->last_cmd |= 0x40;
-       dev->in_snd = 0;
-       restore_flags(flags);
-       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;
-               }
-       }
-       if (dev->ata_cdbu[0] == 0x00) {
-               workrequ->request_bufflen = 0;
-       }
+   if (Srb->cmd_len == 0x06)
+   {
+      ((PUCHAR)&srbp->wslba)[0]=Srb->cmnd[3];
+      ((PUCHAR)&srbp->wslba)[1]=Srb->cmnd[2];
+      ((PUCHAR)&srbp->wslba)[2]=Srb->cmnd[1];
+      ((PUCHAR)&srbp->wslba)[3]=Srb->cmnd[0];
+      srbp->wslba &= 0x000fffff;
+      srbp->wsblkno=Srb->cmnd[4];
+      srbp->wsblkno &=0x00ff;
+   }
+   else
+   {
+      ((PUCHAR)&srbp->wslba)[0]=Srb->cmnd[5];
+      ((PUCHAR)&srbp->wslba)[1]=Srb->cmnd[4];
+      ((PUCHAR)&srbp->wslba)[2]=Srb->cmnd[3];
+      ((PUCHAR)&srbp->wslba)[3]=Srb->cmnd[2];
+#ifdef IXP42X_SUPPORT
+      srbp->wsblkno = Srb->cmnd[8];
+      if (Srb->cmnd[7]!=0) srbp->wsblkno |= (USHORT)(Srb->cmnd[7]<<8);
+#else      
+      ((PUCHAR)&srbp->wsblkno)[0]=Srb->cmnd[8];
+      ((PUCHAR)&srbp->wsblkno)[1]=Srb->cmnd[7];
+#endif      
+   }
+#ifdef IXP42X_DEBUG_MSG      
+      printk("BuildSrb: c[0]=%2X c[1]=%2X c[2]=%2X c[3]=%2X c[4]=%2X c[5]=%2x lba=%8lx\n",Srb->cmnd[0],Srb->cmnd[1],
+                     Srb->cmnd[2],Srb->cmnd[3],Srb->cmnd[4],Srb->cmnd[5],srbp->wslba);
+      printk("BuildSrb: c[6]=%2X c[7]=%2X c[8]=%2X blkno=%4X\n",Srb->cmnd[6],Srb->cmnd[7],Srb->cmnd[8],srbp->wsblkno);
+#endif 
+   return (Raid05(devext,srbp,Srb));
+}
 
-       tmport = workportu + 0x1b;
-       j = 0;
-       target_id = workrequ->target;
+int Raid05(struct hw_device_ext * devext, struct hw_lu_ext * srbp, Scsi_Cmnd * Srb)
+{
+   ULONG  baddr;
+   ULONG  maplen;
+   ULONG  leng,l1;
+#ifdef IXP42X_DEBUG_MSG      
+   ULONG  l2;
+#endif   
+   struct scatterlist *sgpnt;
+   UCHAR  i;
+
+   sgpnt = (struct scatterlist *) Srb->request_buffer;
+   if (Srb->use_sg)
+   {
+          leng = 0;
+          for (i = 0; i < Srb->use_sg; i++)
+          {
+                  if (sgpnt[i].length == 0 || Srb->use_sg > ATP86X_SCATTER)
+                  {
+                          panic("Foooooooood fight!");
+                  }
+                  leng += sgpnt[i].length;
+          }
+   } else {
+          leng = Srb->request_bufflen;
+   }
+   if ((leng != 0x00) && (Srb->cmnd[0] != 0x2f))
+   {
+      l1=0;
+      i=0;
+      while ( leng > 0 )
+      {
+        if (Srb->use_sg)
+        {
+           baddr = virt_to_bus(sgpnt[i].address);
+           maplen = sgpnt[i++].length;
+        } else {
+           baddr = virt_to_bus(Srb->request_buffer);
+           maplen = Srb->request_bufflen;
+        }
+        if ( maplen > leng )
+        {
+           maplen=leng;
+        }
+#ifdef IXP42X_SUPPORT
+         srbp->prd[l1]=(UCHAR)baddr;
+         srbp->prd[l1+1]=(UCHAR)(baddr>>8);     
+         srbp->prd[l1+2]=(UCHAR)(baddr>>16);
+         srbp->prd[l1+3]=(UCHAR)(baddr>>24);
+         l1+=4;
+#else         
+        ((PULONG)srbp->prd)[l1++]=baddr;
+#endif  
+next_64k:
+#ifdef IXP42X_DEBUG_MSG                
+       printk("RAID05: Srb->use_sg = %4X l1=%2lX maplen=%8lX baddr=%8lX\n",Srb->use_sg,l1,maplen,baddr);
+#endif                          
+        if ( maplen > 0x10000 )
+        {
+#ifdef IXP42X_SUPPORT          
+            srbp->prd[l1]=0;
+            srbp->prd[l1+1]=0;  
+            srbp->prd[l1+2]=0;
+            srbp->prd[l1+3]=0;
+            l1+=4;
+#else                                          
+           ((PULONG)srbp->prd)[l1++]=0;
+#endif             
+           maplen -= 0x10000;
+           leng -= 0x10000;
+           baddr += 0x10000;
+#ifdef IXP42X_SUPPORT
+            srbp->prd[l1]=(UCHAR)baddr;
+            srbp->prd[l1+1]=(UCHAR)(baddr>>8);  
+            srbp->prd[l1+2]=(UCHAR)(baddr>>16);
+            srbp->prd[l1+3]=(UCHAR)(baddr>>24);
+            l1+=4;
+#else              
+           ((PULONG)srbp->prd)[l1++]=baddr;
+#endif                     
+           goto next_64k;
+        }
+        leng -= maplen;
+#ifdef IXP42X_SUPPORT
+         srbp->prd[l1]=(UCHAR)maplen;
+         srbp->prd[l1+1]=(UCHAR)(maplen>>8);    
+         srbp->prd[l1+2]=0;
+         srbp->prd[l1+3]=0;     
+         l1+=4;
+#else                   
+        ((PULONG)srbp->prd)[l1++]=maplen;
+#endif                          
+      }
+#ifdef IXP42X_SUPPORT      
+      l1--;
+      srbp->prd[l1]=0x80;
+#else                                 
+      l1=((l1 << 2) - 2) >> 1;
+      ((PUSHORT)srbp->prd)[l1]=0x8000;
+#endif                          
+   }
+#ifdef IXP42X_DEBUG_MSG      
+   for (l1=0;l1<=Srb->use_sg;l1++)
+   {
+      printk("l1= %2lX ",l1);
+      for (l2=l1*8;l2<(l1*8+8);l2++)
+      {
+       printk("[%2lX]= %2X ",l2,(UCHAR) (srbp->prd[l2]));
+      }
+      printk("\n");
+   }
+#endif            
+   return TRUE ;
+}
 
-       /*
-        *      Wide ?
-        */
-       w = 1;
-       w = w << target_id;
-       if ((w & dev->wide_idu) != 0) {
-               j |= 0x01;
-       }
-       outb(j, tmport);
-       while ((inb(tmport) & 0x01) != j)
-       {
-          outb(j,tmport);
-       }
+int SendScsi(struct hw_device_ext * devext, Scsi_Cmnd * Srb, ULONG Ch)
+{
+   ULONG baseIoAddress = devext->BaseIoAddress[Ch];
+   ULONG baseIoAddresm = devext->BaseIoAddresm[Ch];
+   struct hw_lu_ext * srbp;
+   ULONG  t;
+#ifndef IXP42X_SUPPORT   
+   USHORT k;
+#endif   
+   UCHAR  devno;
+
+#ifdef QUEUECOMMAND_DEBUG
+   printk("SendSCSI: Ch=%2lX Tarrget=%2X CDB[0]= %2X  \n",Ch,Srb->target,Srb->cmnd[0]);
+#endif
+   srbp=devext->Cplsrb[Ch];
+
+   Outpb(baseIoAddresm,2,0x06);
+
+   t = (ULONG)Srb->target;
+   if ((t & 1) == 0)
+   {
+      devno=0xe0;
+   }
+   else
+   {
+      devno=0xf0;
+   }
+   Outpb(baseIoAddress,6,devno);
+// add for smart read  =================//
+   if (Srb->cmnd[0] == 0xB0)
+   {
+       Outpb(baseIoAddress,1,0xD0);
+       Outpb(baseIoAddress,4,0x4F);
+       Outpb(baseIoAddress,5,0xC2);
+       Outpb(baseIoAddress,7,0xB0);
+       return TRUE;
+   }
+//=====================================//
+   if ((Srb->cmnd[0] == 0x28) || (Srb->cmnd[0] == 0x2a) || (Srb->cmnd[0] == 0x2e) || 
+       (Srb->cmnd[0] == 0x08) || (Srb->cmnd[0] == 0x0a))
+   {
+      Outpl(baseIoAddresm,4,srbp->prdaddr);
+#ifdef IXP42X_SUPPORT      
+      if (devext->bigdrv[t] == 0)
+      {
+        if ((Srb->cmnd[0] == 0x2a) || (Srb->cmnd[0] == 0x0a) || (Srb->cmnd[0] == 0x2e))
+        {
+           Sendnorm(baseIoAddress,baseIoAddresm,srbp->wslba,(UCHAR)srbp->wsblkno,0x01,0xca);       
+        }
+        else
+        {
+           Sendnorm(baseIoAddress,baseIoAddresm,srbp->wslba,(UCHAR)srbp->wsblkno,0x09,0xc8);       
+        }
+      }
+      else
+      {
+        if ((Srb->cmnd[0] == 0x2a) || (Srb->cmnd[0] == 0x0a)|| (Srb->cmnd[0] == 0x2e))
+        {
+           Sendbigd(baseIoAddress,baseIoAddresm,srbp->wslba,srbp->wsblkno,0x01,0x35);      
+        }
+        else
+        {
+           Sendbigd(baseIoAddress,baseIoAddresm,srbp->wslba,srbp->wsblkno,0x09,0x25);
+        }
+      }         
+#else          
+      if (devext->bigdrv[t] == 0)
+      {
+        if ((Srb->cmnd[0] == 0x2a) || (Srb->cmnd[0] == 0x0a) || (Srb->cmnd[0] == 0x2e))
+        {
+           k=0x01ca;
+        }
+        else
+        {
+           k=0x09c8;
+        }
+        Sendnorm(baseIoAddress,baseIoAddresm,srbp->wslba,srbp->wsblkno,k);
+      }
+      else
+      {
+        if ((Srb->cmnd[0] == 0x2a) || (Srb->cmnd[0] == 0x0a)|| (Srb->cmnd[0] == 0x2e))
+        {
+           k=0x0135;
+        }
+        else
+        {
+           k=0x0925;
+        }
+        Sendbigd(baseIoAddress,baseIoAddresm,srbp->wslba,srbp->wsblkno,k);
+      }         
+#endif  
+
+      return TRUE;
+   }
+
+   if (Srb->cmnd[0] == 0x35)
+   {
+      if (devext->bigdrv[t] == 0)
+      {
+        Outpb(baseIoAddress,7,0xe7);
+      }
+      else
+      {
+        Outpb(baseIoAddress,7,0xea);
+      }
+      return TRUE ;
+   }
+
+   if (Srb->cmnd[0] == 0x1b)
+   {
+      if (Srb->cmnd[4] == 0x00)
+      {
+#ifdef IXP42X_SUPPORT          
+        Sendnorm(baseIoAddress,baseIoAddresm,0,0,0x00,0xe0);
+#else          
+        Sendnorm(baseIoAddress,baseIoAddresm,0,0,0x00e0);
+#endif  
+      }
+      else
+      {
+#ifdef IXP42X_SUPPORT          
+        Sendnorm(baseIoAddress,baseIoAddresm,0,0x40,0x00,0x40);
+#else          
+        Sendnorm(baseIoAddress,baseIoAddresm,0,0x40,0x40);
+#endif  
+      }
+      return TRUE ;
+   }
+
+   if ((Srb->cmnd[0] == 0x0b) || (Srb->cmnd[0] == 0x2b))
+   {
+      if (devext->bigdrv[t] == 0)
+      {
+#ifdef IXP42X_SUPPORT          
+        Sendnorm(baseIoAddress,baseIoAddresm,srbp->wslba,1,0x00,0x70);
+#else          
+        Sendnorm(baseIoAddress,baseIoAddresm,srbp->wslba,1,0x70);
+#endif  
+      }
+      else
+      {
+#ifdef IXP42X_SUPPORT
+        Sendbigd(baseIoAddress,baseIoAddresm,srbp->wslba,1,0X00,0x42);
+#else          
+        Sendbigd(baseIoAddress,baseIoAddresm,srbp->wslba,1,0x42);
+#endif
+      }
+      return TRUE ;
+   }
+
+   if (Srb->cmnd[0] == 0x2f)
+   {
+      if (devext->bigdrv[t] == 0)
+      {
+#ifdef IXP42X_SUPPORT          
+        Sendnorm(baseIoAddress,baseIoAddresm,srbp->wslba,(UCHAR) srbp->wsblkno,0x00,0x40);
+#else          
+        Sendnorm(baseIoAddress,baseIoAddresm,srbp->wslba,srbp->wsblkno,0x40);
+#endif  
+      }
+      else
+      {
+#ifdef IXP42X_SUPPORT
+        Sendbigd(baseIoAddress,baseIoAddresm,srbp->wslba,srbp->wsblkno,0x00,0x42);
+#else          
+        Sendbigd(baseIoAddress,baseIoAddresm,srbp->wslba,srbp->wsblkno,0x42);
+#endif  
+      }
+   }
+   return TRUE ;
+}
 
-       /*
-        *      Write the command
-        */
+#ifdef IXP42X_SUPPORT
+void Sendnorm(ULONG baseIoAddress, ULONG baseIoAddresm, ULONG wklba, UCHAR wkblkno, UCHAR pcicmd, UCHAR cmd)
+{
+      UCHAR  i;
+
+      outb(wkblkno, baseIoAddress + 2);
+#ifdef IXP42X_DEBUG_MSG            
+      printk("Sendnorm: 1X2 wkblkno=%2X \n",wkblkno);
+#endif      
+      outb(((PUCHAR)&wklba)[0], baseIoAddress+3);
+#ifdef IXP42X_DEBUG_MSG                  
+      printk("Sendnorm: 1X3 = %2X \n",((PUCHAR)&wklba)[0]);
+#endif      
+      outb(((PUCHAR)&wklba)[1], baseIoAddress+4);
+#ifdef IXP42X_DEBUG_MSG                  
+      printk("Sendnorm: 1X4 = %2X \n",((PUCHAR)&wklba)[1]);
+#endif      
+      outb(((PUCHAR)&wklba)[2], baseIoAddress+5);
+#ifdef IXP42X_DEBUG_MSG                  
+      printk("Sendnorm: 1X5 = %2X \n",((PUCHAR)&wklba)[2]);
+#endif      
+      i=((PUCHAR)&wklba)[3] & 0x0f;
+
+      outb((UCHAR)((inb(baseIoAddress+6) & 0xf0) | i), baseIoAddress+6);
+#ifdef IXP42X_DEBUG_MSG                        
+      printk("Sendnorm: 1X6 = %2X \n",inb(baseIoAddress+6));
+#endif      
+      outb(cmd, baseIoAddress+7);
+#ifdef IXP42X_DEBUG_MSG                        
+      printk("Sendnorm: 1X7 = %2X \n",cmd);
+#endif            
+      outb(pcicmd, baseIoAddresm);
+#ifdef IXP42X_DEBUG_MSG                        
+      printk("Sendnorm: PCI cmd = %2X \n",pcicmd);
+#endif                  
+      return;
+}
 
-       tmport = workportu;
-       outb(workrequ->cmd_len, tmport++);
-       outb(0x2c, tmport++);
-       outb(0xcf, tmport++);
-       for (i = 0; i < workrequ->cmd_len; i++) {
-               outb(dev->ata_cdbu[i], tmport++);
-       }
-       tmport = workportu + 0x0f;
-       outb(workrequ->lun, tmport);
-       tmport += 0x02;
-       /*
-        *      Write the target
-        */
-       outb(dev->id[target_id].devspu, tmport++);
+void Sendbigd(ULONG baseIoAddress, ULONG baseIoAddresm, ULONG wklba, USHORT wkblkno, UCHAR pcicmd, UCHAR cmd)
+{
+//      outb(((PUCHAR)&wkblkno)[1], baseIoAddress+2);
+      outb((UCHAR)(wkblkno>>8),baseIoAddress+2);
+#ifdef IXP42X_DEBUG_MSG            
+      printk("Sendbigd: 1X2 =%2X  wkblkno=%2X\n",(UCHAR)(wkblkno>>8),wkblkno);
+#endif            
+//      outb(((PUCHAR)&wkblkno)[0], baseIoAddress+2);
+      outb((UCHAR)(wkblkno),baseIoAddress+2);
+#ifdef IXP42X_DEBUG_MSG            
+      printk("Sendbigd: 1X2 =%2X  wkblkno=%2X\n",(UCHAR)(wkblkno),wkblkno);
+#endif                  
+      outb(((PUCHAR)&wklba)[3], baseIoAddress+3);
+#ifdef IXP42X_DEBUG_MSG            
+      printk("Sendbigd: 1X3 =%2X \n",((PUCHAR)&wklba)[3]);
+#endif                        
+      outb(0, baseIoAddress+4);
+#ifdef IXP42X_DEBUG_MSG            
+      printk("Sendbigd: 1X4 =0 \n");
+#endif                              
+      outb(0, baseIoAddress+5);
+#ifdef IXP42X_DEBUG_MSG            
+      printk("Sendbigd: 1X5 =0 \n");
+#endif                                   
+      outb(((PUCHAR)&wklba)[0], baseIoAddress+3);
+#ifdef IXP42X_DEBUG_MSG            
+      printk("Sendbigd: 1X3 =%2X \n",((PUCHAR)&wklba)[0]);
+#endif                              
+      outb(((PUCHAR)&wklba)[1], baseIoAddress+4);
+#ifdef IXP42X_DEBUG_MSG            
+      printk("Sendbigd: 1X4 =%2X \n",((PUCHAR)&wklba)[1]);
+#endif                                   
+      outb(((PUCHAR)&wklba)[2], baseIoAddress+5);
+#ifdef IXP42X_DEBUG_MSG            
+      printk("Sendbigd: 1X5 =%2X \n",((PUCHAR)&wklba)[2]);
+#endif                                   
+      outb(cmd, baseIoAddress+7);
+#ifdef IXP42X_DEBUG_MSG            
+      printk("Sendbigd: 1X7 =%2X \n",cmd);
+#endif                                   
+      outb(pcicmd, baseIoAddresm);
+#ifdef IXP42X_DEBUG_MSG            
+      printk("Sendbigd: pcicmd =%2X \n",pcicmd);
+#endif                                   
+      return;
+}
 
-       /*
-        *      Figure out the transfer size
-        */
-       if (workrequ->use_sg)
-       {
-               l = 0;
-               sgpnt = (struct scatterlist *) workrequ->request_buffer;
-               for (i = 0; i < workrequ->use_sg; i++)
-               {
-                       if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER)
-                       {
-                               panic("Foooooooood fight!");
-                       }
-                       l += sgpnt[i].length;
-               }
-       } else {
-               l = workrequ->request_bufflen;
-       }
-       /*
-        *      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;
-       /*
-        *      Flip the wide bits
-        */
-       if ((j & 0x08) != 0) {
-               j = (j & 0x07) | 0x40;
-       }
-       /*
-        *      Check transfer direction
-        */
-       if ((dev->ata_cdbu[0] == WRITE_6) || (dev->ata_cdbu[0] == WRITE_10) ||
-           (dev->ata_cdbu[0] == WRITE_12) || (dev->ata_cdbu[0] == MODE_SELECT)) {
-               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;
-       if (l == 0) {
-               if (inb(tmport) == 0) {
-                       tmport = workportu + 0x18;
-                       outb(0x08, tmport);
-               } else {
-                       dev->last_cmd |= 0x40;
-               }
-               dev->in_snd = 0;
-               restore_flags(flags);
-               return;
-       }
-       tmpcip = dev->pciport;
-       prd = dev->id[target_id].prd_tableu;
-       dev->id[target_id].prd_posu = prd;
+#else
 
-       /*
-        *      Now write the request list. Either as scatter/gather or as
-        *      a linear chain.
-        */
+void Sendnorm(ULONG baseIoAddress, ULONG baseIoAddresm, ULONG wklba, USHORT wkblkno, USHORT cmd)
+{
+      UCHAR  i;
+
+      outb((UCHAR)wkblkno, baseIoAddress + 2);
+      outb(((PUCHAR)&wklba)[0], baseIoAddress+3);
+      outb(((PUCHAR)&wklba)[1], baseIoAddress+4);
+      outb(((PUCHAR)&wklba)[2], baseIoAddress+5);
+      i=((PUCHAR)&wklba)[3] & 0x0f;
+      outb((UCHAR)((inb(baseIoAddress+6) & 0xf0) | i), baseIoAddress+6);
+      outb(((PUCHAR)&cmd)[0], baseIoAddress+7);
+      outb(((PUCHAR)&cmd)[1], baseIoAddresm);
+      return;
+}
+void Sendbigd(ULONG baseIoAddress, ULONG baseIoAddresm, ULONG wklba, USHORT wkblkno, USHORT cmd)
+{
+      outb(((PUCHAR)&wkblkno)[1], baseIoAddress+2);
+      outb(((PUCHAR)&wkblkno)[0], baseIoAddress+2);
+      outb(((PUCHAR)&wklba)[3], baseIoAddress+3);
+      outb(0, baseIoAddress+4);
+      outb(0, baseIoAddress+5);
+      outb(((PUCHAR)&wklba)[0], baseIoAddress+3);
+      outb(((PUCHAR)&wklba)[1], baseIoAddress+4);
+      outb(((PUCHAR)&wklba)[2], baseIoAddress+5);
+      outb(((PUCHAR)&cmd)[0], baseIoAddress+7);
+      outb(((PUCHAR)&cmd)[1], baseIoAddresm);
+      return;
+}
 
-       if (workrequ->use_sg)
-       {
-               sgpnt = (struct scatterlist *) workrequ->request_buffer;
-               i = 0;
-               for (j = 0; j < workrequ->use_sg; j++) {
-                       bttl = virt_to_bus(sgpnt[j].address);
-                       l = sgpnt[j].length;
-                       while (l > 0x10000) {
-                               (((unsigned short int *) (prd))[i + 3]) = 0x0000;
-                               (((unsigned short int *) (prd))[i + 2]) = 0x0000;
-                               (((unsigned long *) (prd))[i >> 1]) = bttl;
-                               l -= 0x10000;
-                               bttl += 0x10000;
-                               i += 0x04;
-                       }
-                       (((unsigned long *) (prd))[i >> 1]) = bttl;
-                       (((unsigned short int *) (prd))[i + 2]) = l;
-                       (((unsigned short int *) (prd))[i + 3]) = 0;
-                       i += 0x04;
-               }
-               (((unsigned short int *) (prd))[i - 1]) = 0x8000;
-       } else {
-               /*
-                *      For a linear request write a chain of blocks
-                */
-               bttl = virt_to_bus(workrequ->request_buffer);
-               l = workrequ->request_bufflen;
-               i = 0;
-               while (l > 0x10000) {
-                       (((unsigned short int *) (prd))[i + 3]) = 0x0000;
-                       (((unsigned short int *) (prd))[i + 2]) = 0x0000;
-                       (((unsigned long *) (prd))[i >> 1]) = bttl;
-                       l -= 0x10000;
-                       bttl += 0x10000;
-                       i += 0x04;
-               }
-               (((unsigned short int *) (prd))[i + 3]) = 0x8000;
-               (((unsigned short int *) (prd))[i + 2]) = l;
-               (((unsigned long *) (prd))[i >> 1]) = bttl;
-       }
-       tmpcip = tmpcip + 4;
-       dev->id[target_id].prdaddru = virt_to_bus(dev->id[target_id].prd_tableu);
-       outl(dev->id[target_id].prdaddru, 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((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport);
-          }
-          else
-          {
-             outb((unsigned char)(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))
-          {
-             outb((unsigned char)((inb(tmport) & 0x3f) | 0xc0),tmport);
-          }
-          else
-          {
-             outb((unsigned char)(inb(tmport) & 0x3f),tmport);
-          }
-       }
-       tmport = workportu + 0x1c;
+#endif
 
-       if ((dev->ata_cdbu[0] == WRITE_6) || (dev->ata_cdbu[0] == WRITE_10) ||
-           (dev->ata_cdbu[0] == WRITE_12) || (dev->ata_cdbu[0] == MODE_SELECT))
-       {
-               dev->id[target_id].dirctu = 0x20;
-               if (inb(tmport) == 0) {
-                       tmport = workportu + 0x18;
-                       outb(0x08, tmport);
-                       outb(0x01, tmpcip);
-               } else {
-                       dev->last_cmd |= 0x40;
-               }
-               dev->in_snd = 0;
-               restore_flags(flags);
-               return;
-       }
-       if (inb(tmport) == 0)
-       {
-               tmport = workportu + 0x18;
-               outb(0x08, tmport);
-               outb(0x09, tmpcip);
-       } else {
-               dev->last_cmd |= 0x40;
-       }
-       dev->in_snd = 0;
-       restore_flags(flags);
-       return;
 
-}
 
 static void internal_done(Scsi_Cmnd * SCpnt)
 {
        SCpnt->SCp.Status++;
 }
 
-int atp870u_command(Scsi_Cmnd * SCpnt)
+int atp86x_command(Scsi_Cmnd * SCpnt)
 {
 
-       atp870u_queuecommand(SCpnt, internal_done);
+       atp86x_queuecommand(SCpnt, internal_done);
 
        SCpnt->SCp.Status = 0;
        while (!SCpnt->SCp.Status)
@@ -920,1768 +1137,1685 @@ int atp870u_command(Scsi_Cmnd * SCpnt)
        return SCpnt->result;
 }
 
-unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
+int fill_sensekey_buf(struct hw_device_ext * devext, UCHAR tid)
 {
-       unsigned int tmport;
-       unsigned short int i, k;
-       unsigned char j;
-
-       tmport = dev->ioport + 0x1c;
-       outw(*val, tmport);
-FUN_D7:
-       for (i = 0; i < 10; i++) {      /* stable >= bus settle delay(400 ns)  */
-               k = inw(tmport);
-               j = (unsigned char) (k >> 8);
-               if ((k & 0x8000) != 0) {        /* DB7 all release?    */
-                       goto FUN_D7;
-               }
-       }
-       *val |= 0x4000;         /* assert DB6           */
-       outw(*val, tmport);
-       *val &= 0xdfff;         /* assert DB5           */
-       outw(*val, tmport);
-FUN_D5:
-       for (i = 0; i < 10; i++) {      /* stable >= bus settle delay(400 ns) */
-               if ((inw(tmport) & 0x2000) != 0) {      /* DB5 all release?       */
-                       goto FUN_D5;
-               }
-       }
-       *val |= 0x8000;         /* no DB4-0, assert DB7    */
-       *val &= 0xe0ff;
-       outw(*val, tmport);
-       *val &= 0xbfff;         /* release DB6             */
-       outw(*val, tmport);
-      FUN_D6:
-       for (i = 0; i < 10; i++) {      /* stable >= bus settle delay(400 ns)  */
-               if ((inw(tmport) & 0x4000) != 0) {      /* DB6 all release?  */
-                       goto FUN_D6;
-               }
-       }
-
-       return j;
+       int i;
+       static UCHAR sensd[16]=   {0xF0,0,0x03,0,0,0,0,0x8,0,0,0,0,0x11,0x00,0,0};
+       static UCHAR sensdw[16]=  {0xF0,0,0x03,0,0,0,0,0x8,0,0,0,0,0x0C,0x00,0,0};      
+       static UCHAR sensda[16]=  {0x70,0,0x05,0,0,0,0,0x8,0,0,0,0,0x20,0x00,0,0};
+       static UCHAR sensdif[16]= {0x70,0,0x05,0,0,0,0,0x8,0,0,0,0,0x24,0x00,0,0};      
+       static UCHAR sensdip[16]= {0x70,0,0x05,0,0,0,0,0x8,0,0,0,0,0x26,0x00,0,0};
+       static UCHAR sensdor[16]= {0xF0,0,0x05,0,0,0,0,0x8,0,0,0,0,0x1A,0x00,0,0};      
+       static UCHAR sensdcrc[16]={0x70,0,0x04,0,0,0,0,0x8,0,0,0,0,0x08,0x03,0,0};
+       static UCHAR sensdabt[16]={0x70,0,0x0B,0,0,0,0,0x8,0,0,0,0,0x00,0x00,0,0};      
+       static UCHAR sensdok[16]= {0x70,0,0x00,0,0,0,0,0x8,0,0,0,0,0x00,0x00,0,0};
+               
+       switch (devext->dskerr[tid])
+       {
+               case 0x50:     
+                              for(i=0;i<16;i++) 
+                              {
+                                   devext->sensd[tid][i]=sensda[i];
+                              }
+                              break;
+               case 0x54:     
+                              for(i=0;i<16;i++) 
+                              {
+                                   devext->sensd[tid][i]=sensdif[i];
+                              }
+                              break;                                   
+               case 0x56:     
+                              for(i=0;i<16;i++) 
+                              {
+                                   devext->sensd[tid][i]=sensdip[i];
+                              }
+                              break;           
+               case 0x5A:     
+                              for(i=0;i<16;i++) 
+                              {
+                                   devext->sensd[tid][i]=sensdor[i];
+                              }
+                              goto fill_err_LBA;
+               case 0x31:     
+                              for(i=0;i<16;i++) 
+                              {
+                                   devext->sensd[tid][i]=sensd[i];
+                              }
+fill_err_LBA:                         
+                              devext->sensd[tid][3]=(UCHAR)((devext->dskerr_LBA[tid]>>24));
+                              devext->sensd[tid][4]=(UCHAR)((devext->dskerr_LBA[tid]>>16));
+                              devext->sensd[tid][5]=(UCHAR)((devext->dskerr_LBA[tid]>>8));
+                              devext->sensd[tid][6]=(UCHAR)(devext->dskerr_LBA[tid]);
+                              break;           
+               case 0x3C:     
+                              for(i=0;i<16;i++) 
+                              {
+                                   devext->sensd[tid][i]=sensdw[i];
+                              }
+                              goto fill_err_LBA;
+               case 0x48:     
+                              for(i=0;i<16;i++) 
+                              {
+                                   devext->sensd[tid][i]=sensdcrc[i];
+                              }
+                              break;           
+               case 0x00:     
+                              for(i=0;i<16;i++) 
+                              {
+                                   devext->sensd[tid][i]=sensdok[i];
+                              }
+                              break;                                      
+               case 0xB0:
+               default:
+                              for(i=0;i<16;i++) 
+                              {
+                                   devext->sensd[tid][i]=sensdabt[i];
+                              }
+                              break;
+       }
+#ifdef DEBUG_SENSEKEY
+                              printk("TID %2X SenseKey=",tid);
+                              for(i=0;i<16;i++) 
+                              {
+                                   printk("%2X ",devext->sensd[tid][i]);
+                              }
+                              printk("\n");                           
+#endif 
+       return 0;
 }
 
-void tscam(unsigned char host)
+//axl+
+unsigned char EnableSMART(struct hw_device_ext * devext)
 {
+       unsigned char   Value8;
+       
+       Outpb(devext->SamwiseBaseIoAddress, 6, devext->SamwiseHDSelect);
+       mdelay(10);
 
-       unsigned int tmport;
-       unsigned char i, j, k;
-       unsigned long n;
-       unsigned short int m, assignid_map, val;
-       unsigned char mbuf[33], quintet[2];
-       struct atp_unit *dev = &atp_unit[host];
-       static unsigned char g2q_tab[8] = {
-               0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
-       };
-
-
-       for (i = 0; i < 0x10; i++) {
-               mydlyu(0xffff);
+       Value8 = Inpb(devext->SamwiseBaseIoAddress, 7);
+       if((Value8 & 0x88) != 0x00)
+       {
+          return 1;
        }
 
-       tmport = dev->ioport + 1;
-       outb(0x08, tmport++);
-       outb(0x7f, tmport);
-       tmport = dev->ioport + 0x11;
-       outb(0x20, tmport);
+       /* ATA Identify device command */
+       Outpb(devext->SamwiseBaseIoAddress, 1, 0xd8);
+       Outpb(devext->SamwiseBaseIoAddress, 4, 0x4f);
+       Outpb(devext->SamwiseBaseIoAddress, 5, 0xc2);
+       Outpb(devext->SamwiseBaseIoAddress, 7, 0xb0);
+       mdelay(400);
 
-       if ((dev->scam_on & 0x40) == 0) {
-               return;
-       }
-       m = 1;
-       m <<= dev->host_idu;
-       j = 16;
-       if (dev->chip_veru < 4) {
-               m |= 0xff00;
-               j = 8;
+       while(1)
+       {
+       Value8 = Inpb(devext->SamwiseBaseIoAddress, 7);
+       if((Value8 & 0x80) == 0 )
+       {
+               break;
+       }
        }
-       assignid_map = m;
-       tmport = dev->ioport + 0x02;
-       outb(0x02, tmport++);   /* 2*2=4ms,3EH 2/32*3E=3.9ms */
-       outb(0, tmport++);
-       outb(0, tmport++);
-       outb(0, tmport++);
-       outb(0, tmport++);
-       outb(0, tmport++);
-       outb(0, tmport++);
-
-       for (i = 0; i < j; i++) {
-               m = 1;
-               m = m << i;
-               if ((m & assignid_map) != 0) {
-                       continue;
-               }
-               tmport = dev->ioport + 0x0f;
-               outb(0, tmport++);
-               tmport += 0x02;
-               outb(0, tmport++);
-               outb(0, tmport++);
-               outb(0, tmport++);
-               if (i > 7) {
-                       k = (i & 0x07) | 0x40;
-               } else {
-                       k = i;
-               }
-               outb(k, tmport++);
-               tmport = dev->ioport + 0x1b;
-               if (dev->chip_veru == 4) {
-                       outb(0x01, tmport);
-               } else {
-                       outb(0x00, tmport);
-               }
-wait_rdyok:
-               tmport = dev->ioport + 0x18;
-               outb(0x09, tmport);
-               tmport += 0x07;
-
-               while ((inb(tmport) & 0x80) == 0x00);
-               tmport -= 0x08;
-               k = inb(tmport);
-               if (k != 0x16) {
-                       if ((k == 0x85) || (k == 0x42)) {
-                               continue;
-                       }
-                       tmport = dev->ioport + 0x10;
-                       outb(0x41, tmport);
-                       goto wait_rdyok;
-               }
-               assignid_map |= m;
 
+       if ((Value8 & 0x01) == 0x01 )
+       {
+               return 2;
        }
-       tmport = dev->ioport + 0x02;
-       outb(0x7f, tmport);
-       tmport = dev->ioport + 0x1b;
-       outb(0x02, tmport);
-
-       outb(0, 0x80);
-
-       val = 0x0080;           /* bsy  */
-       tmport = dev->ioport + 0x1c;
-       outw(val, tmport);
-       val |= 0x0040;          /* sel  */
-       outw(val, tmport);
-       val |= 0x0004;          /* msg  */
-       outw(val, tmport);
-       inb(0x80);              /* 2 deskew delay(45ns*2=90ns) */
-       val &= 0x007f;          /* no bsy  */
-       outw(val, tmport);
-       mydlyu(0xffff);         /* recommanded SCAM selection response time */
-       mydlyu(0xffff);
-       val &= 0x00fb;          /* after 1ms no msg */
-       outw(val, tmport);
-wait_nomsg:
-       if ((inb(tmport) & 0x04) != 0) {
-               goto wait_nomsg;
-       }
-       outb(1, 0x80);
-       mydlyu(100);
-       for (n = 0; n < 0x30000; n++) {
-               if ((inb(tmport) & 0x80) != 0) {        /* bsy ? */
-                       goto wait_io;
-               }
-       }
-       goto TCM_SYNC;
-wait_io:
-       for (n = 0; n < 0x30000; n++) {
-               if ((inb(tmport) & 0x81) == 0x0081) {
-                       goto wait_io1;
-               }
-       }
-       goto TCM_SYNC;
-wait_io1:
-       inb(0x80);
-       val |= 0x8003;          /* io,cd,db7  */
-       outw(val, tmport);
-       inb(0x80);
-       val &= 0x00bf;          /* no sel     */
-       outw(val, tmport);
-       outb(2, 0x80);
-TCM_SYNC:
-       mydlyu(0x800);
-       if ((inb(tmport) & 0x80) == 0x00) {     /* bsy ? */
-               outw(0, tmport--);
-               outb(0, tmport);
-               tmport = dev->ioport + 0x15;
-               outb(0, tmport);
-               tmport += 0x03;
-               outb(0x09, tmport);
-               tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0);
-               tmport -= 0x08;
-               inb(tmport);
-               return;
-       }
-       val &= 0x00ff;          /* synchronization  */
-       val |= 0x3f00;
-       fun_scam(dev, &val);
-       outb(3, 0x80);
-       val &= 0x00ff;          /* isolation        */
-       val |= 0x2000;
-       fun_scam(dev, &val);
-       outb(4, 0x80);
-       i = 8;
-       j = 0;
-TCM_ID:
-       if ((inw(tmport) & 0x2000) == 0) {
-               goto TCM_ID;
-       }
-       outb(5, 0x80);
-       val &= 0x00ff;          /* get ID_STRING */
-       val |= 0x2000;
-       k = fun_scam(dev, &val);
-       if ((k & 0x03) == 0) {
-               goto TCM_5;
-       }
-       mbuf[j] <<= 0x01;
-       mbuf[j] &= 0xfe;
-       if ((k & 0x02) != 0) {
-               mbuf[j] |= 0x01;
-       }
-       i--;
-       if (i > 0) {
-               goto TCM_ID;
-       }
-       j++;
-       i = 8;
-       goto TCM_ID;
-
-TCM_5:                 /* isolation complete..  */
-/*    mbuf[32]=0;
-       printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
-       i = 15;
-       j = mbuf[0];
-       if ((j & 0x20) != 0) {  /* bit5=1:ID upto 7      */
-               i = 7;
-       }
-       if ((j & 0x06) == 0) {  /* IDvalid?             */
-               goto G2Q5;
-       }
-       k = mbuf[1];
-small_id:
-       m = 1;
-       m <<= k;
-       if ((m & assignid_map) == 0) {
-               goto G2Q_QUIN;
-       }
-       if (k > 0) {
-               k--;
-               goto small_id;
-       }
-G2Q5:                          /* srch from max acceptable ID#  */
-       k = i;                  /* max acceptable ID#            */
-G2Q_LP:
-       m = 1;
-       m <<= k;
-       if ((m & assignid_map) == 0) {
-               goto G2Q_QUIN;
-       }
-       if (k > 0) {
-               k--;
-               goto G2Q_LP;
-       }
-G2Q_QUIN:              /* k=binID#,       */
-       assignid_map |= m;
-       if (k < 8) {
-               quintet[0] = 0x38;      /* 1st dft ID<8    */
-       } else {
-               quintet[0] = 0x31;      /* 1st  ID>=8      */
+       
+       if ((Value8 & 0xf8) == 0x58 )
+       {
+               return 3;
        }
-       k &= 0x07;
-       quintet[1] = g2q_tab[k];
-
-       val &= 0x00ff;          /* AssignID 1stQuintet,AH=001xxxxx  */
-       m = quintet[0] << 8;
-       val |= m;
-       fun_scam(dev, &val);
-       val &= 0x00ff;          /* AssignID 2ndQuintet,AH=001xxxxx */
-       m = quintet[1] << 8;
-       val |= m;
-       fun_scam(dev, &val);
-
-       goto TCM_SYNC;
 
-}
-
-void is870(unsigned long host, unsigned int wkport)
-{
-       unsigned int tmport;
-       unsigned char i, j, k, rmb, n;
-       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};
-       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 = &atp_unit[host];
-
-       sync_idu = 0;
-       tmport = wkport + 0x3a;
-       outb((unsigned char) (inb(tmport) | 0x10), tmport);
-
-       for (i = 0; i < 16; i++) {
-               if ((dev->chip_veru != 4) && (i > 7)) {
-                       break;
-               }
-               m = 1;
-               m = m << i;
-               if ((m & dev->active_idu) != 0) {
-                       continue;
-               }
-               if (i == dev->host_idu) {
-                       printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_idu);
-                       continue;
-               }
-               tmport = wkport + 0x1b;
-               if (dev->chip_veru == 4) {
-                  outb(0x01, tmport);
-               }
-               else
-               {
-                  outb(0x00, tmport);
-               }
-               tmport = wkport + 1;
-               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[i].devspu, 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);
-               tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
-                       continue;
-               }
-               while (inb(tmport) != 0x8e);
-               dev->active_idu |= m;
-
-               tmport = wkport + 0x10;
-               outb(0x30, tmport);
-               tmport = wkport + 0x04;
-               outb(0x00, tmport);
-
-phase_cmd:
-               tmport = wkport + 0x18;
-               outb(0x08, tmport);
-               tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
-               tmport -= 0x08;
-               j = inb(tmport);
-               if (j != 0x16) {
-                       tmport = wkport + 0x10;
-                       outb(0x41, tmport);
-                       goto phase_cmd;
-               }
-sel_ok:
-               tmport = wkport + 3;
-               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[i].devspu, 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);
-               tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
-                       continue;
-               }
-               while (inb(tmport) != 0x8e);
-               tmport = wkport + 0x1b;
-               if (dev->chip_veru == 4) {
-                       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);
-               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[i].devtypeu = mbuf[0];
-               rmb = mbuf[1];
-               n = mbuf[7];
-               if (dev->chip_veru != 4) {
-                       goto not_wide;
-               }
-               if ((mbuf[7] & 0x60) == 0) {
-                       goto not_wide;
-               }
-               if ((dev->global_map & 0x20) == 0) {
-                       goto not_wide;
-               }
-               tmport = wkport + 0x1b;
-               outb(0x01, tmport);
-               tmport = wkport + 3;
-               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[i].devspu, 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);
-               tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
-                       continue;
-               }
-               while (inb(tmport) != 0x8e);
-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;
-                       }
-               }
-               tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
-               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;
-                       }
-               }
-               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);
-               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_idu |= m;
-not_wide:
-               if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) ||
-                   ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0)))
-               {
-                       goto set_sync;
-               }
-               continue;
-set_sync:
-               tmport = wkport + 0x1b;
-               j = 0;
-               if ((m & dev->wide_idu) != 0) {
-                       j |= 0x01;
-               }
-               outb(j, tmport);
-               tmport = wkport + 3;
-               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[i].devspu, 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);
-               tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
-                       continue;
-               }
-               while (inb(tmport) != 0x8e);
-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_idu) != 0) {
-                                       outb(synw[j++], tmport);
-                               } else {
-                                       if ((m & dev->ultra_map) != 0) {
-                                               outb(synu[j++], tmport);
-                                       } else {
-                                               outb(synn[j++], tmport);
-                                       }
-                               }
-                               tmport += 0x06;
-                       }
-               }
-               tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
-               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;
-                       }
-               }
-               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(0xff, 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);
-               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] > 0x0c) {
-                       mbuf[4] = 0x0c;
-               }
-               dev->id[i].devspu = mbuf[4];
-               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[i].devspu = (dev->id[i].devspu & 0x0f) | j;
-       }
-       tmport = wkport + 0x3a;
-       outb((unsigned char) (inb(tmport) & 0xef), tmport);
-}
+       return 0;
+}//end EnableSMART()
+//axl-
 
-void is880(unsigned long host, unsigned int wkport)
+void Noiocmd(struct hw_device_ext * devext, Scsi_Cmnd * Srb)
 {
-       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 };
-       struct atp_unit *dev = &atp_unit[host];
-
-       sync_idu = 0;
-       lvdmode=inb(wkport + 0x3f) & 0x40;
-
-       for (i = 0; i < 16; i++) {
-               m = 1;
-               m = m << i;
-               if ((m & dev->active_idu) != 0) {
-                       continue;
-               }
-               if (i == dev->host_idu) {
-                       printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_idu);
-                       continue;
-               }
-               tmport = wkport + 0x5b;
-               outb(0x01, tmport);
-               tmport = wkport + 0x41;
-               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[i].devspu, 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);
-               tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
-                       continue;
-               }
-               while (inb(tmport) != 0x8e);
-               dev->active_idu |= m;
-
-               tmport = wkport + 0x50;
-               outb(0x30, tmport);
-               tmport = wkport + 0x54;
-               outb(0x00, tmport);
-
-phase_cmd:
-               tmport = wkport + 0x58;
-               outb(0x08, tmport);
-               tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
-               tmport -= 0x08;
-               j = inb(tmport);
-               if (j != 0x16) {
-                       tmport = wkport + 0x50;
-                       outb(0x41, tmport);
-                       goto phase_cmd;
-               }
-sel_ok:
-               tmport = wkport + 0x43;
-               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[i].devspu, 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);
-               tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
-                       continue;
-               }
-               while (inb(tmport) != 0x8e);
-               tmport = wkport + 0x5b;
-               outb(0x00, tmport);
-               tmport = wkport + 0x58;
-               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 + 0x50;
-               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);
-               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[i].devtypeu = mbuf[0];
-               rmb = mbuf[1];
-               n = mbuf[7];
-               if ((mbuf[7] & 0x60) == 0) {
-                       goto not_wide;
-               }
-               if ((i < 8) && ((dev->global_map & 0x20) == 0)) {
-                       goto not_wide;
-               }
-               if (lvdmode == 0)
-               {
-                  goto chg_wide;
-               }
-               if (dev->sp[i] != 0x04)          // force u2
-               {
-                  goto chg_wide;
-               }
-
-               tmport = wkport + 0x5b;
-               outb(0x01, tmport);
-               tmport = wkport + 0x43;
-               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[i].devspu, 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);
-               tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
-                       continue;
-               }
-               while (inb(tmport) != 0x8e);
-try_u3:
-               j = 0;
-               tmport = wkport + 0x54;
-               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;
-                       }
-               }
-               tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
-               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 + 0x58;
-               outb(0x20, tmport);
-               tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0) {
-                       if ((inb(tmport) & 0x01) != 0) {
-                               tmport -= 0x06;
-                               outb(0, tmport);
-                               tmport += 0x06;
-                       }
-               }
-               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 + 0x54;
-               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 + 0x50;
-               outb(0x30, tmport);
-               tmport = wkport + 0x54;
-               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_idu |= m;
-                  dev->id[i].devspu = 0xce;
-                  continue;
-               }
-chg_wide:
-               tmport = wkport + 0x5b;
-               outb(0x01, tmport);
-               tmport = wkport + 0x43;
-               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[i].devspu, 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);
-               tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
-                       continue;
-               }
-               while (inb(tmport) != 0x8e);
-try_wide:
-               j = 0;
-               tmport = wkport + 0x54;
-               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;
-                       }
-               }
-               tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
-               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 + 0x58;
-               outb(0x20, tmport);
-               tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0) {
-                       if ((inb(tmport) & 0x01) != 0) {
-                               tmport -= 0x06;
-                               outb(0, tmport);
-                               tmport += 0x06;
+    UCHAR i,j,t;
+    UCHAR c[8];
+    PUCHAR saddr;
+    ULONG l;
+    struct scatterlist *sgpnt;
+//#ifdef MODESENSE_DEBUG               
+//         printk("Noiocmd: CDB=%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n",Srb->cmnd[0],Srb->cmnd[1],
+//                     Srb->cmnd[2],Srb->cmnd[3],Srb->cmnd[4],Srb->cmnd[5],Srb->cmnd[6],Srb->cmnd[7],
+//                     Srb->cmnd[8],Srb->cmnd[9]);
+//#endif
+           sgpnt = (struct scatterlist *) Srb->request_buffer;
+           if (Srb->use_sg)
+           {
+              saddr = sgpnt[0].address;
+           } else {
+              saddr=Srb->request_buffer;
+           }
+           t = Srb->target;
+           j=Srb->cmnd[0];
+           if (j == 0x1a)
+           {
+#ifdef MODESENSE_DEBUG         
+               printk("Noiocmd: Mode Sense(6): Page=%2X, length=%2X cap=%8lX\n",Srb->cmnd[2],Srb->cmnd[4],
+                       devext->cap[t]);
+#endif
+              l=devext->cap[t];
+#ifdef IXP42X_SUPPORT
+              devext->page0[4]=(UCHAR)(l>>24);
+              devext->page0[5]=(UCHAR)(l>>16);
+              devext->page0[6]=(UCHAR)(l>>8);         
+              devext->page0[7]=(UCHAR)(l);     
+              devext->page1[4]=(UCHAR)(l>>24);
+              devext->page1[5]=(UCHAR)(l>>16);
+              devext->page1[6]=(UCHAR)(l>>8);         
+              devext->page1[7]=(UCHAR)(l);                           
+              devext->page1c[4]=(UCHAR)(l>>24);
+              devext->page1c[5]=(UCHAR)(l>>16);
+              devext->page1c[6]=(UCHAR)(l>>8);        
+              devext->page1c[7]=(UCHAR)(l);                   
+#else         
+              i=((PUCHAR)&l)[0];
+              ((PUCHAR)&l)[0]=((PUCHAR)&l)[3];
+              ((PUCHAR)&l)[3]=i;
+              i=((PUCHAR)&l)[1];
+              ((PUCHAR)&l)[1]=((PUCHAR)&l)[2];
+              ((PUCHAR)&l)[2]=i;
+              ((PULONG)&devext->page0[4])[0]=l;
+              ((PULONG)&devext->page1[4])[0]=l;
+              ((PULONG)&devext->page1c[4])[0]=l;
+#endif        
+              Srb->result=0;
+#ifdef MODESENSE_DEBUG         
+              printk("Noiocm: Mode Sense(6): Page data[4]=%2X %2X %2X %2X\n",devext->page0[4],
+                     devext->page0[5],devext->page0[6],devext->page0[7]);
+#endif
+              j=Srb->cmnd[4];
+              if ((Srb->cmnd[2] & 0x3f) == 0)
+              {
+                 if ( j > 0x10 )
+                 {
+                    j=0x10;
+                 }
+                 memcpy(saddr,&devext->page0[0],j);
+              }
+              else
+              {
+                 if ((Srb->cmnd[2] & 0x3f) == 1)
+                 {
+                    if ( j > 0x18 )
+                    {
+                       j=0x18;
+                    }
+                    memcpy(saddr,&devext->page1[0],j);
+                 }
+                 else
+                 {
+                    if ((Srb->cmnd[2] & 0x3f) == 0x1c)
+                    {
+                       if ( j > 0x18 )
+                       {
+                          j=0x18;
                        }
-               }
-               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 + 0x54;
-               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 + 0x50;
-               outb(0x30, tmport);
-               tmport = wkport + 0x54;
-               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 widep_out;
+                       memcpy(saddr,&devext->page1c[0],j);
+                    }
+                    else
+                    {
+                       if ((Srb->cmnd[2] & 0x3f) == 0x3f)
+                       {
+                          i=j;
+                          if ( i > 0x18 )
+                          {
+                             i=0x18;
+                          }
+                          memcpy(saddr,&devext->page1[0],i);
+                          c[0]=0x33;
+                          memcpy(saddr,&c[0],1);
+                          (ULONG)saddr += i;
+                          j -= i;
+                          i=j;
+                          if ( i > 0x0c )
+                          {
+                             i=0x0c;
+                          }
+                          memcpy(saddr,&devext->page1c[12],i);
+                          (ULONG)saddr += i;
+                          j -= i;
+                          i=j;
+                          if ( i > 0x10 )
+                          {
+                             i=0x10;
+                          }
+                          memcpy(saddr,&devext->page0[0],i);
                        }
-                       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_idu |= m;
-not_wide:
-               if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) ||
-                   ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0)))
-               {
-                       m = 1;
-                       m = m << i;
-                       if ((dev->async & m) != 0)
+                       else
                        {
-                          goto set_sync;
+                          goto do_autosens;
                        }
-               }
-               continue;
-set_sync:
-               if (dev->sp[i] == 0x02)
+                    }
+                 }
+              }
+              goto EXECUTE_SCSI1;
+           }
+           if ( j == 0x12 )
+           {
+//axl +
+               switch(Srb->cmnd[3])
+               {
+                       case 0:
+                              if (Srb->cmnd[1] & 0x01)
+                              {
+                                       devext->dskerr[t]=0x54;
+                                       goto print_autosens; // EVPD not supported
+                              }
+                              j=Srb->cmnd[4];
+                                              if ( j > 0x38 )
+                              {
+                                                               j=0x38;
+                              }
+                              memcpy(saddr,&devext->inqdat[t][0],j);
+                              Srb->result=0;
+                              break;
+
+                       case 1:
+                               memcpy(saddr, smart_buf, sizeof(smart_buf));
+                               Srb->result=0;
+                              break;
+                       }
+               goto EXECUTE_SCSI1;
+           }
+           if ( j == 0x01 )
+           {
+{
+               unsigned char cStatus;
+               Srb->result = EnableSMART(devext);
+//             printk("EnableSMART cStatus %x\n",Srb->result);
+               if(Srb->result == 0)
+               {
+                       devext->inqdat[t][38] = 1;
+               }
+}
+//axl end
+              goto EXECUTE_SCSI1;
+           }
+           if ( j == 0x25 )
+           {
+#ifdef IXP42X_SUPPORT
+              c[0]= (UCHAR) (devext->cap[t]>>24);
+              c[1]= (UCHAR) (devext->cap[t]>>16);
+              c[2]= (UCHAR) (devext->cap[t]>>8);
+              c[3]= (UCHAR) (devext->cap[t]);
+               c[4]= 0x00;
+               c[5]= 0x00;
+               c[6]= 0x02; // block length = 512 bytes
+               c[7]= 0x00;
+#else          
+              c[0]=((PUCHAR)(&devext->cap[t]))[3];
+              c[1]=((PUCHAR)(&devext->cap[t]))[2];
+              c[2]=((PUCHAR)(&devext->cap[t]))[1];
+              c[3]=((PUCHAR)(&devext->cap[t]))[0];
+              ((PULONG)&c[4])[0]=0x00020000;
+#endif        
+              memcpy(saddr,&c[0],8);
+              Srb->result=0;
+              goto EXECUTE_SCSI1;
+           }
+           if ( j == 0x03 )
+           {
+#ifdef DEBUG_SENSEKEY                  
+               printk("ATP86X: Request sense command comes!\n"); 
+#endif         
+              j=Srb->cmnd[4];
+              if ( j > 0x10 )
+              {
+                 j=0x10;
+              }
+              fill_sensekey_buf(devext,t);
+              memcpy(saddr,&devext->sensd[t][0],j);           
+               devext->dskerr[t]=0;
+              Srb->result=0;
+              goto EXECUTE_SCSI1;
+           }
+           Srb->result=0;
+           if ((j != 0x00) && (j != 0x15) && (j != 0x55) &&
+               (j != 0x1e) && (j != 0x04))
+           {
+//printk("Noiocmd: NOT 'TUR' 'Mode Select(6)' 'Mode Select(10)' 'PAMR' 'FORMAT UNIT'\n");
+do_autosens:
+              devext->dskerr[t]=0x50;
+print_autosens:                       
+              Srb->result=0x02;
+#ifdef DEBUG_SENSEKEY         
+              printk("ATP86X: Not supported CDB = ");
+              for (j=0;j<Srb->cmd_len;j++ )
+               printk("%2X ",Srb->cmnd[j]);
+              printk("\n");
+#endif        
+           }
+EXECUTE_SCSI1:
+           return ;
+}
+
+void is867(struct hw_device_ext * devext)
+{
+    ULONG baseIoAddress = devext->BaseIoAddress[0];
+    ULONG  r;
+    UCHAR  i,j,k,l,ata66,is66,iswd;
+    UCHAR  cbuf[4];
+    USHORT m,mbuf[256];
+
+    /* Port 4A: IDE0 8 bit IO ports speed  */
+    Outpb(baseIoAddress,0x4a,0x43);
+    Outpb(baseIoAddress,0x5a,0x43);
+    Outpb(baseIoAddress,0x6a,0x43);
+    Outpb(baseIoAddress,0x7a,0x43);
+    
+    ata66=0x00;
+    devext->ata66=ata66;
+    /* Port 48: IDE0 master DATA PIO/NDMA speed : 0aaarrrr          
+       Port 49: IDE0 slave  DATA PIO/NDMA speed : 0aaarrrr  
+       Port 4B: IDE0 UDMA mode (default 00H)
+               bit7=0.
+               bit6-4 :slave-IDE UDMA MODE#
+               000 : disable UDMA
+               001 : UDMA mode 0
+               010 : UDMA mode 1
+               011 : UDMA mode 2
+               100 : UDMA mode 3
+               101 : UDMA mode 4
+               110 : UDMA mode 5
+               111 : UDMA mode 6
+               bit3=0.
+               bit2-0 :master-IDE UDMA MODE#
+               000 : disable UDMA
+               001 : UDMA mode 0
+               010 : UDMA mode 1
+               011 : UDMA mode 2
+               100 : UDMA mode 3
+               101 : UDMA mode 4
+               110 : UDMA mode 5
+               111 : UDMA mode 6
+    */ 
+    Outpb(baseIoAddress,0x48,0x31);
+    Outpb(baseIoAddress,0x49,0x31);
+    Outpb(baseIoAddress,0x4b,0x00);
+    Outpb(baseIoAddress,0x58,0x31);
+    Outpb(baseIoAddress,0x59,0x31);
+    Outpb(baseIoAddress,0x5b,0x00);
+    Outpb(baseIoAddress,0x68,0x31);
+    Outpb(baseIoAddress,0x69,0x31);
+    Outpb(baseIoAddress,0x6b,0x00);
+    Outpb(baseIoAddress,0x78,0x31);
+    Outpb(baseIoAddress,0x79,0x31);
+    Outpb(baseIoAddress,0x7b,0x00);
+    /*         cbuf[0]: UDMA mode value for port 0x4B  IDE0
+       cbuf[1]: UDMA mode value for port 0x5B  IDE1   
+       cbuf[2]: UDMA mode value for port 0x6B  IDE2
+       cbuf[3]: UDMA mode value for port 0x7B  IDE3   
+    */
+    cbuf[0] = 0x00;
+    cbuf[1] = 0x00;
+    cbuf[2] = 0x00;
+    cbuf[3] = 0x00;
+
+    /* Scan device for master/slave of 4 channels */
+    for ( i = 0 ; i < 8 ; i++ )
+    {
+       /* j = out to 1X6 value , i=xx0: Master 0xA0 or i=xx1: Slave 0xB0 */
+       baseIoAddress=devext->BaseIoAddress[i >> 1];
+       j=0xa0;
+       if ((i & 0x01) != 0)
+       {
+          j=0xb0;
+       }
+       Outpb(baseIoAddress,6,j);
+       mdelay(10);
+       /* k = in from 1X7 value */     
+       k=Inpb(baseIoAddress,7);
+       if ((k & 0x88) != 0x00)
+       {
+          devext->hd_status[i]=0x7f;
+          continue;
+       }
+       /* ATA Identify device command */
+       Outpb(baseIoAddress,7,0xec);
+       mdelay(400);
+wait_drq:
+       l=Inpb(baseIoAddress,7);
+       if ((l & 0x80) != 0 )
+       {
+         goto wait_drq;
+       }
+       if ((l & 0x01) == 0x01 )
+       {
+         devext->hd_status[i]=0x7f;
+         continue;
+       }
+       if ((l & 0xf8) != 0x58 )
+       {
+         devext->hd_status[i]=0x7f;
+         continue;
+       }
+       for (m=0; m < 0x100; m++)
+       {
+         mbuf[m]=Inpw(baseIoAddress,0);
+       }
+       /* Clear IRQ? */
+       mdelay(1);
+       k=Inpb(baseIoAddress,7);       
+       /* active_id = device exists */
+       k=1;
+       k=k<<i;
+       devext->active_id |= k;
+
+       /* device type =0, capacity = word 60:61 (28-bit LBA) or word 100:101 (48-bit LBA) */
+       devext->devtype[i]=0;
+#ifdef IXP42X_SUPPORT
+       devext->cap[i] =  mbuf[61]<<16;
+       devext->cap[i] |= mbuf[60];
+#else              
+       devext->cap[i]=((PULONG)&mbuf[60])[0];
+#endif       
+       if (devext->cap[i] == 0x0fffffff)
+       {
+         if ((mbuf[100] != 0) || (mbuf[101] != 0) ||
+             (mbuf[102] != 0) || (mbuf[103] != 0))
+         {
+            devext->bigdrv[i]=1;
+#ifdef IXP42X_SUPPORT       
+                    devext->cap[i] =  mbuf[101]<<16;
+             devext->cap[i] |= mbuf[100];           
+#else                               
+            devext->cap[i]=((PULONG)&mbuf[100])[0];
+#endif      
+            r=((PULONG)&mbuf[102])[0];
+            if (r != 0)
+            {
+               devext->cap[i]=0xffffffff;
+            }
+         }
+       }
+       /* capacity -2??  why ??*/
+       devext->cap[i] -= 2;
+       /* fill inquiry data from byte 8 to byte 8+ 14*2 */
+       k=4;
+       for ( l=27; l < 41; l++ )
+       {
+          ((PUSHORT)&devext->inqdat[i][0])[k++]=(USHORT)((((PUCHAR)&mbuf[l])[0] << 8) | ((PUCHAR)&mbuf[l])[1]);
+       }
+       /* fill inquiry data from byte 0 to byte 7 */       
+#ifdef  IXP42X_SUPPORT
+       devext->inqdat[i][0]= 0x00;
+       devext->inqdat[i][1]= 0x00;       
+       devext->inqdat[i][2]= 0x02;
+       devext->inqdat[i][3]= 0x02;
+       devext->inqdat[i][4]= 0x7D;
+       devext->inqdat[i][5]= 0x00;
+       devext->inqdat[i][6]= 0x00;
+       devext->inqdat[i][7]= 0x32;       
+#else
+       ((PULONG)(&devext->inqdat[i][0]))[0]=0x02020000;
+       ((PULONG)(&devext->inqdat[i][0]))[1]=0x3200007d;       
+#endif       
+       devext->inqdat[i][36]=0;
+       printk(KERN_INFO "         ID: %2d  %s     ", i, &devext->inqdat[i][8]);
+#ifndef DEBUG_UDMA
+       printk("\n");
+#endif       
+       is66=0;
+       iswd=0;
+
+/* fill PIO/DMA/UDMA speed table and set feature to drive here */
+    
+       /* 1X1 = 0x3  */
+       Outpb(baseIoAddress,1,0x03);
+       /* Identify device word 88:   
+               F 15 Reserved
+               V 14 1 = Ultra DMA mode 6 is selected
+               0 = Ultra DMA mode 6 is not selected
+               V 13 1 = Ultra DMA mode 5 is selected
+               0 = Ultra DMA mode 5 is not selected
+               V 12 1 = Ultra DMA mode 4 is selected
+               0 = Ultra DMA mode 4 is not selected
+               V 11 1 = Ultra DMA mode 3 is selected
+               0 = Ultra DMA mode 3 is not selected
+               V 10 1 = Ultra DMA mode 2 is selected
+               0 = Ultra DMA mode 2 is not selected
+               V 9 1 = Ultra DMA mode 1 is selected
+               0 = Ultra DMA mode 1 is not selected
+               V 8 1 = Ultra DMA mode 0 is selected
+               0 = Ultra DMA mode 0 is not selected
+               F 7 Reserved
+               F 6 1 = Ultra DMA mode 6 and below are supported
+               F 5 1 = Ultra DMA mode 5 and below are supported
+               F 4 1 = Ultra DMA mode 4 and below are supported
+               F 3 1 = Ultra DMA mode 3 and below are supported
+               F 2 1 = Ultra DMA mode 2 and below are supported
+               F 1 1 = Ultra DMA mode 1 and below are supported
+               F 0 1 = Ultra DMA mode 0 is supported 
+       */
+       if ((mbuf[88] & 0x0018) == 0)
+       {
+         if ((iswd == 0) && ((mbuf[88] & 0x007f) != 0))
+         {
+            /* UDMA mode 2 */
+            Outpb(baseIoAddress,2,0x42);
+#ifdef DEBUG_UDMA
+            printk("UDMA2 (33)\n");
+#endif      
+         }
+         else
+         {
+force_normdma:
+            /* Multiword DMA mode 0-2 */
+            k=(UCHAR)(mbuf[63] & 0x0007);
+            k >>= 1;
+            if (k > 2)
+               k=2;
+#ifdef DEBUG_UDMA
+            printk("Mw-DMA %2X\n",k);
+#endif              
+             k |= 0x20;
+            Outpb(baseIoAddress,2,k);
+            iswd=1;
+
+         }
+       }
+       else
+       {
+         if ( iswd != 0 )
+         {
+            goto force_normdma;
+         }
+
+         if (((i < 2) && ((ata66 & 0x01) == 0)) ||
+             ((i > 1) && ((ata66 & 0x02) == 0)))
+         {
+            if ((mbuf[88] & 0x0020) == 0)
+            {
+               /* UDMA mode 4 */                               
+               Outpb(baseIoAddress,2,0x44);
+               is66=1;
+#ifdef DEBUG_UDMA
+               printk("UDMA4 (66)\n");
+#endif                 
+            }
+            else
+            {
+               /* UDMA mode 5 */
+               if ((mbuf[88] & 0x0040) == 0)
                {
-                  synu[4]=0x0c;
-                  synuw[4]=0x0c;
+                  is66=2;
+                  Outpb(baseIoAddress,2,0x45);
+#ifdef DEBUG_UDMA
+                  printk("UDMA5 (100)\n");
+#endif                            
                }
                else
                {
-                  if (dev->sp[i] >= 0x03)
-                  {
-                     synu[4]=0x0a;
-                     synuw[4]=0x0a;
-                  }
-               }
-               tmport = wkport + 0x5b;
-               j = 0;
-               if ((m & dev->wide_idu) != 0) {
-                       j |= 0x01;
-               }
-               outb(j, tmport);
-               tmport = wkport + 0x43;
-               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[i].devspu, 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);
-               tmport -= 0x08;
-               if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
-                       continue;
-               }
-               while (inb(tmport) != 0x8e);
-try_sync:
-               j = 0;
-               tmport = wkport + 0x54;
-               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_idu) != 0) {
-                                       if ((m & dev->ultra_map) != 0) {
-                                               outb(synuw[j++], tmport);
-                                       } else {
-                                               outb(synw[j++], tmport);
-                                       }
-                               } else {
-                                       if ((m & dev->ultra_map) != 0) {
-                                               outb(synu[j++], tmport);
-                                       } else {
-                                               outb(synn[j++], tmport);
-                                       }
-                               }
-                               tmport += 0x06;
-                       }
-               }
-               tmport -= 0x08;
-               while ((inb(tmport) & 0x80) == 0x00);
-               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 + 0x58;
-               outb(0x20, tmport);
-               tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00) {
-                       if ((inb(tmport) & 0x01) != 0x00) {
-                               tmport -= 0x06;
-                               outb(0x00, tmport);
-                               tmport += 0x06;
-                       }
-               }
-               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;
+               /* UDMA mode 6 */                       
+                  is66=3;
+                  Outpb(baseIoAddress,2,0x46);
+#ifdef DEBUG_UDMA
+                  printk("UDMA6 (133)\n");
+#endif                            
+               }
+            }
+         }
+         else
+         {
+            /* UDMA mode 2 */          
+            Outpb(baseIoAddress,2,0x42);
+#ifdef DEBUG_UDMA
+            printk("UDMA2 (33)\n");
+#endif                      
+         }
+       }
+       /* set feature  UDMA or NDMA mode */
+       Outpb(baseIoAddress,7,0xef);
+       mdelay(1000);
+       k=Inpb(baseIoAddress,7);
+       while ((k & 0x80) != 0)
+       {
+        k=Inpb(baseIoAddress,7);
+       }
+       if ((k & 0xf9) == 0x50)
+       {
+         if ( is66 == 0)
+         {
+           if ( iswd == 0 )
+           {
+              if ( i == 0 )
+              {
+                 cbuf[0] |= 0x03;
+              }
+              if ( i == 1 )
+              {
+                 cbuf[0] |= 0x30;
+              }
+              if ( i == 2 )
+              {
+                 cbuf[1] |= 0x03;
+              }
+              if ( i == 3 )
+              {
+                 cbuf[1] |= 0x30;
+              }
+              if ( i == 4 )
+              {
+                 cbuf[2] |= 0x03;
+              }
+              if ( i == 5 )
+              {
+                 cbuf[2] |= 0x30;
+              }
+              if ( i == 6 )
+              {
+                 cbuf[3] |= 0x03;
+              }
+              if ( i == 7 )
+              {
+                 cbuf[3] |= 0x30;
+              }
+           }
+         }
+         else
+         {
+            if ( i == 0 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[0] |= 0x05;
                }
-               continue;
-phase_ins:
-               tmport = wkport + 0x54;
-               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;
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[0] |= 0x06;
+                  else
+                     cbuf[0] |= 0x07;
+               }
+            }
+            if ( i == 1 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[0] |= 0x50;
                }
-               continue;
-phase_cmds:
-               tmport = wkport + 0x50;
-               outb(0x30, tmport);
-tar_dcons:
-               tmport = wkport + 0x54;
-               outb(0x00, tmport);
-               tmport += 0x04;
-               outb(0x08, tmport);
-               tmport += 0x07;
-               while ((inb(tmport) & 0x80) == 0x00);
-               tmport -= 0x08;
-               j = inb(tmport);
-               if (j != 0x16) {
-                       continue;
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[0] |= 0x60;
+                  else
+                     cbuf[0] |= 0x70;
+               }
+            }
+            if ( i == 2 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[1] |= 0x05;
                }
-               if (mbuf[0] != 0x01) {
-                       continue;
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[1] |= 0x06;
+                  else
+                     cbuf[1] |= 0x07;
+               }
+            }
+            if ( i == 3 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[1] |= 0x50;
                }
-               if (mbuf[1] != 0x03) {
-                       continue;
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[1] |= 0x60;
+                  else
+                     cbuf[1] |= 0x70;
+               }
+            }
+            if ( i == 4 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[2] |= 0x05;
                }
-               if (mbuf[4] == 0x00) {
-                       continue;
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[2] |= 0x06;
+                  else
+                     cbuf[2] |= 0x07;
+               }
+            }
+            if ( i == 5 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[2] |= 0x50;
                }
-               if (mbuf[3] > 0x64) {
-                       continue;
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[2] |= 0x60;
+                  else
+                     cbuf[2] |= 0x70;
+               }
+            }
+            if ( i == 6 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[3] |= 0x05;
                }
-               if (mbuf[4] > 0x0e) {
-                       mbuf[4] = 0x0e;
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[3] |= 0x06;
+                  else
+                     cbuf[3] |= 0x07;
+               }
+            }
+            if ( i == 7 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[3] |= 0x50;
                }
-               dev->id[i].devspu = mbuf[4];
-               if (mbuf[3] < 0x0c){
-                       j = 0xb0;
-                       goto set_syn_ok;
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[3] |= 0x60;
+                  else
+                     cbuf[3] |= 0x70;
+               }
+            }
+         }
+       }
+    }
+    baseIoAddress=devext->BaseIoAddress[0];
+    Outpb(baseIoAddress,0x4b,cbuf[0]);
+    Outpb(baseIoAddress,0x5b,cbuf[1]);
+    Outpb(baseIoAddress,0x6b,cbuf[2]);
+    Outpb(baseIoAddress,0x7b,cbuf[3]);
+    return;
+}
+
+void is865(struct hw_device_ext * devext,struct pci_dev *pdev)
+{
+    ULONG baseIoAddress = devext->BaseIoAddress[0];
+    ULONG  r;
+    UCHAR  i,j,k,l,ata66,is66,iswd;
+    UCHAR  cbuf[4];
+    USHORT m,mbuf[256];
+
+    ata66=0x00;
+    devext->ata66=ata66;
+    /* config +40+00: IDE0 master DATA PIO/NDMA speed : 0aaarrrr          
+       config +40+01: IDE0 slave  DATA PIO/NDMA speed : 0aaarrrr          
+       config +40+02: IDE1 master DATA PIO/NDMA speed : 0aaarrrr          
+       config +40+03: IDE1 slave  DATA PIO/NDMA speed : 0aaarrrr                     
+       config +40+04: IDE0 UDMA mode (default 00H)
+       config +40+05: IDE1 UDMA mode (default 00H)       
+               bit7=0.
+               bit6-4 :slave-IDE UDMA MODE#
+               000 : disable UDMA
+               001 : UDMA mode 0
+               010 : UDMA mode 1
+               011 : UDMA mode 2
+               100 : UDMA mode 3
+               101 : UDMA mode 4
+               110 : UDMA mode 5
+               bit3=0.
+               bit2-0 :master-IDE UDMA MODE#
+               000 : disable UDMA
+               001 : UDMA mode 0
+               010 : UDMA mode 1
+               011 : UDMA mode 2
+               100 : UDMA mode 3
+               101 : UDMA mode 4
+               110 : UDMA mode 5
+    */ 
+#ifdef IS865_DEBUG    
+       printk("is865: write PIO/DMA speed: 40,41,42,43=0x31. 44,45 =0 \n");
+#endif
+    pci_write_config_byte(pdev, 0x40, 0x31);    
+    pci_write_config_byte(pdev, 0x41, 0x31);        
+    pci_write_config_byte(pdev, 0x42, 0x31);    
+    pci_write_config_byte(pdev, 0x43, 0x31);
+    pci_write_config_byte(pdev, 0x44, 0x00);
+    pci_write_config_byte(pdev, 0x45, 0x00);
+    
+    /*         cbuf[0]: UDMA mode value for port 0x4B  IDE0
+       cbuf[1]: UDMA mode value for port 0x5B  IDE1   
+       cbuf[2]: UDMA mode value for port 0x6B  IDE2
+       cbuf[3]: UDMA mode value for port 0x7B  IDE3   
+    */
+    cbuf[0] = 0x00;
+    cbuf[1] = 0x00;
+    cbuf[2] = 0x00;
+    cbuf[3] = 0x00;
+#ifdef IS865_DEBUG    
+       printk("is865: scan 4 devices of 2 channels\n");
+#endif
+    /* Scan device for master/slave of 2 channels */
+    for ( i = 0 ; i < 4 ; i++ )
+    {
+       /* j = out to 1X6 value , i=xx0: Master 0xA0 or i=xx1: Slave 0xB0 */
+       if (i<2) baseIoAddress=devext->BaseIoAddress[0];
+       else     baseIoAddress=devext->BaseIoAddress[1];
+       j=0xa0;
+       if ((i & 0x01) != 0)
+       {
+          j=0xb0;
+       }
+#ifdef IS865_DEBUG    
+       printk("is865: i=%2X out %2X to port %4lX \n",i,j,(unsigned long)(baseIoAddress+6));
+#endif 
+       Outpb(baseIoAddress,6,j);
+       mdelay(10);
+       /* k = in from 1X7 value */     
+       k=Inpb(baseIoAddress,7);
+#ifdef IS865_DEBUG    
+       printk("is865: i=%2X in port %4lX  = %2X\n",i,(unsigned long)(baseIoAddress+7),k);
+#endif         
+       if ((k & 0x88) != 0x00)
+       {
+          devext->hd_status[i]=0x7f;
+          devext->cap[i]=0;
+          continue;
+       }
+#ifdef IS865_DEBUG    
+       printk("is865: i=%2X out 0xEC to port %4lX \n",i,(unsigned long)(baseIoAddress+7));
+#endif         
+       /* ATA Identify device command */
+       Outpb(baseIoAddress,7,0xec);
+       mdelay(400);
+wait_drq:
+       l=Inpb(baseIoAddress,7);
+#ifdef IS865_DEBUG    
+       printk("is865: i=%2X in port %4lX  = %2X\n",i,(unsigned long)(baseIoAddress+7),l);
+#endif                
+       if ((l & 0x80) != 0 )
+       {
+         goto wait_drq;
+       }
+       if ((l & 0x01) == 0x01 )
+       {
+         devext->hd_status[i]=0x7f;
+         devext->cap[i]=0;       
+         continue;
+       }
+       if ((l & 0xf8) != 0x58 )
+       {
+         devext->hd_status[i]=0x7f;
+         devext->cap[i]=0;       
+         continue;
+       }
+       for (m=0; m < 0x100; m++)
+       {
+         mbuf[m]=Inpw(baseIoAddress,0);
+       }
+       /* Clear IRQ? */
+       mdelay(1);
+       k=Inpb(baseIoAddress,7);       
+       /* active_id = device exists */
+       k=1;
+       k=k<<i;
+       devext->active_id |= k;
+#ifdef IS865_DEBUG    
+       printk("is865: Check 512bytes identify data\n");
+#endif         
+       /* device type =0, capacity = word 60:61 (28-bit LBA) or word 100:101 (48-bit LBA) */
+       devext->devtype[i]=0;
+#ifdef IXP42X_SUPPORT
+       devext->cap[i] =  mbuf[61]<<16;
+       devext->cap[i] |= mbuf[60];
+#else       
+       devext->cap[i]=((PULONG)&mbuf[60])[0];
+#endif       
+       if (devext->cap[i] == 0x0fffffff)
+       {
+         if ((mbuf[100] != 0) || (mbuf[101] != 0) ||
+             (mbuf[102] != 0) || (mbuf[103] != 0))
+         {
+            devext->bigdrv[i]=1;
+#ifdef IXP42X_SUPPORT       
+                    devext->cap[i] =  mbuf[101]<<16;
+             devext->cap[i] |= mbuf[100];           
+#else                    
+            devext->cap[i]=((PULONG)&mbuf[100])[0];
+#endif              
+            r=((PULONG)&mbuf[102])[0];
+            if (r != 0)
+            {
+               devext->cap[i]=0xffffffff;
+            }
+         }
+       }
+       /* capacity -2??  why ??*/
+       devext->cap[i] -= 2;
+
+#ifdef IS865_DEBUG    
+       printk("is865: capacity[%2x] = %8lX\n",i,devext->cap[i]);
+#endif                
+       /* fill inquiry data from byte 8 to byte 8+ 14*2 */
+       k=4;
+       for ( l=27; l < 41; l++ )
+       {
+          ((PUSHORT)&devext->inqdat[i][0])[k++]=(USHORT)((((PUCHAR)&mbuf[l])[0] << 8) | ((PUCHAR)&mbuf[l])[1]);
+       }
+       /* fill inquiry data from byte 0 to byte 7 */       
+#ifdef  IXP42X_SUPPORT
+       devext->inqdat[i][0]= 0x00;
+       devext->inqdat[i][1]= 0x00;       
+       devext->inqdat[i][2]= 0x02;
+       devext->inqdat[i][3]= 0x02;
+       devext->inqdat[i][4]= 0x7D;
+       devext->inqdat[i][5]= 0x00;
+       devext->inqdat[i][6]= 0x00;
+       devext->inqdat[i][7]= 0x32;       
+#else       
+       ((PULONG)(&devext->inqdat[i][0]))[0]=0x02020000;
+       ((PULONG)(&devext->inqdat[i][0]))[1]=0x3200007d;
+#endif       
+       devext->inqdat[i][36]=0;
+//axl+       
+       devext->inqdat[i][37] = 0;
+       devext->inqdat[i][38] = 0;
+       if((mbuf[83] & 0x4000) == 0x4000)
+       {
+              if((mbuf[82] & 0x01) == 0x01)
+              {
+                       devext->inqdat[i][37] = 1;
+                               if((mbuf[85] & 0x01) == 0x01)
+                               {
+                                       devext->inqdat[i][38] = 1;
+                               }
+              }
+       }
+               
+               devext->SamwiseBaseIoAddress = baseIoAddress;
+               devext->SamwiseHDSelect          = j;
+//       printk("\n %x %x", devext->SamwiseBaseIoAddress, devext->SamwiseHDSelect);
+//axl end
+       printk(KERN_INFO "         ID: %2d  %s     ", i, &devext->inqdat[i][8]);
+#ifndef DEBUG_UDMA
+       printk("\n");
+#endif              
+       is66=0;
+       iswd=0;
+
+/* fill PIO/DMA/UDMA speed table and set feature to drive here */
+    
+       /* 1X1 = 0x3  */
+       Outpb(baseIoAddress,1,0x03);
+       /* Identify device word 88:   
+               F 15 Reserved
+               V 14 1 = Ultra DMA mode 6 is selected
+               0 = Ultra DMA mode 6 is not selected
+               V 13 1 = Ultra DMA mode 5 is selected
+               0 = Ultra DMA mode 5 is not selected
+               V 12 1 = Ultra DMA mode 4 is selected
+               0 = Ultra DMA mode 4 is not selected
+               V 11 1 = Ultra DMA mode 3 is selected
+               0 = Ultra DMA mode 3 is not selected
+               V 10 1 = Ultra DMA mode 2 is selected
+               0 = Ultra DMA mode 2 is not selected
+               V 9 1 = Ultra DMA mode 1 is selected
+               0 = Ultra DMA mode 1 is not selected
+               V 8 1 = Ultra DMA mode 0 is selected
+               0 = Ultra DMA mode 0 is not selected
+               F 7 Reserved
+               F 6 1 = Ultra DMA mode 6 and below are supported
+               F 5 1 = Ultra DMA mode 5 and below are supported
+               F 4 1 = Ultra DMA mode 4 and below are supported
+               F 3 1 = Ultra DMA mode 3 and below are supported
+               F 2 1 = Ultra DMA mode 2 and below are supported
+               F 1 1 = Ultra DMA mode 1 and below are supported
+               F 0 1 = Ultra DMA mode 0 is supported 
+       */
+       if ((mbuf[88] & 0x0018) == 0)
+       {
+         if ((iswd == 0) && ((mbuf[88] & 0x007f) != 0))
+         {
+            /* UDMA mode 2 */
+            Outpb(baseIoAddress,2,0x42);            
+#ifdef DEBUG_UDMA
+            printk("UDMA2 (33)\n");
+#endif
+         }
+         else
+         {
+force_normdma:
+            /* Multiword DMA mode 0-2 */
+            k=(UCHAR)(mbuf[63] & 0x0007);
+            k >>= 1;
+            if (k > 2)
+               k=2;
+#ifdef DEBUG_UDMA
+            printk("MwDMA %2X\n",k);
+#endif      
+             k |= 0x20;
+            Outpb(baseIoAddress,2,k);
+            iswd=1;
+         }
+       }
+       else
+       {
+         if ( iswd != 0 )
+         {
+            goto force_normdma;
+         }
+
+         if (((i < 2) && ((ata66 & 0x01) == 0)) ||
+             ((i > 1) && ((ata66 & 0x02) == 0)))
+         {
+            if ((mbuf[88] & 0x0020) == 0)
+            {
+               /* UDMA mode 4 */                               
+               Outpb(baseIoAddress,2,0x44);
+               is66=1;
+#ifdef DEBUG_UDMA
+               printk("UDMA4 (66)\n");
+#endif         
+            }
+            else
+            {
+               /* UDMA mode 5 */
+               if ((devext->chipver <=3) || ((mbuf[88] & 0x0040) == 0))
+               {
+                  is66=2;
+                  Outpb(baseIoAddress,2,0x45);
+#ifdef DEBUG_UDMA
+                  printk("UDMA5 (100)\n");
+#endif            
                }
-               if ((mbuf[3] < 0x0d) && (rmb == 0)) {
-                       j = 0xa0;
-                       goto set_syn_ok;
+               else
+               {
+               /* UDMA mode 6 */                       
+                  is66=3;
+                  Outpb(baseIoAddress,2,0x46);
+#ifdef DEBUG_UDMA
+                  printk("UDMA6 (133)\n");
+#endif            
+               }
+            }
+         }
+         else
+         {
+            /* UDMA mode 2 */          
+            Outpb(baseIoAddress,2,0x42);
+#ifdef DEBUG_UDMA
+            printk("UDMA2 (33)\n");
+#endif      
+         }
+       }
+#ifdef IS865_DEBUG    
+       printk("is865: Set Featur: enable UDMA or NDMA\n");
+#endif                    
+       /* set feature  UDMA or NDMA mode */
+       Outpb(baseIoAddress,7,0xef);
+       mdelay(1000);
+       k=Inpb(baseIoAddress,7);
+       while ((k & 0x80) != 0)
+       {
+        k=Inpb(baseIoAddress,7);
+       }
+       if ((k & 0xf9) == 0x50)
+       {
+         if ( is66 == 0)
+         {
+           if ( iswd == 0 )
+           {
+              if ( i == 0 )
+              {
+                 cbuf[0] |= 0x03;
+              }
+              if ( i == 1 )
+              {
+                 cbuf[0] |= 0x30;
+              }
+              if ( i == 2 )
+              {
+                 cbuf[1] |= 0x03;
+              }
+              if ( i == 3 )
+              {
+                 cbuf[1] |= 0x30;
+              }
+           }
+         }
+         else
+         {
+            if ( i == 0 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[0] |= 0x05;
                }
-               if (mbuf[3] < 0x1a) {
-                       j = 0x20;
-                       goto set_syn_ok;
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[0] |= 0x06;
+                  else
+                     cbuf[0] |= 0x07;
+               }
+            }
+            if ( i == 1 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[0] |= 0x50;
                }
-               if (mbuf[3] < 0x33) {
-                       j = 0x40;
-                       goto set_syn_ok;
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[0] |= 0x60;
+                  else
+                     cbuf[0] |= 0x70;
+               }
+            }
+            if ( i == 2 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[1] |= 0x05;
                }
-               if (mbuf[3] < 0x4c) {
-                       j = 0x50;
-                       goto set_syn_ok;
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[1] |= 0x06;
+                  else
+                     cbuf[1] |= 0x07;
+               }
+            }
+            if ( i == 3 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[1] |= 0x50;
                }
-               j = 0x60;
-             set_syn_ok:
-               dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
-       }
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[1] |= 0x60;
+                  else
+                     cbuf[1] |= 0x70;
+               }
+            }
+         }
+       }
+    }
+#ifdef IS865_DEBUG    
+       printk("is865: End : enable UDMA 44= %2x ,45= %2x \n",cbuf[0],cbuf[1]);
+#endif             
+    pci_write_config_byte(pdev, 0x44, cbuf[0]);
+    pci_write_config_byte(pdev, 0x45, cbuf[1]);
+    return;    
+       
+       
 }
 
 /* return non-zero on detection */
-int atp870u_detect(Scsi_Host_Template * tpnt)
+int atp86x_detect(Scsi_Host_Template * tpnt)
 {
-       unsigned char irq, h, k, m;
-       unsigned long flags;
-       unsigned int base_io, error, tmport;
-       unsigned short index = 0;
-       struct pci_dev *pdev[3];
-       unsigned char chip_ver[3], host_id;
-       unsigned short dev_id[3], n;
+       UCHAR irq, h;
+       ULONG long flags;
+       ULONG baseIoAddress;
+       unsigned int base_io, error;
+       USHORT index = 0;
+       struct pci_dev *pdev[5];
+       UCHAR chip_ver[5];
+       USHORT dev_id[5];
        struct Scsi_Host *shpnt = NULL;
+       struct hw_device_ext *devext;
        int tmpcnt = 0;
        int count = 0;
+       ULONG  k;
+       UCHAR  j;
+#ifdef I2C_ENABLE      
+       USHORT t;
+       UCHAR  n,l;
+#endif 
+
+       static USHORT devid[4] = { ATP865_DEVID1,ATP865_DEVID2,ATP867_DEVID1, 0};
+       static UCHAR page0[16]={0x0d,0,0,8,0,0,0,0,0,0,2,0,0,0,0,0};
+       static UCHAR page1[24]={0x17,0,0,8,0,0,0,0,0,0,2,0,0x81,0x0a,0xc0,0x08,0x18,0x0a,0,0,0,0,0,0};
+       static UCHAR page1c[24]={0x17,0,0,8,0,0,0,0,0,0,2,0,0x9c,0x0a,0,3,0,0,0,0,0,0,0,1};
 
-       static unsigned short devid[9] = {
-         0x8081, 0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0x8060, 0
-       };
 
-       printk(KERN_INFO "aec671x_detect: \n");
+       printk(KERN_INFO "atp86x_detect: \n");
        if (!pci_present()) {
                printk(KERN_INFO"   NO PCI SUPPORT.\n");
                return count;
        }
-       tpnt->proc_name = "atp870u";
-
-       for (h = 0; h < 2; h++) {
-               struct atp_unit *dev = &atp_unit[h];
-               for(k=0;k<16;k++)
+       tpnt->proc_name = "atp86x";
+
+       for (h = 0; h < 4; h++) {
+           devext = &dev_ext[h];
+           for (k=0; k < sizeof(struct hw_device_ext); k++) {
+               ((PUCHAR)devext)[k] = 0;
+           }
+
+           devext->host_id = 0x08;
+
+           for (k=0; k < 8 ; k++) {
+               devext->devtype[k] = 0x7f;
+           }
+
+           for (k=0; k < 16 ; k++) {
+               devext->page0[k]=page0[k];
+           }
+           for (k=0; k < 24 ; k++) {
+               devext->page1[k]=page1[k];
+               devext->page1c[k]=page1c[k];
+           }
+           for (j=0; j < 8; j++)           
+           {
+               for (k=0; k < 16 ; k++) {
+                       devext->sensd[j][k]=0x0;
+               }
+               devext->dskerr_LBA[j]=0;
+           }
+/*         
+           for (j=0; j < 4; j++)
+           {
+               for (k=0; k < qcnt1; k++)
                {
-                       dev->id[k].prd_tableu = kmalloc(1024, GFP_KERNEL);
-                       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;
-               pdev[h]=NULL;
-               pdev[2]=NULL;
-               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] = 0;
-               }
-               for (k = 0; k < 16; k++) {
-                       dev->id[k].curr_req = 0;
-                       dev->sp[k] = 0x04;
-               }
+                   devext->plsrb[j][k]=&devext->lsrb[j][k];
+#ifdef IXP42X_SUPPORT
+//                 devext->lsrb[j][k].prd = kmalloc(256, GFP_ATOMIC|GFP_DMA);
+                   devext->lsrb[j][k].prd = pci_alloc_consistent(hwif->pci_dev,
+                                                 256,
+                                                 &(devext->lsrb[j][k].prdaddr));
+
+#else              
+                   devext->lsrb[j][k].prd = kmalloc(256, GFP_KERNEL);
+                   devext->lsrb[j][k].prdaddr=(ULONG)virt_to_bus(devext->lsrb[j][k].prd);
+#endif             
+               }
+           }
+*/         
+           pdev[h]=NULL;
+           pdev[4]=NULL;
        }
        h = 0;
        while (devid[h] != 0) {
-               pdev[2] = pci_find_device(0x1191, devid[h], pdev[2]);
-               if (pdev[2] == NULL || pci_enable_device(pdev[2])) {
+               pdev[4] = pci_find_device(0x1191, devid[h], pdev[4]);
+               if (pdev[4] == NULL || pci_enable_device(pdev[4])) {
                        h++;
                        index = 0;
                        continue;
                }
-               chip_ver[2] = 0;
-               dev_id[2] = devid[h];
-
-               if (devid[h] == 0x8002) {
-                       error = pci_read_config_byte(pdev[2], 0x08, &chip_ver[2]);
-                       if (chip_ver[2] < 2) {
-                               goto nxt_devfn;
-                       }
-               }
-               if (devid[h] == 0x8010 || devid[h] == 0x8081 || devid[h] == 0x8050)
-               {
-                       chip_ver[2] = 0x04;
-               }
-               pdev[tmpcnt] = pdev[2];
-               chip_ver[tmpcnt] = chip_ver[2];
-               dev_id[tmpcnt] = dev_id[2];
+               dev_id[4] = devid[h];
+               chip_ver[4] = 0;
+               error = pci_read_config_byte(pdev[4], 0x08, &chip_ver[4]);
+//             printk("Chip version = %2X\n",chip_ver[4]);
+//             pci_write_config_byte(pdev[4], 0x0D, 22);
+               pci_write_config_byte(pdev[4], 0x0D, 0x80);//JCC082803
+               pdev[tmpcnt] = pdev[4];
+               chip_ver[tmpcnt] = chip_ver[4];
+               dev_id[tmpcnt] = dev_id[4];
                tmpcnt++;
-             nxt_devfn:
                index++;
                if (index > 3) {
                        index = 0;
                        h++;
                }
-               if(tmpcnt>1)
+               if(tmpcnt>3)
                        break;
        }
-       for (h = 0; h < 2; h++) {
-               struct atp_unit *dev=&atp_unit[h];
+       for (h = 0; h < 4; h++) {
+               devext = &dev_ext[h];
                if (pdev[h]==NULL) {
                        return count;
                }
+               devext->pdev=pdev[h];
+               for (j=0; j < 4; j++)
+               {
+                       for (k=0; k < qcnt1; k++)
+                       {
+                               devext->plsrb[j][k]=&devext->lsrb[j][k];
+#ifdef IXP42X_SUPPORT
+//                             devext->lsrb[j][k].prd = kmalloc(256, GFP_ATOMIC|GFP_DMA);
+                               devext->lsrb[j][k].prd = pci_alloc_consistent(pdev[h],
+                                                                256,  &(devext->lsrb[j][k].prdaddr));
+#else              
+                               devext->lsrb[j][k].prd = kmalloc(256, GFP_KERNEL);
+                               devext->lsrb[j][k].prdaddr=(ULONG)virt_to_bus(devext->lsrb[j][k].prd);
+#endif             
+                       }
+               }               
+               /* Found an atp86x */
 
-               /* Found an atp870u/w. */
                base_io = pci_resource_start(pdev[h], 0);
                irq = pdev[h]->irq;
 
-               if (dev_id[h] != 0x8081)
+               base_io &= 0xfffffff8;
+//#ifdef DETECT_DEBUG          
+//             printk("atp86x:  dev_id[%d] = %X  base_io =  %X .\n",h, dev_id[h], base_io);
+//#endif               
+               if (dev_id[h] ==0x0A)
                {
-                  error = pci_read_config_byte(pdev[h],0x49,&host_id);
-
-                  base_io &= 0xfffffff8;
-
-                  if (check_region(base_io,0x40) != 0)
-                  {
-                          return 0;
-                  }
-                  printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d    IO:%x, IRQ:%d.\n"
-                         ,h, base_io, irq);
-                  dev->ioport = base_io;
-                  dev->pciport = base_io + 0x20;
-                  dev->deviceid = dev_id[h];
-                  irqnumu[h] = irq;
-                  host_id &= 0x07;
-                  dev->host_idu = host_id;
-                  dev->chip_veru = chip_ver[h];
-
-                  tmport = base_io + 0x22;
-                  dev->scam_on = inb(tmport);
-                  tmport += 0x0b;
-                  dev->global_map = inb(tmport++);
-                  dev->ultra_map = inw(tmport);
-                  if (dev->ultra_map == 0) {
-                          dev->scam_on = 0x00;
-                          dev->global_map = 0x20;
-                          dev->ultra_map = 0xffff;
-                  }
-                  shpnt = scsi_register(tpnt, 4);
-                  if(shpnt==NULL)
-                          return count;
-
-                  save_flags(flags);
-                  cli();
-                  if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", dev)) {
-                          printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
-                          goto unregister;
-                  }
-
-                  if (chip_ver[h] > 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);
-                  mydlyu(0x8000);
-                  outb(k, tmport);
-                  mydlyu(0x8000);
-                  tmport = base_io;
-                  outb((host_id | 0x08), tmport);
-                  tmport += 0x18;
-                  outb(0, tmport);
-                  tmport += 0x07;
-                  while ((inb(tmport) & 0x80) == 0);
-                  tmport -= 0x08;
-                  inb(tmport);
-                  tmport = base_io + 1;
-                  outb(8, tmport++);
-                  outb(0x7f, tmport);
-                  tmport = base_io + 0x11;
-                  outb(0x20, tmport);
-
-                  tscam(h);
-                  is870(h, base_io);
-                  tmport = base_io + 0x3a;
-                  outb((inb(tmport) & 0xef), tmport);
-                  tmport++;
-                  outb((inb(tmport) | 0x20),tmport);
+                       if (check_region(base_io,0x80) != 0)
+                       {
+                               return 0;
+                       }
+               
+                       printk(KERN_INFO "   ACARD ATP-867 PCI ATA133 4-Channels Host Adapter: %d    IO:%X, IRQ:%d.\n"
+                               ,h, base_io, irq);
+                       devext->pdev = pdev[h];
+                       devext->chipver = chip_ver[h];
+//                     printk("Chip version = %2X\n",devext->chipver); 
+                       devext->dev_id  = dev_id[h];
+                       devext->BaseIoAddress[0] = base_io;
+                       devext->BaseIoAddress[1] = base_io + 0x10;
+                       devext->BaseIoAddress[2] = base_io + 0x20;
+                       devext->BaseIoAddress[3] = base_io + 0x30;
+                       devext->BaseIoAddresm[0] = base_io + 0x40;
+                       devext->BaseIoAddresm[1] = base_io + 0x50;
+                       devext->BaseIoAddresm[2] = base_io + 0x60;
+                       devext->BaseIoAddresm[3] = base_io + 0x70;                              
                }
                else
                {
-                  base_io &= 0xfffffff8;
-
-                  if (check_region(base_io,0x60) != 0)
-                  {
-                          return 0;
-                  }
-                  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"
-                         ,h, base_io, irq);
-                  dev->ioport = base_io + 0x40;
-                  dev->pciport = base_io + 0x28;
-                  dev->deviceid = dev_id[h];
-                  irqnumu[h] = irq;
-                  dev->host_idu = host_id;
-                  dev->chip_veru = chip_ver[h];
-
-                  tmport = base_io + 0x22;
-                  dev->scam_on = inb(tmport);
-                  tmport += 0x13;
-                  dev->global_map = inb(tmport);
-                  tmport += 0x07;
-                  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;
-                  }
-                  dev->sp[m++]=inb(base_io + 0x30);
-                  dev->sp[m++]=inb(base_io + 0x31);
-                  dev->sp[m++]=inb(base_io + 0x32);
-                  dev->sp[m++]=inb(base_io + 0x33);
-                  outw(n,base_io + 0x34);
-                  n += 0x0002;
-                  dev->sp[m++]=inb(base_io + 0x30);
-                  dev->sp[m++]=inb(base_io + 0x31);
-                  dev->sp[m++]=inb(base_io + 0x32);
-                  dev->sp[m++]=inb(base_io + 0x33);
-                  outw(n,base_io + 0x34);
-                  n += 0x0002;
-                  dev->sp[m++]=inb(base_io + 0x30);
-                  dev->sp[m++]=inb(base_io + 0x31);
-                  dev->sp[m++]=inb(base_io + 0x32);
-                  dev->sp[m++]=inb(base_io + 0x33);
-                  outw(n,base_io + 0x34);
-                  n += 0x0002;
-                  dev->sp[m++]=inb(base_io + 0x30);
-                  dev->sp[m++]=inb(base_io + 0x31);
-                  dev->sp[m++]=inb(base_io + 0x32);
-                  dev->sp[m++]=inb(base_io + 0x33);
-                  n += 0x0018;
-                  goto next_fblk;
-flash_ok:
-                  outw(0,base_io + 0x34);
-                  dev->ultra_map=0;
-                  dev->async = 0;
-                  for (k=0; k < 16; k++)
-                  {
-                      n=1;
-                      n = n << k;
-                      if (dev->sp[k] > 1)
-                      {
-                         dev->ultra_map |= n;
-                      }
-                      else
-                      {
-                         if (dev->sp[k] == 0)
-                         {
-                            dev->async |= n;
-                         }
-                      }
-                  }
-                  dev->async = ~(dev->async);
-                  outb(dev->global_map,base_io + 0x35);
-
-                  shpnt = scsi_register(tpnt, 4);
-                  if(shpnt==NULL)
-                          return count;
-
-                  save_flags(flags);
-                  cli();
-                  if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", dev)) {
-                          printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
-                          goto unregister;
-                  }
+                       devext->pdev = pdev[h]; 
+                       devext->dev_id  = dev_id[h];
+                       devext->chipver = chip_ver[h];                  
 
-                  tmport = base_io + 0x38;
-                  k = inb(tmport) & 0x80;
-                  outb(k, tmport);
-                  tmport += 0x03;
-                  outb(0x20, tmport);
-                  mydlyu(0x8000);
-                  outb(0, tmport);
-                  mydlyu(0x8000);
-                  tmport = base_io + 0x5b;
-                  inb(tmport);
-                  tmport -= 0x04;
-                  inb(tmport);
-                  tmport = base_io + 0x40;
-                  outb((host_id | 0x08), tmport);
-                  tmport += 0x18;
-                  outb(0, tmport);
-                  tmport += 0x07;
-                  while ((inb(tmport) & 0x80) == 0);
-                  tmport -= 0x08;
-                  inb(tmport);
-                  tmport = base_io + 0x41;
-                  outb(8, tmport++);
-                  outb(0x7f, tmport);
-                  tmport = base_io + 0x51;
-                  outb(0x20, tmport);
-
-                  tscam(h);
-                  is880(h, base_io);
-                  tmport = base_io + 0x38;
-                  outb(0xb0, tmport);
-               }
-
-               atp_host[h] = shpnt;
-               if (dev->chip_veru == 4) {
-                       shpnt->max_id = 16;
-               }
-               shpnt->this_id = host_id;
-               shpnt->unique_id = base_io;
-               shpnt->io_port = base_io;
-               if (dev_id[h] == 0x8081)
+                       if (check_region(base_io,0x8) != 0)
+                       {
+                               return 0;
+                       }
+                       printk(KERN_INFO "   ACARD ATP-865 PCI ATA133 2-Channels Host Adapter: %d    IO:%X, IRQ:%d.\n"
+                               ,h, base_io, irq);                              
+//                     printk("Chip version = %2X\n",devext->chipver);                         
+                       devext->BaseIoAddress[0] = base_io;                                             
+                       base_io = pci_resource_start(pdev[h],1);
+#ifdef DETECT_DEBUG                                    
+                       printk("atp865:  dev_id[%d] = %04X  base_io 1 =  %04X .\n",h, dev_id[h], base_io);                                              
+#endif                 
+                       if (check_region(base_io,0x3) != 0)
+                       {
+                               return 0;
+                       }                       
+                       devext->BaseIoAddress[2] = base_io +2;
+                       base_io = pci_resource_start(pdev[h],2);
+#ifdef DETECT_DEBUG                                                            
+                       printk("atp865:  dev_id[%d] = %04X  base_io 2 =  %04X .\n",h, dev_id[h], base_io);                                              
+#endif                                         
+                       if (check_region(base_io,0x8) != 0)
+                       {
+                               return 0;
+                       }                       
+                       devext->BaseIoAddress[1] = base_io ;                    
+                       base_io = pci_resource_start(pdev[h],3);
+#ifdef DETECT_DEBUG                                    
+                       printk("atp865:  dev_id[%d] = %04X  base_io 3 =  %04X .\n",h, dev_id[h], base_io);                                              
+#endif                                         
+                       if (check_region(base_io,0x3) != 0)
+                       {
+                               return 0;
+                       }                       
+                       devext->BaseIoAddress[3] = base_io +2;                  
+                       base_io = pci_resource_start(pdev[h],4);
+#ifdef DETECT_DEBUG                                                            
+                       printk("atp865:  dev_id[%d] = %04X  base_io 4 =  %04X .\n",h, dev_id[h], base_io);                                              
+#endif                                         
+                       if (check_region(base_io,0x10) != 0)
+                       {
+                               return 0;
+                       }               
+                       devext->BaseIoAddresm[0] = base_io ;                            
+                       devext->BaseIoAddresm[1] = base_io + 0x08;
+                       devext->BaseIoAddresm[2] = base_io + 0x02;
+                       devext->BaseIoAddresm[3] = base_io + 0x0A;                                      
+               }
+               devext->irq = irq;
+               irqnumu[h] = irq;
+
+               shpnt = scsi_register(tpnt, 4);
+               if(shpnt==NULL)
                {
-                  shpnt->n_io_port = 0x60;        /* Number of bytes of I/O space used */
+                       printk(KERN_INFO "scsi_register failure!!\n");
+                       return count;
                }
-               else
+
+               save_flags(flags);
+               cli();
+               if (request_irq(irq, atp86x_intr_handle, SA_SHIRQ, "atp86x", devext)) {
+                       printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
+                       goto unregister;
+               }
+               
+               if (dev_id[h] ==0x0A)
+               {               
+#ifdef DETECT_DEBUG                                                                            
+                       printk("atp867: Out 0x10 to port 0x28 \n");
+#endif         
+                       j=Inpb(base_io,0x28);
+                       j |= 0x10;
+                       Outpb(base_io,0x28,j);
+#ifdef DETECT_DEBUG                                                                                            
+                       printk("atp867: is867 enter \n");
+#endif         
+                       is867(devext);
+#ifdef DETECT_DEBUG
+                       printk("atp867: is867 exit \n");
+                       printk("atp867: clear bit4,5 and set bit 6,7 to port 0x28 \n");
+#endif         
+                       j=Inpb(base_io,0x28);
+                       j &= 0xcf;
+                       j |= 0xc0;
+                       Outpb(base_io,0x28,j);
+#ifdef DETECT_DEBUG
+                       printk("atp867: clear bit0-3 to port 0x29 \n");
+#endif         
+                       baseIoAddress = devext->BaseIoAddress[0];
+                       Outpb(baseIoAddress,0x29,(UCHAR)
+                               (Inpb(baseIoAddress,0x29) & 0xe0));
+#ifdef I2C_ENABLE
+#ifdef DETECT_DEBUG
+                       printk("atp867: I2C init \n");
+#endif                                 
+                       for (t=0; t < 4; t++)
+                       {
+                               baseIoAddress = devext->BaseIoAddress[t];
+                               j=0;
+                               n=0;
+                               l=0;
+                               Outpb(baseIoAddress,0x0e,0x08);
+                               i2cwrite(baseIoAddress,0x4e,0x80);
+                               i2cread(baseIoAddress,0x4f,&j);
+                               i2cwrite(baseIoAddress,0x4e,0x00);
+                               i2cread(baseIoAddress,0x4f,&n);
+                               i2cread(baseIoAddress,0x58,&l);
+                               if ((j == 0x5c) && (n == 0xa3) && (l == 0x40))
+                               {
+                                       j=0x10;
+                                       j <<= t;
+                                       devext->c_mask |= j;
+                                       i2cread(baseIoAddress,0x41,&j);
+                                       i2cread(baseIoAddress,0x42,&j);
+                                       i2cwrite(baseIoAddress,0x43,0xf8);
+                                       i2cwrite(baseIoAddress,0x44,0x0e);
+                                       i2cwrite(baseIoAddress,0x2b,0xff);
+                                       i2cwrite(baseIoAddress,0x2c,0x3e);
+                                       i2cwrite(baseIoAddress,0x2f,0xff);
+                                       i2cwrite(baseIoAddress,0x30,0x3e);
+                                       i2cwrite(baseIoAddress,0x33,0xff);
+                                       i2cwrite(baseIoAddress,0x34,0x3e);
+                                       i2cwrite(baseIoAddress,0x4d,0xc0);
+                                       i2cread(baseIoAddress,0x40,&j);
+                                       i2cread(baseIoAddress,0x41,&j);
+                                       i2cread(baseIoAddress,0x42,&j);
+                                       i2cread(baseIoAddress,0x43,&j);
+                                       i2cread(baseIoAddress,0x44,&j);
+                                       i2cread(baseIoAddress,0x2b,&j);
+                                       i2cread(baseIoAddress,0x2c,&j);
+                                       i2cread(baseIoAddress,0x2f,&j);
+                                       i2cread(baseIoAddress,0x30,&j);
+                                       i2cread(baseIoAddress,0x33,&j);
+                                       i2cread(baseIoAddress,0x34,&j);
+                                       i2cread(baseIoAddress,0x4d,&j);
+                                       i2cwrite(baseIoAddress,0x40,0x43);
+                                       Outpb(baseIoAddress,0x0e,0x08);
+                                       i2cread(baseIoAddress,0x41,&j);
+                                       i2cread(baseIoAddress,0x42,&j);
+                                       if (devext->hd_status[t << 1] == 0)
+                                       {
+                                               Outpb(baseIoAddress,0x43,0x84);
+                                       }
+                                       else
+                                       {
+                                               Outpb(baseIoAddress,0x43,0x80);
+                                       }
+                                       Outpb(baseIoAddress,0x0e,0x08);
+                                       Outpb(baseIoAddress,0x43,0x20);
+                                       baseIoAddress = devext->BaseIoAddress[0];
+                                       Outpb(baseIoAddress,0x29,(UCHAR)
+                                               (Inpb(baseIoAddress,0x29) | 0x10));
+                               }
+                       }
+#endif                 
+                       baseIoAddress = devext->BaseIoAddress[0];
+#ifdef DETECT_DEBUG
+                       printk("atp867: Out 0x06 to port 0x42,0x52,0x62,0x72\n");
+#endif         
+                       Outpb(base_io,0x42,0x06);
+                       Outpb(base_io,0x52,0x06);
+                       Outpb(base_io,0x62,0x06);
+                       Outpb(base_io,0x72,0x06);
+               }
+               else  // of device_id = 0x0A
                {
-                  shpnt->n_io_port = 0x40;        /* Number of bytes of I/O space used */
-               }
+#ifdef DETECT_DEBUG
+                       printk("atp865: scan device start here\n");
+#endif                                 
+                       
+                       /*  PCI config + 0x40 + 0xA:    bit 0: 1= disable INTA  */
+#ifdef DETECT_DEBUG
+                       printk("atp865: read config + 0x4A\n");
+#endif                                 
+                       pci_read_config_byte(pdev[h], 0x4A, &j);                
+#ifdef DETECT_DEBUG
+                       printk("atp865: read config + 0x4A = %X\n",j);
+#endif                                 
+                       j |= 0x01;
+                       pci_write_config_byte(pdev[h], 0x4A, j);
+#ifdef DETECT_DEBUG
+                       printk("atp865: write config + 0x4A = %X\n",j);
+#endif         
+                       is865(devext,pdev[h]);
+////                   ATP865init(devext);
+                       /*  PCI config + 0x40 + 0xA:    bit 0: 0= enable INTA   
+                                                       bit 7: 1= enable PCI bus master 
+                       */
+#ifdef DETECT_DEBUG
+                       printk("atp865: read config + 0x4A\n");
+#endif                                 
+                       pci_read_config_byte(pdev[h], 0x4A, &j);                
+#ifdef DETECT_DEBUG
+                       printk("atp865: read config + 0x4A = %X\n",j);
+#endif                                 
+                       j &= 0xfe;                      
+                       j |= 0x88;
+                       pci_write_config_byte(pdev[h], 0x4A, j);
+#ifdef DETECT_DEBUG
+                       printk("atp865: write config + 0x4A = %X\n",j);
+#endif                                 
+                       /* disable pre-read or post write ,  delayed IRQ */
+                       pci_write_config_byte(pdev[h], 0x4B, 0);                        
+#ifdef DETECT_DEBUG
+                       printk("atp865: write config + 0x4B = 0\n");
+#endif                                 
+                       /* Pre-read counter must be 0x000200  4C,4D,4E - 14,15,16*/ 
+                       pci_write_config_byte(pdev[h], 0x4C, 0);
+#ifdef DETECT_DEBUG
+                       printk("atp865: write config + 0x4C = 0\n");
+#endif                                 
+                       pci_write_config_byte(pdev[h], 0x4D, 0x02);                     
+#ifdef DETECT_DEBUG
+                       printk("atp865: write config + 0x4D = 0x02\n");
+#endif                                 
+                       pci_write_config_byte(pdev[h], 0x4E, 0);                        
+#ifdef DETECT_DEBUG
+                       printk("atp865: write config + 0x4E = 0\n");
+#endif                                 
+                       pci_write_config_byte(pdev[h], 0x14, 0);
+#ifdef DETECT_DEBUG
+                       printk("atp865: write config + 0x14 = 0\n");
+#endif                                 
+                       pci_write_config_byte(pdev[h], 0x15, 0x02);                     
+#ifdef DETECT_DEBUG
+                       printk("atp865: write config + 0x15 = 0x02\n");
+#endif                                 
+                       pci_write_config_byte(pdev[h], 0x16, 0);
+#ifdef DETECT_DEBUG
+                       printk("atp865: write config + 0x16 = 0\n");
+#endif                                 
+
+                       baseIoAddress = devext->BaseIoAddress[0];
+                       
+                       /* Clear Latched IRQ bit and DMA error bit for each channel */
+                       /* set both drives DMA mode for each channel? */
+                       base_io = devext->BaseIoAddresm[0];     
+#ifdef DETECT_DEBUG
+                       printk("atp865: write io= %X , 0x66\n", base_io+0x2);
+                       printk("atp865: write io= %X , 0x66\n", base_io+0xA);                   
+#endif                                 
+                       Outpb(base_io,0x2,0x66);
+                       Outpb(base_io,0xA,0x66);                        
+#ifdef DETECT_DEBUG
+                       printk("atp865: scan device end here\n");
+#endif                                 
+               }
+
+               a867host[h] = shpnt;
+               shpnt->max_id = 9;
+               shpnt->this_id = 0x08;
+               shpnt->unique_id = base_io;
+               shpnt->io_port = base_io;
+               shpnt->n_io_port = 0x80;        /* Number of bytes of I/O space used */
                shpnt->irq = irq;
                restore_flags(flags);
-               if (dev_id[h] == 0x8081)
+               if (dev_id[h] ==0x0A)           
                {
-                  request_region(base_io, 0x60, "atp870u");       /* Register the IO ports that we use */
+#ifdef DETECT_DEBUG
+                       printk("atp867: request region: base_io , 0x80\n");
+#endif                         
+                       request_region(base_io, 0x80, "atp86x"); /* Register the IO ports that we use */
                }
                else
                {
-                  request_region(base_io, 0x40, "atp870u");       /* Register the IO ports that we use */
-               }
+#ifdef DETECT_DEBUG
+                       printk("atp865: request region: devext->BaseIoAddress[0] , 0x8\n");
+#endif                         
+                       request_region(devext->BaseIoAddress[0], 0x8, "atp86x"); /* Register the IO ports that we use */
+#ifdef DETECT_DEBUG
+                       printk("atp865: request region: devext->BaseIoAddress[1] , 0x3\n");
+#endif                         
+                       request_region(devext->BaseIoAddress[2], 0x3, "atp86x"); /* Register the IO ports that we use */                        
+#ifdef DETECT_DEBUG
+                       printk("atp865: request region: devext->BaseIoAddress[2] , 0x8\n");
+#endif                         
+                       request_region(devext->BaseIoAddress[1], 0x8, "atp86x"); /* Register the IO ports that we use */
+#ifdef DETECT_DEBUG
+                       printk("atp865: request region: devext->BaseIoAddress[3] , 0x3\n");
+#endif                         
+                       request_region(devext->BaseIoAddress[3], 0x3, "atp86x"); /* Register the IO ports that we use */                                                
+#ifdef DETECT_DEBUG
+                       printk("atp865: request region: devext->BaseIoAddresm[0] , 0x10\n");
+#endif                         
+                       request_region(devext->BaseIoAddresm[0], 0x10, "atp86x"); /* Register the IO ports that we use */                                                                       
+                       
+               }
+// add for smart read  =================//
+       init_timer(&(devext->AdapterTimer));
+       (devext->AdapterTimer).expires  = jiffies + 100;         // active per second
+       (devext->AdapterTimer).data             = (ULONG)(devext);
+       (devext->AdapterTimer).function = smart_timer;
+       add_timer(&(devext->AdapterTimer));
+//======================================//
                count++;
                index++;
                continue;
@@ -2695,98 +2829,914 @@ unregister:
        return count;
 }
 
+#ifdef I2C_ENABLE
+
+int i2cwrite(ULONG baseIoAddress, UCHAR Rindex, UCHAR Rval)
+{
+       UCHAR   i,j,k,l;
+
+       Outpb(baseIoAddress,0x43,0x81);
+       mdelay(0x10);
+       j=0x81;
+       k=0x5a;
+       for (i=0; i < 8; i++)
+       {
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j &= 0xfd;
+       if ((k & 0x80) != 0)
+       {
+          j |= 0x02;
+       }
+       k <<= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       }
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x02;
+       Outpb(baseIoAddress,0x43,j);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       l=Inpb(baseIoAddress,0x43);
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       if ((l & 0x02) != 0)
+       {
+         Outpb(baseIoAddress,0x43,1);
+         return FALSE;
+       }
+       for (i=0; i < 8; i++)
+       {
+       j &= 0xfd;
+       if ((Rindex & 0x80) != 0)
+       {
+          j |= 0x02;
+       }
+       Rindex <<= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       }
+       j |= 0x02;
+       Outpb(baseIoAddress,0x43,j);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       l=Inpb(baseIoAddress,0x43);
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       if ((l & 0x02) != 0)
+       {
+         Outpb(baseIoAddress,0x43,1);
+         return FALSE;
+       }
+       for (i=0; i < 8; i++)
+       {
+       j &= 0xfd;
+       if ((Rval & 0x80) != 0)
+       {
+          j |= 0x02;
+       }
+       Rval <<= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       }
+       j |= 0x02;
+       Outpb(baseIoAddress,0x43,j);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       l=Inpb(baseIoAddress,0x43);
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       Outpb(baseIoAddress,0x43,1);
+       if ((l & 0x02) != 0)
+       {
+         return FALSE;
+       }
+       return TRUE;
+}
+
+int i2cread(ULONG baseIoAddress, UCHAR Rindex, PUCHAR Rval)
+{
+       UCHAR   i,j,k,l;
+
+       Outpb(baseIoAddress,0x43,0x81);
+       mdelay(0x10);
+       j=0x81;
+       k=0x5a;
+       for (i=0; i < 8; i++)
+       {
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j &= 0xfd;
+       if ((k & 0x80) != 0)
+       {
+          j |= 0x02;
+       }
+       k <<= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       }
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x02;
+       Outpb(baseIoAddress,0x43,j);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       l=Inpb(baseIoAddress,0x43);
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       if ((l & 0x02) != 0)
+       {
+         Outpb(baseIoAddress,0x43,1);
+         return FALSE;
+       }
+       for (i=0; i < 8; i++)
+       {
+       j &= 0xfd;
+       if ((Rindex & 0x80) != 0)
+       {
+          j |= 0x02;
+       }
+       Rindex <<= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       }
+       j |= 0x02;
+       Outpb(baseIoAddress,0x43,j);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       l=Inpb(baseIoAddress,0x43);
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       if ((l & 0x02) != 0)
+       {
+         Outpb(baseIoAddress,0x43,1);
+         return FALSE;
+       }
+
+       Outpb(baseIoAddress,0x43,0x81);
+       mdelay(0x10);
+       j=0x81;
+       k=0x5b;
+       for (i=0; i < 8; i++)
+       {
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j &= 0xfd;
+       if ((k & 0x80) != 0)
+       {
+          j |= 0x02;
+       }
+       k <<= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       }
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x02;
+       Outpb(baseIoAddress,0x43,j);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       l=Inpb(baseIoAddress,0x43);
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       if ((l & 0x02) != 0)
+       {
+         Outpb(baseIoAddress,0x43,1);
+         return FALSE;
+       }
+       *Rval=0;
+       for (i=0; i < 8; i++)
+       {
+       *Rval <<= 0x01;
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       l=Inpb(baseIoAddress,0x43);
+       if ((l & 0x02) != 0)
+       {
+          *Rval |= 0x01;
+       }
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       }
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j &= 0xfd;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x01;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j |= 0x02;
+       Outpb(baseIoAddress,0x43,j);
+       mdelay(0x10);
+       j &= 0xfe;
+       Outpb(baseIoAddress,0x43,j);
+       Outpb(baseIoAddress,0x43,1);
+       return TRUE;
+}
+#endif
+
 /* The abort command does not leave the device in a clean state where
    it is available to be used again.  Until this gets worked out, we will
    leave it commented out.  */
 
-int atp870u_abort(Scsi_Cmnd * SCpnt)
+int atp86x_abort(Scsi_Cmnd * SCpnt)
 {
-       unsigned char h, j, k;
-       Scsi_Cmnd *workrequ;
-       unsigned int tmport;
-       struct atp_unit *dev;
+       unsigned char h;
+       ULONG tmport;
+       struct hw_device_ext *devext;
+
        for (h = 0; h <= admaxu; h++) {
-               if (SCpnt->host == atp_host[h]) {
+               if (SCpnt->host == a867host[h]) {
                        goto find_adp;
                }
        }
        panic("Abort host not found !");
 find_adp:
-       dev=&atp_unit[h];
-       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++) {
-               printk(" r%2x=%2x", j, inb(tmport++));
-       }
-       tmport += 0x05;
-       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));
-       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);
-          }
-       }
+       devext=&dev_ext[h];
+       printk(KERN_DEBUG "c0=%x c1=%x c2=%x c3=%x ", (u_int)devext->CSrb[0],
+         (u_int)devext->CSrb[1],(u_int)devext->CSrb[2],(u_int)devext->CSrb[3]);
+       tmport=devext->BaseIoAddress[0];
+       printk(KERN_DEBUG " r%2x=%2x", 0x2a, inb(tmport+0x2a));
        return (SCSI_ABORT_SNOOZE);
 }
 
-int atp870u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
+int atp86x_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
 {
-       unsigned char h;
-       struct atp_unit *dev;
+       UCHAR h,i,j;
+#ifdef I2C_ENABLE      
+       UCHAR k,l;
+#endif 
+       ULONG baseIoAddress;
+       struct hw_device_ext *devext;
        /*
         * See if a bus reset was suggested.
         */
        for (h = 0; h <= admaxu; h++) {
-               if (SCpnt->host == atp_host[h]) {
+               if (SCpnt->host == a867host[h]) {
                        goto find_host;
                }
        }
        panic("Reset bus host not found !");
 find_host:
-       dev=&atp_unit[h];
-/*     SCpnt->result = 0x00080000;
+       devext=&dev_ext[h];
+       if (devext->dev_id == ATP867_DEVID1)
+       {
+               // BaseIO+0x28: bit 4=1 disable INTA
+               baseIoAddress = devext->BaseIoAddress[0];
+               Outpb(baseIoAddress,0x28,(UCHAR)
+                       (Inpb(baseIoAddress,0x28) | 0x10));
+               // Stop PCI transfer for all channels                   
+               Outpb(baseIoAddress,0x40,0);
+               Outpb(baseIoAddress,0x50,0);
+               Outpb(baseIoAddress,0x60,0);
+               Outpb(baseIoAddress,0x70,0);
+#ifdef I2C_ENABLE              
+               if (devext->c_mask != 0)
+               {
+                       i=devext->c_mask;
+                       for (k=0; k < 4; k++)
+                       {
+                               if ((i & 0x10) != 0)
+                               {
+                                       baseIoAddress = devext->BaseIoAddress[k];
+                                       i2cread(baseIoAddress,0x41,&l);
+                                       i2cread(baseIoAddress,0x42,&l);
+                                       i2cread(baseIoAddress,0x40,&l);
+                                       i2cread(baseIoAddress,0x41,&l);
+                                       i2cread(baseIoAddress,0x42,&l);
+                                       Outpb(baseIoAddress,0x43,0x20);
+                               }
+                               i >>= 1;
+                       }
+                       baseIoAddress = devext->BaseIoAddress[0];
+               }
+#else
+               baseIoAddress = devext->BaseIoAddress[0];
+#endif         
+               // Enable Master IDE PreRead
+               Outpb(baseIoAddress,0x41,(UCHAR)
+                       (Inpb(baseIoAddress,0x41) | 0x10));
+               Outpb(baseIoAddress,0x51,(UCHAR)
+                       (Inpb(baseIoAddress,0x51) | 0x10));
+               Outpb(baseIoAddress,0x61,(UCHAR)
+                       (Inpb(baseIoAddress,0x61) | 0x10));
+               Outpb(baseIoAddress,0x71,(UCHAR)
+                       (Inpb(baseIoAddress,0x71) | 0x10));
+               mdelay(0x100);
+               // Disable Master IDE PreRead           
+               Outpb(baseIoAddress,0x41,(UCHAR)
+                       (Inpb(baseIoAddress,0x41) & 0xef));
+               Outpb(baseIoAddress,0x51,(UCHAR)
+                       (Inpb(baseIoAddress,0x51) & 0xef));
+               Outpb(baseIoAddress,0x61,(UCHAR)
+                       (Inpb(baseIoAddress,0x61) & 0xef));
+               Outpb(baseIoAddress,0x71,(UCHAR)
+                       (Inpb(baseIoAddress,0x71) & 0xef));
+               ATP867init(devext);
+       }
+       else
+       {
+
+               // CFG_base+0x40+0x0A: bit 0 =1 disable INTA
+               pci_read_config_byte(devext->pdev, 0x4A, &j);
+#ifdef RESET_DEBUG             
+               printk("865RESET: Read: config+0x4A= %2X\n",j);
+#endif                         
+               j |= 0x01;
+               pci_write_config_byte(devext->pdev, 0x4A, j);
+#ifdef RESET_DEBUG             
+               printk("865RESET: Write: config+0x4A= %2X\n",j);
+#endif                                         
+
+               // Stop PCI transfer for all channels   
+               Outpb(devext->BaseIoAddresm[0],0,0);
+               Outpb(devext->BaseIoAddresm[1],0,0);            
+#ifdef RESET_DEBUG             
+               printk("865RESET: Write: IO%4lX and %4lX=0\n",devext->BaseIoAddresm[0],devext->BaseIoAddresm[1]);
+#endif                                         
+               /* disable pre-read or post write ,  delayed IRQ */
+               pci_write_config_byte(devext->pdev, 0x4B, 0);                   
+               mdelay(0x100);  
+               /* Pre-read counter must be 0x000200  4C,4D,4E - 14,15,16*/ 
+               pci_write_config_byte(devext->pdev, 0x4C, 0);
+               pci_write_config_byte(devext->pdev, 0x4D, 0x02);                        
+               pci_write_config_byte(devext->pdev, 0x4E, 0);                   
+               pci_write_config_byte(devext->pdev, 0x14, 0);
+               pci_write_config_byte(devext->pdev, 0x15, 0x02);                        
+               pci_write_config_byte(devext->pdev, 0x16, 0);
+       
+               ATP865init(devext);     
+               
+               /*  PCI config + 0x40 + 0xA:    bit 0: 0= enable INTA   
+                                                       bit 7: 1= enable PCI bus master 
+               */
+#ifdef RESET_DEBUG
+               printk("atp865: read config + 0x4A\n");
+#endif                                 
+               pci_read_config_byte(devext->pdev, 0x4A, &j);           
+#ifdef RESET_DEBUG
+               printk("atp865: read config + 0x4A = %X\n",j);
+#endif                                 
+               j &= 0xfe;                      
+               j |= 0x88;
+               pci_write_config_byte(devext->pdev, 0x4A, j);           
+               
+/*             // Enable Master IDE PreRead
+               Outpb(baseIoAddress,0x41,(UCHAR)
+                       (Inpb(baseIoAddress,0x41) | 0x10));
+               Outpb(baseIoAddress,0x51,(UCHAR)
+                       (Inpb(baseIoAddress,0x51) | 0x10));
+               Outpb(baseIoAddress,0x61,(UCHAR)
+                       (Inpb(baseIoAddress,0x61) | 0x10));
+               Outpb(baseIoAddress,0x71,(UCHAR)
+                       (Inpb(baseIoAddress,0x71) | 0x10));
+               mdelay(0x100);
+               // Disable Master IDE PreRead           
+               Outpb(baseIoAddress,0x41,(UCHAR)
+                       (Inpb(baseIoAddress,0x41) & 0xef));
+               Outpb(baseIoAddress,0x51,(UCHAR)
+                       (Inpb(baseIoAddress,0x51) & 0xef));
+               Outpb(baseIoAddress,0x61,(UCHAR)
+                       (Inpb(baseIoAddress,0x61) & 0xef));
+               Outpb(baseIoAddress,0x71,(UCHAR)
+                       (Inpb(baseIoAddress,0x71) & 0xef));             
+*/                     
+       
+       }
+
+//     S3init(devext);
+
+       for (i=0; i < 4 ; i++) {
+               devext->CSrb[i]=0;
+               devext->que_hd[i]=0;
+               devext->que_end[i]=0;
+       }
+       devext->in_int=0;
+/*
+       SCpnt->result = 0x00080000;
        SCpnt->scsi_done(SCpnt);
-       dev->working=0;
-       dev->quhdu=0;
-       dev->quendu=0;
        return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET);  */
        return (SCSI_RESET_SNOOZE);
 }
 
-const char *atp870u_info(struct Scsi_Host *notused)
+void ATP867init(struct hw_device_ext * devext)
+{
+    ULONG baseIoAddress = devext->BaseIoAddress[0];
+    ULONG baseIoAddresm = devext->BaseIoAddresm[0];
+    UCHAR  i,j,k,l,ata66,is66,iswd;
+    UCHAR  cbuf[4];
+    USHORT m,mbuf[256];
+#ifdef I2C_ENABLE
+    UCHAR  n;
+#endif    
+
+    mdelay(10000);
+    Outpb(baseIoAddress,0x28,(UCHAR)
+           (Inpb(baseIoAddress,0x28) | 0x10));
+
+    if (devext->chipver < 0x10)
+    {
+       Outpb(baseIoAddress,0x3f,0x08);
+    }
+    else
+    {
+       Outpb(baseIoAddress,0x3f,0x0a);
+    }
+    Outpb(baseIoAddress,0x4a,0x43);
+    Outpb(baseIoAddress,0x5a,0x43);
+    Outpb(baseIoAddress,0x6a,0x43);
+    Outpb(baseIoAddress,0x7a,0x43);
+    ata66=devext->ata66;
+    Outpb(baseIoAddress,0x48,0x31);
+    Outpb(baseIoAddress,0x49,0x31);
+    Outpb(baseIoAddress,0x4b,0x00);
+    Outpb(baseIoAddress,0x58,0x31);
+    Outpb(baseIoAddress,0x59,0x31);
+    Outpb(baseIoAddress,0x5b,0x00);
+    Outpb(baseIoAddress,0x68,0x31);
+    Outpb(baseIoAddress,0x69,0x31);
+    Outpb(baseIoAddress,0x6b,0x00);
+    Outpb(baseIoAddress,0x78,0x31);
+    Outpb(baseIoAddress,0x79,0x31);
+    Outpb(baseIoAddress,0x7b,0x00);
+    cbuf[0] = 0x00;
+    cbuf[1] = 0x00;
+    cbuf[2] = 0x00;
+    cbuf[3] = 0x00;
+
+    for ( i = 0 ; i < 8 ; i++ )
+    {
+       baseIoAddress=devext->BaseIoAddress[i >> 1];
+       j=0xa0;
+       if ((i & 0x01) != 0)
+       {
+          j=0xb0;
+       }
+       Outpb(baseIoAddress,6,j);
+       mdelay(100);
+       k=Inpb(baseIoAddress,7);
+       if ((k & 0x88) != 0x00)
+       {
+          devext->hd_status[i]=0x7f;
+          devext->cap[i]=0;
+          continue;
+       }
+wait_drdy:
+       l=Inpb(baseIoAddress,7);
+       if ((l & 0x80) != 0 )
+       {
+          goto wait_drdy;
+       }
+       Outpb(baseIoAddress,7,0xec);
+       mdelay(400);
+wait_drq:
+       l=Inpb(baseIoAddress,7);
+       if ((l & 0x80) != 0 )
+       {
+         goto wait_drq;
+       }
+       if ((l & 0x01) == 0x01 )
+       {
+         devext->hd_status[i]=0x7f;
+         devext->cap[i]=0;
+         continue;
+       }
+       if ((l & 0xf8) != 0x58 )
+       {
+         devext->hd_status[i]=0x7f;
+         devext->cap[i]=0;
+         continue;
+       }
+       for (m=0; m < 0x100; m++)
+       {
+         mbuf[m]=Inpw(baseIoAddress,0);
+       }
+
+       is66=0;
+       iswd=0;
+
+       Outpb(baseIoAddress,1,0x03);
+       if ((mbuf[88] & 0x0018) == 0)
+       {
+         if ((iswd == 0) && ((mbuf[88] & 0x007f) != 0))
+         {
+            Outpb(baseIoAddress,2,0x42);
+         }
+         else
+         {
+force_normdma:
+            k=(UCHAR)(mbuf[63] & 0x0007);
+            k >>= 1;
+            if (k > 2)
+               k=2;
+            k |= 0x20;
+            Outpb(baseIoAddress,2,k);
+            iswd=1;
+         }
+       }
+       else
+       {
+         if ( iswd != 0 )
+         {
+            goto force_normdma;
+         }
+
+         if (((i < 2) && ((ata66 & 0x01) == 0)) ||
+             ((i > 1) && ((ata66 & 0x02) == 0)))
+         {
+            if ((mbuf[88] & 0x0020) == 0)
+            {
+               Outpb(baseIoAddress,2,0x44);
+               is66=1;
+            }
+            else
+            {
+               if ((mbuf[88] & 0x0040) == 0)
+               {
+                  is66=2;
+                  Outpb(baseIoAddress,2,0x45);
+               }
+               else
+               {
+                  is66=3;
+                  Outpb(baseIoAddress,2,0x46);
+               }
+            }
+         }
+         else
+         {
+            Outpb(baseIoAddress,2,0x42);
+         }
+       }
+       Outpb(baseIoAddress,7,0xef);
+       mdelay(1000);
+       k=Inpb(baseIoAddress,7);
+       while ((k & 0x80) != 0)
+       {
+        k=Inpb(baseIoAddress,7);
+       }
+       if ((k & 0xf9) == 0x50)
+       {
+         if ( is66 == 0)
+         {
+           if ( iswd == 0 )
+           {
+              if ( i == 0 )
+              {
+                 cbuf[0] |= 0x03;
+              }
+              if ( i == 1 )
+              {
+                 cbuf[0] |= 0x30;
+              }
+              if ( i == 2 )
+              {
+                 cbuf[1] |= 0x03;
+              }
+              if ( i == 3 )
+              {
+                 cbuf[1] |= 0x30;
+              }
+              if ( i == 4 )
+              {
+                 cbuf[2] |= 0x03;
+              }
+              if ( i == 5 )
+              {
+                 cbuf[2] |= 0x30;
+              }
+              if ( i == 6 )
+              {
+                 cbuf[3] |= 0x03;
+              }
+              if ( i == 7 )
+              {
+                 cbuf[3] |= 0x30;
+              }
+           }
+         }
+         else
+         {
+            if ( i == 0 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[0] |= 0x05;
+               }
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[0] |= 0x06;
+                  else
+                     cbuf[0] |= 0x07;
+               }
+            }
+            if ( i == 1 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[0] |= 0x50;
+               }
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[0] |= 0x60;
+                  else
+                     cbuf[0] |= 0x70;
+               }
+            }
+            if ( i == 2 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[1] |= 0x05;
+               }
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[1] |= 0x06;
+                  else
+                     cbuf[1] |= 0x07;
+               }
+            }
+            if ( i == 3 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[1] |= 0x50;
+               }
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[1] |= 0x60;
+                  else
+                     cbuf[1] |= 0x70;
+               }
+            }
+            if ( i == 4 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[2] |= 0x05;
+               }
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[2] |= 0x06;
+                  else
+                     cbuf[2] |= 0x07;
+               }
+            }
+            if ( i == 5 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[2] |= 0x50;
+               }
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[2] |= 0x60;
+                  else
+                     cbuf[2] |= 0x70;
+               }
+            }
+            if ( i == 6 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[3] |= 0x05;
+               }
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[3] |= 0x06;
+                  else
+                     cbuf[3] |= 0x07;
+               }
+            }
+            if ( i == 7 )
+            {
+               if ( is66 == 1 )
+               {
+                  cbuf[3] |= 0x50;
+               }
+               else
+               {
+                  if ( is66 == 2 )
+                     cbuf[3] |= 0x60;
+                  else
+                     cbuf[3] |= 0x70;
+               }
+            }
+         }
+       }
+    }
+    baseIoAddress=devext->BaseIoAddress[0];
+    Outpb(baseIoAddress,0x4b,cbuf[0]);
+    Outpb(baseIoAddress,0x5b,cbuf[1]);
+    Outpb(baseIoAddress,0x6b,cbuf[2]);
+    Outpb(baseIoAddress,0x7b,cbuf[3]);
+
+    j=Inpb(baseIoAddress,0x28);
+    j &= 0xcf;
+    j |= 0xd0;
+    Outpb(baseIoAddress,0x28,j);
+    Outpb(baseIoAddress,0x29,(UCHAR)
+           (Inpb(baseIoAddress,0x29) & 0xe0));
+    devext->c_mask = 0;
+#ifdef I2C_ENABLE    
+    for (i=0; i < 4; i++)
+    {
+       baseIoAddress = devext->BaseIoAddress[i];
+       j=0;
+       n=0;
+       l=0;
+       Outpb(baseIoAddress,0x0e,0x08);
+       i2cwrite(baseIoAddress,0x4e,0x80);
+       i2cread(baseIoAddress,0x4f,&j);
+       i2cwrite(baseIoAddress,0x4e,0x00);
+       i2cread(baseIoAddress,0x4f,&n);
+       i2cread(baseIoAddress,0x58,&l);
+       if ((j == 0x5c) && (n == 0xa3) && (l == 0x40))
+       {
+          j=0x10;
+          j <<= i;
+          devext->c_mask |= j;
+          i2cread(baseIoAddress,0x41,&j);
+          i2cread(baseIoAddress,0x42,&j);
+          i2cwrite(baseIoAddress,0x43,0xf8);
+          i2cwrite(baseIoAddress,0x44,0x0e);
+          i2cwrite(baseIoAddress,0x2b,0xff);
+          i2cwrite(baseIoAddress,0x2c,0x3e);
+          i2cwrite(baseIoAddress,0x2f,0xff);
+          i2cwrite(baseIoAddress,0x30,0x3e);
+          i2cwrite(baseIoAddress,0x33,0xff);
+          i2cwrite(baseIoAddress,0x34,0x3e);
+          i2cwrite(baseIoAddress,0x4d,0xc0);
+          i2cread(baseIoAddress,0x40,&j);
+          i2cread(baseIoAddress,0x41,&j);
+          i2cread(baseIoAddress,0x42,&j);
+          i2cread(baseIoAddress,0x43,&j);
+          i2cread(baseIoAddress,0x44,&j);
+          i2cread(baseIoAddress,0x2b,&j);
+          i2cread(baseIoAddress,0x2c,&j);
+          i2cread(baseIoAddress,0x2f,&j);
+          i2cread(baseIoAddress,0x30,&j);
+          i2cread(baseIoAddress,0x33,&j);
+          i2cread(baseIoAddress,0x34,&j);
+          i2cwrite(baseIoAddress,0x40,0x43);
+          Outpb(baseIoAddress,0x0e,0x08);
+          i2cread(baseIoAddress,0x41,&j);
+          i2cread(baseIoAddress,0x42,&j);
+          if (devext->hd_status[i << 1] == 0)
+          {
+             Outpb(baseIoAddress,0x43,0x84);
+          }
+          else
+          {
+             Outpb(baseIoAddress,0x43,0x80);
+          }
+          Outpb(baseIoAddress,0x0e,0x08);
+          Outpb(baseIoAddress,0x43,0x20);
+          baseIoAddress = devext->BaseIoAddress[0];
+          Outpb(baseIoAddress,0x29,(UCHAR)
+                (Inpb(baseIoAddress,0x29) | 0x10));
+       }
+    }
+#endif    
+    baseIoAddress=devext->BaseIoAddress[0];
+
+    Outpb(baseIoAddresm,2,0x06);
+    Outpb(baseIoAddresm,0x12,0x06);
+    Outpb(baseIoAddresm,0x22,0x06);
+    Outpb(baseIoAddresm,0x32,0x06);
+    Outpb(baseIoAddress,0x28,(UCHAR)
+           (Inpb(baseIoAddress,0x28) & 0xef));
+    return;
+}
+
+void ATP865init(struct hw_device_ext * devext)
+{
+//    ULONG baseIoAddress = devext->BaseIoAddress[1];
+//    ULONG baseIoAddresm = devext->BaseIoAddresm[0];
+//    UCHAR  i,j,k,l,n,ata66,is66,iswd;
+//    UCHAR  cbuf[4];
+//    USHORT m,mbuf[256];
+
+    mdelay(1000);
+#ifdef RESET_DEBUG
+    printk("865RESET: Should h/w or s/w reset IDE first.\n");    
+#endif
+    // 3X6=  
+    Outpb(devext->BaseIoAddress[0],6,0xA0);
+    Outpb(devext->BaseIoAddress[2],2,0x04);
+    Outpb(devext->BaseIoAddress[0],6,0xB0);
+    Outpb(devext->BaseIoAddress[2],2,0x04);    
+    Outpb(devext->BaseIoAddress[1],6,0xA0);
+    Outpb(devext->BaseIoAddress[3],2,0x04);
+    Outpb(devext->BaseIoAddress[1],6,0xB0);
+    Outpb(devext->BaseIoAddress[3],2,0x04);    
+    mdelay(10);
+    Outpb(devext->BaseIoAddress[0],6,0xA0);
+    Outpb(devext->BaseIoAddress[2],2,0x00);
+    Outpb(devext->BaseIoAddress[0],6,0xB0);
+    Outpb(devext->BaseIoAddress[2],2,0x00);    
+    Outpb(devext->BaseIoAddress[1],6,0xA0);
+    Outpb(devext->BaseIoAddress[3],2,0x00);
+    Outpb(devext->BaseIoAddress[1],6,0xB0);
+    Outpb(devext->BaseIoAddress[3],2,0x00);
+    mdelay(5000);
+    Outpb(devext->BaseIoAddress[0],6,0xA0);    
+    Inpb(devext->BaseIoAddress[0],0x7);
+    Outpb(devext->BaseIoAddress[0],6,0xB0);
+    Inpb(devext->BaseIoAddress[0],0x7);    
+    Outpb(devext->BaseIoAddress[1],6,0xA0);    
+    Inpb(devext->BaseIoAddress[1],0x7);
+    Outpb(devext->BaseIoAddress[1],6,0xB0);
+    Inpb(devext->BaseIoAddress[1],0x7);        
+#ifdef RESET_DEBUG
+    printk("865RESET: init routine not ready, use is865() instead.\n");
+#endif
+    is865(devext,devext->pdev);
+    return;
+}
+
+
+const char *atp86x_info(struct Scsi_Host *notused)
 {
        static char buffer[128];
 
-       strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
+       strcpy(buffer, "ACARD ATP86X PCI ATA133 Adapter Driver Ver: 0.78  Date: 2004/01/15\n");
+
+       notused->ide_hdd = 1;   //+Wilson05112005, IDE Bridge exist
 
        return buffer;
 }
 
-int atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
+int atp86x_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
 {
        return -ENOSYS;         /* Currently this is a no-op */
 }
 
 #define BLS buffer + len + size
-int atp870u_proc_info(char *buffer, char **start, off_t offset, int length,
+int atp86x_proc_info(char *buffer, char **start, off_t offset, int length,
                      int hostno, int inout)
 {
        struct Scsi_Host *HBAptr;
@@ -2798,8 +3748,8 @@ int atp870u_proc_info(char *buffer, char **start, off_t offset, int length,
        off_t pos = 0;
 
        HBAptr = NULL;
-       for (i = 0; i < 2; i++) {
-               if ((HBAptr = atp_host[i]) != NULL) {
+       for (i = 0; i < 4; i++) {
+               if ((HBAptr = a867host[i]) != NULL) {
                        if (HBAptr->host_no == hostno) {
                                break;
                        }
@@ -2815,12 +3765,12 @@ int atp870u_proc_info(char *buffer, char **start, off_t offset, int length,
                goto stop_output;
        }
        if (inout == TRUE) {    /* Has data been written to the file? */
-               return (atp870u_set_info(buffer, length, HBAptr));
+               return (atp86x_set_info(buffer, length, HBAptr));
        }
        if (offset == 0) {
                memset(buff, 0, sizeof(buff));
        }
-       size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
+       size += sprintf(BLS, "ACARD ATP86X PCI ATA133 Adapter Driver Ver: 0.78  Date: 2004/01/15\n");
        len += size;
        pos = begin + len;
        size = 0;
@@ -2844,7 +3794,7 @@ stop_output:
 
 #include "sd.h"
 
-int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int *ip)
+int atp86x_biosparam(Scsi_Disk * disk, kdev_t dev, int *ip)
 {
        int heads, sectors, cylinders;
 
@@ -2864,26 +3814,128 @@ int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int *ip)
        return 0;
 }
 
-
-int atp870u_release (struct Scsi_Host *pshost)
+int atp86x_release (struct Scsi_Host *pshost)
 {
-       int h;
+       int h,i,k;
+       struct hw_device_ext *devext;
+
        for (h = 0; h <= admaxu; h++)
        {
-               if (pshost == atp_host[h]) {
-                       int k;
-                       free_irq (pshost->irq, &atp_unit[h]);
-                       release_region (pshost->io_port, pshost->n_io_port);
+               if (pshost == a867host[h]) {
+                       devext = &dev_ext[h];
+                       free_irq (pshost->irq, devext);
+                       if (devext->dev_id == ATP867_DEVID1)
+                               release_region (pshost->io_port, pshost->n_io_port);
+                       else
+                       {
+                               release_region(devext->BaseIoAddress[0],  0x8); /* Register the IO ports that we use */
+                               release_region(devext->BaseIoAddress[2],  0x3); /* Register the IO ports that we use */
+                               release_region(devext->BaseIoAddress[1],  0x8); /* Register the IO ports that we use */
+                               release_region(devext->BaseIoAddress[3],  0x3); /* Register the IO ports that we use */                 
+                               release_region(devext->BaseIoAddresm[0], 0x10); /* Register the IO ports that we use */                         
+                       }
                        scsi_unregister(pshost);
-                       for(k=0;k<16;k++)
-                               kfree(atp_unit[h].id[k].prd_tableu);
+                       for(i=0;i < 4;i++)
+                       {
+                          for(k=0;k < qcnt1;k++)
+                          {
+#ifdef IXP42X_SUPPORT
+                               pci_free_consistent(devext->pdev, 256,
+                                   devext->lsrb[i][k].prd, devext->lsrb[i][k].prdaddr);
+#else                          
+                             kfree(devext->lsrb[i][k].prd);
+#endif                       
+                          }
+                       }
+                       // add for smart read  =================//
+                       devext->FG_TimerStop = 1;
+                       mdelay(30);
+                       del_timer_sync(&(devext->AdapterTimer));
+                       //======================================//
                        return 0;
                }
        }
-       panic("atp870u: bad scsi host passed.\n");
+       panic("atp86x: bad scsi host passed.\n");
+}
+// add for smart read  =================//
+void smart_timer(ULONG para)
+{
+       struct hw_device_ext * devext;
+       Scsi_Cmnd *pScsiCmd;
+
+       devext  = (struct hw_device_ext *)para;
+       if (   (devext->FG_SmartRead == 0)
+            &&(devext->cap[0] != 0)
+            &&(devext->hd_status[0] != 0x7f)
+          )
+       {       // if smart read command not send to channel queue of hard disk yet
+//             printk("send smart read command\n");
+               pScsiCmd = &(devext->SmartSrb);
+               pScsiCmd->cmnd[0]   = 0xB0;
+               pScsiCmd->lun       = 0;
+               pScsiCmd->target    = 0;
+               pScsiCmd->scsi_done = internal_done;
+               if ((devext->que_end[0] += 1) > qcnt1 - 1)
+        {
+                  devext->que_end[0]=0;
+        }
+        devext->QSrb[0][devext->que_end[0]] = pScsiCmd;
+               devext->FG_SmartRead = 1;
+               if (devext->in_int == 0)
+               {
+                       if ( (devext->CSrb[0]   == 0) &&
+                                (devext->que_hd[0] != devext->que_end[0]) )
+                       {
+                               if ( devext->que_hd[0] == qcnt1 - 1 )
+                               {
+                                       devext->que_hd[0]=0;
+                               }else
+                               {
+                                       devext->que_hd[0]++;
+                               }
+                               devext->CSrb[0]=devext->QSrb[0][devext->que_hd[0]];
+                               devext->Cplsrb[0]=devext->plsrb[0][devext->que_hd[0]];
+                               SendScsi(devext,devext->CSrb[0],0);
+                       }
+               }
+       }
 
+       if( !(devext->FG_TimerStop) )
+       {
+               (devext->AdapterTimer).expires = jiffies + HZ*30;
+               add_timer(&(devext->AdapterTimer));
+       }
 }
+//======================================//
 MODULE_LICENSE("GPL");
 
-static Scsi_Host_Template driver_template = ATP870U;
+static Scsi_Host_Template driver_template = {
+       next: NULL,
+       module: NULL,
+       proc_info: atp86x_proc_info,
+       name: NULL,
+       detect: atp86x_detect,
+       release: atp86x_release,
+       info: atp86x_info,
+       command: atp86x_command,
+       queuecommand: atp86x_queuecommand,
+       eh_strategy_handler: NULL,
+       eh_abort_handler: NULL,
+       eh_device_reset_handler: NULL,
+       eh_bus_reset_handler: NULL,
+       eh_host_reset_handler: NULL,
+       abort: atp86x_abort,
+       reset: atp86x_reset,
+       slave_attach: NULL,
+       bios_param: atp86x_biosparam,
+       can_queue: qcnt,         /* max simultaneous cmds      */
+       this_id: 8,            /* scsi id of host adapter    */
+       sg_tablesize: ATP86X_SCATTER,   /* max scatter-gather cmds    */
+       cmd_per_lun: ATP86X_CMDLUN,     /* cmds per lun (linked cmds) */
+       present: 0,             /* number of xxx's present   */
+       unchecked_isa_dma: 0,   /* no memory DMA restrictions */
+       use_clustering: ENABLE_CLUSTERING,
+       use_new_eh_code: 0
+};
 #include "scsi_module.c"
+
index 3964404..cb19224 100644 (file)
@@ -1,71 +1,57 @@
-#ifndef _ATP870U_H
-
-/* $Id: atp870u.h,v 1.0 1997/05/07 15:09:00 root Exp root $
-
- * Header file for the ACARD 870U/W driver for Linux
- *
+#ifndef _ATP86X_H\r
+\r
+/* $Id: atp870u.h,v 1.1.1.1 2005/04/11 02:50:35 jack Exp $\r
+\r
+ * Header file for the ACARD 86x driver for Linux\r
+ *\r
  * $Log: atp870u.h,v $
- * Revision 1.0  1997/05/07  15:09:00  root
- * Initial revision
+ * Revision 1.1.1.1  2005/04/11 02:50:35  jack
+ * first release
  *
- */
-
-#include <linux/types.h>
-#include <linux/kdev_t.h>
-
-/* I/O Port */
-
-#define MAX_CDB 12
-#define MAX_SENSE 14
-
-int atp870u_detect(Scsi_Host_Template *);
-int atp870u_command(Scsi_Cmnd *);
-int atp870u_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
-int atp870u_abort(Scsi_Cmnd *);
-int atp870u_reset(Scsi_Cmnd *, unsigned int);
-int atp870u_biosparam(Disk *, kdev_t, int *);
-int atp870u_release(struct Scsi_Host *);
-void send_s870(unsigned char);
-
-#define qcnt           32
-#define ATP870U_SCATTER 128
-#define ATP870U_CMDLUN 1
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-extern const char *atp870u_info(struct Scsi_Host *);
-
-extern int atp870u_proc_info(char *, char **, off_t, int, int, int);
-
-#define ATP870U {                                              \
-       next: NULL,                                             \
-       module: NULL,                                           \
-       proc_info: atp870u_proc_info,                           \
-       name: NULL,                                             \
-       detect: atp870u_detect,                                 \
-       release: atp870u_release,                               \
-       info: atp870u_info,                                     \
-       command: atp870u_command,                               \
-       queuecommand: atp870u_queuecommand,                     \
-       eh_strategy_handler: NULL,                              \
-       eh_abort_handler: NULL,                                 \
-       eh_device_reset_handler: NULL,                          \
-       eh_bus_reset_handler: NULL,                             \
-       eh_host_reset_handler: NULL,                            \
-       abort: atp870u_abort,                                   \
-       reset: atp870u_reset,                                   \
-       slave_attach: NULL,                                     \
-       bios_param: atp870u_biosparam,                          \
-       can_queue: qcnt,         /* max simultaneous cmds      */\
-       this_id: 7,            /* scsi id of host adapter    */\
-       sg_tablesize: ATP870U_SCATTER,  /* max scatter-gather cmds    */\
-       cmd_per_lun: ATP870U_CMDLUN,    /* cmds per lun (linked cmds) */\
-       present: 0,             /* number of 7xxx's present   */\
-       unchecked_isa_dma: 0,   /* no memory DMA restrictions */\
-       use_clustering: ENABLE_CLUSTERING,                      \
-       use_new_eh_code: 0                                      \
-}
-
-#endif
+ * Revision 1.2  2005/01/25 05:58:34  wilsonc
+ * 1. Check-in Acard ATP865A Driver source code
+ *\r
+ * Revision 0.50  2003/12/26  11:30:00  root\r
+ *\r
+ */\r
+\r
+#include <linux/types.h>\r
+#include <linux/kdev_t.h>\r
+\r
+\r
+#define ATP865_DEVID1  0x0008\r
+#define ATP865_DEVID2  0x0009\r
+#define ATP867_DEVID1  0x000A\r
+\r
+\r
+/* I/O Port */\r
+\r
+#define MAX_CDB 12\r
+#define MAX_SENSE 14\r
+\r
+int atp86x_detect(Scsi_Host_Template *);\r
+int atp86x_command(Scsi_Cmnd *);\r
+int atp86x_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));\r
+int atp86x_abort(Scsi_Cmnd *);\r
+int atp86x_reset(Scsi_Cmnd *, unsigned int);\r
+int atp86x_biosparam(Disk *, kdev_t, int *);\r
+int atp86x_release(struct Scsi_Host *);\r
+\r
+//#define qcnt         32\r
+//#define qcnt1                8\r
+#define qcnt1          32\r
+#define qcnt           (qcnt1*4)\r
+\r
+#define ATP86X_SCATTER 32\r
+#define ATP86X_CMDLUN 2\r
+\r
+#ifndef NULL\r
+#define NULL 0\r
+#endif\r
+\r
+extern const char *atp86x_info(struct Scsi_Host *);\r
+\r
+extern int atp86x_proc_info(char *, char **, off_t, int, int, int);\r
+\r
+#endif\r
+\r
index 98e3e81..94d0153 100644 (file)
@@ -360,6 +360,7 @@ struct Scsi_Host
     unsigned char n_io_port;
     unsigned char dma_channel;
     unsigned int  irq;
+    unsigned int ide_hdd;      //+Wilson05112005, ide exist flag
 
     /*
      * This is a unique identifier that must be assigned so that we