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
7 * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes
9 * Wu Ching Chen : NULL pointer fixes 2000/06/02
11 * enable 32 bit fifo transfer
12 * support cdrom & remove device run ultra speed
15 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/types.h>
19 #include <linux/string.h>
20 #include <linux/ioport.h>
21 #include <linux/delay.h>
22 #include <linux/sched.h>
23 #include <linux/proc_fs.h>
24 #include <linux/spinlock.h>
25 #include <asm/system.h>
27 #include <linux/pci.h>
28 #include <linux/blk.h>
35 #include<linux/stat.h>
37 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;
44 static unsigned short int sync_idu
;
46 static unsigned int irqnumu
[2] = {0, 0};
52 unsigned long pciport
;
53 unsigned char last_cmd
;
58 unsigned char scam_on
;
59 unsigned char global_map
;
60 unsigned char chip_veru
;
61 unsigned char host_idu
;
63 unsigned short wide_idu
;
64 unsigned short active_idu
;
65 unsigned short ultra_map
;
66 unsigned char ata_cdbu
[16];
67 Scsi_Cmnd
*querequ
[qcnt
];
72 unsigned char devtypeu
;
73 unsigned long prdaddru
;
74 unsigned long tran_lenu
;
75 unsigned long last_lenu
;
76 unsigned char *prd_posu
;
77 unsigned char *prd_tableu
;
82 static struct Scsi_Host
*atp_host
[2] = {NULL
, NULL
};
83 static struct atp_unit atp_unit
[2];
85 static void atp870u_intr_handle(int irq
, void *dev_id
, struct pt_regs
*regs
)
88 unsigned short int tmpcip
, id
;
89 unsigned char i
, j
, h
, target_id
, lun
;
92 unsigned int workportu
, tmport
;
93 unsigned long adrcntu
, k
;
95 struct atp_unit
*dev
= dev_id
;
97 for (h
= 0; h
< 2; h
++) {
98 if (irq
== irqnumu
[h
]) {
105 workportu
= dev
->ioport
;
108 if (dev
->working
!= 0)
118 tmpcip
= dev
->pciport
;
119 if ((inb(tmpcip
) & 0x08) != 0)
122 for (k
=0; k
< 1000; k
++)
124 if ((inb(tmpcip
) & 0x08) == 0)
128 if ((inb(tmpcip
) & 0x01) == 0)
135 tmpcip
= dev
->pciport
;
142 if ((dev
->last_cmd
& 0x40) == 0)
144 dev
->last_cmd
= 0xff;
147 else dev
->last_cmd
|= 0x40;
150 target_id
= inb(tmport
);
154 * Remap wide devices onto id numbers
157 if ((target_id
& 0x40) != 0) {
158 target_id
= (target_id
& 0x07) | 0x08;
168 if (dev
->wide_idu
!= 0)
170 tmport
= workportu
+ 0x1b;
172 while ((inb(tmport
) & 0x01) != 0x01)
178 * Issue more commands
180 if (((dev
->quhdu
!= dev
->quendu
) || (dev
->last_cmd
!= 0xff)) &&
195 ((unsigned char *) &adrcntu
)[2] = inb(tmport
++);
196 ((unsigned char *) &adrcntu
)[1] = inb(tmport
++);
197 ((unsigned char *) &adrcntu
)[0] = inb(tmport
);
198 k
= dev
->id
[target_id
].last_lenu
;
200 dev
->id
[target_id
].tran_lenu
= k
;
201 dev
->id
[target_id
].last_lenu
= adrcntu
;
209 if ((i
== 0x80) || (i
== 0x8f))
214 if (j
== 0x44 || i
==0x80) {
216 lun
= inb(tmport
) & 0x07;
222 ((unsigned char *) &adrcntu
)[2] = inb(tmport
++);
223 ((unsigned char *) &adrcntu
)[1] = inb(tmport
++);
224 ((unsigned char *) &adrcntu
)[0] = inb(tmport
);
225 k
= dev
->id
[target_id
].last_lenu
;
227 dev
->id
[target_id
].tran_lenu
= k
;
228 dev
->id
[target_id
].last_lenu
= adrcntu
;
237 dev
->id
[target_id
].dirctu
= 0x00;
239 outb(0x00, tmport
++);
240 outb(0x00, tmport
++);
241 outb(0x00, tmport
++);
248 tmport
= workportu
+ 0x10;
251 target_id
= inb(tmport
);
253 * Remap wide identifiers
255 if ((target_id
& 0x10) != 0)
257 target_id
= (target_id
& 0x07) | 0x08;
261 workrequ
= dev
->id
[target_id
].curr_req
;
262 tmport
= workportu
+ 0x0f;
265 outb(dev
->id
[target_id
].devspu
, tmport
++);
266 adrcntu
= dev
->id
[target_id
].tran_lenu
;
267 k
= dev
->id
[target_id
].last_lenu
;
268 outb(((unsigned char *) &k
)[2], tmport
++);
269 outb(((unsigned char *) &k
)[1], tmport
++);
270 outb(((unsigned char *) &k
)[0], tmport
++);
274 j
= (j
& 0x07) | 0x40;
277 j
|= dev
->id
[target_id
].dirctu
;
281 /* enable 32 bit fifo transfer */
282 tmport
= workportu
+ 0x3a;
283 if ((dev
->ata_cdbu
[0] == 0x08) || (dev
->ata_cdbu
[0] == 0x28) ||
284 (dev
->ata_cdbu
[0] == 0x0a) || (dev
->ata_cdbu
[0] == 0x2a))
286 outb((unsigned char)((inb(tmport
) & 0xf3) | 0x08),tmport
);
290 outb((unsigned char)(inb(tmport
) & 0xf3),tmport
);
293 tmport
= workportu
+ 0x1b;
296 id
= id
<< target_id
;
298 * Is this a wide device
300 if ((id
& dev
->wide_idu
) != 0) {
304 while ((inb(tmport
) & 0x01) != j
)
309 if (dev
->id
[target_id
].last_lenu
== 0) {
310 tmport
= workportu
+ 0x18;
315 prd
= dev
->id
[target_id
].prd_posu
;
318 id
= ((unsigned short int *) (prd
))[2];
325 ((unsigned short int *) (prd
))[2] = (unsigned short int)
327 ((unsigned long *) (prd
))[0] += adrcntu
;
329 dev
->id
[target_id
].prd_posu
= prd
;
332 dev
->id
[target_id
].prdaddru
+= 0x08;
335 dev
->id
[target_id
].prd_posu
= prd
;
339 tmpcip
= dev
->pciport
+ 0x04;
340 outl(dev
->id
[target_id
].prdaddru
, tmpcip
);
345 tmport
= workportu
+ 0x18;
347 * Check transfer direction
349 if (dev
->id
[target_id
].dirctu
!= 0) {
362 * Current scsi request on this target
365 workrequ
= dev
->id
[target_id
].curr_req
;
369 workrequ
->result
= errstus
;
376 errstus
= inb(tmport
);
377 workrequ
->result
= errstus
;
380 * Complete the command
382 spin_lock_irqsave(&io_request_lock
, flags
);
383 (*workrequ
->scsi_done
) (workrequ
);
384 spin_unlock_irqrestore(&io_request_lock
, flags
);
387 * Clear it off the queue
389 dev
->id
[target_id
].curr_req
= 0;
394 if (dev
->wide_idu
!= 0) {
395 tmport
= workportu
+ 0x1b;
397 while ((inb(tmport
) & 0x01) != 0x01)
403 * If there is stuff to send and nothing going then send it
405 if (((dev
->last_cmd
!= 0xff) || (dev
->quhdu
!= dev
->quendu
)) &&
419 outl(dev
->id
[target_id
].prdaddru
, tmpcip
);
424 tmport
= workportu
+ 0x10;
426 dev
->id
[target_id
].dirctu
= 0x00;
435 outl(dev
->id
[target_id
].prdaddru
, tmpcip
);
440 tmport
= workportu
+ 0x10;
443 outb((unsigned char) (inb(tmport
) | 0x20), tmport
);
444 dev
->id
[target_id
].dirctu
= 0x20;
457 dev
->id
[target_id
].dirctu
= 0x00;
459 outb(0x00, tmport
++);
460 outb(0x00, tmport
++);
461 outb(0x00, tmport
++);
467 // tmport = workportu + 0x17;
475 int atp870u_queuecommand(Scsi_Cmnd
* req_p
, void (*done
) (Scsi_Cmnd
*))
479 unsigned short int m
;
481 struct atp_unit
*dev
;
483 for (h
= 0; h
<= admaxu
; h
++) {
484 if (req_p
->host
== atp_host
[h
]) {
490 if (req_p
->channel
!= 0) {
491 req_p
->result
= 0x00040000;
497 m
= m
<< req_p
->target
;
500 * Fake a timeout for missing targets
503 if ((m
& dev
->active_idu
) == 0) {
504 req_p
->result
= 0x00040000;
509 req_p
->scsi_done
= done
;
511 printk(KERN_WARNING
"atp870u_queuecommand: done can't be NULL\n");
520 if (dev
->quendu
>= qcnt
) {
527 if (dev
->quhdu
== dev
->quendu
) {
532 dev
->querequ
[dev
->quendu
] = req_p
;
533 if (dev
->quendu
== 0) {
538 tmport
= dev
->ioport
+ 0x1c;
539 restore_flags(flags
);
540 if ((inb(tmport
) == 0) && (dev
->in_int
== 0) && (dev
->in_snd
== 0)) {
546 void mydlyu(unsigned int dlycnt
)
549 for (i
= 0; i
< dlycnt
; i
++) {
554 void send_s870(unsigned char h
)
560 unsigned char j
, target_id
;
562 unsigned short int tmpcip
, w
;
563 unsigned long l
, bttl
;
564 unsigned int workportu
;
565 struct scatterlist
*sgpnt
;
566 struct atp_unit
*dev
= &atp_unit
[h
];
570 if (dev
->in_snd
!= 0) {
571 restore_flags(flags
);
575 if ((dev
->last_cmd
!= 0xff) && ((dev
->last_cmd
& 0x40) != 0)) {
576 dev
->last_cmd
&= 0x0f;
577 workrequ
= dev
->id
[dev
->last_cmd
].curr_req
;
578 if (workrequ
!= NULL
) /* check NULL pointer */
582 dev
->last_cmd
= 0xff;
583 if (dev
->quhdu
== dev
->quendu
)
586 restore_flags(flags
);
593 if (dev
->quhdu
>= qcnt
) {
596 workrequ
= dev
->querequ
[dev
->quhdu
];
597 if (dev
->id
[workrequ
->target
].curr_req
== 0) {
598 dev
->id
[workrequ
->target
].curr_req
= workrequ
;
599 dev
->last_cmd
= workrequ
->target
;
605 restore_flags(flags
);
608 workportu
= dev
->ioport
;
609 tmport
= workportu
+ 0x1f;
610 if ((inb(tmport
) & 0xb0) != 0) {
613 tmport
= workportu
+ 0x1c;
614 if (inb(tmport
) == 0) {
618 dev
->last_cmd
|= 0x40;
620 restore_flags(flags
);
623 memcpy(&dev
->ata_cdbu
[0], &workrequ
->cmnd
[0], workrequ
->cmd_len
);
624 if (dev
->ata_cdbu
[0] == READ_CAPACITY
) {
625 if (workrequ
->request_bufflen
> 8) {
626 workrequ
->request_bufflen
= 0x08;
629 if (dev
->ata_cdbu
[0] == 0x00) {
630 workrequ
->request_bufflen
= 0;
633 * Why limit this ????
635 if (dev
->ata_cdbu
[0] == INQUIRY
) {
636 if (workrequ
->request_bufflen
> 0x24) {
637 workrequ
->request_bufflen
= 0x24;
638 dev
->ata_cdbu
[4] = 0x24;
642 tmport
= workportu
+ 0x1b;
644 target_id
= workrequ
->target
;
651 if ((w
& dev
->wide_idu
) != 0) {
655 while ((inb(tmport
) & 0x01) != j
)
665 outb(workrequ
->cmd_len
, tmport
++);
666 outb(0x2c, tmport
++);
667 outb(0xcf, tmport
++);
668 for (i
= 0; i
< workrequ
->cmd_len
; i
++) {
669 outb(dev
->ata_cdbu
[i
], tmport
++);
671 tmport
= workportu
+ 0x0f;
672 outb(workrequ
->lun
, tmport
);
677 outb(dev
->id
[target_id
].devspu
, tmport
++);
680 * Figure out the transfer size
682 if (workrequ
->use_sg
)
685 sgpnt
= (struct scatterlist
*) workrequ
->request_buffer
;
686 for (i
= 0; i
< workrequ
->use_sg
; i
++)
688 if (sgpnt
[i
].length
== 0 || workrequ
->use_sg
> ATP870U_SCATTER
)
690 panic("Foooooooood fight!");
692 l
+= sgpnt
[i
].length
;
695 l
= workrequ
->request_bufflen
;
698 * Write transfer size
700 outb((unsigned char) (((unsigned char *) (&l
))[2]), tmport
++);
701 outb((unsigned char) (((unsigned char *) (&l
))[1]), tmport
++);
702 outb((unsigned char) (((unsigned char *) (&l
))[0]), tmport
++);
704 dev
->id
[j
].last_lenu
= l
;
705 dev
->id
[j
].tran_lenu
= 0;
709 if ((j
& 0x08) != 0) {
710 j
= (j
& 0x07) | 0x40;
713 * Check transfer direction
715 if ((dev
->ata_cdbu
[0] == WRITE_6
) || (dev
->ata_cdbu
[0] == WRITE_10
) ||
716 (dev
->ata_cdbu
[0] == WRITE_12
) || (dev
->ata_cdbu
[0] == MODE_SELECT
)) {
717 outb((unsigned char) (j
| 0x20), tmport
++);
721 outb((unsigned char)(inb(tmport
) | 0x80),tmport
);
723 tmport
= workportu
+ 0x1c;
724 dev
->id
[target_id
].dirctu
= 0;
726 if (inb(tmport
) == 0) {
727 tmport
= workportu
+ 0x18;
730 dev
->last_cmd
|= 0x40;
733 restore_flags(flags
);
736 tmpcip
= dev
->pciport
;
737 prd
= dev
->id
[target_id
].prd_tableu
;
738 dev
->id
[target_id
].prd_posu
= prd
;
741 * Now write the request list. Either as scatter/gather or as
745 if (workrequ
->use_sg
)
747 sgpnt
= (struct scatterlist
*) workrequ
->request_buffer
;
749 for (j
= 0; j
< workrequ
->use_sg
; j
++) {
750 (unsigned long) (((unsigned long *) (prd
))[i
>> 1]) = virt_to_bus(sgpnt
[j
].address
);
751 (unsigned short int) (((unsigned short int *) (prd
))[i
+ 2]) = sgpnt
[j
].length
;
752 (unsigned short int) (((unsigned short int *) (prd
))[i
+ 3]) = 0;
755 (unsigned short int) (((unsigned short int *) (prd
))[i
- 1]) = 0x8000;
758 * For a linear request write a chain of blocks
760 bttl
= virt_to_bus(workrequ
->request_buffer
);
761 l
= workrequ
->request_bufflen
;
763 while (l
> 0x10000) {
764 (unsigned short int) (((unsigned short int *) (prd
))[i
+ 3]) = 0x0000;
765 (unsigned short int) (((unsigned short int *) (prd
))[i
+ 2]) = 0x0000;
766 (unsigned long) (((unsigned long *) (prd
))[i
>> 1]) = bttl
;
771 (unsigned short int) (((unsigned short int *) (prd
))[i
+ 3]) = 0x8000;
772 (unsigned short int) (((unsigned short int *) (prd
))[i
+ 2]) = l
;
773 (unsigned long) (((unsigned long *) (prd
))[i
>> 1]) = bttl
;
776 dev
->id
[target_id
].prdaddru
= virt_to_bus(dev
->id
[target_id
].prd_tableu
);
777 outl(dev
->id
[target_id
].prdaddru
, tmpcip
);
783 tmport
= workportu
+ 0x3a;
784 if ((dev
->ata_cdbu
[0] == 0x08) || (dev
->ata_cdbu
[0] == 0x28) ||
785 (dev
->ata_cdbu
[0] == 0x0a) || (dev
->ata_cdbu
[0] == 0x2a))
787 outb((unsigned char)((inb(tmport
) & 0xf3) | 0x08),tmport
);
791 outb((unsigned char)(inb(tmport
) & 0xf3),tmport
);
793 tmport
= workportu
+ 0x1c;
795 if ((dev
->ata_cdbu
[0] == WRITE_6
) || (dev
->ata_cdbu
[0] == WRITE_10
) ||
796 (dev
->ata_cdbu
[0] == WRITE_12
) || (dev
->ata_cdbu
[0] == MODE_SELECT
))
798 dev
->id
[target_id
].dirctu
= 0x20;
799 if (inb(tmport
) == 0) {
800 tmport
= workportu
+ 0x18;
804 dev
->last_cmd
|= 0x40;
807 restore_flags(flags
);
810 if (inb(tmport
) == 0)
812 tmport
= workportu
+ 0x18;
816 dev
->last_cmd
|= 0x40;
819 restore_flags(flags
);
824 static void internal_done(Scsi_Cmnd
* SCpnt
)
829 int atp870u_command(Scsi_Cmnd
* SCpnt
)
832 atp870u_queuecommand(SCpnt
, internal_done
);
834 SCpnt
->SCp
.Status
= 0;
835 while (!SCpnt
->SCp
.Status
)
837 return SCpnt
->result
;
840 unsigned char fun_scam(struct atp_unit
*dev
, unsigned short int *val
)
843 unsigned short int i
, k
;
846 tmport
= dev
->ioport
+ 0x1c;
849 for (i
= 0; i
< 10; i
++) { /* stable >= bus settle delay(400 ns) */
851 j
= (unsigned char) (k
>> 8);
852 if ((k
& 0x8000) != 0) { /* DB7 all release? */
856 *val
|= 0x4000; /* assert DB6 */
858 *val
&= 0xdfff; /* assert DB5 */
861 for (i
= 0; i
< 10; i
++) { /* stable >= bus settle delay(400 ns) */
862 if ((inw(tmport
) & 0x2000) != 0) { /* DB5 all release? */
866 *val
|= 0x8000; /* no DB4-0, assert DB7 */
869 *val
&= 0xbfff; /* release DB6 */
872 for (i
= 0; i
< 10; i
++) { /* stable >= bus settle delay(400 ns) */
873 if ((inw(tmport
) & 0x4000) != 0) { /* DB6 all release? */
881 void tscam(unsigned char host
)
885 unsigned char i
, j
, k
;
887 unsigned short int m
, assignid_map
, val
;
888 unsigned char mbuf
[33], quintet
[2];
889 struct atp_unit
*dev
= &atp_unit
[host
];
890 static unsigned char g2q_tab
[8] = {
891 0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
895 for (i
= 0; i
< 0x10; i
++) {
899 tmport
= dev
->ioport
+ 1;
900 outb(0x08, tmport
++);
902 tmport
= dev
->ioport
+ 0x11;
905 if ((dev
->scam_on
& 0x40) == 0) {
911 if (dev
->chip_veru
< 4) {
916 tmport
= dev
->ioport
+ 0x02;
917 outb(0x02, tmport
++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */
925 for (i
= 0; i
< j
; i
++) {
928 if ((m
& assignid_map
) != 0) {
931 tmport
= dev
->ioport
+ 0x0f;
938 k
= (i
& 0x07) | 0x40;
943 tmport
= dev
->ioport
+ 0x1b;
944 if (dev
->chip_veru
== 4) {
950 tmport
= dev
->ioport
+ 0x18;
954 while ((inb(tmport
) & 0x80) == 0x00);
958 if ((k
== 0x85) || (k
== 0x42)) {
961 tmport
= dev
->ioport
+ 0x10;
968 tmport
= dev
->ioport
+ 0x02;
970 tmport
= dev
->ioport
+ 0x1b;
975 val
= 0x0080; /* bsy */
976 tmport
= dev
->ioport
+ 0x1c;
978 val
|= 0x0040; /* sel */
980 val
|= 0x0004; /* msg */
982 inb(0x80); /* 2 deskew delay(45ns*2=90ns) */
983 val
&= 0x007f; /* no bsy */
985 mydlyu(0xffff); /* recommanded SCAM selection response time */
987 val
&= 0x00fb; /* after 1ms no msg */
990 if ((inb(tmport
) & 0x04) != 0) {
995 for (n
= 0; n
< 0x30000; n
++) {
996 if ((inb(tmport
) & 0x80) != 0) { /* bsy ? */
1002 for (n
= 0; n
< 0x30000; n
++) {
1003 if ((inb(tmport
) & 0x81) == 0x0081) {
1010 val
|= 0x8003; /* io,cd,db7 */
1013 val
&= 0x00bf; /* no sel */
1018 if ((inb(tmport
) & 0x80) == 0x00) { /* bsy ? */
1021 tmport
= dev
->ioport
+ 0x15;
1026 while ((inb(tmport
) & 0x80) == 0);
1031 val
&= 0x00ff; /* synchronization */
1033 fun_scam(dev
, &val
);
1035 val
&= 0x00ff; /* isolation */
1037 fun_scam(dev
, &val
);
1042 if ((inw(tmport
) & 0x2000) == 0) {
1046 val
&= 0x00ff; /* get ID_STRING */
1048 k
= fun_scam(dev
, &val
);
1049 if ((k
& 0x03) == 0) {
1054 if ((k
& 0x02) != 0) {
1065 TCM_5
: /* isolation complete.. */
1067 printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
1070 if ((j
& 0x20) != 0) { /* bit5=1:ID upto 7 */
1073 if ((j
& 0x06) == 0) { /* IDvalid? */
1080 if ((m
& assignid_map
) == 0) {
1087 G2Q5
: /* srch from max acceptable ID# */
1088 k
= i
; /* max acceptable ID# */
1092 if ((m
& assignid_map
) == 0) {
1099 G2Q_QUIN
: /* k=binID#, */
1102 quintet
[0] = 0x38; /* 1st dft ID<8 */
1104 quintet
[0] = 0x31; /* 1st ID>=8 */
1107 quintet
[1] = g2q_tab
[k
];
1109 val
&= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */
1110 m
= quintet
[0] << 8;
1112 fun_scam(dev
, &val
);
1113 val
&= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */
1114 m
= quintet
[1] << 8;
1116 fun_scam(dev
, &val
);
1122 void is870(unsigned long host
, unsigned int wkport
)
1124 unsigned int tmport
;
1125 unsigned char i
, j
, k
, rmb
, n
;
1126 unsigned short int m
;
1127 static unsigned char mbuf
[512];
1128 static unsigned char satn
[9] = {0, 0, 0, 0, 0, 0, 0, 6, 6};
1129 static unsigned char inqd
[9] = {0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
1130 static unsigned char synn
[6] = {0x80, 1, 3, 1, 0x19, 0x0e};
1131 static unsigned char synu
[6] = {0x80, 1, 3, 1, 0x0c, 0x0e};
1132 static unsigned char synw
[6] = {0x80, 1, 3, 1, 0x0c, 0x07};
1133 static unsigned char wide
[6] = {0x80, 1, 2, 3, 1, 0};
1134 struct atp_unit
*dev
= &atp_unit
[host
];
1137 tmport
= wkport
+ 0x3a;
1138 outb((unsigned char) (inb(tmport
) | 0x10), tmport
);
1140 for (i
= 0; i
< 16; i
++) {
1141 if ((dev
->chip_veru
!= 4) && (i
> 7)) {
1146 if ((m
& dev
->active_idu
) != 0) {
1149 if (i
== dev
->host_idu
) {
1150 printk(KERN_INFO
" ID: %2d Host Adapter\n", dev
->host_idu
);
1153 tmport
= wkport
+ 0x1b;
1154 if (dev
->chip_veru
== 4) {
1161 tmport
= wkport
+ 1;
1162 outb(0x08, tmport
++);
1163 outb(0x7f, tmport
++);
1164 outb(satn
[0], tmport
++);
1165 outb(satn
[1], tmport
++);
1166 outb(satn
[2], tmport
++);
1167 outb(satn
[3], tmport
++);
1168 outb(satn
[4], tmport
++);
1169 outb(satn
[5], tmport
++);
1173 outb(dev
->id
[i
].devspu
, tmport
++);
1175 outb(satn
[6], tmport
++);
1176 outb(satn
[7], tmport
++);
1178 if ((j
& 0x08) != 0) {
1179 j
= (j
& 0x07) | 0x40;
1183 outb(satn
[8], tmport
);
1186 while ((inb(tmport
) & 0x80) == 0x00);
1188 if ((inb(tmport
) != 0x11) && (inb(tmport
) != 0x8e)) {
1191 while (inb(tmport
) != 0x8e);
1192 dev
->active_idu
|= m
;
1194 tmport
= wkport
+ 0x10;
1196 tmport
= wkport
+ 0x04;
1200 tmport
= wkport
+ 0x18;
1203 while ((inb(tmport
) & 0x80) == 0x00);
1207 tmport
= wkport
+ 0x10;
1212 tmport
= wkport
+ 3;
1213 outb(inqd
[0], tmport
++);
1214 outb(inqd
[1], tmport
++);
1215 outb(inqd
[2], tmport
++);
1216 outb(inqd
[3], tmport
++);
1217 outb(inqd
[4], tmport
++);
1218 outb(inqd
[5], tmport
);
1222 outb(dev
->id
[i
].devspu
, tmport
++);
1224 outb(inqd
[6], tmport
++);
1225 outb(inqd
[7], tmport
++);
1227 outb(inqd
[8], tmport
);
1229 while ((inb(tmport
) & 0x80) == 0x00);
1231 if ((inb(tmport
) != 0x11) && (inb(tmport
) != 0x8e)) {
1234 while (inb(tmport
) != 0x8e);
1235 tmport
= wkport
+ 0x1b;
1236 if (dev
->chip_veru
== 4) {
1239 tmport
= wkport
+ 0x18;
1245 if ((k
& 0x01) != 0) {
1247 mbuf
[j
++] = inb(tmport
);
1251 if ((k
& 0x80) == 0) {
1259 tmport
= wkport
+ 0x10;
1268 while ((inb(tmport
) & 0x80) == 0x00);
1270 if (inb(tmport
) != 0x16) {
1275 printk(KERN_INFO
" ID: %2d %s\n", i
, &mbuf
[8]);
1276 dev
->id
[i
].devtypeu
= mbuf
[0];
1279 if (dev
->chip_veru
!= 4) {
1282 if ((mbuf
[7] & 0x60) == 0) {
1285 if ((dev
->global_map
& 0x20) == 0) {
1288 tmport
= wkport
+ 0x1b;
1290 tmport
= wkport
+ 3;
1291 outb(satn
[0], tmport
++);
1292 outb(satn
[1], tmport
++);
1293 outb(satn
[2], tmport
++);
1294 outb(satn
[3], tmport
++);
1295 outb(satn
[4], tmport
++);
1296 outb(satn
[5], tmport
++);
1300 outb(dev
->id
[i
].devspu
, tmport
++);
1302 outb(satn
[6], tmport
++);
1303 outb(satn
[7], tmport
++);
1305 outb(satn
[8], tmport
);
1308 while ((inb(tmport
) & 0x80) == 0x00);
1310 if ((inb(tmport
) != 0x11) && (inb(tmport
) != 0x8e)) {
1313 while (inb(tmport
) != 0x8e);
1316 tmport
= wkport
+ 0x14;
1322 while ((inb(tmport
) & 0x80) == 0) {
1323 if ((inb(tmport
) & 0x01) != 0) {
1325 outb(wide
[j
++], tmport
);
1330 while ((inb(tmport
) & 0x80) == 0x00);
1331 j
= inb(tmport
) & 0x0f;
1343 tmport
= wkport
+ 0x18;
1346 while ((inb(tmport
) & 0x80) == 0) {
1347 if ((inb(tmport
) & 0x01) != 0) {
1354 j
= inb(tmport
) & 0x0f;
1366 tmport
= wkport
+ 0x14;
1374 if ((j
& 0x01) != 0) {
1376 mbuf
[k
++] = inb(tmport
);
1380 if ((j
& 0x80) == 0x00) {
1384 j
= inb(tmport
) & 0x0f;
1396 tmport
= wkport
+ 0x10;
1398 tmport
= wkport
+ 0x14;
1403 while ((inb(tmport
) & 0x80) == 0x00);
1412 if (mbuf
[0] != 0x01) {
1415 if (mbuf
[1] != 0x02) {
1418 if (mbuf
[2] != 0x03) {
1421 if (mbuf
[3] != 0x01) {
1428 if ((dev
->id
[i
].devtypeu
== 0x00) || (dev
->id
[i
].devtypeu
== 0x07) ||
1429 ((dev
->id
[i
].devtypeu
== 0x05) && ((n
& 0x10) != 0)))
1435 tmport
= wkport
+ 0x1b;
1437 if ((m
& dev
->wide_idu
) != 0) {
1441 tmport
= wkport
+ 3;
1442 outb(satn
[0], tmport
++);
1443 outb(satn
[1], tmport
++);
1444 outb(satn
[2], tmport
++);
1445 outb(satn
[3], tmport
++);
1446 outb(satn
[4], tmport
++);
1447 outb(satn
[5], tmport
++);
1451 outb(dev
->id
[i
].devspu
, tmport
++);
1453 outb(satn
[6], tmport
++);
1454 outb(satn
[7], tmport
++);
1456 outb(satn
[8], tmport
);
1459 while ((inb(tmport
) & 0x80) == 0x00);
1461 if ((inb(tmport
) != 0x11) && (inb(tmport
) != 0x8e)) {
1464 while (inb(tmport
) != 0x8e);
1467 tmport
= wkport
+ 0x14;
1473 while ((inb(tmport
) & 0x80) == 0) {
1474 if ((inb(tmport
) & 0x01) != 0) {
1476 if ((m
& dev
->wide_idu
) != 0) {
1477 outb(synw
[j
++], tmport
);
1479 if ((m
& dev
->ultra_map
) != 0) {
1480 outb(synu
[j
++], tmport
);
1482 outb(synn
[j
++], tmport
);
1489 while ((inb(tmport
) & 0x80) == 0x00);
1490 j
= inb(tmport
) & 0x0f;
1502 tmport
= wkport
+ 0x18;
1505 while ((inb(tmport
) & 0x80) == 0x00) {
1506 if ((inb(tmport
) & 0x01) != 0x00) {
1529 tmport
= wkport
+ 0x14;
1537 if ((j
& 0x01) != 0x00) {
1539 mbuf
[k
++] = inb(tmport
);
1543 if ((j
& 0x80) == 0x00) {
1547 while ((inb(tmport
) & 0x80) == 0x00);
1564 tmport
= wkport
+ 0x10;
1567 tmport
= wkport
+ 0x14;
1572 while ((inb(tmport
) & 0x80) == 0x00);
1578 if (mbuf
[0] != 0x01) {
1581 if (mbuf
[1] != 0x03) {
1584 if (mbuf
[4] == 0x00) {
1587 if (mbuf
[3] > 0x64) {
1590 if (mbuf
[4] > 0x0c) {
1593 dev
->id
[i
].devspu
= mbuf
[4];
1594 if ((mbuf
[3] < 0x0d) && (rmb
== 0)) {
1598 if (mbuf
[3] < 0x1a) {
1602 if (mbuf
[3] < 0x33) {
1606 if (mbuf
[3] < 0x4c) {
1612 dev
->id
[i
].devspu
= (dev
->id
[i
].devspu
& 0x0f) | j
;
1614 tmport
= wkport
+ 0x3a;
1615 outb((unsigned char) (inb(tmport
) & 0xef), tmport
);
1618 /* return non-zero on detection */
1619 int atp870u_detect(Scsi_Host_Template
* tpnt
)
1621 unsigned char irq
, h
, k
;
1622 unsigned long flags
;
1623 unsigned int base_io
, error
, tmport
;
1624 unsigned short index
= 0;
1625 struct pci_dev
*pdev
[3];
1626 unsigned char chip_ver
[3], host_id
;
1627 struct Scsi_Host
*shpnt
= NULL
;
1631 static unsigned short devid
[8] = {
1632 0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0x8060, 0
1635 printk(KERN_INFO
"aec671x_detect: \n");
1636 if (!pci_present()) {
1637 printk(KERN_INFO
" NO PCI SUPPORT.\n");
1640 tpnt
->proc_name
= "atp870u";
1642 for (h
= 0; h
< 2; h
++) {
1643 struct atp_unit
*dev
= &atp_unit
[h
];
1646 dev
->id
[k
].prd_tableu
= kmalloc(1024, GFP_KERNEL
);
1647 dev
->id
[k
].devspu
=0x20;
1648 dev
->id
[k
].devtypeu
= 0;
1649 dev
->id
[k
].curr_req
= NULL
;
1651 dev
->active_idu
= 0;
1653 dev
->host_idu
= 0x07;
1659 dev
->last_cmd
= 0xff;
1662 for (k
= 0; k
< qcnt
; k
++) {
1663 dev
->querequ
[k
] = 0;
1665 for (k
= 0; k
< 16; k
++) {
1666 dev
->id
[k
].curr_req
= 0;
1670 while (devid
[h
] != 0) {
1671 pdev
[2] = pci_find_device(0x1191, devid
[h
], pdev
[2]);
1672 if (pdev
[2] == NULL
|| pci_enable_device(pdev
[2])) {
1679 if (devid
[h
] == 0x8002) {
1680 error
= pci_read_config_byte(pdev
[2], 0x08, &chip_ver
[2]);
1681 if (chip_ver
[2] < 2) {
1685 if (devid
[h
] == 0x8010 || devid
[h
] == 0x8050) {
1688 pdev
[tmpcnt
] = pdev
[2];
1689 chip_ver
[tmpcnt
] = chip_ver
[2];
1700 for (h
= 0; h
< 2; h
++) {
1701 struct atp_unit
*dev
=&atp_unit
[h
];
1702 if (pdev
[h
]==NULL
) {
1706 /* Found an atp870u/w. */
1707 base_io
= pci_resource_start(pdev
[h
], 0);
1709 error
= pci_read_config_byte(pdev
[h
],0x49,&host_id
);
1711 base_io
&= 0xfffffff8;
1713 if (check_region(base_io
,0x40) != 0)
1717 printk(KERN_INFO
" ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d IO:%x, IRQ:%d.\n"
1719 dev
->ioport
= base_io
;
1720 dev
->pciport
= base_io
+ 0x20;
1723 dev
->host_idu
= host_id
;
1724 dev
->chip_veru
= chip_ver
[h
];
1726 tmport
= base_io
+ 0x22;
1727 dev
->scam_on
= inb(tmport
);
1729 dev
->global_map
= inb(tmport
++);
1730 dev
->ultra_map
= inw(tmport
);
1731 if (dev
->ultra_map
== 0) {
1732 dev
->scam_on
= 0x00;
1733 dev
->global_map
= 0x20;
1734 dev
->ultra_map
= 0xffff;
1736 shpnt
= scsi_register(tpnt
, 4);
1742 if (request_irq(irq
, atp870u_intr_handle
, SA_SHIRQ
, "atp870u", dev
)) {
1743 printk(KERN_ERR
"Unable to allocate IRQ for Acard controller.\n");
1747 if (chip_ver
[h
] > 0x07) /* check if atp876 chip */
1748 { /* then enable terminator */
1749 tmport
= base_io
+ 0x3e;
1753 tmport
= base_io
+ 0x3a;
1754 k
= (inb(tmport
) & 0xf3) | 0x10;
1756 outb((k
& 0xdf), tmport
);
1761 outb((host_id
| 0x08), tmport
);
1765 while ((inb(tmport
) & 0x80) == 0);
1768 tmport
= base_io
+ 1;
1771 tmport
= base_io
+ 0x11;
1776 tmport
= base_io
+ 0x3a;
1777 outb((inb(tmport
) & 0xef), tmport
);
1779 outb((inb(tmport
) | 0x20),tmport
);
1781 atp_host
[h
] = shpnt
;
1782 if (dev
->chip_veru
== 4) {
1785 shpnt
->this_id
= host_id
;
1786 shpnt
->unique_id
= base_io
;
1787 shpnt
->io_port
= base_io
;
1788 shpnt
->n_io_port
= 0x40; /* Number of bytes of I/O space used */
1790 restore_flags(flags
);
1791 request_region(base_io
, 0x40, "atp870u"); /* Register the IO ports that we use */
1796 scsi_unregister(shpnt
);
1797 restore_flags(flags
);
1805 /* The abort command does not leave the device in a clean state where
1806 it is available to be used again. Until this gets worked out, we will
1807 leave it commented out. */
1809 int atp870u_abort(Scsi_Cmnd
* SCpnt
)
1812 unsigned int tmport
;
1813 struct atp_unit
*dev
;
1814 for (h
= 0; h
<= admaxu
; h
++) {
1815 if (SCpnt
->host
== atp_host
[h
]) {
1819 panic("Abort host not found !");
1822 printk(KERN_DEBUG
"working=%x last_cmd=%x ", dev
->working
, dev
->last_cmd
);
1823 printk(" quhdu=%x quendu=%x ", dev
->quhdu
, dev
->quendu
);
1824 tmport
= dev
->ioport
;
1825 for (j
= 0; j
< 0x17; j
++) {
1826 printk(" r%2x=%2x", j
, inb(tmport
++));
1829 printk(" r1c=%2x", inb(tmport
));
1831 printk(" r1f=%2x in_snd=%2x ", inb(tmport
), dev
->in_snd
);
1833 printk(" r20=%2x", inb(tmport
));
1835 printk(" r22=%2x", inb(tmport
));
1837 printk(" r3a=%2x \n",inb(tmport
));
1838 return (SCSI_ABORT_SNOOZE
);
1841 int atp870u_reset(Scsi_Cmnd
* SCpnt
, unsigned int reset_flags
)
1845 * See if a bus reset was suggested.
1847 for (h
= 0; h
<= admaxu
; h
++) {
1848 if (SCpnt
->host
== atp_host
[h
]) {
1852 panic("Reset bus host not found !");
1854 /* SCpnt->result = 0x00080000;
1855 SCpnt->scsi_done(SCpnt);
1859 return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET); */
1860 return (SCSI_RESET_SNOOZE
);
1863 const char *atp870u_info(struct Scsi_Host
*notused
)
1865 static char buffer
[128];
1867 strcpy(buffer
, "ACARD AEC-6710/6712 PCI Ultra/W SCSI-3 Adapter Driver V2.1+ac ");
1872 int atp870u_set_info(char *buffer
, int length
, struct Scsi_Host
*HBAptr
)
1874 return -ENOSYS
; /* Currently this is a no-op */
1877 #define BLS buffer + len + size
1878 int atp870u_proc_info(char *buffer
, char **start
, off_t offset
, int length
,
1879 int hostno
, int inout
)
1881 struct Scsi_Host
*HBAptr
;
1882 static u8 buff
[512];
1890 for (i
= 0; i
< 2; i
++) {
1891 if ((HBAptr
= atp_host
[i
]) != NULL
) {
1892 if (HBAptr
->host_no
== hostno
) {
1899 if (HBAptr
== NULL
) {
1900 size
+= sprintf(BLS
, "Can't find adapter for host number %d\n", hostno
);
1906 if (inout
== TRUE
) { /* Has data been written to the file? */
1907 return (atp870u_set_info(buffer
, length
, HBAptr
));
1910 memset(buff
, 0, sizeof(buff
));
1912 size
+= sprintf(BLS
, "ACARD AEC-671X Driver Version: 2.1+ac\n");
1917 size
+= sprintf(BLS
, "\n");
1918 size
+= sprintf(BLS
, "Adapter Configuration:\n");
1919 size
+= sprintf(BLS
, " Base IO: %#.4lx\n", HBAptr
->io_port
);
1920 size
+= sprintf(BLS
, " IRQ: %d\n", HBAptr
->irq
);
1926 *start
= buffer
+ (offset
- begin
); /* Start of wanted data */
1927 len
-= (offset
- begin
); /* Start slop */
1929 len
= length
; /* Ending slop */
1936 int atp870u_biosparam(Scsi_Disk
* disk
, kdev_t dev
, int *ip
)
1938 int heads
, sectors
, cylinders
;
1942 cylinders
= disk
->capacity
/ (heads
* sectors
);
1944 if (cylinders
> 1024) {
1947 cylinders
= disk
->capacity
/ (heads
* sectors
);
1957 int atp870u_release (struct Scsi_Host
*pshost
)
1960 for (h
= 0; h
<= admaxu
; h
++)
1962 if (pshost
== atp_host
[h
]) {
1964 free_irq (pshost
->irq
, &atp_unit
[h
]);
1965 release_region (pshost
->io_port
, pshost
->n_io_port
);
1966 scsi_unregister(pshost
);
1968 kfree(atp_unit
[h
].id
[k
].prd_tableu
);
1972 panic("atp870u: bad scsi host passed.\n");
1976 static Scsi_Host_Template driver_template
= ATP870U
;
1977 #include "scsi_module.c"