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