|
|
1.1 root 1: /* $Id: aha1740.c,v 1.1 1999/04/26 05:54:13 tb Exp $
2: * 1993/03/31
3: * linux/kernel/aha1740.c
4: *
5: * Based loosely on aha1542.c which is
6: * Copyright (C) 1992 Tommy Thorn and
7: * Modified by Eric Youngdale
8: *
9: * This file is aha1740.c, written and
10: * Copyright (C) 1992,1993 Brad McLean
11: *
12: * Modifications to makecode and queuecommand
13: * for proper handling of multiple devices courteously
14: * provided by Michael Weller, March, 1993
15: *
16: * Multiple adapter support, extended translation detection,
17: * update to current scsi subsystem changes, proc fs support,
18: * working (!) module support based on patches from Andreas Arens,
19: * by Andreas Degert <[email protected]>, 2/1997
20: *
21: * aha1740_makecode may still need even more work
22: * if it doesn't work for your devices, take a look.
23: */
24:
25: #ifdef MODULE
26: #include <linux/module.h>
27: #endif
28:
29: #include <linux/kernel.h>
30: #include <linux/head.h>
31: #include <linux/types.h>
32: #include <linux/string.h>
33: #include <linux/ioport.h>
34: #include <linux/proc_fs.h>
35: #include <linux/sched.h>
36: #include <asm/dma.h>
37:
38: #include <asm/system.h>
39: #include <asm/io.h>
40: #include <linux/blk.h>
41: #include "scsi.h"
42: #include "hosts.h"
43: #include "sd.h"
44:
45: #include "aha1740.h"
46: #include<linux/stat.h>
47:
48: struct proc_dir_entry proc_scsi_aha1740 = {
49: PROC_SCSI_AHA1740, 7, "aha1740",
50: S_IFDIR | S_IRUGO | S_IXUGO, 2
51: };
52:
53: /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
54: IT WORK, THEN:
55: #define DEBUG
56: */
57: #ifdef DEBUG
58: #define DEB(x) x
59: #else
60: #define DEB(x)
61: #endif
62:
63: /*
1.1.1.3 ! root 64: static const char RCSid[] = "$Header: cvs/gnumach/linux/src/drivers/scsi/Attic/aha1740.c,v 1.1 1999/04/26 05:54:13 tb Exp $";
1.1 root 65: */
66:
67: struct aha1740_hostdata {
68: unsigned int slot;
69: unsigned int translation;
70: unsigned int last_ecb_used;
71: struct ecb ecb[AHA1740_ECBS];
72: };
73:
74: #define HOSTDATA(host) ((struct aha1740_hostdata *) &host->hostdata)
75:
76: /* One for each IRQ level (9-15) */
77: static struct Scsi_Host * aha_host[8] = {NULL, };
78:
79: int aha1740_proc_info(char *buffer, char **start, off_t offset,
80: int length, int hostno, int inout)
81: {
82: int len;
83: struct Scsi_Host * shpnt;
84: struct aha1740_hostdata *host;
85:
86: if (inout)
87: return(-ENOSYS);
88:
89: for (len = 0; len < 8; len++) {
90: shpnt = aha_host[len];
91: if (shpnt && shpnt->host_no == hostno)
92: break;
93: }
94: host = HOSTDATA(shpnt);
95:
96: len = sprintf(buffer, "aha174x at IO:%x, IRQ %d, SLOT %d.\n"
97: "Extended translation %sabled.\n",
98: shpnt->io_port, shpnt->irq, host->slot,
99: host->translation ? "en" : "dis");
100:
101: if (offset > len) {
102: *start = buffer;
103: return 0;
104: }
105:
106: *start = buffer + offset;
107: len -= offset;
108: if (len > length)
109: len = length;
110: return len;
111: }
112:
113:
114: int aha1740_makecode(unchar *sense, unchar *status)
115: {
116: struct statusword
117: {
118: ushort don:1, /* Command Done - No Error */
119: du:1, /* Data underrun */
120: :1, qf:1, /* Queue full */
121: sc:1, /* Specification Check */
122: dor:1, /* Data overrun */
123: ch:1, /* Chaining Halted */
124: intr:1, /* Interrupt issued */
125: asa:1, /* Additional Status Available */
126: sns:1, /* Sense information Stored */
127: :1, ini:1, /* Initialization Required */
128: me:1, /* Major error or exception */
129: :1, eca:1, /* Extended Contingent alliance */
130: :1;
131: } status_word;
132: int retval = DID_OK;
133:
134: status_word = * (struct statusword *) status;
135: #ifdef DEBUG
136: printk("makecode from %x,%x,%x,%x %x,%x,%x,%x",
137: status[0], status[1], status[2], status[3],
138: sense[0], sense[1], sense[2], sense[3]);
139: #endif
140: if (!status_word.don) /* Anything abnormal was detected */
141: {
142: if ( (status[1]&0x18) || status_word.sc ) /*Additional info available*/
143: {
144: /* Use the supplied info for further diagnostics */
145: switch ( status[2] )
146: {
147: case 0x12:
148: if ( status_word.dor )
149: retval=DID_ERROR; /* It's an Overrun */
150: /* If not overrun, assume underrun and ignore it! */
151: case 0x00: /* No info, assume no error, should not occur */
152: break;
153: case 0x11:
154: case 0x21:
155: retval=DID_TIME_OUT;
156: break;
157: case 0x0a:
158: retval=DID_BAD_TARGET;
159: break;
160: case 0x04:
161: case 0x05:
162: retval=DID_ABORT;
163: /* Either by this driver or the AHA1740 itself */
164: break;
165: default:
166: retval=DID_ERROR; /* No further diagnostics possible */
167: }
168: }
169: else
170: { /* Michael suggests, and Brad concurs: */
171: if ( status_word.qf )
172: {
173: retval = DID_TIME_OUT; /* forces a redo */
174: /* I think this specific one should not happen -Brad */
175: printk("aha1740.c: WARNING: AHA1740 queue overflow!\n");
176: }
177: else if ( status[0]&0x60 )
178: {
179: retval = DID_ERROR; /* Didn't find a better error */
180: }
181: /* In any other case return DID_OK so for example
182: CONDITION_CHECKS make it through to the appropriate
183: device driver */
184: }
185: }
186: /* Under all circumstances supply the target status -Michael */
187: return status[3] | retval << 16;
188: }
189:
190: int aha1740_test_port(unsigned int base)
191: {
192: char name[4], tmp;
193:
194: /* Okay, look for the EISA ID's */
195: name[0]= 'A' -1 + ((tmp = inb(HID0(base))) >> 2); /* First character */
196: name[1]= 'A' -1 + ((tmp & 3) << 3);
197: name[1]+= ((tmp = inb(HID1(base))) >> 5)&0x7; /* Second Character */
198: name[2]= 'A' -1 + (tmp & 0x1f); /* Third Character */
199: name[3]=0;
200: tmp = inb(HID2(base));
201: if ( strcmp ( name, HID_MFG ) || inb(HID2(base)) != HID_PRD )
202: return 0; /* Not an Adaptec 174x */
203:
204: /* if ( inb(HID3(base)) != HID_REV )
205: printk("aha174x: Warning; board revision of %d; expected %d\n",
206: inb(HID3(base)),HID_REV); */
207:
208: if ( inb(EBCNTRL(base)) != EBCNTRL_VALUE )
209: {
210: printk("aha174x: Board detected, but EBCNTRL = %x, so disabled it.\n",
211: inb(EBCNTRL(base)));
212: return 0;
213: }
214:
215: if ( inb(PORTADR(base)) & PORTADDR_ENH )
216: return 1; /* Okay, we're all set */
217:
218: printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n");
219: return 0;
220: }
221:
222: /* A "high" level interrupt handler */
223: void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
224: {
225: void (*my_done)(Scsi_Cmnd *);
226: int errstatus, adapstat;
227: int number_serviced;
228: struct ecb *ecbptr;
229: Scsi_Cmnd *SCtmp;
230: unsigned int base;
231:
232: if (!aha_host[irq - 9])
233: panic("aha1740.c: Irq from unknown host!\n");
234: base = aha_host[irq - 9]->io_port;
235: number_serviced = 0;
236:
237: while(inb(G2STAT(base)) & G2STAT_INTPEND)
238: {
239: DEB(printk("aha1740_intr top of loop.\n"));
240: adapstat = inb(G2INTST(base));
241: ecbptr = (struct ecb *) bus_to_virt(inl(MBOXIN0(base)));
242: outb(G2CNTRL_IRST,G2CNTRL(base)); /* interrupt reset */
243:
244: switch ( adapstat & G2INTST_MASK )
245: {
246: case G2INTST_CCBRETRY:
247: case G2INTST_CCBERROR:
248: case G2INTST_CCBGOOD:
249: /* Host Ready -> Mailbox in complete */
250: outb(G2CNTRL_HRDY,G2CNTRL(base));
251: if (!ecbptr)
252: {
253: printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n",
254: inb(G2STAT(base)),adapstat,
255: inb(G2INTST(base)), number_serviced++);
256: continue;
257: }
258: SCtmp = ecbptr->SCpnt;
259: if (!SCtmp)
260: {
261: printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n",
262: inb(G2STAT(base)),adapstat,
263: inb(G2INTST(base)), number_serviced++);
264: continue;
265: }
266: if (SCtmp->host_scribble)
267: scsi_free(SCtmp->host_scribble, 512);
268: /* Fetch the sense data, and tuck it away, in the required slot.
269: The Adaptec automatically fetches it, and there is no
270: guarantee that we will still have it in the cdb when we come
271: back */
272: if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR )
273: {
274: memcpy(SCtmp->sense_buffer, ecbptr->sense,
275: sizeof(SCtmp->sense_buffer));
276: errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status);
277: }
278: else
279: errstatus = 0;
280: DEB(if (errstatus) printk("aha1740_intr_handle: returning %6x\n",
281: errstatus));
282: SCtmp->result = errstatus;
283: my_done = ecbptr->done;
284: memset(ecbptr,0,sizeof(struct ecb));
285: if ( my_done )
286: my_done(SCtmp);
287: break;
288: case G2INTST_HARDFAIL:
289: printk(KERN_ALERT "aha1740 hardware failure!\n");
290: panic("aha1740.c"); /* Goodbye */
291: case G2INTST_ASNEVENT:
292: printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",
293: adapstat, inb(MBOXIN0(base)), inb(MBOXIN1(base)),
294: inb(MBOXIN2(base)), inb(MBOXIN3(base))); /* Say What? */
295: /* Host Ready -> Mailbox in complete */
296: outb(G2CNTRL_HRDY,G2CNTRL(base));
297: break;
298: case G2INTST_CMDGOOD:
299: /* set immediate command success flag here: */
300: break;
301: case G2INTST_CMDERROR:
302: /* Set immediate command failure flag here: */
303: break;
304: }
305: number_serviced++;
306: }
307: }
308:
309: int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
310: {
311: unchar direction;
312: unchar *cmd = (unchar *) SCpnt->cmnd;
313: unchar target = SCpnt->target;
314: struct aha1740_hostdata *host = HOSTDATA(SCpnt->host);
315: unsigned long flags;
316: void *buff = SCpnt->request_buffer;
317: int bufflen = SCpnt->request_bufflen;
318: int ecbno;
319: DEB(int i);
320:
321: if(*cmd == REQUEST_SENSE)
322: {
323: if (bufflen != sizeof(SCpnt->sense_buffer))
324: {
325: printk("Wrong buffer length supplied for request sense (%d)\n",
326: bufflen);
327: }
328: SCpnt->result = 0;
329: done(SCpnt);
330: return 0;
331: }
332:
333: #ifdef DEBUG
334: if (*cmd == READ_10 || *cmd == WRITE_10)
335: i = xscsi2int(cmd+2);
336: else if (*cmd == READ_6 || *cmd == WRITE_6)
337: i = scsi2int(cmd+2);
338: else
339: i = -1;
340: printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
341: target, *cmd, i, bufflen);
342: printk("scsi cmd:");
343: for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
344: printk("\n");
345: #endif
346:
347: /* locate an available ecb */
348: save_flags(flags);
349: cli();
350: ecbno = host->last_ecb_used + 1; /* An optimization */
351: if (ecbno >= AHA1740_ECBS)
352: ecbno = 0;
353: do {
354: if (!host->ecb[ecbno].cmdw)
355: break;
356: ecbno++;
357: if (ecbno >= AHA1740_ECBS)
358: ecbno = 0;
359: } while (ecbno != host->last_ecb_used);
360:
361: if (host->ecb[ecbno].cmdw)
362: panic("Unable to find empty ecb for aha1740.\n");
363:
364: host->ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command
365: doubles as reserved flag */
366:
367: host->last_ecb_used = ecbno;
368: restore_flags(flags);
369:
370: #ifdef DEBUG
371: printk("Sending command (%d %x)...", ecbno, done);
372: #endif
373:
374: host->ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command Descriptor Block Length */
375:
376: direction = 0;
377: if (*cmd == READ_10 || *cmd == READ_6)
378: direction = 1;
379: else if (*cmd == WRITE_10 || *cmd == WRITE_6)
380: direction = 0;
381:
382: memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len);
383:
384: if (SCpnt->use_sg)
385: {
386: struct scatterlist * sgpnt;
387: struct aha1740_chain * cptr;
388: int i;
389: DEB(unsigned char * ptr);
390:
391: host->ecb[ecbno].sg = 1; /* SCSI Initiator Command w/scatter-gather*/
392: SCpnt->host_scribble = (unsigned char *) scsi_malloc(512);
393: sgpnt = (struct scatterlist *) SCpnt->request_buffer;
394: cptr = (struct aha1740_chain *) SCpnt->host_scribble;
395: if (cptr == NULL) panic("aha1740.c: unable to allocate DMA memory\n");
396: for(i=0; i<SCpnt->use_sg; i++)
397: {
398: cptr[i].datalen = sgpnt[i].length;
399: cptr[i].dataptr = virt_to_bus(sgpnt[i].address);
400: }
401: host->ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain);
402: host->ecb[ecbno].dataptr = virt_to_bus(cptr);
403: #ifdef DEBUG
404: printk("cptr %x: ",cptr);
405: ptr = (unsigned char *) cptr;
406: for(i=0;i<24;i++) printk("%02x ", ptr[i]);
407: #endif
408: }
409: else
410: {
411: SCpnt->host_scribble = NULL;
412: host->ecb[ecbno].datalen = bufflen;
413: host->ecb[ecbno].dataptr = virt_to_bus(buff);
414: }
415: host->ecb[ecbno].lun = SCpnt->lun;
416: host->ecb[ecbno].ses = 1; /* Suppress underrun errors */
417: host->ecb[ecbno].dir = direction;
418: host->ecb[ecbno].ars = 1; /* Yes, get the sense on an error */
419: host->ecb[ecbno].senselen = 12;
420: host->ecb[ecbno].senseptr = virt_to_bus(host->ecb[ecbno].sense);
421: host->ecb[ecbno].statusptr = virt_to_bus(host->ecb[ecbno].status);
422: host->ecb[ecbno].done = done;
423: host->ecb[ecbno].SCpnt = SCpnt;
424: #ifdef DEBUG
425: {
426: int i;
427: printk("aha1740_command: sending.. ");
428: for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++)
429: printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]);
430: }
431: printk("\n");
432: #endif
433: if (done)
434: { /* The Adaptec Spec says the card is so fast that the loops will
435: only be executed once in the code below. Even if this was true
436: with the fastest processors when the spec was written, it doesn't
437: seem to be true with todays fast processors. We print a warning
438: if the code is executed more often than LOOPCNT_WARN. If this
439: happens, it should be investigated. If the count reaches
440: LOOPCNT_MAX, we assume something is broken; since there is no
441: way to return an error (the return value is ignored by the
442: mid-level scsi layer) we have to panic (and maybe that's the
443: best thing we can do then anyhow). */
444:
445: #define LOOPCNT_WARN 10 /* excessive mbxout wait -> syslog-msg */
446: #define LOOPCNT_MAX 1000000 /* mbxout deadlock -> panic() after ~ 2 sec. */
447: int loopcnt;
448: unsigned int base = SCpnt->host->io_port;
449: DEB(printk("aha1740[%d] critical section\n",ecbno));
450: save_flags(flags);
451: cli();
452: for (loopcnt = 0; ; loopcnt++) {
453: if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;
454: if (loopcnt == LOOPCNT_WARN) {
455: printk("aha1740[%d]_mbxout wait!\n",ecbno);
456: cli(); /* printk may have done a sti()! */
457: }
458: if (loopcnt == LOOPCNT_MAX)
459: panic("aha1740.c: mbxout busy!\n");
460: }
461: outl(virt_to_bus(host->ecb + ecbno), MBOXOUT0(base));
462: for (loopcnt = 0; ; loopcnt++) {
463: if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;
464: if (loopcnt == LOOPCNT_WARN) {
465: printk("aha1740[%d]_attn wait!\n",ecbno);
466: cli();
467: }
468: if (loopcnt == LOOPCNT_MAX)
469: panic("aha1740.c: attn wait failed!\n");
470: }
471: outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */
472: restore_flags(flags);
473: DEB(printk("aha1740[%d] request queued.\n",ecbno));
474: }
475: else
476: printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
477: return 0;
478: }
479:
480: static void internal_done(Scsi_Cmnd * SCpnt)
481: {
482: SCpnt->SCp.Status++;
483: }
484:
485: int aha1740_command(Scsi_Cmnd * SCpnt)
486: {
487: aha1740_queuecommand(SCpnt, internal_done);
488: SCpnt->SCp.Status = 0;
489: while (!SCpnt->SCp.Status)
490: barrier();
491: return SCpnt->result;
492: }
493:
494: /* Query the board for its irq_level. Nothing else matters
495: in enhanced mode on an EISA bus. */
496:
497: void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
498: unsigned int *translation)
499: {
500: static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
501:
502: *irq_level = intab[inb(INTDEF(base)) & 0x7];
503: *translation = inb(RESV1(base)) & 0x1;
504: outb(inb(INTDEF(base)) | 0x10, INTDEF(base));
505: }
506:
507: int aha1740_detect(Scsi_Host_Template * tpnt)
508: {
509: int count = 0, slot;
510:
511: DEB(printk("aha1740_detect: \n"));
512:
513: for ( slot=MINEISA; slot <= MAXEISA; slot++ )
514: {
515: int slotbase;
516: unsigned int irq_level, translation;
517: struct Scsi_Host *shpnt;
518: struct aha1740_hostdata *host;
519: slotbase = SLOTBASE(slot);
520: /*
521: * The ioports for eisa boards are generally beyond that used in the
522: * check/allocate region code, but this may change at some point,
523: * so we go through the motions.
524: */
525: if (check_region(slotbase, SLOTSIZE)) /* See if in use */
526: continue;
527: if (!aha1740_test_port(slotbase))
528: continue;
529: aha1740_getconfig(slotbase,&irq_level,&translation);
530: if ((inb(G2STAT(slotbase)) &
531: (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT)
532: { /* If the card isn't ready, hard reset it */
533: outb(G2CNTRL_HRST, G2CNTRL(slotbase));
534: outb(0, G2CNTRL(slotbase));
535: }
536: printk("Configuring aha174x at IO:%x, IRQ %d\n", slotbase, irq_level);
537: printk("aha174x: Extended translation %sabled.\n",
538: translation ? "en" : "dis");
539: DEB(printk("aha1740_detect: enable interrupt channel %d\n",irq_level));
540: if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",NULL)) {
541: printk("Unable to allocate IRQ for adaptec controller.\n");
542: continue;
543: }
544: shpnt = scsi_register(tpnt, sizeof(struct aha1740_hostdata));
545: request_region(slotbase, SLOTSIZE, "aha1740");
546: shpnt->base = 0;
547: shpnt->io_port = slotbase;
548: shpnt->n_io_port = SLOTSIZE;
549: shpnt->irq = irq_level;
550: shpnt->dma_channel = 0xff;
551: host = HOSTDATA(shpnt);
552: host->slot = slot;
553: host->translation = translation;
554: aha_host[irq_level - 9] = shpnt;
555: count++;
556: }
557: return count;
558: }
559:
560: /* Note: They following two functions do not apply very well to the Adaptec,
561: which basically manages its own affairs quite well without our interference,
562: so I haven't put anything into them. I can faintly imagine someone with a
563: *very* badly behaved SCSI target (perhaps an old tape?) wanting the abort(),
564: but it hasn't happened yet, and doing aborts brings the Adaptec to its
565: knees. I cannot (at this moment in time) think of any reason to reset the
566: card once it's running. So there. */
567:
568: int aha1740_abort(Scsi_Cmnd * SCpnt)
569: {
570: DEB(printk("aha1740_abort called\n"));
571: return SCSI_ABORT_SNOOZE;
572: }
573:
574: /* We do not implement a reset function here, but the upper level code assumes
575: that it will get some kind of response for the command in SCpnt. We must
576: oblige, or the command will hang the scsi system */
577:
578: int aha1740_reset(Scsi_Cmnd * SCpnt, unsigned int ignored)
579: {
580: DEB(printk("aha1740_reset called\n"));
581: return SCSI_RESET_PUNT;
582: }
583:
584: int aha1740_biosparam(Disk * disk, kdev_t dev, int* ip)
585: {
586: int size = disk->capacity;
587: int extended = HOSTDATA(disk->device->host)->translation;
588:
589: DEB(printk("aha1740_biosparam\n"));
590: if (extended && (ip[2] > 1024))
591: {
592: ip[0] = 255;
593: ip[1] = 63;
594: ip[2] = size / (255 * 63);
595: }
596: else
597: {
598: ip[0] = 64;
599: ip[1] = 32;
600: ip[2] = size >> 11;
601: }
602: return 0;
603: }
604:
605: #ifdef MODULE
606: /* Eventually this will go into an include file, but this will be later */
607: Scsi_Host_Template driver_template = AHA1740;
608:
609: #include "scsi_module.c"
610: #endif
611:
612: /* Okay, you made it all the way through. As of this writing, 3/31/93, I'm
613: [email protected] or [email protected]. I'll try to help as time
614: permits if you have any trouble with this driver. Happy Linuxing! */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.