xref: /netbsd-src/sys/dev/mscp/mscp_subr.c (revision 001c68bd94f75ce9270b69227c4199fbf34ee396)
1 /*	$NetBSD: mscp_subr.c,v 1.23 2003/01/01 00:10:22 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.23 2003/01/01 00:10:22 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 		aprint_normal("%c%c", MSCP_MID_CHAR(2, type),
470 		    MSCP_MID_CHAR(1, type));
471 		if (MSCP_MID_ECH(0, type))
472 			aprint_normal("%c", MSCP_MID_CHAR(0, type));
473 		aprint_normal("%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_PUT(&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_PEEK(&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 		(void)BUFQ_GET(&mi->mi_resq);
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