Import 2.3.18pre1
[davej-history.git] / drivers / scsi / atp870u.c
blob83215d11520c36d462a638caf5f55c96d71370b5
1 /* $Id: atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $
2 * linux/kernel/atp870u.c
4 * Copyright (C) 1997 Wu Ching Chen
5 * 2.1.x update (C) 1998 Krzysztof G. Baranowski
6 *
7 * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes
8 *
9 */
11 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/types.h>
15 #include <linux/string.h>
16 #include <linux/ioport.h>
17 #include <linux/delay.h>
18 #include <linux/sched.h>
19 #include <linux/proc_fs.h>
20 #include <linux/spinlock.h>
21 #include <asm/system.h>
22 #include <asm/io.h>
23 #include <linux/pci.h>
24 #include <linux/blk.h>
25 #include "scsi.h"
26 #include "hosts.h"
29 #include "atp870u.h"
31 #include<linux/stat.h>
33 struct proc_dir_entry proc_scsi_atp870u = {
34 PROC_SCSI_ATP870U, 7, "atp870u",
35 S_IFDIR | S_IRUGO | S_IXUGO, 2
38 void mydlyu(unsigned int);
40 static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $";
43 static unsigned char admaxu=1,host_idu[2],chip_veru[2],scam_on[2],global_map[2];
44 static unsigned short int active_idu[2],wide_idu[2],sync_idu,ultra_map[2];
45 static int workingu[2]={0,0};
46 static Scsi_Cmnd *querequ[2][qcnt],*curr_req[2][16];
47 static unsigned char devspu[2][16] = {{0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
48 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20},
49 {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
50 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}};
51 static unsigned char dirctu[2][16],last_cmd[2],in_snd[2],in_int[2];
52 static unsigned char ata_cdbu[2][16];
53 static unsigned int ioportu[2]={0,0};
54 static unsigned int irqnumu[2]={0,0};
55 static unsigned short int pciportu[2];
56 static unsigned long prdaddru[2][16],tran_lenu[2][16],last_lenu[2][16];
57 static unsigned char prd_tableu[2][16][1024];
58 static unsigned char *prd_posu[2][16];
59 static unsigned char quhdu[2],quendu[2];
60 static unsigned char devtypeu[2][16] = {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
61 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
62 static struct Scsi_Host * atp_host[2]={NULL,NULL};
64 static void atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
66 unsigned long flags;
67 unsigned short int tmpcip,id;
68 unsigned char i,j,h,tarid,lun;
69 unsigned char *prd;
70 Scsi_Cmnd *workrequ;
71 unsigned int workportu,tmport;
72 unsigned long adrcntu,k;
73 int errstus;
75 for ( h=0; h < 2; h++ )
77 if ( ( irq & 0x0f ) == irqnumu[h] )
79 goto irq_numok;
82 return;
83 irq_numok:
84 in_int[h]=1;
85 workportu=ioportu[h];
86 tmport=workportu;
88 if ( workingu[h] != 0 )
90 tmport += 0x1f;
91 j=inb(tmport);
92 tmpcip=pciportu[h];
93 if ((inb(tmpcip) & 0x08) != 0)
95 tmpcip += 0x2;
96 while((inb(tmpcip) & 0x08) != 0);
98 tmpcip=pciportu[h];
99 outb(0x00,tmpcip);
100 tmport -=0x08;
101 i=inb(tmport);
102 if ((j & 0x40) == 0)
104 if ((last_cmd[h] & 0x40) == 0)
106 last_cmd[h]=0xff;
109 else
111 last_cmd[h] |= 0x40;
113 tmport -= 0x02;
114 tarid=inb(tmport);
115 tmport += 0x02;
116 if ((tarid & 0x40) != 0)
118 tarid=(tarid & 0x07) | 0x08;
120 else
122 tarid &= 0x07;
124 if ( i == 0x85 )
126 if (wide_idu[h] != 0)
128 tmport=workportu+0x1b;
129 j=inb(tmport) & 0x0e;
130 j |= 0x01;
131 outb(j,tmport);
133 if (((quhdu[h] != quendu[h]) || (last_cmd[h] != 0xff)) &&
134 (in_snd[h] == 0))
136 send_s870(h);
138 in_int[h]=0;
139 return;
141 if ( i == 0x21 )
143 tmport -= 0x05;
144 adrcntu=0;
145 ((unsigned char *)&adrcntu)[2]=inb(tmport++);
146 ((unsigned char *)&adrcntu)[1]=inb(tmport++);
147 ((unsigned char *)&adrcntu)[0]=inb(tmport);
148 k=last_lenu[h][tarid];
149 k -= adrcntu;
150 tran_lenu[h][tarid]= k;
151 last_lenu[h][tarid]=adrcntu;
152 tmport -= 0x04;
153 outb(0x41,tmport);
154 tmport += 0x08;
155 outb(0x08,tmport);
156 in_int[h]=0;
157 return ;
160 if ((i == 0x80) || (i == 0x8f))
162 lun=0;
163 tmport -= 0x07;
164 j=inb(tmport);
165 if ( j == 0x44 )
167 tmport += 0x0d;
168 lun=inb(tmport) & 0x07;
170 else
172 if ( j == 0x41 )
174 tmport += 0x02;
175 adrcntu=0;
176 ((unsigned char *)&adrcntu)[2]=inb(tmport++);
177 ((unsigned char *)&adrcntu)[1]=inb(tmport++);
178 ((unsigned char *)&adrcntu)[0]=inb(tmport);
179 k=last_lenu[h][tarid];
180 k -= adrcntu;
181 tran_lenu[h][tarid]= k;
182 last_lenu[h][tarid]=adrcntu;
183 tmport += 0x04;
184 outb(0x08,tmport);
185 in_int[h]=0;
186 return ;
188 else
190 outb(0x46,tmport);
191 dirctu[h][tarid]=0x00;
192 tmport += 0x02;
193 outb(0x00,tmport++);
194 outb(0x00,tmport++);
195 outb(0x00,tmport++);
196 tmport+=0x03;
197 outb(0x08,tmport);
198 in_int[h]=0;
199 return;
202 tmport=workportu + 0x10;
203 outb(0x45,tmport);
204 tmport += 0x06;
205 tarid=inb(tmport);
206 if ((tarid & 0x10) != 0)
208 tarid=(tarid & 0x07) | 0x08;
210 else
212 tarid &= 0x07;
214 workrequ=curr_req[h][tarid];
215 tmport=workportu + 0x0f;
216 outb(lun,tmport);
217 tmport += 0x02;
218 outb(devspu[h][tarid],tmport++);
219 adrcntu=tran_lenu[h][tarid];
220 k=last_lenu[h][tarid];
221 outb(((unsigned char *)&k)[2],tmport++);
222 outb(((unsigned char *)&k)[1],tmport++);
223 outb(((unsigned char *)&k)[0],tmport++);
224 j=tarid;
225 if ( tarid > 7 )
227 j = (j & 0x07) | 0x40;
229 j |= dirctu[h][tarid];
230 outb(j,tmport++);
231 outb(0x80,tmport);
232 tmport=workportu + 0x1b;
233 j=inb(tmport) & 0x0e;
234 id=1;
235 id=id << tarid;
236 if ((id & wide_idu[h]) != 0)
238 j |= 0x01;
240 outb(j,tmport);
241 if ( last_lenu[h][tarid] == 0 )
243 tmport=workportu + 0x18;
244 outb(0x08,tmport);
245 in_int[h]=0;
246 return ;
248 prd=prd_posu[h][tarid];
249 while ( adrcntu != 0 )
251 id=((unsigned short int *)(prd))[2];
252 if ( id == 0 )
254 k=0x10000;
256 else
258 k=id;
260 if ( k > adrcntu )
262 ((unsigned short int *)(prd))[2] =(unsigned short int)
263 (k - adrcntu);
264 ((unsigned long *)(prd))[0] += adrcntu;
265 adrcntu=0;
266 prd_posu[h][tarid]=prd;
268 else
270 adrcntu -= k;
271 prdaddru[h][tarid] += 0x08;
272 prd += 0x08;
273 if ( adrcntu == 0 )
275 prd_posu[h][tarid]=prd;
279 tmpcip=pciportu[h] + 0x04;
280 outl(prdaddru[h][tarid],tmpcip);
281 tmpcip -= 0x02;
282 outb(0x06,tmpcip);
283 outb(0x00,tmpcip);
284 tmpcip -= 0x02;
285 tmport=workportu + 0x18;
286 if ( dirctu[h][tarid] != 0 )
288 outb(0x08,tmport);
289 outb(0x01,tmpcip);
290 in_int[h]=0;
291 return;
293 outb(0x08,tmport);
294 outb(0x09,tmpcip);
295 in_int[h]=0;
296 return;
299 workrequ=curr_req[h][tarid];
300 if ( i == 0x42 )
302 errstus=0x02;
303 workrequ->result=errstus;
304 goto go_42;
306 if ( i == 0x16 )
308 errstus=0;
309 tmport -= 0x08;
310 errstus=inb(tmport);
311 workrequ->result=errstus;
312 /* if ( errstus == 0x02 )
314 tmport +=0x10;
315 if ((inb(tmport) & 0x80) != 0)
317 printk(" autosense ");
319 tmport -=0x09;
320 outb(0,tmport);
321 tmport=workportu+0x3a;
322 outb((unsigned char)(inb(tmport) | 0x10),tmport);
323 tmport -= 0x39;
325 outb(0x08,tmport++);
326 outb(0x7f,tmport++);
327 outb(0x03,tmport++);
328 outb(0x00,tmport++);
329 outb(0x00,tmport++);
330 outb(0x00,tmport++);
331 outb(0x0e,tmport++);
332 outb(0x00,tmport);
333 tmport+=0x07;
334 outb(0x00,tmport++);
335 tmport++;
336 outb(devspu[h][workrequ->target],tmport++);
337 outb(0x00,tmport++);
338 outb(0x00,tmport++);
339 outb(0x0e,tmport++);
340 tmport+=0x03;
341 outb(0x09,tmport);
342 tmport+=0x07;
343 i=0;
344 adrcntu=(unsigned long)(&workrequ->sense_buffer[0]);
345 get_sens:
346 j=inb(tmport);
347 if ((j & 0x01) != 0)
349 tmport-=0x06;
350 (unsigned char)(((caddr_t) adrcntu)[i++])=inb(tmport);
351 tmport+=0x06;
352 goto get_sens;
354 if ((j & 0x80) == 0)
356 goto get_sens;
358 if ((j & 0x40) == 0)
360 tmport-=0x08;
361 i=inb(tmport);
363 tmport=workportu+0x3a;
364 outb((unsigned char)(inb(tmport) & 0xef),tmport);
365 tmport=workportu+0x01;
366 outb(0x2c,tmport);
367 tmport += 0x15;
368 outb(0x80,tmport);
369 } */
370 go_42:
371 spin_lock_irqsave(&io_request_lock, flags);
372 (*workrequ->scsi_done)(workrequ);
373 spin_unlock_irqrestore(&io_request_lock, flags);
375 curr_req[h][tarid]=0;
376 workingu[h]--;
377 if (wide_idu[h] != 0)
379 tmport=workportu+0x1b;
380 j=inb(tmport) & 0x0e;
381 j |= 0x01;
382 outb(j,tmport);
384 if (((last_cmd[h] != 0xff) || (quhdu[h] != quendu[h])) &&
385 (in_snd[h] == 0))
387 send_s870(h);
389 in_int[h]=0;
390 return;
392 if ( i == 0x4f )
394 i=0x89;
396 i &= 0x0f;
397 if ( i == 0x09 )
399 tmpcip=tmpcip+4;
400 outl(prdaddru[h][tarid],tmpcip);
401 tmpcip=tmpcip-2;
402 outb(0x06,tmpcip);
403 outb(0x00,tmpcip);
404 tmpcip=tmpcip-2;
405 tmport=workportu+0x10;
406 outb(0x41,tmport);
407 dirctu[h][tarid]=0x00;
408 tmport += 0x08;
409 outb(0x08,tmport);
410 outb(0x09,tmpcip);
411 in_int[h]=0;
412 return;
414 if ( i == 0x08 )
416 tmpcip=tmpcip+4;
417 outl(prdaddru[h][tarid],tmpcip);
418 tmpcip=tmpcip-2;
419 outb(0x06,tmpcip);
420 outb(0x00,tmpcip);
421 tmpcip=tmpcip-2;
422 tmport=workportu+0x10;
423 outb(0x41,tmport);
424 tmport += 0x05;
425 outb((unsigned char)(inb(tmport) | 0x20),tmport);
426 dirctu[h][tarid]=0x20;
427 tmport += 0x03;
428 outb(0x08,tmport);
429 outb(0x01,tmpcip);
430 in_int[h]=0;
431 return;
433 tmport -= 0x07;
434 if ( i == 0x0a )
436 outb(0x30,tmport);
438 else
440 outb(0x46,tmport);
442 dirctu[h][tarid]=0x00;
443 tmport += 0x02;
444 outb(0x00,tmport++);
445 outb(0x00,tmport++);
446 outb(0x00,tmport++);
447 tmport+=0x03;
448 outb(0x08,tmport);
449 in_int[h]=0;
450 return;
452 else
454 tmport=workportu+0x17;
455 inb(tmport);
456 workingu[h]=0;
457 in_int[h]=0;
458 return;
462 int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done)(Scsi_Cmnd *))
464 unsigned char i,h;
465 unsigned long flags;
466 unsigned short int m;
467 unsigned int tmport;
469 for( h=0; h <= admaxu; h++ )
471 if ( req_p->host == atp_host[h] )
473 goto host_ok;
476 return 0;
477 host_ok:
478 if ( req_p->channel != 0 )
480 req_p->result = 0x00040000;
481 done(req_p);
482 return 0;
484 m=1;
485 m= m << req_p->target;
486 if ( ( m & active_idu[h] ) == 0 )
488 req_p->result = 0x00040000;
489 done(req_p);
490 return 0;
492 if (done)
494 req_p->scsi_done = done;
496 else
498 printk("atp870u_queuecommand: done can't be NULL\n");
499 req_p->result = 0;
500 done(req_p);
501 return 0;
503 quendu[h]++;
504 if ( quendu[h] >= qcnt )
506 quendu[h]=0;
508 wait_que_empty:
509 if ( quhdu[h] == quendu[h] )
511 goto wait_que_empty;
513 save_flags(flags);
514 cli();
515 querequ[h][quendu[h]]=req_p;
516 if ( quendu[h] == 0 )
518 i=qcnt-1;
520 else
522 i=quendu[h]-1;
524 tmport = ioportu[h]+0x1c;
525 restore_flags(flags);
526 if ((inb(tmport) == 0) && (in_int[h] == 0) && (in_snd[h] == 0))
528 send_s870(h);
530 return 0;
533 void mydlyu(unsigned int dlycnt )
535 unsigned int i ;
536 for ( i = 0 ; i < dlycnt ; i++ )
538 inb(0x80);
542 void send_s870(unsigned char h)
544 unsigned int tmport;
545 Scsi_Cmnd *workrequ;
546 unsigned long flags;
547 unsigned int i;
548 unsigned char j,tarid;
549 unsigned char *prd;
550 unsigned short int tmpcip,w;
551 unsigned long l,bttl;
552 unsigned int workportu;
553 struct scatterlist * sgpnt;
555 save_flags(flags);
556 cli();
557 if ( in_snd[h] != 0 )
559 restore_flags(flags);
560 return;
562 in_snd[h]=1;
563 if ((last_cmd[h] != 0xff) && ((last_cmd[h] & 0x40) != 0))
565 last_cmd[h] &= 0x0f;
566 workrequ=curr_req[h][last_cmd[h]];
567 goto cmd_subp;
569 workingu[h]++;
570 j=quhdu[h];
571 quhdu[h]++;
572 if ( quhdu[h] >= qcnt )
574 quhdu[h]=0;
576 workrequ=querequ[h][quhdu[h]];
577 if ( curr_req[h][workrequ->target] == 0 )
579 curr_req[h][workrequ->target]=workrequ;
580 last_cmd[h]=workrequ->target;
581 goto cmd_subp;
583 quhdu[h]=j;
584 workingu[h]--;
585 in_snd[h]=0;
586 restore_flags(flags);
587 return ;
588 cmd_subp:
589 workportu=ioportu[h];
590 tmport=workportu+0x1f;
591 if ((inb(tmport) & 0xb0) != 0)
593 goto abortsnd;
595 tmport=workportu+0x1c;
596 if ( inb(tmport) == 0 )
598 goto oktosend;
600 abortsnd:
601 last_cmd[h] |= 0x40;
602 in_snd[h]=0;
603 restore_flags(flags);
604 return;
605 oktosend:
606 memcpy(&ata_cdbu[h][0], &workrequ->cmnd[0], workrequ->cmd_len);
607 if ( ata_cdbu[h][0] == 0x25 )
609 if ( workrequ->request_bufflen > 8 )
611 workrequ->request_bufflen=0x08;
614 if ( ata_cdbu[h][0] == 0x12 )
616 if ( workrequ->request_bufflen > 0x24 )
618 workrequ->request_bufflen = 0x24;
619 ata_cdbu[h][4]=0x24;
623 tmport=workportu+0x1b;
624 j=inb(tmport) & 0x0e;
625 tarid=workrequ->target;
626 w=1;
627 w = w << tarid;
628 if ((w & wide_idu[h]) != 0)
630 j |= 0x01;
632 outb(j,tmport);
633 tmport=workportu;
634 outb(workrequ->cmd_len,tmport++);
635 outb(0x2c,tmport++);
636 outb(0xcf,tmport++);
637 for ( i=0 ; i < workrequ->cmd_len ; i++ )
639 outb(ata_cdbu[h][i],tmport++);
641 tmport=workportu+0x0f;
642 outb(0x00,tmport);
643 tmport+=0x02;
644 outb(devspu[h][tarid],tmport++);
645 if (workrequ->use_sg)
648 l=0;
649 sgpnt = (struct scatterlist *) workrequ->request_buffer;
650 for(i=0; i<workrequ->use_sg; i++)
652 if(sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER)
654 panic("Foooooooood fight!");
656 l += sgpnt[i].length;
659 else
661 l=workrequ->request_bufflen;
663 outb((unsigned char)(((unsigned char *)(&l))[2]),tmport++);
664 outb((unsigned char)(((unsigned char *)(&l))[1]),tmport++);
665 outb((unsigned char)(((unsigned char *)(&l))[0]),tmport++);
666 j=tarid;
667 last_lenu[h][j]=l;
668 tran_lenu[h][j]=0;
669 if ((j & 0x08) != 0)
671 j=(j & 0x07) | 0x40;
673 if ((ata_cdbu[h][0] == 0x0a) || (ata_cdbu[h][0] == 0x2a) ||
674 (ata_cdbu[h][0] == 0xaa) || (ata_cdbu[h][0] == 0x15))
676 outb((unsigned char)(j | 0x20),tmport++);
678 else
680 outb(j,tmport++);
682 outb(0x80,tmport);
683 tmport=workportu + 0x1c;
684 dirctu[h][tarid]=0;
685 if ( l == 0 )
687 if ( inb(tmport) == 0 )
689 tmport=workportu+0x18;
690 outb(0x08,tmport);
692 else
694 last_cmd[h] |= 0x40;
696 in_snd[h]=0;
697 restore_flags(flags);
698 return;
700 tmpcip=pciportu[h];
701 prd=&prd_tableu[h][tarid][0];
702 prd_posu[h][tarid]=prd;
703 if (workrequ->use_sg)
705 sgpnt = (struct scatterlist *) workrequ->request_buffer;
706 i=0;
707 for(j=0; j<workrequ->use_sg; j++)
709 (unsigned long)(((unsigned long *)(prd))[i >> 1])=(unsigned long)sgpnt[j].address;
710 (unsigned short int)(((unsigned short int *)(prd))[i+2])=sgpnt[j].length;
711 (unsigned short int)(((unsigned short int *)(prd))[i+3])=0;
712 i +=0x04;
714 (unsigned short int)(((unsigned short int *)(prd))[i-1])=0x8000;
716 else
718 bttl=(unsigned long)workrequ->request_buffer;
719 l=workrequ->request_bufflen;
720 i=0;
721 while ( l > 0x10000 )
723 (unsigned short int)(((unsigned short int *)(prd))[i+3])=0x0000;
724 (unsigned short int)(((unsigned short int *)(prd))[i+2])=0x0000;
725 (unsigned long)(((unsigned long *)(prd))[i >> 1])=bttl;
726 l -= 0x10000;
727 bttl += 0x10000;
728 i += 0x04;
730 (unsigned short int)(((unsigned short int *)(prd))[i+3])=0x8000;
731 (unsigned short int)(((unsigned short int *)(prd))[i+2])=l;
732 (unsigned long)(((unsigned long *)(prd))[i >> 1])=bttl;
734 tmpcip=tmpcip+4;
735 prdaddru[h][tarid]=(unsigned long)&prd_tableu[h][tarid][0];
736 outl(prdaddru[h][tarid],tmpcip);
737 tmpcip=tmpcip-2;
738 outb(0x06,tmpcip);
739 outb(0x00,tmpcip);
740 tmpcip=tmpcip-2;
741 if ((ata_cdbu[h][0] == 0x0a) || (ata_cdbu[h][0] == 0x2a) ||
742 (ata_cdbu[h][0] == 0xaa) || (ata_cdbu[h][0] == 0x15))
744 dirctu[h][tarid]=0x20;
745 if ( inb(tmport) == 0 )
747 tmport=workportu+0x18;
748 outb(0x08,tmport);
749 outb(0x01,tmpcip);
751 else
753 last_cmd[h] |= 0x40;
755 in_snd[h]=0;
756 restore_flags(flags);
757 return;
759 if ( inb(tmport) == 0 )
761 tmport=workportu+0x18;
762 outb(0x08,tmport);
763 outb(0x09,tmpcip);
765 else
767 last_cmd[h] |= 0x40;
769 in_snd[h]=0;
770 restore_flags(flags);
771 return;
775 static void internal_done(Scsi_Cmnd * SCpnt)
777 SCpnt->SCp.Status++;
780 int atp870u_command(Scsi_Cmnd * SCpnt)
783 atp870u_queuecommand(SCpnt, internal_done);
785 SCpnt->SCp.Status = 0;
786 while (!SCpnt->SCp.Status)
787 barrier();
788 return SCpnt->result;
791 unsigned char fun_scam ( unsigned char host,unsigned short int * val )
793 unsigned int tmport ;
794 unsigned short int i,k;
795 unsigned char j;
797 tmport = ioportu[host]+0x1c;
798 outw(*val,tmport);
799 FUN_D7:
800 for ( i=0; i < 10; i++ ) /* stable >= bus settle delay(400 ns) */
802 k=inw(tmport);
803 j= (unsigned char)(k >> 8);
804 if ((k & 0x8000) != 0) /* DB7 all release? */
806 goto FUN_D7;
809 *val |= 0x4000; /* assert DB6 */
810 outw(*val,tmport);
811 *val &= 0xdfff; /* assert DB5 */
812 outw(*val,tmport);
813 FUN_D5:
814 for ( i=0; i < 10; i++ ) /* stable >= bus settle delay(400 ns) */
816 if ((inw(tmport) & 0x2000) != 0) /* DB5 all release? */
818 goto FUN_D5;
821 *val |= 0x8000; /* no DB4-0, assert DB7 */
822 *val &= 0xe0ff;
823 outw(*val,tmport);
824 *val &= 0xbfff; /* release DB6 */
825 outw(*val,tmport);
826 FUN_D6:
827 for ( i=0; i < 10; i++ ) /* stable >= bus settle delay(400 ns) */
829 if ((inw(tmport) & 0x4000) != 0) /* DB6 all release? */
831 goto FUN_D6;
835 return j;
838 void tscam( unsigned char host )
841 unsigned int tmport ;
842 unsigned char i,j,k;
843 unsigned long n;
844 unsigned short int m,assignid_map,val;
845 unsigned char mbuf[33],quintet[2];
846 static unsigned char g2q_tab[8]={ 0x38,0x31,0x32,0x2b,0x34,0x2d,0x2e,0x27 };
849 for ( i=0; i < 0x10; i++ )
851 mydlyu(0xffff);
854 tmport = ioportu[host]+1;
855 outb(0x08,tmport++);
856 outb(0x7f,tmport);
857 tmport = ioportu[host]+0x11;
858 outb(0x20,tmport);
860 if ((scam_on[host] & 0x40) == 0)
862 return;
865 m=1;
866 m <<= host_idu[host];
867 j=16;
868 if ( chip_veru[host] < 4 )
870 m |= 0xff00;
871 j=8;
873 assignid_map=m;
874 tmport = ioportu[host]+0x02;
875 outb(0x02,tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */
876 outb(0,tmport++);
877 outb(0,tmport++);
878 outb(0,tmport++);
879 outb(0,tmport++);
880 outb(0,tmport++);
881 outb(0,tmport++);
883 for ( i = 0 ; i < j ; i ++ )
885 m=1;
886 m=m<<i;
887 if ( ( m & assignid_map ) != 0 )
889 continue;
891 tmport = ioportu[host]+0x0f;
892 outb(0,tmport++);
893 tmport += 0x02;
894 outb(0,tmport++);
895 outb(0,tmport++);
896 outb(0,tmport++);
897 if ( i > 7 )
899 k=(i & 0x07) | 0x40;
901 else
903 k=i;
905 outb(k,tmport++);
906 tmport = ioportu[host]+0x1b;
907 if ( chip_veru[host] == 4 )
909 outb((unsigned char)((inb(tmport) & 0x0e) | 0x01),tmport);
911 else
913 outb((unsigned char)(inb(tmport) & 0x0e),tmport);
915 wait_rdyok:
916 tmport = ioportu[host]+0x18;
917 outb(0x09,tmport);
918 tmport += 0x07;
920 while ((inb(tmport) & 0x80) == 0x00);
921 tmport -= 0x08;
922 k=inb(tmport);
923 if ( k != 0x16 )
925 if ((k == 0x85) || (k == 0x42))
927 continue;
929 tmport = ioportu[host]+0x10;
930 outb(0x41,tmport);
931 goto wait_rdyok;
933 assignid_map |= m;
936 tmport = ioportu[host]+0x02;
937 outb(0x7f,tmport);
938 tmport = ioportu[host]+0x1b;
939 outb(0x02,tmport);
941 outb(0,0x80);
943 val=0x0080; /* bsy */
944 tmport = ioportu[host]+0x1c;
945 outw(val,tmport);
946 val |=0x0040; /* sel */
947 outw(val,tmport);
948 val |=0x0004; /* msg */
949 outw(val,tmport);
950 inb(0x80); /* 2 deskew delay(45ns*2=90ns) */
951 val &=0x007f; /* no bsy */
952 outw(val,tmport);
953 mydlyu(0xffff); /* recommanded SCAM selection response time */
954 mydlyu(0xffff);
955 val &=0x00fb; /* after 1ms no msg */
956 outw(val,tmport);
957 wait_nomsg:
958 if ((inb(tmport) & 0x04) != 0)
960 goto wait_nomsg;
962 outb(1,0x80);
963 mydlyu(100);
964 for ( n=0; n < 0x30000; n++ )
966 if ((inb(tmport) & 0x80) != 0) /* bsy ? */
968 goto wait_io;
971 goto TCM_SYNC;
972 wait_io:
973 for ( n=0; n < 0x30000; n++ )
975 if ((inb(tmport) & 0x81) == 0x0081)
977 goto wait_io1;
980 goto TCM_SYNC;
981 wait_io1:
982 inb(0x80);
983 val |=0x8003; /* io,cd,db7 */
984 outw(val,tmport);
985 inb(0x80);
986 val &=0x00bf; /* no sel */
987 outw(val,tmport);
988 outb(2,0x80);
989 TCM_SYNC:
990 mydlyu(0x800);
991 if ((inb(tmport) & 0x80) == 0x00) /* bsy ? */
993 outw(0,tmport--);
994 outb(0,tmport);
995 tmport=ioportu[host] + 0x15;
996 outb(0,tmport);
997 tmport += 0x03;
998 outb(0x09,tmport);
999 tmport += 0x07;
1000 while ((inb(tmport) & 0x80) == 0);
1001 tmport -= 0x08;
1002 inb(tmport);
1003 return;
1006 val &= 0x00ff; /* synchronization */
1007 val |= 0x3f00;
1008 fun_scam(host,&val);
1009 outb(3,0x80);
1010 val &= 0x00ff; /* isolation */
1011 val |= 0x2000;
1012 fun_scam(host,&val);
1013 outb(4,0x80);
1014 i=8;
1015 j=0;
1016 TCM_ID:
1017 if ((inw(tmport) & 0x2000) == 0)
1019 goto TCM_ID;
1021 outb(5,0x80);
1022 val &= 0x00ff; /* get ID_STRING */
1023 val |= 0x2000;
1024 k=fun_scam(host,&val);
1025 if ((k & 0x03) == 0)
1027 goto TCM_5;
1029 mbuf[j] <<= 0x01;
1030 mbuf[j] &= 0xfe;
1031 if ((k & 0x02) != 0)
1033 mbuf[j] |= 0x01;
1035 i--;
1036 if ( i > 0 )
1038 goto TCM_ID;
1040 j++;
1041 i=8;
1042 goto TCM_ID;
1044 TCM_5: /* isolation complete.. */
1045 /* mbuf[32]=0;
1046 printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
1047 i=15;
1048 j=mbuf[0];
1049 if ((j & 0x20) != 0) /* bit5=1:ID upto 7 */
1051 i=7;
1053 if ((j & 0x06) == 0) /* IDvalid? */
1055 goto G2Q5;
1057 k=mbuf[1];
1058 small_id:
1059 m=1;
1060 m <<= k;
1061 if ((m & assignid_map) == 0)
1063 goto G2Q_QUIN;
1065 if ( k > 0 )
1067 k--;
1068 goto small_id;
1070 G2Q5: /* srch from max acceptable ID# */
1071 k=i; /* max acceptable ID# */
1072 G2Q_LP:
1073 m=1;
1074 m <<= k;
1075 if ((m & assignid_map) == 0)
1077 goto G2Q_QUIN;
1079 if ( k > 0 )
1081 k--;
1082 goto G2Q_LP;
1084 G2Q_QUIN: /* k=binID#, */
1085 assignid_map |= m;
1086 if ( k < 8 )
1088 quintet[0]=0x38; /* 1st dft ID<8 */
1090 else
1092 quintet[0]=0x31; /* 1st ID>=8 */
1094 k &= 0x07;
1095 quintet[1]=g2q_tab[k];
1097 val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */
1098 m=quintet[0] << 8;
1099 val |= m;
1100 fun_scam(host,&val);
1101 val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */
1102 m=quintet[1] << 8;
1103 val |= m;
1104 fun_scam(host,&val);
1106 goto TCM_SYNC;
1110 void is870(unsigned long host,unsigned int wkport )
1112 unsigned int tmport ;
1113 unsigned char i,j,k,rmb;
1114 unsigned short int m;
1115 static unsigned char mbuf[512];
1116 static unsigned char satn[9] = { 0,0,0,0,0,0,0,6,6 };
1117 static unsigned char inqd[9] = { 0x12,0,0,0,0x24,0,0,0x24,6 };
1118 static unsigned char synn[6] = { 0x80,1,3,1,0x19,0x0e };
1119 static unsigned char synu[6] = { 0x80,1,3,1,0x0c,0x0e };
1120 static unsigned char synw[6] = { 0x80,1,3,1,0x0c,0x07 };
1121 static unsigned char wide[6] = { 0x80,1,2,3,1,0 };
1123 sync_idu=0;
1124 tmport=wkport+0x3a;
1125 outb((unsigned char)(inb(tmport) | 0x10),tmport);
1127 for ( i = 0 ; i < 16 ; i ++ )
1129 if ((chip_veru[host] != 4) && (i > 7))
1131 break;
1133 m=1;
1134 m=m<<i;
1135 if ( ( m & active_idu[host] ) != 0 )
1137 continue;
1139 if ( i == host_idu[host] )
1141 printk(" ID: %2d Host Adapter\n",host_idu[host]);
1142 continue;
1144 if ( chip_veru[host] == 4 )
1146 tmport=wkport+0x1b;
1147 j=(inb(tmport) & 0x0e) | 0x01;
1148 outb(j,tmport);
1150 tmport=wkport+1;
1151 outb(0x08,tmport++);
1152 outb(0x7f,tmport++);
1153 outb(satn[0],tmport++);
1154 outb(satn[1],tmport++);
1155 outb(satn[2],tmport++);
1156 outb(satn[3],tmport++);
1157 outb(satn[4],tmport++);
1158 outb(satn[5],tmport++);
1159 tmport+=0x06;
1160 outb(0,tmport);
1161 tmport+=0x02;
1162 outb(devspu[host][i],tmport++);
1163 outb(0,tmport++);
1164 outb(satn[6],tmport++);
1165 outb(satn[7],tmport++);
1166 j=i;
1167 if ((j & 0x08) != 0)
1169 j=(j & 0x07) | 0x40;
1171 outb(j,tmport);
1172 tmport+=0x03;
1173 outb(satn[8],tmport);
1174 tmport+=0x07;
1176 while ((inb(tmport) & 0x80) == 0x00);
1177 tmport-=0x08;
1178 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
1180 continue;
1182 while ( inb(tmport) != 0x8e );
1183 active_idu[host] |= m;
1185 tmport=wkport+0x10;
1186 outb(0x30,tmport);
1187 tmport=wkport+0x04;
1188 outb(0x00,tmport);
1190 phase_cmd:
1191 tmport=wkport+0x18;
1192 outb(0x08,tmport);
1193 tmport+=0x07;
1194 while ((inb(tmport) & 0x80) == 0x00);
1195 tmport-=0x08;
1196 j=inb(tmport);
1197 if ( j != 0x16 )
1199 tmport=wkport+0x10;
1200 outb(0x41,tmport);
1201 goto phase_cmd;
1203 sel_ok:
1204 tmport=wkport+3;
1205 outb(inqd[0],tmport++);
1206 outb(inqd[1],tmport++);
1207 outb(inqd[2],tmport++);
1208 outb(inqd[3],tmport++);
1209 outb(inqd[4],tmport++);
1210 outb(inqd[5],tmport);
1211 tmport+=0x07;
1212 outb(0,tmport);
1213 tmport+=0x02;
1214 outb(devspu[host][i],tmport++);
1215 outb(0,tmport++);
1216 outb(inqd[6],tmport++);
1217 outb(inqd[7],tmport++);
1218 tmport+=0x03;
1219 outb(inqd[8],tmport);
1220 tmport+=0x07;
1221 while ((inb(tmport) & 0x80) == 0x00);
1222 tmport-=0x08;
1223 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
1225 continue;
1227 while ( inb(tmport) != 0x8e );
1228 if ( chip_veru[host] == 4 )
1230 tmport=wkport+0x1b;
1231 j=inb(tmport) & 0x0e;
1232 outb(j,tmport);
1234 tmport=wkport+0x18;
1235 outb(0x08,tmport);
1236 tmport += 0x07;
1237 j=0;
1238 rd_inq_data:
1239 k=inb(tmport);
1240 if ((k & 0x01) != 0 )
1242 tmport-=0x06;
1243 mbuf[j++]=inb(tmport);
1244 tmport+=0x06;
1245 goto rd_inq_data;
1247 if ((k & 0x80) == 0 )
1249 goto rd_inq_data;
1251 tmport-=0x08;
1252 j=inb(tmport);
1253 if ( j == 0x16 )
1255 goto inq_ok;
1257 tmport=wkport+0x10;
1258 outb(0x46,tmport);
1259 tmport+=0x02;
1260 outb(0,tmport++);
1261 outb(0,tmport++);
1262 outb(0,tmport++);
1263 tmport+=0x03;
1264 outb(0x08,tmport);
1265 tmport+=0x07;
1266 while ((inb(tmport) & 0x80) == 0x00);
1267 tmport-=0x08;
1268 if (inb(tmport) != 0x16)
1270 goto sel_ok;
1272 inq_ok:
1273 mbuf[36]=0;
1274 printk(" ID: %2d %s\n",i,&mbuf[8]);
1275 devtypeu[host][i]=mbuf[0];
1276 rmb=mbuf[1];
1277 if ( chip_veru[host] != 4 )
1279 goto not_wide;
1281 if ((mbuf[7] & 0x60) == 0)
1283 goto not_wide;
1285 if ((global_map[host] & 0x20) == 0)
1287 goto not_wide;
1289 tmport=wkport+0x1b;
1290 j=(inb(tmport) & 0x0e) | 0x01;
1291 outb(j,tmport);
1292 tmport=wkport+3;
1293 outb(satn[0],tmport++);
1294 outb(satn[1],tmport++);
1295 outb(satn[2],tmport++);
1296 outb(satn[3],tmport++);
1297 outb(satn[4],tmport++);
1298 outb(satn[5],tmport++);
1299 tmport+=0x06;
1300 outb(0,tmport);
1301 tmport+=0x02;
1302 outb(devspu[host][i],tmport++);
1303 outb(0,tmport++);
1304 outb(satn[6],tmport++);
1305 outb(satn[7],tmport++);
1306 tmport+=0x03;
1307 outb(satn[8],tmport);
1308 tmport+=0x07;
1310 while ((inb(tmport) & 0x80) == 0x00);
1311 tmport-=0x08;
1312 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
1314 continue;
1316 while ( inb(tmport) != 0x8e );
1317 try_wide:
1318 j=0;
1319 tmport=wkport+0x14;
1320 outb(0x05,tmport);
1321 tmport += 0x04;
1322 outb(0x20,tmport);
1323 tmport+=0x07;
1325 while ((inb(tmport) & 0x80) == 0 )
1327 if ((inb(tmport) & 0x01) != 0 )
1329 tmport-=0x06;
1330 outb(wide[j++],tmport);
1331 tmport+=0x06;
1334 tmport-=0x08;
1335 while ((inb(tmport) & 0x80) == 0x00);
1336 j=inb(tmport) & 0x0f;
1337 if ( j == 0x0f )
1339 goto widep_in;
1341 if ( j == 0x0a )
1343 goto widep_cmd;
1345 if ( j == 0x0e )
1347 goto try_wide;
1349 continue;
1350 widep_out:
1351 tmport=wkport+0x18;
1352 outb(0x20,tmport);
1353 tmport+=0x07;
1354 while ((inb(tmport) & 0x80) == 0 )
1356 if ((inb(tmport) & 0x01) != 0 )
1358 tmport-=0x06;
1359 outb(0,tmport);
1360 tmport+=0x06;
1363 tmport-=0x08;
1364 j=inb(tmport) & 0x0f;
1365 if ( j == 0x0f )
1367 goto widep_in;
1369 if ( j == 0x0a )
1371 goto widep_cmd;
1373 if ( j == 0x0e )
1375 goto widep_out;
1377 continue;
1378 widep_in:
1379 tmport=wkport+0x14;
1380 outb(0xff,tmport);
1381 tmport += 0x04;
1382 outb(0x20,tmport);
1383 tmport+=0x07;
1384 k=0;
1385 widep_in1:
1386 j=inb(tmport);
1387 if ((j & 0x01) != 0)
1389 tmport-=0x06;
1390 mbuf[k++]=inb(tmport);
1391 tmport+=0x06;
1392 goto widep_in1;
1394 if ((j & 0x80) == 0x00)
1396 goto widep_in1;
1398 tmport-=0x08;
1399 j=inb(tmport) & 0x0f;
1400 if ( j == 0x0f )
1402 goto widep_in;
1404 if ( j == 0x0a )
1406 goto widep_cmd;
1408 if ( j == 0x0e )
1410 goto widep_out;
1412 continue;
1413 widep_cmd:
1414 tmport=wkport+0x10;
1415 outb(0x30,tmport);
1416 tmport=wkport+0x14;
1417 outb(0x00,tmport);
1418 tmport+=0x04;
1419 outb(0x08,tmport);
1420 tmport+=0x07;
1421 while ((inb(tmport) & 0x80) == 0x00);
1422 tmport-=0x08;
1423 j=inb(tmport);
1424 if ( j != 0x16 )
1426 if ( j == 0x4e )
1428 goto widep_out;
1430 continue;
1432 if ( mbuf[0] != 0x01 )
1434 goto not_wide;
1436 if ( mbuf[1] != 0x02 )
1438 goto not_wide;
1440 if ( mbuf[2] != 0x03 )
1442 goto not_wide;
1444 if ( mbuf[3] != 0x01 )
1446 goto not_wide;
1448 m=1;
1449 m = m << i;
1450 wide_idu[host] |= m;
1451 not_wide:
1452 if ((devtypeu[host][i] == 0x00) || (devtypeu[host][i] == 0x07))
1454 goto set_sync;
1456 continue;
1457 set_sync:
1458 tmport=wkport+0x1b;
1459 j=inb(tmport) & 0x0e;
1460 if ((m & wide_idu[host]) != 0 )
1462 j |= 0x01;
1464 outb(j,tmport);
1465 tmport=wkport+3;
1466 outb(satn[0],tmport++);
1467 outb(satn[1],tmport++);
1468 outb(satn[2],tmport++);
1469 outb(satn[3],tmport++);
1470 outb(satn[4],tmport++);
1471 outb(satn[5],tmport++);
1472 tmport+=0x06;
1473 outb(0,tmport);
1474 tmport+=0x02;
1475 outb(devspu[host][i],tmport++);
1476 outb(0,tmport++);
1477 outb(satn[6],tmport++);
1478 outb(satn[7],tmport++);
1479 tmport+=0x03;
1480 outb(satn[8],tmport);
1481 tmport+=0x07;
1483 while ((inb(tmport) & 0x80) == 0x00);
1484 tmport-=0x08;
1485 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
1487 continue;
1489 while ( inb(tmport) != 0x8e);
1490 try_sync:
1491 j=0;
1492 tmport=wkport+0x14;
1493 outb(0x06,tmport);
1494 tmport += 0x04;
1495 outb(0x20,tmport);
1496 tmport+=0x07;
1498 while ((inb(tmport) & 0x80) == 0 )
1500 if ((inb(tmport) & 0x01) != 0 )
1502 tmport-=0x06;
1503 if ( rmb != 0 )
1505 outb(synn[j++],tmport);
1507 else
1509 if ((m & wide_idu[host]) != 0)
1511 outb(synw[j++],tmport);
1513 else
1515 if ((m & ultra_map[host]) != 0)
1517 outb(synu[j++],tmport);
1519 else
1521 outb(synn[j++],tmport);
1525 tmport+=0x06;
1528 tmport-=0x08;
1529 while ((inb(tmport) & 0x80) == 0x00);
1530 j=inb(tmport) & 0x0f;
1531 if ( j == 0x0f )
1533 goto phase_ins;
1535 if ( j == 0x0a )
1537 goto phase_cmds;
1539 if ( j == 0x0e )
1541 goto try_sync;
1543 continue;
1544 phase_outs:
1545 tmport=wkport+0x18;
1546 outb(0x20,tmport);
1547 tmport+=0x07;
1548 while ((inb(tmport) & 0x80) == 0x00)
1550 if ((inb(tmport) & 0x01) != 0x00)
1552 tmport-=0x06;
1553 outb(0x00,tmport);
1554 tmport+=0x06;
1557 tmport-=0x08;
1558 j=inb(tmport);
1559 if ( j == 0x85 )
1561 goto tar_dcons;
1563 j &= 0x0f;
1564 if ( j == 0x0f )
1566 goto phase_ins;
1568 if ( j == 0x0a )
1570 goto phase_cmds;
1572 if ( j == 0x0e )
1574 goto phase_outs;
1576 continue;
1577 phase_ins:
1578 tmport=wkport+0x14;
1579 outb(0xff,tmport);
1580 tmport += 0x04;
1581 outb(0x20,tmport);
1582 tmport+=0x07;
1583 k=0;
1584 phase_ins1:
1585 j=inb(tmport);
1586 if ((j & 0x01) != 0x00)
1588 tmport-=0x06;
1589 mbuf[k++]=inb(tmport);
1590 tmport+=0x06;
1591 goto phase_ins1;
1593 if ((j & 0x80) == 0x00)
1595 goto phase_ins1;
1597 tmport-=0x08;
1598 while ((inb(tmport) & 0x80) == 0x00);
1599 j=inb(tmport);
1600 if ( j == 0x85 )
1602 goto tar_dcons;
1604 j &= 0x0f;
1605 if ( j == 0x0f )
1607 goto phase_ins;
1609 if ( j == 0x0a )
1611 goto phase_cmds;
1613 if ( j == 0x0e )
1615 goto phase_outs;
1617 continue;
1618 phase_cmds:
1619 tmport=wkport+0x10;
1620 outb(0x30,tmport);
1621 tar_dcons:
1622 tmport=wkport+0x14;
1623 outb(0x00,tmport);
1624 tmport+=0x04;
1625 outb(0x08,tmport);
1626 tmport+=0x07;
1627 while ((inb(tmport) & 0x80) == 0x00);
1628 tmport-=0x08;
1629 j=inb(tmport);
1630 if ( j != 0x16 )
1632 continue;
1634 if ( mbuf[0] != 0x01 )
1636 continue;
1638 if ( mbuf[1] != 0x03 )
1640 continue;
1642 if ( mbuf[4] == 0x00 )
1644 continue;
1646 if ( mbuf[3] > 0x64 )
1648 continue;
1650 if ( mbuf[4] > 0x0c )
1652 mbuf[4]=0x0c;
1654 devspu[host][i] = mbuf[4];
1655 if ((mbuf[3] < 0x0d) && (rmb == 0))
1657 j=0xa0;
1658 goto set_syn_ok;
1660 if ( mbuf[3] < 0x1a )
1662 j=0x20;
1663 goto set_syn_ok;
1665 if ( mbuf[3] < 0x33 )
1667 j=0x40;
1668 goto set_syn_ok;
1670 if ( mbuf[3] < 0x4c )
1672 j=0x50;
1673 goto set_syn_ok;
1675 j=0x60;
1676 set_syn_ok:
1677 devspu[host][i] = (devspu[host][i] & 0x0f) | j;
1679 tmport=wkport+0x3a;
1680 outb((unsigned char)(inb(tmport) & 0xef),tmport);
1683 /* return non-zero on detection */
1684 int atp870u_detect(Scsi_Host_Template * tpnt)
1686 unsigned char irq,h,k;
1687 unsigned long flags;
1688 unsigned int base_io,error,tmport;
1689 unsigned short index = 0;
1690 unsigned char pci_bus[3], pci_device_fn[3], chip_ver[3],host_id;
1691 struct Scsi_Host * shpnt = NULL;
1692 int count = 0;
1693 static unsigned short devid[7]={0x8002,0x8010,0x8020,0x8030,0x8040,0x8050,0};
1694 static struct pci_dev *pdev = NULL, *acard_pdev[3];
1696 printk("aec671x_detect: \n");
1697 if (!pci_present())
1699 printk(" NO BIOS32 SUPPORT.\n");
1700 return count;
1703 tpnt->proc_dir = &proc_scsi_atp870u;
1705 for ( h = 0 ; h < 2 ; h++ )
1707 active_idu[h]=0;
1708 wide_idu[h]=0;
1709 host_idu[h]=0x07;
1710 quhdu[h]=0;
1711 quendu[h]=0;
1712 pci_bus[h]=0;
1713 pci_device_fn[h]=0xff;
1714 chip_ver[h]=0;
1715 last_cmd[h]=0xff;
1716 in_snd[h]=0;
1717 in_int[h]=0;
1718 for ( k = 0 ; k < qcnt ; k++ )
1720 querequ[h][k]=0;
1722 for ( k = 0 ; k < 16 ; k++ )
1724 curr_req[h][k]=0;
1727 h=0;
1728 while ( devid[h] != 0 )
1730 pdev = pci_find_device(0x1191,devid[h],pdev);
1731 if (pdev == NULL) {
1732 h++;
1733 index=0;
1734 continue;
1736 chip_ver[2]=0;
1738 /* To avoid messing with the things below... */
1739 acard_pdev[2] = pdev;
1740 pci_device_fn[2] = pdev->devfn;
1741 pci_bus[2] = pdev->bus->number;
1743 if ( devid[h] == 0x8002 )
1745 error = pci_read_config_byte(pdev,0x08,&chip_ver[2]);
1746 if ( chip_ver[2] < 2 )
1748 goto nxt_devfn;
1751 if ( devid[h] == 0x8010 )
1753 chip_ver[2]=0x04;
1755 if ( pci_device_fn[2] < pci_device_fn[0] )
1757 acard_pdev[1]=acard_pdev[0];
1758 pci_bus[1]=pci_bus[0];
1759 pci_device_fn[1]=pci_device_fn[0];
1760 chip_ver[1]=chip_ver[0];
1761 acard_pdev[0]=acard_pdev[2];
1762 pci_bus[0]=pci_bus[2];
1763 pci_device_fn[0]=pci_device_fn[2];
1764 chip_ver[0]=chip_ver[2];
1766 else if ( pci_device_fn[2] < pci_device_fn[1] )
1768 acard_pdev[1]=acard_pdev[2];
1769 pci_bus[1]=pci_bus[2];
1770 pci_device_fn[1]=pci_device_fn[2];
1771 chip_ver[1]=chip_ver[2];
1773 nxt_devfn:
1774 index++;
1775 if ( index > 3 )
1777 index=0;
1778 h++;
1781 for ( h=0; h < 2; h++ )
1783 if ( pci_device_fn[h] == 0xff )
1785 return count;
1788 pdev = acard_pdev[h];
1789 pdev->devfn = pci_device_fn[h];
1790 pdev->bus->number = pci_bus[h];
1792 /* Found an atp870u/w. */
1793 error = pci_read_config_dword(pdev,0x10,&base_io);
1794 error += pci_read_config_byte(pdev,0x3c,&irq);
1795 error += pci_read_config_byte(pdev,0x49,&host_id);
1797 base_io &= 0xfffffff8;
1798 printk(" ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d IO:%x, IRQ:%d.\n"
1799 ,h,base_io,irq);
1800 ioportu[h]=base_io;
1801 pciportu[h]=base_io + 0x20;
1802 irqnumu[h]=irq;
1803 host_id &= 0x07;
1804 host_idu[h]=host_id;
1805 chip_veru[h]=chip_ver[h];
1807 tmport=base_io+0x22;
1808 scam_on[h]=inb(tmport);
1809 tmport += 0x0b;
1810 global_map[h]=inb(tmport++);
1811 ultra_map[h]=inw(tmport);
1812 if ( ultra_map[h] == 0 )
1814 scam_on[h]=0x00;
1815 global_map[h]=0x20;
1816 ultra_map[h]=0xffff;
1819 shpnt = scsi_register(tpnt,4);
1821 save_flags(flags);
1822 cli();
1823 if (request_irq(irq,atp870u_intr_handle, 0, "atp870u", NULL))
1825 printk("Unable to allocate IRQ for Acard controller.\n");
1826 goto unregister;
1829 tmport=base_io+0x3a;
1830 k=(inb(tmport) & 0xf3) | 0x10;
1831 outb(k,tmport);
1832 outb((k & 0xdf),tmport);
1833 mydlyu(0x8000);
1834 outb(k,tmport);
1835 mydlyu(0x8000);
1836 tmport=base_io;
1837 outb((host_id | 0x08),tmport);
1838 tmport += 0x18;
1839 outb(0,tmport);
1840 tmport += 0x07;
1841 while ((inb(tmport) & 0x80) == 0);
1842 tmport -= 0x08;
1843 inb(tmport);
1844 tmport = base_io +1;
1845 outb(8,tmport++);
1846 outb(0x7f,tmport);
1847 tmport = base_io + 0x11;
1848 outb(0x20,tmport);
1850 tscam(h);
1851 is870(h,base_io);
1852 tmport=base_io+0x3a;
1853 outb((inb(tmport) & 0xef),tmport);
1855 atp_host[h] = shpnt;
1856 if ( chip_ver[h] == 4 )
1858 shpnt->max_id = 16;
1860 shpnt->this_id = host_id;
1861 shpnt->unique_id = base_io;
1862 shpnt->io_port = base_io;
1863 shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */
1864 shpnt->irq = irq;
1865 restore_flags(flags);
1866 request_region(base_io, 0x40,"atp870u"); /* Register the IO ports that we use */
1867 count++;
1868 index++;
1869 continue;
1870 unregister:
1871 scsi_unregister(shpnt);
1872 restore_flags(flags);
1873 index++;
1874 continue;
1877 return count;
1880 /* The abort command does not leave the device in a clean state where
1881 it is available to be used again. Until this gets worked out, we will
1882 leave it commented out. */
1884 int atp870u_abort(Scsi_Cmnd * SCpnt)
1886 unsigned char h,j;
1887 unsigned int tmport;
1888 /* printk(" atp870u_abort: \n"); */
1889 for ( h=0; h <= admaxu; h++ )
1891 if ( SCpnt->host == atp_host[h] )
1893 goto find_adp;
1896 panic("Abort host not found !");
1897 find_adp:
1898 printk(" workingu=%x last_cmd=%x ",workingu[h],last_cmd[h]);
1899 printk(" quhdu=%x quendu=%x ",quhdu[h],quendu[h]);
1900 tmport=ioportu[h];
1901 for ( j=0; j < 0x17; j++)
1903 printk(" r%2x=%2x",j,inb(tmport++));
1905 tmport += 0x05;
1906 printk(" r1c=%2x",inb(tmport));
1907 tmport += 0x03;
1908 printk(" r1f=%2x in_snd=%2x ",inb(tmport),in_snd[h]);
1909 tmport++;
1910 printk(" r20=%2x",inb(tmport));
1911 tmport += 0x02;
1912 printk(" r22=%2x \n",inb(tmport));
1913 return (SCSI_ABORT_SNOOZE);
1916 int atp870u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
1918 unsigned char h;
1920 * See if a bus reset was suggested.
1922 /* printk("atp870u_reset: \n"); */
1923 for( h=0; h <= admaxu; h++ )
1925 if ( SCpnt->host == atp_host[h] )
1927 goto find_host;
1930 panic("Reset bus host not found !");
1931 find_host:
1932 /* SCpnt->result = 0x00080000;
1933 SCpnt->scsi_done(SCpnt);
1934 workingu[h]=0;
1935 quhdu[h]=0;
1936 quendu[h]=0;
1937 return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET); */
1938 return (SCSI_RESET_SNOOZE);
1941 const char *
1942 atp870u_info(struct Scsi_Host *notused)
1944 static char buffer[128];
1946 strcpy(buffer, "ACARD AEC-6710/6712 PCI Ultra/W SCSI-3 Adapter Driver V1.0 ");
1948 return buffer;
1952 atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
1954 return (-ENOSYS); /* Currently this is a no-op */
1957 #define BLS buffer + len + size
1959 atp870u_proc_info(char *buffer, char **start, off_t offset, int length,
1960 int hostno, int inout)
1962 struct Scsi_Host *HBAptr;
1963 static u8 buff[512];
1964 int i;
1965 int size = 0;
1966 int len = 0;
1967 off_t begin = 0;
1968 off_t pos = 0;
1970 HBAptr = NULL;
1971 for (i = 0; i < 2; i++)
1973 if ((HBAptr = atp_host[i]) != NULL)
1975 if (HBAptr->host_no == hostno)
1977 break;
1979 HBAptr = NULL;
1983 if (HBAptr == NULL)
1985 size += sprintf(BLS, "Can't find adapter for host number %d\n", hostno);
1986 len += size; pos = begin + len; size = 0;
1987 goto stop_output;
1990 if (inout == TRUE) /* Has data been written to the file? */
1992 return (atp870u_set_info(buffer, length, HBAptr));
1995 if (offset == 0)
1997 memset(buff, 0, sizeof(buff));
2000 size += sprintf(BLS, "ACARD AEC-671X Driver Version: 1.0\n");
2001 len += size; pos = begin + len; size = 0;
2003 size += sprintf(BLS, "\n");
2004 size += sprintf(BLS, "Adapter Configuration:\n");
2005 size += sprintf(BLS, " Base IO: %#.4lx\n", HBAptr->io_port);
2006 size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq);
2007 len += size; pos = begin + len; size = 0;
2009 stop_output:
2010 *start = buffer + (offset - begin); /* Start of wanted data */
2011 len -= (offset - begin); /* Start slop */
2012 if (len > length)
2014 len = length; /* Ending slop */
2017 return (len);
2020 #include "sd.h"
2022 int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int * ip)
2024 int heads, sectors, cylinders;
2026 heads = 64;
2027 sectors = 32;
2028 cylinders = disk->capacity / (heads * sectors);
2030 if ( cylinders > 1024 )
2032 heads = 255;
2033 sectors = 63;
2034 cylinders = disk->capacity / (heads * sectors);
2037 ip[0] = heads;
2038 ip[1] = sectors;
2039 ip[2] = cylinders;
2041 return 0;
2044 #ifdef MODULE
2045 Scsi_Host_Template driver_template = ATP870U;
2047 #include "scsi_module.c"
2048 #endif