|
|
1.1 root 1: /***********************************************************************
2: * Module: hai154x.c
3: *
4: * Host Adapter Interface routines for the Adaptec AHA154XX series
5: * of host adapters.
6: *
7: * Much of the information used to create this driver was obtained
8: * from the AHA1540B/1542B Technical Reference Manual available from
9: * Adaptec by phone or snail mail at:
10: *
11: * Adaptec - Literature Department
12: * 691 South Milpitas Blvd.
13: * Milpitas, CA 95035
14: * (408) 945-8600
15: *
16: * Copyright (c), 1993 Christopher Sean Hilton, All Rights Reserved.
17: *
18: * Last Modified: Sat Jul 24 08:44:54 1993 by [chris]
19: *
20: */
21:
22: #define HA_MODULE /* Host Adaptor Module */
23: #define LOUIS_HACK 1 /* defined for Louis' hacks */
24:
25: #include <stddef.h>
26: #include <sys/coherent.h>
27: #include <sys/con.h>
28: #include <sys/devices.h>
29: #include <sys/types.h>
30: #include <sys/hdioctl.h>
31:
32: #include <sys/haiscsi.h>
33:
34: /*
35: * Configurable variables - see /etc/conf/hai/Space.c
36: */
37: extern unsigned short AHABASE;
38: extern unsigned short AHAINTR;
39: extern unsigned short AHADMACHAN;
40:
41: extern int HAI_SD_HDS;
42: extern int HAI_SD_SPT;
43:
44: #define CTRLREG (AHABASE + 0) /* Control Register (Write) */
45: #define HRST bit(7) /* Hard Reset */
46: #define SRST bit(6) /* Soft Reset */
47: #define IRST bit(5) /* Interrupt Reset */
48: #define SCRST bit(4) /* SCSI Bus Reset */
49:
50: #define STSREG (AHABASE + 0) /* Status Register (Read) */
51: #define STST bit(7) /* Self Test in progress */
52: #define DIAGF bit(6) /* Internal Diagnostic Failure */
53: #define INIT bit(5) /* Mailbox Initialization Required */
54: #define IDLE bit(4) /* SCSI Host Adapter Idle */
55: #define CDF bit(3) /* Command/Data Out Port Full */
56: #define DF bit(2) /* Data In Port Full */
57: #define INVDCMD bit(0) /* Invalid HA Command */
58:
59: #define CMDDATAOUT (AHABASE + 1) /* Command/Data Out (Write) */
60: #define NOP 0x00 /* No Operation (really?) */
61: #define MBINIT 0x01 /* Mail Box Initialization */
62: #define STARTSCSI 0x02 /* Start a SCSI Command */
63: #define STARTBIOS 0x03 /* Start a BIOS Command */
64: #define HAINQUIRY 0x04 /* HA Inquiry */
65: #define ENBLMBOA 0x05 /* Enable Mailbox Out Available Interrupt */
66: #define STSELTO 0x06 /* Set Selection Timeout */
67: #define SETBUSON 0x07 /* Set Bus on time */
68: #define SETBUSOFF 0x08 /* Set Bus off time */
69: #define SETXFER 0x09 /* Set transfer speed */
70: #define RETINSTDEV 0x0a /* Return Installed Devices */
71: #define RETCFGDATA 0x0b /* Return Configuration Data */
72: #define ENBLTRGTMD 0x0c /* Enable Target Mode */
73: #define RETSUDATA 0x0d /* Return Setup Data */
74:
75: #define DATAIN (AHABASE + 1)
76:
77: #define INTRFLGS (AHABASE + 2)
78: #define ANYINTR bit(7) /* Any Interrupt */
79: #define SCRD bit(3) /* SCSI Reset Detected */
80: #define HACC bit(2) /* HA Command Complete */
81: #define MBOA bit(1) /* MBO Empty */
82: #define MBIF bit(0) /* MBI Full */
83:
84: #define MBOFREE 0x00 /* Mailbox out is free */
85: #define MBOSTART 0x01 /* Start CCB in this Mailbox */
86: #define MBOABORT 0x02 /* Abort CCB in this Mailbox */
87:
88: #define MBIFREE 0x00 /* Mailbox in is free */
89: #define MBISUCCESS 0x01 /* Mailbox's CCB Completed Successfully */
90: #define MBIABORTED 0x02 /* Mailbox's CCB Aborted */
91: #define MBIABRTFLD 0x03 /* CCB to Abort not found */
92: #define MBIERROR 0x04 /* CCB Completed with error */
93:
94: #define TIMEOUT -1 /* Timeout from pollxxx() functions. */
95:
96: #define ST_HAINIT 0x0001 /* Host Adapter being initialized */
97: #define ST_HAIDLE 0x0002 /* Host Adapter is idle */
98:
99: /***********************************************************************
100: * Types
101: */
102:
103: #pragma align 1
104:
105: typedef union addr3_u { /* addr3_u for big/little endian conversions */
106: unsigned long value;
107: unsigned char byteval[sizeof(unsigned long)];
108: } addr3_t;
109:
110: typedef union mbo_u *mbo_p; /* Out Box to host adapter */
111:
112: typedef union mbo_u {
113: unsigned char cmd;
114: paddr_t ccbaddr;
115: } mbo_t;
116:
117: typedef union mbi_u *mbi_p; /* In Box from host adapter */
118:
119: typedef union mbi_u {
120: unsigned char sts;
121: paddr_t ccbaddr;
122: } mbi_t;
123:
124: typedef struct mb_s { /* Host adapter mailbox type */
125: mbo_t o[MAXDEVS]; /* One out box for each device */
126: mbi_t i[MAXDEVS]; /* One in box for each possible reply */
127: } mb_t;
128:
129: typedef struct haccb_s *haccb_p; /* Host Adapter Command/Control Block */
130:
131: typedef struct haccb_s {
132: unsigned char opcode;
133: unsigned char addrctrl;
134: unsigned char cdblen;
135: unsigned char senselen;
136: unsigned char datalen[3];
137: unsigned char bufaddr[3];
138: unsigned char linkaddr[3];
139: unsigned char linkid;
140: unsigned char hoststs;
141: unsigned char trgtsts;
142: unsigned char pad[2];
143: cdb_t cdb;
144: } haccb_t;
145:
146: typedef struct dsentry_s *dsentry_p;
147:
148: typedef struct dsentry_s {
149: unsigned char size[3];
150: unsigned char addr[3];
151: } dsentry_t;
152:
153: typedef struct dslist_s *dslist_p;
154:
155: typedef struct dslist_s {
156: dsentry_t entries[16];
157: } dslist_t;
158:
159: #pragma align
160:
161: /***********************************************************************
162: * Variables
163: */
164:
165: static int hastate; /* Host Adapter State */
166: static mb_t mb; /* Mailboxes for host adapter */
167: static haccb_t ccb[MAXDEVS]; /* CCB's for mailboxes */
168: static paddr_t ccbbase; /* ccbbase address for quick checkmail */
169: static srb_p actv[MAXDEVS]; /* Active srb's for each target */
170: static dslist_t ds[MAXDEVS]; /* Data segment lists one for each target */
171: static unsigned chkport = 0, /* Port for chkset/ckhclr */
172: chkstop = 0, /* Target value for chkset/chkclr */
173: chkval = 0; /* Value in port chkset/chkclr */
174: int hapresent; /* Host adapter present flag */
175:
176: /***********************************************************************
177: * Support Functions
178: */
179:
180: #define min(a, b) (((a) <= (b)) ? (a) : (b))
181:
182: /***********************************************************************
183: * chkclr() -- Check port (chkport) for bits (chkstop) to be clear.
184: * If clear return 1 else return 0. Leave value of
185: * port in chkval;
186: */
187:
188: static int chkclr()
189:
190: {
191: return ((chkval = inb(chkport)) & chkstop) == 0;
192: } /* chkclr() */
193:
194: /***********************************************************************
195: * chkset() -- Check port (chkport) for bits (chkstop) to be set.
196: * If all bits are set return 1 else return 0. Leave
197: * value of port in chkval.
198: */
199:
200: static int chkset()
201:
202: {
203: return ((chkval = inb(chkport)) & chkstop) == chkstop;
204: } /* chkset() */
205:
206: /***********************************************************************
207: * pollclr() -- Wait usec milliseconds for bit(s) to clear in a
208: * port.
209: */
210:
211: static int pollclr(port, bits, usec)
212: register unsigned port; /* port to watch */
213: register unsigned bits; /* bits to watch for */
214: unsigned usec; /* number of milliseconds to wait for */
215: {
216: register s;
217:
218: s = sphi();
219: chkport = port;
220: chkstop = bits;
221: busyWait(chkclr, usec);
222: spl(s);
223:
224: #if 1 /* DEBUG */
225: if ((chkval & bits) == 0)
226: return chkval;
227: else {
228: printf("pollclr: <Timeout Reg: 0x%x mask 0x%x value 0x%x>\n", port, bits, chkval);
229: return TIMEOUT;
230: }
231: #else
232: return ((chkval & bits) == 0) ? chkval : TIMEOUT;
233: #endif
234: } /* pollclr() */
235:
236: /***********************************************************************
237: * pollset() -- Wait usec milliseconds for bit(s) set in a port.
238: */
239:
240: static int pollset(port, bits, usec)
241: register unsigned port; /* port to watch */
242: register unsigned bits; /* bits to watch for */
243: unsigned usec; /* number of milliseconds to wait for */
244: {
245: register s;
246:
247: s = sphi();
248: chkport = port;
249: chkstop = bits;
250: busyWait(chkset, usec);
251: spl(s);
252:
253: #if 1 /* DEBUG */
254: if ((chkval & bits) == bits)
255: return chkval;
256: else {
257: printf("pollset: <Timeout Reg: 0x%x mask 0x%x value 0x%x>\n", port, bits, chkval);
258: return TIMEOUT;
259: }
260: #else
261: return ((chkval & bits) == bits) ? chkval : TIMEOUT;
262: #endif
263: } /* pollset() */
264:
265: /***********************************************************************
266: * hacc()
267: *
268: * Host Adapter Command Completed - Returns 1 if last host adapter
269: * command completed without error.
270: */
271:
272: static int hacc()
273:
274: {
275: register unsigned stsreg;
276:
277: #ifdef LOUIS_HACK
278: register unsigned louis_stsreg;
279: if((louis_stsreg = pollset(INTRFLGS, HACC, 350)) == TIMEOUT)
280: return 0;
281: printf("HACC - louis_stsreg: 0x%x\n", louis_stsreg);
282: #else
283: if (pollset(INTRFLGS, HACC, 350) == TIMEOUT)
284: return 0;
285: #endif
286:
287: stsreg = pollset(STSREG, IDLE, 350) & (IDLE | INIT | CDF | INVDCMD);
288: if (stsreg != IDLE) {
289: printf("Aha154x stuck - STSREG: 0x%x\n", stsreg);
290: return 0;
291: }
292: return 1;
293: } /* hacc() */
294:
295: /***********************************************************************
296: * haidle()
297: *
298: * Returns 1 if the Idle Bit is on in the adapter status register
299: */
300:
301: #define haidle() (pollset(STSREG, IDLE, 350) != TIMEOUT)
302:
303: /***********************************************************************
304: * gethabyte()
305: *
306: * Get a byte from the host adapter Data In register.
307: */
308:
309: static int gethabyte()
310:
311: {
312: if (pollset(STSREG, DF, 350) == TIMEOUT) {
313: printf("haiscsi: <gethabyte timeout (0x%x) 0x%x 0x%x>\n", STSREG, DF, chkval);
314: return TIMEOUT;
315: }
316: else
317: return (inb(DATAIN) & 0xff);
318: } /* gethabyte() */
319:
320: /***********************************************************************
321: * puthabyte()
322: *
323: * Write a byte to the host adapter Command/Data Out Register.
324: */
325:
326: static int puthabyte(b)
327: unsigned char b;
328:
329: {
330: if (pollclr(STSREG, CDF, 350) == TIMEOUT)
331: return 0;
332: else {
333: outb(CMDDATAOUT, b);
334: return 1;
335: }
336: } /* puthabyte() */
337:
338: /***********************************************************************
339: * is_154x()
340: *
341: * Returns a string indicating the type and revision of the AHA154x
342: * host adapter on the bus if it is out there. Caveat: if something
343: * else is out there that can respond to this message I don't know
344: * what will happen.
345: */
346:
347: static int is_154x(haport)
348: unsigned haport;
349: {
350: char buf[4],
351: *p;
352: int ch,
353: oldhaport,
354: s,
355: r = 0;
356:
357: oldhaport = AHABASE;
358: s = sphi();
359: AHABASE = haport;
360: if (haidle() && puthabyte(HAINQUIRY)) {
361: for (p = buf; p < buf + sizeof(buf); ++p) {
362: ch = gethabyte();
363: if (ch == TIMEOUT)
364: break;
365: else
366: *p = ch;
367: }
368: if (p >= buf + sizeof(buf)) {
369: outb(CTRLREG, IRST);
370: if ((pollset(STSREG, IDLE, 350) & IDLE) == IDLE) {
371: if (buf[0] == '\0') {
372: printf("AHA-1540 with 16 Head BIOS Detected\n");
373: /* SDS_HDS = 16; Should we? */
374: }
375: r = 1;
376: }
377: }
378: }
379: AHABASE = oldhaport;
380: spl(s);
381: return r;
382: } /* is_154x() */
383:
384: /***********************************************************************
385: * hareset()
386: *
387: * Reset the host adapter and leave it ready for operation.
388: */
389:
390: static int hareset()
391:
392: {
393: paddr_t mbaddr; /* Mail box array's paddr. */
394: int mbiok, /* Mail box initialization proceding ok */
395: stsreg, /* local copy of STSREG */
396: retval, /* return value */
397: s;
398:
399: retval = 0;
400: s = sphi();
401: outb(CTRLREG, SRST);
402: if ((stsreg = pollclr(STSREG, STST, 350)) == TIMEOUT)
403: printf("AHA-154x: Reset failed, host adapter stuck.\n");
404: else
405: #ifdef LOUIS_HACK
406: printf("Resetting - stsreg: 0x%x\n", stsreg);
407: #endif
408: if ((stsreg & DIAGF) || (stsreg & (INIT | IDLE)) != (INIT | IDLE))
409: printf("AHA-154x: Reset/diagnostics failed.\n");
410: else {
411:
412: mbaddr = vtop(&mb);
413: #ifdef LOUIS_HACK
414: printf("init commands bytes will be:\n");
415: printf(" MBINIT: 0x%x, COUNT: 0x%x, ADDR_MSB: 0x%x, ADDR_2: 0x%x, ADDR_LSB: 0x%x\n", \
416: MBINIT, (sizeof(mb) / (sizeof(mbo_t) + sizeof(mbi_t))), ((unsigned char *) &mbaddr)[2], \
417: ((unsigned char *) &mbaddr)[1], ((unsigned char *) &mbaddr)[0]);
418: #endif
419: mbiok = 1;
420: mbiok &= puthabyte(MBINIT);
421: mbiok &= puthabyte(sizeof(mb) / (sizeof(mbo_t) + sizeof(mbi_t)));
422: mbiok &= puthabyte(((unsigned char *) &mbaddr)[2]);
423: mbiok &= puthabyte(((unsigned char *) &mbaddr)[1]);
424: mbiok &= puthabyte(((unsigned char *) &mbaddr)[0]);
425: if (!mbiok || !hacc())
426: printf("AHA-154x: Mailbox initialization failed.\n");
427: else
428: retval = 1;
429: }
430: spl(s);
431: return retval;
432: } /* hareset() */
433:
434: /***********************************************************************
435: * dmacascade()
436: *
437: * Set the selected (AHADMACHAN) dma channel to cascade mode.
438: */
439:
440: static void dmacascade()
441:
442: {
443: int dmaporta, dmaportb, s;
444:
445: s = sphi();
446: if (AHADMACHAN == 0) {
447: dmaporta = 0x0b;
448: dmaportb = 0x0a;
449: } else {
450: dmaporta = 0xd6;
451: dmaportb = 0xd4;
452: }
453: outb(dmaporta, 0xc0 | (AHADMACHAN & 3));
454: outb(dmaportb, (AHADMACHAN & 3));
455: spl(s);
456: } /* dmacascade() */
457:
458: /***********************************************************************
459: * checkmail()
460: *
461: * Check the incoming mailboxes for messages. Do this on any Mail
462: * Box In Full interrupt and before you fail a command for timeout.
463: * The code to determine which target device finished by tid is a
464: * bit tricky and relies on the following assumptions:
465: *
466: * 1) The host adapter is installed in a Intel (big-endian)
467: * machine. Believe it or not there is (are) non-Intel CPU
468: * ISA bus machines. and the one that I know of is a M68000
469: * machine where this would not work.
470: *
471: * 2) The kernel's data space is physically contiguous and is
472: * never swapped out.
473: */
474:
475: static int checkmail()
476:
477: {
478: static int startid = 0;
479: int msgs = 0;
480: int sts;
481: int s;
482: register int id;
483: register srb_p r;
484: register int i = startid;
485:
486: do {
487: if (mb. i[i]. sts != MBIFREE) {
488: s = sphi();
489: sts = mb. i[i]. sts;
490: flip(mb. i[i]. ccbaddr);
491: id = (unsigned) ((mb. i[i]. ccbaddr & 0x00ffffffL) - ccbbase) / sizeof(haccb_t);
492: if (r = actv[id]) {
493: switch (sts) {
494: case MBIABRTFLD:
495: devmsg(r->dev, "Command 0x%x abort failed\n", r->cdb. g0. opcode);
496: case MBISUCCESS:
497: case MBIERROR:
498: r->status = ccb[id]. trgtsts;
499: break;
500: case MBIABORTED:
501: devmsg(r->dev, "Command 0x%x aborted successfully\n", r->cdb. g0. opcode);
502: r->status = ST_DRVABRT;
503: break;
504: default:
505: printf("Host Adapter Mailbox In value corrupted\n");
506: break;
507: }
508:
509: actv[id] = NULL;
510: if (r->cleanup)
511: (*(r->cleanup))(r);
512: msgs |= bit(id);
513: }
514: mb. i[i]. ccbaddr = 0;
515: spl(s);
516: }
517: else if (msgs)
518: break;
519: i = (i + 1) & 7;
520: } while (i != startid);
521: startid = i;
522:
523: return msgs;
524: } /* checkmail() */
525:
526: /***********************************************************************
527: * Driver Interface Functions
528: */
529:
530: /***********************************************************************
531: * hatimer()
532: *
533: * Host adapter Timeout handler.
534: */
535:
536: void hatimer()
537:
538: {
539: register int id;
540: register srb_p r;
541: register int active;
542: int s;
543:
544: s = sphi();
545: checkmail(); /* Cleanup any missed interrupts, etc. */
546: active = 0;
547: for (id = 0; id < MAXDEVS; ++id) {
548: if ((r = actv[id]) != NULL && r->timeout != 0) {
549: if (--r->timeout == 0) {
550: abortscsi(r);
551: r->status = ST_DRVABRT;
552: }
553: else
554: active = 1;
555: }
556: }
557: drvl[SCSIMAJOR]. d_time = active;
558: spl(s);
559: } /* hatimer() */
560:
561: /***********************************************************************
562: * haintr()
563: *
564: * SCSI interrupt handler for host adapter.
565: */
566:
567: void haintr()
568:
569: {
570: int intrflgs;
571:
572: intrflgs = inb(INTRFLGS);
573: if (intrflgs & ANYINTR)
574: outb(CTRLREG, IRST);
575:
576: if (hastate == ST_HAINIT)
577: return;
578: if (intrflgs & MBIF) {
579: checkmail();
580: return;
581: }
582: } /* haintr() */
583:
584: /***********************************************************************
585: * hainit()
586: *
587: * Initialize the host adapter for operation.
588: */
589:
590: int hainit()
591:
592: {
593: register int i;
594:
595: hastate = ST_HAINIT;
596: hapresent = 0;
597: printf("Host Adapter Module: AHA-154x v1.1\n");
598: if (!is_154x(AHABASE)) {
599: printf("hainit() failed: Adaptec AHA-154x not found.\n");
600: return 0;
601: }
602:
603: setivec(AHAINTR, haintr);
604: if (!(hapresent = hareset())) {
605: printf("hainit() failed: Could not initialize AHA-154x at (0x%x)\n", AHABASE);
606: return 0;
607: }
608:
609: for (i = 0; i < MAXDEVS; ++i) {
610: actv[i] = NULL;
611: mb. o[i]. ccbaddr = vtop(ccb + i);
612: flip(mb. o[i]. ccbaddr);
613: mb. o[i]. cmd = MBOFREE;
614: }
615: ccbbase = vtop(ccb);
616: dmacascade();
617: hastate = ST_HAIDLE;
618: return 1;
619: } /* hainit() */
620:
621: /***********************************************************************
622: * mkdslist()
623: *
624: * Make an Adaptec Data Segment list for a Scatter/Gather Request.
625: * Input: d - the memory area for the Scatter/Gather List.
626: * b - the bufaddr structure for the memory block.
627: */
628:
629: static int mkdslist(d, b)
630: register dsentry_p d;
631: bufaddr_p b;
632: {
633: paddr_t p_start;
634: size_t p_size;
635: paddr_t p_next;
636: int segments = 1;
637: register unsigned long start;
638: register unsigned long end;
639: dsentry_p l = d;
640:
641: switch (b->space) {
642: case KRNL_ADDR: /* Kernal Address */
643: case USER_ADDR: /* User Address (Anything goes) */
644: start = b->addr. caddr;
645: p_start = vtop(start);
646: break;
647: case SYSGLBL_ADDR: /* System Global address (yeah) */
648: start = b->addr. paddr;
649: p_start = P2P(start);
650: break;
651: case PHYS_ADDR: /* Physical Address - (who knows) */
652: default:
653: return 0;
654: }
655: end = start + b->size;
656: p_size = min(NBPC - (p_start & (NBPC - 1)), end - start);
657:
658: for ( ; ; ) {
659: d->size[2] = ((unsigned char *) &p_size)[0];
660: d->size[1] = ((unsigned char *) &p_size)[1];
661: d->size[0] = ((unsigned char *) &p_size)[2];
662: d->addr[2] = ((unsigned char *) &p_start)[0];
663: d->addr[1] = ((unsigned char *) &p_start)[1];
664: d->addr[0] = ((unsigned char *) &p_start)[2];
665: if (start + p_size >= end)
666: return segments;
667:
668: p_next = (b->space == SYSGLBL_ADDR) ? P2P(start + p_size) :
669: vtop(start + p_size);
670: if (p_next == p_start + p_size)
671: /* Continue Last Segment */
672: p_size += min(NBPC, end - start - p_size);
673: else {
674: /* Start New Segment */
675: p_start = p_next;
676: start += p_size;
677: p_size = min(NBPC, end - start);
678: ++d;
679: if (++segments > (sizeof(dslist_t) / sizeof(dsentry_t)))
680: return 0;
681: }
682: }
683: } /* mkdslist() */
684:
685: /***********************************************************************
686: * startscsi()
687: *
688: * Send a SCSI CDB to a target device on the bus.
689: */
690:
691: int startscsi(r)
692: register srb_p r;
693: {
694: register haccb_p c;
695: paddr_t bufaddr;
696: size_t datalen;
697: register int s;
698:
699: if (r->target >= MAXDEVS || r->lun >= MAXUNITS) {
700: printf("Illegal device ID: %d LUN: %d", r->target, r->lun);
701: return 0;
702: }
703:
704: ++r->tries;
705: if (actv[r->target]) {
706: devmsg(r->dev,
707: "Device busy: old opcode (0x%x) new opcode (0x%x)",
708: ccb[r->target]. cdb. g0. opcode,
709: r->cdb. g0. opcode);
710: return 0;
711: }
712:
713: s = sphi();
714: r->status = ST_PENDING;
715: c = ccb + r->target;
716: memset(c, 0, sizeof(haccb_t));
717: c->opcode = 0; /* Start SCSI CDB */
718: c->addrctrl = (r->target << 5) | (r->lun & 7);
719: if (r->xferdir & DMAREAD) c->addrctrl |= 0x08;
720: if (r->xferdir & DMAWRITE) c->addrctrl |= 0x10;
721: c->cdblen = cpycdb(&(c->cdb), &(r->cdb));
722: c->senselen = 1;
723:
724: /***********************************************************************
725: * Set up the CCB's Address here. This turned out to be a bit more
726: * complicated than I thought it would be.
727: */
728:
729: if (r->buf. space == PHYS_ADDR) {
730: c->datalen[0] = ((unsigned char *) &(r->buf. size))[2];
731: c->datalen[1] = ((unsigned char *) &(r->buf. size))[1];
732: c->datalen[2] = ((unsigned char *) &(r->buf. size))[0];
733: c->bufaddr[0] = ((unsigned char *) &(r->buf. addr. paddr))[2];
734: c->bufaddr[1] = ((unsigned char *) &(r->buf. addr. paddr))[1];
735: c->bufaddr[2] = ((unsigned char *) &(r->buf. addr. paddr))[0];
736: }
737: else {
738: datalen = mkdslist(ds[r->target]. entries, &(r->buf));
739: if (datalen == 0) {
740: printf("SCSI ID %d - Bad Scatter/Gather list\n", r->target);
741: spl(s);
742: return 0;
743: }
744: else if (datalen == 1)
745: memcpy(c->datalen, ds[r->target]. entries, 6);
746: else {
747: c->opcode = 2;
748: bufaddr = vtop(ds[r->target]. entries);
749: datalen *= 6;
750: c->datalen[0] = ((unsigned char *) &datalen)[2];
751: c->datalen[1] = ((unsigned char *) &datalen)[1];
752: c->datalen[2] = ((unsigned char *) &datalen)[0];
753: c->bufaddr[0] = ((unsigned char *) &bufaddr)[2];
754: c->bufaddr[1] = ((unsigned char *) &bufaddr)[1];
755: c->bufaddr[2] = ((unsigned char *) &bufaddr)[0];
756: }
757: }
758:
759: mb. o[r->target]. cmd = MBOSTART;
760: if (puthabyte(STARTSCSI) && (inb(STSREG) & INVDCMD) == 0) {
761: actv[r->target] = r;
762: if (r->timeout)
763: drvl[SCSIMAJOR]. d_time = 1;
764: }
765: else {
766: printf("startscsi() failed: Resetting host adapter.\n");
767: mb. o[r->target]. cmd = MBOFREE;
768: actv[r->target] = NULL;
769: r->status = ST_DRVABRT;
770: if (r->cleanup)
771: (*r->cleanup)(r);
772: hapresent = hareset();
773: return 0;
774: }
775:
776: spl(s);
777: return 1;
778: } /* startscsi() */
779:
780: /***********************************************************************
781: * abortscsi()
782: *
783: * Abort the SCSI Command at a target device on the bus.
784: */
785:
786: void abortscsi(r)
787: register srb_p r;
788: {
789: int s,
790: tries;
791:
792: printf("abortscsi(id: %d opcode: (0x%x))\n", r->target, r->cdb. g0. opcode);
793: s = sphi();
794: r->timeout = 0;
795: for (tries = 10; hapresent && tries > 0; --tries) {
796: mb. o[r->target]. cmd = MBOABORT;
797: if (puthabyte(STARTSCSI) && (inb(STSREG) & INVDCMD) == 0)
798: break;
799:
800: printf("abortscsi(): AHA-154x Command start failed.\n");
801: hapresent = hareset();
802: }
803:
804: if (tries <= 0)
805: printf("abortscsi() failed: Cannot reach host adapter\n");
806: else {
807: busyWait(checkmail, 1000);
808:
809: if (r->status == ST_PENDING) {
810: printf("abortscsi() failed: id %d\n", r->target);
811: resetdevice(r->target);
812:
813: actv[r->target] = NULL;
814: r->status = ST_DRVABRT;
815: if (r->cleanup)
816: (*r->cleanup)(r);
817: }
818: }
819:
820: spl(s);
821: } /* abortscsi() */
822:
823: /***********************************************************************
824: * resetdevice()
825: *
826: * Reset a SCSI target.
827: */
828:
829: void resetdevice(id)
830: register int id;
831: {
832: register haccb_p c = &(ccb[HAI_HAID]);
833: int tries;
834:
835: c->opcode = 0x81;
836: c->addrctrl = (id << 5);
837: for (tries = 10; tries > 0; --tries) {
838: if (!hapresent)
839: hapresent = hareset();
840: if (hapresent) {
841: mb. o[HAI_HAID]. cmd = MBOSTART;
842: if (puthabyte(STARTSCSI) && (inb(STSREG) & INVDCMD) == 0)
843: break;
844: }
845: }
846: } /* resetdevice() */
847:
848: /***********************************************************************
849: * haihdgeta() -- Get disk driver paramters.
850: *
851: * This function is provided to support the HDGETA/HDSETA I/O Controls
852: * so you don't need the old Adaptec SCSI driver to set up the partition
853: * table on initial setup. There is a catch-22 with this. You need
854: * to know the drive's geometry in order to set up the partition table
855: * but cannot get the drive's geometry until you have set up the partition
856: * table. We solve this by using the drive's size and then dividing
857: * down based upon SDS_HDS heads and SDS_SPT sectors per track. Every
858: * host adapter will want to do this differently. The Adaptec solution
859: * is the best that I've seen so far. (It allows you to use Huge (1.0
860: * GB) disks under DOS without trouble.
861: */
862:
863: void haihdgeta(hdp, diskcap)
864: register hdparm_t *hdp;
865: register unsigned diskcap;
866: {
867: unsigned short ncyl = (unsigned short) (diskcap / (HAI_SD_HDS * HAI_SD_SPT)),
868: landc = ncyl,
869: rwccp = 0xffff,
870: wpcc = 0xffff;
871:
872: memset(hdp, 0, sizeof(hdparm_t));
873: *((unsigned short *) hdp->ncyl) = ncyl;
874: *((unsigned short *) hdp->rwccp) = rwccp;
875: *((unsigned short *) hdp->wpcc) = wpcc;
876: *((unsigned short *) hdp->landc) = landc;
877:
878: hdp->nhead = HAI_SD_HDS;
879: if (hdp->nhead > 8)
880: hdp->ctrl |= 8;
881: hdp->nspt = HAI_SD_SPT;
882: } /* haihdseta() */
883:
884: /***********************************************************************
885: * haihdseta() -- Set disk parameters in accordance with HDSETA
886: * I/O Control.
887: *
888: * Set the disk paramters accordingly for a request from the fdisk
889: * program. This call really doesn't do anything on the adaptec or
890: * in the SCSI driver in general because SCSI Disks use Logical Block
891: * addressing rather than Cylinder/Head/Track addressing found with
892: * less intelligent Disk drive types. What this will do is allow
893: * the fdisk program to work so a user can format his disk and install
894: * Coherent on it (A Good Thing). This boils down to a fancy way to
895: * patch SDS_HDS and SDS_SPT.
896: */
897:
898: void haihdseta(hdp)
899: register hdparm_t *hdp;
900: {
901: HAI_SD_HDS = hdp->nhead;
902: HAI_SD_SPT = hdp->nspt;
903: } /* haihdseta() */
904:
905: /* End of file */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.