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