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