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