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