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 static void setup_mailboxes(void);
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 setup_mailboxes();
189
190 debug = 3;
191
192 outb(CMD_ECHO, DATA);
193
194 debug = 4;
195
196 WAIT(STATUS, STATMASK, 0, STST|DIAGF|INVDCMD|DF|CDF);
197
198 debug = 5;
199
200 outb(42, DATA);
201
202 debug = 6;
203
204 WAIT(STATUS, STATMASK, DF, STST|DIAGF|CDF|INVDCMD);
205
206 debug = 7;
207
208 if (inb(DATA) != 42) goto fail;
209
210 debug = 8;
211
212 if (inb(STATUS) & DF) goto fail;
213
214 debug = 9;
215
216 WAIT(INTRFLAGS, HACC, HACC, 0);
217
218
219 debug = 10;
220
221 outb(IRST, CONTROL);
222
223 debug = 11;
224
225 return debug;
226 fail:
227 return 0;
228 }
229
230
231 const char *aha1542_info(void)
232 {
233 static char buffer[] = "Adaptec 1542";
234 return buffer;
235 }
236
237
238 void aha1542_intr_handle(int foo)
239 {
240 void (*my_done)(Scsi_Cmnd *) = NULL;
241 int errstatus, mbi, mbo, mbistatus;
242 int number_serviced;
243 Scsi_Cmnd * SCtmp;
244
245 #ifdef DEBUG
246 {
247 int flag = inb(INTRFLAGS);
248 printk("aha1542_intr_handle: ");
249 if (!(flag&ANYINTR)) printk("no interrupt?");
250 if (flag&MBIF) printk("MBIF ");
251 if (flag&MBOA) printk("MBOF ");
252 if (flag&HACC) printk("HACC ");
253 if (flag&SCRD) printk("SCRD ");
254 printk("status %02x\n", inb(STATUS));
255 };
256 #endif
257 number_serviced = 0;
258
259 while(1==1){
260 aha1542_intr_reset();
261
262 cli();
263 mbi = aha1542_last_mbi_used + 1;
264 if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
265
266 do{
267 if(mb[mbi].status != 0) break;
268 mbi++;
269 if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
270 } while (mbi != aha1542_last_mbi_used);
271
272 if(mb[mbi].status == 0){
273 sti();
274
275 if (number_serviced) return;
276 printk("aha1542.c: interrupt received, but no mail.\n");
277 return;
278 };
279
280 mbo = (scsi2int(mb[mbi].ccbptr) - ((unsigned int) &ccb[0])) / sizeof(struct ccb);
281 mbistatus = mb[mbi].status;
282 mb[mbi].status = 0;
283 aha1542_last_mbi_used = mbi;
284 sti();
285
286 #ifdef DEBUG
287 {
288 if (ccb[mbo].tarstat|ccb[mbo].hastat)
289 printk("aha1542_command: returning %x (status %d)\n",
290 ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
291 };
292 #endif
293
294 if(mbistatus == 3) continue;
295
296 #ifdef DEBUG
297 printk("...done %d %d\n",mbo, mbi);
298 #endif
299
300 SCtmp = SCint[mbo];
301
302 if (!SCtmp || !SCtmp->scsi_done) {
303 printk("aha1542_intr_handle: Unexpected interrupt\n");
304 return;
305 }
306
307 my_done = SCtmp->scsi_done;
308 if (SCtmp->host_scribble) scsi_free(SCtmp->host_scribble, 512);
309
310
311
312
313 if (ccb[mbo].tarstat == 2)
314 memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
315 sizeof(SCtmp->sense_buffer));
316
317
318
319
320
321 if (mbistatus != 1)
322
323 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
324 else
325 errstatus = 0;
326
327 #ifdef DEBUG
328 if(errstatus) printk("(aha1542 error:%x %x %x) ",errstatus,
329 ccb[mbo].hastat, ccb[mbo].tarstat);
330 #endif
331
332 if (ccb[mbo].tarstat == 2) {
333 #ifdef DEBUG
334 int i;
335 #endif
336 DEB(printk("aha1542_intr_handle: sense:"));
337 #ifdef DEBUG
338 for (i = 0; i < 12; i++)
339 printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen+i]);
340 printk("\n");
341 #endif
342
343
344
345
346
347
348 }
349 DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
350 SCtmp->result = errstatus;
351 SCint[mbo] = NULL;
352
353 my_done(SCtmp);
354 number_serviced++;
355 };
356 }
357
358 int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
359 {
360 unchar ahacmd = CMD_START_SCSI;
361 unchar direction;
362 unchar *cmd = (unchar *) SCpnt->cmnd;
363 unchar target = SCpnt->target;
364 unchar lun = SCpnt->lun;
365 void *buff = SCpnt->request_buffer;
366 int bufflen = SCpnt->request_bufflen;
367 int mbo;
368
369 DEB(int i);
370
371 DEB(if (target > 1) {
372 SCpnt->result = DID_TIME_OUT << 16;
373 done(SCpnt); return 0;});
374
375 if(*cmd == REQUEST_SENSE){
376 #ifndef DEBUG
377 if (bufflen != 16) {
378 printk("Wrong buffer length supplied for request sense (%d)\n",bufflen);
379 panic("aha1542.c");
380 };
381 #endif
382 SCpnt->result = 0;
383 done(SCpnt);
384 return 0;
385 };
386
387 #ifdef DEBUG
388 if (*cmd == READ_10 || *cmd == WRITE_10)
389 i = xscsi2int(cmd+2);
390 else if (*cmd == READ_6 || *cmd == WRITE_6)
391 i = scsi2int(cmd+2);
392 else
393 i = -1;
394 if (done)
395 printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
396 else
397 printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
398 aha1542_stat();
399 printk("aha1542_queuecommand: dumping scsi cmd:");
400 for (i = 0; i < (COMMAND_SIZE(*cmd)); i++) printk("%02x ", cmd[i]);
401 printk("\n");
402 if (*cmd == WRITE_10 || *cmd == WRITE_6)
403 return 0;
404 #endif
405
406
407
408 cli();
409 mbo = aha1542_last_mbo_used + 1;
410 if (mbo >= AHA1542_MAILBOXES) mbo = 0;
411
412 do{
413 if(mb[mbo].status == 0 && SCint[mbo] == NULL)
414 break;
415 mbo++;
416 if (mbo >= AHA1542_MAILBOXES) mbo = 0;
417 } while (mbo != aha1542_last_mbo_used);
418
419 if(mb[mbo].status || SCint[mbo])
420 panic("Unable to find empty mailbox for aha1542.\n");
421
422 SCint[mbo] = SCpnt;
423
424
425 aha1542_last_mbo_used = mbo;
426 sti();
427
428 #ifdef DEBUG
429 printk("Sending command (%d %x)...",mbo, done);
430 #endif
431
432 memset(&ccb[mbo], 0, sizeof(struct ccb));
433
434 ccb[mbo].cdblen = COMMAND_SIZE(*cmd);
435
436 direction = 0;
437 if (*cmd == READ_10 || *cmd == READ_6)
438 direction = 8;
439 else if (*cmd == WRITE_10 || *cmd == WRITE_6)
440 direction = 16;
441
442 memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
443
444 if (SCpnt->use_sg) {
445 struct scatterlist * sgpnt;
446 struct chain * cptr;
447 #ifdef DEBUG
448 unsigned char * ptr;
449 #endif
450 int i;
451 ccb[mbo].op = 2;
452 SCpnt->host_scribble = scsi_malloc(512);
453 sgpnt = (struct scatterlist *) SCpnt->request_buffer;
454 cptr = (struct chain *) SCpnt->host_scribble;
455 if (cptr == NULL) panic("aha1542.c: unable to allocate DMA memory\n");
456 for(i=0; i<SCpnt->use_sg; i++) {
457 if(sgpnt[i].length == 0 || SCpnt->use_sg > 16 ||
458 (((int)sgpnt[i].address) & 1) || (sgpnt[i].length & 1)){
459 unsigned char * ptr;
460 printk("Bad segment list supplied to aha1542.c (%d, %d)\n",SCpnt->use_sg,i);
461 for(i=0;i<SCpnt->use_sg++;i++){
462 printk("%d: %x %x %d\n",i,sgpnt[i].address, sgpnt[i].alt_address,
463 sgpnt[i].length);
464 };
465 printk("cptr %x: ",cptr);
466 ptr = (unsigned char *) &cptr[i];
467 for(i=0;i<18;i++) printk("%02x ", ptr[i]);
468 panic("Foooooooood fight!");
469 };
470 any2scsi(cptr[i].dataptr, sgpnt[i].address);
471 any2scsi(cptr[i].datalen, sgpnt[i].length);
472 };
473 any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
474 any2scsi(ccb[mbo].dataptr, cptr);
475 #ifdef DEBUG
476 printk("cptr %x: ",cptr);
477 ptr = (unsigned char *) cptr;
478 for(i=0;i<18;i++) printk("%02x ", ptr[i]);
479 #endif
480 } else {
481 ccb[mbo].op = 0;
482 SCpnt->host_scribble = NULL;
483 any2scsi(ccb[mbo].datalen, bufflen);
484 any2scsi(ccb[mbo].dataptr, buff);
485 };
486 ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7);
487 ccb[mbo].rsalen = 12;
488 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
489 ccb[mbo].commlinkid = 0;
490
491 #ifdef DEBUGd
492 { int i;
493 printk("aha1542_command: sending.. ");
494 for (i = 0; i < sizeof(ccb[mbo])-10; i++)
495 printk("%02x ", ((unchar *)&ccb[mbo])[i]);
496 };
497 #endif
498
499 if (done) {
500 DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
501 SCpnt->scsi_done = done;
502 mb[mbo].status = 1;
503 aha1542_out(&ahacmd, 1);
504 DEB(aha1542_stat());
505 }
506 else
507 printk("aha1542_queuecommand: done can't be NULL\n");
508
509 return 0;
510 }
511
512 static volatile int internal_done_flag = 0;
513 static volatile int internal_done_errcode = 0;
514 static void internal_done(Scsi_Cmnd * SCpnt)
515 {
516 internal_done_errcode = SCpnt->result;
517 ++internal_done_flag;
518 }
519
520 int aha1542_command(Scsi_Cmnd * SCpnt)
521 {
522 DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
523
524 aha1542_queuecommand(SCpnt, internal_done);
525
526 while (!internal_done_flag);
527 internal_done_flag = 0;
528 return internal_done_errcode;
529 }
530
531
532 static void setup_mailboxes(void)
533 {
534 int i;
535 static unchar cmd[5] = {CMD_MBINIT, AHA1542_MAILBOXES};
536
537 for(i=0; i<AHA1542_MAILBOXES; i++){
538 mb[i].status = mb[AHA1542_MAILBOXES+i].status = 0;
539 any2scsi(mb[i].ccbptr, &ccb[i]);
540 };
541 aha1542_intr_reset();
542 any2scsi((cmd+2), mb);
543 aha1542_out(cmd, 5);
544 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
545 while (0) {
546 fail:
547 printk("aha1542_detect: failed setting up mailboxes\n");
548 }
549 aha1542_intr_reset();
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
780 return 0;
781 }