Annotation of sys/arch/vax/mscp/mscp_subr.c, Revision 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