|
|
1.1 root 1: /* $Id: aha1542.c,v 1.1 1992/04/24 18:01:50 root Exp root $
2: * linux/kernel/aha1542.c
3: *
4: * (C) 1992 Tommy Thorn
5: */
6:
7: #include <linux/config.h>
8: #include <linux/kernel.h>
9: #include <linux/head.h>
10: #include <linux/string.h>
11: #include <asm/system.h>
12: #include <asm/io.h>
1.1.1.2 ! root 13: #include <sys/types.h>
1.1 root 14: #include "scsi.h"
15: #include "hosts.h"
16:
17: #include "aha1542.h"
18: #ifdef DEBUG
19: #define DEB(x) x
20: #else
21: #define DEB(x)
22: #endif
23:
24: /*
25: static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1542.c,v 1.1 1992/04/24 18:01:50 root Exp root $";
26: */
27:
28: #define base 0x330
29: #define intr_chan 11
30:
31: static struct mailbox mb[2];
32: static struct ccb ccb;
33:
34: long WAITtimeout, WAITnexttimeout = 3000000;
35:
36: void (*do_done)() = NULL;
37: extern void aha1542_interrupt();
38:
39: #define aha1542_intr_reset() outb(IRST, CONTROL)
40: #define aha1542_enable_intr() outb(inb_p(0xA1) & ~8, 0xA1)
41: #define aha1542_disable_intr() outb(inb_p(0xA1) | 8, 0xA1)
42:
43: #define WAIT(port, mask, allof, noneof) \
44: { register WAITbits; \
45: register WAITtimeout = WAITnexttimeout; \
46: while (1) { \
47: WAITbits = inb(port) & (mask); \
48: if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
49: break; \
50: if (--WAITtimeout == 0) goto fail; \
51: } \
52: }
53:
54: static void aha1542_stat(void)
55: {
56: int s = inb(STATUS), i = inb(INTRFLAGS);
57: /* printk("status = %x, intrflags = %x served %d last %x timeout %d\n", s, i, intr_flag, intr_last, WAITtimeout); */
58: printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout);
59: }
60:
61: static int aha1542_out(unchar *cmdp, int len)
62: {
63: while (len--)
64: {
65: WAIT(STATUS, CDF, 0, CDF);
66: outb(*cmdp++, DATA);
67: }
68: return 0;
69: fail:
70: printk("aha1542_out failed(%d): ", len+1); aha1542_stat();
71: return 1;
72: }
73:
74: int makecode(unsigned hosterr, unsigned scsierr)
75: {
76: switch (hosterr) {
77: case 0x0:
78: case 0xa: /* Linked command complete without error and linked normally */
79: case 0xb: /* Linked command complete without error, interrupt generated */
80: hosterr = 0;
81: break;
82:
83: case 0x11: /* Selection time out-The initiator selection or target
84: reselection was not complete within the SCSI Time out period */
85: hosterr = DID_TIME_OUT;
86: break;
87:
88: case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
89: thean was allocated by the Data Length field or the sum of the
90: Scatter / Gather Data Length fields. */
91:
92: case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
93:
94: case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
95: invalid. This usually indicates a software failure. */
96:
97: case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
98: This usually indicates a software failure. */
99:
100: case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
101: of linked CCB's does not specify the same logical unit number as
102: the first. */
103: case 0x18: /* Invalid Target Direction received from Host-The direction of a
104: Target Mode CCB was invalid. */
105:
106: case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
107: received to service data transfer between the same target LUN
108: and initiator SCSI ID in the same direction. */
109:
110: case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
111: length segment or invalid segment list boundaries was received.
112: A CCB parameter was invalid. */
113: hosterr = DID_ERROR; /* Couldn't find any better */
114: break;
115:
116: case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
117: phase sequence was requested by the target. The host adapter
118: will generate a SCSI Reset Condition, notifying the host with
119: a SCRD interrupt */
120: hosterr = DID_RESET;
121: break;
122: default:
123: printk("makecode: unknown hoststatus %x\n", hosterr);
124: break;
125: }
126: return scsierr|(hosterr << 16);
127: }
128:
129: int aha1542_test_port(void)
130: {
131: volatile int debug = 0;
132:
133: /* Reset the adapter. I ought to make a hard reset, but it's not really nessesary */
134:
135: /* DEB(printk("aha1542_test_port called \n")); */
136:
137: outb(SRST|IRST/*|SCRST*/, CONTROL);
138:
139: debug = 1;
140: /* Expect INIT and IDLE, any of the others are bad */
141: WAIT(STATUS, STATMASK, INIT|IDLE, STST|DIAGF|INVDCMD|DF|CDF);
142:
143: debug = 2;
144: /* Shouldn't have generated any interrupts during reset */
145: if (inb(INTRFLAGS)&INTRMASK) goto fail;
146:
147: debug = 3;
148: /* Test the basic ECHO command */
149: outb(CMD_ECHO, DATA);
150:
151: debug = 4;
152: /* Wait for CDF=0. If any of the others are set, it's bad */
153: WAIT(STATUS, STATMASK, 0, STST|DIAGF|INVDCMD|DF|CDF);
154:
155: debug = 5;
156: /* The meaning of life */
157: outb(42, DATA);
158:
159: debug = 6;
160: /* Expect only DF, that is, data ready */
161: WAIT(STATUS, STATMASK, DF, STST|DIAGF|CDF|INVDCMD);
162:
163: debug = 7;
164: /* Is the answer correct? */
165: if (inb(DATA) != 42) goto fail;
166:
167: debug = 8;
168: /* Reading port should reset DF */
169: if (inb(STATUS) & DF) goto fail;
170:
171: debug = 9;
172: /* When HACC, command is completed, and we're though testing */
173: WAIT(INTRFLAGS, HACC, HACC, 0);
174: /* now initialize adapter */
175:
176: debug = 10;
177: /* Clear interrupts */
178: outb(IRST, CONTROL);
179:
180: debug = 11;
181:
182: return debug; /* 1 = ok */
183: fail:
184: return 0; /* 0 = not ok */
185: }
186:
187: /* What's this little function for? */
188: char *aha1542_info(void)
189: {
190: static char buffer[] = "Adaptec 1542";
191: return buffer;
192: }
193:
194: /* A "high" level interrupt handler */
195: void aha1542_intr_handle(void)
196: {
197: int flag = inb(INTRFLAGS);
198: void (*my_done)() = do_done;
199: int errstatus;
200:
201: do_done = NULL;
202: #ifdef DEBUG
203: printk("aha1542_intr_handle: ");
204: if (!(flag&ANYINTR)) printk("no interrupt?");
205: if (flag&MBIF) printk("MBIF ");
206: if (flag&MBOA) printk("MBOF ");
207: if (flag&HACC) printk("HACC ");
208: if (flag&SCRD) printk("SCRD ");
209: printk("status %02x\n", inb(STATUS));
210: if (ccb.tarstat|ccb.hastat)
211: printk("aha1542_command: returning %x (status %d)\n", ccb.tarstat + ((int) ccb.hastat << 16), mb[1].status);
212: #endif
213: aha1542_intr_reset();
214: if (!my_done) {
215: printk("aha1542_intr_handle: Unexpected interrupt\n");
216: return;
217: }
218:
219: /* is there mail :-) */
220:
221: if (!mb[1].status) {
222: DEB(printk("aha1542_intr_handle: strange: mbif but no mail!\n"));
223: my_done(DID_TIME_OUT << 16);
224: return;
225: }
226:
227: /* more error checking left out here */
228: if (mb[1].status != 1)
229: /* This is surely wrong, but I don't know what's right */
230: errstatus = makecode(ccb.hastat, ccb.tarstat);
231: else
232: errstatus = 0;
233:
234: mb[1].status = 0;
235:
236: if (ccb.tarstat == 2) {
237: int i;
238: DEB(printk("aha1542_intr_handle: sense:"));
239: for (i = 0; i < 12; i++)
240: printk("%02x ", ccb.cdb[ccb.cdblen+i]);
241: printk("\n");
242: /*
243: DEB(printk("aha1542_intr_handle: buf:"));
244: for (i = 0; i < bufflen; i++)
245: printk("%02x ", ((unchar *)buff)[i]);
246: printk("\n");
247: */
248: }
249: DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
250: my_done(errstatus);
251: return;
252: }
253:
254: int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int))
255: {
256: unchar ahacmd = CMD_START_SCSI;
257: int i;
258: unchar *cmd = (unchar *) cmnd;
259:
260: DEB(if (target > 1) {done(DID_TIME_OUT << 16); return 0;});
261:
262: #ifdef DEBUG
263: if (*cmd == READ_10 || *cmd == WRITE_10)
264: i = xscsi2int(cmd+2);
265: else if (*cmd == READ_6 || *cmd == WRITE_6)
266: i = scsi2int(cmd+2);
267: else
268: i = -1;
269: if (done)
270: printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
271: else
272: printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
273: aha1542_stat();
274: printk("aha1542_queuecommand: dumping scsi cmd:");
275: for (i = 0; i < (*cmd<=0x1f?6:10); i++) printk("%02x ", cmd[i]);
276: printk("\n");
277: if (*cmd == WRITE_10 || *cmd == WRITE_6)
278: return 0; /* we are still testing, so *don't* write */
279: #endif
280: memset(&ccb, 0, sizeof ccb);
281:
282: ccb.cdblen = (*cmd<=0x1f)?6:10; /* SCSI Command Descriptor Block Length */
283:
284: memcpy(ccb.cdb, cmd, ccb.cdblen);
285: ccb.op = 0; /* SCSI Initiator Command */
286: ccb.idlun = (target&7)<<5; /* SCSI Target Id */
287: ccb.rsalen = 12;
288: any2scsi(ccb.datalen, bufflen);
289: any2scsi(ccb.dataptr, buff);
290: ccb.linkptr[0] = ccb.linkptr[1] = ccb.linkptr[2] = 0;
291: ccb.commlinkid = 0;
292:
293: mb[0].status = 1;
294: mb[1].status = 0;
295:
296: #ifdef DEBUGd
297: printk("aha1542_command: sending.. ");
298: for (i = 0; i < sizeof(ccb)-10; i++)
299: printk("%02x ", ((unchar *)&ccb)[i]);
300: #endif
301:
302: if (done) {
303: DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
304: if (do_done)
305: printk("aha1542_queuecommand: Two concurrent queuecommand?\n");
306: else
307: do_done = done;
308: aha1542_out(&ahacmd, 1); /* start scsi command */
309: DEB(aha1542_stat());
310: aha1542_enable_intr();
311: }
312: else
313: printk("aha1542_queuecommand: done can't be NULL\n");
314:
315: return 0;
316: }
317:
318: volatile static int internal_done_flag = 0;
319: volatile static int internal_done_errcode = 0;
320: static void internal_done(int errcode)
321: {
322: internal_done_errcode = errcode;
323: ++internal_done_flag;
324: }
325:
326: int aha1542_command(unchar target, const void *cmnd, void *buff, int bufflen)
327: {
328: DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
329: aha1542_queuecommand(target, cmnd, buff, bufflen, internal_done);
330:
331: while (!internal_done_flag);
332: internal_done_flag = 0;
333: return internal_done_errcode;
334: }
335:
336: /* Initialize mailboxes */
337: static void setup_mailboxes()
338: {
339: static unchar cmd[5] = {CMD_MBINIT, 1};
340:
341: mb[0].status = mb[1].status = 0;
342: aha1542_intr_reset(); /* reset interrupts, so they don't block */
343: any2scsi((cmd+2), mb);
344: any2scsi(mb[0].ccbptr, &ccb);
345: aha1542_out(cmd, 5);
346: WAIT(INTRFLAGS, INTRMASK, HACC, 0);
347: while (0) {
348: fail:
349: printk("aha1542_detect: failed setting up mailboxes\n");
350: }
351: aha1542_intr_reset();
352: }
353:
354: /* a hack to avoid a strange compilation error */
355:
356: void call_buh()
357: {
358: set_intr_gate(0x2b,&aha1542_interrupt);
359: }
360:
361: /* return non-zero on detection */
362: int aha1542_detect(int hostnum) /* hostnum ignored for now */
363: {
364: int i;
365:
366: DEB(printk("aha1542_detect: \n"));
367:
368: if (!(i = aha1542_test_port())) {
369: return 0;
370: }
371:
372: /* Set the Bus on/off-times as not to ruin floppy performens */
373: {
374: static unchar oncmd[] = {CMD_BUSON_TIME, 5};
375: static unchar offcmd[] = {CMD_BUSOFF_TIME, 9};
376:
377: aha1542_intr_reset();
378: aha1542_out(oncmd, 2);
379: WAIT(INTRFLAGS, INTRMASK, HACC, 0);
380: aha1542_intr_reset();
381: aha1542_out(offcmd, 2);
382: WAIT(INTRFLAGS, INTRMASK, HACC, 0);
383: while (0) {
384: fail:
385: printk("aha1542_detect: setting bus on/off-time failed\n");
386: }
387: aha1542_intr_reset();
388: }
389:
390: aha1542_stat();
391: setup_mailboxes();
392:
393: aha1542_stat();
394:
395: DEB(printk("aha1542_detect: enable interrupt channel %d\n", intr_chan));
396: call_buh();
397:
398: if (intr_chan >= 8)
399: outb(inb_p(0x21)&0xfb,0x21); /* open for slave ?? */
400:
401: DEB(printk("aha1542_detect: enabling interrupts\n"));
402: aha1542_enable_intr();
403:
404: #ifdef DEBUG
405: DEB(printk(" *** READ CAPACITY ***\n"));
406:
407: {
408: unchar buf[8];
409: static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
410: int i;
411:
412: for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
413: for (i = 0; i < 2; ++i)
414: if (!aha1542_command(i, cmd, buf, sizeof(buf))) {
415: printk("aha_detect: LU %d sector_size %d device_size %d\n",
416: i, xscsi2int(buf+4), xscsi2int(buf));
417: }
418: }
419:
420: DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n"));
421:
422: for (i = 0; i < 4; ++i)
423: {
424: unsigned char cmd[10];
425: static buffer[512];
426:
427: cmd[0] = READ_10;
428: cmd[1] = 0;
429: xany2scsi(cmd+2, i);
430: cmd[6] = 0;
431: cmd[7] = 0;
432: cmd[8] = 1;
433: cmd[9] = 0;
434: aha1542_command(0, cmd, buffer, 512);
435: }
436: #endif
437: return 1;
438: }
439:
440: int aha1542_abort(int i)
441: {
442: DEB(printk("aha1542_abort\n"));
443: return 0;
444: }
445:
446: int aha1542_reset(void)
447: {
448: DEB(printk("aha1542_reset called\n"));
449: return 0;
450: }
451:
452: __asm__("
453: _aha1542_interrupt:
454: cld
455: pushl %eax
456: pushl %ecx
457: pushl %edx
458: push %ds
459: push %es
460: push %fs
461: movl $0x10,%eax
462: mov %ax,%ds
463: mov %ax,%es
464: movl $0x17,%eax
465: mov %ax,%fs
466: movb $0x20,%al
467: outb %al,$0xA0 # EOI to interrupt controller #1
468: jmp 1f # give port chance to breathe
469: 1: jmp 1f
470: 1: outb %al,$0x20
471: # Please, someone, change this to use the timer
472: # andl $0xfffeffff,_timer_active
473: movl $_aha1542_intr_handle,%edx
474: call *%edx # ``interesting'' way of handling intr.
475: pop %fs
476: pop %es
477: pop %ds
478: popl %edx
479: popl %ecx
480: popl %eax
481: iret
482: ");
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.