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