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