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