|
|
1.1 root 1: /*
2: * @(#)sd.c 1.1 86/02/03 Copyright (c) 1985 by Sun Microsystems, Inc.
3: */
4: #include <sys/param.h>
5: #include <sys/inode.h>
6: #include <sun/dklabel.h>
7: #include <sun/dkio.h>
8: #include <sys/buf.h>
9: #include <sundev/screg.h>
10: #include <sundev/sireg.h>
11: #include <sundev/scsi.h>
12: #include <machine/sunromvec.h>
13: #include <machine/idprom.h>
14: #include "saio.h"
15: #include "param.h"
16:
17: /* For RAM-based code, print detailed error messages */
18: #if !defined(SDBOOT) && !defined(BOOTBLOCK)
19: #define SDERRORS
20: #endif
21:
22: /*
23: * Scsi disk parameter block
24: */
25: struct sdparam {
26: int sd_target;
27: int sd_unit;
28: int sd_boff;
29: #ifdef SUN3
30: int sd_ha_type;
31: #endif
32: struct saioreq subsip[1]; /* Sip for host adapter */
33: };
34:
35: /*
36: * Record an error message from scsi
37: */
38: #define DEBUG FIXME
39:
40: #if (!defined(SDBOOT)) & !defined(STBOOT) & !defined(DEBUG)
41:
42: #define sc_error(msg) scerrmsg = msg
43: #define DEFERRED_ERRORS
44: extern char *scerrmsg;
45:
46: #else
47:
48: extern sc_error(); /* It's in sc.c */
49: #undef DEFERRED_ERRORS
50:
51: #endif
52:
53: /*
54: * Our DMA space
55: */
56: struct sddma {
57: char buffer[MAXBSIZE];
58: struct dk_label xlabel[1];
59: };
60:
61: #define SDBUF (((struct sddma *)sip->si_dmaaddr)->buffer)
62: #define label (((struct sddma *)sip->si_dmaaddr)->xlabel)
63:
64: /*
65: * What resources we need to run
66: */
67: struct devinfo sdinfo = {
68: 0, /* No device to map in */
69: sizeof (struct sddma),
70: sizeof (struct sdparam),
71: 0, /* Dummy devices */
72: 0, /* Dummy devices */
73: MAP_MAINMEM,
74: MAXBSIZE, /* transfer size */
75: };
76:
77: /*
78: * The interfaces we export
79: */
80: extern int xxprobe(), xxboot();
81: int sdopen(), sdclose(), sdstrategy();
82:
83: struct boottab sddriver = {
84: "sd", xxprobe, xxboot,
85: sdopen, sdclose, sdstrategy,
86: "sd: Adaptec SCSI disk", &sdinfo
87: };
88:
89: #ifndef BOOTBLOCK
90:
91: /*
92: * Test routine for isspinning() to see if SCSI disk is running.
93: */
94: sdspin(sip, dummy)
95: struct saioreq *sip;
96: int dummy;
97: {
98:
99: #ifdef lint
100: dummy = dummy;
101: #endif lint
102: sip->si_bn = 0;
103: sip->si_cc = 0;
104: sip->si_ma = 0;
105: return (sdcmd (SC_TEST_UNIT_READY, sip, 0));
106: }
107: #endif
108:
109: #ifdef SUN3
110: /*
111: * Determine type of host adaptor interface, si or sc.
112: * Returns 1 if si host adaptor and 0 if sc host adaptor.
113: */
114: sd_probe(sip)
115: struct saioreq *sip;
116: {
117: if (siprobe(sip)) {
118: return (1);
119: } else {
120: return (0);
121: }
122: }
123: #endif
124:
125: /*
126: * Open the SCSI Disk controller
127: */
128: sdopen(sip)
129: register struct saioreq *sip;
130: {
131: register struct sdparam *sdp;
132: register short *sp, sum;
133: register int count, r;
134:
135: sdp = (struct sdparam *)sip->si_devdata;
136: bzero( (char *)sdp, (sizeof (struct sdparam)));
137:
138: /*
139: * Open the host adapter
140: */
141: *sdp->subsip = *sip; /* Initialize sub-sip */
142: #ifdef SUN3
143: {
144: extern struct boottab scdriver;
145: extern struct boottab sidriver;
146:
147: /* FIXME, find out which scsi interface to use */
148: if (sd_probe(sip)) {
149: sdp->sd_ha_type = 1;
150:
151: /* FIXME, must vector thru table */
152: sdp->subsip->si_boottab = &sidriver;
153: } else {
154: sdp->sd_ha_type = 0;
155:
156: /* FIXME, must vector thru table */
157: sdp->subsip->si_boottab = &scdriver;
158: }
159:
160: }
161: #endif
162: #ifdef SUN2
163: {
164: extern struct boottab scdriver;
165:
166: sdp->subsip->si_boottab = &scdriver;
167: }
168: #endif
169: sdp->subsip->si_unit = sip->si_unit >> 2; /* Target number */
170: r = devopen(sdp->subsip);
171: if (r < 0) return r;
172:
173: sdp->sd_unit = sip->si_unit & 0x03; /* Logical unit number */
174:
175: #ifndef BOOTBLOCK
176: /*
177: * Check that the disk is up and running...
178: */
179: switch (isspinning(sdspin, (char *)sip, 0)) {
180:
181: default: /* Error from sdspin */
182: case 0: /* Disk still not ready */
183: /* isspinning has already printed "Giving up..." */
184: return (-1);
185:
186: case 1:
187: break;
188:
189: case 2:
190: DELAY(1000000); /* one second delay after spinup */
191: break;
192: }
193: #endif
194:
195: /*
196: * Actually read the label
197: */
198: label->dkl_magic = 0;
199: sip->si_ma = (char *)label;
200: sip->si_cc = SECSIZE;
201: sip->si_bn = 0; /* Read block #0 */
202: if (sdcmd(SC_READ, sip, 1) <= 0) {
203: return (-1);
204: }
205: if (chklabel(label))
206: return -1;
207: sdp->sd_boff = (unsigned short)(label->dkl_map[sip->si_boff].dkl_cylno)
208: * (unsigned short)(label->dkl_nhead * label->dkl_nsect);
209: return (0);
210: }
211:
212: /*
213: * Execute reads or writes for the outside world.
214: */
215: sdstrategy(sip, rw)
216: struct saioreq *sip;
217: register int rw;
218: {
219: rw = sdcmd(rw == WRITE ? SC_WRITE : SC_READ, sip, 1);
220: if (rw < 0)
221: rw = 0;
222: return rw;
223: }
224:
225: /*
226: * Internal interface to the disk command set
227: *
228: * Returns the character count read (or 1 if count==0) for success,
229: * returns 0 for failure, or -1 for severe unretryable failure.
230: */
231: int
232: sdcmd(cmd, sip, errprint)
233: int cmd;
234: register struct saioreq *sip;
235: int errprint;
236: {
237: int blkno, acount;
238: register char *buf;
239: register struct sdparam *sdp;
240: struct scsi_cdb cdb, scdb;
241: struct scsi_scb scb, sscb;
242: register int retry, r, i, count;
243:
244: blkno = sip->si_bn;
245: acount = sip->si_cc;
246: buf = sip->si_ma;
247: sdp = (struct sdparam *)sip->si_devdata;
248:
249: if (cmd == SC_WRITE)
250: bcopy(buf, SDBUF, (unsigned)acount);
251:
252: /* set up cdb */
253: bzero((char *) &cdb, sizeof cdb);
254: cdb.cmd = cmd;
255: cdb.lun = sdp->sd_unit;
256: blkno += sdp->sd_boff;
257: cdbaddr(&cdb, blkno);
258: count = (acount + SECSIZE -1) & ~(SECSIZE-1);
259: cdb.count = count / SECSIZE;
260: retry = 0;
261: do {
262: sdp->subsip->si_cc = count;
263: sdp->subsip->si_ma = SDBUF;
264: #ifdef SUN3
265: if (sdp->sd_ha_type)
266: r = sidoit(&cdb, &scb, sdp->subsip);
267: else
268: #endif
269: r = scdoit(&cdb, &scb, sdp->subsip);
270: if (r < 0)
271: return -1; /* Major SCSI bus error, already printed */
272: if (scb.chk) {
273: bzero((char *) &scdb, sizeof scdb);
274: scdb.cmd = SC_REQUEST_SENSE;
275: scdb.lun = sdp->sd_unit;
276: scdb.count = sizeof (struct scsi_sense);
277: sdp->subsip->si_cc = scdb.count;
278: sdp->subsip->si_ma = SDBUF;
279: #ifdef SUN3
280: if (sdp->sd_ha_type)
281: i = sidoit(&scdb, &sscb, sdp->subsip);
282: else
283: #endif
284: i = scdoit(&scdb, &sscb, sdp->subsip);
285: if (i >= 4) { /* all the sense Adaptec gives us */
286: #ifndef DEFERRED_ERRORS
287: if (errprint) sd_pr_sense(SDBUF, i);
288: #endif
289: continue;
290: } else { /* can't get sense, give up */
291: if (errprint) {
292: printf("sd: scsi %s\n",
293: #ifdef DEFERRED_ERRORS
294: scerrmsg ? scerrmsg :
295: #endif
296: "sense failed");
297: }
298: return (0);
299: }
300: } else if (scb.busy) {
301: sc_error("disk busy");
302: DELAY(100000);
303: continue;
304: }
305: if (r != count) {
306: #ifndef DEFERRED_ERRORS
307: if (errprint)
308: printf("sd: dma count is %d wanted %d\n",
309: r, count);
310: #endif
311: continue;
312: }
313: if (cmd == SC_READ)
314: bcopy(SDBUF, buf, (unsigned)acount);
315: #ifdef DEFERRED_ERRORS
316: scerrmsg = 0;
317: #endif
318: return (count ? count : 1);
319: } while (retry++ < 16);
320: #ifdef DEFERRED_ERRORS
321: if (errprint) {
322: if (scb.chk) {
323: sd_pr_sense(SDBUF, i);
324: } else if (scerrmsg) {
325: printf("sd: scsi %s\n", scerrmsg);
326: } else if (r != count) {
327: printf("sd: dma count is %d wanted %d\n", r, count);
328: } else {
329: /* we should never get this far */
330: printf("sd: retry count exceeded\n");
331: }
332: }
333: #endif
334: return (0);
335: }
336:
337: #ifdef SDERRORS
338: char *class_00_errors[] = {
339: "No sense",
340: "No index signal",
341: "No seek complete",
342: "Write fault",
343: "Drive not ready",
344: "Drive not selected",
345: "No track 00",
346: "Multiple drives selected",
347: "No address acknowledged",
348: "Media not loaded",
349: "Insufficient capacity",
350: };
351:
352: char *class_01_errors[] = {
353: "I.D. CRC error",
354: "Unrecoverable data error",
355: "I.D. address mark not found",
356: "Data address mark not found",
357: "Record not found",
358: "Seek error",
359: "DMA timeout error",
360: "Write protected",
361: "Correctable data check",
362: "Bad block found",
363: "Interleave error",
364: "Data transfer incomplete",
365: "Unformatted or bad format on drive",
366: "Self test failed",
367: "Defective track (media errors)",
368: };
369:
370: char *class_02_errors[] = {
371: "Invalid command",
372: "Illegal block address",
373: "Aborted",
374: "Volume overflow",
375: };
376:
377: char **sc_errors[] = {
378: class_00_errors,
379: class_01_errors,
380: class_02_errors,
381: 0, 0, 0, 0,
382: };
383:
384: int sc_errct[] = {
385: sizeof class_00_errors / sizeof (char *),
386: sizeof class_01_errors / sizeof (char *),
387: sizeof class_02_errors / sizeof (char *),
388: 0, 0, 0, 0,
389: };
390:
391: char *sc_sense7_keys [] = {
392: "No sense",
393: "Recoverable error",
394: "Not ready",
395: "Media error",
396: "Hardware error",
397: "Illegal request",
398: "Media change",
399: "Write protect",
400: "Diagnostic unique",
401: "Vendor unique",
402: "Power up failed",
403: "Aborted command",
404: "Equal",
405: "Volume overflow",
406: };
407: #endif SDERRORS
408:
409: /*
410: * Print out sense info.
411: */
412: sd_pr_sense(sp, len)
413: register unsigned char *sp;
414: register int len;
415: {
416:
417: #ifndef SDERRORS
418: printf("sd: error");
419: while (--len >= 0) {
420: printf(" %x", *sp++);
421: }
422: printf("\n");
423: #else SDERRORS
424: #ifdef lint
425: len = len; /* Avoid spurious "len unused" messages */
426: #endif lint
427: printf("sd: ");
428: if (((struct scsi_sense *)sp)->class <= 6) {
429: register struct scsi_sense *sense;
430:
431: sense = (struct scsi_sense *) sp;
432: if (sense->code < sc_errct[sense->class]) {
433: printf("%s", sc_errors[sense->class][sense->code]);
434: } else {
435: printf("error %x", *sp);
436: }
437: if (sense->adr_val) {
438: printf("- block no. %d", (sense->high_addr << 16) |
439: (sense->mid_addr << 8) | sense->low_addr);
440: }
441: } else { /* Sense class 7: the standardized one */
442: register struct scsi_ext_sense *sense7;
443:
444: sense7 = (struct scsi_ext_sense *) sp;
445: if (sense7->fil_mk) {
446: printf("file mark ");
447: }
448: if (sense7->eom) {
449: printf("end of medium ");
450: }
451: if (sense7->key
452: < sizeof (sc_sense7_keys) / sizeof (sc_sense7_keys[0])) {
453: printf("%s", sc_sense7_keys[sense7->key]);
454: } else {
455: printf("sense key %x", sense7->key);
456: }
457: printf(" block no. %x", (sense7->info_1 << 24) |
458: (sense7->info_2 << 16) | (sense7->info_3 << 8) |
459: sense7->info_4);
460: }
461: printf("\n");
462: #endif SDERRORS
463: }
464:
465:
466: /*
467: * Close scsi disk
468: *
469: * We must close the host adapter too.
470: */
471: int
472: sdclose(sip)
473: struct saioreq *sip;
474: {
475: devclose(((struct sdparam *)sip->si_devdata)->subsip);
476: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.