vserver 1.9.5.x5
[linux-2.6.git] / drivers / scsi / atp870u.c
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 <alan@redhat.com>
5  *  2.6.x update (C) 2004  Red Hat <alan@redhat.com>
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
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/interrupt.h>
21 #include <linux/kernel.h>
22 #include <linux/types.h>
23 #include <linux/string.h>
24 #include <linux/ioport.h>
25 #include <linux/delay.h>
26 #include <linux/proc_fs.h>
27 #include <linux/spinlock.h>
28 #include <linux/pci.h>
29 #include <linux/blkdev.h>
30 #include <asm/system.h>
31 #include <asm/io.h>
32
33 #include <scsi/scsi.h>
34 #include <scsi/scsi_cmnd.h>
35 #include <scsi/scsi_device.h>
36 #include <scsi/scsi_host.h>
37
38 #include "atp870u.h"
39
40 static struct scsi_host_template atp870u_template;
41 static void send_s870(struct Scsi_Host *host);
42
43
44 static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
45                                         struct pt_regs *regs)
46 {
47         unsigned long flags;
48         unsigned short int tmpcip, id;
49         unsigned char i, j, target_id, lun;
50         unsigned char *prd;
51         struct scsi_cmnd *workrequ;
52         unsigned int workportu, tmport;
53         unsigned long adrcntu, k;
54         int errstus;
55         struct Scsi_Host *host = dev_id;
56         struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
57
58         dev->in_int = 1;
59         workportu = dev->ioport;
60         tmport = workportu;
61
62         if (dev->working != 0) {
63                 tmport += 0x1f;
64                 j = inb(tmport);
65                 if ((j & 0x80) == 0) {
66                         dev->in_int = 0;
67                         return IRQ_NONE;
68                 }
69
70                 tmpcip = dev->pciport;
71                 if ((inb(tmpcip) & 0x08) != 0) {
72                         tmpcip += 0x2;
73                         for (k = 0; k < 1000; k++) {
74                                 if ((inb(tmpcip) & 0x08) == 0) {
75                                         goto stop_dma;
76                                 }
77                                 if ((inb(tmpcip) & 0x01) == 0) {
78                                         goto stop_dma;
79                                 }
80                         }
81                 }
82 stop_dma:
83                 tmpcip = dev->pciport;
84                 outb(0x00, tmpcip);
85                 tmport -= 0x08;
86
87                 i = inb(tmport);
88
89                 tmport -= 0x02;
90                 target_id = inb(tmport);
91                 tmport += 0x02;
92
93                 /*
94                  *      Remap wide devices onto id numbers
95                  */
96
97                 if ((target_id & 0x40) != 0) {
98                         target_id = (target_id & 0x07) | 0x08;
99                 } else {
100                         target_id &= 0x07;
101                 }
102
103                 if ((j & 0x40) != 0) {
104                         if (dev->last_cmd == 0xff) {
105                                 dev->last_cmd = target_id;
106                         }
107                         dev->last_cmd |= 0x40;
108                 }
109
110                 if (i == 0x85) {
111                         if ((dev->last_cmd & 0xf0) != 0x40) {
112                                 dev->last_cmd = 0xff;
113                         }
114                         /*
115                          *      Flip wide
116                          */
117                         if (dev->wide_idu != 0) {
118                                 tmport = workportu + 0x1b;
119                                 outb(0x01, tmport);
120                                 while ((inb(tmport) & 0x01) != 0x01) {
121                                         outb(0x01, tmport);
122                                 }
123                         }
124                         /*
125                          *      Issue more commands
126                          */
127                         spin_lock_irqsave(dev->host->host_lock, flags);
128                         if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) && (dev->in_snd == 0)) {
129                                 send_s870(host);
130                         }
131                         spin_unlock_irqrestore(dev->host->host_lock, flags);
132                         /*
133                          *      Done
134                          */
135                         dev->in_int = 0;
136                         goto out;
137                 }
138
139                 if (i == 0x40) {
140                         dev->last_cmd |= 0x40;
141                         dev->in_int = 0;
142                         goto out;
143                 }
144
145                 if (i == 0x21) {
146                         if ((dev->last_cmd & 0xf0) != 0x40) {
147                                 dev->last_cmd = 0xff;
148                         }
149                         tmport -= 0x05;
150                         adrcntu = 0;
151                         ((unsigned char *) &adrcntu)[2] = inb(tmport++);
152                         ((unsigned char *) &adrcntu)[1] = inb(tmport++);
153                         ((unsigned char *) &adrcntu)[0] = inb(tmport);
154                         k = dev->id[target_id].last_lenu;
155                         k -= adrcntu;
156                         dev->id[target_id].tran_lenu = k;
157                         dev->id[target_id].last_lenu = adrcntu;
158                         tmport -= 0x04;
159                         outb(0x41, tmport);
160                         tmport += 0x08;
161                         outb(0x08, tmport);
162                         dev->in_int = 0;
163                         goto out;
164                 }
165                 if ((i == 0x80) || (i == 0x8f)) {
166                         lun = 0;
167                         tmport -= 0x07;
168                         j = inb(tmport);
169                         if (j == 0x44 || i == 0x80) {
170                                 tmport += 0x0d;
171                                 lun = inb(tmport) & 0x07;
172                         } else {
173                                 if ((dev->last_cmd & 0xf0) != 0x40) {
174                                         dev->last_cmd = 0xff;
175                                 }
176                                 if (j == 0x41) {
177                                         tmport += 0x02;
178                                         adrcntu = 0;
179                                         ((unsigned char *) &adrcntu)[2] = inb(tmport++);
180                                         ((unsigned char *) &adrcntu)[1] = inb(tmport++);
181                                         ((unsigned char *) &adrcntu)[0] = inb(tmport);
182                                         k = dev->id[target_id].last_lenu;
183                                         k -= adrcntu;
184                                         dev->id[target_id].tran_lenu = k;
185                                         dev->id[target_id].last_lenu = adrcntu;
186                                         tmport += 0x04;
187                                         outb(0x08, tmport);
188                                         dev->in_int = 0;
189                                         goto out;
190                                 } else {
191                                         outb(0x46, tmport);
192                                         dev->id[target_id].dirctu = 0x00;
193                                         tmport += 0x02;
194                                         outb(0x00, tmport++);
195                                         outb(0x00, tmport++);
196                                         outb(0x00, tmport++);
197                                         tmport += 0x03;
198                                         outb(0x08, tmport);
199                                         dev->in_int = 0;
200                                         goto out;
201                                 }
202                         }
203                         if (dev->last_cmd != 0xff) {
204                                 dev->last_cmd |= 0x40;
205                         }
206                         tmport = workportu + 0x10;
207                         outb(0x45, tmport);
208                         tmport += 0x06;
209                         target_id = inb(tmport);
210                         /*
211                          *      Remap wide identifiers
212                          */
213                         if ((target_id & 0x10) != 0) {
214                                 target_id = (target_id & 0x07) | 0x08;
215                         } else {
216                                 target_id &= 0x07;
217                         }
218                         workrequ = dev->id[target_id].curr_req;
219                         tmport = workportu + 0x0f;
220                         outb(lun, tmport);
221                         tmport += 0x02;
222                         outb(dev->id[target_id].devspu, tmport++);
223                         adrcntu = dev->id[target_id].tran_lenu;
224                         k = dev->id[target_id].last_lenu;
225                         outb(((unsigned char *) &k)[2], tmport++);
226                         outb(((unsigned char *) &k)[1], tmport++);
227                         outb(((unsigned char *) &k)[0], tmport++);
228                         /* Remap wide */
229                         j = target_id;
230                         if (target_id > 7) {
231                                 j = (j & 0x07) | 0x40;
232                         }
233                         /* Add direction */
234                         j |= dev->id[target_id].dirctu;
235                         outb(j, tmport++);
236                         outb(0x80, tmport);
237
238                         /* enable 32 bit fifo transfer */
239                         if (dev->deviceid != 0x8081) {
240                                 tmport = workportu + 0x3a;
241                                 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
242                                         outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
243                                 } else {
244                                         outb((unsigned char) (inb(tmport) & 0xf3), tmport);
245                                 }
246                         } else {
247                                 tmport = workportu - 0x05;
248                                 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
249                                         outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
250                                 } else {
251                                         outb((unsigned char) (inb(tmport) & 0x3f), tmport);
252                                 }
253                         }
254
255                         tmport = workportu + 0x1b;
256                         j = 0;
257                         id = 1;
258                         id = id << target_id;
259                         /*
260                          *      Is this a wide device
261                          */
262                         if ((id & dev->wide_idu) != 0) {
263                                 j |= 0x01;
264                         }
265                         outb(j, tmport);
266                         while ((inb(tmport) & 0x01) != j) {
267                                 outb(j, tmport);
268                         }
269
270                         if (dev->id[target_id].last_lenu == 0) {
271                                 tmport = workportu + 0x18;
272                                 outb(0x08, tmport);
273                                 dev->in_int = 0;
274                                 goto out;
275                         }
276                         prd = dev->id[target_id].prd_posu;
277                         while (adrcntu != 0) {
278                                 id = ((unsigned short int *) (prd))[2];
279                                 if (id == 0) {
280                                         k = 0x10000;
281                                 } else {
282                                         k = id;
283                                 }
284                                 if (k > adrcntu) {
285                                         ((unsigned short int *) (prd))[2] = (unsigned short int)
286                                             (k - adrcntu);
287                                         ((unsigned long *) (prd))[0] += adrcntu;
288                                         adrcntu = 0;
289                                         dev->id[target_id].prd_posu = prd;
290                                 } else {
291                                         adrcntu -= k;
292                                         dev->id[target_id].prdaddru += 0x08;
293                                         prd += 0x08;
294                                         if (adrcntu == 0) {
295                                                 dev->id[target_id].prd_posu = prd;
296                                         }
297                                 }
298                         }
299                         tmpcip = dev->pciport + 0x04;
300                         outl(dev->id[target_id].prdaddru, tmpcip);
301                         tmpcip -= 0x02;
302                         outb(0x06, tmpcip);
303                         outb(0x00, tmpcip);
304                         tmpcip -= 0x02;
305                         tmport = workportu + 0x18;
306                         /*
307                          *      Check transfer direction
308                          */
309                         if (dev->id[target_id].dirctu != 0) {
310                                 outb(0x08, tmport);
311                                 outb(0x01, tmpcip);
312                                 dev->in_int = 0;
313                                 goto out;
314                         }
315                         outb(0x08, tmport);
316                         outb(0x09, tmpcip);
317                         dev->in_int = 0;
318                         goto out;
319                 }
320
321                 /*
322                  *      Current scsi request on this target
323                  */
324
325                 workrequ = dev->id[target_id].curr_req;
326
327                 if (i == 0x42) {
328                         if ((dev->last_cmd & 0xf0) != 0x40) {
329                                 dev->last_cmd = 0xff;
330                         }
331                         errstus = 0x02;
332                         workrequ->result = errstus;
333                         goto go_42;
334                 }
335                 if (i == 0x16) {
336                         if ((dev->last_cmd & 0xf0) != 0x40) {
337                                 dev->last_cmd = 0xff;
338                         }
339                         errstus = 0;
340                         tmport -= 0x08;
341                         errstus = inb(tmport);
342                         workrequ->result = errstus;
343 go_42:
344                         /*
345                          *      Complete the command
346                          */
347                          
348                         if (workrequ->use_sg) {
349                                 pci_unmap_sg(dev->pdev,
350                                         (struct scatterlist *)workrequ->buffer,
351                                         workrequ->use_sg,
352                                         workrequ->sc_data_direction);
353                         } else if (workrequ->request_bufflen &&
354                                         workrequ->sc_data_direction != DMA_NONE) {
355                                 pci_unmap_single(dev->pdev,
356                                         workrequ->SCp.dma_handle,
357                                         workrequ->request_bufflen,
358                                         workrequ->sc_data_direction);
359                         }
360                         spin_lock_irqsave(dev->host->host_lock, flags);
361                         (*workrequ->scsi_done) (workrequ);
362
363                         /*
364                          *      Clear it off the queue
365                          */
366                         dev->id[target_id].curr_req = NULL;
367                         dev->working--;
368                         spin_unlock_irqrestore(dev->host->host_lock, flags);
369                         /*
370                          *      Take it back wide
371                          */
372                         if (dev->wide_idu != 0) {
373                                 tmport = workportu + 0x1b;
374                                 outb(0x01, tmport);
375                                 while ((inb(tmport) & 0x01) != 0x01) {
376                                         outb(0x01, tmport);
377                                 }
378                         }
379                         /*
380                          *      If there is stuff to send and nothing going then send it
381                          */
382                         spin_lock_irqsave(dev->host->host_lock, flags);
383                         if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) && (dev->in_snd == 0)) {
384                                 send_s870(host);
385                         }
386                         spin_unlock_irqrestore(dev->host->host_lock, flags);
387                         dev->in_int = 0;
388                         goto out;
389                 }
390                 if ((dev->last_cmd & 0xf0) != 0x40) {
391                         dev->last_cmd = 0xff;
392                 }
393                 if (i == 0x4f) {
394                         i = 0x89;
395                 }
396                 i &= 0x0f;
397                 if (i == 0x09) {
398                         tmpcip = tmpcip + 4;
399                         outl(dev->id[target_id].prdaddru, tmpcip);
400                         tmpcip = tmpcip - 2;
401                         outb(0x06, tmpcip);
402                         outb(0x00, tmpcip);
403                         tmpcip = tmpcip - 2;
404                         tmport = workportu + 0x10;
405                         outb(0x41, tmport);
406                         dev->id[target_id].dirctu = 0x00;
407                         tmport += 0x08;
408                         outb(0x08, tmport);
409                         outb(0x09, tmpcip);
410                         dev->in_int = 0;
411                         goto out;
412                 }
413                 if (i == 0x08) {
414                         tmpcip = tmpcip + 4;
415                         outl(dev->id[target_id].prdaddru, tmpcip);
416                         tmpcip = tmpcip - 2;
417                         outb(0x06, tmpcip);
418                         outb(0x00, tmpcip);
419                         tmpcip = tmpcip - 2;
420                         tmport = workportu + 0x10;
421                         outb(0x41, tmport);
422                         tmport += 0x05;
423                         outb((unsigned char) (inb(tmport) | 0x20), tmport);
424                         dev->id[target_id].dirctu = 0x20;
425                         tmport += 0x03;
426                         outb(0x08, tmport);
427                         outb(0x01, tmpcip);
428                         dev->in_int = 0;
429                         goto out;
430                 }
431                 tmport -= 0x07;
432                 if (i == 0x0a) {
433                         outb(0x30, tmport);
434                 } else {
435                         outb(0x46, tmport);
436                 }
437                 dev->id[target_id].dirctu = 0x00;
438                 tmport += 0x02;
439                 outb(0x00, tmport++);
440                 outb(0x00, tmport++);
441                 outb(0x00, tmport++);
442                 tmport += 0x03;
443                 outb(0x08, tmport);
444                 dev->in_int = 0;
445                 goto out;
446         } else {
447 //              tmport = workportu + 0x17;
448 //              inb(tmport);
449 //              dev->working = 0;
450                 dev->in_int = 0;
451         }
452 out:
453         return IRQ_HANDLED;
454 }
455
456 /**
457  *      atp870u_queuecommand    -       Queue SCSI command
458  *      @req_p: request block
459  *      @done: completion function
460  *
461  *      Queue a command to the ATP queue. Called with the host lock held.
462  */
463  
464 static int atp870u_queuecommand(struct scsi_cmnd *req_p,
465                 void (*done) (struct scsi_cmnd *))
466 {
467         unsigned short int m;
468         unsigned int tmport;
469         struct Scsi_Host *host;
470         struct atp_unit *dev;
471
472         if (req_p->device->channel != 0) {
473                 req_p->result = 0x00040000;
474                 done(req_p);
475                 return 0;
476         };
477
478         host = req_p->device->host;
479         dev = (struct atp_unit *)&host->hostdata;
480         
481         m = 1;
482         m = m << req_p->device->id;
483
484         /*
485          *      Fake a timeout for missing targets
486          */
487
488         if ((m & dev->active_idu) == 0) {
489                 req_p->result = 0x00040000;
490                 done(req_p);
491                 return 0;
492         }
493         if (done) {
494                 req_p->scsi_done = done;
495         } else {
496                 printk(KERN_WARNING "atp870u_queuecommand: done can't be NULL\n");
497                 req_p->result = 0;
498                 done(req_p);
499                 return 0;
500         }
501         /*
502          *      Count new command
503          */
504
505         dev->quendu++;
506         if (dev->quendu >= qcnt) {
507                 dev->quendu = 0;
508         }
509         /*
510          *      Check queue state
511          */
512         if (dev->quhdu == dev->quendu) {
513                 if (dev->quendu == 0) {
514                         dev->quendu = qcnt;
515                 }
516                 dev->quendu--;
517                 req_p->result = 0x00020000;
518                 done(req_p);
519                 return 0;
520         }
521         dev->querequ[dev->quendu] = req_p;
522         tmport = dev->ioport + 0x1c;
523         if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) {
524                 send_s870(host);
525         }
526         return 0;
527 }
528
529 /**
530  *      send_s870       -       send a command to the controller
531  *      @host: host
532  *
533  *      On entry there is work queued to be done. We move some of that work to the
534  *      controller itself. 
535  *
536  *      Caller holds the host lock.
537  */
538  
539 static void send_s870(struct Scsi_Host *host)
540 {
541         unsigned int tmport;
542         struct scsi_cmnd *workrequ;
543         unsigned int i;
544         unsigned char j, target_id;
545         unsigned char *prd;
546         unsigned short int tmpcip, w;
547         unsigned long l;
548         dma_addr_t bttl;
549         unsigned int workportu;
550         struct scatterlist *sgpnt;
551         struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
552         int sg_count;
553
554         if (dev->in_snd != 0) {
555                 return;
556         }
557         dev->in_snd = 1;
558         if ((dev->last_cmd != 0xff) && ((dev->last_cmd & 0x40) != 0)) {
559                 dev->last_cmd &= 0x0f;
560                 workrequ = dev->id[dev->last_cmd].curr_req;
561                 if (workrequ != NULL) { /* check NULL pointer */
562                         goto cmd_subp;
563                 }
564                 dev->last_cmd = 0xff;
565                 if (dev->quhdu == dev->quendu) {
566                         dev->in_snd = 0;
567                         return;
568                 }
569         }
570         if ((dev->last_cmd != 0xff) && (dev->working != 0)) {
571                 dev->in_snd = 0;
572                 return;
573         }
574         dev->working++;
575         j = dev->quhdu;
576         dev->quhdu++;
577         if (dev->quhdu >= qcnt) {
578                 dev->quhdu = 0;
579         }
580         workrequ = dev->querequ[dev->quhdu];
581         if (dev->id[workrequ->device->id].curr_req == 0) {
582                 dev->id[workrequ->device->id].curr_req = workrequ;
583                 dev->last_cmd = workrequ->device->id;
584                 goto cmd_subp;
585         }
586         dev->quhdu = j;
587         dev->working--;
588         dev->in_snd = 0;
589         return;
590 cmd_subp:
591         workportu = dev->ioport;
592         tmport = workportu + 0x1f;
593         if ((inb(tmport) & 0xb0) != 0) {
594                 goto abortsnd;
595         }
596         tmport = workportu + 0x1c;
597         if (inb(tmport) == 0) {
598                 goto oktosend;
599         }
600 abortsnd:
601         dev->last_cmd |= 0x40;
602         dev->in_snd = 0;
603         return;
604 oktosend:
605         memcpy(&dev->ata_cdbu[0], &workrequ->cmnd[0], workrequ->cmd_len);
606         if (dev->ata_cdbu[0] == READ_CAPACITY) {
607                 if (workrequ->request_bufflen > 8) {
608                         workrequ->request_bufflen = 0x08;
609                 }
610         }
611         if (dev->ata_cdbu[0] == 0x00) {
612                 workrequ->request_bufflen = 0;
613         }
614
615         tmport = workportu + 0x1b;
616         j = 0;
617         target_id = workrequ->device->id;
618
619         /*
620          *      Wide ?
621          */
622         w = 1;
623         w = w << target_id;
624         if ((w & dev->wide_idu) != 0) {
625                 j |= 0x01;
626         }
627         outb(j, tmport);
628         while ((inb(tmport) & 0x01) != j) {
629                 outb(j, tmport);
630         }
631
632         /*
633          *      Write the command
634          */
635
636         tmport = workportu;
637         outb(workrequ->cmd_len, tmport++);
638         outb(0x2c, tmport++);
639         outb(0xcf, tmport++);
640         for (i = 0; i < workrequ->cmd_len; i++) {
641                 outb(dev->ata_cdbu[i], tmport++);
642         }
643         tmport = workportu + 0x0f;
644         outb(workrequ->device->lun, tmport);
645         tmport += 0x02;
646         /*
647          *      Write the target
648          */
649         outb(dev->id[target_id].devspu, tmport++);
650
651         /*
652          *      Figure out the transfer size
653          */
654         if (workrequ->use_sg) {
655                 l = 0;
656                 sgpnt = (struct scatterlist *) workrequ->request_buffer;
657                 sg_count = pci_map_sg(dev->pdev, sgpnt, workrequ->use_sg,
658                                 workrequ->sc_data_direction);
659                 for (i = 0; i < workrequ->use_sg; i++) {
660                         if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER) {
661                                 panic("Foooooooood fight!");
662                         }
663                         l += sgpnt[i].length;
664                 }
665         } else if(workrequ->request_bufflen && workrequ->sc_data_direction != PCI_DMA_NONE) {
666                 workrequ->SCp.dma_handle = pci_map_single(dev->pdev,
667                                 workrequ->request_buffer,
668                                 workrequ->request_bufflen,
669                                 workrequ->sc_data_direction);
670                 l = workrequ->request_bufflen;
671         }
672         else l = 0;
673         /*
674          *      Write transfer size
675          */
676         outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
677         outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
678         outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
679         j = target_id;
680         dev->id[j].last_lenu = l;
681         dev->id[j].tran_lenu = 0;
682         /*
683          *      Flip the wide bits
684          */
685         if ((j & 0x08) != 0) {
686                 j = (j & 0x07) | 0x40;
687         }
688         /*
689          *      Check transfer direction
690          */
691         if (workrequ->sc_data_direction == DMA_TO_DEVICE) {
692                 outb((unsigned char) (j | 0x20), tmport++);
693         } else {
694                 outb(j, tmport++);
695         }
696         outb((unsigned char) (inb(tmport) | 0x80), tmport);
697         outb(0x80, tmport);
698         tmport = workportu + 0x1c;
699         dev->id[target_id].dirctu = 0;
700         if (l == 0) {
701                 if (inb(tmport) == 0) {
702                         tmport = workportu + 0x18;
703                         outb(0x08, tmport);
704                 } else {
705                         dev->last_cmd |= 0x40;
706                 }
707                 dev->in_snd = 0;
708                 return;
709         }
710         tmpcip = dev->pciport;
711         prd = dev->id[target_id].prd_tableu;
712         dev->id[target_id].prd_posu = prd;
713
714         /*
715          *      Now write the request list. Either as scatter/gather or as
716          *      a linear chain.
717          */
718
719         if (workrequ->use_sg) {
720                 sgpnt = (struct scatterlist *) workrequ->request_buffer;
721                 i = 0;
722                 for (j = 0; j < workrequ->use_sg; j++) {
723                         bttl = sg_dma_address(&sgpnt[j]);
724                         l = sg_dma_len(&sgpnt[j]);
725                         while (l > 0x10000) {
726                                 (((u16 *) (prd))[i + 3]) = 0x0000;
727                                 (((u16 *) (prd))[i + 2]) = 0x0000;
728                                 (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
729                                 l -= 0x10000;
730                                 bttl += 0x10000;
731                                 i += 0x04;
732                         }
733                         (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
734                         (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
735                         (((u16 *) (prd))[i + 3]) = 0;
736                         i += 0x04;
737                 }
738                 (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
739         } else {
740                 /*
741                  *      For a linear request write a chain of blocks
742                  */
743                 bttl = workrequ->SCp.dma_handle;
744                 l = workrequ->request_bufflen;
745                 i = 0;
746                 while (l > 0x10000) {
747                         (((u16 *) (prd))[i + 3]) = 0x0000;
748                         (((u16 *) (prd))[i + 2]) = 0x0000;
749                         (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
750                         l -= 0x10000;
751                         bttl += 0x10000;
752                         i += 0x04;
753                 }
754                 (((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000);
755                 (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
756                 (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
757         }
758         tmpcip = tmpcip + 4;
759         dev->id[target_id].prdaddru = dev->id[target_id].prd_phys;
760         outl(dev->id[target_id].prd_phys, tmpcip);
761         tmpcip = tmpcip - 2;
762         outb(0x06, tmpcip);
763         outb(0x00, tmpcip);
764         tmpcip = tmpcip - 2;
765
766         if (dev->deviceid != 0x8081) {
767                 tmport = workportu + 0x3a;
768                 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
769                         outb((inb(tmport) & 0xf3) | 0x08, tmport);
770                 } else {
771                         outb(inb(tmport) & 0xf3, tmport);
772                 }
773         } else {
774                 tmport = workportu - 0x05;
775                 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
776                         outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
777                 } else {
778                         outb((unsigned char) (inb(tmport) & 0x3f), tmport);
779                 }
780         }
781         tmport = workportu + 0x1c;
782
783         if (workrequ->sc_data_direction == DMA_TO_DEVICE) {
784                 dev->id[target_id].dirctu = 0x20;
785                 if (inb(tmport) == 0) {
786                         tmport = workportu + 0x18;
787                         outb(0x08, tmport);
788                         outb(0x01, tmpcip);
789                 } else {
790                         dev->last_cmd |= 0x40;
791                 }
792                 dev->in_snd = 0;
793                 return;
794         }
795         if (inb(tmport) == 0) {
796                 tmport = workportu + 0x18;
797                 outb(0x08, tmport);
798                 outb(0x09, tmpcip);
799         } else {
800                 dev->last_cmd |= 0x40;
801         }
802         dev->in_snd = 0;
803 }
804
805 static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
806 {
807         unsigned int tmport;
808         unsigned short int i, k;
809         unsigned char j;
810
811         tmport = dev->ioport + 0x1c;
812         outw(*val, tmport);
813 FUN_D7:
814         for (i = 0; i < 10; i++) {      /* stable >= bus settle delay(400 ns)  */
815                 k = inw(tmport);
816                 j = (unsigned char) (k >> 8);
817                 if ((k & 0x8000) != 0) {        /* DB7 all release?    */
818                         goto FUN_D7;
819                 }
820         }
821         *val |= 0x4000;         /* assert DB6           */
822         outw(*val, tmport);
823         *val &= 0xdfff;         /* assert DB5           */
824         outw(*val, tmport);
825 FUN_D5:
826         for (i = 0; i < 10; i++) {      /* stable >= bus settle delay(400 ns) */
827                 if ((inw(tmport) & 0x2000) != 0) {      /* DB5 all release?       */
828                         goto FUN_D5;
829                 }
830         }
831         *val |= 0x8000;         /* no DB4-0, assert DB7    */
832         *val &= 0xe0ff;
833         outw(*val, tmport);
834         *val &= 0xbfff;         /* release DB6             */
835         outw(*val, tmport);
836 FUN_D6:
837         for (i = 0; i < 10; i++) {      /* stable >= bus settle delay(400 ns)  */
838                 if ((inw(tmport) & 0x4000) != 0) {      /* DB6 all release?  */
839                         goto FUN_D6;
840                 }
841         }
842
843         return j;
844 }
845
846 static void tscam(struct Scsi_Host *host)
847 {
848
849         unsigned int tmport;
850         unsigned char i, j, k;
851         unsigned long n;
852         unsigned short int m, assignid_map, val;
853         unsigned char mbuf[33], quintet[2];
854         struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
855         static unsigned char g2q_tab[8] = {
856                 0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
857         };
858
859 /*  I can't believe we need this before we've even done anything.  Remove it
860  *  and see if anyone bitches.
861         for (i = 0; i < 0x10; i++) {
862                 udelay(0xffff);
863         }
864  */
865
866         tmport = dev->ioport + 1;
867         outb(0x08, tmport++);
868         outb(0x7f, tmport);
869         tmport = dev->ioport + 0x11;
870         outb(0x20, tmport);
871
872         if ((dev->scam_on & 0x40) == 0) {
873                 return;
874         }
875         m = 1;
876         m <<= dev->host_idu;
877         j = 16;
878         if (dev->chip_veru < 4) {
879                 m |= 0xff00;
880                 j = 8;
881         }
882         assignid_map = m;
883         tmport = dev->ioport + 0x02;
884         outb(0x02, tmport++);   /* 2*2=4ms,3EH 2/32*3E=3.9ms */
885         outb(0, tmport++);
886         outb(0, tmport++);
887         outb(0, tmport++);
888         outb(0, tmport++);
889         outb(0, tmport++);
890         outb(0, tmport++);
891
892         for (i = 0; i < j; i++) {
893                 m = 1;
894                 m = m << i;
895                 if ((m & assignid_map) != 0) {
896                         continue;
897                 }
898                 tmport = dev->ioport + 0x0f;
899                 outb(0, tmport++);
900                 tmport += 0x02;
901                 outb(0, tmport++);
902                 outb(0, tmport++);
903                 outb(0, tmport++);
904                 if (i > 7) {
905                         k = (i & 0x07) | 0x40;
906                 } else {
907                         k = i;
908                 }
909                 outb(k, tmport++);
910                 tmport = dev->ioport + 0x1b;
911                 if (dev->chip_veru == 4) {
912                         outb(0x01, tmport);
913                 } else {
914                         outb(0x00, tmport);
915                 }
916 wait_rdyok:
917                 tmport = dev->ioport + 0x18;
918                 outb(0x09, tmport);
919                 tmport += 0x07;
920
921                 while ((inb(tmport) & 0x80) == 0x00);
922                 tmport -= 0x08;
923                 k = inb(tmport);
924                 if (k != 0x16) {
925                         if ((k == 0x85) || (k == 0x42)) {
926                                 continue;
927                         }
928                         tmport = dev->ioport + 0x10;
929                         outb(0x41, tmport);
930                         goto wait_rdyok;
931                 }
932                 assignid_map |= m;
933
934         }
935         tmport = dev->ioport + 0x02;
936         outb(0x7f, tmport);
937         tmport = dev->ioport + 0x1b;
938         outb(0x02, tmport);
939
940         outb(0, 0x80);
941
942         val = 0x0080;           /* bsy  */
943         tmport = dev->ioport + 0x1c;
944         outw(val, tmport);
945         val |= 0x0040;          /* sel  */
946         outw(val, tmport);
947         val |= 0x0004;          /* msg  */
948         outw(val, tmport);
949         inb(0x80);              /* 2 deskew delay(45ns*2=90ns) */
950         val &= 0x007f;          /* no bsy  */
951         outw(val, tmport);
952         mdelay(128);
953         val &= 0x00fb;          /* after 1ms no msg */
954         outw(val, tmport);
955 wait_nomsg:
956         if ((inb(tmport) & 0x04) != 0) {
957                 goto wait_nomsg;
958         }
959         outb(1, 0x80);
960         udelay(100);
961         for (n = 0; n < 0x30000; n++) {
962                 if ((inb(tmport) & 0x80) != 0) {        /* bsy ? */
963                         goto wait_io;
964                 }
965         }
966         goto TCM_SYNC;
967 wait_io:
968         for (n = 0; n < 0x30000; n++) {
969                 if ((inb(tmport) & 0x81) == 0x0081) {
970                         goto wait_io1;
971                 }
972         }
973         goto TCM_SYNC;
974 wait_io1:
975         inb(0x80);
976         val |= 0x8003;          /* io,cd,db7  */
977         outw(val, tmport);
978         inb(0x80);
979         val &= 0x00bf;          /* no sel     */
980         outw(val, tmport);
981         outb(2, 0x80);
982 TCM_SYNC:
983         udelay(0x800);
984         if ((inb(tmport) & 0x80) == 0x00) {     /* bsy ? */
985                 outw(0, tmport--);
986                 outb(0, tmport);
987                 tmport = dev->ioport + 0x15;
988                 outb(0, tmport);
989                 tmport += 0x03;
990                 outb(0x09, tmport);
991                 tmport += 0x07;
992                 while ((inb(tmport) & 0x80) == 0);
993                 tmport -= 0x08;
994                 inb(tmport);
995                 return;
996         }
997         val &= 0x00ff;          /* synchronization  */
998         val |= 0x3f00;
999         fun_scam(dev, &val);
1000         outb(3, 0x80);
1001         val &= 0x00ff;          /* isolation        */
1002         val |= 0x2000;
1003         fun_scam(dev, &val);
1004         outb(4, 0x80);
1005         i = 8;
1006         j = 0;
1007 TCM_ID:
1008         if ((inw(tmport) & 0x2000) == 0) {
1009                 goto TCM_ID;
1010         }
1011         outb(5, 0x80);
1012         val &= 0x00ff;          /* get ID_STRING */
1013         val |= 0x2000;
1014         k = fun_scam(dev, &val);
1015         if ((k & 0x03) == 0) {
1016                 goto TCM_5;
1017         }
1018         mbuf[j] <<= 0x01;
1019         mbuf[j] &= 0xfe;
1020         if ((k & 0x02) != 0) {
1021                 mbuf[j] |= 0x01;
1022         }
1023         i--;
1024         if (i > 0) {
1025                 goto TCM_ID;
1026         }
1027         j++;
1028         i = 8;
1029         goto TCM_ID;
1030
1031 TCM_5:                  /* isolation complete..  */
1032 /*    mbuf[32]=0;
1033         printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
1034         i = 15;
1035         j = mbuf[0];
1036         if ((j & 0x20) != 0) {  /* bit5=1:ID upto 7      */
1037                 i = 7;
1038         }
1039         if ((j & 0x06) == 0) {  /* IDvalid?             */
1040                 goto G2Q5;
1041         }
1042         k = mbuf[1];
1043 small_id:
1044         m = 1;
1045         m <<= k;
1046         if ((m & assignid_map) == 0) {
1047                 goto G2Q_QUIN;
1048         }
1049         if (k > 0) {
1050                 k--;
1051                 goto small_id;
1052         }
1053 G2Q5:                   /* srch from max acceptable ID#  */
1054         k = i;                  /* max acceptable ID#            */
1055 G2Q_LP:
1056         m = 1;
1057         m <<= k;
1058         if ((m & assignid_map) == 0) {
1059                 goto G2Q_QUIN;
1060         }
1061         if (k > 0) {
1062                 k--;
1063                 goto G2Q_LP;
1064         }
1065 G2Q_QUIN:               /* k=binID#,       */
1066         assignid_map |= m;
1067         if (k < 8) {
1068                 quintet[0] = 0x38;      /* 1st dft ID<8    */
1069         } else {
1070                 quintet[0] = 0x31;      /* 1st  ID>=8      */
1071         }
1072         k &= 0x07;
1073         quintet[1] = g2q_tab[k];
1074
1075         val &= 0x00ff;          /* AssignID 1stQuintet,AH=001xxxxx  */
1076         m = quintet[0] << 8;
1077         val |= m;
1078         fun_scam(dev, &val);
1079         val &= 0x00ff;          /* AssignID 2ndQuintet,AH=001xxxxx */
1080         m = quintet[1] << 8;
1081         val |= m;
1082         fun_scam(dev, &val);
1083
1084         goto TCM_SYNC;
1085
1086 }
1087
1088 static void is870(struct Scsi_Host *host, unsigned int wkport)
1089 {
1090         unsigned int tmport;
1091         unsigned char i, j, k, rmb, n;
1092         unsigned short int m;
1093         static unsigned char mbuf[512];
1094         static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1095         static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1096         static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1097         static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
1098         static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
1099         static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1100         struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
1101
1102         tmport = wkport + 0x3a;
1103         outb((unsigned char) (inb(tmport) | 0x10), tmport);
1104
1105         for (i = 0; i < 16; i++) {
1106                 if ((dev->chip_veru != 4) && (i > 7)) {
1107                         break;
1108                 }
1109                 m = 1;
1110                 m = m << i;
1111                 if ((m & dev->active_idu) != 0) {
1112                         continue;
1113                 }
1114                 if (i == dev->host_idu) {
1115                         printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_idu);
1116                         continue;
1117                 }
1118                 tmport = wkport + 0x1b;
1119                 if (dev->chip_veru == 4) {
1120                         outb(0x01, tmport);
1121                 } else {
1122                         outb(0x00, tmport);
1123                 }
1124                 tmport = wkport + 1;
1125                 outb(0x08, tmport++);
1126                 outb(0x7f, tmport++);
1127                 outb(satn[0], tmport++);
1128                 outb(satn[1], tmport++);
1129                 outb(satn[2], tmport++);
1130                 outb(satn[3], tmport++);
1131                 outb(satn[4], tmport++);
1132                 outb(satn[5], tmport++);
1133                 tmport += 0x06;
1134                 outb(0, tmport);
1135                 tmport += 0x02;
1136                 outb(dev->id[i].devspu, tmport++);
1137                 outb(0, tmport++);
1138                 outb(satn[6], tmport++);
1139                 outb(satn[7], tmport++);
1140                 j = i;
1141                 if ((j & 0x08) != 0) {
1142                         j = (j & 0x07) | 0x40;
1143                 }
1144                 outb(j, tmport);
1145                 tmport += 0x03;
1146                 outb(satn[8], tmport);
1147                 tmport += 0x07;
1148
1149                 while ((inb(tmport) & 0x80) == 0x00);
1150                 tmport -= 0x08;
1151                 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1152                         continue;
1153                 }
1154                 while (inb(tmport) != 0x8e);
1155                 dev->active_idu |= m;
1156
1157                 tmport = wkport + 0x10;
1158                 outb(0x30, tmport);
1159                 tmport = wkport + 0x04;
1160                 outb(0x00, tmport);
1161
1162 phase_cmd:
1163                 tmport = wkport + 0x18;
1164                 outb(0x08, tmport);
1165                 tmport += 0x07;
1166                 while ((inb(tmport) & 0x80) == 0x00);
1167                 tmport -= 0x08;
1168                 j = inb(tmport);
1169                 if (j != 0x16) {
1170                         tmport = wkport + 0x10;
1171                         outb(0x41, tmport);
1172                         goto phase_cmd;
1173                 }
1174 sel_ok:
1175                 tmport = wkport + 3;
1176                 outb(inqd[0], tmport++);
1177                 outb(inqd[1], tmport++);
1178                 outb(inqd[2], tmport++);
1179                 outb(inqd[3], tmport++);
1180                 outb(inqd[4], tmport++);
1181                 outb(inqd[5], tmport);
1182                 tmport += 0x07;
1183                 outb(0, tmport);
1184                 tmport += 0x02;
1185                 outb(dev->id[i].devspu, tmport++);
1186                 outb(0, tmport++);
1187                 outb(inqd[6], tmport++);
1188                 outb(inqd[7], tmport++);
1189                 tmport += 0x03;
1190                 outb(inqd[8], tmport);
1191                 tmport += 0x07;
1192                 while ((inb(tmport) & 0x80) == 0x00);
1193                 tmport -= 0x08;
1194                 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1195                         continue;
1196                 }
1197                 while (inb(tmport) != 0x8e);
1198                 tmport = wkport + 0x1b;
1199                 if (dev->chip_veru == 4) {
1200                         outb(0x00, tmport);
1201                 }
1202                 tmport = wkport + 0x18;
1203                 outb(0x08, tmport);
1204                 tmport += 0x07;
1205                 j = 0;
1206 rd_inq_data:
1207                 k = inb(tmport);
1208                 if ((k & 0x01) != 0) {
1209                         tmport -= 0x06;
1210                         mbuf[j++] = inb(tmport);
1211                         tmport += 0x06;
1212                         goto rd_inq_data;
1213                 }
1214                 if ((k & 0x80) == 0) {
1215                         goto rd_inq_data;
1216                 }
1217                 tmport -= 0x08;
1218                 j = inb(tmport);
1219                 if (j == 0x16) {
1220                         goto inq_ok;
1221                 }
1222                 tmport = wkport + 0x10;
1223                 outb(0x46, tmport);
1224                 tmport += 0x02;
1225                 outb(0, tmport++);
1226                 outb(0, tmport++);
1227                 outb(0, tmport++);
1228                 tmport += 0x03;
1229                 outb(0x08, tmport);
1230                 tmport += 0x07;
1231                 while ((inb(tmport) & 0x80) == 0x00);
1232                 tmport -= 0x08;
1233                 if (inb(tmport) != 0x16) {
1234                         goto sel_ok;
1235                 }
1236 inq_ok:
1237                 mbuf[36] = 0;
1238                 printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
1239                 dev->id[i].devtypeu = mbuf[0];
1240                 rmb = mbuf[1];
1241                 n = mbuf[7];
1242                 if (dev->chip_veru != 4) {
1243                         goto not_wide;
1244                 }
1245                 if ((mbuf[7] & 0x60) == 0) {
1246                         goto not_wide;
1247                 }
1248                 if ((dev->global_map & 0x20) == 0) {
1249                         goto not_wide;
1250                 }
1251                 tmport = wkport + 0x1b;
1252                 outb(0x01, tmport);
1253                 tmport = wkport + 3;
1254                 outb(satn[0], tmport++);
1255                 outb(satn[1], tmport++);
1256                 outb(satn[2], tmport++);
1257                 outb(satn[3], tmport++);
1258                 outb(satn[4], tmport++);
1259                 outb(satn[5], tmport++);
1260                 tmport += 0x06;
1261                 outb(0, tmport);
1262                 tmport += 0x02;
1263                 outb(dev->id[i].devspu, tmport++);
1264                 outb(0, tmport++);
1265                 outb(satn[6], tmport++);
1266                 outb(satn[7], tmport++);
1267                 tmport += 0x03;
1268                 outb(satn[8], tmport);
1269                 tmport += 0x07;
1270
1271                 while ((inb(tmport) & 0x80) == 0x00);
1272                 tmport -= 0x08;
1273                 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1274                         continue;
1275                 }
1276                 while (inb(tmport) != 0x8e);
1277 try_wide:
1278                 j = 0;
1279                 tmport = wkport + 0x14;
1280                 outb(0x05, tmport);
1281                 tmport += 0x04;
1282                 outb(0x20, tmport);
1283                 tmport += 0x07;
1284
1285                 while ((inb(tmport) & 0x80) == 0) {
1286                         if ((inb(tmport) & 0x01) != 0) {
1287                                 tmport -= 0x06;
1288                                 outb(wide[j++], tmport);
1289                                 tmport += 0x06;
1290                         }
1291                 }
1292                 tmport -= 0x08;
1293                 while ((inb(tmport) & 0x80) == 0x00);
1294                 j = inb(tmport) & 0x0f;
1295                 if (j == 0x0f) {
1296                         goto widep_in;
1297                 }
1298                 if (j == 0x0a) {
1299                         goto widep_cmd;
1300                 }
1301                 if (j == 0x0e) {
1302                         goto try_wide;
1303                 }
1304                 continue;
1305 widep_out:
1306                 tmport = wkport + 0x18;
1307                 outb(0x20, tmport);
1308                 tmport += 0x07;
1309                 while ((inb(tmport) & 0x80) == 0) {
1310                         if ((inb(tmport) & 0x01) != 0) {
1311                                 tmport -= 0x06;
1312                                 outb(0, tmport);
1313                                 tmport += 0x06;
1314                         }
1315                 }
1316                 tmport -= 0x08;
1317                 j = inb(tmport) & 0x0f;
1318                 if (j == 0x0f) {
1319                         goto widep_in;
1320                 }
1321                 if (j == 0x0a) {
1322                         goto widep_cmd;
1323                 }
1324                 if (j == 0x0e) {
1325                         goto widep_out;
1326                 }
1327                 continue;
1328 widep_in:
1329                 tmport = wkport + 0x14;
1330                 outb(0xff, tmport);
1331                 tmport += 0x04;
1332                 outb(0x20, tmport);
1333                 tmport += 0x07;
1334                 k = 0;
1335 widep_in1:
1336                 j = inb(tmport);
1337                 if ((j & 0x01) != 0) {
1338                         tmport -= 0x06;
1339                         mbuf[k++] = inb(tmport);
1340                         tmport += 0x06;
1341                         goto widep_in1;
1342                 }
1343                 if ((j & 0x80) == 0x00) {
1344                         goto widep_in1;
1345                 }
1346                 tmport -= 0x08;
1347                 j = inb(tmport) & 0x0f;
1348                 if (j == 0x0f) {
1349                         goto widep_in;
1350                 }
1351                 if (j == 0x0a) {
1352                         goto widep_cmd;
1353                 }
1354                 if (j == 0x0e) {
1355                         goto widep_out;
1356                 }
1357                 continue;
1358 widep_cmd:
1359                 tmport = wkport + 0x10;
1360                 outb(0x30, tmport);
1361                 tmport = wkport + 0x14;
1362                 outb(0x00, tmport);
1363                 tmport += 0x04;
1364                 outb(0x08, tmport);
1365                 tmport += 0x07;
1366                 while ((inb(tmport) & 0x80) == 0x00);
1367                 tmport -= 0x08;
1368                 j = inb(tmport);
1369                 if (j != 0x16) {
1370                         if (j == 0x4e) {
1371                                 goto widep_out;
1372                         }
1373                         continue;
1374                 }
1375                 if (mbuf[0] != 0x01) {
1376                         goto not_wide;
1377                 }
1378                 if (mbuf[1] != 0x02) {
1379                         goto not_wide;
1380                 }
1381                 if (mbuf[2] != 0x03) {
1382                         goto not_wide;
1383                 }
1384                 if (mbuf[3] != 0x01) {
1385                         goto not_wide;
1386                 }
1387                 m = 1;
1388                 m = m << i;
1389                 dev->wide_idu |= m;
1390 not_wide:
1391                 if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) {
1392                         goto set_sync;
1393                 }
1394                 continue;
1395 set_sync:
1396                 tmport = wkport + 0x1b;
1397                 j = 0;
1398                 if ((m & dev->wide_idu) != 0) {
1399                         j |= 0x01;
1400                 }
1401                 outb(j, tmport);
1402                 tmport = wkport + 3;
1403                 outb(satn[0], tmport++);
1404                 outb(satn[1], tmport++);
1405                 outb(satn[2], tmport++);
1406                 outb(satn[3], tmport++);
1407                 outb(satn[4], tmport++);
1408                 outb(satn[5], tmport++);
1409                 tmport += 0x06;
1410                 outb(0, tmport);
1411                 tmport += 0x02;
1412                 outb(dev->id[i].devspu, tmport++);
1413                 outb(0, tmport++);
1414                 outb(satn[6], tmport++);
1415                 outb(satn[7], tmport++);
1416                 tmport += 0x03;
1417                 outb(satn[8], tmport);
1418                 tmport += 0x07;
1419
1420                 while ((inb(tmport) & 0x80) == 0x00);
1421                 tmport -= 0x08;
1422                 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1423                         continue;
1424                 }
1425                 while (inb(tmport) != 0x8e);
1426 try_sync:
1427                 j = 0;
1428                 tmport = wkport + 0x14;
1429                 outb(0x06, tmport);
1430                 tmport += 0x04;
1431                 outb(0x20, tmport);
1432                 tmport += 0x07;
1433
1434                 while ((inb(tmport) & 0x80) == 0) {
1435                         if ((inb(tmport) & 0x01) != 0) {
1436                                 tmport -= 0x06;
1437                                 if ((m & dev->wide_idu) != 0) {
1438                                         outb(synw[j++], tmport);
1439                                 } else {
1440                                         if ((m & dev->ultra_map) != 0) {
1441                                                 outb(synu[j++], tmport);
1442                                         } else {
1443                                                 outb(synn[j++], tmport);
1444                                         }
1445                                 }
1446                                 tmport += 0x06;
1447                         }
1448                 }
1449                 tmport -= 0x08;
1450                 while ((inb(tmport) & 0x80) == 0x00);
1451                 j = inb(tmport) & 0x0f;
1452                 if (j == 0x0f) {
1453                         goto phase_ins;
1454                 }
1455                 if (j == 0x0a) {
1456                         goto phase_cmds;
1457                 }
1458                 if (j == 0x0e) {
1459                         goto try_sync;
1460                 }
1461                 continue;
1462 phase_outs:
1463                 tmport = wkport + 0x18;
1464                 outb(0x20, tmport);
1465                 tmport += 0x07;
1466                 while ((inb(tmport) & 0x80) == 0x00) {
1467                         if ((inb(tmport) & 0x01) != 0x00) {
1468                                 tmport -= 0x06;
1469                                 outb(0x00, tmport);
1470                                 tmport += 0x06;
1471                         }
1472                 }
1473                 tmport -= 0x08;
1474                 j = inb(tmport);
1475                 if (j == 0x85) {
1476                         goto tar_dcons;
1477                 }
1478                 j &= 0x0f;
1479                 if (j == 0x0f) {
1480                         goto phase_ins;
1481                 }
1482                 if (j == 0x0a) {
1483                         goto phase_cmds;
1484                 }
1485                 if (j == 0x0e) {
1486                         goto phase_outs;
1487                 }
1488                 continue;
1489 phase_ins:
1490                 tmport = wkport + 0x14;
1491                 outb(0xff, tmport);
1492                 tmport += 0x04;
1493                 outb(0x20, tmport);
1494                 tmport += 0x07;
1495                 k = 0;
1496 phase_ins1:
1497                 j = inb(tmport);
1498                 if ((j & 0x01) != 0x00) {
1499                         tmport -= 0x06;
1500                         mbuf[k++] = inb(tmport);
1501                         tmport += 0x06;
1502                         goto phase_ins1;
1503                 }
1504                 if ((j & 0x80) == 0x00) {
1505                         goto phase_ins1;
1506                 }
1507                 tmport -= 0x08;
1508                 while ((inb(tmport) & 0x80) == 0x00);
1509                 j = inb(tmport);
1510                 if (j == 0x85) {
1511                         goto tar_dcons;
1512                 }
1513                 j &= 0x0f;
1514                 if (j == 0x0f) {
1515                         goto phase_ins;
1516                 }
1517                 if (j == 0x0a) {
1518                         goto phase_cmds;
1519                 }
1520                 if (j == 0x0e) {
1521                         goto phase_outs;
1522                 }
1523                 continue;
1524 phase_cmds:
1525                 tmport = wkport + 0x10;
1526                 outb(0x30, tmport);
1527 tar_dcons:
1528                 tmport = wkport + 0x14;
1529                 outb(0x00, tmport);
1530                 tmport += 0x04;
1531                 outb(0x08, tmport);
1532                 tmport += 0x07;
1533                 while ((inb(tmport) & 0x80) == 0x00);
1534                 tmport -= 0x08;
1535                 j = inb(tmport);
1536                 if (j != 0x16) {
1537                         continue;
1538                 }
1539                 if (mbuf[0] != 0x01) {
1540                         continue;
1541                 }
1542                 if (mbuf[1] != 0x03) {
1543                         continue;
1544                 }
1545                 if (mbuf[4] == 0x00) {
1546                         continue;
1547                 }
1548                 if (mbuf[3] > 0x64) {
1549                         continue;
1550                 }
1551                 if (mbuf[4] > 0x0c) {
1552                         mbuf[4] = 0x0c;
1553                 }
1554                 dev->id[i].devspu = mbuf[4];
1555                 if ((mbuf[3] < 0x0d) && (rmb == 0)) {
1556                         j = 0xa0;
1557                         goto set_syn_ok;
1558                 }
1559                 if (mbuf[3] < 0x1a) {
1560                         j = 0x20;
1561                         goto set_syn_ok;
1562                 }
1563                 if (mbuf[3] < 0x33) {
1564                         j = 0x40;
1565                         goto set_syn_ok;
1566                 }
1567                 if (mbuf[3] < 0x4c) {
1568                         j = 0x50;
1569                         goto set_syn_ok;
1570                 }
1571                 j = 0x60;
1572 set_syn_ok:
1573                 dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
1574         }
1575         tmport = wkport + 0x3a;
1576         outb((unsigned char) (inb(tmport) & 0xef), tmport);
1577 }
1578
1579 static void is880(struct Scsi_Host *host, unsigned int wkport)
1580 {
1581         unsigned int tmport;
1582         unsigned char i, j, k, rmb, n, lvdmode;
1583         unsigned short int m;
1584         static unsigned char mbuf[512];
1585         static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1586         static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1587         static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1588         unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1589         static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1590         unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1591         static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1592         static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
1593         struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
1594
1595         lvdmode = inb(wkport + 0x3f) & 0x40;
1596
1597         for (i = 0; i < 16; i++) {
1598                 m = 1;
1599                 m = m << i;
1600                 if ((m & dev->active_idu) != 0) {
1601                         continue;
1602                 }
1603                 if (i == dev->host_idu) {
1604                         printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_idu);
1605                         continue;
1606                 }
1607                 tmport = wkport + 0x5b;
1608                 outb(0x01, tmport);
1609                 tmport = wkport + 0x41;
1610                 outb(0x08, tmport++);
1611                 outb(0x7f, tmport++);
1612                 outb(satn[0], tmport++);
1613                 outb(satn[1], tmport++);
1614                 outb(satn[2], tmport++);
1615                 outb(satn[3], tmport++);
1616                 outb(satn[4], tmport++);
1617                 outb(satn[5], tmport++);
1618                 tmport += 0x06;
1619                 outb(0, tmport);
1620                 tmport += 0x02;
1621                 outb(dev->id[i].devspu, tmport++);
1622                 outb(0, tmport++);
1623                 outb(satn[6], tmport++);
1624                 outb(satn[7], tmport++);
1625                 j = i;
1626                 if ((j & 0x08) != 0) {
1627                         j = (j & 0x07) | 0x40;
1628                 }
1629                 outb(j, tmport);
1630                 tmport += 0x03;
1631                 outb(satn[8], tmport);
1632                 tmport += 0x07;
1633
1634                 while ((inb(tmport) & 0x80) == 0x00);
1635                 tmport -= 0x08;
1636                 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1637                         continue;
1638                 }
1639                 while (inb(tmport) != 0x8e);
1640                 dev->active_idu |= m;
1641
1642                 tmport = wkport + 0x50;
1643                 outb(0x30, tmport);
1644                 tmport = wkport + 0x54;
1645                 outb(0x00, tmport);
1646
1647 phase_cmd:
1648                 tmport = wkport + 0x58;
1649                 outb(0x08, tmport);
1650                 tmport += 0x07;
1651                 while ((inb(tmport) & 0x80) == 0x00);
1652                 tmport -= 0x08;
1653                 j = inb(tmport);
1654                 if (j != 0x16) {
1655                         tmport = wkport + 0x50;
1656                         outb(0x41, tmport);
1657                         goto phase_cmd;
1658                 }
1659 sel_ok:
1660                 tmport = wkport + 0x43;
1661                 outb(inqd[0], tmport++);
1662                 outb(inqd[1], tmport++);
1663                 outb(inqd[2], tmport++);
1664                 outb(inqd[3], tmport++);
1665                 outb(inqd[4], tmport++);
1666                 outb(inqd[5], tmport);
1667                 tmport += 0x07;
1668                 outb(0, tmport);
1669                 tmport += 0x02;
1670                 outb(dev->id[i].devspu, tmport++);
1671                 outb(0, tmport++);
1672                 outb(inqd[6], tmport++);
1673                 outb(inqd[7], tmport++);
1674                 tmport += 0x03;
1675                 outb(inqd[8], tmport);
1676                 tmport += 0x07;
1677                 while ((inb(tmport) & 0x80) == 0x00);
1678                 tmport -= 0x08;
1679                 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1680                         continue;
1681                 }
1682                 while (inb(tmport) != 0x8e);
1683                 tmport = wkport + 0x5b;
1684                 outb(0x00, tmport);
1685                 tmport = wkport + 0x58;
1686                 outb(0x08, tmport);
1687                 tmport += 0x07;
1688                 j = 0;
1689 rd_inq_data:
1690                 k = inb(tmport);
1691                 if ((k & 0x01) != 0) {
1692                         tmport -= 0x06;
1693                         mbuf[j++] = inb(tmport);
1694                         tmport += 0x06;
1695                         goto rd_inq_data;
1696                 }
1697                 if ((k & 0x80) == 0) {
1698                         goto rd_inq_data;
1699                 }
1700                 tmport -= 0x08;
1701                 j = inb(tmport);
1702                 if (j == 0x16) {
1703                         goto inq_ok;
1704                 }
1705                 tmport = wkport + 0x50;
1706                 outb(0x46, tmport);
1707                 tmport += 0x02;
1708                 outb(0, tmport++);
1709                 outb(0, tmport++);
1710                 outb(0, tmport++);
1711                 tmport += 0x03;
1712                 outb(0x08, tmport);
1713                 tmport += 0x07;
1714                 while ((inb(tmport) & 0x80) == 0x00);
1715                 tmport -= 0x08;
1716                 if (inb(tmport) != 0x16) {
1717                         goto sel_ok;
1718                 }
1719 inq_ok:
1720                 mbuf[36] = 0;
1721                 printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
1722                 dev->id[i].devtypeu = mbuf[0];
1723                 rmb = mbuf[1];
1724                 n = mbuf[7];
1725                 if ((mbuf[7] & 0x60) == 0) {
1726                         goto not_wide;
1727                 }
1728                 if ((i < 8) && ((dev->global_map & 0x20) == 0)) {
1729                         goto not_wide;
1730                 }
1731                 if (lvdmode == 0) {
1732                         goto chg_wide;
1733                 }
1734                 if (dev->sp[i] != 0x04) // force u2
1735                 {
1736                         goto chg_wide;
1737                 }
1738
1739                 tmport = wkport + 0x5b;
1740                 outb(0x01, tmport);
1741                 tmport = wkport + 0x43;
1742                 outb(satn[0], tmport++);
1743                 outb(satn[1], tmport++);
1744                 outb(satn[2], tmport++);
1745                 outb(satn[3], tmport++);
1746                 outb(satn[4], tmport++);
1747                 outb(satn[5], tmport++);
1748                 tmport += 0x06;
1749                 outb(0, tmport);
1750                 tmport += 0x02;
1751                 outb(dev->id[i].devspu, tmport++);
1752                 outb(0, tmport++);
1753                 outb(satn[6], tmport++);
1754                 outb(satn[7], tmport++);
1755                 tmport += 0x03;
1756                 outb(satn[8], tmport);
1757                 tmport += 0x07;
1758
1759                 while ((inb(tmport) & 0x80) == 0x00);
1760                 tmport -= 0x08;
1761                 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1762                         continue;
1763                 }
1764                 while (inb(tmport) != 0x8e);
1765 try_u3:
1766                 j = 0;
1767                 tmport = wkport + 0x54;
1768                 outb(0x09, tmport);
1769                 tmport += 0x04;
1770                 outb(0x20, tmport);
1771                 tmport += 0x07;
1772
1773                 while ((inb(tmport) & 0x80) == 0) {
1774                         if ((inb(tmport) & 0x01) != 0) {
1775                                 tmport -= 0x06;
1776                                 outb(u3[j++], tmport);
1777                                 tmport += 0x06;
1778                         }
1779                 }
1780                 tmport -= 0x08;
1781                 while ((inb(tmport) & 0x80) == 0x00);
1782                 j = inb(tmport) & 0x0f;
1783                 if (j == 0x0f) {
1784                         goto u3p_in;
1785                 }
1786                 if (j == 0x0a) {
1787                         goto u3p_cmd;
1788                 }
1789                 if (j == 0x0e) {
1790                         goto try_u3;
1791                 }
1792                 continue;
1793 u3p_out:
1794                 tmport = wkport + 0x58;
1795                 outb(0x20, tmport);
1796                 tmport += 0x07;
1797                 while ((inb(tmport) & 0x80) == 0) {
1798                         if ((inb(tmport) & 0x01) != 0) {
1799                                 tmport -= 0x06;
1800                                 outb(0, tmport);
1801                                 tmport += 0x06;
1802                         }
1803                 }
1804                 tmport -= 0x08;
1805                 j = inb(tmport) & 0x0f;
1806                 if (j == 0x0f) {
1807                         goto u3p_in;
1808                 }
1809                 if (j == 0x0a) {
1810                         goto u3p_cmd;
1811                 }
1812                 if (j == 0x0e) {
1813                         goto u3p_out;
1814                 }
1815                 continue;
1816 u3p_in:
1817                 tmport = wkport + 0x54;
1818                 outb(0x09, tmport);
1819                 tmport += 0x04;
1820                 outb(0x20, tmport);
1821                 tmport += 0x07;
1822                 k = 0;
1823 u3p_in1:
1824                 j = inb(tmport);
1825                 if ((j & 0x01) != 0) {
1826                         tmport -= 0x06;
1827                         mbuf[k++] = inb(tmport);
1828                         tmport += 0x06;
1829                         goto u3p_in1;
1830                 }
1831                 if ((j & 0x80) == 0x00) {
1832                         goto u3p_in1;
1833                 }
1834                 tmport -= 0x08;
1835                 j = inb(tmport) & 0x0f;
1836                 if (j == 0x0f) {
1837                         goto u3p_in;
1838                 }
1839                 if (j == 0x0a) {
1840                         goto u3p_cmd;
1841                 }
1842                 if (j == 0x0e) {
1843                         goto u3p_out;
1844                 }
1845                 continue;
1846 u3p_cmd:
1847                 tmport = wkport + 0x50;
1848                 outb(0x30, tmport);
1849                 tmport = wkport + 0x54;
1850                 outb(0x00, tmport);
1851                 tmport += 0x04;
1852                 outb(0x08, tmport);
1853                 tmport += 0x07;
1854                 while ((inb(tmport) & 0x80) == 0x00);
1855                 tmport -= 0x08;
1856                 j = inb(tmport);
1857                 if (j != 0x16) {
1858                         if (j == 0x4e) {
1859                                 goto u3p_out;
1860                         }
1861                         continue;
1862                 }
1863                 if (mbuf[0] != 0x01) {
1864                         goto chg_wide;
1865                 }
1866                 if (mbuf[1] != 0x06) {
1867                         goto chg_wide;
1868                 }
1869                 if (mbuf[2] != 0x04) {
1870                         goto chg_wide;
1871                 }
1872                 if (mbuf[3] == 0x09) {
1873                         m = 1;
1874                         m = m << i;
1875                         dev->wide_idu |= m;
1876                         dev->id[i].devspu = 0xce;
1877                         continue;
1878                 }
1879 chg_wide:
1880                 tmport = wkport + 0x5b;
1881                 outb(0x01, tmport);
1882                 tmport = wkport + 0x43;
1883                 outb(satn[0], tmport++);
1884                 outb(satn[1], tmport++);
1885                 outb(satn[2], tmport++);
1886                 outb(satn[3], tmport++);
1887                 outb(satn[4], tmport++);
1888                 outb(satn[5], tmport++);
1889                 tmport += 0x06;
1890                 outb(0, tmport);
1891                 tmport += 0x02;
1892                 outb(dev->id[i].devspu, tmport++);
1893                 outb(0, tmport++);
1894                 outb(satn[6], tmport++);
1895                 outb(satn[7], tmport++);
1896                 tmport += 0x03;
1897                 outb(satn[8], tmport);
1898                 tmport += 0x07;
1899
1900                 while ((inb(tmport) & 0x80) == 0x00);
1901                 tmport -= 0x08;
1902                 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1903                         continue;
1904                 }
1905                 while (inb(tmport) != 0x8e);
1906 try_wide:
1907                 j = 0;
1908                 tmport = wkport + 0x54;
1909                 outb(0x05, tmport);
1910                 tmport += 0x04;
1911                 outb(0x20, tmport);
1912                 tmport += 0x07;
1913
1914                 while ((inb(tmport) & 0x80) == 0) {
1915                         if ((inb(tmport) & 0x01) != 0) {
1916                                 tmport -= 0x06;
1917                                 outb(wide[j++], tmport);
1918                                 tmport += 0x06;
1919                         }
1920                 }
1921                 tmport -= 0x08;
1922                 while ((inb(tmport) & 0x80) == 0x00);
1923                 j = inb(tmport) & 0x0f;
1924                 if (j == 0x0f) {
1925                         goto widep_in;
1926                 }
1927                 if (j == 0x0a) {
1928                         goto widep_cmd;
1929                 }
1930                 if (j == 0x0e) {
1931                         goto try_wide;
1932                 }
1933                 continue;
1934 widep_out:
1935                 tmport = wkport + 0x58;
1936                 outb(0x20, tmport);
1937                 tmport += 0x07;
1938                 while ((inb(tmport) & 0x80) == 0) {
1939                         if ((inb(tmport) & 0x01) != 0) {
1940                                 tmport -= 0x06;
1941                                 outb(0, tmport);
1942                                 tmport += 0x06;
1943                         }
1944                 }
1945                 tmport -= 0x08;
1946                 j = inb(tmport) & 0x0f;
1947                 if (j == 0x0f) {
1948                         goto widep_in;
1949                 }
1950                 if (j == 0x0a) {
1951                         goto widep_cmd;
1952                 }
1953                 if (j == 0x0e) {
1954                         goto widep_out;
1955                 }
1956                 continue;
1957 widep_in:
1958                 tmport = wkport + 0x54;
1959                 outb(0xff, tmport);
1960                 tmport += 0x04;
1961                 outb(0x20, tmport);
1962                 tmport += 0x07;
1963                 k = 0;
1964 widep_in1:
1965                 j = inb(tmport);
1966                 if ((j & 0x01) != 0) {
1967                         tmport -= 0x06;
1968                         mbuf[k++] = inb(tmport);
1969                         tmport += 0x06;
1970                         goto widep_in1;
1971                 }
1972                 if ((j & 0x80) == 0x00) {
1973                         goto widep_in1;
1974                 }
1975                 tmport -= 0x08;
1976                 j = inb(tmport) & 0x0f;
1977                 if (j == 0x0f) {
1978                         goto widep_in;
1979                 }
1980                 if (j == 0x0a) {
1981                         goto widep_cmd;
1982                 }
1983                 if (j == 0x0e) {
1984                         goto widep_out;
1985                 }
1986                 continue;
1987 widep_cmd:
1988                 tmport = wkport + 0x50;
1989                 outb(0x30, tmport);
1990                 tmport = wkport + 0x54;
1991                 outb(0x00, tmport);
1992                 tmport += 0x04;
1993                 outb(0x08, tmport);
1994                 tmport += 0x07;
1995                 while ((inb(tmport) & 0x80) == 0x00);
1996                 tmport -= 0x08;
1997                 j = inb(tmport);
1998                 if (j != 0x16) {
1999                         if (j == 0x4e) {
2000                                 goto widep_out;
2001                         }
2002                         continue;
2003                 }
2004                 if (mbuf[0] != 0x01) {
2005                         goto not_wide;
2006                 }
2007                 if (mbuf[1] != 0x02) {
2008                         goto not_wide;
2009                 }
2010                 if (mbuf[2] != 0x03) {
2011                         goto not_wide;
2012                 }
2013                 if (mbuf[3] != 0x01) {
2014                         goto not_wide;
2015                 }
2016                 m = 1;
2017                 m = m << i;
2018                 dev->wide_idu |= m;
2019 not_wide:
2020                 if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) {
2021                         m = 1;
2022                         m = m << i;
2023                         if ((dev->async & m) != 0) {
2024                                 goto set_sync;
2025                         }
2026                 }
2027                 continue;
2028 set_sync:
2029                 if (dev->sp[i] == 0x02) {
2030                         synu[4] = 0x0c;
2031                         synuw[4] = 0x0c;
2032                 } else {
2033                         if (dev->sp[i] >= 0x03) {
2034                                 synu[4] = 0x0a;
2035                                 synuw[4] = 0x0a;
2036                         }
2037                 }
2038                 tmport = wkport + 0x5b;
2039                 j = 0;
2040                 if ((m & dev->wide_idu) != 0) {
2041                         j |= 0x01;
2042                 }
2043                 outb(j, tmport);
2044                 tmport = wkport + 0x43;
2045                 outb(satn[0], tmport++);
2046                 outb(satn[1], tmport++);
2047                 outb(satn[2], tmport++);
2048                 outb(satn[3], tmport++);
2049                 outb(satn[4], tmport++);
2050                 outb(satn[5], tmport++);
2051                 tmport += 0x06;
2052                 outb(0, tmport);
2053                 tmport += 0x02;
2054                 outb(dev->id[i].devspu, tmport++);
2055                 outb(0, tmport++);
2056                 outb(satn[6], tmport++);
2057                 outb(satn[7], tmport++);
2058                 tmport += 0x03;
2059                 outb(satn[8], tmport);
2060                 tmport += 0x07;
2061
2062                 while ((inb(tmport) & 0x80) == 0x00);
2063                 tmport -= 0x08;
2064                 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
2065                         continue;
2066                 }
2067                 while (inb(tmport) != 0x8e);
2068 try_sync:
2069                 j = 0;
2070                 tmport = wkport + 0x54;
2071                 outb(0x06, tmport);
2072                 tmport += 0x04;
2073                 outb(0x20, tmport);
2074                 tmport += 0x07;
2075
2076                 while ((inb(tmport) & 0x80) == 0) {
2077                         if ((inb(tmport) & 0x01) != 0) {
2078                                 tmport -= 0x06;
2079                                 if ((m & dev->wide_idu) != 0) {
2080                                         if ((m & dev->ultra_map) != 0) {
2081                                                 outb(synuw[j++], tmport);
2082                                         } else {
2083                                                 outb(synw[j++], tmport);
2084                                         }
2085                                 } else {
2086                                         if ((m & dev->ultra_map) != 0) {
2087                                                 outb(synu[j++], tmport);
2088                                         } else {
2089                                                 outb(synn[j++], tmport);
2090                                         }
2091                                 }
2092                                 tmport += 0x06;
2093                         }
2094                 }
2095                 tmport -= 0x08;
2096                 while ((inb(tmport) & 0x80) == 0x00);
2097                 j = inb(tmport) & 0x0f;
2098                 if (j == 0x0f) {
2099                         goto phase_ins;
2100                 }
2101                 if (j == 0x0a) {
2102                         goto phase_cmds;
2103                 }
2104                 if (j == 0x0e) {
2105                         goto try_sync;
2106                 }
2107                 continue;
2108 phase_outs:
2109                 tmport = wkport + 0x58;
2110                 outb(0x20, tmport);
2111                 tmport += 0x07;
2112                 while ((inb(tmport) & 0x80) == 0x00) {
2113                         if ((inb(tmport) & 0x01) != 0x00) {
2114                                 tmport -= 0x06;
2115                                 outb(0x00, tmport);
2116                                 tmport += 0x06;
2117                         }
2118                 }
2119                 tmport -= 0x08;
2120                 j = inb(tmport);
2121                 if (j == 0x85) {
2122                         goto tar_dcons;
2123                 }
2124                 j &= 0x0f;
2125                 if (j == 0x0f) {
2126                         goto phase_ins;
2127                 }
2128                 if (j == 0x0a) {
2129                         goto phase_cmds;
2130                 }
2131                 if (j == 0x0e) {
2132                         goto phase_outs;
2133                 }
2134                 continue;
2135 phase_ins:
2136                 tmport = wkport + 0x54;
2137                 outb(0x06, tmport);
2138                 tmport += 0x04;
2139                 outb(0x20, tmport);
2140                 tmport += 0x07;
2141                 k = 0;
2142 phase_ins1:
2143                 j = inb(tmport);
2144                 if ((j & 0x01) != 0x00) {
2145                         tmport -= 0x06;
2146                         mbuf[k++] = inb(tmport);
2147                         tmport += 0x06;
2148                         goto phase_ins1;
2149                 }
2150                 if ((j & 0x80) == 0x00) {
2151                         goto phase_ins1;
2152                 }
2153                 tmport -= 0x08;
2154                 while ((inb(tmport) & 0x80) == 0x00);
2155                 j = inb(tmport);
2156                 if (j == 0x85) {
2157                         goto tar_dcons;
2158                 }
2159                 j &= 0x0f;
2160                 if (j == 0x0f) {
2161                         goto phase_ins;
2162                 }
2163                 if (j == 0x0a) {
2164                         goto phase_cmds;
2165                 }
2166                 if (j == 0x0e) {
2167                         goto phase_outs;
2168                 }
2169                 continue;
2170 phase_cmds:
2171                 tmport = wkport + 0x50;
2172                 outb(0x30, tmport);
2173 tar_dcons:
2174                 tmport = wkport + 0x54;
2175                 outb(0x00, tmport);
2176                 tmport += 0x04;
2177                 outb(0x08, tmport);
2178                 tmport += 0x07;
2179                 while ((inb(tmport) & 0x80) == 0x00);
2180                 tmport -= 0x08;
2181                 j = inb(tmport);
2182                 if (j != 0x16) {
2183                         continue;
2184                 }
2185                 if (mbuf[0] != 0x01) {
2186                         continue;
2187                 }
2188                 if (mbuf[1] != 0x03) {
2189                         continue;
2190                 }
2191                 if (mbuf[4] == 0x00) {
2192                         continue;
2193                 }
2194                 if (mbuf[3] > 0x64) {
2195                         continue;
2196                 }
2197                 if (mbuf[4] > 0x0e) {
2198                         mbuf[4] = 0x0e;
2199                 }
2200                 dev->id[i].devspu = mbuf[4];
2201                 if (mbuf[3] < 0x0c) {
2202                         j = 0xb0;
2203                         goto set_syn_ok;
2204                 }
2205                 if ((mbuf[3] < 0x0d) && (rmb == 0)) {
2206                         j = 0xa0;
2207                         goto set_syn_ok;
2208                 }
2209                 if (mbuf[3] < 0x1a) {
2210                         j = 0x20;
2211                         goto set_syn_ok;
2212                 }
2213                 if (mbuf[3] < 0x33) {
2214                         j = 0x40;
2215                         goto set_syn_ok;
2216                 }
2217                 if (mbuf[3] < 0x4c) {
2218                         j = 0x50;
2219                         goto set_syn_ok;
2220                 }
2221                 j = 0x60;
2222 set_syn_ok:
2223                 dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
2224         }
2225 }
2226
2227 static void atp870u_free_tables(struct Scsi_Host *host)
2228 {
2229         struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
2230         int k;
2231
2232         for (k = 0; k < 16; k++) {
2233                 if (!atp_dev->id[k].prd_tableu)
2234                         continue;
2235                 pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[k].prd_tableu,
2236                                         atp_dev->id[k].prd_phys);
2237                 atp_dev->id[k].prd_tableu = NULL;
2238         }
2239 }
2240
2241 static int atp870u_init_tables(struct Scsi_Host *host)
2242 {
2243         struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
2244         int k, i;
2245
2246         for (i = k = 0; k < 16; k++) {
2247                 dev->id[k].prd_tableu = pci_alloc_consistent(dev->pdev, 1024, &dev->id[k].prd_phys);
2248                 if (!dev->id[k].prd_tableu) {
2249                         atp870u_free_tables(host);
2250                         return -ENOMEM;
2251                 }
2252                 dev->id[k].devspu = 0x20;
2253                 dev->id[k].devtypeu = 0;
2254                 dev->id[k].curr_req = NULL;
2255         }
2256         dev->active_idu = 0;
2257         dev->wide_idu = 0;
2258         dev->host_idu = 0x07;
2259         dev->quhdu = 0;
2260         dev->quendu = 0;
2261         dev->chip_veru = 0;
2262         dev->last_cmd = 0xff;
2263         dev->in_snd = 0;
2264         dev->in_int = 0;
2265         for (k = 0; k < qcnt; k++) {
2266                 dev->querequ[k] = NULL;
2267         }
2268         for (k = 0; k < 16; k++) {
2269                 dev->id[k].curr_req = NULL;
2270                 dev->sp[k] = 0x04;
2271         }
2272         return 0;
2273 }
2274
2275 /* return non-zero on detection */
2276 static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent)
2277 {
2278         unsigned char k, m;
2279         unsigned long flags;
2280         unsigned int base_io, error, tmport;
2281         unsigned char host_id;
2282         unsigned short n;
2283         struct Scsi_Host *shpnt;
2284         struct atp_unit atp_dev, *p;
2285         static int count;
2286
2287         if (pci_enable_device(dev))
2288                 return -EIO;
2289
2290         if (pci_set_dma_mask(dev, 0xFFFFFFFFUL)) {
2291                 printk(KERN_ERR "atp870u: 32bit DMA mask required but not available.\n");
2292                 return -EIO;
2293         }
2294         
2295         memset(&atp_dev, 0, sizeof atp_dev);
2296  
2297         /*
2298          * It's probably easier to weed out some revisions like
2299          * this than via the PCI device table
2300          */
2301         if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
2302                 error = pci_read_config_byte(dev, PCI_CLASS_REVISION, &atp_dev.chip_veru);
2303                 if (atp_dev.chip_veru < 2)
2304                         return -EIO;
2305         }
2306
2307         switch (ent->device) {
2308         case 0x8081:
2309         case PCI_DEVICE_ID_ARTOP_AEC7612UW:
2310         case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
2311                 atp_dev.chip_veru = 0x04;
2312         default:
2313                 break;
2314         }
2315
2316         base_io = pci_resource_start(dev, 0);
2317
2318         if (ent->device != 0x8081) {
2319                 error = pci_read_config_byte(dev, 0x49, &host_id);
2320                 base_io &= 0xfffffff8;
2321
2322                 printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d "
2323                         "IO:%x, IRQ:%d.\n", count, base_io, dev->irq);
2324
2325                 atp_dev.unit = count;   
2326                 atp_dev.ioport = base_io;
2327                 atp_dev.pciport = base_io + 0x20;
2328                 atp_dev.deviceid = ent->device;
2329                 host_id &= 0x07;
2330                 atp_dev.host_idu = host_id;
2331                 tmport = base_io + 0x22;
2332                 atp_dev.scam_on = inb(tmport);
2333                 tmport += 0x0b;
2334                 atp_dev.global_map = inb(tmport++);
2335                 atp_dev.ultra_map = inw(tmport);
2336
2337                 if (atp_dev.ultra_map == 0) {
2338                         atp_dev.scam_on = 0x00;
2339                         atp_dev.global_map = 0x20;
2340                         atp_dev.ultra_map = 0xffff;
2341                 }
2342
2343                 shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2344                 if (!shpnt)
2345                         return -ENOMEM;
2346
2347                 p = (struct atp_unit *)&shpnt->hostdata;
2348                 
2349                 atp_dev.host = shpnt;
2350                 atp_dev.pdev = dev;
2351                 pci_set_drvdata(dev, p);
2352                 memcpy(p, &atp_dev, sizeof atp_dev);
2353                 if (atp870u_init_tables(shpnt) < 0)
2354                         goto unregister;
2355
2356                 if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
2357                         printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq);
2358                         goto free_tables;
2359                 }
2360
2361                 spin_lock_irqsave(shpnt->host_lock, flags);
2362                 if (atp_dev.chip_veru > 0x07) { /* check if atp876 chip then enable terminator */
2363                         tmport = base_io + 0x3e;
2364                         outb(0x00, tmport);
2365                 }
2366  
2367                 tmport = base_io + 0x3a;
2368                 k = (inb(tmport) & 0xf3) | 0x10;
2369                 outb(k, tmport);
2370                 outb((k & 0xdf), tmport);
2371                 mdelay(32);
2372                 outb(k, tmport);
2373                 mdelay(32);
2374                 tmport = base_io;
2375                 outb((host_id | 0x08), tmport);
2376                 tmport += 0x18;
2377                 outb(0, tmport);
2378                 tmport += 0x07;
2379                 while ((inb(tmport) & 0x80) == 0)
2380                         mdelay(1);
2381
2382                 tmport -= 0x08;
2383                 inb(tmport);
2384                 tmport = base_io + 1;
2385                 outb(8, tmport++);
2386                 outb(0x7f, tmport);
2387                 tmport = base_io + 0x11;
2388                 outb(0x20, tmport);
2389
2390                 tscam(shpnt);
2391                 is870(shpnt, base_io);
2392                 tmport = base_io + 0x3a;
2393                 outb((inb(tmport) & 0xef), tmport);
2394                 tmport++;
2395                 outb((inb(tmport) | 0x20), tmport);
2396         } else {
2397                 base_io &= 0xfffffff8;
2398                 host_id = inb(base_io + 0x39);
2399                 host_id >>= 0x04;
2400
2401                 printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
2402                         "    IO:%x, IRQ:%d.\n", count, base_io, dev->irq);
2403                 atp_dev.ioport = base_io + 0x40;
2404                 atp_dev.pciport = base_io + 0x28;
2405                 atp_dev.deviceid = ent->device;
2406                 atp_dev.host_idu = host_id;
2407
2408                 tmport = base_io + 0x22;
2409                 atp_dev.scam_on = inb(tmport);
2410                 tmport += 0x13;
2411                 atp_dev.global_map = inb(tmport);
2412                 tmport += 0x07;
2413                 atp_dev.ultra_map = inw(tmport);
2414
2415                 n = 0x3f09;
2416 next_fblk:
2417                 if (n >= 0x4000)
2418                         goto flash_ok;
2419
2420                 m = 0;
2421                 outw(n, base_io + 0x34);
2422                 n += 0x0002;
2423                 if (inb(base_io + 0x30) == 0xff)
2424                         goto flash_ok;
2425
2426                 atp_dev.sp[m++] = inb(base_io + 0x30);
2427                 atp_dev.sp[m++] = inb(base_io + 0x31);
2428                 atp_dev.sp[m++] = inb(base_io + 0x32);
2429                 atp_dev.sp[m++] = inb(base_io + 0x33);
2430                 outw(n, base_io + 0x34);
2431                 n += 0x0002;
2432                 atp_dev.sp[m++] = inb(base_io + 0x30);
2433                 atp_dev.sp[m++] = inb(base_io + 0x31);
2434                 atp_dev.sp[m++] = inb(base_io + 0x32);
2435                 atp_dev.sp[m++] = inb(base_io + 0x33);
2436                 outw(n, base_io + 0x34);
2437                 n += 0x0002;
2438                 atp_dev.sp[m++] = inb(base_io + 0x30);
2439                 atp_dev.sp[m++] = inb(base_io + 0x31);
2440                 atp_dev.sp[m++] = inb(base_io + 0x32);
2441                 atp_dev.sp[m++] = inb(base_io + 0x33);
2442                 outw(n, base_io + 0x34);
2443                 n += 0x0002;
2444                 atp_dev.sp[m++] = inb(base_io + 0x30);
2445                 atp_dev.sp[m++] = inb(base_io + 0x31);
2446                 atp_dev.sp[m++] = inb(base_io + 0x32);
2447                 atp_dev.sp[m++] = inb(base_io + 0x33);
2448                 n += 0x0018;
2449                 goto next_fblk;
2450 flash_ok:
2451                 outw(0, base_io + 0x34);
2452                 atp_dev.ultra_map = 0;
2453                 atp_dev.async = 0;
2454                 for (k = 0; k < 16; k++) {
2455                         n = 1;
2456                         n = n << k;
2457                         if (atp_dev.sp[k] > 1) {
2458                                 atp_dev.ultra_map |= n;
2459                         } else {
2460                                 if (atp_dev.sp[k] == 0)
2461                                         atp_dev.async |= n;
2462                         }
2463                 }
2464                 atp_dev.async = ~(atp_dev.async);
2465                 outb(atp_dev.global_map, base_io + 0x35);
2466  
2467                 shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2468                 if (!shpnt)
2469                         return -ENOMEM;
2470
2471                 p = (struct atp_unit *)&shpnt->hostdata;
2472
2473                 atp_dev.host = shpnt;
2474                 atp_dev.pdev = dev;
2475                 pci_set_drvdata(dev, p);
2476                 memcpy(p, &atp_dev, sizeof atp_dev);
2477                 if (atp870u_init_tables(shpnt) < 0) {
2478                         printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
2479                         goto unregister;
2480                 }
2481
2482                 if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
2483                         printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq);
2484                         goto free_tables;
2485                 }
2486
2487                 spin_lock_irqsave(shpnt->host_lock, flags);
2488                 tmport = base_io + 0x38;
2489                 k = inb(tmport) & 0x80;
2490                 outb(k, tmport);
2491                 tmport += 0x03;
2492                 outb(0x20, tmport);
2493                 mdelay(32);
2494                 outb(0, tmport);
2495                 mdelay(32);
2496                 tmport = base_io + 0x5b;
2497                 inb(tmport);
2498                 tmport -= 0x04;
2499                 inb(tmport);
2500                 tmport = base_io + 0x40;
2501                 outb((host_id | 0x08), tmport);
2502                 tmport += 0x18;
2503                 outb(0, tmport);
2504                 tmport += 0x07;
2505                 while ((inb(tmport) & 0x80) == 0)
2506                         mdelay(1);
2507                 tmport -= 0x08;
2508                 inb(tmport);
2509                 tmport = base_io + 0x41;
2510                 outb(8, tmport++);
2511                 outb(0x7f, tmport);
2512                 tmport = base_io + 0x51;
2513                 outb(0x20, tmport);
2514
2515                 tscam(shpnt);
2516                 is880(shpnt, base_io);
2517                 tmport = base_io + 0x38;
2518                 outb(0xb0, tmport);
2519         }
2520
2521         if (p->chip_veru == 4)
2522                 shpnt->max_id = 16;
2523
2524         shpnt->this_id = host_id;
2525         shpnt->unique_id = base_io;
2526         shpnt->io_port = base_io;
2527         if (ent->device == 0x8081) {
2528                 shpnt->n_io_port = 0x60;        /* Number of bytes of I/O space used */
2529         } else {
2530                 shpnt->n_io_port = 0x40;        /* Number of bytes of I/O space used */
2531         }
2532         shpnt->irq = dev->irq;
2533         spin_unlock_irqrestore(shpnt->host_lock, flags);
2534         if (ent->device == 0x8081) {
2535                 if (!request_region(base_io, 0x60, "atp870u"))
2536                         goto request_io_fail;
2537         } else {
2538                 if (!request_region(base_io, 0x40, "atp870u"))
2539                         goto request_io_fail;
2540         }
2541
2542         count++;
2543         if (scsi_add_host(shpnt, &dev->dev))
2544                 goto scsi_add_fail;
2545         scsi_scan_host(shpnt);
2546         return 0;
2547   
2548 scsi_add_fail:
2549         if (ent->device == 0x8081)
2550                 release_region(base_io, 0x60);
2551         else
2552                 release_region(base_io, 0x40);
2553 request_io_fail:
2554         free_irq(dev->irq, shpnt);
2555 free_tables:
2556         atp870u_free_tables(shpnt);
2557 unregister:
2558         scsi_host_put(shpnt);
2559         return -1;
2560 }
2561
2562 /* The abort command does not leave the device in a clean state where
2563    it is available to be used again.  Until this gets worked out, we will
2564    leave it commented out.  */
2565
2566 static int atp870u_abort(struct scsi_cmnd * SCpnt)
2567 {
2568         unsigned char j, k;
2569         struct scsi_cmnd *workrequ;
2570         unsigned int tmport;
2571         struct atp_unit *dev = (struct atp_unit *)&SCpnt->device->host->hostdata;
2572
2573         printk(KERN_DEBUG "working=%x last_cmd=%x ", dev->working, dev->last_cmd);
2574         printk(" quhdu=%x quendu=%x ", dev->quhdu, dev->quendu);
2575         tmport = dev->ioport;
2576         for (j = 0; j < 0x17; j++) {
2577                 printk(" r%2x=%2x", j, inb(tmport++));
2578         }
2579         tmport += 0x05;
2580         printk(" r1c=%2x", inb(tmport));
2581         tmport += 0x03;
2582         printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd);
2583         tmport = dev->pciport;
2584         printk(" r20=%2x", inb(tmport));
2585         tmport += 0x02;
2586         printk(" r22=%2x", inb(tmport));
2587         tmport = dev->ioport + 0x3a;
2588         printk(" r3a=%2x \n", inb(tmport));
2589         tmport = dev->ioport + 0x3b;
2590         printk(" r3b=%2x \n", inb(tmport));
2591         for (j = 0; j < 16; j++) {
2592                 if (dev->id[j].curr_req != NULL) {
2593                         workrequ = dev->id[j].curr_req;
2594                         printk("\n que cdb= ");
2595                         for (k = 0; k < workrequ->cmd_len; k++) {
2596                                 printk(" %2x ", workrequ->cmnd[k]);
2597                         }
2598                         printk(" last_lenu= %lx ", dev->id[j].last_lenu);
2599                 }
2600         }
2601         /* Sort of - the thing handles itself */
2602         return SUCCESS;
2603 }
2604
2605 static const char *atp870u_info(struct Scsi_Host *notused)
2606 {
2607         static char buffer[128];
2608
2609         strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
2610
2611         return buffer;
2612 }
2613
2614 #define BLS buffer + len + size
2615 static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
2616                 char **start, off_t offset, int length, int inout)
2617 {
2618         static u8 buff[512];
2619         int size = 0;
2620         int len = 0;
2621         off_t begin = 0;
2622         off_t pos = 0;
2623
2624         if (inout)
2625                 return -ENOSYS;
2626         if (offset == 0) {
2627                 memset(buff, 0, sizeof(buff));
2628         }
2629         size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
2630         len += size;
2631         pos = begin + len;
2632         size = 0;
2633
2634         size += sprintf(BLS, "\n");
2635         size += sprintf(BLS, "Adapter Configuration:\n");
2636         size += sprintf(BLS, "               Base IO: %#.4lx\n", HBAptr->io_port);
2637         size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
2638         len += size;
2639         pos = begin + len;
2640
2641         *start = buffer + (offset - begin);     /* Start of wanted data */
2642         len -= (offset - begin);        /* Start slop */
2643         if (len > length) {
2644                 len = length;   /* Ending slop */
2645         }
2646         return (len);
2647 }
2648
2649 static int atp870u_biosparam(struct scsi_device *sdev,
2650                 struct block_device *dev, sector_t capacity, int *ip)
2651 {
2652         int heads, sectors, cylinders;
2653
2654         heads = 64;
2655         sectors = 32;
2656         cylinders = (unsigned long)capacity / (heads * sectors);
2657
2658         if (cylinders > 1024) {
2659                 heads = 255;
2660                 sectors = 63;
2661                 cylinders = (unsigned long)capacity / (heads * sectors);
2662         }
2663         ip[0] = heads;
2664         ip[1] = sectors;
2665         ip[2] = cylinders;
2666
2667         return 0;
2668 }
2669
2670 static void atp870u_remove(struct pci_dev *pdev)
2671 {
2672         struct atp_unit *atp_dev = pci_get_drvdata(pdev);
2673         struct Scsi_Host *pshost = atp_dev->host;
2674
2675         scsi_remove_host(pshost);
2676         free_irq(pshost->irq, pshost);
2677         release_region(pshost->io_port, pshost->n_io_port);
2678         atp870u_free_tables(pshost);
2679         scsi_host_put(pshost);
2680         pci_set_drvdata(pdev, NULL);
2681 }
2682
2683 MODULE_LICENSE("GPL");
2684
2685 static struct scsi_host_template atp870u_template = {
2686         .module                 = THIS_MODULE,
2687         .name                   = "atp870u",
2688         .proc_name              = "atp870u",
2689         .proc_info              = atp870u_proc_info,
2690         .info                   = atp870u_info,
2691         .queuecommand           = atp870u_queuecommand,
2692         .eh_abort_handler       = atp870u_abort,
2693         .bios_param             = atp870u_biosparam,
2694         .can_queue              = qcnt,
2695         .this_id                = 7,
2696         .sg_tablesize           = ATP870U_SCATTER,
2697         .cmd_per_lun            = ATP870U_CMDLUN,
2698         .use_clustering         = ENABLE_CLUSTERING,
2699 };
2700
2701 static struct pci_device_id atp870u_id_table[] = {
2702         { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, 0x8081)                         },
2703         { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
2704         { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
2705         { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
2706         { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S)   },
2707         { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D)   },
2708         { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
2709         { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060)       },
2710         { 0, },
2711 };
2712
2713 MODULE_DEVICE_TABLE(pci, atp870u_id_table);
2714
2715 static struct pci_driver atp870u_driver = {     
2716         .id_table       = atp870u_id_table,
2717         .name           = "atp870u",
2718         .probe          = atp870u_probe,
2719         .remove         = __devexit_p(atp870u_remove),
2720 };
2721
2722 static int __init atp870u_init(void)
2723 {
2724         return pci_module_init(&atp870u_driver);
2725 }
2726
2727 static void __exit atp870u_exit(void)
2728 {
2729         pci_unregister_driver(&atp870u_driver);
2730 }
2731
2732 module_init(atp870u_init);
2733 module_exit(atp870u_exit);
2734