Home | History | Annotate | Line # | Download | only in mscp
mscp_subr.c revision 1.13
      1 /*	$NetBSD: mscp_subr.c,v 1.13 2000/01/21 23:39:59 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/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 	BUFQ_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 (BUFQ_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 	BUFQ_INSERT_TAIL(&mi->mi_resq, bp);
    489 	mscp_kickaway(mi);
    490 	splx(s);
    491 }
    492 
    493 
    494 void
    495 mscp_kickaway(mi)
    496 	struct	mscp_softc *mi;
    497 {
    498 	struct buf *bp;
    499 	struct	mscp *mp;
    500 	int next;
    501 
    502 	while ((bp = BUFQ_FIRST(&mi->mi_resq)) != NULL) {
    503 		/*
    504 		 * Ok; we are ready to try to start a xfer. Get a MSCP packet
    505 		 * and try to start...
    506 		 */
    507 		if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) {
    508 			if (mi->mi_credits > MSCP_MINCREDITS)
    509 				printf("%s: command ring too small\n",
    510 				    mi->mi_dev.dv_parent->dv_xname);
    511 			/*
    512 			 * By some (strange) reason we didn't get a MSCP packet.
    513 			 * Just return and wait for free packets.
    514 			 */
    515 			return;
    516 		}
    517 
    518 		if ((next = (ffs(mi->mi_mxiuse) - 1)) < 0)
    519 			panic("no mxi buffers");
    520 		mi->mi_mxiuse &= ~(1 << next);
    521 		if (mi->mi_xi[next].mxi_inuse)
    522 			panic("mxi inuse");
    523 		/*
    524 		 * Set up the MSCP packet and ask the ctlr to start.
    525 		 */
    526 		mp->mscp_opcode =
    527 		    (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
    528 		mp->mscp_cmdref = next;
    529 		mi->mi_xi[next].mxi_bp = bp;
    530 		mi->mi_xi[next].mxi_mp = mp;
    531 		mi->mi_xi[next].mxi_inuse = 1;
    532 		bp->b_resid = next;
    533 		(*mi->mi_me->me_fillin)(bp, mp);
    534 		(*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, &mi->mi_xi[next]);
    535 		BUFQ_REMOVE(&mi->mi_resq, bp);
    536 	}
    537 }
    538 
    539 void
    540 mscp_dgo(mi, mxi)
    541 	struct mscp_softc *mi;
    542 	struct mscp_xi *mxi;
    543 {
    544 	volatile int i;
    545 	struct	mscp *mp;
    546 
    547 	/*
    548 	 * Fill in the MSCP packet and move the buffer to the I/O wait queue.
    549 	 */
    550 	mp = mxi->mxi_mp;
    551 	mp->mscp_seq.seq_buffer = mxi->mxi_dmam->dm_segs[0].ds_addr;
    552 
    553 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
    554 	i = READ_IP;
    555 }
    556 
    557 #ifdef DIAGNOSTIC
    558 /*
    559  * Dump the entire contents of an MSCP packet in hex.  Mainly useful
    560  * for debugging....
    561  */
    562 void
    563 mscp_hexdump(mp)
    564 	register struct mscp *mp;
    565 {
    566 	register long *p = (long *) mp;
    567 	register int i = mp->mscp_msglen;
    568 
    569 	if (i > 256)		/* sanity */
    570 		i = 256;
    571 	i /= sizeof (*p);	/* ASSUMES MULTIPLE OF sizeof(long) */
    572 	while (--i >= 0)
    573 		printf("0x%x ", (int)*p++);
    574 	printf("\n");
    575 }
    576 #endif
    577 
    578 /*
    579  * MSCP error reporting
    580  */
    581 
    582 /*
    583  * Messages for the various subcodes.
    584  */
    585 static char unknown_msg[] = "unknown subcode";
    586 
    587 /*
    588  * Subcodes for Success (0)
    589  */
    590 static char *succ_msgs[] = {
    591 	"normal",		/* 0 */
    592 	"spin down ignored",	/* 1 = Spin-Down Ignored */
    593 	"still connected",	/* 2 = Still Connected */
    594 	unknown_msg,
    595 	"dup. unit #",		/* 4 = Duplicate Unit Number */
    596 	unknown_msg,
    597 	unknown_msg,
    598 	unknown_msg,
    599 	"already online",	/* 8 = Already Online */
    600 	unknown_msg,
    601 	unknown_msg,
    602 	unknown_msg,
    603 	unknown_msg,
    604 	unknown_msg,
    605 	unknown_msg,
    606 	unknown_msg,
    607 	"still online",		/* 16 = Still Online */
    608 };
    609 
    610 /*
    611  * Subcodes for Invalid Command (1)
    612  */
    613 static char *icmd_msgs[] = {
    614 	"invalid msg length",	/* 0 = Invalid Message Length */
    615 };
    616 
    617 /*
    618  * Subcodes for Command Aborted (2)
    619  */
    620 /* none known */
    621 
    622 /*
    623  * Subcodes for Unit Offline (3)
    624  */
    625 static char *offl_msgs[] = {
    626 	"unknown drive",	/* 0 = Unknown, or online to other ctlr */
    627 	"not mounted",		/* 1 = Unmounted, or RUN/STOP at STOP */
    628 	"inoperative",		/* 2 = Unit Inoperative */
    629 	unknown_msg,
    630 	"duplicate",		/* 4 = Duplicate Unit Number */
    631 	unknown_msg,
    632 	unknown_msg,
    633 	unknown_msg,
    634 	"in diagnosis",		/* 8 = Disabled by FS or diagnostic */
    635 };
    636 
    637 /*
    638  * Subcodes for Unit Available (4)
    639  */
    640 /* none known */
    641 
    642 /*
    643  * Subcodes for Media Format Error (5)
    644  */
    645 static char *media_fmt_msgs[] = {
    646 	"fct unread - edc",	/* 0 = FCT unreadable */
    647 	"invalid sector header",/* 1 = Invalid Sector Header */
    648 	"not 512 sectors",	/* 2 = Not 512 Byte Sectors */
    649 	"not formatted",	/* 3 = Not Formatted */
    650 	"fct ecc",		/* 4 = FCT ECC */
    651 };
    652 
    653 /*
    654  * Subcodes for Write Protected (6)
    655  * N.B.:  Code 6 subcodes are 7 bits higher than other subcodes
    656  * (i.e., bits 12-15).
    657  */
    658 static char *wrprot_msgs[] = {
    659 	unknown_msg,
    660 	"software",		/* 1 = Software Write Protect */
    661 	"hardware",		/* 2 = Hardware Write Protect */
    662 };
    663 
    664 /*
    665  * Subcodes for Compare Error (7)
    666  */
    667 /* none known */
    668 
    669 /*
    670  * Subcodes for Data Error (8)
    671  */
    672 static char *data_msgs[] = {
    673 	"forced error",		/* 0 = Forced Error (software) */
    674 	unknown_msg,
    675 	"header compare",	/* 2 = Header Compare Error */
    676 	"sync timeout",		/* 3 = Sync Timeout Error */
    677 	unknown_msg,
    678 	unknown_msg,
    679 	unknown_msg,
    680 	"uncorrectable ecc",	/* 7 = Uncorrectable ECC */
    681 	"1 symbol ecc",		/* 8 = 1 bit ECC */
    682 	"2 symbol ecc",		/* 9 = 2 bit ECC */
    683 	"3 symbol ecc",		/* 10 = 3 bit ECC */
    684 	"4 symbol ecc",		/* 11 = 4 bit ECC */
    685 	"5 symbol ecc",		/* 12 = 5 bit ECC */
    686 	"6 symbol ecc",		/* 13 = 6 bit ECC */
    687 	"7 symbol ecc",		/* 14 = 7 bit ECC */
    688 	"8 symbol ecc",		/* 15 = 8 bit ECC */
    689 };
    690 
    691 /*
    692  * Subcodes for Host Buffer Access Error (9)
    693  */
    694 static char *host_buffer_msgs[] = {
    695 	unknown_msg,
    696 	"odd xfer addr",	/* 1 = Odd Transfer Address */
    697 	"odd xfer count",	/* 2 = Odd Transfer Count */
    698 	"non-exist. memory",	/* 3 = Non-Existent Memory */
    699 	"memory parity",	/* 4 = Memory Parity Error */
    700 };
    701 
    702 /*
    703  * Subcodes for Controller Error (10)
    704  */
    705 static char *cntlr_msgs[] = {
    706 	unknown_msg,
    707 	"serdes overrun",	/* 1 = Serialiser/Deserialiser Overrun */
    708 	"edc",			/* 2 = Error Detection Code? */
    709 	"inconsistant internal data struct",/* 3 = Internal Error */
    710 };
    711 
    712 /*
    713  * Subcodes for Drive Error (11)
    714  */
    715 static char *drive_msgs[] = {
    716 	unknown_msg,
    717 	"sdi command timeout",	/* 1 = SDI Command Timeout */
    718 	"ctlr detected protocol",/* 2 = Controller Detected Protocol Error */
    719 	"positioner",		/* 3 = Positioner Error */
    720 	"lost rd/wr ready",	/* 4 = Lost R/W Ready Error */
    721 	"drive clock dropout",	/* 5 = Lost Drive Clock */
    722 	"lost recvr ready",	/* 6 = Lost Receiver Ready */
    723 	"drive detected error", /* 7 = Drive Error */
    724 	"ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
    725 };
    726 
    727 /*
    728  * The following table correlates message codes with the
    729  * decoding strings.
    730  */
    731 struct code_decode {
    732 	char	*cdc_msg;
    733 	int	cdc_nsubcodes;
    734 	char	**cdc_submsgs;
    735 } code_decode[] = {
    736 #define SC(m)	sizeof (m) / sizeof (m[0]), m
    737 	{"success",			SC(succ_msgs)},
    738 	{"invalid command",		SC(icmd_msgs)},
    739 	{"command aborted",		0, 0},
    740 	{"unit offline",		SC(offl_msgs)},
    741 	{"unit available",		0, 0},
    742 	{"media format error",		SC(media_fmt_msgs)},
    743 	{"write protected",		SC(wrprot_msgs)},
    744 	{"compare error",		0, 0},
    745 	{"data error",			SC(data_msgs)},
    746 	{"host buffer access error",	SC(host_buffer_msgs)},
    747 	{"controller error",		SC(cntlr_msgs)},
    748 	{"drive error",			SC(drive_msgs)},
    749 #undef SC
    750 };
    751 
    752 /*
    753  * Print the decoded error event from an MSCP error datagram.
    754  */
    755 void
    756 mscp_printevent(mp)
    757 	struct mscp *mp;
    758 {
    759 	register int event = mp->mscp_event;
    760 	register struct code_decode *cdc;
    761 	int c, sc;
    762 	char *cm, *scm;
    763 
    764 	/*
    765 	 * The code is the lower six bits of the event number (aka
    766 	 * status).  If that is 6 (write protect), the subcode is in
    767 	 * bits 12-15; otherwise, it is in bits 5-11.
    768 	 * I WONDER WHAT THE OTHER BITS ARE FOR.  IT SURE WOULD BE
    769 	 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
    770 	 */
    771 	c = event & M_ST_MASK;
    772 	sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff;
    773 	if (c >= sizeof code_decode / sizeof code_decode[0])
    774 		cm = "- unknown code", scm = "??";
    775 	else {
    776 		cdc = &code_decode[c];
    777 		cm = cdc->cdc_msg;
    778 		if (sc >= cdc->cdc_nsubcodes)
    779 			scm = unknown_msg;
    780 		else
    781 			scm = cdc->cdc_submsgs[sc];
    782 	}
    783 	printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc);
    784 }
    785 
    786 static char *codemsg[16] = {
    787 	"lbn", "code 1", "code 2", "code 3",
    788 	"code 4", "code 5", "rbn", "code 7",
    789 	"code 8", "code 9", "code 10", "code 11",
    790 	"code 12", "code 13", "code 14", "code 15"
    791 };
    792 /*
    793  * Print the code and logical block number for an error packet.
    794  * THIS IS PROBABLY PECULIAR TO DISK DRIVES.  IT SURE WOULD BE
    795  * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
    796  */
    797 int
    798 mscp_decodeerror(name, mp, mi)
    799 	char *name;
    800 	register struct mscp *mp;
    801 	struct mscp_softc *mi;
    802 {
    803 	int issoft;
    804 	/*
    805 	 * We will get three sdi errors of type 11 after autoconfig
    806 	 * is finished; depending of searching for non-existing units.
    807 	 * How can we avoid this???
    808 	 */
    809 	if (((mp->mscp_event & M_ST_MASK) == 11) && (mi->mi_ierr++ < 3))
    810 		return 1;
    811 	/*
    812 	 * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and
    813 	 * the logical block number.  Code 0 is a regular block; code 6
    814 	 * is a replacement block.  The remaining codes are currently
    815 	 * undefined.  The code is in the upper four bits of the header
    816 	 * (bits 0-27 are the lbn).
    817 	 */
    818 	issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT);
    819 #define BADCODE(h)	(codemsg[(unsigned)(h) >> 28])
    820 #define BADLBN(h)	((h) & 0xfffffff)
    821 
    822 	printf("%s: drive %d %s error datagram%s:", name, mp->mscp_unit,
    823 		issoft ? "soft" : "hard",
    824 		mp->mscp_flags & M_LF_CONT ? " (continuing)" : "");
    825 	switch (mp->mscp_format & 0377) {
    826 
    827 	case M_FM_CTLRERR:	/* controller error */
    828 		break;
    829 
    830 	case M_FM_BUSADDR:	/* host memory access error */
    831 		printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr);
    832 		break;
    833 
    834 	case M_FM_DISKTRN:
    835 		printf(" unit %d: level %d retry %d, %s %d:",
    836 			mp->mscp_unit,
    837 			mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry,
    838 			BADCODE(mp->mscp_erd.erd_hdr),
    839 			(int)BADLBN(mp->mscp_erd.erd_hdr));
    840 		break;
    841 
    842 	case M_FM_SDI:
    843 		printf(" unit %d: %s %d:", mp->mscp_unit,
    844 			BADCODE(mp->mscp_erd.erd_hdr),
    845 			(int)BADLBN(mp->mscp_erd.erd_hdr));
    846 		break;
    847 
    848 	case M_FM_SMLDSK:
    849 		printf(" unit %d: small disk error, cyl %d:",
    850 			mp->mscp_unit, mp->mscp_erd.erd_sdecyl);
    851 		break;
    852 
    853 	case M_FM_TAPETRN:
    854 		printf(" unit %d: tape transfer error, grp 0x%x event 0%o:",
    855 		    mp->mscp_unit, mp->mscp_erd.erd_sdecyl, mp->mscp_event);
    856 		break;
    857 
    858 	case M_FM_STIERR:
    859 		printf(" unit %d: STI error, event 0%o:", mp->mscp_unit,
    860 		    mp->mscp_event);
    861 		break;
    862 
    863 	default:
    864 		printf(" unit %d: unknown error, format 0x%x:",
    865 			mp->mscp_unit, mp->mscp_format);
    866 	}
    867 	mscp_printevent(mp);
    868 	return 0;
    869 #undef BADCODE
    870 #undef BADLBN
    871 }
    872