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