Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / scsi / atp870u.c
blob890d44426f7d4eb917702f8c7c9188e2cf5a0887
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
10 * support atp876 chip
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>
26 #include <asm/io.h>
27 #include <linux/pci.h>
28 #include <linux/blk.h>
29 #include "scsi.h"
30 #include "hosts.h"
33 #include "atp870u.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};
48 struct atp_unit
50 unsigned long ioport;
51 unsigned long irq;
52 unsigned long pciport;
53 unsigned char last_cmd;
54 unsigned char in_snd;
55 unsigned char in_int;
56 unsigned char quhdu;
57 unsigned char quendu;
58 unsigned char scam_on;
59 unsigned char global_map;
60 unsigned char chip_veru;
61 unsigned char host_idu;
62 int working;
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];
68 struct atp_id
70 unsigned char dirctu;
71 unsigned char devspu;
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;
78 Scsi_Cmnd *curr_req;
79 } id[16];
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)
87 unsigned long flags;
88 unsigned short int tmpcip, id;
89 unsigned char i, j, h, target_id, lun;
90 unsigned char *prd;
91 Scsi_Cmnd *workrequ;
92 unsigned int workportu, tmport;
93 unsigned long adrcntu, k;
94 int errstus;
95 struct atp_unit *dev = dev_id;
97 for (h = 0; h < 2; h++) {
98 if (irq == irqnumu[h]) {
99 goto irq_numok;
102 return;
103 irq_numok:
104 dev->in_int = 1;
105 workportu = dev->ioport;
106 tmport = workportu;
108 if (dev->working != 0)
110 tmport += 0x1f;
111 j = inb(tmport);
112 if ((j & 0x80) == 0)
114 dev->in_int = 0;
115 return;
118 tmpcip = dev->pciport;
119 if ((inb(tmpcip) & 0x08) != 0)
121 tmpcip += 0x2;
122 for (k=0; k < 1000; k++)
124 if ((inb(tmpcip) & 0x08) == 0)
126 goto stop_dma;
128 if ((inb(tmpcip) & 0x01) == 0)
130 goto stop_dma;
134 stop_dma:
135 tmpcip = dev->pciport;
136 outb(0x00, tmpcip);
137 tmport -= 0x08;
139 i = inb(tmport);
140 if ((j & 0x40) == 0)
142 if ((dev->last_cmd & 0x40) == 0)
144 dev->last_cmd = 0xff;
147 else dev->last_cmd |= 0x40;
149 tmport -= 0x02;
150 target_id = inb(tmport);
151 tmport += 0x02;
154 * Remap wide devices onto id numbers
157 if ((target_id & 0x40) != 0) {
158 target_id = (target_id & 0x07) | 0x08;
159 } else {
160 target_id &= 0x07;
163 if (i == 0x85)
166 * Flip wide
168 if (dev->wide_idu != 0)
170 tmport = workportu + 0x1b;
171 outb(0x01,tmport);
172 while ((inb(tmport) & 0x01) != 0x01)
174 outb(0x01,tmport);
178 * Issue more commands
180 if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) &&
181 (dev->in_snd == 0))
183 send_s870(h);
186 * Done
188 dev->in_int = 0;
189 return;
191 if (i == 0x21)
193 tmport -= 0x05;
194 adrcntu = 0;
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;
199 k -= adrcntu;
200 dev->id[target_id].tran_lenu = k;
201 dev->id[target_id].last_lenu = adrcntu;
202 tmport -= 0x04;
203 outb(0x41, tmport);
204 tmport += 0x08;
205 outb(0x08, tmport);
206 dev->in_int = 0;
207 return;
209 if ((i == 0x80) || (i == 0x8f))
211 lun = 0;
212 tmport -= 0x07;
213 j = inb(tmport);
214 if (j == 0x44 || i==0x80) {
215 tmport += 0x0d;
216 lun = inb(tmport) & 0x07;
217 } else {
218 if (j == 0x41)
220 tmport += 0x02;
221 adrcntu = 0;
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;
226 k -= adrcntu;
227 dev->id[target_id].tran_lenu = k;
228 dev->id[target_id].last_lenu = adrcntu;
229 tmport += 0x04;
230 outb(0x08, tmport);
231 dev->in_int = 0;
232 return;
234 else
236 outb(0x46, tmport);
237 dev->id[target_id].dirctu = 0x00;
238 tmport += 0x02;
239 outb(0x00, tmport++);
240 outb(0x00, tmport++);
241 outb(0x00, tmport++);
242 tmport += 0x03;
243 outb(0x08, tmport);
244 dev->in_int = 0;
245 return;
248 tmport = workportu + 0x10;
249 outb(0x45, tmport);
250 tmport += 0x06;
251 target_id = inb(tmport);
253 * Remap wide identifiers
255 if ((target_id & 0x10) != 0)
257 target_id = (target_id & 0x07) | 0x08;
258 } else {
259 target_id &= 0x07;
261 workrequ = dev->id[target_id].curr_req;
262 tmport = workportu + 0x0f;
263 outb(lun, tmport);
264 tmport += 0x02;
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++);
271 /* Remap wide */
272 j = target_id;
273 if (target_id > 7) {
274 j = (j & 0x07) | 0x40;
276 /* Add direction */
277 j |= dev->id[target_id].dirctu;
278 outb(j, tmport++);
279 outb(0x80, tmport);
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);
288 else
290 outb((unsigned char)(inb(tmport) & 0xf3),tmport);
293 tmport = workportu + 0x1b;
294 j = 0;
295 id = 1;
296 id = id << target_id;
298 * Is this a wide device
300 if ((id & dev->wide_idu) != 0) {
301 j |= 0x01;
303 outb(j, tmport);
304 while ((inb(tmport) & 0x01) != j)
306 outb(j,tmport);
309 if (dev->id[target_id].last_lenu == 0) {
310 tmport = workportu + 0x18;
311 outb(0x08, tmport);
312 dev->in_int = 0;
313 return;
315 prd = dev->id[target_id].prd_posu;
316 while (adrcntu != 0)
318 id = ((unsigned short int *) (prd))[2];
319 if (id == 0) {
320 k = 0x10000;
321 } else {
322 k = id;
324 if (k > adrcntu) {
325 ((unsigned short int *) (prd))[2] = (unsigned short int)
326 (k - adrcntu);
327 ((unsigned long *) (prd))[0] += adrcntu;
328 adrcntu = 0;
329 dev->id[target_id].prd_posu = prd;
330 } else {
331 adrcntu -= k;
332 dev->id[target_id].prdaddru += 0x08;
333 prd += 0x08;
334 if (adrcntu == 0) {
335 dev->id[target_id].prd_posu = prd;
339 tmpcip = dev->pciport + 0x04;
340 outl(dev->id[target_id].prdaddru, tmpcip);
341 tmpcip -= 0x02;
342 outb(0x06, tmpcip);
343 outb(0x00, tmpcip);
344 tmpcip -= 0x02;
345 tmport = workportu + 0x18;
347 * Check transfer direction
349 if (dev->id[target_id].dirctu != 0) {
350 outb(0x08, tmport);
351 outb(0x01, tmpcip);
352 dev->in_int = 0;
353 return;
355 outb(0x08, tmport);
356 outb(0x09, tmpcip);
357 dev->in_int = 0;
358 return;
362 * Current scsi request on this target
365 workrequ = dev->id[target_id].curr_req;
367 if (i == 0x42) {
368 errstus = 0x02;
369 workrequ->result = errstus;
370 goto go_42;
372 if (i == 0x16)
374 errstus = 0;
375 tmport -= 0x08;
376 errstus = inb(tmport);
377 workrequ->result = errstus;
378 go_42:
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;
390 dev->working--;
392 * Take it back wide
394 if (dev->wide_idu != 0) {
395 tmport = workportu + 0x1b;
396 outb(0x01,tmport);
397 while ((inb(tmport) & 0x01) != 0x01)
399 outb(0x01,tmport);
403 * If there is stuff to send and nothing going then send it
405 if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) &&
406 (dev->in_snd == 0))
408 send_s870(h);
410 dev->in_int = 0;
411 return;
413 if (i == 0x4f) {
414 i = 0x89;
416 i &= 0x0f;
417 if (i == 0x09) {
418 tmpcip = tmpcip + 4;
419 outl(dev->id[target_id].prdaddru, tmpcip);
420 tmpcip = tmpcip - 2;
421 outb(0x06, tmpcip);
422 outb(0x00, tmpcip);
423 tmpcip = tmpcip - 2;
424 tmport = workportu + 0x10;
425 outb(0x41, tmport);
426 dev->id[target_id].dirctu = 0x00;
427 tmport += 0x08;
428 outb(0x08, tmport);
429 outb(0x09, tmpcip);
430 dev->in_int = 0;
431 return;
433 if (i == 0x08) {
434 tmpcip = tmpcip + 4;
435 outl(dev->id[target_id].prdaddru, tmpcip);
436 tmpcip = tmpcip - 2;
437 outb(0x06, tmpcip);
438 outb(0x00, tmpcip);
439 tmpcip = tmpcip - 2;
440 tmport = workportu + 0x10;
441 outb(0x41, tmport);
442 tmport += 0x05;
443 outb((unsigned char) (inb(tmport) | 0x20), tmport);
444 dev->id[target_id].dirctu = 0x20;
445 tmport += 0x03;
446 outb(0x08, tmport);
447 outb(0x01, tmpcip);
448 dev->in_int = 0;
449 return;
451 tmport -= 0x07;
452 if (i == 0x0a) {
453 outb(0x30, tmport);
454 } else {
455 outb(0x46, tmport);
457 dev->id[target_id].dirctu = 0x00;
458 tmport += 0x02;
459 outb(0x00, tmport++);
460 outb(0x00, tmport++);
461 outb(0x00, tmport++);
462 tmport += 0x03;
463 outb(0x08, tmport);
464 dev->in_int = 0;
465 return;
466 } else {
467 // tmport = workportu + 0x17;
468 // inb(tmport);
469 // dev->working = 0;
470 dev->in_int = 0;
471 return;
475 int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done) (Scsi_Cmnd *))
477 unsigned char i, h;
478 unsigned long flags;
479 unsigned short int m;
480 unsigned int tmport;
481 struct atp_unit *dev;
483 for (h = 0; h <= admaxu; h++) {
484 if (req_p->host == atp_host[h]) {
485 goto host_ok;
488 return 0;
489 host_ok:
490 if (req_p->channel != 0) {
491 req_p->result = 0x00040000;
492 done(req_p);
493 return 0;
495 dev = &atp_unit[h];
496 m = 1;
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;
505 done(req_p);
506 return 0;
508 if (done) {
509 req_p->scsi_done = done;
510 } else {
511 printk(KERN_WARNING "atp870u_queuecommand: done can't be NULL\n");
512 req_p->result = 0;
513 done(req_p);
514 return 0;
517 * Count new command
519 dev->quendu++;
520 if (dev->quendu >= qcnt) {
521 dev->quendu = 0;
524 * Check queue state
526 wait_que_empty:
527 if (dev->quhdu == dev->quendu) {
528 goto wait_que_empty;
530 save_flags(flags);
531 cli();
532 dev->querequ[dev->quendu] = req_p;
533 if (dev->quendu == 0) {
534 i = qcnt - 1;
535 } else {
536 i = dev->quendu - 1;
538 tmport = dev->ioport + 0x1c;
539 restore_flags(flags);
540 if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) {
541 send_s870(h);
543 return 0;
546 void mydlyu(unsigned int dlycnt)
548 unsigned int i;
549 for (i = 0; i < dlycnt; i++) {
550 inb(0x80);
554 void send_s870(unsigned char h)
556 unsigned int tmport;
557 Scsi_Cmnd *workrequ;
558 unsigned long flags;
559 unsigned int i;
560 unsigned char j, target_id;
561 unsigned char *prd;
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];
568 save_flags(flags);
569 cli();
570 if (dev->in_snd != 0) {
571 restore_flags(flags);
572 return;
574 dev->in_snd = 1;
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 */
580 goto cmd_subp;
582 dev->last_cmd = 0xff;
583 if (dev->quhdu == dev->quendu)
585 dev->in_snd = 0;
586 restore_flags(flags);
587 return ;
590 dev->working++;
591 j = dev->quhdu;
592 dev->quhdu++;
593 if (dev->quhdu >= qcnt) {
594 dev->quhdu = 0;
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;
600 goto cmd_subp;
602 dev->quhdu = j;
603 dev->working--;
604 dev->in_snd = 0;
605 restore_flags(flags);
606 return;
607 cmd_subp:
608 workportu = dev->ioport;
609 tmport = workportu + 0x1f;
610 if ((inb(tmport) & 0xb0) != 0) {
611 goto abortsnd;
613 tmport = workportu + 0x1c;
614 if (inb(tmport) == 0) {
615 goto oktosend;
617 abortsnd:
618 dev->last_cmd |= 0x40;
619 dev->in_snd = 0;
620 restore_flags(flags);
621 return;
622 oktosend:
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;
643 j = 0;
644 target_id = workrequ->target;
647 * Wide ?
649 w = 1;
650 w = w << target_id;
651 if ((w & dev->wide_idu) != 0) {
652 j |= 0x01;
654 outb(j, tmport);
655 while ((inb(tmport) & 0x01) != j)
657 outb(j,tmport);
661 * Write the command
664 tmport = workportu;
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);
673 tmport += 0x02;
675 * Write the target
677 outb(dev->id[target_id].devspu, tmport++);
680 * Figure out the transfer size
682 if (workrequ->use_sg)
684 l = 0;
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;
694 } else {
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++);
703 j = target_id;
704 dev->id[j].last_lenu = l;
705 dev->id[j].tran_lenu = 0;
707 * Flip the wide bits
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++);
718 } else {
719 outb(j, tmport++);
721 outb((unsigned char)(inb(tmport) | 0x80),tmport);
722 outb(0x80, tmport);
723 tmport = workportu + 0x1c;
724 dev->id[target_id].dirctu = 0;
725 if (l == 0) {
726 if (inb(tmport) == 0) {
727 tmport = workportu + 0x18;
728 outb(0x08, tmport);
729 } else {
730 dev->last_cmd |= 0x40;
732 dev->in_snd = 0;
733 restore_flags(flags);
734 return;
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
742 * a linear chain.
745 if (workrequ->use_sg)
747 sgpnt = (struct scatterlist *) workrequ->request_buffer;
748 i = 0;
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;
753 i += 0x04;
755 (unsigned short int) (((unsigned short int *) (prd))[i - 1]) = 0x8000;
756 } else {
758 * For a linear request write a chain of blocks
760 bttl = virt_to_bus(workrequ->request_buffer);
761 l = workrequ->request_bufflen;
762 i = 0;
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;
767 l -= 0x10000;
768 bttl += 0x10000;
769 i += 0x04;
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;
775 tmpcip = tmpcip + 4;
776 dev->id[target_id].prdaddru = virt_to_bus(dev->id[target_id].prd_tableu);
777 outl(dev->id[target_id].prdaddru, tmpcip);
778 tmpcip = tmpcip - 2;
779 outb(0x06, tmpcip);
780 outb(0x00, tmpcip);
781 tmpcip = tmpcip - 2;
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);
789 else
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;
801 outb(0x08, tmport);
802 outb(0x01, tmpcip);
803 } else {
804 dev->last_cmd |= 0x40;
806 dev->in_snd = 0;
807 restore_flags(flags);
808 return;
810 if (inb(tmport) == 0)
812 tmport = workportu + 0x18;
813 outb(0x08, tmport);
814 outb(0x09, tmpcip);
815 } else {
816 dev->last_cmd |= 0x40;
818 dev->in_snd = 0;
819 restore_flags(flags);
820 return;
824 static void internal_done(Scsi_Cmnd * SCpnt)
826 SCpnt->SCp.Status++;
829 int atp870u_command(Scsi_Cmnd * SCpnt)
832 atp870u_queuecommand(SCpnt, internal_done);
834 SCpnt->SCp.Status = 0;
835 while (!SCpnt->SCp.Status)
836 barrier();
837 return SCpnt->result;
840 unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
842 unsigned int tmport;
843 unsigned short int i, k;
844 unsigned char j;
846 tmport = dev->ioport + 0x1c;
847 outw(*val, tmport);
848 FUN_D7:
849 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
850 k = inw(tmport);
851 j = (unsigned char) (k >> 8);
852 if ((k & 0x8000) != 0) { /* DB7 all release? */
853 goto FUN_D7;
856 *val |= 0x4000; /* assert DB6 */
857 outw(*val, tmport);
858 *val &= 0xdfff; /* assert DB5 */
859 outw(*val, tmport);
860 FUN_D5:
861 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
862 if ((inw(tmport) & 0x2000) != 0) { /* DB5 all release? */
863 goto FUN_D5;
866 *val |= 0x8000; /* no DB4-0, assert DB7 */
867 *val &= 0xe0ff;
868 outw(*val, tmport);
869 *val &= 0xbfff; /* release DB6 */
870 outw(*val, tmport);
871 FUN_D6:
872 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
873 if ((inw(tmport) & 0x4000) != 0) { /* DB6 all release? */
874 goto FUN_D6;
878 return j;
881 void tscam(unsigned char host)
884 unsigned int tmport;
885 unsigned char i, j, k;
886 unsigned long n;
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++) {
896 mydlyu(0xffff);
899 tmport = dev->ioport + 1;
900 outb(0x08, tmport++);
901 outb(0x7f, tmport);
902 tmport = dev->ioport + 0x11;
903 outb(0x20, tmport);
905 if ((dev->scam_on & 0x40) == 0) {
906 return;
908 m = 1;
909 m <<= dev->host_idu;
910 j = 16;
911 if (dev->chip_veru < 4) {
912 m |= 0xff00;
913 j = 8;
915 assignid_map = m;
916 tmport = dev->ioport + 0x02;
917 outb(0x02, tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */
918 outb(0, tmport++);
919 outb(0, tmport++);
920 outb(0, tmport++);
921 outb(0, tmport++);
922 outb(0, tmport++);
923 outb(0, tmport++);
925 for (i = 0; i < j; i++) {
926 m = 1;
927 m = m << i;
928 if ((m & assignid_map) != 0) {
929 continue;
931 tmport = dev->ioport + 0x0f;
932 outb(0, tmport++);
933 tmport += 0x02;
934 outb(0, tmport++);
935 outb(0, tmport++);
936 outb(0, tmport++);
937 if (i > 7) {
938 k = (i & 0x07) | 0x40;
939 } else {
940 k = i;
942 outb(k, tmport++);
943 tmport = dev->ioport + 0x1b;
944 if (dev->chip_veru == 4) {
945 outb(0x01, tmport);
946 } else {
947 outb(0x00, tmport);
949 wait_rdyok:
950 tmport = dev->ioport + 0x18;
951 outb(0x09, tmport);
952 tmport += 0x07;
954 while ((inb(tmport) & 0x80) == 0x00);
955 tmport -= 0x08;
956 k = inb(tmport);
957 if (k != 0x16) {
958 if ((k == 0x85) || (k == 0x42)) {
959 continue;
961 tmport = dev->ioport + 0x10;
962 outb(0x41, tmport);
963 goto wait_rdyok;
965 assignid_map |= m;
968 tmport = dev->ioport + 0x02;
969 outb(0x7f, tmport);
970 tmport = dev->ioport + 0x1b;
971 outb(0x02, tmport);
973 outb(0, 0x80);
975 val = 0x0080; /* bsy */
976 tmport = dev->ioport + 0x1c;
977 outw(val, tmport);
978 val |= 0x0040; /* sel */
979 outw(val, tmport);
980 val |= 0x0004; /* msg */
981 outw(val, tmport);
982 inb(0x80); /* 2 deskew delay(45ns*2=90ns) */
983 val &= 0x007f; /* no bsy */
984 outw(val, tmport);
985 mydlyu(0xffff); /* recommanded SCAM selection response time */
986 mydlyu(0xffff);
987 val &= 0x00fb; /* after 1ms no msg */
988 outw(val, tmport);
989 wait_nomsg:
990 if ((inb(tmport) & 0x04) != 0) {
991 goto wait_nomsg;
993 outb(1, 0x80);
994 mydlyu(100);
995 for (n = 0; n < 0x30000; n++) {
996 if ((inb(tmport) & 0x80) != 0) { /* bsy ? */
997 goto wait_io;
1000 goto TCM_SYNC;
1001 wait_io:
1002 for (n = 0; n < 0x30000; n++) {
1003 if ((inb(tmport) & 0x81) == 0x0081) {
1004 goto wait_io1;
1007 goto TCM_SYNC;
1008 wait_io1:
1009 inb(0x80);
1010 val |= 0x8003; /* io,cd,db7 */
1011 outw(val, tmport);
1012 inb(0x80);
1013 val &= 0x00bf; /* no sel */
1014 outw(val, tmport);
1015 outb(2, 0x80);
1016 TCM_SYNC:
1017 mydlyu(0x800);
1018 if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */
1019 outw(0, tmport--);
1020 outb(0, tmport);
1021 tmport = dev->ioport + 0x15;
1022 outb(0, tmport);
1023 tmport += 0x03;
1024 outb(0x09, tmport);
1025 tmport += 0x07;
1026 while ((inb(tmport) & 0x80) == 0);
1027 tmport -= 0x08;
1028 inb(tmport);
1029 return;
1031 val &= 0x00ff; /* synchronization */
1032 val |= 0x3f00;
1033 fun_scam(dev, &val);
1034 outb(3, 0x80);
1035 val &= 0x00ff; /* isolation */
1036 val |= 0x2000;
1037 fun_scam(dev, &val);
1038 outb(4, 0x80);
1039 i = 8;
1040 j = 0;
1041 TCM_ID:
1042 if ((inw(tmport) & 0x2000) == 0) {
1043 goto TCM_ID;
1045 outb(5, 0x80);
1046 val &= 0x00ff; /* get ID_STRING */
1047 val |= 0x2000;
1048 k = fun_scam(dev, &val);
1049 if ((k & 0x03) == 0) {
1050 goto TCM_5;
1052 mbuf[j] <<= 0x01;
1053 mbuf[j] &= 0xfe;
1054 if ((k & 0x02) != 0) {
1055 mbuf[j] |= 0x01;
1057 i--;
1058 if (i > 0) {
1059 goto TCM_ID;
1061 j++;
1062 i = 8;
1063 goto TCM_ID;
1065 TCM_5: /* isolation complete.. */
1066 /* mbuf[32]=0;
1067 printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
1068 i = 15;
1069 j = mbuf[0];
1070 if ((j & 0x20) != 0) { /* bit5=1:ID upto 7 */
1071 i = 7;
1073 if ((j & 0x06) == 0) { /* IDvalid? */
1074 goto G2Q5;
1076 k = mbuf[1];
1077 small_id:
1078 m = 1;
1079 m <<= k;
1080 if ((m & assignid_map) == 0) {
1081 goto G2Q_QUIN;
1083 if (k > 0) {
1084 k--;
1085 goto small_id;
1087 G2Q5: /* srch from max acceptable ID# */
1088 k = i; /* max acceptable ID# */
1089 G2Q_LP:
1090 m = 1;
1091 m <<= k;
1092 if ((m & assignid_map) == 0) {
1093 goto G2Q_QUIN;
1095 if (k > 0) {
1096 k--;
1097 goto G2Q_LP;
1099 G2Q_QUIN: /* k=binID#, */
1100 assignid_map |= m;
1101 if (k < 8) {
1102 quintet[0] = 0x38; /* 1st dft ID<8 */
1103 } else {
1104 quintet[0] = 0x31; /* 1st ID>=8 */
1106 k &= 0x07;
1107 quintet[1] = g2q_tab[k];
1109 val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */
1110 m = quintet[0] << 8;
1111 val |= m;
1112 fun_scam(dev, &val);
1113 val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */
1114 m = quintet[1] << 8;
1115 val |= m;
1116 fun_scam(dev, &val);
1118 goto TCM_SYNC;
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];
1136 sync_idu = 0;
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)) {
1142 break;
1144 m = 1;
1145 m = m << i;
1146 if ((m & dev->active_idu) != 0) {
1147 continue;
1149 if (i == dev->host_idu) {
1150 printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu);
1151 continue;
1153 tmport = wkport + 0x1b;
1154 if (dev->chip_veru == 4) {
1155 outb(0x01, tmport);
1157 else
1159 outb(0x00, tmport);
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++);
1170 tmport += 0x06;
1171 outb(0, tmport);
1172 tmport += 0x02;
1173 outb(dev->id[i].devspu, tmport++);
1174 outb(0, tmport++);
1175 outb(satn[6], tmport++);
1176 outb(satn[7], tmport++);
1177 j = i;
1178 if ((j & 0x08) != 0) {
1179 j = (j & 0x07) | 0x40;
1181 outb(j, tmport);
1182 tmport += 0x03;
1183 outb(satn[8], tmport);
1184 tmport += 0x07;
1186 while ((inb(tmport) & 0x80) == 0x00);
1187 tmport -= 0x08;
1188 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1189 continue;
1191 while (inb(tmport) != 0x8e);
1192 dev->active_idu |= m;
1194 tmport = wkport + 0x10;
1195 outb(0x30, tmport);
1196 tmport = wkport + 0x04;
1197 outb(0x00, tmport);
1199 phase_cmd:
1200 tmport = wkport + 0x18;
1201 outb(0x08, tmport);
1202 tmport += 0x07;
1203 while ((inb(tmport) & 0x80) == 0x00);
1204 tmport -= 0x08;
1205 j = inb(tmport);
1206 if (j != 0x16) {
1207 tmport = wkport + 0x10;
1208 outb(0x41, tmport);
1209 goto phase_cmd;
1211 sel_ok:
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);
1219 tmport += 0x07;
1220 outb(0, tmport);
1221 tmport += 0x02;
1222 outb(dev->id[i].devspu, tmport++);
1223 outb(0, tmport++);
1224 outb(inqd[6], tmport++);
1225 outb(inqd[7], tmport++);
1226 tmport += 0x03;
1227 outb(inqd[8], tmport);
1228 tmport += 0x07;
1229 while ((inb(tmport) & 0x80) == 0x00);
1230 tmport -= 0x08;
1231 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1232 continue;
1234 while (inb(tmport) != 0x8e);
1235 tmport = wkport + 0x1b;
1236 if (dev->chip_veru == 4) {
1237 outb(0x00, tmport);
1239 tmport = wkport + 0x18;
1240 outb(0x08, tmport);
1241 tmport += 0x07;
1242 j = 0;
1243 rd_inq_data:
1244 k = inb(tmport);
1245 if ((k & 0x01) != 0) {
1246 tmport -= 0x06;
1247 mbuf[j++] = inb(tmport);
1248 tmport += 0x06;
1249 goto rd_inq_data;
1251 if ((k & 0x80) == 0) {
1252 goto rd_inq_data;
1254 tmport -= 0x08;
1255 j = inb(tmport);
1256 if (j == 0x16) {
1257 goto inq_ok;
1259 tmport = wkport + 0x10;
1260 outb(0x46, tmport);
1261 tmport += 0x02;
1262 outb(0, tmport++);
1263 outb(0, tmport++);
1264 outb(0, tmport++);
1265 tmport += 0x03;
1266 outb(0x08, tmport);
1267 tmport += 0x07;
1268 while ((inb(tmport) & 0x80) == 0x00);
1269 tmport -= 0x08;
1270 if (inb(tmport) != 0x16) {
1271 goto sel_ok;
1273 inq_ok:
1274 mbuf[36] = 0;
1275 printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]);
1276 dev->id[i].devtypeu = mbuf[0];
1277 rmb = mbuf[1];
1278 n = mbuf[7];
1279 if (dev->chip_veru != 4) {
1280 goto not_wide;
1282 if ((mbuf[7] & 0x60) == 0) {
1283 goto not_wide;
1285 if ((dev->global_map & 0x20) == 0) {
1286 goto not_wide;
1288 tmport = wkport + 0x1b;
1289 outb(0x01, tmport);
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++);
1297 tmport += 0x06;
1298 outb(0, tmport);
1299 tmport += 0x02;
1300 outb(dev->id[i].devspu, tmport++);
1301 outb(0, tmport++);
1302 outb(satn[6], tmport++);
1303 outb(satn[7], tmport++);
1304 tmport += 0x03;
1305 outb(satn[8], tmport);
1306 tmport += 0x07;
1308 while ((inb(tmport) & 0x80) == 0x00);
1309 tmport -= 0x08;
1310 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1311 continue;
1313 while (inb(tmport) != 0x8e);
1314 try_wide:
1315 j = 0;
1316 tmport = wkport + 0x14;
1317 outb(0x05, tmport);
1318 tmport += 0x04;
1319 outb(0x20, tmport);
1320 tmport += 0x07;
1322 while ((inb(tmport) & 0x80) == 0) {
1323 if ((inb(tmport) & 0x01) != 0) {
1324 tmport -= 0x06;
1325 outb(wide[j++], tmport);
1326 tmport += 0x06;
1329 tmport -= 0x08;
1330 while ((inb(tmport) & 0x80) == 0x00);
1331 j = inb(tmport) & 0x0f;
1332 if (j == 0x0f) {
1333 goto widep_in;
1335 if (j == 0x0a) {
1336 goto widep_cmd;
1338 if (j == 0x0e) {
1339 goto try_wide;
1341 continue;
1342 widep_out:
1343 tmport = wkport + 0x18;
1344 outb(0x20, tmport);
1345 tmport += 0x07;
1346 while ((inb(tmport) & 0x80) == 0) {
1347 if ((inb(tmport) & 0x01) != 0) {
1348 tmport -= 0x06;
1349 outb(0, tmport);
1350 tmport += 0x06;
1353 tmport -= 0x08;
1354 j = inb(tmport) & 0x0f;
1355 if (j == 0x0f) {
1356 goto widep_in;
1358 if (j == 0x0a) {
1359 goto widep_cmd;
1361 if (j == 0x0e) {
1362 goto widep_out;
1364 continue;
1365 widep_in:
1366 tmport = wkport + 0x14;
1367 outb(0xff, tmport);
1368 tmport += 0x04;
1369 outb(0x20, tmport);
1370 tmport += 0x07;
1371 k = 0;
1372 widep_in1:
1373 j = inb(tmport);
1374 if ((j & 0x01) != 0) {
1375 tmport -= 0x06;
1376 mbuf[k++] = inb(tmport);
1377 tmport += 0x06;
1378 goto widep_in1;
1380 if ((j & 0x80) == 0x00) {
1381 goto widep_in1;
1383 tmport -= 0x08;
1384 j = inb(tmport) & 0x0f;
1385 if (j == 0x0f) {
1386 goto widep_in;
1388 if (j == 0x0a) {
1389 goto widep_cmd;
1391 if (j == 0x0e) {
1392 goto widep_out;
1394 continue;
1395 widep_cmd:
1396 tmport = wkport + 0x10;
1397 outb(0x30, tmport);
1398 tmport = wkport + 0x14;
1399 outb(0x00, tmport);
1400 tmport += 0x04;
1401 outb(0x08, tmport);
1402 tmport += 0x07;
1403 while ((inb(tmport) & 0x80) == 0x00);
1404 tmport -= 0x08;
1405 j = inb(tmport);
1406 if (j != 0x16) {
1407 if (j == 0x4e) {
1408 goto widep_out;
1410 continue;
1412 if (mbuf[0] != 0x01) {
1413 goto not_wide;
1415 if (mbuf[1] != 0x02) {
1416 goto not_wide;
1418 if (mbuf[2] != 0x03) {
1419 goto not_wide;
1421 if (mbuf[3] != 0x01) {
1422 goto not_wide;
1424 m = 1;
1425 m = m << i;
1426 dev->wide_idu |= m;
1427 not_wide:
1428 if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) ||
1429 ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0)))
1431 goto set_sync;
1433 continue;
1434 set_sync:
1435 tmport = wkport + 0x1b;
1436 j = 0;
1437 if ((m & dev->wide_idu) != 0) {
1438 j |= 0x01;
1440 outb(j, tmport);
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++);
1448 tmport += 0x06;
1449 outb(0, tmport);
1450 tmport += 0x02;
1451 outb(dev->id[i].devspu, tmport++);
1452 outb(0, tmport++);
1453 outb(satn[6], tmport++);
1454 outb(satn[7], tmport++);
1455 tmport += 0x03;
1456 outb(satn[8], tmport);
1457 tmport += 0x07;
1459 while ((inb(tmport) & 0x80) == 0x00);
1460 tmport -= 0x08;
1461 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1462 continue;
1464 while (inb(tmport) != 0x8e);
1465 try_sync:
1466 j = 0;
1467 tmport = wkport + 0x14;
1468 outb(0x06, tmport);
1469 tmport += 0x04;
1470 outb(0x20, tmport);
1471 tmport += 0x07;
1473 while ((inb(tmport) & 0x80) == 0) {
1474 if ((inb(tmport) & 0x01) != 0) {
1475 tmport -= 0x06;
1476 if ((m & dev->wide_idu) != 0) {
1477 outb(synw[j++], tmport);
1478 } else {
1479 if ((m & dev->ultra_map) != 0) {
1480 outb(synu[j++], tmport);
1481 } else {
1482 outb(synn[j++], tmport);
1485 tmport += 0x06;
1488 tmport -= 0x08;
1489 while ((inb(tmport) & 0x80) == 0x00);
1490 j = inb(tmport) & 0x0f;
1491 if (j == 0x0f) {
1492 goto phase_ins;
1494 if (j == 0x0a) {
1495 goto phase_cmds;
1497 if (j == 0x0e) {
1498 goto try_sync;
1500 continue;
1501 phase_outs:
1502 tmport = wkport + 0x18;
1503 outb(0x20, tmport);
1504 tmport += 0x07;
1505 while ((inb(tmport) & 0x80) == 0x00) {
1506 if ((inb(tmport) & 0x01) != 0x00) {
1507 tmport -= 0x06;
1508 outb(0x00, tmport);
1509 tmport += 0x06;
1512 tmport -= 0x08;
1513 j = inb(tmport);
1514 if (j == 0x85) {
1515 goto tar_dcons;
1517 j &= 0x0f;
1518 if (j == 0x0f) {
1519 goto phase_ins;
1521 if (j == 0x0a) {
1522 goto phase_cmds;
1524 if (j == 0x0e) {
1525 goto phase_outs;
1527 continue;
1528 phase_ins:
1529 tmport = wkport + 0x14;
1530 outb(0xff, tmport);
1531 tmport += 0x04;
1532 outb(0x20, tmport);
1533 tmport += 0x07;
1534 k = 0;
1535 phase_ins1:
1536 j = inb(tmport);
1537 if ((j & 0x01) != 0x00) {
1538 tmport -= 0x06;
1539 mbuf[k++] = inb(tmport);
1540 tmport += 0x06;
1541 goto phase_ins1;
1543 if ((j & 0x80) == 0x00) {
1544 goto phase_ins1;
1546 tmport -= 0x08;
1547 while ((inb(tmport) & 0x80) == 0x00);
1548 j = inb(tmport);
1549 if (j == 0x85) {
1550 goto tar_dcons;
1552 j &= 0x0f;
1553 if (j == 0x0f) {
1554 goto phase_ins;
1556 if (j == 0x0a) {
1557 goto phase_cmds;
1559 if (j == 0x0e) {
1560 goto phase_outs;
1562 continue;
1563 phase_cmds:
1564 tmport = wkport + 0x10;
1565 outb(0x30, tmport);
1566 tar_dcons:
1567 tmport = wkport + 0x14;
1568 outb(0x00, tmport);
1569 tmport += 0x04;
1570 outb(0x08, tmport);
1571 tmport += 0x07;
1572 while ((inb(tmport) & 0x80) == 0x00);
1573 tmport -= 0x08;
1574 j = inb(tmport);
1575 if (j != 0x16) {
1576 continue;
1578 if (mbuf[0] != 0x01) {
1579 continue;
1581 if (mbuf[1] != 0x03) {
1582 continue;
1584 if (mbuf[4] == 0x00) {
1585 continue;
1587 if (mbuf[3] > 0x64) {
1588 continue;
1590 if (mbuf[4] > 0x0c) {
1591 mbuf[4] = 0x0c;
1593 dev->id[i].devspu = mbuf[4];
1594 if ((mbuf[3] < 0x0d) && (rmb == 0)) {
1595 j = 0xa0;
1596 goto set_syn_ok;
1598 if (mbuf[3] < 0x1a) {
1599 j = 0x20;
1600 goto set_syn_ok;
1602 if (mbuf[3] < 0x33) {
1603 j = 0x40;
1604 goto set_syn_ok;
1606 if (mbuf[3] < 0x4c) {
1607 j = 0x50;
1608 goto set_syn_ok;
1610 j = 0x60;
1611 set_syn_ok:
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;
1628 int tmpcnt = 0;
1629 int count = 0;
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");
1638 return count;
1640 tpnt->proc_name = "atp870u";
1642 for (h = 0; h < 2; h++) {
1643 struct atp_unit *dev = &atp_unit[h];
1644 for(k=0;k<16;k++)
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;
1652 dev->wide_idu = 0;
1653 dev->host_idu = 0x07;
1654 dev->quhdu = 0;
1655 dev->quendu = 0;
1656 pdev[h]=NULL;
1657 pdev[2]=NULL;
1658 dev->chip_veru = 0;
1659 dev->last_cmd = 0xff;
1660 dev->in_snd = 0;
1661 dev->in_int = 0;
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;
1669 h = 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])) {
1673 h++;
1674 index = 0;
1675 continue;
1677 chip_ver[2] = 0;
1679 if (devid[h] == 0x8002) {
1680 error = pci_read_config_byte(pdev[2], 0x08, &chip_ver[2]);
1681 if (chip_ver[2] < 2) {
1682 goto nxt_devfn;
1685 if (devid[h] == 0x8010 || devid[h] == 0x8050) {
1686 chip_ver[2] = 0x04;
1688 pdev[tmpcnt] = pdev[2];
1689 chip_ver[tmpcnt] = chip_ver[2];
1690 tmpcnt++;
1691 nxt_devfn:
1692 index++;
1693 if (index > 3) {
1694 index = 0;
1695 h++;
1697 if(tmpcnt>1)
1698 break;
1700 for (h = 0; h < 2; h++) {
1701 struct atp_unit *dev=&atp_unit[h];
1702 if (pdev[h]==NULL) {
1703 return count;
1706 /* Found an atp870u/w. */
1707 base_io = pci_resource_start(pdev[h], 0);
1708 irq = pdev[h]->irq;
1709 error = pci_read_config_byte(pdev[h],0x49,&host_id);
1711 base_io &= 0xfffffff8;
1713 if (check_region(base_io,0x40) != 0)
1715 return 0;
1717 printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d IO:%x, IRQ:%d.\n"
1718 ,h, base_io, irq);
1719 dev->ioport = base_io;
1720 dev->pciport = base_io + 0x20;
1721 irqnumu[h] = irq;
1722 host_id &= 0x07;
1723 dev->host_idu = host_id;
1724 dev->chip_veru = chip_ver[h];
1726 tmport = base_io + 0x22;
1727 dev->scam_on = inb(tmport);
1728 tmport += 0x0b;
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);
1737 if(shpnt==NULL)
1738 return count;
1740 save_flags(flags);
1741 cli();
1742 if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", dev)) {
1743 printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
1744 goto unregister;
1747 if (chip_ver[h] > 0x07) /* check if atp876 chip */
1748 { /* then enable terminator */
1749 tmport = base_io + 0x3e;
1750 outb(0x30, tmport);
1753 tmport = base_io + 0x3a;
1754 k = (inb(tmport) & 0xf3) | 0x10;
1755 outb(k, tmport);
1756 outb((k & 0xdf), tmport);
1757 mydlyu(0x8000);
1758 outb(k, tmport);
1759 mydlyu(0x8000);
1760 tmport = base_io;
1761 outb((host_id | 0x08), tmport);
1762 tmport += 0x18;
1763 outb(0, tmport);
1764 tmport += 0x07;
1765 while ((inb(tmport) & 0x80) == 0);
1766 tmport -= 0x08;
1767 inb(tmport);
1768 tmport = base_io + 1;
1769 outb(8, tmport++);
1770 outb(0x7f, tmport);
1771 tmport = base_io + 0x11;
1772 outb(0x20, tmport);
1774 tscam(h);
1775 is870(h, base_io);
1776 tmport = base_io + 0x3a;
1777 outb((inb(tmport) & 0xef), tmport);
1778 tmport++;
1779 outb((inb(tmport) | 0x20),tmport);
1781 atp_host[h] = shpnt;
1782 if (dev->chip_veru == 4) {
1783 shpnt->max_id = 16;
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 */
1789 shpnt->irq = irq;
1790 restore_flags(flags);
1791 request_region(base_io, 0x40, "atp870u"); /* Register the IO ports that we use */
1792 count++;
1793 index++;
1794 continue;
1795 unregister:
1796 scsi_unregister(shpnt);
1797 restore_flags(flags);
1798 index++;
1799 continue;
1802 return count;
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)
1811 unsigned char h, j;
1812 unsigned int tmport;
1813 struct atp_unit *dev;
1814 for (h = 0; h <= admaxu; h++) {
1815 if (SCpnt->host == atp_host[h]) {
1816 goto find_adp;
1819 panic("Abort host not found !");
1820 find_adp:
1821 dev=&atp_unit[h];
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++));
1828 tmport += 0x05;
1829 printk(" r1c=%2x", inb(tmport));
1830 tmport += 0x03;
1831 printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd);
1832 tmport++;
1833 printk(" r20=%2x", inb(tmport));
1834 tmport += 0x02;
1835 printk(" r22=%2x", inb(tmport));
1836 tmport += 0x18;
1837 printk(" r3a=%2x \n",inb(tmport));
1838 return (SCSI_ABORT_SNOOZE);
1841 int atp870u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
1843 unsigned char h;
1845 * See if a bus reset was suggested.
1847 for (h = 0; h <= admaxu; h++) {
1848 if (SCpnt->host == atp_host[h]) {
1849 goto find_host;
1852 panic("Reset bus host not found !");
1853 find_host:
1854 /* SCpnt->result = 0x00080000;
1855 SCpnt->scsi_done(SCpnt);
1856 dev->working=0;
1857 dev->quhdu=0;
1858 dev->quendu=0;
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 ");
1869 return buffer;
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];
1883 int i;
1884 int size = 0;
1885 int len = 0;
1886 off_t begin = 0;
1887 off_t pos = 0;
1889 HBAptr = NULL;
1890 for (i = 0; i < 2; i++) {
1891 if ((HBAptr = atp_host[i]) != NULL) {
1892 if (HBAptr->host_no == hostno) {
1893 break;
1895 HBAptr = NULL;
1899 if (HBAptr == NULL) {
1900 size += sprintf(BLS, "Can't find adapter for host number %d\n", hostno);
1901 len += size;
1902 pos = begin + len;
1903 size = 0;
1904 goto stop_output;
1906 if (inout == TRUE) { /* Has data been written to the file? */
1907 return (atp870u_set_info(buffer, length, HBAptr));
1909 if (offset == 0) {
1910 memset(buff, 0, sizeof(buff));
1912 size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.1+ac\n");
1913 len += size;
1914 pos = begin + len;
1915 size = 0;
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);
1921 len += size;
1922 pos = begin + len;
1923 size = 0;
1925 stop_output:
1926 *start = buffer + (offset - begin); /* Start of wanted data */
1927 len -= (offset - begin); /* Start slop */
1928 if (len > length) {
1929 len = length; /* Ending slop */
1931 return (len);
1934 #include "sd.h"
1936 int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int *ip)
1938 int heads, sectors, cylinders;
1940 heads = 64;
1941 sectors = 32;
1942 cylinders = disk->capacity / (heads * sectors);
1944 if (cylinders > 1024) {
1945 heads = 255;
1946 sectors = 63;
1947 cylinders = disk->capacity / (heads * sectors);
1949 ip[0] = heads;
1950 ip[1] = sectors;
1951 ip[2] = cylinders;
1953 return 0;
1957 int atp870u_release (struct Scsi_Host *pshost)
1959 int h;
1960 for (h = 0; h <= admaxu; h++)
1962 if (pshost == atp_host[h]) {
1963 int k;
1964 free_irq (pshost->irq, &atp_unit[h]);
1965 release_region (pshost->io_port, pshost->n_io_port);
1966 scsi_unregister(pshost);
1967 for(k=0;k<16;k++)
1968 kfree(atp_unit[h].id[k].prd_tableu);
1969 return 0;
1972 panic("atp870u: bad scsi host passed.\n");
1976 static Scsi_Host_Template driver_template = ATP870U;
1977 #include "scsi_module.c"