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 my_done = SCtmp->scsi_done;
301 if (SCtmp->host_scribble) scsi_free(SCtmp->host_scribble, 512);
302
303 if (!my_done) {
304 printk("aha1542_intr_handle: Unexpected interrupt\n");
305 return;
306 }
307
308
309
310
311 if (ccb[mbo].tarstat == 2)
312 memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
313 sizeof(SCtmp->sense_buffer));
314
315
316
317
318
319 if (mbistatus != 1)
320
321 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
322 else
323 errstatus = 0;
324
325 #ifdef DEBUG
326 if(errstatus) printk("(aha1542 error:%x %x %x) ",errstatus,
327 ccb[mbo].hastat, ccb[mbo].tarstat);
328 #endif
329
330 if (ccb[mbo].tarstat == 2) {
331 #ifdef DEBUG
332 int i;
333 #endif
334 DEB(printk("aha1542_intr_handle: sense:"));
335 #ifdef DEBUG
336 for (i = 0; i < 12; i++)
337 printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen+i]);
338 printk("\n");
339 #endif
340
341
342
343
344
345
346 }
347 DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
348 SCtmp->result = errstatus;
349 SCint[mbo] = NULL;
350
351 my_done(SCtmp);
352 number_serviced++;
353 };
354 }
355
356 int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
357 {
358 unchar ahacmd = CMD_START_SCSI;
359 unchar direction;
360 unchar *cmd = (unchar *) SCpnt->cmnd;
361 unchar target = SCpnt->target;
362 unchar lun = SCpnt->lun;
363 void *buff = SCpnt->request_buffer;
364 int bufflen = SCpnt->request_bufflen;
365 int mbo;
366
367 DEB(int i);
368
369 DEB(if (target > 1) {
370 SCpnt->result = DID_TIME_OUT << 16;
371 done(SCpnt); return 0;});
372
373 if(*cmd == REQUEST_SENSE){
374 #ifndef DEBUG
375 if (bufflen != 16) {
376 printk("Wrong buffer length supplied for request sense (%d)\n",bufflen);
377 panic("aha1542.c");
378 };
379 #endif
380 SCpnt->result = 0;
381 done(SCpnt);
382 return 0;
383 };
384
385 #ifdef DEBUG
386 if (*cmd == READ_10 || *cmd == WRITE_10)
387 i = xscsi2int(cmd+2);
388 else if (*cmd == READ_6 || *cmd == WRITE_6)
389 i = scsi2int(cmd+2);
390 else
391 i = -1;
392 if (done)
393 printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
394 else
395 printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
396 aha1542_stat();
397 printk("aha1542_queuecommand: dumping scsi cmd:");
398 for (i = 0; i < (*cmd<=0x1f?6:10); i++) printk("%02x ", cmd[i]);
399 printk("\n");
400 if (*cmd == WRITE_10 || *cmd == WRITE_6)
401 return 0;
402 #endif
403
404
405
406 cli();
407 mbo = aha1542_last_mbo_used + 1;
408 if (mbo >= AHA1542_MAILBOXES) mbo = 0;
409
410 do{
411 if(mb[mbo].status == 0 && SCint[mbo] == NULL)
412 break;
413 mbo++;
414 if (mbo >= AHA1542_MAILBOXES) mbo = 0;
415 } while (mbo != aha1542_last_mbo_used);
416
417 if(mb[mbo].status || SCint[mbo])
418 panic("Unable to find empty mailbox for aha1542.\n");
419
420 SCint[mbo] = SCpnt;
421
422
423 aha1542_last_mbo_used = mbo;
424 sti();
425
426 #ifdef DEBUG
427 printk("Sending command (%d %x)...",mbo, done);
428 #endif
429
430 memset(&ccb[mbo], 0, sizeof(struct ccb));
431
432 ccb[mbo].cdblen = (*cmd<=0x1f)?6:10;
433
434 direction = 0;
435 if (*cmd == READ_10 || *cmd == READ_6)
436 direction = 8;
437 else if (*cmd == WRITE_10 || *cmd == WRITE_6)
438 direction = 16;
439
440 memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
441
442 if (SCpnt->use_sg) {
443 struct scatterlist * sgpnt;
444 struct chain * cptr;
445 #ifdef DEBUG
446 unsigned char * ptr;
447 #endif
448 int i;
449 ccb[mbo].op = 2;
450 SCpnt->host_scribble = scsi_malloc(512);
451 sgpnt = (struct scatterlist *) SCpnt->request_buffer;
452 cptr = (struct chain *) SCpnt->host_scribble;
453 if (cptr == NULL) panic("aha1542.c: unable to allocate DMA memory\n");
454 for(i=0; i<SCpnt->use_sg; i++) {
455 if(sgpnt[i].length == 0 || SCpnt->use_sg > 16 ||
456 (((int)sgpnt[i].address) & 1) || (sgpnt[i].length & 1)){
457 unsigned char * ptr;
458 printk("Bad segment list supplied to aha1542.c (%d, %d)\n",SCpnt->use_sg,i);
459 for(i=0;i<SCpnt->use_sg++;i++){
460 printk("%d: %x %x %d\n",i,sgpnt[i].address, sgpnt[i].alt_address,
461 sgpnt[i].length);
462 };
463 printk("cptr %x: ",cptr);
464 ptr = (unsigned char *) &cptr[i];
465 for(i=0;i<18;i++) printk("%02x ", ptr[i]);
466 panic("Foooooooood fight!");
467 };
468 any2scsi(cptr[i].dataptr, sgpnt[i].address);
469 any2scsi(cptr[i].datalen, sgpnt[i].length);
470 };
471 any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
472 any2scsi(ccb[mbo].dataptr, cptr);
473 #ifdef DEBUG
474 printk("cptr %x: ",cptr);
475 ptr = (unsigned char *) cptr;
476 for(i=0;i<18;i++) printk("%02x ", ptr[i]);
477 #endif
478 } else {
479 ccb[mbo].op = 0;
480 SCpnt->host_scribble = NULL;
481 any2scsi(ccb[mbo].datalen, bufflen);
482 any2scsi(ccb[mbo].dataptr, buff);
483 };
484 ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7);
485 ccb[mbo].rsalen = 12;
486 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
487 ccb[mbo].commlinkid = 0;
488
489 #ifdef DEBUGd
490 { int i;
491 printk("aha1542_command: sending.. ");
492 for (i = 0; i < sizeof(ccb[mbo])-10; i++)
493 printk("%02x ", ((unchar *)&ccb[mbo])[i]);
494 };
495 #endif
496
497 if (done) {
498 DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
499 SCpnt->scsi_done = done;
500 mb[mbo].status = 1;
501 aha1542_out(&ahacmd, 1);
502 DEB(aha1542_stat());
503 }
504 else
505 printk("aha1542_queuecommand: done can't be NULL\n");
506
507 return 0;
508 }
509
510 static volatile int internal_done_flag = 0;
511 static volatile int internal_done_errcode = 0;
512 static void internal_done(Scsi_Cmnd * SCpnt)
513 {
514 internal_done_errcode = SCpnt->result;
515 ++internal_done_flag;
516 }
517
518 int aha1542_command(Scsi_Cmnd * SCpnt)
519 {
520 DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
521
522 aha1542_queuecommand(SCpnt, internal_done);
523
524 while (!internal_done_flag);
525 internal_done_flag = 0;
526 return internal_done_errcode;
527 }
528
529
530 static void setup_mailboxes()
531 {
532 int i;
533 static unchar cmd[5] = {CMD_MBINIT, AHA1542_MAILBOXES};
534
535 for(i=0; i<AHA1542_MAILBOXES; i++){
536 mb[i].status = mb[AHA1542_MAILBOXES+i].status = 0;
537 any2scsi(mb[i].ccbptr, &ccb[i]);
538 };
539 aha1542_intr_reset();
540 any2scsi((cmd+2), mb);
541 aha1542_out(cmd, 5);
542 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
543 while (0) {
544 fail:
545 printk("aha1542_detect: failed setting up mailboxes\n");
546 }
547 aha1542_intr_reset();
548 }
549
550
551 static int aha1542_getconfig(int hostnum)
552 {
553 static unchar inquiry_cmd[] = {CMD_RETCONF };
554 static unchar inquiry_result[3];
555 int i;
556 i = inb(STATUS);
557 if (i & DF) {
558 i = inb(DATA);
559 };
560 aha1542_out(inquiry_cmd, 1);
561 aha1542_in(inquiry_result, 3);
562 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
563 while (0) {
564 fail:
565 printk("aha1542_detect: query board settings\n");
566 }
567 aha1542_intr_reset();
568 switch(inquiry_result[0]){
569 case 0x80:
570 dma_chan = 7;
571 break;
572 case 0x40:
573 dma_chan = 6;
574 break;
575 case 0x20:
576 dma_chan = 5;
577 break;
578 case 1:
579 printk("DMA priority 0 not available for Adaptec driver\n");
580 return -1;
581 default:
582 printk("Unable to determine Adaptec DMA priority. Disabling board\n");
583 return -1;
584 };
585 switch(inquiry_result[1]){
586 case 0x40:
587 irq_level = 15;
588 break;
589 case 0x20:
590 irq_level = 14;
591 break;
592 case 0x8:
593 irq_level = 12;
594 break;
595 case 0x4:
596 irq_level = 11;
597 break;
598 case 0x2:
599 irq_level = 10;
600 break;
601 case 0x1:
602 irq_level = 9;
603 break;
604 default:
605 printk("Unable to determine Adaptec IRQ level. Disabling board\n");
606 return -1;
607 };
608 return 0;
609 }
610
611
612 static void aha1542_query(int hostnum)
613 {
614 static unchar inquiry_cmd[] = {CMD_INQUIRY };
615 static unchar inquiry_result[4];
616 int i;
617 i = inb(STATUS);
618 if (i & DF) {
619 i = inb(DATA);
620 };
621 aha1542_out(inquiry_cmd, 1);
622 aha1542_in(inquiry_result, 4);
623 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
624 while (0) {
625 fail:
626 printk("aha1542_detect: query card type\n");
627 }
628 aha1542_intr_reset();
629
630
631
632
633
634
635
636 if (inquiry_result[0] == 0x43) {
637 printk("aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
638 aha_disable = 1;
639 };
640 }
641
642
643 int aha1542_detect(int hostnum)
644 {
645 int i;
646 int indx;
647
648 DEB(printk("aha1542_detect: \n"));
649
650 indx = 0;
651 while(indx < sizeof(bases)/sizeof(bases[0])){
652 i = aha1542_test_port(bases[indx]);
653 if (i) break;
654 indx++;
655 }
656 if (indx == sizeof(bases)/sizeof(bases[0])) return 0;
657
658
659 {
660 static unchar oncmd[] = {CMD_BUSON_TIME, 7};
661 static unchar offcmd[] = {CMD_BUSOFF_TIME, 5};
662
663 aha1542_intr_reset();
664 aha1542_out(oncmd, 2);
665 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
666 aha1542_intr_reset();
667 aha1542_out(offcmd, 2);
668 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
669 while (0) {
670 fail:
671 printk("aha1542_detect: setting bus on/off-time failed\n");
672 }
673 aha1542_intr_reset();
674 }
675 aha1542_query(hostnum);
676
677 if (aha_disable) return 0;
678
679 if (aha1542_getconfig(hostnum) == -1) return 0;
680
681 printk("Configuring Adaptec at IO:%x, IRQ %d, DMA priority %d\n",base,
682 irq_level, dma_chan);
683
684 DEB(aha1542_stat());
685 setup_mailboxes();
686
687 DEB(aha1542_stat());
688
689 DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
690
691 if (request_irq(irq_level,aha1542_intr_handle)) {
692 printk("Unable to allocate IRQ for adaptec controller.\n");
693 return 0;
694 };
695
696 if(request_dma(dma_chan)){
697 printk("Unable to allocate DMA channel for Adaptec.\n");
698 free_irq(irq_level);
699 return 0;
700 };
701
702 if(dma_chan >= 5){
703 outb(((dma_chan - 4)|CASCADE),DMA_MODE_REG);
704 outb((dma_chan-4),DMA_MASK_REG);
705 };
706
707 #if 0
708 DEB(printk(" *** READ CAPACITY ***\n"));
709
710 {
711 unchar buf[8];
712 static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
713 int i;
714
715 for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
716 for (i = 0; i < 2; ++i)
717 if (!aha1542_command(i, cmd, buf, sizeof(buf))) {
718 printk("aha_detect: LU %d sector_size %d device_size %d\n",
719 i, xscsi2int(buf+4), xscsi2int(buf));
720 }
721 }
722
723 DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n"));
724
725 for (i = 0; i < 4; ++i)
726 {
727 unsigned char cmd[10];
728 static buffer[512];
729
730 cmd[0] = READ_10;
731 cmd[1] = 0;
732 xany2scsi(cmd+2, i);
733 cmd[6] = 0;
734 cmd[7] = 0;
735 cmd[8] = 1;
736 cmd[9] = 0;
737 aha1542_command(0, cmd, buffer, 512);
738 }
739 #endif
740 aha1542_host = hostnum;
741 return 1;
742 }
743
744
745
746
747
748 int aha1542_abort(Scsi_Cmnd * SCpnt, int i)
749 {
750 #if 0
751 unchar ahacmd = CMD_START_SCSI;
752 int mbo;
753 #endif
754 DEB(printk("aha1542_abort\n"));
755 #if 0
756 cli();
757 for(mbo = 0; mbo < AHA1542_MAILBOXES; mbo++)
758 if (SCpnt == SCint[mbo]){
759 mb[mbo].status = 2;
760 aha1542_out(&ahacmd, 1);
761 sti();
762 break;
763 };
764 #endif
765 return 0;
766 }
767
768 int aha1542_reset(void)
769 {
770 DEB(printk("aha1542_reset called\n"));
771 return 0;
772 }
773
774 int aha1542_biosparam(int size, int dev, int* info){
775 info[0] = 64;
776 info[1] = 32;
777 info[2] = size >> 11;
778 if (info[2] >= 1024) info[2] = 1024;
779 return 0;
780 }