This source file includes following definitions.
- aha1542_stat
- aha1542_out
- aha1542_in
- makecode
- aha1542_test_port
- aha1542_info
- aha1542_intr_handle
- aha1542_queuecommand
- internal_done
- aha1542_command
- setup_mailboxes
- aha1542_getconfig
- aha1542_query
- aha1542_detect
- aha1542_abort
- aha1542_reset
- aha1542_biosparam
1
2
3
4
5
6
7
8
9
10
11
12 #include <linux/kernel.h>
13 #include <linux/head.h>
14 #include <linux/types.h>
15 #include <linux/string.h>
16
17 #include <linux/sched.h>
18 #include <asm/dma.h>
19
20 #include <asm/system.h>
21 #include <asm/io.h>
22 #include "../blk.h"
23 #include "scsi.h"
24 #include "hosts.h"
25
26 #include "aha1542.h"
27
28 #ifdef DEBUG
29 #define DEB(x) x
30 #else
31 #define DEB(x)
32 #endif
33
34
35
36
37
38
39
40
41
42 static unsigned int bases[]={0x330, 0x334};
43
44 static unsigned int base;
45 static unsigned char dma_chan;
46 static unsigned char irq_level;
47
48 static int aha_disable = 0;
49
50
51
52 #define DMA_MODE_REG 0xd6
53 #define DMA_MASK_REG 0xd4
54 #define CASCADE 0xc0
55
56 static struct mailbox mb[2*AHA1542_MAILBOXES];
57 static struct ccb ccb[AHA1542_MAILBOXES];
58
59 static Scsi_Cmnd * SCint[AHA1542_MAILBOXES] = {NULL, };
60
61
62 static int aha1542_last_mbi_used = (2*AHA1542_MAILBOXES - 1);
63 static int aha1542_last_mbo_used = (AHA1542_MAILBOXES - 1);
64
65
66 static long WAITnexttimeout = 3000000;
67
68 static int aha1542_host = 0;
69 extern void aha1542_interrupt();
70
71 #define aha1542_intr_reset() outb(IRST, CONTROL)
72
73 #define WAIT(port, mask, allof, noneof) \
74 { register WAITbits; \
75 register WAITtimeout = WAITnexttimeout; \
76 while (1) { \
77 WAITbits = inb(port) & (mask); \
78 if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
79 break; \
80 if (--WAITtimeout == 0) goto fail; \
81 } \
82 }
83
84 static void aha1542_stat(void)
85 {
86
87
88 }
89
90 static int aha1542_out(unchar *cmdp, int len)
91 {
92 while (len--)
93 {
94 WAIT(STATUS, CDF, 0, CDF);
95 outb(*cmdp++, DATA);
96 }
97 return 0;
98 fail:
99 printk("aha1542_out failed(%d): ", len+1); aha1542_stat();
100 return 1;
101 }
102
103 static int aha1542_in(unchar *cmdp, int len)
104 {
105 while (len--)
106 {
107 WAIT(STATUS, DF, DF, 0);
108 *cmdp++ = inb(DATA);
109 }
110 return 0;
111 fail:
112 printk("aha1542_in failed(%d): ", len+1); aha1542_stat();
113 return 1;
114 }
115 int makecode(unsigned hosterr, unsigned scsierr)
116 {
117 switch (hosterr) {
118 case 0x0:
119 case 0xa:
120 case 0xb:
121 hosterr = 0;
122 break;
123
124 case 0x11:
125
126 hosterr = DID_TIME_OUT;
127 break;
128
129 case 0x12:
130
131
132
133 case 0x13:
134
135 case 0x15:
136
137
138 case 0x16:
139
140
141 case 0x17:
142
143
144 case 0x18:
145
146
147 case 0x19:
148
149
150
151 case 0x1a:
152
153
154 hosterr = DID_ERROR;
155 break;
156
157 case 0x14:
158
159
160
161 hosterr = DID_RESET;
162 break;
163 default:
164 printk("makecode: unknown hoststatus %x\n", hosterr);
165 break;
166 }
167 return scsierr|(hosterr << 16);
168 }
169
170 int aha1542_test_port(int bse)
171 {
172 volatile int debug = 0;
173
174 base = bse;
175
176
177
178
179 outb(SRST|IRST, CONTROL);
180
181 debug = 1;
182
183 WAIT(STATUS, STATMASK, INIT|IDLE, STST|DIAGF|INVDCMD|DF|CDF);
184
185 debug = 2;
186
187 if (inb(INTRFLAGS)&INTRMASK) goto fail;
188
189 debug = 3;
190
191 outb(CMD_ECHO, DATA);
192
193 debug = 4;
194
195 WAIT(STATUS, STATMASK, 0, STST|DIAGF|INVDCMD|DF|CDF);
196
197 debug = 5;
198
199 outb(42, DATA);
200
201 debug = 6;
202
203 WAIT(STATUS, STATMASK, DF, STST|DIAGF|CDF|INVDCMD);
204
205 debug = 7;
206
207 if (inb(DATA) != 42) goto fail;
208
209 debug = 8;
210
211 if (inb(STATUS) & DF) goto fail;
212
213 debug = 9;
214
215 WAIT(INTRFLAGS, HACC, HACC, 0);
216
217
218 debug = 10;
219
220 outb(IRST, CONTROL);
221
222 debug = 11;
223
224 return debug;
225 fail:
226 return 0;
227 }
228
229
230 const char *aha1542_info(void)
231 {
232 static char buffer[] = "";
233 return buffer;
234 }
235
236
237 void aha1542_intr_handle(int foo)
238 {
239 void (*my_done)(Scsi_Cmnd *) = NULL;
240 int errstatus, mbi, mbo, mbistatus;
241 int number_serviced;
242 Scsi_Cmnd * SCtmp;
243
244 #ifdef DEBUG
245 {
246 int flag = inb(INTRFLAGS);
247 printk("aha1542_intr_handle: ");
248 if (!(flag&ANYINTR)) printk("no interrupt?");
249 if (flag&MBIF) printk("MBIF ");
250 if (flag&MBOA) printk("MBOF ");
251 if (flag&HACC) printk("HACC ");
252 if (flag&SCRD) printk("SCRD ");
253 printk("status %02x\n", inb(STATUS));
254 };
255 #endif
256 number_serviced = 0;
257
258 while(1==1){
259 aha1542_intr_reset();
260
261 cli();
262 mbi = aha1542_last_mbi_used + 1;
263 if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
264
265 do{
266 if(mb[mbi].status != 0) break;
267 mbi++;
268 if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
269 } while (mbi != aha1542_last_mbi_used);
270
271 if(mb[mbi].status == 0){
272 sti();
273
274 if (number_serviced) return;
275 printk("aha1542.c: interrupt received, but no mail.\n");
276 return;
277 };
278
279 mbo = (scsi2int(mb[mbi].ccbptr) - ((unsigned int) &ccb[0])) / sizeof(struct ccb);
280 mbistatus = mb[mbi].status;
281 mb[mbi].status = 0;
282 aha1542_last_mbi_used = mbi;
283 sti();
284
285 #ifdef DEBUG
286 {
287 if (ccb[mbo].tarstat|ccb[mbo].hastat)
288 printk("aha1542_command: returning %x (status %d)\n",
289 ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
290 };
291 #endif
292
293 if(mbistatus == 3) continue;
294
295 #ifdef DEBUG
296 printk("...done %d %d\n",mbo, mbi);
297 #endif
298
299 SCtmp = SCint[mbo];
300
301 if (!SCtmp || !SCtmp->scsi_done) {
302 printk("aha1542_intr_handle: Unexpected interrupt\n");
303 return;
304 }
305
306 my_done = SCtmp->scsi_done;
307 if (SCtmp->host_scribble) scsi_free(SCtmp->host_scribble, 512);
308
309
310
311
312 if (ccb[mbo].tarstat == 2)
313 memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
314 sizeof(SCtmp->sense_buffer));
315
316
317
318
319
320 if (mbistatus != 1)
321
322 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
323 else
324 errstatus = 0;
325
326 #ifdef DEBUG
327 if(errstatus) printk("(aha1542 error:%x %x %x) ",errstatus,
328 ccb[mbo].hastat, ccb[mbo].tarstat);
329 #endif
330
331 if (ccb[mbo].tarstat == 2) {
332 #ifdef DEBUG
333 int i;
334 #endif
335 DEB(printk("aha1542_intr_handle: sense:"));
336 #ifdef DEBUG
337 for (i = 0; i < 12; i++)
338 printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen+i]);
339 printk("\n");
340 #endif
341
342
343
344
345
346
347 }
348 DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
349 SCtmp->result = errstatus;
350 SCint[mbo] = NULL;
351
352 my_done(SCtmp);
353 number_serviced++;
354 };
355 }
356
357 int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
358 {
359 unchar ahacmd = CMD_START_SCSI;
360 unchar direction;
361 unchar *cmd = (unchar *) SCpnt->cmnd;
362 unchar target = SCpnt->target;
363 unchar lun = SCpnt->lun;
364 void *buff = SCpnt->request_buffer;
365 int bufflen = SCpnt->request_bufflen;
366 int mbo;
367
368 DEB(int i);
369
370 DEB(if (target > 1) {
371 SCpnt->result = DID_TIME_OUT << 16;
372 done(SCpnt); return 0;});
373
374 if(*cmd == REQUEST_SENSE){
375 #ifndef DEBUG
376 if (bufflen != 16) {
377 printk("Wrong buffer length supplied for request sense (%d)\n",bufflen);
378 panic("aha1542.c");
379 };
380 #endif
381 SCpnt->result = 0;
382 done(SCpnt);
383 return 0;
384 };
385
386 #ifdef DEBUG
387 if (*cmd == READ_10 || *cmd == WRITE_10)
388 i = xscsi2int(cmd+2);
389 else if (*cmd == READ_6 || *cmd == WRITE_6)
390 i = scsi2int(cmd+2);
391 else
392 i = -1;
393 if (done)
394 printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
395 else
396 printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
397 aha1542_stat();
398 printk("aha1542_queuecommand: dumping scsi cmd:");
399 for (i = 0; i < (*cmd<=0x1f?6:10); i++) printk("%02x ", cmd[i]);
400 printk("\n");
401 if (*cmd == WRITE_10 || *cmd == WRITE_6)
402 return 0;
403 #endif
404
405
406
407 cli();
408 mbo = aha1542_last_mbo_used + 1;
409 if (mbo >= AHA1542_MAILBOXES) mbo = 0;
410
411 do{
412 if(mb[mbo].status == 0 && SCint[mbo] == NULL)
413 break;
414 mbo++;
415 if (mbo >= AHA1542_MAILBOXES) mbo = 0;
416 } while (mbo != aha1542_last_mbo_used);
417
418 if(mb[mbo].status || SCint[mbo])
419 panic("Unable to find empty mailbox for aha1542.\n");
420
421 SCint[mbo] = SCpnt;
422
423
424 aha1542_last_mbo_used = mbo;
425 sti();
426
427 #ifdef DEBUG
428 printk("Sending command (%d %x)...",mbo, done);
429 #endif
430
431 memset(&ccb[mbo], 0, sizeof(struct ccb));
432
433 ccb[mbo].cdblen = (*cmd<=0x1f)?6:10;
434
435 direction = 0;
436 if (*cmd == READ_10 || *cmd == READ_6)
437 direction = 8;
438 else if (*cmd == WRITE_10 || *cmd == WRITE_6)
439 direction = 16;
440
441 memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
442
443 if (SCpnt->use_sg) {
444 struct scatterlist * sgpnt;
445 struct chain * cptr;
446 #ifdef DEBUG
447 unsigned char * ptr;
448 #endif
449 int i;
450 ccb[mbo].op = 2;
451 SCpnt->host_scribble = scsi_malloc(512);
452 sgpnt = (struct scatterlist *) SCpnt->request_buffer;
453 cptr = (struct chain *) SCpnt->host_scribble;
454 if (cptr == NULL) panic("aha1542.c: unable to allocate DMA memory\n");
455 for(i=0; i<SCpnt->use_sg; i++) {
456 if(sgpnt[i].length == 0 || SCpnt->use_sg > 16 ||
457 (((int)sgpnt[i].address) & 1) || (sgpnt[i].length & 1)){
458 unsigned char * ptr;
459 printk("Bad segment list supplied to aha1542.c (%d, %d)\n",SCpnt->use_sg,i);
460 for(i=0;i<SCpnt->use_sg++;i++){
461 printk("%d: %x %x %d\n",i,sgpnt[i].address, sgpnt[i].alt_address,
462 sgpnt[i].length);
463 };
464 printk("cptr %x: ",cptr);
465 ptr = (unsigned char *) &cptr[i];
466 for(i=0;i<18;i++) printk("%02x ", ptr[i]);
467 panic("Foooooooood fight!");
468 };
469 any2scsi(cptr[i].dataptr, sgpnt[i].address);
470 any2scsi(cptr[i].datalen, sgpnt[i].length);
471 };
472 any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
473 any2scsi(ccb[mbo].dataptr, cptr);
474 #ifdef DEBUG
475 printk("cptr %x: ",cptr);
476 ptr = (unsigned char *) cptr;
477 for(i=0;i<18;i++) printk("%02x ", ptr[i]);
478 #endif
479 } else {
480 ccb[mbo].op = 0;
481 SCpnt->host_scribble = NULL;
482 any2scsi(ccb[mbo].datalen, bufflen);
483 any2scsi(ccb[mbo].dataptr, buff);
484 };
485 ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7);
486 ccb[mbo].rsalen = 12;
487 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
488 ccb[mbo].commlinkid = 0;
489
490 #ifdef DEBUGd
491 { int i;
492 printk("aha1542_command: sending.. ");
493 for (i = 0; i < sizeof(ccb[mbo])-10; i++)
494 printk("%02x ", ((unchar *)&ccb[mbo])[i]);
495 };
496 #endif
497
498 if (done) {
499 DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
500 SCpnt->scsi_done = done;
501 mb[mbo].status = 1;
502 aha1542_out(&ahacmd, 1);
503 DEB(aha1542_stat());
504 }
505 else
506 printk("aha1542_queuecommand: done can't be NULL\n");
507
508 return 0;
509 }
510
511 static volatile int internal_done_flag = 0;
512 static volatile int internal_done_errcode = 0;
513 static void internal_done(Scsi_Cmnd * SCpnt)
514 {
515 internal_done_errcode = SCpnt->result;
516 ++internal_done_flag;
517 }
518
519 int aha1542_command(Scsi_Cmnd * SCpnt)
520 {
521 DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
522
523 aha1542_queuecommand(SCpnt, internal_done);
524
525 while (!internal_done_flag);
526 internal_done_flag = 0;
527 return internal_done_errcode;
528 }
529
530
531 static void setup_mailboxes()
532 {
533 int i;
534 static unchar cmd[5] = {CMD_MBINIT, AHA1542_MAILBOXES};
535
536 for(i=0; i<AHA1542_MAILBOXES; i++){
537 mb[i].status = mb[AHA1542_MAILBOXES+i].status = 0;
538 any2scsi(mb[i].ccbptr, &ccb[i]);
539 };
540 aha1542_intr_reset();
541 any2scsi((cmd+2), mb);
542 aha1542_out(cmd, 5);
543 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
544 while (0) {
545 fail:
546 printk("aha1542_detect: failed setting up mailboxes\n");
547 }
548 aha1542_intr_reset();
549 }
550
551
552 static int aha1542_getconfig(int hostnum)
553 {
554 static unchar inquiry_cmd[] = {CMD_RETCONF };
555 static unchar inquiry_result[3];
556 int i;
557 i = inb(STATUS);
558 if (i & DF) {
559 i = inb(DATA);
560 };
561 aha1542_out(inquiry_cmd, 1);
562 aha1542_in(inquiry_result, 3);
563 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
564 while (0) {
565 fail:
566 printk("aha1542_detect: query board settings\n");
567 }
568 aha1542_intr_reset();
569 switch(inquiry_result[0]){
570 case 0x80:
571 dma_chan = 7;
572 break;
573 case 0x40:
574 dma_chan = 6;
575 break;
576 case 0x20:
577 dma_chan = 5;
578 break;
579 case 1:
580 printk("DMA priority 0 not available for Adaptec driver\n");
581 return -1;
582 default:
583 printk("Unable to determine Adaptec DMA priority. Disabling board\n");
584 return -1;
585 };
586 switch(inquiry_result[1]){
587 case 0x40:
588 irq_level = 15;
589 break;
590 case 0x20:
591 irq_level = 14;
592 break;
593 case 0x8:
594 irq_level = 12;
595 break;
596 case 0x4:
597 irq_level = 11;
598 break;
599 case 0x2:
600 irq_level = 10;
601 break;
602 case 0x1:
603 irq_level = 9;
604 break;
605 default:
606 printk("Unable to determine Adaptec IRQ level. Disabling board\n");
607 return -1;
608 };
609 return 0;
610 }
611
612
613 static void aha1542_query(int hostnum)
614 {
615 static unchar inquiry_cmd[] = {CMD_INQUIRY };
616 static unchar inquiry_result[4];
617 int i;
618 i = inb(STATUS);
619 if (i & DF) {
620 i = inb(DATA);
621 };
622 aha1542_out(inquiry_cmd, 1);
623 aha1542_in(inquiry_result, 4);
624 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
625 while (0) {
626 fail:
627 printk("aha1542_detect: query card type\n");
628 }
629 aha1542_intr_reset();
630
631
632
633
634
635
636
637 if (inquiry_result[0] == 0x43) {
638 printk("aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
639 aha_disable = 1;
640 };
641 }
642
643
644 int aha1542_detect(int hostnum)
645 {
646 int i;
647 int indx;
648
649 DEB(printk("aha1542_detect: \n"));
650
651 indx = 0;
652 while(indx < sizeof(bases)/sizeof(bases[0])){
653 i = aha1542_test_port(bases[indx]);
654 if (i) break;
655 indx++;
656 }
657 if (indx == sizeof(bases)/sizeof(bases[0])) return 0;
658
659
660 {
661 static unchar oncmd[] = {CMD_BUSON_TIME, 7};
662 static unchar offcmd[] = {CMD_BUSOFF_TIME, 5};
663
664 aha1542_intr_reset();
665 aha1542_out(oncmd, 2);
666 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
667 aha1542_intr_reset();
668 aha1542_out(offcmd, 2);
669 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
670 while (0) {
671 fail:
672 printk("aha1542_detect: setting bus on/off-time failed\n");
673 }
674 aha1542_intr_reset();
675 }
676 aha1542_query(hostnum);
677
678 if (aha_disable) return 0;
679
680 if (aha1542_getconfig(hostnum) == -1) return 0;
681
682 printk("Configuring Adaptec at IO:%x, IRQ %d, DMA priority %d\n",base,
683 irq_level, dma_chan);
684
685 DEB(aha1542_stat());
686 setup_mailboxes();
687
688 DEB(aha1542_stat());
689
690 DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
691
692 if (request_irq(irq_level,aha1542_intr_handle)) {
693 printk("Unable to allocate IRQ for adaptec controller.\n");
694 return 0;
695 };
696
697 if(request_dma(dma_chan)){
698 printk("Unable to allocate DMA channel for Adaptec.\n");
699 free_irq(irq_level);
700 return 0;
701 };
702
703 if(dma_chan >= 5){
704 outb(((dma_chan - 4)|CASCADE),DMA_MODE_REG);
705 outb((dma_chan-4),DMA_MASK_REG);
706 };
707
708 #if 0
709 DEB(printk(" *** READ CAPACITY ***\n"));
710
711 {
712 unchar buf[8];
713 static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
714 int i;
715
716 for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
717 for (i = 0; i < 2; ++i)
718 if (!aha1542_command(i, cmd, buf, sizeof(buf))) {
719 printk("aha_detect: LU %d sector_size %d device_size %d\n",
720 i, xscsi2int(buf+4), xscsi2int(buf));
721 }
722 }
723
724 DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n"));
725
726 for (i = 0; i < 4; ++i)
727 {
728 unsigned char cmd[10];
729 static buffer[512];
730
731 cmd[0] = READ_10;
732 cmd[1] = 0;
733 xany2scsi(cmd+2, i);
734 cmd[6] = 0;
735 cmd[7] = 0;
736 cmd[8] = 1;
737 cmd[9] = 0;
738 aha1542_command(0, cmd, buffer, 512);
739 }
740 #endif
741 aha1542_host = hostnum;
742 return 1;
743 }
744
745
746
747
748
749 int aha1542_abort(Scsi_Cmnd * SCpnt, int i)
750 {
751 #if 0
752 unchar ahacmd = CMD_START_SCSI;
753 int mbo;
754 #endif
755 DEB(printk("aha1542_abort\n"));
756 #if 0
757 cli();
758 for(mbo = 0; mbo < AHA1542_MAILBOXES; mbo++)
759 if (SCpnt == SCint[mbo]){
760 mb[mbo].status = 2;
761 aha1542_out(&ahacmd, 1);
762 sti();
763 break;
764 };
765 #endif
766 return 0;
767 }
768
769 int aha1542_reset(void)
770 {
771 DEB(printk("aha1542_reset called\n"));
772 return 0;
773 }
774
775 int aha1542_biosparam(int size, int dev, int* info){
776 info[0] = 64;
777 info[1] = 32;
778 info[2] = size >> 11;
779 if (info[2] >= 1024) info[2] = 1024;
780 return 0;
781 }