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 any2scsi(mb[mbo].ccbptr, &ccb[mbo]);
435
436 memset(&ccb[mbo], 0, sizeof(struct ccb));
437
438 ccb[mbo].cdblen = COMMAND_SIZE(*cmd);
439
440 direction = 0;
441 if (*cmd == READ_10 || *cmd == READ_6)
442 direction = 8;
443 else if (*cmd == WRITE_10 || *cmd == WRITE_6)
444 direction = 16;
445
446 memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
447
448 if (SCpnt->use_sg) {
449 struct scatterlist * sgpnt;
450 struct chain * cptr;
451 #ifdef DEBUG
452 unsigned char * ptr;
453 #endif
454 int i;
455 ccb[mbo].op = 2;
456 SCpnt->host_scribble = (unsigned char *) scsi_malloc(512);
457 sgpnt = (struct scatterlist *) SCpnt->request_buffer;
458 cptr = (struct chain *) SCpnt->host_scribble;
459 if (cptr == NULL) panic("aha1542.c: unable to allocate DMA memory\n");
460 for(i=0; i<SCpnt->use_sg; i++) {
461 if(sgpnt[i].length == 0 || SCpnt->use_sg > 16 ||
462 (((int)sgpnt[i].address) & 1) || (sgpnt[i].length & 1)){
463 unsigned char * ptr;
464 printk("Bad segment list supplied to aha1542.c (%d, %d)\n",SCpnt->use_sg,i);
465 for(i=0;i<SCpnt->use_sg++;i++){
466 printk("%d: %x %x %d\n",i,sgpnt[i].address, sgpnt[i].alt_address,
467 sgpnt[i].length);
468 };
469 printk("cptr %x: ",cptr);
470 ptr = (unsigned char *) &cptr[i];
471 for(i=0;i<18;i++) printk("%02x ", ptr[i]);
472 panic("Foooooooood fight!");
473 };
474 any2scsi(cptr[i].dataptr, sgpnt[i].address);
475 any2scsi(cptr[i].datalen, sgpnt[i].length);
476 };
477 any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
478 any2scsi(ccb[mbo].dataptr, cptr);
479 #ifdef DEBUG
480 printk("cptr %x: ",cptr);
481 ptr = (unsigned char *) cptr;
482 for(i=0;i<18;i++) printk("%02x ", ptr[i]);
483 #endif
484 } else {
485 ccb[mbo].op = 0;
486 SCpnt->host_scribble = NULL;
487 any2scsi(ccb[mbo].datalen, bufflen);
488 any2scsi(ccb[mbo].dataptr, buff);
489 };
490 ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7);
491 ccb[mbo].rsalen = 12;
492 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
493 ccb[mbo].commlinkid = 0;
494
495 #ifdef DEBUGd
496 { int i;
497 printk("aha1542_command: sending.. ");
498 for (i = 0; i < sizeof(ccb[mbo])-10; i++)
499 printk("%02x ", ((unchar *)&ccb[mbo])[i]);
500 };
501 #endif
502
503 if (done) {
504 DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
505 SCpnt->scsi_done = done;
506 mb[mbo].status = 1;
507 aha1542_out(&ahacmd, 1);
508 DEB(aha1542_stat());
509 }
510 else
511 printk("aha1542_queuecommand: done can't be NULL\n");
512
513 return 0;
514 }
515
516 static volatile int internal_done_flag = 0;
517 static volatile int internal_done_errcode = 0;
518 static void internal_done(Scsi_Cmnd * SCpnt)
519 {
520 internal_done_errcode = SCpnt->result;
521 ++internal_done_flag;
522 }
523
524 int aha1542_command(Scsi_Cmnd * SCpnt)
525 {
526 DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
527
528 aha1542_queuecommand(SCpnt, internal_done);
529
530 while (!internal_done_flag);
531 internal_done_flag = 0;
532 return internal_done_errcode;
533 }
534
535
536 static void setup_mailboxes(void)
537 {
538 int i;
539 static unchar cmd[5] = {CMD_MBINIT, AHA1542_MAILBOXES};
540
541 for(i=0; i<AHA1542_MAILBOXES; i++){
542 mb[i].status = mb[AHA1542_MAILBOXES+i].status = 0;
543 any2scsi(mb[i].ccbptr, &ccb[i]);
544 };
545 aha1542_intr_reset();
546 any2scsi((cmd+2), mb);
547 aha1542_out(cmd, 5);
548 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
549 while (0) {
550 fail:
551 printk("aha1542_detect: failed setting up mailboxes\n");
552 }
553 aha1542_intr_reset();
554 }
555
556 static int aha1542_getconfig(int hostnum)
557 {
558 static unchar inquiry_cmd[] = {CMD_RETCONF };
559 static unchar inquiry_result[3];
560 int i;
561 i = inb(STATUS);
562 if (i & DF) {
563 i = inb(DATA);
564 };
565 aha1542_out(inquiry_cmd, 1);
566 aha1542_in(inquiry_result, 3);
567 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
568 while (0) {
569 fail:
570 printk("aha1542_detect: query board settings\n");
571 }
572 aha1542_intr_reset();
573 switch(inquiry_result[0]){
574 case 0x80:
575 dma_chan = 7;
576 break;
577 case 0x40:
578 dma_chan = 6;
579 break;
580 case 0x20:
581 dma_chan = 5;
582 break;
583 case 0x01:
584 printk("DMA priority 0 not available for Adaptec driver\n");
585 return -1;
586 case 0:
587
588
589 dma_chan = 0xFF;
590 break;
591 default:
592 printk("Unable to determine Adaptec DMA priority. Disabling board\n");
593 return -1;
594 };
595 switch(inquiry_result[1]){
596 case 0x40:
597 irq_level = 15;
598 break;
599 case 0x20:
600 irq_level = 14;
601 break;
602 case 0x8:
603 irq_level = 12;
604 break;
605 case 0x4:
606 irq_level = 11;
607 break;
608 case 0x2:
609 irq_level = 10;
610 break;
611 case 0x1:
612 irq_level = 9;
613 break;
614 default:
615 printk("Unable to determine Adaptec IRQ level. Disabling board\n");
616 return -1;
617 };
618 return 0;
619 }
620
621
622 static void aha1542_query(int hostnum)
623 {
624 static unchar inquiry_cmd[] = {CMD_INQUIRY };
625 static unchar inquiry_result[4];
626 int i;
627 i = inb(STATUS);
628 if (i & DF) {
629 i = inb(DATA);
630 };
631 aha1542_out(inquiry_cmd, 1);
632 aha1542_in(inquiry_result, 4);
633 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
634 while (0) {
635 fail:
636 printk("aha1542_detect: query card type\n");
637 }
638 aha1542_intr_reset();
639
640
641
642
643
644
645
646 if (inquiry_result[0] == 0x43) {
647 printk("aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
648 aha_disable = 1;
649 };
650 }
651
652
653 int aha1542_detect(int hostnum)
654 {
655 int i;
656 int indx;
657
658 DEB(printk("aha1542_detect: \n"));
659
660 indx = 0;
661 while(indx < sizeof(bases)/sizeof(bases[0])){
662 i = aha1542_test_port(bases[indx]);
663 if (i) break;
664 indx++;
665 }
666 if (indx == sizeof(bases)/sizeof(bases[0])) return 0;
667
668
669 {
670 static unchar oncmd[] = {CMD_BUSON_TIME, 7};
671 static unchar offcmd[] = {CMD_BUSOFF_TIME, 5};
672
673 aha1542_intr_reset();
674 aha1542_out(oncmd, 2);
675 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
676 aha1542_intr_reset();
677 aha1542_out(offcmd, 2);
678 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
679 while (0) {
680 fail:
681 printk("aha1542_detect: setting bus on/off-time failed\n");
682 }
683 aha1542_intr_reset();
684 }
685 aha1542_query(hostnum);
686
687 if (aha_disable) return 0;
688
689 if (aha1542_getconfig(hostnum) == -1) return 0;
690
691 printk("Configuring Adaptec at IO:%x, IRQ %d",base, irq_level);
692 if (dma_chan != 0xFF)
693 printk(", DMA priority %d", dma_chan);
694 printk("\n");
695
696 DEB(aha1542_stat());
697 setup_mailboxes();
698
699 DEB(aha1542_stat());
700
701 DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
702
703 if (request_irq(irq_level,aha1542_intr_handle)) {
704 printk("Unable to allocate IRQ for adaptec controller.\n");
705 return 0;
706 }
707
708 if (dma_chan != 0xFF) {
709 if (request_dma(dma_chan)) {
710 printk("Unable to allocate DMA channel for Adaptec.\n");
711 free_irq(irq_level);
712 return 0;
713 }
714
715 if (dma_chan >= 5) {
716 outb((dma_chan - 4) | CASCADE, DMA_MODE_REG);
717 outb(dma_chan - 4, DMA_MASK_REG);
718 }
719 }
720
721 #if 0
722 DEB(printk(" *** READ CAPACITY ***\n"));
723
724 {
725 unchar buf[8];
726 static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
727 int i;
728
729 for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
730 for (i = 0; i < 2; ++i)
731 if (!aha1542_command(i, cmd, buf, sizeof(buf))) {
732 printk("aha_detect: LU %d sector_size %d device_size %d\n",
733 i, xscsi2int(buf+4), xscsi2int(buf));
734 }
735 }
736
737 DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n"));
738
739 for (i = 0; i < 4; ++i)
740 {
741 unsigned char cmd[10];
742 static buffer[512];
743
744 cmd[0] = READ_10;
745 cmd[1] = 0;
746 xany2scsi(cmd+2, i);
747 cmd[6] = 0;
748 cmd[7] = 0;
749 cmd[8] = 1;
750 cmd[9] = 0;
751 aha1542_command(0, cmd, buffer, 512);
752 }
753 #endif
754 aha1542_host = hostnum;
755 return 1;
756 }
757
758
759
760
761
762 int aha1542_abort(Scsi_Cmnd * SCpnt, int i)
763 {
764 #if 0
765 unchar ahacmd = CMD_START_SCSI;
766 int mbo;
767 #endif
768 DEB(printk("aha1542_abort\n"));
769 #if 0
770 cli();
771 for(mbo = 0; mbo < AHA1542_MAILBOXES; mbo++)
772 if (SCpnt == SCint[mbo]){
773 mb[mbo].status = 2;
774 aha1542_out(&ahacmd, 1);
775 sti();
776 break;
777 };
778 #endif
779 return 0;
780 }
781
782 int aha1542_reset(void)
783 {
784 DEB(printk("aha1542_reset called\n"));
785 return 0;
786 }
787
788 int aha1542_biosparam(int size, int dev, int * ip)
789 {
790 ip[0] = 64;
791 ip[1] = 32;
792 ip[2] = size >> 11;
793
794 return 0;
795 }