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