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