linux/drivers/scsi/atp870u.c
<<
>>
Prefs
   1/* 
   2 *  Copyright (C) 1997  Wu Ching Chen
   3 *  2.1.x update (C) 1998  Krzysztof G. Baranowski
   4 *  2.5.x update (C) 2002  Red Hat
   5 *  2.6.x update (C) 2004  Red Hat
   6 *
   7 * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes
   8 *
   9 * Wu Ching Chen : NULL pointer fixes  2000/06/02
  10 *                 support atp876 chip
  11 *                 enable 32 bit fifo transfer
  12 *                 support cdrom & remove device run ultra speed
  13 *                 fix disconnect bug  2000/12/21
  14 *                 support atp880 chip lvd u160 2001/05/15
  15 *                 fix prd table bug 2001/09/12 (7.1)
  16 *
  17 * atp885 support add by ACARD Hao Ping Lian 2005/01/05
  18 */
  19#include <linux/module.h>
  20#include <linux/init.h>
  21#include <linux/interrupt.h>
  22#include <linux/kernel.h>
  23#include <linux/types.h>
  24#include <linux/string.h>
  25#include <linux/ioport.h>
  26#include <linux/delay.h>
  27#include <linux/proc_fs.h>
  28#include <linux/spinlock.h>
  29#include <linux/pci.h>
  30#include <linux/blkdev.h>
  31#include <linux/dma-mapping.h>
  32#include <linux/slab.h>
  33#include <asm/system.h>
  34#include <asm/io.h>
  35
  36#include <scsi/scsi.h>
  37#include <scsi/scsi_cmnd.h>
  38#include <scsi/scsi_device.h>
  39#include <scsi/scsi_host.h>
  40
  41#include "atp870u.h"
  42
  43static struct scsi_host_template atp870u_template;
  44static void send_s870(struct atp_unit *dev,unsigned char c);
  45static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
  46static void tscam_885(void);
  47
  48static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
  49{
  50        unsigned long flags;
  51        unsigned short int tmpcip, id;
  52        unsigned char i, j, c, target_id, lun,cmdp;
  53        unsigned char *prd;
  54        struct scsi_cmnd *workreq;
  55        unsigned int workport, tmport, tmport1;
  56        unsigned long adrcnt, k;
  57#ifdef ED_DBGP
  58        unsigned long l;
  59#endif
  60        int errstus;
  61        struct Scsi_Host *host = dev_id;
  62        struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
  63
  64        for (c = 0; c < 2; c++) {
  65                tmport = dev->ioport[c] + 0x1f;
  66                j = inb(tmport);
  67                if ((j & 0x80) != 0)
  68                {                       
  69                        goto ch_sel;
  70                }
  71                dev->in_int[c] = 0;
  72        }
  73        return IRQ_NONE;
  74ch_sel:
  75#ifdef ED_DBGP  
  76        printk("atp870u_intr_handle enter\n");
  77#endif  
  78        dev->in_int[c] = 1;
  79        cmdp = inb(dev->ioport[c] + 0x10);
  80        workport = dev->ioport[c];
  81        if (dev->working[c] != 0) {
  82                if (dev->dev_id == ATP885_DEVID) {
  83                        tmport1 = workport + 0x16;
  84                        if ((inb(tmport1) & 0x80) == 0)
  85                                outb((inb(tmport1) | 0x80), tmport1);
  86                }               
  87                tmpcip = dev->pciport[c];
  88                if ((inb(tmpcip) & 0x08) != 0)
  89                {
  90                        tmpcip += 0x2;
  91                        for (k=0; k < 1000; k++) {
  92                                if ((inb(tmpcip) & 0x08) == 0) {
  93                                        goto stop_dma;
  94                                }
  95                                if ((inb(tmpcip) & 0x01) == 0) {
  96                                        goto stop_dma;
  97                                }
  98                        }
  99                }
 100stop_dma:
 101                tmpcip = dev->pciport[c];
 102                outb(0x00, tmpcip);
 103                tmport -= 0x08;
 104                
 105                i = inb(tmport);
 106                
 107                if (dev->dev_id == ATP885_DEVID) {
 108                        tmpcip += 2;
 109                        outb(0x06, tmpcip);
 110                        tmpcip -= 2;
 111                }
 112
 113                tmport -= 0x02;
 114                target_id = inb(tmport);
 115                tmport += 0x02;
 116
 117                /*
 118                 *      Remap wide devices onto id numbers
 119                 */
 120
 121                if ((target_id & 0x40) != 0) {
 122                        target_id = (target_id & 0x07) | 0x08;
 123                } else {
 124                        target_id &= 0x07;
 125                }
 126
 127                if ((j & 0x40) != 0) {
 128                     if (dev->last_cmd[c] == 0xff) {
 129                        dev->last_cmd[c] = target_id;
 130                     }
 131                     dev->last_cmd[c] |= 0x40;
 132                }
 133                if (dev->dev_id == ATP885_DEVID) 
 134                        dev->r1f[c][target_id] |= j;
 135#ifdef ED_DBGP
 136                printk("atp870u_intr_handle status = %x\n",i);
 137#endif  
 138                if (i == 0x85) {
 139                        if ((dev->last_cmd[c] & 0xf0) != 0x40) {
 140                           dev->last_cmd[c] = 0xff;
 141                        }
 142                        if (dev->dev_id == ATP885_DEVID) {
 143                                tmport -= 0x05;
 144                                adrcnt = 0;
 145                                ((unsigned char *) &adrcnt)[2] = inb(tmport++);
 146                                ((unsigned char *) &adrcnt)[1] = inb(tmport++);
 147                                ((unsigned char *) &adrcnt)[0] = inb(tmport);
 148                                if (dev->id[c][target_id].last_len != adrcnt)
 149                                {
 150                                        k = dev->id[c][target_id].last_len;
 151                                        k -= adrcnt;
 152                                        dev->id[c][target_id].tran_len = k;                        
 153                                dev->id[c][target_id].last_len = adrcnt;                           
 154                                }
 155#ifdef ED_DBGP
 156                                printk("tmport = %x dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = %d\n",tmport,dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len);
 157#endif          
 158                        }
 159
 160                        /*
 161                         *      Flip wide
 162                         */                     
 163                        if (dev->wide_id[c] != 0) {
 164                                tmport = workport + 0x1b;
 165                                outb(0x01, tmport);
 166                                while ((inb(tmport) & 0x01) != 0x01) {
 167                                        outb(0x01, tmport);
 168                                }
 169                        }               
 170                        /*
 171                         *      Issue more commands
 172                         */
 173                        spin_lock_irqsave(dev->host->host_lock, flags);                                          
 174                        if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) &&
 175                            (dev->in_snd[c] == 0)) {
 176#ifdef ED_DBGP
 177                                printk("Call sent_s870\n");
 178#endif                          
 179                                send_s870(dev,c);
 180                        }
 181                        spin_unlock_irqrestore(dev->host->host_lock, flags);
 182                        /*
 183                         *      Done
 184                         */
 185                        dev->in_int[c] = 0;
 186#ifdef ED_DBGP
 187                                printk("Status 0x85 return\n");
 188#endif                          
 189                        goto handled;
 190                }
 191
 192                if (i == 0x40) {
 193                     dev->last_cmd[c] |= 0x40;
 194                     dev->in_int[c] = 0;
 195                     goto handled;
 196                }
 197
 198                if (i == 0x21) {
 199                        if ((dev->last_cmd[c] & 0xf0) != 0x40) {
 200                           dev->last_cmd[c] = 0xff;
 201                        }
 202                        tmport -= 0x05;
 203                        adrcnt = 0;
 204                        ((unsigned char *) &adrcnt)[2] = inb(tmport++);
 205                        ((unsigned char *) &adrcnt)[1] = inb(tmport++);
 206                        ((unsigned char *) &adrcnt)[0] = inb(tmport);
 207                        k = dev->id[c][target_id].last_len;
 208                        k -= adrcnt;
 209                        dev->id[c][target_id].tran_len = k;
 210                        dev->id[c][target_id].last_len = adrcnt;
 211                        tmport -= 0x04;
 212                        outb(0x41, tmport);
 213                        tmport += 0x08;
 214                        outb(0x08, tmport);
 215                        dev->in_int[c] = 0;
 216                        goto handled;
 217                }
 218
 219                if (dev->dev_id == ATP885_DEVID) {
 220                        if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) {
 221                                if ((i == 0x4c) || (i == 0x8c)) 
 222                                        i=0x48;
 223                                else 
 224                                        i=0x49;
 225                        }       
 226                        
 227                }
 228                if ((i == 0x80) || (i == 0x8f)) {
 229#ifdef ED_DBGP
 230                        printk(KERN_DEBUG "Device reselect\n");
 231#endif                  
 232                        lun = 0;
 233                        tmport -= 0x07;
 234                        if (cmdp == 0x44 || i==0x80) {
 235                                tmport += 0x0d;
 236                                lun = inb(tmport) & 0x07;
 237                        } else {
 238                                if ((dev->last_cmd[c] & 0xf0) != 0x40) {
 239                                   dev->last_cmd[c] = 0xff;
 240                                }
 241                                if (cmdp == 0x41) {
 242#ifdef ED_DBGP
 243                                        printk("cmdp = 0x41\n");
 244#endif                                          
 245                                        tmport += 0x02;
 246                                        adrcnt = 0;
 247                                        ((unsigned char *) &adrcnt)[2] = inb(tmport++);
 248                                        ((unsigned char *) &adrcnt)[1] = inb(tmport++);
 249                                        ((unsigned char *) &adrcnt)[0] = inb(tmport);
 250                                        k = dev->id[c][target_id].last_len;
 251                                        k -= adrcnt;
 252                                        dev->id[c][target_id].tran_len = k;
 253                                        dev->id[c][target_id].last_len = adrcnt;
 254                                        tmport += 0x04;
 255                                        outb(0x08, tmport);
 256                                        dev->in_int[c] = 0;
 257                                        goto handled;
 258                                } else {
 259#ifdef ED_DBGP
 260                                        printk("cmdp != 0x41\n");
 261#endif                                          
 262                                        outb(0x46, tmport);
 263                                        dev->id[c][target_id].dirct = 0x00;
 264                                        tmport += 0x02;
 265                                        outb(0x00, tmport++);
 266                                        outb(0x00, tmport++);
 267                                        outb(0x00, tmport++);
 268                                        tmport += 0x03;
 269                                        outb(0x08, tmport);
 270                                        dev->in_int[c] = 0;
 271                                        goto handled;
 272                                }
 273                        }
 274                        if (dev->last_cmd[c] != 0xff) {
 275                           dev->last_cmd[c] |= 0x40;
 276                        }
 277                        if (dev->dev_id == ATP885_DEVID) {
 278                                j = inb(dev->baseport + 0x29) & 0xfe;
 279                                outb(j, dev->baseport + 0x29);
 280                                tmport = workport + 0x16;
 281                        } else {
 282                                tmport = workport + 0x10;
 283                                outb(0x45, tmport);
 284                                tmport += 0x06;                         
 285                        }
 286                        
 287                        target_id = inb(tmport);
 288                        /*
 289                         *      Remap wide identifiers
 290                         */
 291                        if ((target_id & 0x10) != 0) {
 292                                target_id = (target_id & 0x07) | 0x08;
 293                        } else {
 294                                target_id &= 0x07;
 295                        }
 296                        if (dev->dev_id == ATP885_DEVID) {
 297                                tmport = workport + 0x10;
 298                                outb(0x45, tmport);
 299                        }
 300                        workreq = dev->id[c][target_id].curr_req;
 301#ifdef ED_DBGP                  
 302                        scmd_printk(KERN_DEBUG, workreq, "CDB");
 303                        for (l = 0; l < workreq->cmd_len; l++)
 304                                printk(KERN_DEBUG " %x",workreq->cmnd[l]);
 305                        printk("\n");
 306#endif  
 307                        
 308                        tmport = workport + 0x0f;
 309                        outb(lun, tmport);
 310                        tmport += 0x02;
 311                        outb(dev->id[c][target_id].devsp, tmport++);
 312                        adrcnt = dev->id[c][target_id].tran_len;
 313                        k = dev->id[c][target_id].last_len;
 314
 315                        outb(((unsigned char *) &k)[2], tmport++);
 316                        outb(((unsigned char *) &k)[1], tmport++);
 317                        outb(((unsigned char *) &k)[0], tmport++);
 318#ifdef ED_DBGP                  
 319                        printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k, inb(tmport-1), inb(tmport-2), inb(tmport-3));
 320#endif                  
 321                        /* Remap wide */
 322                        j = target_id;
 323                        if (target_id > 7) {
 324                                j = (j & 0x07) | 0x40;
 325                        }
 326                        /* Add direction */
 327                        j |= dev->id[c][target_id].dirct;
 328                        outb(j, tmport++);
 329                        outb(0x80,tmport);
 330                        
 331                        /* enable 32 bit fifo transfer */       
 332                        if (dev->dev_id == ATP885_DEVID) {
 333                                tmpcip = dev->pciport[c] + 1;
 334                                i=inb(tmpcip) & 0xf3;
 335                                //j=workreq->cmnd[0];                           
 336                                if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
 337                                   i |= 0x0c;
 338                                }
 339                                outb(i,tmpcip);                                         
 340                        } else if ((dev->dev_id == ATP880_DEVID1) ||
 341                                   (dev->dev_id == ATP880_DEVID2) ) {
 342                                tmport = workport - 0x05;
 343                                if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
 344                                        outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
 345                                } else {
 346                                        outb((unsigned char) (inb(tmport) & 0x3f), tmport);
 347                                }
 348                        } else {                                
 349                                tmport = workport + 0x3a;
 350                                if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
 351                                        outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
 352                                } else {
 353                                        outb((unsigned char) (inb(tmport) & 0xf3), tmport);
 354                                }                                                                                                               
 355                        }       
 356                        tmport = workport + 0x1b;
 357                        j = 0;
 358                        id = 1;
 359                        id = id << target_id;
 360                        /*
 361                         *      Is this a wide device
 362                         */
 363                        if ((id & dev->wide_id[c]) != 0) {
 364                                j |= 0x01;
 365                        }
 366                        outb(j, tmport);
 367                        while ((inb(tmport) & 0x01) != j) {
 368                                outb(j,tmport);
 369                        }
 370                        if (dev->id[c][target_id].last_len == 0) {
 371                                tmport = workport + 0x18;
 372                                outb(0x08, tmport);
 373                                dev->in_int[c] = 0;
 374#ifdef ED_DBGP
 375                                printk("dev->id[c][target_id].last_len = 0\n");
 376#endif                                  
 377                                goto handled;
 378                        }
 379#ifdef ED_DBGP
 380                        printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
 381#endif                  
 382                        prd = dev->id[c][target_id].prd_pos;
 383                        while (adrcnt != 0) {
 384                                id = ((unsigned short int *)prd)[2];
 385                                if (id == 0) {
 386                                        k = 0x10000;
 387                                } else {
 388                                        k = id;
 389                                }
 390                                if (k > adrcnt) {
 391                                        ((unsigned short int *)prd)[2] = (unsigned short int)
 392                                            (k - adrcnt);
 393                                        ((unsigned long *)prd)[0] += adrcnt;
 394                                        adrcnt = 0;
 395                                        dev->id[c][target_id].prd_pos = prd;
 396                                } else {
 397                                        adrcnt -= k;
 398                                        dev->id[c][target_id].prdaddr += 0x08;
 399                                        prd += 0x08;
 400                                        if (adrcnt == 0) {
 401                                                dev->id[c][target_id].prd_pos = prd;
 402                                        }
 403                                }                               
 404                        }
 405                        tmpcip = dev->pciport[c] + 0x04;
 406                        outl(dev->id[c][target_id].prdaddr, tmpcip);
 407#ifdef ED_DBGP
 408                        printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr);
 409#endif
 410                        if (dev->dev_id == ATP885_DEVID) {
 411                                tmpcip -= 0x04;
 412                        } else {
 413                                tmpcip -= 0x02;
 414                                outb(0x06, tmpcip);
 415                                outb(0x00, tmpcip);
 416                                tmpcip -= 0x02;
 417                        }
 418                        tmport = workport + 0x18;
 419                        /*
 420                         *      Check transfer direction
 421                         */
 422                        if (dev->id[c][target_id].dirct != 0) {
 423                                outb(0x08, tmport);
 424                                outb(0x01, tmpcip);
 425                                dev->in_int[c] = 0;
 426#ifdef ED_DBGP
 427                                printk("status 0x80 return dirct != 0\n");
 428#endif                          
 429                                goto handled;
 430                        }
 431                        outb(0x08, tmport);
 432                        outb(0x09, tmpcip);
 433                        dev->in_int[c] = 0;
 434#ifdef ED_DBGP
 435                        printk("status 0x80 return dirct = 0\n");
 436#endif                  
 437                        goto handled;
 438                }
 439
 440                /*
 441                 *      Current scsi request on this target
 442                 */
 443
 444                workreq = dev->id[c][target_id].curr_req;
 445
 446                if (i == 0x42) {
 447                        if ((dev->last_cmd[c] & 0xf0) != 0x40)
 448                        {
 449                           dev->last_cmd[c] = 0xff;
 450                        }
 451                        errstus = 0x02;
 452                        workreq->result = errstus;
 453                        goto go_42;
 454                }
 455                if (i == 0x16) {
 456                        if ((dev->last_cmd[c] & 0xf0) != 0x40) {
 457                           dev->last_cmd[c] = 0xff;
 458                        }
 459                        errstus = 0;
 460                        tmport -= 0x08;
 461                        errstus = inb(tmport);
 462                        if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) {
 463                           printk(KERN_WARNING "AEC67162 CRC ERROR !\n");
 464                           errstus = 0x02;
 465                        }
 466                        workreq->result = errstus;
 467go_42:
 468                        if (dev->dev_id == ATP885_DEVID) {              
 469                                j = inb(dev->baseport + 0x29) | 0x01;
 470                                outb(j, dev->baseport + 0x29);
 471                        }
 472                        /*
 473                         *      Complete the command
 474                         */
 475                        scsi_dma_unmap(workreq);
 476
 477                        spin_lock_irqsave(dev->host->host_lock, flags);
 478                        (*workreq->scsi_done) (workreq);
 479#ifdef ED_DBGP
 480                           printk("workreq->scsi_done\n");
 481#endif  
 482                        /*
 483                         *      Clear it off the queue
 484                         */
 485                        dev->id[c][target_id].curr_req = NULL;
 486                        dev->working[c]--;
 487                        spin_unlock_irqrestore(dev->host->host_lock, flags);
 488                        /*
 489                         *      Take it back wide
 490                         */
 491                        if (dev->wide_id[c] != 0) {
 492                                tmport = workport + 0x1b;
 493                                outb(0x01, tmport);
 494                                while ((inb(tmport) & 0x01) != 0x01) {
 495                                        outb(0x01, tmport);
 496                                }       
 497                        } 
 498                        /*
 499                         *      If there is stuff to send and nothing going then send it
 500                         */
 501                        spin_lock_irqsave(dev->host->host_lock, flags);
 502                        if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) &&
 503                            (dev->in_snd[c] == 0)) {
 504#ifdef ED_DBGP
 505                           printk("Call sent_s870(scsi_done)\n");
 506#endif                             
 507                           send_s870(dev,c);
 508                        }
 509                        spin_unlock_irqrestore(dev->host->host_lock, flags);
 510                        dev->in_int[c] = 0;
 511                        goto handled;
 512                }
 513                if ((dev->last_cmd[c] & 0xf0) != 0x40) {
 514                   dev->last_cmd[c] = 0xff;
 515                }
 516                if (i == 0x4f) {
 517                        i = 0x89;
 518                }
 519                i &= 0x0f;
 520                if (i == 0x09) {
 521                        tmpcip += 4;
 522                        outl(dev->id[c][target_id].prdaddr, tmpcip);
 523                        tmpcip = tmpcip - 2;
 524                        outb(0x06, tmpcip);
 525                        outb(0x00, tmpcip);
 526                        tmpcip = tmpcip - 2;
 527                        tmport = workport + 0x10;
 528                        outb(0x41, tmport);
 529                        if (dev->dev_id == ATP885_DEVID) {
 530                                tmport += 2;
 531                                k = dev->id[c][target_id].last_len;
 532                                outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
 533                                outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
 534                                outb((unsigned char) (((unsigned char *) (&k))[0]), tmport);
 535                                dev->id[c][target_id].dirct = 0x00;
 536                                tmport += 0x04;
 537                        } else {
 538                                dev->id[c][target_id].dirct = 0x00;
 539                                tmport += 0x08;                         
 540                        }
 541                        outb(0x08, tmport);
 542                        outb(0x09, tmpcip);
 543                        dev->in_int[c] = 0;
 544                        goto handled;
 545                }
 546                if (i == 0x08) {
 547                        tmpcip += 4;
 548                        outl(dev->id[c][target_id].prdaddr, tmpcip);
 549                        tmpcip = tmpcip - 2;
 550                        outb(0x06, tmpcip);
 551                        outb(0x00, tmpcip);
 552                        tmpcip = tmpcip - 2;
 553                        tmport = workport + 0x10;
 554                        outb(0x41, tmport);
 555                        if (dev->dev_id == ATP885_DEVID) {              
 556                                tmport += 2;
 557                                k = dev->id[c][target_id].last_len;
 558                                outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
 559                                outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
 560                                outb((unsigned char) (((unsigned char *) (&k))[0]), tmport++);
 561                        } else {
 562                                tmport += 5;
 563                        }
 564                        outb((unsigned char) (inb(tmport) | 0x20), tmport);
 565                        dev->id[c][target_id].dirct = 0x20;
 566                        tmport += 0x03;
 567                        outb(0x08, tmport);
 568                        outb(0x01, tmpcip);
 569                        dev->in_int[c] = 0;
 570                        goto handled;
 571                }
 572                tmport -= 0x07;
 573                if (i == 0x0a) {
 574                        outb(0x30, tmport);
 575                } else {
 576                        outb(0x46, tmport);
 577                }
 578                dev->id[c][target_id].dirct = 0x00;
 579                tmport += 0x02;
 580                outb(0x00, tmport++);
 581                outb(0x00, tmport++);
 582                outb(0x00, tmport++);
 583                tmport += 0x03;
 584                outb(0x08, tmport);
 585                dev->in_int[c] = 0;
 586                goto handled;
 587        } else {
 588//              tmport = workport + 0x17;
 589//              inb(tmport);
 590//              dev->working[c] = 0;
 591                dev->in_int[c] = 0;
 592                goto handled;
 593        }
 594        
 595handled:
 596#ifdef ED_DBGP
 597        printk("atp870u_intr_handle exit\n");
 598#endif                  
 599        return IRQ_HANDLED;
 600}
 601/**
 602 *      atp870u_queuecommand    -       Queue SCSI command
 603 *      @req_p: request block
 604 *      @done: completion function
 605 *
 606 *      Queue a command to the ATP queue. Called with the host lock held.
 607 */
 608static int atp870u_queuecommand_lck(struct scsi_cmnd *req_p,
 609                         void (*done) (struct scsi_cmnd *))
 610{
 611        unsigned char c;
 612        unsigned int tmport,m;  
 613        struct atp_unit *dev;
 614        struct Scsi_Host *host;
 615
 616        c = scmd_channel(req_p);
 617        req_p->sense_buffer[0]=0;
 618        scsi_set_resid(req_p, 0);
 619        if (scmd_channel(req_p) > 1) {
 620                req_p->result = 0x00040000;
 621                done(req_p);
 622#ifdef ED_DBGP          
 623                printk("atp870u_queuecommand : req_p->device->channel > 1\n");  
 624#endif                  
 625                return 0;
 626        }
 627
 628        host = req_p->device->host;
 629        dev = (struct atp_unit *)&host->hostdata;
 630                
 631
 632                
 633        m = 1;
 634        m = m << scmd_id(req_p);
 635
 636        /*
 637         *      Fake a timeout for missing targets
 638         */
 639
 640        if ((m & dev->active_id[c]) == 0) {
 641                req_p->result = 0x00040000;
 642                done(req_p);
 643                return 0;
 644        }
 645
 646        if (done) {
 647                req_p->scsi_done = done;
 648        } else {
 649#ifdef ED_DBGP          
 650                printk( "atp870u_queuecommand: done can't be NULL\n");
 651#endif          
 652                req_p->result = 0;
 653                done(req_p);
 654                return 0;
 655        }
 656        
 657        /*
 658         *      Count new command
 659         */
 660        dev->quend[c]++;
 661        if (dev->quend[c] >= qcnt) {
 662                dev->quend[c] = 0;
 663        }
 664        
 665        /*
 666         *      Check queue state
 667         */
 668        if (dev->quhd[c] == dev->quend[c]) {
 669                if (dev->quend[c] == 0) {
 670                        dev->quend[c] = qcnt;
 671                }
 672#ifdef ED_DBGP          
 673                printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
 674#endif          
 675                dev->quend[c]--;
 676                req_p->result = 0x00020000;
 677                done(req_p);    
 678                return 0;
 679        }
 680        dev->quereq[c][dev->quend[c]] = req_p;
 681        tmport = dev->ioport[c] + 0x1c;
 682#ifdef ED_DBGP  
 683        printk("dev->ioport[c] = %x inb(tmport) = %x dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",dev->ioport[c],inb(tmport),c,dev->in_int[c],c,dev->in_snd[c]);
 684#endif
 685        if ((inb(tmport) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) {
 686#ifdef ED_DBGP
 687                printk("Call sent_s870(atp870u_queuecommand)\n");
 688#endif          
 689                send_s870(dev,c);
 690        }
 691#ifdef ED_DBGP  
 692        printk("atp870u_queuecommand : exit\n");
 693#endif  
 694        return 0;
 695}
 696
 697static DEF_SCSI_QCMD(atp870u_queuecommand)
 698
 699/**
 700 *      send_s870       -       send a command to the controller
 701 *      @host: host
 702 *
 703 *      On entry there is work queued to be done. We move some of that work to the
 704 *      controller itself. 
 705 *
 706 *      Caller holds the host lock.
 707 */
 708static void send_s870(struct atp_unit *dev,unsigned char c)
 709{
 710        unsigned int tmport;
 711        struct scsi_cmnd *workreq;
 712        unsigned int i;//,k;
 713        unsigned char  j, target_id;
 714        unsigned char *prd;
 715        unsigned short int tmpcip, w;
 716        unsigned long l, bttl = 0;
 717        unsigned int workport;
 718        unsigned long  sg_count;
 719
 720        if (dev->in_snd[c] != 0) {
 721#ifdef ED_DBGP          
 722                printk("cmnd in_snd\n");
 723#endif
 724                return;
 725        }
 726#ifdef ED_DBGP
 727        printk("Sent_s870 enter\n");
 728#endif
 729        dev->in_snd[c] = 1;
 730        if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
 731                dev->last_cmd[c] &= 0x0f;
 732                workreq = dev->id[c][dev->last_cmd[c]].curr_req;
 733                if (workreq != NULL) {  /* check NULL pointer */
 734                   goto cmd_subp;
 735                }
 736                dev->last_cmd[c] = 0xff;        
 737                if (dev->quhd[c] == dev->quend[c]) {
 738                        dev->in_snd[c] = 0;
 739                        return ;
 740                }
 741        }
 742        if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
 743                dev->in_snd[c] = 0;
 744                return ;
 745        }
 746        dev->working[c]++;
 747        j = dev->quhd[c];
 748        dev->quhd[c]++;
 749        if (dev->quhd[c] >= qcnt) {
 750                dev->quhd[c] = 0;
 751        }
 752        workreq = dev->quereq[c][dev->quhd[c]];
 753        if (dev->id[c][scmd_id(workreq)].curr_req == NULL) {
 754                dev->id[c][scmd_id(workreq)].curr_req = workreq;
 755                dev->last_cmd[c] = scmd_id(workreq);
 756                goto cmd_subp;
 757        }       
 758        dev->quhd[c] = j;
 759        dev->working[c]--;
 760        dev->in_snd[c] = 0;
 761        return;
 762cmd_subp:
 763        workport = dev->ioport[c];
 764        tmport = workport + 0x1f;
 765        if ((inb(tmport) & 0xb0) != 0) {
 766                goto abortsnd;
 767        }
 768        tmport = workport + 0x1c;
 769        if (inb(tmport) == 0) {
 770                goto oktosend;
 771        }
 772abortsnd:
 773#ifdef ED_DBGP
 774        printk("Abort to Send\n");
 775#endif
 776        dev->last_cmd[c] |= 0x40;
 777        dev->in_snd[c] = 0;
 778        return;
 779oktosend:
 780#ifdef ED_DBGP
 781        printk("OK to Send\n");
 782        scmd_printk(KERN_DEBUG, workreq, "CDB");
 783        for(i=0;i<workreq->cmd_len;i++) {
 784                printk(" %x",workreq->cmnd[i]);
 785        }
 786        printk("\n");
 787#endif  
 788        l = scsi_bufflen(workreq);
 789
 790        if (dev->dev_id == ATP885_DEVID) {
 791                j = inb(dev->baseport + 0x29) & 0xfe;
 792                outb(j, dev->baseport + 0x29);
 793                dev->r1f[c][scmd_id(workreq)] = 0;
 794        }
 795        
 796        if (workreq->cmnd[0] == READ_CAPACITY) {
 797                if (l > 8)
 798                        l = 8;
 799        }
 800        if (workreq->cmnd[0] == 0x00) {
 801                l = 0;
 802        }
 803
 804        tmport = workport + 0x1b;
 805        j = 0;
 806        target_id = scmd_id(workreq);
 807
 808        /*
 809         *      Wide ?
 810         */
 811        w = 1;
 812        w = w << target_id;
 813        if ((w & dev->wide_id[c]) != 0) {
 814                j |= 0x01;
 815        }
 816        outb(j, tmport);
 817        while ((inb(tmport) & 0x01) != j) {
 818                outb(j,tmport);
 819#ifdef ED_DBGP
 820                printk("send_s870 while loop 1\n");
 821#endif
 822        }
 823        /*
 824         *      Write the command
 825         */
 826
 827        tmport = workport;
 828        outb(workreq->cmd_len, tmport++);
 829        outb(0x2c, tmport++);
 830        if (dev->dev_id == ATP885_DEVID) {
 831                outb(0x7f, tmport++);
 832        } else {
 833                outb(0xcf, tmport++);   
 834        }       
 835        for (i = 0; i < workreq->cmd_len; i++) {
 836                outb(workreq->cmnd[i], tmport++);
 837        }
 838        tmport = workport + 0x0f;
 839        outb(workreq->device->lun, tmport);
 840        tmport += 0x02;
 841        /*
 842         *      Write the target
 843         */
 844        outb(dev->id[c][target_id].devsp, tmport++);     
 845#ifdef ED_DBGP  
 846        printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp);
 847#endif
 848
 849        sg_count = scsi_dma_map(workreq);
 850        /*
 851         *      Write transfer size
 852         */
 853        outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
 854        outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
 855        outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
 856        j = target_id;  
 857        dev->id[c][j].last_len = l;
 858        dev->id[c][j].tran_len = 0;
 859#ifdef ED_DBGP  
 860        printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
 861#endif  
 862        /*
 863         *      Flip the wide bits
 864         */
 865        if ((j & 0x08) != 0) {
 866                j = (j & 0x07) | 0x40;
 867        }
 868        /*
 869         *      Check transfer direction
 870         */
 871        if (workreq->sc_data_direction == DMA_TO_DEVICE) {
 872                outb((unsigned char) (j | 0x20), tmport++);
 873        } else {
 874                outb(j, tmport++);
 875        }
 876        outb((unsigned char) (inb(tmport) | 0x80), tmport);
 877        outb(0x80, tmport);
 878        tmport = workport + 0x1c;
 879        dev->id[c][target_id].dirct = 0;
 880        if (l == 0) {
 881                if (inb(tmport) == 0) {
 882                        tmport = workport + 0x18;
 883#ifdef ED_DBGP
 884                        printk("change SCSI_CMD_REG 0x08\n");   
 885#endif                          
 886                        outb(0x08, tmport);
 887                } else {
 888                        dev->last_cmd[c] |= 0x40;
 889                }
 890                dev->in_snd[c] = 0;
 891                return;
 892        }
 893        tmpcip = dev->pciport[c];
 894        prd = dev->id[c][target_id].prd_table;
 895        dev->id[c][target_id].prd_pos = prd;
 896
 897        /*
 898         *      Now write the request list. Either as scatter/gather or as
 899         *      a linear chain.
 900         */
 901
 902        if (l) {
 903                struct scatterlist *sgpnt;
 904                i = 0;
 905                scsi_for_each_sg(workreq, sgpnt, sg_count, j) {
 906                        bttl = sg_dma_address(sgpnt);
 907                        l=sg_dma_len(sgpnt);
 908#ifdef ED_DBGP          
 909                        printk("1. bttl %x, l %x\n",bttl, l);
 910#endif                  
 911                        while (l > 0x10000) {
 912                                (((u16 *) (prd))[i + 3]) = 0x0000;
 913                                (((u16 *) (prd))[i + 2]) = 0x0000;
 914                                (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
 915                                l -= 0x10000;
 916                                bttl += 0x10000;
 917                                i += 0x04;
 918                        }
 919                        (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
 920                        (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
 921                        (((u16 *) (prd))[i + 3]) = 0;
 922                        i += 0x04;                      
 923                }
 924                (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000); 
 925#ifdef ED_DBGP          
 926                printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
 927                printk("2. bttl %x, l %x\n",bttl, l);
 928#endif                  
 929        }
 930        tmpcip += 4;
 931#ifdef ED_DBGP          
 932        printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id);
 933#endif  
 934        dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
 935        outl(dev->id[c][target_id].prdaddr, tmpcip);
 936        tmpcip = tmpcip - 2;
 937        outb(0x06, tmpcip);
 938        outb(0x00, tmpcip);
 939        if (dev->dev_id == ATP885_DEVID) {
 940                tmpcip--;
 941                j=inb(tmpcip) & 0xf3;
 942                if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) ||
 943                (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
 944                        j |= 0x0c;
 945                }
 946                outb(j,tmpcip);
 947                tmpcip--;               
 948        } else if ((dev->dev_id == ATP880_DEVID1) ||
 949                   (dev->dev_id == ATP880_DEVID2)) {
 950                tmpcip =tmpcip -2;      
 951                tmport = workport - 0x05;
 952                if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
 953                        outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
 954                } else {
 955                        outb((unsigned char) (inb(tmport) & 0x3f), tmport);
 956                }               
 957        } else {                
 958                tmpcip =tmpcip -2;
 959                tmport = workport + 0x3a;
 960                if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
 961                        outb((inb(tmport) & 0xf3) | 0x08, tmport);
 962                } else {
 963                        outb(inb(tmport) & 0xf3, tmport);
 964                }               
 965        }       
 966        tmport = workport + 0x1c;
 967
 968        if(workreq->sc_data_direction == DMA_TO_DEVICE) {
 969                dev->id[c][target_id].dirct = 0x20;
 970                if (inb(tmport) == 0) {
 971                        tmport = workport + 0x18;
 972                        outb(0x08, tmport);
 973                        outb(0x01, tmpcip);
 974#ifdef ED_DBGP          
 975                printk( "start DMA(to target)\n");
 976#endif                          
 977                } else {
 978                        dev->last_cmd[c] |= 0x40;
 979                }
 980                dev->in_snd[c] = 0;
 981                return;
 982        }
 983        if (inb(tmport) == 0) {         
 984                tmport = workport + 0x18;
 985                outb(0x08, tmport);
 986                outb(0x09, tmpcip);
 987#ifdef ED_DBGP          
 988                printk( "start DMA(to host)\n");
 989#endif                  
 990        } else {
 991                dev->last_cmd[c] |= 0x40;
 992        }
 993        dev->in_snd[c] = 0;
 994        return;
 995
 996}
 997
 998static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
 999{
1000        unsigned int tmport;
1001        unsigned short int i, k;
1002        unsigned char j;
1003
1004        tmport = dev->ioport[0] + 0x1c;
1005        outw(*val, tmport);
1006FUN_D7:
1007        for (i = 0; i < 10; i++) {      /* stable >= bus settle delay(400 ns)  */
1008                k = inw(tmport);
1009                j = (unsigned char) (k >> 8);
1010                if ((k & 0x8000) != 0) {        /* DB7 all release?    */
1011                        goto FUN_D7;
1012                }
1013        }
1014        *val |= 0x4000;         /* assert DB6           */
1015        outw(*val, tmport);
1016        *val &= 0xdfff;         /* assert DB5           */
1017        outw(*val, tmport);
1018FUN_D5:
1019        for (i = 0; i < 10; i++) {      /* stable >= bus settle delay(400 ns) */
1020                if ((inw(tmport) & 0x2000) != 0) {      /* DB5 all release?       */
1021                        goto FUN_D5;
1022                }
1023        }
1024        *val |= 0x8000;         /* no DB4-0, assert DB7    */
1025        *val &= 0xe0ff;
1026        outw(*val, tmport);
1027        *val &= 0xbfff;         /* release DB6             */
1028        outw(*val, tmport);
1029FUN_D6:
1030        for (i = 0; i < 10; i++) {      /* stable >= bus settle delay(400 ns)  */
1031                if ((inw(tmport) & 0x4000) != 0) {      /* DB6 all release?  */
1032                        goto FUN_D6;
1033                }
1034        }
1035
1036        return j;
1037}
1038
1039static void tscam(struct Scsi_Host *host)
1040{
1041
1042        unsigned int tmport;
1043        unsigned char i, j, k;
1044        unsigned long n;
1045        unsigned short int m, assignid_map, val;
1046        unsigned char mbuf[33], quintet[2];
1047        struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
1048        static unsigned char g2q_tab[8] = {
1049                0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
1050        };
1051
1052/*  I can't believe we need this before we've even done anything.  Remove it
1053 *  and see if anyone bitches.
1054        for (i = 0; i < 0x10; i++) {
1055                udelay(0xffff);
1056        }
1057 */
1058
1059        tmport = dev->ioport[0] + 1;
1060        outb(0x08, tmport++);
1061        outb(0x7f, tmport);
1062        tmport = dev->ioport[0] + 0x11;
1063        outb(0x20, tmport);
1064
1065        if ((dev->scam_on & 0x40) == 0) {
1066                return;
1067        }
1068        m = 1;
1069        m <<= dev->host_id[0];
1070        j = 16;
1071        if (dev->chip_ver < 4) {
1072                m |= 0xff00;
1073                j = 8;
1074        }
1075        assignid_map = m;
1076        tmport = dev->ioport[0] + 0x02;
1077        outb(0x02, tmport++);   /* 2*2=4ms,3EH 2/32*3E=3.9ms */
1078        outb(0, tmport++);
1079        outb(0, tmport++);
1080        outb(0, tmport++);
1081        outb(0, tmport++);
1082        outb(0, tmport++);
1083        outb(0, tmport++);
1084
1085        for (i = 0; i < j; i++) {
1086                m = 1;
1087                m = m << i;
1088                if ((m & assignid_map) != 0) {
1089                        continue;
1090                }
1091                tmport = dev->ioport[0] + 0x0f;
1092                outb(0, tmport++);
1093                tmport += 0x02;
1094                outb(0, tmport++);
1095                outb(0, tmport++);
1096                outb(0, tmport++);
1097                if (i > 7) {
1098                        k = (i & 0x07) | 0x40;
1099                } else {
1100                        k = i;
1101                }
1102                outb(k, tmport++);
1103                tmport = dev->ioport[0] + 0x1b;
1104                if (dev->chip_ver == 4) {
1105                        outb(0x01, tmport);
1106                } else {
1107                        outb(0x00, tmport);
1108                }
1109wait_rdyok:
1110                tmport = dev->ioport[0] + 0x18;
1111                outb(0x09, tmport);
1112                tmport += 0x07;
1113
1114                while ((inb(tmport) & 0x80) == 0x00)
1115                        cpu_relax();
1116                tmport -= 0x08;
1117                k = inb(tmport);
1118                if (k != 0x16) {
1119                        if ((k == 0x85) || (k == 0x42)) {
1120                                continue;
1121                        }
1122                        tmport = dev->ioport[0] + 0x10;
1123                        outb(0x41, tmport);
1124                        goto wait_rdyok;
1125                }
1126                assignid_map |= m;
1127
1128        }
1129        tmport = dev->ioport[0] + 0x02;
1130        outb(0x7f, tmport);
1131        tmport = dev->ioport[0] + 0x1b;
1132        outb(0x02, tmport);
1133
1134        outb(0, 0x80);
1135
1136        val = 0x0080;           /* bsy  */
1137        tmport = dev->ioport[0] + 0x1c;
1138        outw(val, tmport);
1139        val |= 0x0040;          /* sel  */
1140        outw(val, tmport);
1141        val |= 0x0004;          /* msg  */
1142        outw(val, tmport);
1143        inb(0x80);              /* 2 deskew delay(45ns*2=90ns) */
1144        val &= 0x007f;          /* no bsy  */
1145        outw(val, tmport);
1146        mdelay(128);
1147        val &= 0x00fb;          /* after 1ms no msg */
1148        outw(val, tmport);
1149wait_nomsg:
1150        if ((inb(tmport) & 0x04) != 0) {
1151                goto wait_nomsg;
1152        }
1153        outb(1, 0x80);
1154        udelay(100);
1155        for (n = 0; n < 0x30000; n++) {
1156                if ((inb(tmport) & 0x80) != 0) {        /* bsy ? */
1157                        goto wait_io;
1158                }
1159        }
1160        goto TCM_SYNC;
1161wait_io:
1162        for (n = 0; n < 0x30000; n++) {
1163                if ((inb(tmport) & 0x81) == 0x0081) {
1164                        goto wait_io1;
1165                }
1166        }
1167        goto TCM_SYNC;
1168wait_io1:
1169        inb(0x80);
1170        val |= 0x8003;          /* io,cd,db7  */
1171        outw(val, tmport);
1172        inb(0x80);
1173        val &= 0x00bf;          /* no sel     */
1174        outw(val, tmport);
1175        outb(2, 0x80);
1176TCM_SYNC:
1177        udelay(0x800);
1178        if ((inb(tmport) & 0x80) == 0x00) {     /* bsy ? */
1179                outw(0, tmport--);
1180                outb(0, tmport);
1181                tmport = dev->ioport[0] + 0x15;
1182                outb(0, tmport);
1183                tmport += 0x03;
1184                outb(0x09, tmport);
1185                tmport += 0x07;
1186                while ((inb(tmport) & 0x80) == 0)
1187                        cpu_relax();
1188                tmport -= 0x08;
1189                inb(tmport);
1190                return;
1191        }
1192        val &= 0x00ff;          /* synchronization  */
1193        val |= 0x3f00;
1194        fun_scam(dev, &val);
1195        outb(3, 0x80);
1196        val &= 0x00ff;          /* isolation        */
1197        val |= 0x2000;
1198        fun_scam(dev, &val);
1199        outb(4, 0x80);
1200        i = 8;
1201        j = 0;
1202TCM_ID:
1203        if ((inw(tmport) & 0x2000) == 0) {
1204                goto TCM_ID;
1205        }
1206        outb(5, 0x80);
1207        val &= 0x00ff;          /* get ID_STRING */
1208        val |= 0x2000;
1209        k = fun_scam(dev, &val);
1210        if ((k & 0x03) == 0) {
1211                goto TCM_5;
1212        }
1213        mbuf[j] <<= 0x01;
1214        mbuf[j] &= 0xfe;
1215        if ((k & 0x02) != 0) {
1216                mbuf[j] |= 0x01;
1217        }
1218        i--;
1219        if (i > 0) {
1220                goto TCM_ID;
1221        }
1222        j++;
1223        i = 8;
1224        goto TCM_ID;
1225
1226TCM_5:                  /* isolation complete..  */
1227/*    mbuf[32]=0;
1228        printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
1229        i = 15;
1230        j = mbuf[0];
1231        if ((j & 0x20) != 0) {  /* bit5=1:ID up to 7      */
1232                i = 7;
1233        }
1234        if ((j & 0x06) == 0) {  /* IDvalid?             */
1235                goto G2Q5;
1236        }
1237        k = mbuf[1];
1238small_id:
1239        m = 1;
1240        m <<= k;
1241        if ((m & assignid_map) == 0) {
1242                goto G2Q_QUIN;
1243        }
1244        if (k > 0) {
1245                k--;
1246                goto small_id;
1247        }
1248G2Q5:                   /* srch from max acceptable ID#  */
1249        k = i;                  /* max acceptable ID#            */
1250G2Q_LP:
1251        m = 1;
1252        m <<= k;
1253        if ((m & assignid_map) == 0) {
1254                goto G2Q_QUIN;
1255        }
1256        if (k > 0) {
1257                k--;
1258                goto G2Q_LP;
1259        }
1260G2Q_QUIN:               /* k=binID#,       */
1261        assignid_map |= m;
1262        if (k < 8) {
1263                quintet[0] = 0x38;      /* 1st dft ID<8    */
1264        } else {
1265                quintet[0] = 0x31;      /* 1st  ID>=8      */
1266        }
1267        k &= 0x07;
1268        quintet[1] = g2q_tab[k];
1269
1270        val &= 0x00ff;          /* AssignID 1stQuintet,AH=001xxxxx  */
1271        m = quintet[0] << 8;
1272        val |= m;
1273        fun_scam(dev, &val);
1274        val &= 0x00ff;          /* AssignID 2ndQuintet,AH=001xxxxx */
1275        m = quintet[1] << 8;
1276        val |= m;
1277        fun_scam(dev, &val);
1278
1279        goto TCM_SYNC;
1280
1281}
1282
1283static void is870(struct atp_unit *dev, unsigned int wkport)
1284{
1285        unsigned int tmport;
1286        unsigned char i, j, k, rmb, n;
1287        unsigned short int m;
1288        static unsigned char mbuf[512];
1289        static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1290        static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1291        static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1292        static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
1293        static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
1294        static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1295        
1296        tmport = wkport + 0x3a;
1297        outb((unsigned char) (inb(tmport) | 0x10), tmport);
1298
1299        for (i = 0; i < 16; i++) {
1300                if ((dev->chip_ver != 4) && (i > 7)) {
1301                        break;
1302                }
1303                m = 1;
1304                m = m << i;
1305                if ((m & dev->active_id[0]) != 0) {
1306                        continue;
1307                }
1308                if (i == dev->host_id[0]) {
1309                        printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
1310                        continue;
1311                }
1312                tmport = wkport + 0x1b;
1313                if (dev->chip_ver == 4) {
1314                        outb(0x01, tmport);
1315                } else {
1316                        outb(0x00, tmport);
1317                }
1318                tmport = wkport + 1;
1319                outb(0x08, tmport++);
1320                outb(0x7f, tmport++);
1321                outb(satn[0], tmport++);
1322                outb(satn[1], tmport++);
1323                outb(satn[2], tmport++);
1324                outb(satn[3], tmport++);
1325                outb(satn[4], tmport++);
1326                outb(satn[5], tmport++);
1327                tmport += 0x06;
1328                outb(0, tmport);
1329                tmport += 0x02;
1330                outb(dev->id[0][i].devsp, tmport++);
1331                outb(0, tmport++);
1332                outb(satn[6], tmport++);
1333                outb(satn[7], tmport++);
1334                j = i;
1335                if ((j & 0x08) != 0) {
1336                        j = (j & 0x07) | 0x40;
1337                }
1338                outb(j, tmport);
1339                tmport += 0x03;
1340                outb(satn[8], tmport);
1341                tmport += 0x07;
1342
1343                while ((inb(tmport) & 0x80) == 0x00)
1344                        cpu_relax();
1345
1346                tmport -= 0x08;
1347                if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1348                        continue;
1349
1350                while (inb(tmport) != 0x8e)
1351                        cpu_relax();
1352
1353                dev->active_id[0] |= m;
1354
1355                tmport = wkport + 0x10;
1356                outb(0x30, tmport);
1357                tmport = wkport + 0x04;
1358                outb(0x00, tmport);
1359
1360phase_cmd:
1361                tmport = wkport + 0x18;
1362                outb(0x08, tmport);
1363                tmport += 0x07;
1364                while ((inb(tmport) & 0x80) == 0x00)
1365                        cpu_relax();
1366                tmport -= 0x08;
1367                j = inb(tmport);
1368                if (j != 0x16) {
1369                        tmport = wkport + 0x10;
1370                        outb(0x41, tmport);
1371                        goto phase_cmd;
1372                }
1373sel_ok:
1374                tmport = wkport + 3;
1375                outb(inqd[0], tmport++);
1376                outb(inqd[1], tmport++);
1377                outb(inqd[2], tmport++);
1378                outb(inqd[3], tmport++);
1379                outb(inqd[4], tmport++);
1380                outb(inqd[5], tmport);
1381                tmport += 0x07;
1382                outb(0, tmport);
1383                tmport += 0x02;
1384                outb(dev->id[0][i].devsp, tmport++);
1385                outb(0, tmport++);
1386                outb(inqd[6], tmport++);
1387                outb(inqd[7], tmport++);
1388                tmport += 0x03;
1389                outb(inqd[8], tmport);
1390                tmport += 0x07;
1391
1392                while ((inb(tmport) & 0x80) == 0x00)
1393                        cpu_relax();
1394                        
1395                tmport -= 0x08;
1396                if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1397                        continue;
1398
1399                while (inb(tmport) != 0x8e)
1400                        cpu_relax();
1401                        
1402                tmport = wkport + 0x1b;
1403                if (dev->chip_ver == 4)
1404                        outb(0x00, tmport);
1405
1406                tmport = wkport + 0x18;
1407                outb(0x08, tmport);
1408                tmport += 0x07;
1409                j = 0;
1410rd_inq_data:
1411                k = inb(tmport);
1412                if ((k & 0x01) != 0) {
1413                        tmport -= 0x06;
1414                        mbuf[j++] = inb(tmport);
1415                        tmport += 0x06;
1416                        goto rd_inq_data;
1417                }
1418                if ((k & 0x80) == 0) {
1419                        goto rd_inq_data;
1420                }
1421                tmport -= 0x08;
1422                j = inb(tmport);
1423                if (j == 0x16) {
1424                        goto inq_ok;
1425                }
1426                tmport = wkport + 0x10;
1427                outb(0x46, tmport);
1428                tmport += 0x02;
1429                outb(0, tmport++);
1430                outb(0, tmport++);
1431                outb(0, tmport++);
1432                tmport += 0x03;
1433                outb(0x08, tmport);
1434                tmport += 0x07;
1435
1436                while ((inb(tmport) & 0x80) == 0x00)
1437                        cpu_relax();
1438                        
1439                tmport -= 0x08;
1440                if (inb(tmport) != 0x16) {
1441                        goto sel_ok;
1442                }
1443inq_ok:
1444                mbuf[36] = 0;
1445                printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
1446                dev->id[0][i].devtype = mbuf[0];
1447                rmb = mbuf[1];
1448                n = mbuf[7];
1449                if (dev->chip_ver != 4) {
1450                        goto not_wide;
1451                }
1452                if ((mbuf[7] & 0x60) == 0) {
1453                        goto not_wide;
1454                }
1455                if ((dev->global_map[0] & 0x20) == 0) {
1456                        goto not_wide;
1457                }
1458                tmport = wkport + 0x1b;
1459                outb(0x01, tmport);
1460                tmport = wkport + 3;
1461                outb(satn[0], tmport++);
1462                outb(satn[1], tmport++);
1463                outb(satn[2], tmport++);
1464                outb(satn[3], tmport++);
1465                outb(satn[4], tmport++);
1466                outb(satn[5], tmport++);
1467                tmport += 0x06;
1468                outb(0, tmport);
1469                tmport += 0x02;
1470                outb(dev->id[0][i].devsp, tmport++);
1471                outb(0, tmport++);
1472                outb(satn[6], tmport++);
1473                outb(satn[7], tmport++);
1474                tmport += 0x03;
1475                outb(satn[8], tmport);
1476                tmport += 0x07;
1477
1478                while ((inb(tmport) & 0x80) == 0x00)
1479                        cpu_relax();
1480                        
1481                tmport -= 0x08;
1482                if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1483                        continue;
1484
1485                while (inb(tmport) != 0x8e)
1486                        cpu_relax();
1487                        
1488try_wide:
1489                j = 0;
1490                tmport = wkport + 0x14;
1491                outb(0x05, tmport);
1492                tmport += 0x04;
1493                outb(0x20, tmport);
1494                tmport += 0x07;
1495
1496                while ((inb(tmport) & 0x80) == 0) {
1497                        if ((inb(tmport) & 0x01) != 0) {
1498                                tmport -= 0x06;
1499                                outb(wide[j++], tmport);
1500                                tmport += 0x06;
1501                        }
1502                }
1503                tmport -= 0x08;
1504                
1505                while ((inb(tmport) & 0x80) == 0x00)
1506                        cpu_relax();
1507                        
1508                j = inb(tmport) & 0x0f;
1509                if (j == 0x0f) {
1510                        goto widep_in;
1511                }
1512                if (j == 0x0a) {
1513                        goto widep_cmd;
1514                }
1515                if (j == 0x0e) {
1516                        goto try_wide;
1517                }
1518                continue;
1519widep_out:
1520                tmport = wkport + 0x18;
1521                outb(0x20, tmport);
1522                tmport += 0x07;
1523                while ((inb(tmport) & 0x80) == 0) {
1524                        if ((inb(tmport) & 0x01) != 0) {
1525                                tmport -= 0x06;
1526                                outb(0, tmport);
1527                                tmport += 0x06;
1528                        }
1529                }
1530                tmport -= 0x08;
1531                j = inb(tmport) & 0x0f;
1532                if (j == 0x0f) {
1533                        goto widep_in;
1534                }
1535                if (j == 0x0a) {
1536                        goto widep_cmd;
1537                }
1538                if (j == 0x0e) {
1539                        goto widep_out;
1540                }
1541                continue;
1542widep_in:
1543                tmport = wkport + 0x14;
1544                outb(0xff, tmport);
1545                tmport += 0x04;
1546                outb(0x20, tmport);
1547                tmport += 0x07;
1548                k = 0;
1549widep_in1:
1550                j = inb(tmport);
1551                if ((j & 0x01) != 0) {
1552                        tmport -= 0x06;
1553                        mbuf[k++] = inb(tmport);
1554                        tmport += 0x06;
1555                        goto widep_in1;
1556                }
1557                if ((j & 0x80) == 0x00) {
1558                        goto widep_in1;
1559                }
1560                tmport -= 0x08;
1561                j = inb(tmport) & 0x0f;
1562                if (j == 0x0f) {
1563                        goto widep_in;
1564                }
1565                if (j == 0x0a) {
1566                        goto widep_cmd;
1567                }
1568                if (j == 0x0e) {
1569                        goto widep_out;
1570                }
1571                continue;
1572widep_cmd:
1573                tmport = wkport + 0x10;
1574                outb(0x30, tmport);
1575                tmport = wkport + 0x14;
1576                outb(0x00, tmport);
1577                tmport += 0x04;
1578                outb(0x08, tmport);
1579                tmport += 0x07;
1580                
1581                while ((inb(tmport) & 0x80) == 0x00)
1582                        cpu_relax();
1583
1584                tmport -= 0x08;
1585                j = inb(tmport);
1586                if (j != 0x16) {
1587                        if (j == 0x4e) {
1588                                goto widep_out;
1589                        }
1590                        continue;
1591                }
1592                if (mbuf[0] != 0x01) {
1593                        goto not_wide;
1594                }
1595                if (mbuf[1] != 0x02) {
1596                        goto not_wide;
1597                }
1598                if (mbuf[2] != 0x03) {
1599                        goto not_wide;
1600                }
1601                if (mbuf[3] != 0x01) {
1602                        goto not_wide;
1603                }
1604                m = 1;
1605                m = m << i;
1606                dev->wide_id[0] |= m;
1607not_wide:
1608                if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
1609                        goto set_sync;
1610                }
1611                continue;
1612set_sync:
1613                tmport = wkport + 0x1b;
1614                j = 0;
1615                if ((m & dev->wide_id[0]) != 0) {
1616                        j |= 0x01;
1617                }
1618                outb(j, tmport);
1619                tmport = wkport + 3;
1620                outb(satn[0], tmport++);
1621                outb(satn[1], tmport++);
1622                outb(satn[2], tmport++);
1623                outb(satn[3], tmport++);
1624                outb(satn[4], tmport++);
1625                outb(satn[5], tmport++);
1626                tmport += 0x06;
1627                outb(0, tmport);
1628                tmport += 0x02;
1629                outb(dev->id[0][i].devsp, tmport++);
1630                outb(0, tmport++);
1631                outb(satn[6], tmport++);
1632                outb(satn[7], tmport++);
1633                tmport += 0x03;
1634                outb(satn[8], tmport);
1635                tmport += 0x07;
1636
1637                while ((inb(tmport) & 0x80) == 0x00)
1638                        cpu_relax();
1639                        
1640                tmport -= 0x08;
1641                if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1642                        continue;
1643
1644                while (inb(tmport) != 0x8e)
1645                        cpu_relax();
1646                        
1647try_sync:
1648                j = 0;
1649                tmport = wkport + 0x14;
1650                outb(0x06, tmport);
1651                tmport += 0x04;
1652                outb(0x20, tmport);
1653                tmport += 0x07;
1654
1655                while ((inb(tmport) & 0x80) == 0) {
1656                        if ((inb(tmport) & 0x01) != 0) {
1657                                tmport -= 0x06;
1658                                if ((m & dev->wide_id[0]) != 0) {
1659                                        outb(synw[j++], tmport);
1660                                } else {
1661                                        if ((m & dev->ultra_map[0]) != 0) {
1662                                                outb(synu[j++], tmport);
1663                                        } else {
1664                                                outb(synn[j++], tmport);
1665                                        }
1666                                }
1667                                tmport += 0x06;
1668                        }
1669                }
1670                tmport -= 0x08;
1671                
1672                while ((inb(tmport) & 0x80) == 0x00)
1673                        cpu_relax();
1674                        
1675                j = inb(tmport) & 0x0f;
1676                if (j == 0x0f) {
1677                        goto phase_ins;
1678                }
1679                if (j == 0x0a) {
1680                        goto phase_cmds;
1681                }
1682                if (j == 0x0e) {
1683                        goto try_sync;
1684                }
1685                continue;
1686phase_outs:
1687                tmport = wkport + 0x18;
1688                outb(0x20, tmport);
1689                tmport += 0x07;
1690                while ((inb(tmport) & 0x80) == 0x00) {
1691                        if ((inb(tmport) & 0x01) != 0x00) {
1692                                tmport -= 0x06;
1693                                outb(0x00, tmport);
1694                                tmport += 0x06;
1695                        }
1696                }
1697                tmport -= 0x08;
1698                j = inb(tmport);
1699                if (j == 0x85) {
1700                        goto tar_dcons;
1701                }
1702                j &= 0x0f;
1703                if (j == 0x0f) {
1704                        goto phase_ins;
1705                }
1706                if (j == 0x0a) {
1707                        goto phase_cmds;
1708                }
1709                if (j == 0x0e) {
1710                        goto phase_outs;
1711                }
1712                continue;
1713phase_ins:
1714                tmport = wkport + 0x14;
1715                outb(0xff, tmport);
1716                tmport += 0x04;
1717                outb(0x20, tmport);
1718                tmport += 0x07;
1719                k = 0;
1720phase_ins1:
1721                j = inb(tmport);
1722                if ((j & 0x01) != 0x00) {
1723                        tmport -= 0x06;
1724                        mbuf[k++] = inb(tmport);
1725                        tmport += 0x06;
1726                        goto phase_ins1;
1727                }
1728                if ((j & 0x80) == 0x00) {
1729                        goto phase_ins1;
1730                }
1731                tmport -= 0x08;
1732
1733                while ((inb(tmport) & 0x80) == 0x00)
1734                        cpu_relax();
1735                        
1736                j = inb(tmport);
1737                if (j == 0x85) {
1738                        goto tar_dcons;
1739                }
1740                j &= 0x0f;
1741                if (j == 0x0f) {
1742                        goto phase_ins;
1743                }
1744                if (j == 0x0a) {
1745                        goto phase_cmds;
1746                }
1747                if (j == 0x0e) {
1748                        goto phase_outs;
1749                }
1750                continue;
1751phase_cmds:
1752                tmport = wkport + 0x10;
1753                outb(0x30, tmport);
1754tar_dcons:
1755                tmport = wkport + 0x14;
1756                outb(0x00, tmport);
1757                tmport += 0x04;
1758                outb(0x08, tmport);
1759                tmport += 0x07;
1760                
1761                while ((inb(tmport) & 0x80) == 0x00)
1762                        cpu_relax();
1763                        
1764                tmport -= 0x08;
1765                j = inb(tmport);
1766                if (j != 0x16) {
1767                        continue;
1768                }
1769                if (mbuf[0] != 0x01) {
1770                        continue;
1771                }
1772                if (mbuf[1] != 0x03) {
1773                        continue;
1774                }
1775                if (mbuf[4] == 0x00) {
1776                        continue;
1777                }
1778                if (mbuf[3] > 0x64) {
1779                        continue;
1780                }
1781                if (mbuf[4] > 0x0c) {
1782                        mbuf[4] = 0x0c;
1783                }
1784                dev->id[0][i].devsp = mbuf[4];
1785                if ((mbuf[3] < 0x0d) && (rmb == 0)) {
1786                        j = 0xa0;
1787                        goto set_syn_ok;
1788                }
1789                if (mbuf[3] < 0x1a) {
1790                        j = 0x20;
1791                        goto set_syn_ok;
1792                }
1793                if (mbuf[3] < 0x33) {
1794                        j = 0x40;
1795                        goto set_syn_ok;
1796                }
1797                if (mbuf[3] < 0x4c) {
1798                        j = 0x50;
1799                        goto set_syn_ok;
1800                }
1801                j = 0x60;
1802set_syn_ok:
1803                dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
1804        }
1805        tmport = wkport + 0x3a;
1806        outb((unsigned char) (inb(tmport) & 0xef), tmport);
1807}
1808
1809static void is880(struct atp_unit *dev, unsigned int wkport)
1810{
1811        unsigned int tmport;
1812        unsigned char i, j, k, rmb, n, lvdmode;
1813        unsigned short int m;
1814        static unsigned char mbuf[512];
1815        static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1816        static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1817        static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1818        unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1819        static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1820        unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1821        static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1822        static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
1823
1824        lvdmode = inb(wkport + 0x3f) & 0x40;
1825
1826        for (i = 0; i < 16; i++) {
1827                m = 1;
1828                m = m << i;
1829                if ((m & dev->active_id[0]) != 0) {
1830                        continue;
1831                }
1832                if (i == dev->host_id[0]) {
1833                        printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
1834                        continue;
1835                }
1836                tmport = wkport + 0x5b;
1837                outb(0x01, tmport);
1838                tmport = wkport + 0x41;
1839                outb(0x08, tmport++);
1840                outb(0x7f, tmport++);
1841                outb(satn[0], tmport++);
1842                outb(satn[1], tmport++);
1843                outb(satn[2], tmport++);
1844                outb(satn[3], tmport++);
1845                outb(satn[4], tmport++);
1846                outb(satn[5], tmport++);
1847                tmport += 0x06;
1848                outb(0, tmport);
1849                tmport += 0x02;
1850                outb(dev->id[0][i].devsp, tmport++);
1851                outb(0, tmport++);
1852                outb(satn[6], tmport++);
1853                outb(satn[7], tmport++);
1854                j = i;
1855                if ((j & 0x08) != 0) {
1856                        j = (j & 0x07) | 0x40;
1857                }
1858                outb(j, tmport);
1859                tmport += 0x03;
1860                outb(satn[8], tmport);
1861                tmport += 0x07;
1862
1863                while ((inb(tmport) & 0x80) == 0x00)
1864                        cpu_relax();
1865
1866                tmport -= 0x08;
1867                if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1868                        continue;
1869
1870                while (inb(tmport) != 0x8e)
1871                        cpu_relax();
1872                        
1873                dev->active_id[0] |= m;
1874
1875                tmport = wkport + 0x50;
1876                outb(0x30, tmport);
1877                tmport = wkport + 0x54;
1878                outb(0x00, tmport);
1879
1880phase_cmd:
1881                tmport = wkport + 0x58;
1882                outb(0x08, tmport);
1883                tmport += 0x07;
1884                
1885                while ((inb(tmport) & 0x80) == 0x00)
1886                        cpu_relax();
1887
1888                tmport -= 0x08;
1889                j = inb(tmport);
1890                if (j != 0x16) {
1891                        tmport = wkport + 0x50;
1892                        outb(0x41, tmport);
1893                        goto phase_cmd;
1894                }
1895sel_ok:
1896                tmport = wkport + 0x43;
1897                outb(inqd[0], tmport++);
1898                outb(inqd[1], tmport++);
1899                outb(inqd[2], tmport++);
1900                outb(inqd[3], tmport++);
1901                outb(inqd[4], tmport++);
1902                outb(inqd[5], tmport);
1903                tmport += 0x07;
1904                outb(0, tmport);
1905                tmport += 0x02;
1906                outb(dev->id[0][i].devsp, tmport++);
1907                outb(0, tmport++);
1908                outb(inqd[6], tmport++);
1909                outb(inqd[7], tmport++);
1910                tmport += 0x03;
1911                outb(inqd[8], tmport);
1912                tmport += 0x07;
1913                
1914                while ((inb(tmport) & 0x80) == 0x00)
1915                        cpu_relax();
1916                        
1917                tmport -= 0x08;
1918                if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1919                        continue;
1920
1921                while (inb(tmport) != 0x8e)
1922                        cpu_relax();
1923                        
1924                tmport = wkport + 0x5b;
1925                outb(0x00, tmport);
1926                tmport = wkport + 0x58;
1927                outb(0x08, tmport);
1928                tmport += 0x07;
1929                j = 0;
1930rd_inq_data:
1931                k = inb(tmport);
1932                if ((k & 0x01) != 0) {
1933                        tmport -= 0x06;
1934                        mbuf[j++] = inb(tmport);
1935                        tmport += 0x06;
1936                        goto rd_inq_data;
1937                }
1938                if ((k & 0x80) == 0) {
1939                        goto rd_inq_data;
1940                }
1941                tmport -= 0x08;
1942                j = inb(tmport);
1943                if (j == 0x16) {
1944                        goto inq_ok;
1945                }
1946                tmport = wkport + 0x50;
1947                outb(0x46, tmport);
1948                tmport += 0x02;
1949                outb(0, tmport++);
1950                outb(0, tmport++);
1951                outb(0, tmport++);
1952                tmport += 0x03;
1953                outb(0x08, tmport);
1954                tmport += 0x07;
1955                while ((inb(tmport) & 0x80) == 0x00)
1956                        cpu_relax();
1957                        
1958                tmport -= 0x08;
1959                if (inb(tmport) != 0x16)
1960                        goto sel_ok;
1961
1962inq_ok:
1963                mbuf[36] = 0;
1964                printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
1965                dev->id[0][i].devtype = mbuf[0];
1966                rmb = mbuf[1];
1967                n = mbuf[7];
1968                if ((mbuf[7] & 0x60) == 0) {
1969                        goto not_wide;
1970                }
1971                if ((i < 8) && ((dev->global_map[0] & 0x20) == 0)) {
1972                        goto not_wide;
1973                }
1974                if (lvdmode == 0) {
1975                        goto chg_wide;
1976                }
1977                if (dev->sp[0][i] != 0x04)      // force u2
1978                {
1979                        goto chg_wide;
1980                }
1981
1982                tmport = wkport + 0x5b;
1983                outb(0x01, tmport);
1984                tmport = wkport + 0x43;
1985                outb(satn[0], tmport++);
1986                outb(satn[1], tmport++);
1987                outb(satn[2], tmport++);
1988                outb(satn[3], tmport++);
1989                outb(satn[4], tmport++);
1990                outb(satn[5], tmport++);
1991                tmport += 0x06;
1992                outb(0, tmport);
1993                tmport += 0x02;
1994                outb(dev->id[0][i].devsp, tmport++);
1995                outb(0, tmport++);
1996                outb(satn[6], tmport++);
1997                outb(satn[7], tmport++);
1998                tmport += 0x03;
1999                outb(satn[8], tmport);
2000                tmport += 0x07;
2001
2002                while ((inb(tmport) & 0x80) == 0x00)
2003                        cpu_relax();
2004
2005                tmport -= 0x08;
2006
2007                if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
2008                        continue;
2009
2010                while (inb(tmport) != 0x8e)
2011                        cpu_relax();
2012
2013try_u3:
2014                j = 0;
2015                tmport = wkport + 0x54;
2016                outb(0x09, tmport);
2017                tmport += 0x04;
2018                outb(0x20, tmport);
2019                tmport += 0x07;
2020
2021                while ((inb(tmport) & 0x80) == 0) {
2022                        if ((inb(tmport) & 0x01) != 0) {
2023                                tmport -= 0x06;
2024                                outb(u3[j++], tmport);
2025                                tmport += 0x06;
2026                        }
2027                }
2028                tmport -= 0x08;
2029
2030                while ((inb(tmport) & 0x80) == 0x00)
2031                        cpu_relax();
2032                        
2033                j = inb(tmport) & 0x0f;
2034                if (j == 0x0f) {
2035                        goto u3p_in;
2036                }
2037                if (j == 0x0a) {
2038                        goto u3p_cmd;
2039                }
2040                if (j == 0x0e) {
2041                        goto try_u3;
2042                }
2043                continue;
2044u3p_out:
2045                tmport = wkport + 0x58;
2046                outb(0x20, tmport);
2047                tmport += 0x07;
2048                while ((inb(tmport) & 0x80) == 0) {
2049                        if ((inb(tmport) & 0x01) != 0) {
2050                                tmport -= 0x06;
2051                                outb(0, tmport);
2052                                tmport += 0x06;
2053                        }
2054                }
2055                tmport -= 0x08;
2056                j = inb(tmport) & 0x0f;
2057                if (j == 0x0f) {
2058                        goto u3p_in;
2059                }
2060                if (j == 0x0a) {
2061                        goto u3p_cmd;
2062                }
2063                if (j == 0x0e) {
2064                        goto u3p_out;
2065                }
2066                continue;
2067u3p_in:
2068                tmport = wkport + 0x54;
2069                outb(0x09, tmport);
2070                tmport += 0x04;
2071                outb(0x20, tmport);
2072                tmport += 0x07;
2073                k = 0;
2074u3p_in1:
2075                j = inb(tmport);
2076                if ((j & 0x01) != 0) {
2077                        tmport -= 0x06;
2078                        mbuf[k++] = inb(tmport);
2079                        tmport += 0x06;
2080                        goto u3p_in1;
2081                }
2082                if ((j & 0x80) == 0x00) {
2083                        goto u3p_in1;
2084                }
2085                tmport -= 0x08;
2086                j = inb(tmport) & 0x0f;
2087                if (j == 0x0f) {
2088                        goto u3p_in;
2089                }
2090                if (j == 0x0a) {
2091                        goto u3p_cmd;
2092                }
2093                if (j == 0x0e) {
2094                        goto u3p_out;
2095                }
2096                continue;
2097u3p_cmd:
2098                tmport = wkport + 0x50;
2099                outb(0x30, tmport);
2100                tmport = wkport + 0x54;
2101                outb(0x00, tmport);
2102                tmport += 0x04;
2103                outb(0x08, tmport);
2104                tmport += 0x07;
2105                
2106                while ((inb(tmport) & 0x80) == 0x00)
2107                        cpu_relax();
2108                        
2109                tmport -= 0x08;
2110                j = inb(tmport);
2111                if (j != 0x16) {
2112                        if (j == 0x4e) {
2113                                goto u3p_out;
2114                        }
2115                        continue;
2116                }
2117                if (mbuf[0] != 0x01) {
2118                        goto chg_wide;
2119                }
2120                if (mbuf[1] != 0x06) {
2121                        goto chg_wide;
2122                }
2123                if (mbuf[2] != 0x04) {
2124                        goto chg_wide;
2125                }
2126                if (mbuf[3] == 0x09) {
2127                        m = 1;
2128                        m = m << i;
2129                        dev->wide_id[0] |= m;
2130                        dev->id[0][i].devsp = 0xce;
2131                        continue;
2132                }
2133chg_wide:
2134                tmport = wkport + 0x5b;
2135                outb(0x01, tmport);
2136                tmport = wkport + 0x43;
2137                outb(satn[0], tmport++);
2138                outb(satn[1], tmport++);
2139                outb(satn[2], tmport++);
2140                outb(satn[3], tmport++);
2141                outb(satn[4], tmport++);
2142                outb(satn[5], tmport++);
2143                tmport += 0x06;
2144                outb(0, tmport);
2145                tmport += 0x02;
2146                outb(dev->id[0][i].devsp, tmport++);
2147                outb(0, tmport++);
2148                outb(satn[6], tmport++);
2149                outb(satn[7], tmport++);
2150                tmport += 0x03;
2151                outb(satn[8], tmport);
2152                tmport += 0x07;
2153
2154                while ((inb(tmport) & 0x80) == 0x00)
2155                        cpu_relax();
2156                        
2157                tmport -= 0x08;
2158                if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
2159                        continue;
2160
2161                while (inb(tmport) != 0x8e)
2162                        cpu_relax();
2163                        
2164try_wide:
2165                j = 0;
2166                tmport = wkport + 0x54;
2167                outb(0x05, tmport);
2168                tmport += 0x04;
2169                outb(0x20, tmport);
2170                tmport += 0x07;
2171
2172                while ((inb(tmport) & 0x80) == 0) {
2173                        if ((inb(tmport) & 0x01) != 0) {
2174                                tmport -= 0x06;
2175                                outb(wide[j++], tmport);
2176                                tmport += 0x06;
2177                        }
2178                }
2179                tmport -= 0x08;
2180                while ((inb(tmport) & 0x80) == 0x00)
2181                        cpu_relax();
2182                        
2183                j = inb(tmport) & 0x0f;
2184                if (j == 0x0f) {
2185                        goto widep_in;
2186                }
2187                if (j == 0x0a) {
2188                        goto widep_cmd;
2189                }
2190                if (j == 0x0e) {
2191                        goto try_wide;
2192                }
2193                continue;
2194widep_out:
2195                tmport = wkport + 0x58;
2196                outb(0x20, tmport);
2197                tmport += 0x07;
2198                while ((inb(tmport) & 0x80) == 0) {
2199                        if ((inb(tmport) & 0x01) != 0) {
2200                                tmport -= 0x06;
2201                                outb(0, tmport);
2202                                tmport += 0x06;
2203                        }
2204                }
2205                tmport -= 0x08;
2206                j = inb(tmport) & 0x0f;
2207                if (j == 0x0f) {
2208                        goto widep_in;
2209                }
2210                if (j == 0x0a) {
2211                        goto widep_cmd;
2212                }
2213                if (j == 0x0e) {
2214                        goto widep_out;
2215                }
2216                continue;
2217widep_in:
2218                tmport = wkport + 0x54;
2219                outb(0xff, tmport);
2220                tmport += 0x04;
2221                outb(0x20, tmport);
2222                tmport += 0x07;
2223                k = 0;
2224widep_in1:
2225                j = inb(tmport);
2226                if ((j & 0x01) != 0) {
2227                        tmport -= 0x06;
2228                        mbuf[k++] = inb(tmport);
2229                        tmport += 0x06;
2230                        goto widep_in1;
2231                }
2232                if ((j & 0x80) == 0x00) {
2233                        goto widep_in1;
2234                }
2235                tmport -= 0x08;
2236                j = inb(tmport) & 0x0f;
2237                if (j == 0x0f) {
2238                        goto widep_in;
2239                }
2240                if (j == 0x0a) {
2241                        goto widep_cmd;
2242                }
2243                if (j == 0x0e) {
2244                        goto widep_out;
2245                }
2246                continue;
2247widep_cmd:
2248                tmport = wkport + 0x50;
2249                outb(0x30, tmport);
2250                tmport = wkport + 0x54;
2251                outb(0x00, tmport);
2252                tmport += 0x04;
2253                outb(0x08, tmport);
2254                tmport += 0x07;
2255
2256                while ((inb(tmport) & 0x80) == 0x00)
2257                        cpu_relax();
2258
2259                tmport -= 0x08;
2260                j = inb(tmport);
2261                if (j != 0x16) {
2262                        if (j == 0x4e) {
2263                                goto widep_out;
2264                        }
2265                        continue;
2266                }
2267                if (mbuf[0] != 0x01) {
2268                        goto not_wide;
2269                }
2270                if (mbuf[1] != 0x02) {
2271                        goto not_wide;
2272                }
2273                if (mbuf[2] != 0x03) {
2274                        goto not_wide;
2275                }
2276                if (mbuf[3] != 0x01) {
2277                        goto not_wide;
2278                }
2279                m = 1;
2280                m = m << i;
2281                dev->wide_id[0] |= m;
2282not_wide:
2283                if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
2284                        m = 1;
2285                        m = m << i;
2286                        if ((dev->async[0] & m) != 0) {
2287                                goto set_sync;
2288                        }
2289                }
2290                continue;
2291set_sync:
2292                if (dev->sp[0][i] == 0x02) {
2293                        synu[4] = 0x0c;
2294                        synuw[4] = 0x0c;
2295                } else {
2296                        if (dev->sp[0][i] >= 0x03) {
2297                                synu[4] = 0x0a;
2298                                synuw[4] = 0x0a;
2299                        }
2300                }
2301                tmport = wkport + 0x5b;
2302                j = 0;
2303                if ((m & dev->wide_id[0]) != 0) {
2304                        j |= 0x01;
2305                }
2306                outb(j, tmport);
2307                tmport = wkport + 0x43;
2308                outb(satn[0], tmport++);
2309                outb(satn[1], tmport++);
2310                outb(satn[2], tmport++);
2311                outb(satn[3], tmport++);
2312                outb(satn[4], tmport++);
2313                outb(satn[5], tmport++);
2314                tmport += 0x06;
2315                outb(0, tmport);
2316                tmport += 0x02;
2317                outb(dev->id[0][i].devsp, tmport++);
2318                outb(0, tmport++);
2319                outb(satn[6], tmport++);
2320                outb(satn[7], tmport++);
2321                tmport += 0x03;
2322                outb(satn[8], tmport);
2323                tmport += 0x07;
2324
2325                while ((inb(tmport) & 0x80) == 0x00)
2326                        cpu_relax();
2327
2328                tmport -= 0x08;
2329                if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
2330                        continue;
2331                }
2332                while (inb(tmport) != 0x8e)
2333                        cpu_relax();
2334
2335try_sync:
2336                j = 0;
2337                tmport = wkport + 0x54;
2338                outb(0x06, tmport);
2339                tmport += 0x04;
2340                outb(0x20, tmport);
2341                tmport += 0x07;
2342
2343                while ((inb(tmport) & 0x80) == 0) {
2344                        if ((inb(tmport) & 0x01) != 0) {
2345                                tmport -= 0x06;
2346                                if ((m & dev->wide_id[0]) != 0) {
2347                                        if ((m & dev->ultra_map[0]) != 0) {
2348                                                outb(synuw[j++], tmport);
2349                                        } else {
2350                                                outb(synw[j++], tmport);
2351                                        }
2352                                } else {
2353                                        if ((m & dev->ultra_map[0]) != 0) {
2354                                                outb(synu[j++], tmport);
2355                                        } else {
2356                                                outb(synn[j++], tmport);
2357                                        }
2358                                }
2359                                tmport += 0x06;
2360                        }
2361                }
2362                tmport -= 0x08;
2363
2364                while ((inb(tmport) & 0x80) == 0x00)
2365                        cpu_relax();
2366
2367                j = inb(tmport) & 0x0f;
2368                if (j == 0x0f) {
2369                        goto phase_ins;
2370                }
2371                if (j == 0x0a) {
2372                        goto phase_cmds;
2373                }
2374                if (j == 0x0e) {
2375                        goto try_sync;
2376                }
2377                continue;
2378phase_outs:
2379                tmport = wkport + 0x58;
2380                outb(0x20, tmport);
2381                tmport += 0x07;
2382                while ((inb(tmport) & 0x80) == 0x00) {
2383                        if ((inb(tmport) & 0x01) != 0x00) {
2384                                tmport -= 0x06;
2385                                outb(0x00, tmport);
2386                                tmport += 0x06;
2387                        }
2388                }
2389                tmport -= 0x08;
2390                j = inb(tmport);
2391                if (j == 0x85) {
2392                        goto tar_dcons;
2393                }
2394                j &= 0x0f;
2395                if (j == 0x0f) {
2396                        goto phase_ins;
2397                }
2398                if (j == 0x0a) {
2399                        goto phase_cmds;
2400                }
2401                if (j == 0x0e) {
2402                        goto phase_outs;
2403                }
2404                continue;
2405phase_ins:
2406                tmport = wkport + 0x54;
2407                outb(0x06, tmport);
2408                tmport += 0x04;
2409                outb(0x20, tmport);
2410                tmport += 0x07;
2411                k = 0;
2412phase_ins1:
2413                j = inb(tmport);
2414                if ((j & 0x01) != 0x00) {
2415                        tmport -= 0x06;
2416                        mbuf[k++] = inb(tmport);
2417                        tmport += 0x06;
2418                        goto phase_ins1;
2419                }
2420                if ((j & 0x80) == 0x00) {
2421                        goto phase_ins1;
2422                }
2423                tmport -= 0x08;
2424
2425                while ((inb(tmport) & 0x80) == 0x00)
2426                        cpu_relax();
2427
2428                j = inb(tmport);
2429                if (j == 0x85) {
2430                        goto tar_dcons;
2431                }
2432                j &= 0x0f;
2433                if (j == 0x0f) {
2434                        goto phase_ins;
2435                }
2436                if (j == 0x0a) {
2437                        goto phase_cmds;
2438                }
2439                if (j == 0x0e) {
2440                        goto phase_outs;
2441                }
2442                continue;
2443phase_cmds:
2444                tmport = wkport + 0x50;
2445                outb(0x30, tmport);
2446tar_dcons:
2447                tmport = wkport + 0x54;
2448                outb(0x00, tmport);
2449                tmport += 0x04;
2450                outb(0x08, tmport);
2451                tmport += 0x07;
2452
2453                while ((inb(tmport) & 0x80) == 0x00)
2454                        cpu_relax();
2455
2456                tmport -= 0x08;
2457                j = inb(tmport);
2458                if (j != 0x16) {
2459                        continue;
2460                }
2461                if (mbuf[0] != 0x01) {
2462                        continue;
2463                }
2464                if (mbuf[1] != 0x03) {
2465                        continue;
2466                }
2467                if (mbuf[4] == 0x00) {
2468                        continue;
2469                }
2470                if (mbuf[3] > 0x64) {
2471                        continue;
2472                }
2473                if (mbuf[4] > 0x0e) {
2474                        mbuf[4] = 0x0e;
2475                }
2476                dev->id[0][i].devsp = mbuf[4];
2477                if (mbuf[3] < 0x0c) {
2478                        j = 0xb0;
2479                        goto set_syn_ok;
2480                }
2481                if ((mbuf[3] < 0x0d) && (rmb == 0)) {
2482                        j = 0xa0;
2483                        goto set_syn_ok;
2484                }
2485                if (mbuf[3] < 0x1a) {
2486                        j = 0x20;
2487                        goto set_syn_ok;
2488                }
2489                if (mbuf[3] < 0x33) {
2490                        j = 0x40;
2491                        goto set_syn_ok;
2492                }
2493                if (mbuf[3] < 0x4c) {
2494                        j = 0x50;
2495                        goto set_syn_ok;
2496                }
2497                j = 0x60;
2498set_syn_ok:
2499                dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
2500        }
2501}
2502
2503static void atp870u_free_tables(struct Scsi_Host *host)
2504{
2505        struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
2506        int j, k;
2507        for (j=0; j < 2; j++) {
2508                for (k = 0; k < 16; k++) {
2509                        if (!atp_dev->id[j][k].prd_table)
2510                                continue;
2511                        pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus);
2512                        atp_dev->id[j][k].prd_table = NULL;
2513                }
2514        }
2515}
2516
2517static int atp870u_init_tables(struct Scsi_Host *host)
2518{
2519        struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
2520        int c,k;
2521        for(c=0;c < 2;c++) {
2522                for(k=0;k<16;k++) {
2523                                atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus));
2524                                if (!atp_dev->id[c][k].prd_table) {
2525                                        printk("atp870u_init_tables fail\n");
2526                                atp870u_free_tables(host);
2527                                return -ENOMEM;
2528                        }
2529                        atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
2530                        atp_dev->id[c][k].devsp=0x20;
2531                        atp_dev->id[c][k].devtype = 0x7f;
2532                        atp_dev->id[c][k].curr_req = NULL;                         
2533                }
2534                                
2535                atp_dev->active_id[c] = 0;
2536                atp_dev->wide_id[c] = 0;
2537                atp_dev->host_id[c] = 0x07;
2538                atp_dev->quhd[c] = 0;
2539                atp_dev->quend[c] = 0;
2540                atp_dev->last_cmd[c] = 0xff;
2541                atp_dev->in_snd[c] = 0;
2542                atp_dev->in_int[c] = 0;
2543                
2544                for (k = 0; k < qcnt; k++) {
2545                          atp_dev->quereq[c][k] = NULL;
2546                }                          
2547                for (k = 0; k < 16; k++) {
2548                           atp_dev->id[c][k].curr_req = NULL;
2549                           atp_dev->sp[c][k] = 0x04;
2550                }                  
2551        }
2552        return 0;
2553}
2554
2555/* return non-zero on detection */
2556static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2557{
2558        unsigned char k, m, c;
2559        unsigned long flags;
2560        unsigned int base_io, tmport, error,n;
2561        unsigned char host_id;
2562        struct Scsi_Host *shpnt = NULL;
2563        struct atp_unit *atpdev, *p;
2564        unsigned char setupdata[2][16];
2565        int count = 0;
2566
2567        atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
2568        if (!atpdev)
2569                return -ENOMEM;
2570
2571        if (pci_enable_device(pdev))
2572                goto err_eio;
2573
2574        if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
2575                printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
2576        } else {
2577                printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
2578                goto err_eio;
2579        }
2580
2581        /*
2582         * It's probably easier to weed out some revisions like
2583         * this than via the PCI device table
2584         */
2585        if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
2586                error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atpdev->chip_ver);
2587                if (atpdev->chip_ver < 2)
2588                        goto err_eio;
2589        }
2590
2591        switch (ent->device) {
2592        case PCI_DEVICE_ID_ARTOP_AEC7612UW:
2593        case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
2594        case ATP880_DEVID1:     
2595        case ATP880_DEVID2:     
2596        case ATP885_DEVID:      
2597                atpdev->chip_ver = 0x04;
2598        default:
2599                break;
2600        }
2601        base_io = pci_resource_start(pdev, 0);
2602        base_io &= 0xfffffff8;
2603
2604        if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
2605                error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atpdev->chip_ver);
2606                pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
2607
2608                host_id = inb(base_io + 0x39);
2609                host_id >>= 0x04;
2610
2611                printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
2612                        "    IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
2613                atpdev->ioport[0] = base_io + 0x40;
2614                atpdev->pciport[0] = base_io + 0x28;
2615                atpdev->dev_id = ent->device;
2616                atpdev->host_id[0] = host_id;
2617
2618                tmport = base_io + 0x22;
2619                atpdev->scam_on = inb(tmport);
2620                tmport += 0x13;
2621                atpdev->global_map[0] = inb(tmport);
2622                tmport += 0x07;
2623                atpdev->ultra_map[0] = inw(tmport);
2624
2625                n = 0x3f09;
2626next_fblk_880:
2627                if (n >= 0x4000)
2628                        goto flash_ok_880;
2629
2630                m = 0;
2631                outw(n, base_io + 0x34);
2632                n += 0x0002;
2633                if (inb(base_io + 0x30) == 0xff)
2634                        goto flash_ok_880;
2635
2636                atpdev->sp[0][m++] = inb(base_io + 0x30);
2637                atpdev->sp[0][m++] = inb(base_io + 0x31);
2638                atpdev->sp[0][m++] = inb(base_io + 0x32);
2639                atpdev->sp[0][m++] = inb(base_io + 0x33);
2640                outw(n, base_io + 0x34);
2641                n += 0x0002;
2642                atpdev->sp[0][m++] = inb(base_io + 0x30);
2643                atpdev->sp[0][m++] = inb(base_io + 0x31);
2644                atpdev->sp[0][m++] = inb(base_io + 0x32);
2645                atpdev->sp[0][m++] = inb(base_io + 0x33);
2646                outw(n, base_io + 0x34);
2647                n += 0x0002;
2648                atpdev->sp[0][m++] = inb(base_io + 0x30);
2649                atpdev->sp[0][m++] = inb(base_io + 0x31);
2650                atpdev->sp[0][m++] = inb(base_io + 0x32);
2651                atpdev->sp[0][m++] = inb(base_io + 0x33);
2652                outw(n, base_io + 0x34);
2653                n += 0x0002;
2654                atpdev->sp[0][m++] = inb(base_io + 0x30);
2655                atpdev->sp[0][m++] = inb(base_io + 0x31);
2656                atpdev->sp[0][m++] = inb(base_io + 0x32);
2657                atpdev->sp[0][m++] = inb(base_io + 0x33);
2658                n += 0x0018;
2659                goto next_fblk_880;
2660flash_ok_880:
2661                outw(0, base_io + 0x34);
2662                atpdev->ultra_map[0] = 0;
2663                atpdev->async[0] = 0;
2664                for (k = 0; k < 16; k++) {
2665                        n = 1;
2666                        n = n << k;
2667                        if (atpdev->sp[0][k] > 1) {
2668                                atpdev->ultra_map[0] |= n;
2669                        } else {
2670                                if (atpdev->sp[0][k] == 0)
2671                                        atpdev->async[0] |= n;
2672                        }
2673                }
2674                atpdev->async[0] = ~(atpdev->async[0]);
2675                outb(atpdev->global_map[0], base_io + 0x35);
2676 
2677                shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2678                if (!shpnt)
2679                        goto err_nomem;
2680
2681                p = (struct atp_unit *)&shpnt->hostdata;
2682
2683                atpdev->host = shpnt;
2684                atpdev->pdev = pdev;
2685                pci_set_drvdata(pdev, p);
2686                memcpy(p, atpdev, sizeof(*atpdev));
2687                if (atp870u_init_tables(shpnt) < 0) {
2688                        printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
2689                        goto unregister;
2690                }
2691
2692                if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp880i", shpnt)) {
2693                        printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
2694                        goto free_tables;
2695                }
2696
2697                spin_lock_irqsave(shpnt->host_lock, flags);
2698                tmport = base_io + 0x38;
2699                k = inb(tmport) & 0x80;
2700                outb(k, tmport);
2701                tmport += 0x03;
2702                outb(0x20, tmport);
2703                mdelay(32);
2704                outb(0, tmport);
2705                mdelay(32);
2706                tmport = base_io + 0x5b;
2707                inb(tmport);
2708                tmport -= 0x04;
2709                inb(tmport);
2710                tmport = base_io + 0x40;
2711                outb((host_id | 0x08), tmport);
2712                tmport += 0x18;
2713                outb(0, tmport);
2714                tmport += 0x07;
2715                while ((inb(tmport) & 0x80) == 0)
2716                        mdelay(1);
2717                tmport -= 0x08;
2718                inb(tmport);
2719                tmport = base_io + 0x41;
2720                outb(8, tmport++);
2721                outb(0x7f, tmport);
2722                tmport = base_io + 0x51;
2723                outb(0x20, tmport);
2724
2725                tscam(shpnt);
2726                is880(p, base_io);
2727                tmport = base_io + 0x38;
2728                outb(0xb0, tmport);
2729                shpnt->max_id = 16;
2730                shpnt->this_id = host_id;
2731                shpnt->unique_id = base_io;
2732                shpnt->io_port = base_io;
2733                shpnt->n_io_port = 0x60;        /* Number of bytes of I/O space used */
2734                shpnt->irq = pdev->irq;                 
2735        } else if (ent->device == ATP885_DEVID) {       
2736                        printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD Host Adapter:  IO:%x, IRQ:%d.\n"
2737                               , base_io, pdev->irq);
2738                
2739                atpdev->pdev = pdev;
2740                atpdev->dev_id  = ent->device;
2741                atpdev->baseport = base_io;
2742                atpdev->ioport[0] = base_io + 0x80;
2743                atpdev->ioport[1] = base_io + 0xc0;
2744                atpdev->pciport[0] = base_io + 0x40;
2745                atpdev->pciport[1] = base_io + 0x50;
2746                                
2747                shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2748                if (!shpnt)
2749                        goto err_nomem;
2750                
2751                p = (struct atp_unit *)&shpnt->hostdata;
2752                
2753                atpdev->host = shpnt;
2754                atpdev->pdev = pdev;
2755                pci_set_drvdata(pdev, p);
2756                memcpy(p, atpdev, sizeof(struct atp_unit));
2757                if (atp870u_init_tables(shpnt) < 0)
2758                        goto unregister;
2759                        
2760#ifdef ED_DBGP          
2761        printk("request_irq() shpnt %p hostdata %p\n", shpnt, p);
2762#endif          
2763                if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt)) {
2764                                printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
2765                        goto free_tables;
2766                }
2767                
2768                spin_lock_irqsave(shpnt->host_lock, flags);                                             
2769                                
2770                c=inb(base_io + 0x29);
2771                outb((c | 0x04),base_io + 0x29);
2772                
2773                n=0x1f80;
2774next_fblk_885:
2775                if (n >= 0x2000) {
2776                   goto flash_ok_885;
2777                }
2778                outw(n,base_io + 0x3c);
2779                if (inl(base_io + 0x38) == 0xffffffff) {
2780                   goto flash_ok_885;
2781                }
2782                for (m=0; m < 2; m++) {
2783                    p->global_map[m]= 0;
2784                    for (k=0; k < 4; k++) {
2785                        outw(n++,base_io + 0x3c);
2786                        ((unsigned long *)&setupdata[m][0])[k]=inl(base_io + 0x38);
2787                    }
2788                    for (k=0; k < 4; k++) {
2789                        outw(n++,base_io + 0x3c);
2790                        ((unsigned long *)&p->sp[m][0])[k]=inl(base_io + 0x38);
2791                    }
2792                    n += 8;
2793                }
2794                goto next_fblk_885;
2795flash_ok_885:
2796#ifdef ED_DBGP
2797                printk( "Flash Read OK\n");
2798#endif  
2799                c=inb(base_io + 0x29);
2800                outb((c & 0xfb),base_io + 0x29);
2801                for (c=0;c < 2;c++) {
2802                    p->ultra_map[c]=0;
2803                    p->async[c] = 0;
2804                    for (k=0; k < 16; k++) {
2805                        n=1;
2806                        n = n << k;
2807                        if (p->sp[c][k] > 1) {
2808                           p->ultra_map[c] |= n;
2809                        } else {
2810                           if (p->sp[c][k] == 0) {
2811                              p->async[c] |= n;
2812                           }
2813                        }
2814                    }
2815                    p->async[c] = ~(p->async[c]);
2816
2817                    if (p->global_map[c] == 0) {
2818                       k=setupdata[c][1];
2819                       if ((k & 0x40) != 0)
2820                          p->global_map[c] |= 0x20;
2821                       k &= 0x07;
2822                       p->global_map[c] |= k;
2823                       if ((setupdata[c][2] & 0x04) != 0)
2824                          p->global_map[c] |= 0x08;
2825                       p->host_id[c] = setupdata[c][0] & 0x07;
2826                    }
2827                }
2828
2829                k = inb(base_io + 0x28) & 0x8f;
2830                k |= 0x10;
2831                outb(k, base_io + 0x28);
2832                outb(0x80, base_io + 0x41);
2833                outb(0x80, base_io + 0x51);
2834                mdelay(100);
2835                outb(0, base_io + 0x41);
2836                outb(0, base_io + 0x51);
2837                mdelay(1000);
2838                inb(base_io + 0x9b);
2839                inb(base_io + 0x97);
2840                inb(base_io + 0xdb);
2841                inb(base_io + 0xd7);
2842                tmport = base_io + 0x80;
2843                k=p->host_id[0];
2844                if (k > 7)
2845                   k = (k & 0x07) | 0x40;
2846                k |= 0x08;
2847                outb(k, tmport);
2848                tmport += 0x18;
2849                outb(0, tmport);
2850                tmport += 0x07;
2851
2852                while ((inb(tmport) & 0x80) == 0)
2853                        cpu_relax();
2854        
2855                tmport -= 0x08;
2856                inb(tmport);
2857                tmport = base_io + 0x81;
2858                outb(8, tmport++);
2859                outb(0x7f, tmport);
2860                tmport = base_io + 0x91;
2861                outb(0x20, tmport);
2862
2863                tmport = base_io + 0xc0;
2864                k=p->host_id[1];
2865                if (k > 7)
2866                   k = (k & 0x07) | 0x40;
2867                k |= 0x08;
2868                outb(k, tmport);
2869                tmport += 0x18;
2870                outb(0, tmport);
2871                tmport += 0x07;
2872
2873                while ((inb(tmport) & 0x80) == 0)
2874                        cpu_relax();
2875
2876                tmport -= 0x08;
2877                inb(tmport);
2878                tmport = base_io + 0xc1;
2879                outb(8, tmport++);
2880                outb(0x7f, tmport);
2881                tmport = base_io + 0xd1;
2882                outb(0x20, tmport);
2883
2884                tscam_885();
2885                printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
2886                is885(p, base_io + 0x80, 0);
2887                printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
2888                is885(p, base_io + 0xc0, 1);
2889
2890                k = inb(base_io + 0x28) & 0xcf;
2891                k |= 0xc0;
2892                outb(k, base_io + 0x28);
2893                k = inb(base_io + 0x1f) | 0x80;
2894                outb(k, base_io + 0x1f);
2895                k = inb(base_io + 0x29) | 0x01;
2896                outb(k, base_io + 0x29);
2897#ifdef ED_DBGP
2898                //printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
2899#endif          
2900                shpnt->max_id = 16;
2901                shpnt->max_lun = (p->global_map[0] & 0x07) + 1;
2902                shpnt->max_channel = 1;
2903                shpnt->this_id = p->host_id[0];
2904                shpnt->unique_id = base_io;
2905                shpnt->io_port = base_io;
2906                shpnt->n_io_port = 0xff;        /* Number of bytes of I/O space used */
2907                shpnt->irq = pdev->irq;
2908                                
2909        } else {
2910                error = pci_read_config_byte(pdev, 0x49, &host_id);
2911
2912                printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
2913                        "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
2914
2915                atpdev->ioport[0] = base_io;
2916                atpdev->pciport[0] = base_io + 0x20;
2917                atpdev->dev_id = ent->device;
2918                host_id &= 0x07;
2919                atpdev->host_id[0] = host_id;
2920                tmport = base_io + 0x22;
2921                atpdev->scam_on = inb(tmport);
2922                tmport += 0x0b;
2923                atpdev->global_map[0] = inb(tmport++);
2924                atpdev->ultra_map[0] = inw(tmport);
2925
2926                if (atpdev->ultra_map[0] == 0) {
2927                        atpdev->scam_on = 0x00;
2928                        atpdev->global_map[0] = 0x20;
2929                        atpdev->ultra_map[0] = 0xffff;
2930                }
2931
2932                shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2933                if (!shpnt)
2934                        goto err_nomem;
2935
2936                p = (struct atp_unit *)&shpnt->hostdata;
2937                
2938                atpdev->host = shpnt;
2939                atpdev->pdev = pdev;
2940                pci_set_drvdata(pdev, p);
2941                memcpy(p, atpdev, sizeof(*atpdev));
2942                if (atp870u_init_tables(shpnt) < 0)
2943                        goto unregister;
2944
2945                if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870i", shpnt)) {
2946                        printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
2947                        goto free_tables;
2948                }
2949
2950                spin_lock_irqsave(shpnt->host_lock, flags);
2951                if (atpdev->chip_ver > 0x07) {  /* check if atp876 chip then enable terminator */
2952                        tmport = base_io + 0x3e;
2953                        outb(0x00, tmport);
2954                }
2955 
2956                tmport = base_io + 0x3a;
2957                k = (inb(tmport) & 0xf3) | 0x10;
2958                outb(k, tmport);
2959                outb((k & 0xdf), tmport);
2960                mdelay(32);
2961                outb(k, tmport);
2962                mdelay(32);
2963                tmport = base_io;
2964                outb((host_id | 0x08), tmport);
2965                tmport += 0x18;
2966                outb(0, tmport);
2967                tmport += 0x07;
2968                while ((inb(tmport) & 0x80) == 0)
2969                        mdelay(1);
2970
2971                tmport -= 0x08;
2972                inb(tmport);
2973                tmport = base_io + 1;
2974                outb(8, tmport++);
2975                outb(0x7f, tmport);
2976                tmport = base_io + 0x11;
2977                outb(0x20, tmport);
2978
2979                tscam(shpnt);
2980                is870(p, base_io);
2981                tmport = base_io + 0x3a;
2982                outb((inb(tmport) & 0xef), tmport);
2983                tmport++;
2984                outb((inb(tmport) | 0x20), tmport);
2985                if (atpdev->chip_ver == 4)
2986                        shpnt->max_id = 16;
2987                else            
2988                        shpnt->max_id = 8;
2989                shpnt->this_id = host_id;
2990                shpnt->unique_id = base_io;
2991                shpnt->io_port = base_io;
2992                shpnt->n_io_port = 0x40;        /* Number of bytes of I/O space used */
2993                shpnt->irq = pdev->irq;         
2994        } 
2995                spin_unlock_irqrestore(shpnt->host_lock, flags);
2996                if(ent->device==ATP885_DEVID) {
2997                        if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */
2998                                goto request_io_fail;
2999                } else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
3000                        if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */
3001                                goto request_io_fail;
3002                } else {
3003                        if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */
3004                                goto request_io_fail;
3005                }                               
3006                count++;
3007                if (scsi_add_host(shpnt, &pdev->dev))
3008                        goto scsi_add_fail;
3009                scsi_scan_host(shpnt);
3010#ifdef ED_DBGP                  
3011                printk("atp870u_prob : exit\n");
3012#endif          
3013                return 0;
3014
3015scsi_add_fail:
3016        printk("atp870u_prob:scsi_add_fail\n");
3017        if(ent->device==ATP885_DEVID) {
3018                release_region(base_io, 0xff);
3019        } else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
3020                release_region(base_io, 0x60);
3021        } else {
3022                release_region(base_io, 0x40);
3023        }
3024request_io_fail:
3025        printk("atp870u_prob:request_io_fail\n");
3026        free_irq(pdev->irq, shpnt);
3027free_tables:
3028        printk("atp870u_prob:free_table\n");
3029        atp870u_free_tables(shpnt);
3030unregister:
3031        printk("atp870u_prob:unregister\n");
3032        scsi_host_put(shpnt);
3033        return -1;              
3034err_eio:
3035        kfree(atpdev);
3036        return -EIO;
3037err_nomem:
3038        kfree(atpdev);
3039        return -ENOMEM;
3040}
3041
3042/* The abort command does not leave the device in a clean state where
3043   it is available to be used again.  Until this gets worked out, we will
3044   leave it commented out.  */
3045
3046static int atp870u_abort(struct scsi_cmnd * SCpnt)
3047{
3048        unsigned char  j, k, c;
3049        struct scsi_cmnd *workrequ;
3050        unsigned int tmport;
3051        struct atp_unit *dev;   
3052        struct Scsi_Host *host;
3053        host = SCpnt->device->host;
3054
3055        dev = (struct atp_unit *)&host->hostdata;
3056        c = scmd_channel(SCpnt);
3057        printk(" atp870u: abort Channel = %x \n", c);
3058        printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
3059        printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
3060        tmport = dev->ioport[c];
3061        for (j = 0; j < 0x18; j++) {
3062                printk(" r%2x=%2x", j, inb(tmport++));
3063        }
3064        tmport += 0x04;
3065        printk(" r1c=%2x", inb(tmport));
3066        tmport += 0x03;
3067        printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd[c]);
3068        tmport= dev->pciport[c];
3069        printk(" d00=%2x", inb(tmport));
3070        tmport += 0x02;
3071        printk(" d02=%2x", inb(tmport));
3072        for(j=0;j<16;j++) {
3073           if (dev->id[c][j].curr_req != NULL) {
3074                workrequ = dev->id[c][j].curr_req;
3075                printk("\n que cdb= ");
3076                for (k=0; k < workrequ->cmd_len; k++) {
3077                    printk(" %2x ",workrequ->cmnd[k]);
3078                }
3079                printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
3080           }
3081        }
3082        return SUCCESS;
3083}
3084
3085static const char *atp870u_info(struct Scsi_Host *notused)
3086{
3087        static char buffer[128];
3088
3089        strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
3090
3091        return buffer;
3092}
3093
3094#define BLS buffer + len + size
3095static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, 
3096                             char **start, off_t offset, int length, int inout)
3097{
3098        static u8 buff[512];
3099        int size = 0;
3100        int len = 0;
3101        off_t begin = 0;
3102        off_t pos = 0;
3103        
3104        if (inout)      
3105                return -EINVAL;
3106        if (offset == 0)
3107                memset(buff, 0, sizeof(buff));
3108        size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
3109        len += size;
3110        pos = begin + len;
3111        size = 0;
3112
3113        size += sprintf(BLS, "\n");
3114        size += sprintf(BLS, "Adapter Configuration:\n");
3115        size += sprintf(BLS, "               Base IO: %#.4lx\n", HBAptr->io_port);
3116        size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
3117        len += size;
3118        pos = begin + len;
3119        
3120        *start = buffer + (offset - begin);     /* Start of wanted data */
3121        len -= (offset - begin);        /* Start slop */
3122        if (len > length) {
3123                len = length;   /* Ending slop */
3124        }
3125        return (len);
3126}
3127
3128
3129static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
3130                        sector_t capacity, int *ip)
3131{
3132        int heads, sectors, cylinders;
3133
3134        heads = 64;
3135        sectors = 32;
3136        cylinders = (unsigned long)capacity / (heads * sectors);
3137        if (cylinders > 1024) {
3138                heads = 255;
3139                sectors = 63;
3140                cylinders = (unsigned long)capacity / (heads * sectors);
3141        }
3142        ip[0] = heads;
3143        ip[1] = sectors;
3144        ip[2] = cylinders;
3145
3146        return 0;
3147}
3148
3149static void atp870u_remove (struct pci_dev *pdev)
3150{       
3151        struct atp_unit *devext = pci_get_drvdata(pdev);
3152        struct Scsi_Host *pshost = devext->host;
3153        
3154        
3155        scsi_remove_host(pshost);
3156        printk(KERN_INFO "free_irq : %d\n",pshost->irq);
3157        free_irq(pshost->irq, pshost);
3158        release_region(pshost->io_port, pshost->n_io_port);
3159        printk(KERN_INFO "atp870u_free_tables : %p\n",pshost);
3160        atp870u_free_tables(pshost);
3161        printk(KERN_INFO "scsi_host_put : %p\n",pshost);
3162        scsi_host_put(pshost);
3163        printk(KERN_INFO "pci_set_drvdata : %p\n",pdev);
3164        pci_set_drvdata(pdev, NULL);    
3165}
3166MODULE_LICENSE("GPL");
3167
3168static struct scsi_host_template atp870u_template = {
3169     .module                    = THIS_MODULE,
3170     .name                      = "atp870u"             /* name */,
3171     .proc_name                 = "atp870u",
3172     .proc_info                 = atp870u_proc_info,
3173     .info                      = atp870u_info          /* info */,
3174     .queuecommand              = atp870u_queuecommand  /* queuecommand */,
3175     .eh_abort_handler          = atp870u_abort         /* abort */,
3176     .bios_param                = atp870u_biosparam     /* biosparm */,
3177     .can_queue                 = qcnt                  /* can_queue */,
3178     .this_id                   = 7                     /* SCSI ID */,
3179     .sg_tablesize              = ATP870U_SCATTER       /*SG_ALL*/ /*SG_NONE*/,
3180     .cmd_per_lun               = ATP870U_CMDLUN                /* commands per lun */,
3181     .use_clustering            = ENABLE_CLUSTERING,
3182     .max_sectors               = ATP870U_MAX_SECTORS,
3183};
3184
3185static struct pci_device_id atp870u_id_table[] = {
3186        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)                   },
3187        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)                          },
3188        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)                          },
3189        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
3190        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
3191        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
3192        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S)   },
3193        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D)   },
3194        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
3195        { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060)       },
3196        { 0, },
3197};
3198
3199MODULE_DEVICE_TABLE(pci, atp870u_id_table);
3200
3201static struct pci_driver atp870u_driver = {
3202        .id_table       = atp870u_id_table,
3203        .name           = "atp870u",
3204        .probe          = atp870u_probe,
3205        .remove         = __devexit_p(atp870u_remove),
3206};
3207
3208static int __init atp870u_init(void)
3209{
3210#ifdef ED_DBGP  
3211        printk("atp870u_init: Entry\n");
3212#endif  
3213        return pci_register_driver(&atp870u_driver);
3214}
3215
3216static void __exit atp870u_exit(void)
3217{
3218#ifdef ED_DBGP  
3219        printk("atp870u_exit: Entry\n");
3220#endif
3221        pci_unregister_driver(&atp870u_driver);
3222}
3223
3224static void tscam_885(void)
3225{
3226        unsigned char i;
3227
3228        for (i = 0; i < 0x2; i++) {
3229                mdelay(300);
3230        }
3231        return;
3232}
3233
3234
3235
3236static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
3237{
3238        unsigned int tmport;
3239        unsigned char i, j, k, rmb, n, lvdmode;
3240        unsigned short int m;
3241        static unsigned char mbuf[512];
3242        static unsigned char satn[9] =  {0, 0, 0, 0, 0, 0, 0, 6, 6};
3243        static unsigned char inqd[9] =  {0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
3244        static unsigned char synn[6] =  {0x80, 1, 3, 1, 0x19, 0x0e};
3245        unsigned char synu[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
3246        static unsigned char synw[6] =  {0x80, 1, 3, 1, 0x19, 0x0e};
3247        unsigned char synuw[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
3248        static unsigned char wide[6] =  {0x80, 1, 2, 3, 1, 0};
3249        static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
3250
3251        lvdmode=inb(wkport + 0x1b) >> 7;
3252
3253        for (i = 0; i < 16; i++) {
3254                m = 1;
3255                m = m << i;
3256                if ((m & dev->active_id[c]) != 0) {
3257                        continue;
3258                }
3259                if (i == dev->host_id[c]) {
3260                        printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
3261                        continue;
3262                }
3263                tmport = wkport + 0x1b;
3264                outb(0x01, tmport);
3265                tmport = wkport + 0x01;
3266                outb(0x08, tmport++);
3267                outb(0x7f, tmport++);
3268                outb(satn[0], tmport++);
3269                outb(satn[1], tmport++);
3270                outb(satn[2], tmport++);
3271                outb(satn[3], tmport++);
3272                outb(satn[4], tmport++);
3273                outb(satn[5], tmport++);
3274                tmport += 0x06;
3275                outb(0, tmport);
3276                tmport += 0x02;
3277                outb(dev->id[c][i].devsp, tmport++);
3278                
3279                outb(0, tmport++);
3280                outb(satn[6], tmport++);
3281                outb(satn[7], tmport++);
3282                j = i;
3283                if ((j & 0x08) != 0) {
3284                        j = (j & 0x07) | 0x40;
3285                }
3286                outb(j, tmport);
3287                tmport += 0x03;
3288                outb(satn[8], tmport);
3289                tmport += 0x07;
3290
3291                while ((inb(tmport) & 0x80) == 0x00)
3292                        cpu_relax();
3293                tmport -= 0x08;
3294                if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3295                        continue;
3296                }
3297                while (inb(tmport) != 0x8e)
3298                        cpu_relax();
3299                dev->active_id[c] |= m;
3300
3301                tmport = wkport + 0x10;
3302                outb(0x30, tmport);
3303                tmport = wkport + 0x14;
3304                outb(0x00, tmport);
3305
3306phase_cmd:
3307                tmport = wkport + 0x18;
3308                outb(0x08, tmport);
3309                tmport += 0x07;
3310                while ((inb(tmport) & 0x80) == 0x00)
3311                        cpu_relax();
3312                tmport -= 0x08;
3313                j = inb(tmport);
3314                if (j != 0x16) {
3315                        tmport = wkport + 0x10;
3316                        outb(0x41, tmport);
3317                        goto phase_cmd;
3318                }
3319sel_ok:
3320                tmport = wkport + 0x03;
3321                outb(inqd[0], tmport++);
3322                outb(inqd[1], tmport++);
3323                outb(inqd[2], tmport++);
3324                outb(inqd[3], tmport++);
3325                outb(inqd[4], tmport++);
3326                outb(inqd[5], tmport);
3327                tmport += 0x07;
3328                outb(0, tmport);
3329                tmport += 0x02;
3330                outb(dev->id[c][i].devsp, tmport++);
3331                outb(0, tmport++);
3332                outb(inqd[6], tmport++);
3333                outb(inqd[7], tmport++);
3334                tmport += 0x03;
3335                outb(inqd[8], tmport);
3336                tmport += 0x07;
3337                while ((inb(tmport) & 0x80) == 0x00)
3338                        cpu_relax();
3339                tmport -= 0x08;
3340                if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3341                        continue;
3342                }
3343                while (inb(tmport) != 0x8e)
3344                        cpu_relax();
3345                tmport = wkport + 0x1b;
3346                outb(0x00, tmport);
3347                tmport = wkport + 0x18;
3348                outb(0x08, tmport);
3349                tmport += 0x07;
3350                j = 0;
3351rd_inq_data:
3352                k = inb(tmport);
3353                if ((k & 0x01) != 0) {
3354                        tmport -= 0x06;
3355                        mbuf[j++] = inb(tmport);
3356                        tmport += 0x06;
3357                        goto rd_inq_data;
3358                }
3359                if ((k & 0x80) == 0) {
3360                        goto rd_inq_data;
3361                }
3362                tmport -= 0x08;
3363                j = inb(tmport);
3364                if (j == 0x16) {
3365                        goto inq_ok;
3366                }
3367                tmport = wkport + 0x10;
3368                outb(0x46, tmport);
3369                tmport += 0x02;
3370                outb(0, tmport++);
3371                outb(0, tmport++);
3372                outb(0, tmport++);
3373                tmport += 0x03;
3374                outb(0x08, tmport);
3375                tmport += 0x07;
3376                while ((inb(tmport) & 0x80) == 0x00)
3377                        cpu_relax();
3378                tmport -= 0x08;
3379                if (inb(tmport) != 0x16) {
3380                        goto sel_ok;
3381                }
3382inq_ok:
3383                mbuf[36] = 0;
3384                printk( KERN_INFO"         ID: %2d  %s\n", i, &mbuf[8]);
3385                dev->id[c][i].devtype = mbuf[0];
3386                rmb = mbuf[1];
3387                n = mbuf[7];
3388                if ((mbuf[7] & 0x60) == 0) {
3389                        goto not_wide;
3390                }
3391                if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) {
3392                        goto not_wide;
3393                }
3394                if (lvdmode == 0) {
3395                   goto chg_wide;
3396                }
3397                if (dev->sp[c][i] != 0x04) {    // force u2
3398                   goto chg_wide;
3399                }
3400
3401                tmport = wkport + 0x1b;
3402                outb(0x01, tmport);
3403                tmport = wkport + 0x03;
3404                outb(satn[0], tmport++);
3405                outb(satn[1], tmport++);
3406                outb(satn[2], tmport++);
3407                outb(satn[3], tmport++);
3408                outb(satn[4], tmport++);
3409                outb(satn[5], tmport++);
3410                tmport += 0x06;
3411                outb(0, tmport);
3412                tmport += 0x02;
3413                outb(dev->id[c][i].devsp, tmport++);
3414                outb(0, tmport++);
3415                outb(satn[6], tmport++);
3416                outb(satn[7], tmport++);
3417                tmport += 0x03;
3418                outb(satn[8], tmport);
3419                tmport += 0x07;
3420
3421                while ((inb(tmport) & 0x80) == 0x00)
3422                        cpu_relax();
3423                tmport -= 0x08;
3424                if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3425                        continue;
3426                }
3427                while (inb(tmport) != 0x8e)
3428                        cpu_relax();
3429try_u3:
3430                j = 0;
3431                tmport = wkport + 0x14;
3432                outb(0x09, tmport);
3433                tmport += 0x04;
3434                outb(0x20, tmport);
3435                tmport += 0x07;
3436
3437                while ((inb(tmport) & 0x80) == 0) {
3438                        if ((inb(tmport) & 0x01) != 0) {
3439                                tmport -= 0x06;
3440                                outb(u3[j++], tmport);
3441                                tmport += 0x06;
3442                        }
3443                        cpu_relax();
3444                }
3445                tmport -= 0x08;
3446                while ((inb(tmport) & 0x80) == 0x00)
3447                        cpu_relax();
3448                j = inb(tmport) & 0x0f;
3449                if (j == 0x0f) {
3450                        goto u3p_in;
3451                }
3452                if (j == 0x0a) {
3453                        goto u3p_cmd;
3454                }
3455                if (j == 0x0e) {
3456                        goto try_u3;
3457                }
3458                continue;
3459u3p_out:
3460                tmport = wkport + 0x18;
3461                outb(0x20, tmport);
3462                tmport += 0x07;
3463                while ((inb(tmport) & 0x80) == 0) {
3464                        if ((inb(tmport) & 0x01) != 0) {
3465                                tmport -= 0x06;
3466                                outb(0, tmport);
3467                                tmport += 0x06;
3468                        }
3469                        cpu_relax();
3470                }
3471                tmport -= 0x08;
3472                j = inb(tmport) & 0x0f;
3473                if (j == 0x0f) {
3474                        goto u3p_in;
3475                }
3476                if (j == 0x0a) {
3477                        goto u3p_cmd;
3478                }
3479                if (j == 0x0e) {
3480                        goto u3p_out;
3481                }
3482                continue;
3483u3p_in:
3484                tmport = wkport + 0x14;
3485                outb(0x09, tmport);
3486                tmport += 0x04;
3487                outb(0x20, tmport);
3488                tmport += 0x07;
3489                k = 0;
3490u3p_in1:
3491                j = inb(tmport);
3492                if ((j & 0x01) != 0) {
3493                        tmport -= 0x06;
3494                        mbuf[k++] = inb(tmport);
3495                        tmport += 0x06;
3496                        goto u3p_in1;
3497                }
3498                if ((j & 0x80) == 0x00) {
3499                        goto u3p_in1;
3500                }
3501                tmport -= 0x08;
3502                j = inb(tmport) & 0x0f;
3503                if (j == 0x0f) {
3504                        goto u3p_in;
3505                }
3506                if (j == 0x0a) {
3507                        goto u3p_cmd;
3508                }
3509                if (j == 0x0e) {
3510                        goto u3p_out;
3511                }
3512                continue;
3513u3p_cmd:
3514                tmport = wkport + 0x10;
3515                outb(0x30, tmport);
3516                tmport = wkport + 0x14;
3517                outb(0x00, tmport);
3518                tmport += 0x04;
3519                outb(0x08, tmport);
3520                tmport += 0x07;
3521                while ((inb(tmport) & 0x80) == 0x00);
3522                tmport -= 0x08;
3523                j = inb(tmport);
3524                if (j != 0x16) {
3525                        if (j == 0x4e) {
3526                                goto u3p_out;
3527                        }
3528                        continue;
3529                }
3530                if (mbuf[0] != 0x01) {
3531                        goto chg_wide;
3532                }
3533                if (mbuf[1] != 0x06) {
3534                        goto chg_wide;
3535                }
3536                if (mbuf[2] != 0x04) {
3537                        goto chg_wide;
3538                }
3539                if (mbuf[3] == 0x09) {
3540                        m = 1;
3541                        m = m << i;
3542                        dev->wide_id[c] |= m;
3543                        dev->id[c][i].devsp = 0xce;
3544#ifdef ED_DBGP             
3545                        printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
3546#endif
3547                        continue;
3548                }
3549chg_wide:
3550                tmport = wkport + 0x1b;
3551                outb(0x01, tmport);
3552                tmport = wkport + 0x03;
3553                outb(satn[0], tmport++);
3554                outb(satn[1], tmport++);
3555                outb(satn[2], tmport++);
3556                outb(satn[3], tmport++);
3557                outb(satn[4], tmport++);
3558                outb(satn[5], tmport++);
3559                tmport += 0x06;
3560                outb(0, tmport);
3561                tmport += 0x02;
3562                outb(dev->id[c][i].devsp, tmport++);
3563                outb(0, tmport++);
3564                outb(satn[6], tmport++);
3565                outb(satn[7], tmport++);
3566                tmport += 0x03;
3567                outb(satn[8], tmport);
3568                tmport += 0x07;
3569
3570                while ((inb(tmport) & 0x80) == 0x00)
3571                        cpu_relax();
3572                tmport -= 0x08;
3573                if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3574                        continue;
3575                }
3576                while (inb(tmport) != 0x8e)
3577                        cpu_relax();
3578try_wide:
3579                j = 0;
3580                tmport = wkport + 0x14;
3581                outb(0x05, tmport);
3582                tmport += 0x04;
3583                outb(0x20, tmport);
3584                tmport += 0x07;
3585
3586                while ((inb(tmport) & 0x80) == 0) {
3587                        if ((inb(tmport) & 0x01) != 0) {
3588                                tmport -= 0x06;
3589                                outb(wide[j++], tmport);
3590                                tmport += 0x06;
3591                        }
3592                        cpu_relax();
3593                }
3594                tmport -= 0x08;
3595                while ((inb(tmport) & 0x80) == 0x00)
3596                        cpu_relax();
3597                j = inb(tmport) & 0x0f;
3598                if (j == 0x0f) {
3599                        goto widep_in;
3600                }
3601                if (j == 0x0a) {
3602                        goto widep_cmd;
3603                }
3604                if (j == 0x0e) {
3605                        goto try_wide;
3606                }
3607                continue;
3608widep_out:
3609                tmport = wkport + 0x18;
3610                outb(0x20, tmport);
3611                tmport += 0x07;
3612                while ((inb(tmport) & 0x80) == 0) {
3613                        if ((inb(tmport) & 0x01) != 0) {
3614                                tmport -= 0x06;
3615                                outb(0, tmport);
3616                                tmport += 0x06;
3617                        }
3618                        cpu_relax();
3619                }
3620                tmport -= 0x08;
3621                j = inb(tmport) & 0x0f;
3622                if (j == 0x0f) {
3623                        goto widep_in;
3624                }
3625                if (j == 0x0a) {
3626                        goto widep_cmd;
3627                }
3628                if (j == 0x0e) {
3629                        goto widep_out;
3630                }
3631                continue;
3632widep_in:
3633                tmport = wkport + 0x14;
3634                outb(0xff, tmport);
3635                tmport += 0x04;
3636                outb(0x20, tmport);
3637                tmport += 0x07;
3638                k = 0;
3639widep_in1:
3640                j = inb(tmport);
3641                if ((j & 0x01) != 0) {
3642                        tmport -= 0x06;
3643                        mbuf[k++] = inb(tmport);
3644                        tmport += 0x06;
3645                        goto widep_in1;
3646                }
3647                if ((j & 0x80) == 0x00) {
3648                        goto widep_in1;
3649                }
3650                tmport -= 0x08;
3651                j = inb(tmport) & 0x0f;
3652                if (j == 0x0f) {
3653                        goto widep_in;
3654                }
3655                if (j == 0x0a) {
3656                        goto widep_cmd;
3657                }
3658                if (j == 0x0e) {
3659                        goto widep_out;
3660                }
3661                continue;
3662widep_cmd:
3663                tmport = wkport + 0x10;
3664                outb(0x30, tmport);
3665                tmport = wkport + 0x14;
3666                outb(0x00, tmport);
3667                tmport += 0x04;
3668                outb(0x08, tmport);
3669                tmport += 0x07;
3670                while ((inb(tmport) & 0x80) == 0x00)
3671                        cpu_relax();
3672                tmport -= 0x08;
3673                j = inb(tmport);
3674                if (j != 0x16) {
3675                        if (j == 0x4e) {
3676                                goto widep_out;
3677                        }
3678                        continue;
3679                }
3680                if (mbuf[0] != 0x01) {
3681                        goto not_wide;
3682                }
3683                if (mbuf[1] != 0x02) {
3684                        goto not_wide;
3685                }
3686                if (mbuf[2] != 0x03) {
3687                        goto not_wide;
3688                }
3689                if (mbuf[3] != 0x01) {
3690                        goto not_wide;
3691                }
3692                m = 1;
3693                m = m << i;
3694                dev->wide_id[c] |= m;
3695not_wide:
3696                if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) ||
3697                    ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
3698                        m = 1;
3699                        m = m << i;
3700                        if ((dev->async[c] & m) != 0) {
3701                           goto set_sync;
3702                        }
3703                }
3704                continue;
3705set_sync:
3706                if (dev->sp[c][i] == 0x02) {
3707                   synu[4]=0x0c;
3708                   synuw[4]=0x0c;
3709                } else {
3710                   if (dev->sp[c][i] >= 0x03) {
3711                      synu[4]=0x0a;
3712                      synuw[4]=0x0a;
3713                   }
3714                }
3715                tmport = wkport + 0x1b;
3716                j = 0;
3717                if ((m & dev->wide_id[c]) != 0) {
3718                        j |= 0x01;
3719                }
3720                outb(j, tmport);
3721                tmport = wkport + 0x03;
3722                outb(satn[0], tmport++);
3723                outb(satn[1], tmport++);
3724                outb(satn[2], tmport++);
3725                outb(satn[3], tmport++);
3726                outb(satn[4], tmport++);
3727                outb(satn[5], tmport++);
3728                tmport += 0x06;
3729                outb(0, tmport);
3730                tmport += 0x02;
3731                outb(dev->id[c][i].devsp, tmport++);
3732                outb(0, tmport++);
3733                outb(satn[6], tmport++);
3734                outb(satn[7], tmport++);
3735                tmport += 0x03;
3736                outb(satn[8], tmport);
3737                tmport += 0x07;
3738
3739                while ((inb(tmport) & 0x80) == 0x00)
3740                        cpu_relax();
3741                tmport -= 0x08;
3742                if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3743                        continue;
3744                }
3745                while (inb(tmport) != 0x8e)
3746                        cpu_relax();
3747try_sync:
3748                j = 0;
3749                tmport = wkport + 0x14;
3750                outb(0x06, tmport);
3751                tmport += 0x04;
3752                outb(0x20, tmport);
3753                tmport += 0x07;
3754
3755                while ((inb(tmport) & 0x80) == 0) {
3756                        if ((inb(tmport) & 0x01) != 0) {
3757                                tmport -= 0x06;
3758                                if ((m & dev->wide_id[c]) != 0) {
3759                                        if ((m & dev->ultra_map[c]) != 0) {
3760                                                outb(synuw[j++], tmport);
3761                                        } else {
3762                                                outb(synw[j++], tmport);
3763                                        }
3764                                } else {
3765                                        if ((m & dev->ultra_map[c]) != 0) {
3766                                                outb(synu[j++], tmport);
3767                                        } else {
3768                                                outb(synn[j++], tmport);
3769                                        }
3770                                }
3771                                tmport += 0x06;
3772                        }
3773                }
3774                tmport -= 0x08;
3775                while ((inb(tmport) & 0x80) == 0x00)
3776                        cpu_relax();
3777                j = inb(tmport) & 0x0f;
3778                if (j == 0x0f) {
3779                        goto phase_ins;
3780                }
3781                if (j == 0x0a) {
3782                        goto phase_cmds;
3783                }
3784                if (j == 0x0e) {
3785                        goto try_sync;
3786                }
3787                continue;
3788phase_outs:
3789                tmport = wkport + 0x18;
3790                outb(0x20, tmport);
3791                tmport += 0x07;
3792                while ((inb(tmport) & 0x80) == 0x00) {
3793                        if ((inb(tmport) & 0x01) != 0x00) {
3794                                tmport -= 0x06;
3795                                outb(0x00, tmport);
3796                                tmport += 0x06;
3797                        }
3798                        cpu_relax();
3799                }
3800                tmport -= 0x08;
3801                j = inb(tmport);
3802                if (j == 0x85) {
3803                        goto tar_dcons;
3804                }
3805                j &= 0x0f;
3806                if (j == 0x0f) {
3807                        goto phase_ins;
3808                }
3809                if (j == 0x0a) {
3810                        goto phase_cmds;
3811                }
3812                if (j == 0x0e) {
3813                        goto phase_outs;
3814                }
3815                continue;
3816phase_ins:
3817                tmport = wkport + 0x14;
3818                outb(0x06, tmport);
3819                tmport += 0x04;
3820                outb(0x20, tmport);
3821                tmport += 0x07;
3822                k = 0;
3823phase_ins1:
3824                j = inb(tmport);
3825                if ((j & 0x01) != 0x00) {
3826                        tmport -= 0x06;
3827                        mbuf[k++] = inb(tmport);
3828                        tmport += 0x06;
3829                        goto phase_ins1;
3830                }
3831                if ((j & 0x80) == 0x00) {
3832                        goto phase_ins1;
3833                }
3834                tmport -= 0x08;
3835                while ((inb(tmport) & 0x80) == 0x00);
3836                j = inb(tmport);
3837                if (j == 0x85) {
3838                        goto tar_dcons;
3839                }
3840                j &= 0x0f;
3841                if (j == 0x0f) {
3842                        goto phase_ins;
3843                }
3844                if (j == 0x0a) {
3845                        goto phase_cmds;
3846                }
3847                if (j == 0x0e) {
3848                        goto phase_outs;
3849                }
3850                continue;
3851phase_cmds:
3852                tmport = wkport + 0x10;
3853                outb(0x30, tmport);
3854tar_dcons:
3855                tmport = wkport + 0x14;
3856                outb(0x00, tmport);
3857                tmport += 0x04;
3858                outb(0x08, tmport);
3859                tmport += 0x07;
3860                while ((inb(tmport) & 0x80) == 0x00)
3861                        cpu_relax();
3862                tmport -= 0x08;
3863                j = inb(tmport);
3864                if (j != 0x16) {
3865                        continue;
3866                }
3867                if (mbuf[0] != 0x01) {
3868                        continue;
3869                }
3870                if (mbuf[1] != 0x03) {
3871                        continue;
3872                }
3873                if (mbuf[4] == 0x00) {
3874                        continue;
3875                }
3876                if (mbuf[3] > 0x64) {
3877                        continue;
3878                }
3879                if (mbuf[4] > 0x0e) {
3880                        mbuf[4] = 0x0e;
3881                }
3882                dev->id[c][i].devsp = mbuf[4];
3883                if (mbuf[3] < 0x0c){
3884                        j = 0xb0;
3885                        goto set_syn_ok;
3886                }
3887                if ((mbuf[3] < 0x0d) && (rmb == 0)) {
3888                        j = 0xa0;
3889                        goto set_syn_ok;
3890                }
3891                if (mbuf[3] < 0x1a) {
3892                        j = 0x20;
3893                        goto set_syn_ok;
3894                }
3895                if (mbuf[3] < 0x33) {
3896                        j = 0x40;
3897                        goto set_syn_ok;
3898                }
3899                if (mbuf[3] < 0x4c) {
3900                        j = 0x50;
3901                        goto set_syn_ok;
3902                }
3903                j = 0x60;
3904              set_syn_ok:
3905                dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
3906#ifdef ED_DBGP          
3907                printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
3908#endif
3909        }
3910        tmport = wkport + 0x16;
3911        outb(0x80, tmport);
3912}
3913
3914module_init(atp870u_init);
3915module_exit(atp870u_exit);
3916
3917