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