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