OSDN Git Service

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