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