xref: /netbsd-src/sys/dev/mscp/mscp_subr.c (revision 404fbe5fb94ca1e054339640cabb2801ce52dd30)
1 /*	$NetBSD: mscp_subr.c,v 1.35 2008/04/08 20:10:44 cegger 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.35 2008/04/08 20:10:44 cegger 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 <sys/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(struct device *, struct cfdata *, void *);
100 void	mscp_attach(struct device *, struct device *, void *);
101 void	mscp_start(struct	mscp_softc *);
102 int	mscp_init(struct  mscp_softc *);
103 void	mscp_initds(struct mscp_softc *);
104 int	mscp_waitstep(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 = device_private(self);
170 	struct mscp *mp2;
171 	volatile struct mscp *mp;
172 	volatile int i;
173 	int	timeout, next = 0;
174 
175 	mi->mi_mc = ma->ma_mc;
176 	mi->mi_me = NULL;
177 	mi->mi_type = ma->ma_type;
178 	mi->mi_uda = ma->ma_uda;
179 	mi->mi_dmat = ma->ma_dmat;
180 	mi->mi_dmam = ma->ma_dmam;
181 	mi->mi_iot = ma->ma_iot;
182 	mi->mi_iph = ma->ma_iph;
183 	mi->mi_sah = ma->ma_sah;
184 	mi->mi_swh = ma->ma_swh;
185 	mi->mi_ivec = ma->ma_ivec;
186 	mi->mi_adapnr = ma->ma_adapnr;
187 	mi->mi_ctlrnr = ma->ma_ctlrnr;
188 	*ma->ma_softc = mi;
189 	/*
190 	 * Go out to init the bus, so that we can give commands
191 	 * to its devices.
192 	 */
193 	mi->mi_cmd.mri_size = NCMD;
194 	mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc;
195 	mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd;
196 	mi->mi_rsp.mri_size = NRSP;
197 	mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc;
198 	mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp;
199 	bufq_alloc(&mi->mi_resq, "fcfs", 0);
200 
201 	if (mscp_init(mi)) {
202 		aprint_error_dev(&mi->mi_dev, "can't init, controller hung\n");
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 	    device_xname(&mi->mi_dev));
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: ", device_xname(&mi->mi_dev),
299 				mp->mscp_unit);
300 			mp2 = __UNVOLATILE(mp);
301 			mscp_printevent(mp2);
302 			next++;
303 			goto findunit;
304 		}
305 		break;
306 
307 	default:
308 		aprint_error_dev(&mi->mi_dev, "unable to get unit status: ");
309 		mscp_printevent(__UNVOLATILE(mp));
310 		return;
311 	}
312 
313 	/*
314 	 * If we get a lower number, we have circulated around all
315 	 * devices and are finished, otherwise try to find next unit.
316 	 * We shouldn't ever get this, it's a workaround.
317 	 */
318 	if (mp->mscp_unit < next)
319 		return;
320 
321 	next = mp->mscp_unit + 1;
322 	goto findunit;
323 }
324 
325 
326 /*
327  * The ctlr gets initialised, normally after boot but may also be
328  * done if the ctlr gets in an unknown state. Returns 1 if init
329  * fails, 0 otherwise.
330  */
331 int
332 mscp_init(mi)
333 	struct	mscp_softc *mi;
334 {
335 	struct	mscp *mp;
336 	volatile int i;
337 	int	status, count;
338 	unsigned int j = 0;
339 
340 	/*
341 	 * While we are thinking about it, reset the next command
342 	 * and response indicies.
343 	 */
344 	mi->mi_cmd.mri_next = 0;
345 	mi->mi_rsp.mri_next = 0;
346 
347 	mi->mi_flags |= MSC_IGNOREINTR;
348 
349 	if ((mi->mi_type & MSCPBUS_KDB) == 0)
350 		WRITE_IP(0); /* Kick off */;
351 
352 	status = mscp_waitstep(mi, MP_STEP1, MP_STEP1);/* Wait to it wakes up */
353 	if (status == 0)
354 		return 1; /* Init failed */
355 	if (READ_SA & MP_ERR) {
356 		(*mi->mi_mc->mc_saerror)(device_parent(&mi->mi_dev), 0);
357 		return 1;
358 	}
359 
360 	/* step1 */
361 	WRITE_SW(MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) |
362 	    MP_IE | (mi->mi_ivec >> 2));
363 	status = mscp_waitstep(mi, STEP1MASK, STEP1GOOD);
364 	if (status == 0) {
365 		(*mi->mi_mc->mc_saerror)(device_parent(&mi->mi_dev), 0);
366 		return 1;
367 	}
368 
369 	/* step2 */
370 	WRITE_SW(((mi->mi_dmam->dm_segs[0].ds_addr & 0xffff) +
371 	    offsetof(struct mscp_pack, mp_ca.ca_rspdsc[0])) |
372 	    (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0));
373 	status = mscp_waitstep(mi, STEP2MASK, STEP2GOOD(mi->mi_ivec >> 2));
374 	if (status == 0) {
375 		(*mi->mi_mc->mc_saerror)(device_parent(&mi->mi_dev), 0);
376 		return 1;
377 	}
378 
379 	/* step3 */
380 	WRITE_SW((mi->mi_dmam->dm_segs[0].ds_addr >> 16));
381 	status = mscp_waitstep(mi, STEP3MASK, STEP3GOOD);
382 	if (status == 0) {
383 		(*mi->mi_mc->mc_saerror)(device_parent(&mi->mi_dev), 0);
384 		return 1;
385 	}
386 	i = READ_SA & 0377;
387 	printf(": version %d model %d\n", i & 15, i >> 4);
388 
389 #define BURST 4 /* XXX */
390 	if (mi->mi_type & MSCPBUS_UDA) {
391 		WRITE_SW(MP_GO | (BURST - 1) << 2);
392 		printf("%s: DMA burst size set to %d\n",
393 		    device_xname(&mi->mi_dev), BURST);
394 	}
395 	WRITE_SW(MP_GO);
396 
397 	mscp_initds(mi);
398 	mi->mi_flags &= ~MSC_IGNOREINTR;
399 
400 	/*
401 	 * Set up all necessary info in the bus softc struct, get a
402 	 * mscp packet and set characteristics for this controller.
403 	 */
404 	mi->mi_credits = MSCP_MINCREDITS + 1;
405 	mp = mscp_getcp(mi, MSCP_DONTWAIT);
406 
407 	mi->mi_credits = 0;
408 	mp->mscp_opcode = M_OP_SETCTLRC;
409 	mp->mscp_unit = mp->mscp_modifier = mp->mscp_flags =
410 	    mp->mscp_sccc.sccc_version = mp->mscp_sccc.sccc_hosttimo =
411 	    mp->mscp_sccc.sccc_time = mp->mscp_sccc.sccc_time1 =
412 	    mp->mscp_sccc.sccc_errlgfl = 0;
413 	mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | M_CF_THIS;
414 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
415 	i = READ_IP;
416 
417 	count = 0;
418 	while (count < DELAYTEN) {
419 		if (((volatile int)mi->mi_flags & MSC_READY) != 0)
420 			break;
421 		if ((j = READ_SA) & MP_ERR)
422 			goto out;
423 		DELAY(10000);
424 		count += 1;
425 	}
426 	if (count == DELAYTEN) {
427 out:
428 		aprint_error_dev(&mi->mi_dev, "couldn't set ctlr characteristics, sa=%x\n", 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 				    device_xname(device_parent(&mi->mi_dev)));
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)(device_parent(&mi->mi_dev),
570 		    &mi->mi_xi[next]);
571 		(void)BUFQ_GET(mi->mi_resq);
572 	}
573 }
574 
575 void
576 mscp_dgo(mi, mxi)
577 	struct mscp_softc *mi;
578 	struct mscp_xi *mxi;
579 {
580 	volatile int i;
581 	struct	mscp *mp;
582 
583 	/*
584 	 * Fill in the MSCP packet and move the buffer to the I/O wait queue.
585 	 */
586 	mp = mxi->mxi_mp;
587 	mp->mscp_seq.seq_buffer = mxi->mxi_dmam->dm_segs[0].ds_addr;
588 
589 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
590 	i = READ_IP;
591 }
592 
593 #ifdef DIAGNOSTIC
594 /*
595  * Dump the entire contents of an MSCP packet in hex.  Mainly useful
596  * for debugging....
597  */
598 void
599 mscp_hexdump(mp)
600 	struct mscp *mp;
601 {
602 	long *p = (long *) mp;
603 	int i = mp->mscp_msglen;
604 
605 	if (i > 256)		/* sanity */
606 		i = 256;
607 	i /= sizeof (*p);	/* ASSUMES MULTIPLE OF sizeof(long) */
608 	while (--i >= 0)
609 		printf("0x%x ", (int)*p++);
610 	printf("\n");
611 }
612 #endif
613 
614 /*
615  * MSCP error reporting
616  */
617 
618 /*
619  * Messages for the various subcodes.
620  */
621 static char unknown_msg[] = "unknown subcode";
622 
623 /*
624  * Subcodes for Success (0)
625  */
626 static const char *succ_msgs[] = {
627 	"normal",		/* 0 */
628 	"spin down ignored",	/* 1 = Spin-Down Ignored */
629 	"still connected",	/* 2 = Still Connected */
630 	unknown_msg,
631 	"dup. unit #",		/* 4 = Duplicate Unit Number */
632 	unknown_msg,
633 	unknown_msg,
634 	unknown_msg,
635 	"already online",	/* 8 = Already Online */
636 	unknown_msg,
637 	unknown_msg,
638 	unknown_msg,
639 	unknown_msg,
640 	unknown_msg,
641 	unknown_msg,
642 	unknown_msg,
643 	"still online",		/* 16 = Still Online */
644 };
645 
646 /*
647  * Subcodes for Invalid Command (1)
648  */
649 static const char *icmd_msgs[] = {
650 	"invalid msg length",	/* 0 = Invalid Message Length */
651 };
652 
653 /*
654  * Subcodes for Command Aborted (2)
655  */
656 /* none known */
657 
658 /*
659  * Subcodes for Unit Offline (3)
660  */
661 static const char *offl_msgs[] = {
662 	"unknown drive",	/* 0 = Unknown, or online to other ctlr */
663 	"not mounted",		/* 1 = Unmounted, or RUN/STOP at STOP */
664 	"inoperative",		/* 2 = Unit Inoperative */
665 	unknown_msg,
666 	"duplicate",		/* 4 = Duplicate Unit Number */
667 	unknown_msg,
668 	unknown_msg,
669 	unknown_msg,
670 	"in diagnosis",		/* 8 = Disabled by FS or diagnostic */
671 };
672 
673 /*
674  * Subcodes for Unit Available (4)
675  */
676 /* none known */
677 
678 /*
679  * Subcodes for Media Format Error (5)
680  */
681 static const char *media_fmt_msgs[] = {
682 	"fct unread - edc",	/* 0 = FCT unreadable */
683 	"invalid sector header",/* 1 = Invalid Sector Header */
684 	"not 512 sectors",	/* 2 = Not 512 Byte Sectors */
685 	"not formatted",	/* 3 = Not Formatted */
686 	"fct ecc",		/* 4 = FCT ECC */
687 };
688 
689 /*
690  * Subcodes for Write Protected (6)
691  * N.B.:  Code 6 subcodes are 7 bits higher than other subcodes
692  * (i.e., bits 12-15).
693  */
694 static const char *wrprot_msgs[] = {
695 	unknown_msg,
696 	"software",		/* 1 = Software Write Protect */
697 	"hardware",		/* 2 = Hardware Write Protect */
698 };
699 
700 /*
701  * Subcodes for Compare Error (7)
702  */
703 /* none known */
704 
705 /*
706  * Subcodes for Data Error (8)
707  */
708 static const char *data_msgs[] = {
709 	"forced error",		/* 0 = Forced Error (software) */
710 	unknown_msg,
711 	"header compare",	/* 2 = Header Compare Error */
712 	"sync timeout",		/* 3 = Sync Timeout Error */
713 	unknown_msg,
714 	unknown_msg,
715 	unknown_msg,
716 	"uncorrectable ecc",	/* 7 = Uncorrectable ECC */
717 	"1 symbol ecc",		/* 8 = 1 bit ECC */
718 	"2 symbol ecc",		/* 9 = 2 bit ECC */
719 	"3 symbol ecc",		/* 10 = 3 bit ECC */
720 	"4 symbol ecc",		/* 11 = 4 bit ECC */
721 	"5 symbol ecc",		/* 12 = 5 bit ECC */
722 	"6 symbol ecc",		/* 13 = 6 bit ECC */
723 	"7 symbol ecc",		/* 14 = 7 bit ECC */
724 	"8 symbol ecc",		/* 15 = 8 bit ECC */
725 };
726 
727 /*
728  * Subcodes for Host Buffer Access Error (9)
729  */
730 static const char *host_buffer_msgs[] = {
731 	unknown_msg,
732 	"odd xfer addr",	/* 1 = Odd Transfer Address */
733 	"odd xfer count",	/* 2 = Odd Transfer Count */
734 	"non-exist. memory",	/* 3 = Non-Existent Memory */
735 	"memory parity",	/* 4 = Memory Parity Error */
736 };
737 
738 /*
739  * Subcodes for Controller Error (10)
740  */
741 static const char *cntlr_msgs[] = {
742 	unknown_msg,
743 	"serdes overrun",	/* 1 = Serialiser/Deserialiser Overrun */
744 	"edc",			/* 2 = Error Detection Code? */
745 	"inconsistent internal data struct",/* 3 = Internal Error */
746 };
747 
748 /*
749  * Subcodes for Drive Error (11)
750  */
751 static const char *drive_msgs[] = {
752 	unknown_msg,
753 	"sdi command timeout",	/* 1 = SDI Command Timeout */
754 	"ctlr detected protocol",/* 2 = Controller Detected Protocol Error */
755 	"positioner",		/* 3 = Positioner Error */
756 	"lost rd/wr ready",	/* 4 = Lost R/W Ready Error */
757 	"drive clock dropout",	/* 5 = Lost Drive Clock */
758 	"lost recvr ready",	/* 6 = Lost Receiver Ready */
759 	"drive detected error", /* 7 = Drive Error */
760 	"ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
761 };
762 
763 /*
764  * The following table correlates message codes with the
765  * decoding strings.
766  */
767 struct code_decode {
768 	const char	*cdc_msg;
769 	int	cdc_nsubcodes;
770 	const char	**cdc_submsgs;
771 } code_decode[] = {
772 #define SC(m)	sizeof (m) / sizeof (m[0]), m
773 	{"success",			SC(succ_msgs)},
774 	{"invalid command",		SC(icmd_msgs)},
775 	{"command aborted",		0, 0},
776 	{"unit offline",		SC(offl_msgs)},
777 	{"unit available",		0, 0},
778 	{"media format error",		SC(media_fmt_msgs)},
779 	{"write protected",		SC(wrprot_msgs)},
780 	{"compare error",		0, 0},
781 	{"data error",			SC(data_msgs)},
782 	{"host buffer access error",	SC(host_buffer_msgs)},
783 	{"controller error",		SC(cntlr_msgs)},
784 	{"drive error",			SC(drive_msgs)},
785 #undef SC
786 };
787 
788 /*
789  * Print the decoded error event from an MSCP error datagram.
790  */
791 void
792 mscp_printevent(mp)
793 	struct mscp *mp;
794 {
795 	int event = mp->mscp_event;
796 	struct code_decode *cdc;
797 	int c, sc;
798 	const char *cm, *scm;
799 
800 	/*
801 	 * The code is the lower six bits of the event number (aka
802 	 * status).  If that is 6 (write protect), the subcode is in
803 	 * bits 12-15; otherwise, it is in bits 5-11.
804 	 * I WONDER WHAT THE OTHER BITS ARE FOR.  IT SURE WOULD BE
805 	 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
806 	 */
807 	c = event & M_ST_MASK;
808 	sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff;
809 	if (c >= sizeof code_decode / sizeof code_decode[0])
810 		cm = "- unknown code", scm = "??";
811 	else {
812 		cdc = &code_decode[c];
813 		cm = cdc->cdc_msg;
814 		if (sc >= cdc->cdc_nsubcodes)
815 			scm = unknown_msg;
816 		else
817 			scm = cdc->cdc_submsgs[sc];
818 	}
819 	printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc);
820 }
821 
822 static const char *codemsg[16] = {
823 	"lbn", "code 1", "code 2", "code 3",
824 	"code 4", "code 5", "rbn", "code 7",
825 	"code 8", "code 9", "code 10", "code 11",
826 	"code 12", "code 13", "code 14", "code 15"
827 };
828 /*
829  * Print the code and logical block number for an error packet.
830  * THIS IS PROBABLY PECULIAR TO DISK DRIVES.  IT SURE WOULD BE
831  * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
832  */
833 int
834 mscp_decodeerror(name, mp, mi)
835 	const char *name;
836 	struct mscp *mp;
837 	struct mscp_softc *mi;
838 {
839 	int issoft;
840 	/*
841 	 * We will get three sdi errors of type 11 after autoconfig
842 	 * is finished; depending of searching for non-existing units.
843 	 * How can we avoid this???
844 	 */
845 	if (((mp->mscp_event & M_ST_MASK) == 11) && (mi->mi_ierr++ < 3))
846 		return 1;
847 	/*
848 	 * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and
849 	 * the logical block number.  Code 0 is a regular block; code 6
850 	 * is a replacement block.  The remaining codes are currently
851 	 * undefined.  The code is in the upper four bits of the header
852 	 * (bits 0-27 are the lbn).
853 	 */
854 	issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT);
855 #define BADCODE(h)	(codemsg[(unsigned)(h) >> 28])
856 #define BADLBN(h)	((h) & 0xfffffff)
857 
858 	printf("%s: drive %d %s error datagram%s:", name, mp->mscp_unit,
859 		issoft ? "soft" : "hard",
860 		mp->mscp_flags & M_LF_CONT ? " (continuing)" : "");
861 	switch (mp->mscp_format & 0377) {
862 
863 	case M_FM_CTLRERR:	/* controller error */
864 		break;
865 
866 	case M_FM_BUSADDR:	/* host memory access error */
867 		printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr);
868 		break;
869 
870 	case M_FM_DISKTRN:
871 		printf(" unit %d: level %d retry %d, %s %d:",
872 			mp->mscp_unit,
873 			mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry,
874 			BADCODE(mp->mscp_erd.erd_hdr),
875 			(int)BADLBN(mp->mscp_erd.erd_hdr));
876 		break;
877 
878 	case M_FM_SDI:
879 		printf(" unit %d: %s %d:", mp->mscp_unit,
880 			BADCODE(mp->mscp_erd.erd_hdr),
881 			(int)BADLBN(mp->mscp_erd.erd_hdr));
882 		break;
883 
884 	case M_FM_SMLDSK:
885 		printf(" unit %d: small disk error, cyl %d:",
886 			mp->mscp_unit, mp->mscp_erd.erd_sdecyl);
887 		break;
888 
889 	case M_FM_TAPETRN:
890 		printf(" unit %d: tape transfer error, grp 0x%x event 0%o:",
891 		    mp->mscp_unit, mp->mscp_erd.erd_sdecyl, mp->mscp_event);
892 		break;
893 
894 	case M_FM_STIERR:
895 		printf(" unit %d: STI error, event 0%o:", mp->mscp_unit,
896 		    mp->mscp_event);
897 		break;
898 
899 	default:
900 		printf(" unit %d: unknown error, format 0x%x:",
901 			mp->mscp_unit, mp->mscp_format);
902 	}
903 	mscp_printevent(mp);
904 	return 0;
905 #undef BADCODE
906 #undef BADLBN
907 }
908