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