xref: /netbsd-src/sys/dev/mscp/mscp_subr.c (revision 89c5a767f8fc7a4633b2d409966e2becbb98ff92)
1 /*	$NetBSD: mscp_subr.c,v 1.13 2000/01/21 23:39:59 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), 1, (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 
345 	WRITE_SW((mi->mi_dmam->dm_segs[0].ds_addr >> 16));
346 	status = mscp_waitstep(mi, STEP3MASK, STEP3GOOD);
347 	if (status == 0) {
348 		(*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
349 		return 1;
350 	}
351 	i = READ_SA & 0377;
352 	printf(": version %d model %d\n", i & 15, i >> 4);
353 
354 #define BURST 4 /* XXX */
355 	if (mi->mi_type & MSCPBUS_UDA) {
356 		WRITE_SW(MP_GO | (BURST - 1) << 2);
357 		printf("%s: DMA burst size set to %d\n",
358 		    mi->mi_dev.dv_xname, BURST);
359 	}
360 	WRITE_SW(MP_GO);
361 
362 	mscp_initds(mi);
363 	mi->mi_flags &= ~MSC_IGNOREINTR;
364 
365 	/*
366 	 * Set up all necessary info in the bus softc struct, get a
367 	 * mscp packet and set characteristics for this controller.
368 	 */
369 	mi->mi_credits = MSCP_MINCREDITS + 1;
370 	mp = mscp_getcp(mi, MSCP_DONTWAIT);
371 
372 	mi->mi_credits = 0;
373 	mp->mscp_opcode = M_OP_SETCTLRC;
374 	mp->mscp_unit = mp->mscp_modifier = mp->mscp_flags =
375 	    mp->mscp_sccc.sccc_version = mp->mscp_sccc.sccc_hosttimo =
376 	    mp->mscp_sccc.sccc_time = mp->mscp_sccc.sccc_time1 =
377 	    mp->mscp_sccc.sccc_errlgfl = 0;
378 	mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | M_CF_THIS;
379 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
380 	i = READ_IP;
381 
382 	count = 0;
383 	while (count < DELAYTEN) {
384 		if (((volatile int)mi->mi_flags & MSC_READY) != 0)
385 			break;
386 		if ((j = READ_SA) & MP_ERR)
387 			goto out;
388 		DELAY(10000);
389 		count += 1;
390 	}
391 	if (count == DELAYTEN) {
392 out:
393 		printf("%s: couldn't set ctlr characteristics, sa=%x\n",
394 		    mi->mi_dev.dv_xname, j);
395 		return 1;
396 	}
397 	return 0;
398 }
399 
400 /*
401  * Initialise the various data structures that control the mscp protocol.
402  */
403 void
404 mscp_initds(mi)
405 	struct mscp_softc *mi;
406 {
407 	struct mscp_pack *ud = mi->mi_uda;
408 	struct mscp *mp;
409 	int i;
410 
411 	for (i = 0, mp = ud->mp_rsp; i < NRSP; i++, mp++) {
412 		ud->mp_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT |
413 		    (mi->mi_dmam->dm_segs[0].ds_addr +
414 		    offsetof(struct mscp_pack, mp_rsp[i].mscp_cmdref));
415 		mp->mscp_addr = &ud->mp_ca.ca_rspdsc[i];
416 		mp->mscp_msglen = MSCP_MSGLEN;
417 	}
418 	for (i = 0, mp = ud->mp_cmd; i < NCMD; i++, mp++) {
419 		ud->mp_ca.ca_cmddsc[i] = MSCP_INT |
420 		    (mi->mi_dmam->dm_segs[0].ds_addr +
421 		    offsetof(struct mscp_pack, mp_cmd[i].mscp_cmdref));
422 		mp->mscp_addr = &ud->mp_ca.ca_cmddsc[i];
423 		mp->mscp_msglen = MSCP_MSGLEN;
424 		if (mi->mi_type & MSCPBUS_TAPE)
425 			mp->mscp_vcid = 1;
426 	}
427 }
428 
429 static	void mscp_kickaway(struct mscp_softc *);
430 
431 void
432 mscp_intr(mi)
433 	struct mscp_softc *mi;
434 {
435 	struct mscp_pack *ud = mi->mi_uda;
436 
437 	if (mi->mi_flags & MSC_IGNOREINTR)
438 		return;
439 	/*
440 	 * Check for response and command ring transitions.
441 	 */
442 	if (ud->mp_ca.ca_rspint) {
443 		ud->mp_ca.ca_rspint = 0;
444 		mscp_dorsp(mi);
445 	}
446 	if (ud->mp_ca.ca_cmdint) {
447 		ud->mp_ca.ca_cmdint = 0;
448 		MSCP_DOCMD(mi);
449 	}
450 
451 	/*
452 	 * If there are any not-yet-handled request, try them now.
453 	 */
454 	if (BUFQ_FIRST(&mi->mi_resq))
455 		mscp_kickaway(mi);
456 }
457 
458 int
459 mscp_print(aux, name)
460 	void *aux;
461 	const char *name;
462 {
463 	struct drive_attach_args *da = aux;
464 	struct	mscp *mp = da->da_mp;
465 	int type = mp->mscp_guse.guse_mediaid;
466 
467 	if (name) {
468 		printf("%c%c", MSCP_MID_CHAR(2, type), MSCP_MID_CHAR(1, type));
469 		if (MSCP_MID_ECH(0, type))
470 			printf("%c", MSCP_MID_CHAR(0, type));
471 		printf("%d at %s drive %d", MSCP_MID_NUM(type), name,
472 		    mp->mscp_unit);
473 	}
474 	return UNCONF;
475 }
476 
477 /*
478  * common strategy routine for all types of MSCP devices.
479  */
480 void
481 mscp_strategy(bp, usc)
482 	struct buf *bp;
483 	struct device *usc;
484 {
485 	struct	mscp_softc *mi = (void *)usc;
486 	int s = splimp();
487 
488 	BUFQ_INSERT_TAIL(&mi->mi_resq, bp);
489 	mscp_kickaway(mi);
490 	splx(s);
491 }
492 
493 
494 void
495 mscp_kickaway(mi)
496 	struct	mscp_softc *mi;
497 {
498 	struct buf *bp;
499 	struct	mscp *mp;
500 	int next;
501 
502 	while ((bp = BUFQ_FIRST(&mi->mi_resq)) != NULL) {
503 		/*
504 		 * Ok; we are ready to try to start a xfer. Get a MSCP packet
505 		 * and try to start...
506 		 */
507 		if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) {
508 			if (mi->mi_credits > MSCP_MINCREDITS)
509 				printf("%s: command ring too small\n",
510 				    mi->mi_dev.dv_parent->dv_xname);
511 			/*
512 			 * By some (strange) reason we didn't get a MSCP packet.
513 			 * Just return and wait for free packets.
514 			 */
515 			return;
516 		}
517 
518 		if ((next = (ffs(mi->mi_mxiuse) - 1)) < 0)
519 			panic("no mxi buffers");
520 		mi->mi_mxiuse &= ~(1 << next);
521 		if (mi->mi_xi[next].mxi_inuse)
522 			panic("mxi inuse");
523 		/*
524 		 * Set up the MSCP packet and ask the ctlr to start.
525 		 */
526 		mp->mscp_opcode =
527 		    (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
528 		mp->mscp_cmdref = next;
529 		mi->mi_xi[next].mxi_bp = bp;
530 		mi->mi_xi[next].mxi_mp = mp;
531 		mi->mi_xi[next].mxi_inuse = 1;
532 		bp->b_resid = next;
533 		(*mi->mi_me->me_fillin)(bp, mp);
534 		(*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, &mi->mi_xi[next]);
535 		BUFQ_REMOVE(&mi->mi_resq, bp);
536 	}
537 }
538 
539 void
540 mscp_dgo(mi, mxi)
541 	struct mscp_softc *mi;
542 	struct mscp_xi *mxi;
543 {
544 	volatile int i;
545 	struct	mscp *mp;
546 
547 	/*
548 	 * Fill in the MSCP packet and move the buffer to the I/O wait queue.
549 	 */
550 	mp = mxi->mxi_mp;
551 	mp->mscp_seq.seq_buffer = mxi->mxi_dmam->dm_segs[0].ds_addr;
552 
553 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
554 	i = READ_IP;
555 }
556 
557 #ifdef DIAGNOSTIC
558 /*
559  * Dump the entire contents of an MSCP packet in hex.  Mainly useful
560  * for debugging....
561  */
562 void
563 mscp_hexdump(mp)
564 	register struct mscp *mp;
565 {
566 	register long *p = (long *) mp;
567 	register int i = mp->mscp_msglen;
568 
569 	if (i > 256)		/* sanity */
570 		i = 256;
571 	i /= sizeof (*p);	/* ASSUMES MULTIPLE OF sizeof(long) */
572 	while (--i >= 0)
573 		printf("0x%x ", (int)*p++);
574 	printf("\n");
575 }
576 #endif
577 
578 /*
579  * MSCP error reporting
580  */
581 
582 /*
583  * Messages for the various subcodes.
584  */
585 static char unknown_msg[] = "unknown subcode";
586 
587 /*
588  * Subcodes for Success (0)
589  */
590 static char *succ_msgs[] = {
591 	"normal",		/* 0 */
592 	"spin down ignored",	/* 1 = Spin-Down Ignored */
593 	"still connected",	/* 2 = Still Connected */
594 	unknown_msg,
595 	"dup. unit #",		/* 4 = Duplicate Unit Number */
596 	unknown_msg,
597 	unknown_msg,
598 	unknown_msg,
599 	"already online",	/* 8 = Already Online */
600 	unknown_msg,
601 	unknown_msg,
602 	unknown_msg,
603 	unknown_msg,
604 	unknown_msg,
605 	unknown_msg,
606 	unknown_msg,
607 	"still online",		/* 16 = Still Online */
608 };
609 
610 /*
611  * Subcodes for Invalid Command (1)
612  */
613 static char *icmd_msgs[] = {
614 	"invalid msg length",	/* 0 = Invalid Message Length */
615 };
616 
617 /*
618  * Subcodes for Command Aborted (2)
619  */
620 /* none known */
621 
622 /*
623  * Subcodes for Unit Offline (3)
624  */
625 static char *offl_msgs[] = {
626 	"unknown drive",	/* 0 = Unknown, or online to other ctlr */
627 	"not mounted",		/* 1 = Unmounted, or RUN/STOP at STOP */
628 	"inoperative",		/* 2 = Unit Inoperative */
629 	unknown_msg,
630 	"duplicate",		/* 4 = Duplicate Unit Number */
631 	unknown_msg,
632 	unknown_msg,
633 	unknown_msg,
634 	"in diagnosis",		/* 8 = Disabled by FS or diagnostic */
635 };
636 
637 /*
638  * Subcodes for Unit Available (4)
639  */
640 /* none known */
641 
642 /*
643  * Subcodes for Media Format Error (5)
644  */
645 static char *media_fmt_msgs[] = {
646 	"fct unread - edc",	/* 0 = FCT unreadable */
647 	"invalid sector header",/* 1 = Invalid Sector Header */
648 	"not 512 sectors",	/* 2 = Not 512 Byte Sectors */
649 	"not formatted",	/* 3 = Not Formatted */
650 	"fct ecc",		/* 4 = FCT ECC */
651 };
652 
653 /*
654  * Subcodes for Write Protected (6)
655  * N.B.:  Code 6 subcodes are 7 bits higher than other subcodes
656  * (i.e., bits 12-15).
657  */
658 static char *wrprot_msgs[] = {
659 	unknown_msg,
660 	"software",		/* 1 = Software Write Protect */
661 	"hardware",		/* 2 = Hardware Write Protect */
662 };
663 
664 /*
665  * Subcodes for Compare Error (7)
666  */
667 /* none known */
668 
669 /*
670  * Subcodes for Data Error (8)
671  */
672 static char *data_msgs[] = {
673 	"forced error",		/* 0 = Forced Error (software) */
674 	unknown_msg,
675 	"header compare",	/* 2 = Header Compare Error */
676 	"sync timeout",		/* 3 = Sync Timeout Error */
677 	unknown_msg,
678 	unknown_msg,
679 	unknown_msg,
680 	"uncorrectable ecc",	/* 7 = Uncorrectable ECC */
681 	"1 symbol ecc",		/* 8 = 1 bit ECC */
682 	"2 symbol ecc",		/* 9 = 2 bit ECC */
683 	"3 symbol ecc",		/* 10 = 3 bit ECC */
684 	"4 symbol ecc",		/* 11 = 4 bit ECC */
685 	"5 symbol ecc",		/* 12 = 5 bit ECC */
686 	"6 symbol ecc",		/* 13 = 6 bit ECC */
687 	"7 symbol ecc",		/* 14 = 7 bit ECC */
688 	"8 symbol ecc",		/* 15 = 8 bit ECC */
689 };
690 
691 /*
692  * Subcodes for Host Buffer Access Error (9)
693  */
694 static char *host_buffer_msgs[] = {
695 	unknown_msg,
696 	"odd xfer addr",	/* 1 = Odd Transfer Address */
697 	"odd xfer count",	/* 2 = Odd Transfer Count */
698 	"non-exist. memory",	/* 3 = Non-Existent Memory */
699 	"memory parity",	/* 4 = Memory Parity Error */
700 };
701 
702 /*
703  * Subcodes for Controller Error (10)
704  */
705 static char *cntlr_msgs[] = {
706 	unknown_msg,
707 	"serdes overrun",	/* 1 = Serialiser/Deserialiser Overrun */
708 	"edc",			/* 2 = Error Detection Code? */
709 	"inconsistant internal data struct",/* 3 = Internal Error */
710 };
711 
712 /*
713  * Subcodes for Drive Error (11)
714  */
715 static char *drive_msgs[] = {
716 	unknown_msg,
717 	"sdi command timeout",	/* 1 = SDI Command Timeout */
718 	"ctlr detected protocol",/* 2 = Controller Detected Protocol Error */
719 	"positioner",		/* 3 = Positioner Error */
720 	"lost rd/wr ready",	/* 4 = Lost R/W Ready Error */
721 	"drive clock dropout",	/* 5 = Lost Drive Clock */
722 	"lost recvr ready",	/* 6 = Lost Receiver Ready */
723 	"drive detected error", /* 7 = Drive Error */
724 	"ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
725 };
726 
727 /*
728  * The following table correlates message codes with the
729  * decoding strings.
730  */
731 struct code_decode {
732 	char	*cdc_msg;
733 	int	cdc_nsubcodes;
734 	char	**cdc_submsgs;
735 } code_decode[] = {
736 #define SC(m)	sizeof (m) / sizeof (m[0]), m
737 	{"success",			SC(succ_msgs)},
738 	{"invalid command",		SC(icmd_msgs)},
739 	{"command aborted",		0, 0},
740 	{"unit offline",		SC(offl_msgs)},
741 	{"unit available",		0, 0},
742 	{"media format error",		SC(media_fmt_msgs)},
743 	{"write protected",		SC(wrprot_msgs)},
744 	{"compare error",		0, 0},
745 	{"data error",			SC(data_msgs)},
746 	{"host buffer access error",	SC(host_buffer_msgs)},
747 	{"controller error",		SC(cntlr_msgs)},
748 	{"drive error",			SC(drive_msgs)},
749 #undef SC
750 };
751 
752 /*
753  * Print the decoded error event from an MSCP error datagram.
754  */
755 void
756 mscp_printevent(mp)
757 	struct mscp *mp;
758 {
759 	register int event = mp->mscp_event;
760 	register struct code_decode *cdc;
761 	int c, sc;
762 	char *cm, *scm;
763 
764 	/*
765 	 * The code is the lower six bits of the event number (aka
766 	 * status).  If that is 6 (write protect), the subcode is in
767 	 * bits 12-15; otherwise, it is in bits 5-11.
768 	 * I WONDER WHAT THE OTHER BITS ARE FOR.  IT SURE WOULD BE
769 	 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
770 	 */
771 	c = event & M_ST_MASK;
772 	sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff;
773 	if (c >= sizeof code_decode / sizeof code_decode[0])
774 		cm = "- unknown code", scm = "??";
775 	else {
776 		cdc = &code_decode[c];
777 		cm = cdc->cdc_msg;
778 		if (sc >= cdc->cdc_nsubcodes)
779 			scm = unknown_msg;
780 		else
781 			scm = cdc->cdc_submsgs[sc];
782 	}
783 	printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc);
784 }
785 
786 static char *codemsg[16] = {
787 	"lbn", "code 1", "code 2", "code 3",
788 	"code 4", "code 5", "rbn", "code 7",
789 	"code 8", "code 9", "code 10", "code 11",
790 	"code 12", "code 13", "code 14", "code 15"
791 };
792 /*
793  * Print the code and logical block number for an error packet.
794  * THIS IS PROBABLY PECULIAR TO DISK DRIVES.  IT SURE WOULD BE
795  * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
796  */
797 int
798 mscp_decodeerror(name, mp, mi)
799 	char *name;
800 	register struct mscp *mp;
801 	struct mscp_softc *mi;
802 {
803 	int issoft;
804 	/*
805 	 * We will get three sdi errors of type 11 after autoconfig
806 	 * is finished; depending of searching for non-existing units.
807 	 * How can we avoid this???
808 	 */
809 	if (((mp->mscp_event & M_ST_MASK) == 11) && (mi->mi_ierr++ < 3))
810 		return 1;
811 	/*
812 	 * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and
813 	 * the logical block number.  Code 0 is a regular block; code 6
814 	 * is a replacement block.  The remaining codes are currently
815 	 * undefined.  The code is in the upper four bits of the header
816 	 * (bits 0-27 are the lbn).
817 	 */
818 	issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT);
819 #define BADCODE(h)	(codemsg[(unsigned)(h) >> 28])
820 #define BADLBN(h)	((h) & 0xfffffff)
821 
822 	printf("%s: drive %d %s error datagram%s:", name, mp->mscp_unit,
823 		issoft ? "soft" : "hard",
824 		mp->mscp_flags & M_LF_CONT ? " (continuing)" : "");
825 	switch (mp->mscp_format & 0377) {
826 
827 	case M_FM_CTLRERR:	/* controller error */
828 		break;
829 
830 	case M_FM_BUSADDR:	/* host memory access error */
831 		printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr);
832 		break;
833 
834 	case M_FM_DISKTRN:
835 		printf(" unit %d: level %d retry %d, %s %d:",
836 			mp->mscp_unit,
837 			mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry,
838 			BADCODE(mp->mscp_erd.erd_hdr),
839 			(int)BADLBN(mp->mscp_erd.erd_hdr));
840 		break;
841 
842 	case M_FM_SDI:
843 		printf(" unit %d: %s %d:", mp->mscp_unit,
844 			BADCODE(mp->mscp_erd.erd_hdr),
845 			(int)BADLBN(mp->mscp_erd.erd_hdr));
846 		break;
847 
848 	case M_FM_SMLDSK:
849 		printf(" unit %d: small disk error, cyl %d:",
850 			mp->mscp_unit, mp->mscp_erd.erd_sdecyl);
851 		break;
852 
853 	case M_FM_TAPETRN:
854 		printf(" unit %d: tape transfer error, grp 0x%x event 0%o:",
855 		    mp->mscp_unit, mp->mscp_erd.erd_sdecyl, mp->mscp_event);
856 		break;
857 
858 	case M_FM_STIERR:
859 		printf(" unit %d: STI error, event 0%o:", mp->mscp_unit,
860 		    mp->mscp_event);
861 		break;
862 
863 	default:
864 		printf(" unit %d: unknown error, format 0x%x:",
865 			mp->mscp_unit, mp->mscp_format);
866 	}
867 	mscp_printevent(mp);
868 	return 0;
869 #undef BADCODE
870 #undef BADLBN
871 }
872