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