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