Annotation of sys/arch/vax/mscp/mscp_subr.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: mscp_subr.c,v 1.9 2005/11/24 04:54:49 brad Exp $ */
2: /* $NetBSD: mscp_subr.c,v 1.18 2001/11/13 07:38:28 lukem Exp $ */
3: /*
4: * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
5: * Copyright (c) 1988 Regents of the University of California.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley by
9: * Chris Torek.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: *
35: * @(#)mscp.c 7.5 (Berkeley) 12/16/90
36: */
37:
38: /*
39: * MSCP generic driver routines
40: */
41:
42: #include <sys/cdefs.h>
43:
44: #include <sys/param.h>
45: #include <sys/device.h>
46: #include <sys/buf.h>
47: #include <sys/systm.h>
48: #include <sys/proc.h>
49:
50: #include <machine/bus.h>
51: #include <machine/sid.h>
52:
53: #include <arch/vax/mscp/mscp.h>
54: #include <arch/vax/mscp/mscpreg.h>
55: #include <arch/vax/mscp/mscpvar.h>
56:
57: #include "ra.h"
58: #include "mt.h"
59:
60: #define b_forw b_hash.le_next
61:
62: int mscp_match(struct device *, struct cfdata *, void *);
63: void mscp_attach(struct device *, struct device *, void *);
64: void mscp_start(struct mscp_softc *);
65: int mscp_init(struct mscp_softc *);
66: void mscp_initds(struct mscp_softc *);
67: int mscp_waitstep(struct mscp_softc *, int, int);
68:
69: struct cfattach mscpbus_ca = {
70: sizeof(struct mscp_softc), (cfmatch_t)mscp_match, mscp_attach
71: };
72:
73: struct cfdriver mscpbus_cd = {
74: NULL, "mscpbus", DV_DULL
75: };
76:
77: #define READ_SA (bus_space_read_2(mi->mi_iot, mi->mi_sah, 0))
78: #define READ_IP (bus_space_read_2(mi->mi_iot, mi->mi_iph, 0))
79: #define WRITE_IP(x) bus_space_write_2(mi->mi_iot, mi->mi_iph, 0, (x))
80: #define WRITE_SW(x) bus_space_write_2(mi->mi_iot, mi->mi_swh, 0, (x))
81:
82: struct mscp slavereply;
83:
84: /*
85: * This function is for delay during init. Some MSCP clone card (Dilog)
86: * can't handle fast read from its registers, and therefore need
87: * a delay between them.
88: */
89:
90: #define DELAYTEN 1000
91: int
92: mscp_waitstep(mi, mask, result)
93: struct mscp_softc *mi;
94: int mask, result;
95: {
96: int status = 1;
97:
98: if ((READ_SA & mask) != result) {
99: volatile int count = 0;
100: while ((READ_SA & mask) != result) {
101: DELAY(10000);
102: count += 1;
103: if (count > DELAYTEN)
104: break;
105: }
106: if (count > DELAYTEN)
107: status = 0;
108: }
109: return status;
110: }
111:
112: int
113: mscp_match(parent, match, aux)
114: struct device *parent;
115: struct cfdata *match;
116: void *aux;
117: {
118: struct mscp_attach_args *ma = aux;
119:
120: #if NRA || NRX
121: if (ma->ma_type & MSCPBUS_DISK)
122: return 1;
123: #endif
124: #if NMT
125: if (ma->ma_type & MSCPBUS_TAPE)
126: return 1;
127: #endif
128: return 0;
129: };
130:
131: void
132: mscp_attach(parent, self, aux)
133: struct device *parent, *self;
134: void *aux;
135: {
136: struct mscp_attach_args *ma = aux;
137: struct mscp_softc *mi = (void *)self;
138: volatile struct mscp *mp;
139: volatile int i;
140: int timeout, next = 0;
141:
142: mi->mi_mc = ma->ma_mc;
143: mi->mi_me = NULL;
144: mi->mi_type = ma->ma_type;
145: mi->mi_uda = ma->ma_uda;
146: mi->mi_dmat = ma->ma_dmat;
147: mi->mi_dmam = ma->ma_dmam;
148: mi->mi_iot = ma->ma_iot;
149: mi->mi_iph = ma->ma_iph;
150: mi->mi_sah = ma->ma_sah;
151: mi->mi_swh = ma->ma_swh;
152: mi->mi_ivec = ma->ma_ivec;
153: mi->mi_adapnr = ma->ma_adapnr;
154: mi->mi_ctlrnr = ma->ma_ctlrnr;
155: *ma->ma_softc = mi;
156: /*
157: * Go out to init the bus, so that we can give commands
158: * to its devices.
159: */
160: mi->mi_cmd.mri_size = NCMD;
161: mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc;
162: mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd;
163: mi->mi_rsp.mri_size = NRSP;
164: mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc;
165: mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp;
166: SIMPLEQ_INIT(&mi->mi_resq);
167:
168: if (mscp_init(mi)) {
169: printf("%s: can't init, controller hung\n",
170: mi->mi_dev.dv_xname);
171: return;
172: }
173: for (i = 0; i < NCMD; i++) {
174: mi->mi_mxiuse |= (1 << i);
175: if (bus_dmamap_create(mi->mi_dmat, (64*1024), 16, (64*1024),
176: 0, BUS_DMA_NOWAIT, &mi->mi_xi[i].mxi_dmam)) {
177: printf("Couldn't alloc dmamap %d\n", i);
178: return;
179: }
180: }
181:
182:
183: #if NRA
184: if (ma->ma_type & MSCPBUS_DISK) {
185: extern struct mscp_device ra_device;
186:
187: mi->mi_me = &ra_device;
188: }
189: #endif
190: #if NMT
191: if (ma->ma_type & MSCPBUS_TAPE) {
192: extern struct mscp_device mt_device;
193:
194: mi->mi_me = &mt_device;
195: }
196: #endif
197: /*
198: * Go out and search for sub-units on this MSCP bus,
199: * and call config_found for each found.
200: */
201: findunit:
202: mp = mscp_getcp(mi, MSCP_DONTWAIT);
203: if (mp == NULL)
204: panic("mscpattach: no packets");
205: mp->mscp_opcode = M_OP_GETUNITST;
206: mp->mscp_unit = next;
207: mp->mscp_modifier = M_GUM_NEXTUNIT;
208: *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
209: slavereply.mscp_opcode = 0;
210:
211: i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
212: mp = &slavereply;
213: timeout = 1000;
214: while (timeout-- > 0) {
215: DELAY(10000);
216: if (mp->mscp_opcode)
217: goto gotit;
218: }
219: printf("%s: no response to Get Unit Status request\n",
220: mi->mi_dev.dv_xname);
221: return;
222:
223: gotit: /*
224: * Got a slave response. If the unit is there, use it.
225: */
226: switch (mp->mscp_status & M_ST_MASK) {
227:
228: case M_ST_SUCCESS: /* worked */
229: case M_ST_AVAILABLE: /* found another drive */
230: break; /* use it */
231:
232: case M_ST_OFFLINE:
233: /*
234: * Figure out why it is off line. It may be because
235: * it is nonexistent, or because it is spun down, or
236: * for some other reason.
237: */
238: switch (mp->mscp_status & ~M_ST_MASK) {
239:
240: case M_OFFLINE_UNKNOWN:
241: /*
242: * No such drive, and there are none with
243: * higher unit numbers either, if we are
244: * using M_GUM_NEXTUNIT.
245: */
246: mi->mi_ierr = 3;
247: return;
248:
249: case M_OFFLINE_UNMOUNTED:
250: /*
251: * The drive is not spun up. Use it anyway.
252: *
253: * N.B.: this seems to be a common occurrance
254: * after a power failure. The first attempt
255: * to bring it on line seems to spin it up
256: * (and thus takes several minutes). Perhaps
257: * we should note here that the on-line may
258: * take longer than usual.
259: */
260: break;
261:
262: default:
263: /*
264: * In service, or something else equally unusable.
265: */
266: printf("%s: unit %d off line: ", mi->mi_dev.dv_xname,
267: mp->mscp_unit);
268: mscp_printevent((struct mscp *)mp);
269: next++;
270: goto findunit;
271: }
272: break;
273:
274: default:
275: printf("%s: unable to get unit status: ", mi->mi_dev.dv_xname);
276: mscp_printevent((struct mscp *)mp);
277: return;
278: }
279:
280: /*
281: * If we get a lower number, we have circulated around all
282: * devices and are finished, otherwise try to find next unit.
283: * We shouldn't ever get this, it's a workaround.
284: */
285: if (mp->mscp_unit < next)
286: return;
287:
288: next = mp->mscp_unit + 1;
289: goto findunit;
290: }
291:
292:
293: /*
294: * The ctlr gets initialised, normally after boot but may also be
295: * done if the ctlr gets in an unknown state. Returns 1 if init
296: * fails, 0 otherwise.
297: */
298: int
299: mscp_init(mi)
300: struct mscp_softc *mi;
301: {
302: struct mscp *mp;
303: volatile int i;
304: int status, count;
305: unsigned int j = 0;
306:
307: /*
308: * While we are thinking about it, reset the next command
309: * and response indices.
310: */
311: mi->mi_cmd.mri_next = 0;
312: mi->mi_rsp.mri_next = 0;
313:
314: mi->mi_flags |= MSC_IGNOREINTR;
315:
316: if ((mi->mi_type & MSCPBUS_KDB) == 0)
317: WRITE_IP(0); /* Kick off */;
318:
319: status = mscp_waitstep(mi, MP_STEP1, MP_STEP1);/* Wait to it wakes up */
320: if (status == 0)
321: return 1; /* Init failed */
322: if (READ_SA & MP_ERR) {
323: (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
324: return 1;
325: }
326:
327: /* step1 */
328: WRITE_SW(MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) |
329: MP_IE | (mi->mi_ivec >> 2));
330: status = mscp_waitstep(mi, STEP1MASK, STEP1GOOD);
331: if (status == 0) {
332: (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
333: return 1;
334: }
335:
336: /* step2 */
337: WRITE_SW(((mi->mi_dmam->dm_segs[0].ds_addr & 0xffff) +
338: offsetof(struct mscp_pack, mp_ca.ca_rspdsc[0])) |
339: (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0));
340: status = mscp_waitstep(mi, STEP2MASK, STEP2GOOD(mi->mi_ivec >> 2));
341: if (status == 0) {
342: (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
343: return 1;
344: }
345:
346: /* step3 */
347: WRITE_SW((mi->mi_dmam->dm_segs[0].ds_addr >> 16));
348: status = mscp_waitstep(mi, STEP3MASK, STEP3GOOD);
349: if (status == 0) {
350: (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
351: return 1;
352: }
353: i = READ_SA & 0377;
354: printf(": version %d model %d\n", i & 15, i >> 4);
355:
356: #define BURST 4 /* XXX */
357: if (mi->mi_type & MSCPBUS_UDA) {
358: WRITE_SW(MP_GO | (BURST - 1) << 2);
359: printf("%s: DMA burst size set to %d\n",
360: mi->mi_dev.dv_xname, BURST);
361: }
362: WRITE_SW(MP_GO);
363:
364: mscp_initds(mi);
365: mi->mi_flags &= ~MSC_IGNOREINTR;
366:
367: /*
368: * Set up all necessary info in the bus softc struct, get a
369: * mscp packet and set characteristics for this controller.
370: */
371: mi->mi_credits = MSCP_MINCREDITS + 1;
372: mp = mscp_getcp(mi, MSCP_DONTWAIT);
373:
374: mi->mi_credits = 0;
375: mp->mscp_opcode = M_OP_SETCTLRC;
376: mp->mscp_unit = mp->mscp_modifier = mp->mscp_flags =
377: mp->mscp_sccc.sccc_version = mp->mscp_sccc.sccc_hosttimo =
378: mp->mscp_sccc.sccc_time = mp->mscp_sccc.sccc_time1 =
379: mp->mscp_sccc.sccc_errlgfl = 0;
380: mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | M_CF_THIS;
381: *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
382: i = READ_IP;
383:
384: count = 0;
385: while (count < DELAYTEN) {
386: if (((volatile int)mi->mi_flags & MSC_READY) != 0)
387: break;
388: if ((j = READ_SA) & MP_ERR)
389: goto out;
390: DELAY(10000);
391: count += 1;
392: }
393: if (count == DELAYTEN) {
394: out:
395: printf("%s: couldn't set ctlr characteristics, sa=%x\n",
396: mi->mi_dev.dv_xname, j);
397: return 1;
398: }
399: return 0;
400: }
401:
402: /*
403: * Initialise the various data structures that control the mscp protocol.
404: */
405: void
406: mscp_initds(mi)
407: struct mscp_softc *mi;
408: {
409: struct mscp_pack *ud = mi->mi_uda;
410: struct mscp *mp;
411: int i;
412:
413: for (i = 0, mp = ud->mp_rsp; i < NRSP; i++, mp++) {
414: ud->mp_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT |
415: (mi->mi_dmam->dm_segs[0].ds_addr +
416: offsetof(struct mscp_pack, mp_rsp[i].mscp_cmdref));
417: mp->mscp_addr = &ud->mp_ca.ca_rspdsc[i];
418: mp->mscp_msglen = MSCP_MSGLEN;
419: }
420: for (i = 0, mp = ud->mp_cmd; i < NCMD; i++, mp++) {
421: ud->mp_ca.ca_cmddsc[i] = MSCP_INT |
422: (mi->mi_dmam->dm_segs[0].ds_addr +
423: offsetof(struct mscp_pack, mp_cmd[i].mscp_cmdref));
424: mp->mscp_addr = &ud->mp_ca.ca_cmddsc[i];
425: mp->mscp_msglen = MSCP_MSGLEN;
426: if (mi->mi_type & MSCPBUS_TAPE)
427: mp->mscp_vcid = 1;
428: }
429: }
430:
431: static void mscp_kickaway(struct mscp_softc *);
432:
433: void
434: mscp_intr(mi)
435: struct mscp_softc *mi;
436: {
437: struct mscp_pack *ud = mi->mi_uda;
438:
439: if (mi->mi_flags & MSC_IGNOREINTR)
440: return;
441: /*
442: * Check for response and command ring transitions.
443: */
444: if (ud->mp_ca.ca_rspint) {
445: ud->mp_ca.ca_rspint = 0;
446: mscp_dorsp(mi);
447: }
448: if (ud->mp_ca.ca_cmdint) {
449: ud->mp_ca.ca_cmdint = 0;
450: MSCP_DOCMD(mi);
451: }
452:
453: /*
454: * If there are any not-yet-handled request, try them now.
455: */
456: if (SIMPLEQ_FIRST(&mi->mi_resq))
457: mscp_kickaway(mi);
458: }
459:
460: int
461: mscp_print(aux, name)
462: void *aux;
463: const char *name;
464: {
465: struct drive_attach_args *da = aux;
466: struct mscp *mp = da->da_mp;
467: int type = mp->mscp_guse.guse_mediaid;
468:
469: if (name) {
470: printf("%c%c", MSCP_MID_CHAR(2, type), MSCP_MID_CHAR(1, type));
471: if (MSCP_MID_ECH(0, type))
472: printf("%c", MSCP_MID_CHAR(0, type));
473: printf("%d at %s drive %d", MSCP_MID_NUM(type), name,
474: mp->mscp_unit);
475: }
476: return UNCONF;
477: }
478:
479: /*
480: * common strategy routine for all types of MSCP devices.
481: */
482: void
483: mscp_strategy(bp, usc)
484: struct buf *bp;
485: struct device *usc;
486: {
487: struct mscp_softc *mi = (void *)usc;
488: int s = spl6();
489:
490: /* SIMPLEQ_INSERT_TAIL(&mi->mi_resq, bp, xxx) */
491: bp->b_actf = NULL;
492: *mi->mi_resq.sqh_last = bp;
493: mi->mi_resq.sqh_last = &bp->b_actf;
494: mscp_kickaway(mi);
495: splx(s);
496: }
497:
498:
499: void
500: mscp_kickaway(mi)
501: struct mscp_softc *mi;
502: {
503: struct buf *bp;
504: struct mscp *mp;
505: int next;
506:
507: while ((bp = SIMPLEQ_FIRST(&mi->mi_resq))) {
508: /*
509: * Ok; we are ready to try to start a xfer. Get a MSCP packet
510: * and try to start...
511: */
512: if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) {
513: if (mi->mi_credits > MSCP_MINCREDITS)
514: printf("%s: command ring too small\n",
515: mi->mi_dev.dv_parent->dv_xname);
516: /*
517: * By some (strange) reason we didn't get a MSCP packet.
518: * Just return and wait for free packets.
519: */
520: return;
521: }
522:
523: if ((next = (ffs(mi->mi_mxiuse) - 1)) < 0)
524: panic("no mxi buffers");
525: mi->mi_mxiuse &= ~(1 << next);
526: if (mi->mi_xi[next].mxi_inuse)
527: panic("mxi inuse");
528: /*
529: * Set up the MSCP packet and ask the ctlr to start.
530: */
531: mp->mscp_opcode =
532: (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
533: mp->mscp_cmdref = next;
534: mi->mi_xi[next].mxi_bp = bp;
535: mi->mi_xi[next].mxi_mp = mp;
536: mi->mi_xi[next].mxi_inuse = 1;
537: bp->b_resid = next;
538: (*mi->mi_me->me_fillin)(bp, mp);
539: (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, &mi->mi_xi[next]);
540: if ((mi->mi_resq.sqh_first = bp->b_actf) == NULL)
541: mi->mi_resq.sqh_last = &mi->mi_resq.sqh_first;
542: #if 0
543: mi->mi_w = bp->b_actf;
544: #endif
545: }
546: }
547:
548: void
549: mscp_dgo(mi, mxi)
550: struct mscp_softc *mi;
551: struct mscp_xi *mxi;
552: {
553: volatile int i;
554: struct mscp *mp;
555:
556: /*
557: * Fill in the MSCP packet and move the buffer to the I/O wait queue.
558: */
559: mp = mxi->mxi_mp;
560: mp->mscp_seq.seq_buffer = mxi->mxi_dmam->dm_segs[0].ds_addr;
561:
562: *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
563: i = READ_IP;
564: }
565:
566: #ifdef DIAGNOSTIC
567: /*
568: * Dump the entire contents of an MSCP packet in hex. Mainly useful
569: * for debugging....
570: */
571: void
572: mscp_hexdump(mp)
573: struct mscp *mp;
574: {
575: long *p = (long *) mp;
576: int i = mp->mscp_msglen;
577:
578: if (i > 256) /* sanity */
579: i = 256;
580: i /= sizeof (*p); /* ASSUMES MULTIPLE OF sizeof(long) */
581: while (--i >= 0)
582: printf("0x%x ", (int)*p++);
583: printf("\n");
584: }
585: #endif
586:
587: /*
588: * MSCP error reporting
589: */
590:
591: /*
592: * Messages for the various subcodes.
593: */
594: static char unknown_msg[] = "unknown subcode";
595:
596: /*
597: * Subcodes for Success (0)
598: */
599: static char *succ_msgs[] = {
600: "normal", /* 0 */
601: "spin down ignored", /* 1 = Spin-Down Ignored */
602: "still connected", /* 2 = Still Connected */
603: unknown_msg,
604: "dup. unit #", /* 4 = Duplicate Unit Number */
605: unknown_msg,
606: unknown_msg,
607: unknown_msg,
608: "already online", /* 8 = Already Online */
609: unknown_msg,
610: unknown_msg,
611: unknown_msg,
612: unknown_msg,
613: unknown_msg,
614: unknown_msg,
615: unknown_msg,
616: "still online", /* 16 = Still Online */
617: };
618:
619: /*
620: * Subcodes for Invalid Command (1)
621: */
622: static char *icmd_msgs[] = {
623: "invalid msg length", /* 0 = Invalid Message Length */
624: };
625:
626: /*
627: * Subcodes for Command Aborted (2)
628: */
629: /* none known */
630:
631: /*
632: * Subcodes for Unit Offline (3)
633: */
634: static char *offl_msgs[] = {
635: "unknown drive", /* 0 = Unknown, or online to other ctlr */
636: "not mounted", /* 1 = Unmounted, or RUN/STOP at STOP */
637: "inoperative", /* 2 = Unit Inoperative */
638: unknown_msg,
639: "duplicate", /* 4 = Duplicate Unit Number */
640: unknown_msg,
641: unknown_msg,
642: unknown_msg,
643: "in diagnosis", /* 8 = Disabled by FS or diagnostic */
644: };
645:
646: /*
647: * Subcodes for Unit Available (4)
648: */
649: /* none known */
650:
651: /*
652: * Subcodes for Media Format Error (5)
653: */
654: static char *media_fmt_msgs[] = {
655: "fct unread - edc", /* 0 = FCT unreadable */
656: "invalid sector header",/* 1 = Invalid Sector Header */
657: "not 512 sectors", /* 2 = Not 512 Byte Sectors */
658: "not formatted", /* 3 = Not Formatted */
659: "fct ecc", /* 4 = FCT ECC */
660: };
661:
662: /*
663: * Subcodes for Write Protected (6)
664: * N.B.: Code 6 subcodes are 7 bits higher than other subcodes
665: * (i.e., bits 12-15).
666: */
667: static char *wrprot_msgs[] = {
668: unknown_msg,
669: "software", /* 1 = Software Write Protect */
670: "hardware", /* 2 = Hardware Write Protect */
671: };
672:
673: /*
674: * Subcodes for Compare Error (7)
675: */
676: /* none known */
677:
678: /*
679: * Subcodes for Data Error (8)
680: */
681: static char *data_msgs[] = {
682: "forced error", /* 0 = Forced Error (software) */
683: unknown_msg,
684: "header compare", /* 2 = Header Compare Error */
685: "sync timeout", /* 3 = Sync Timeout Error */
686: unknown_msg,
687: unknown_msg,
688: unknown_msg,
689: "uncorrectable ecc", /* 7 = Uncorrectable ECC */
690: "1 symbol ecc", /* 8 = 1 bit ECC */
691: "2 symbol ecc", /* 9 = 2 bit ECC */
692: "3 symbol ecc", /* 10 = 3 bit ECC */
693: "4 symbol ecc", /* 11 = 4 bit ECC */
694: "5 symbol ecc", /* 12 = 5 bit ECC */
695: "6 symbol ecc", /* 13 = 6 bit ECC */
696: "7 symbol ecc", /* 14 = 7 bit ECC */
697: "8 symbol ecc", /* 15 = 8 bit ECC */
698: };
699:
700: /*
701: * Subcodes for Host Buffer Access Error (9)
702: */
703: static char *host_buffer_msgs[] = {
704: unknown_msg,
705: "odd xfer addr", /* 1 = Odd Transfer Address */
706: "odd xfer count", /* 2 = Odd Transfer Count */
707: "non-exist. memory", /* 3 = Non-Existent Memory */
708: "memory parity", /* 4 = Memory Parity Error */
709: };
710:
711: /*
712: * Subcodes for Controller Error (10)
713: */
714: static char *cntlr_msgs[] = {
715: unknown_msg,
716: "serdes overrun", /* 1 = Serialiser/Deserialiser Overrun */
717: "edc", /* 2 = Error Detection Code? */
718: "inconsistent internal data struct",/* 3 = Internal Error */
719: };
720:
721: /*
722: * Subcodes for Drive Error (11)
723: */
724: static char *drive_msgs[] = {
725: unknown_msg,
726: "sdi command timeout", /* 1 = SDI Command Timeout */
727: "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */
728: "positioner", /* 3 = Positioner Error */
729: "lost rd/wr ready", /* 4 = Lost R/W Ready Error */
730: "drive clock dropout", /* 5 = Lost Drive Clock */
731: "lost recvr ready", /* 6 = Lost Receiver Ready */
732: "drive detected error", /* 7 = Drive Error */
733: "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
734: };
735:
736: /*
737: * The following table correlates message codes with the
738: * decoding strings.
739: */
740: struct code_decode {
741: char *cdc_msg;
742: int cdc_nsubcodes;
743: char **cdc_submsgs;
744: } code_decode[] = {
745: #define SC(m) sizeof (m) / sizeof (m[0]), m
746: {"success", SC(succ_msgs)},
747: {"invalid command", SC(icmd_msgs)},
748: {"command aborted", 0, 0},
749: {"unit offline", SC(offl_msgs)},
750: {"unit available", 0, 0},
751: {"media format error", SC(media_fmt_msgs)},
752: {"write protected", SC(wrprot_msgs)},
753: {"compare error", 0, 0},
754: {"data error", SC(data_msgs)},
755: {"host buffer access error", SC(host_buffer_msgs)},
756: {"controller error", SC(cntlr_msgs)},
757: {"drive error", SC(drive_msgs)},
758: #undef SC
759: };
760:
761: /*
762: * Print the decoded error event from an MSCP error datagram.
763: */
764: void
765: mscp_printevent(mp)
766: struct mscp *mp;
767: {
768: int event = mp->mscp_event;
769: struct code_decode *cdc;
770: int c, sc;
771: char *cm, *scm;
772:
773: /*
774: * The code is the lower six bits of the event number (aka
775: * status). If that is 6 (write protect), the subcode is in
776: * bits 12-15; otherwise, it is in bits 5-11.
777: * I WONDER WHAT THE OTHER BITS ARE FOR. IT SURE WOULD BE
778: * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
779: */
780: c = event & M_ST_MASK;
781: sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff;
782: if (c >= sizeof code_decode / sizeof code_decode[0])
783: cm = "- unknown code", scm = "??";
784: else {
785: cdc = &code_decode[c];
786: cm = cdc->cdc_msg;
787: if (sc >= cdc->cdc_nsubcodes)
788: scm = unknown_msg;
789: else
790: scm = cdc->cdc_submsgs[sc];
791: }
792: printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc);
793: }
794:
795: static char *codemsg[16] = {
796: "lbn", "code 1", "code 2", "code 3",
797: "code 4", "code 5", "rbn", "code 7",
798: "code 8", "code 9", "code 10", "code 11",
799: "code 12", "code 13", "code 14", "code 15"
800: };
801: /*
802: * Print the code and logical block number for an error packet.
803: * THIS IS PROBABLY PECULIAR TO DISK DRIVES. IT SURE WOULD BE
804: * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
805: */
806: int
807: mscp_decodeerror(name, mp, mi)
808: char *name;
809: struct mscp *mp;
810: struct mscp_softc *mi;
811: {
812: int issoft;
813: /*
814: * We will get three sdi errors of type 11 after autoconfig
815: * is finished; depending of searching for non-existing units.
816: * How can we avoid this???
817: */
818: if (((mp->mscp_event & M_ST_MASK) == 11) && (mi->mi_ierr++ < 3))
819: return 1;
820: /*
821: * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and
822: * the logical block number. Code 0 is a regular block; code 6
823: * is a replacement block. The remaining codes are currently
824: * undefined. The code is in the upper four bits of the header
825: * (bits 0-27 are the lbn).
826: */
827: issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT);
828: #define BADCODE(h) (codemsg[(unsigned)(h) >> 28])
829: #define BADLBN(h) ((h) & 0xfffffff)
830:
831: printf("%s: drive %d %s error datagram%s:", name, mp->mscp_unit,
832: issoft ? "soft" : "hard",
833: mp->mscp_flags & M_LF_CONT ? " (continuing)" : "");
834: switch (mp->mscp_format & 0377) {
835:
836: case M_FM_CTLRERR: /* controller error */
837: break;
838:
839: case M_FM_BUSADDR: /* host memory access error */
840: printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr);
841: break;
842:
843: case M_FM_DISKTRN:
844: printf(" unit %d: level %d retry %d, %s %d:",
845: mp->mscp_unit,
846: mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry,
847: BADCODE(mp->mscp_erd.erd_hdr),
848: (int)BADLBN(mp->mscp_erd.erd_hdr));
849: break;
850:
851: case M_FM_SDI:
852: printf(" unit %d: %s %d:", mp->mscp_unit,
853: BADCODE(mp->mscp_erd.erd_hdr),
854: (int)BADLBN(mp->mscp_erd.erd_hdr));
855: break;
856:
857: case M_FM_SMLDSK:
858: printf(" unit %d: small disk error, cyl %d:",
859: mp->mscp_unit, mp->mscp_erd.erd_sdecyl);
860: break;
861:
862: case M_FM_TAPETRN:
863: printf(" unit %d: tape transfer error, grp 0x%x event 0%o:",
864: mp->mscp_unit, mp->mscp_erd.erd_sdecyl, mp->mscp_event);
865: break;
866:
867: case M_FM_STIERR:
868: printf(" unit %d: STI error, event 0%o:", mp->mscp_unit,
869: mp->mscp_event);
870: break;
871:
872: default:
873: printf(" unit %d: unknown error, format 0x%x:",
874: mp->mscp_unit, mp->mscp_format);
875: }
876: mscp_printevent(mp);
877: return 0;
878: #undef BADCODE
879: #undef BADLBN
880: }
CVSweb