Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / mscp / mscp_subr.c
blobe78fbe3c38567d73d4823ec7ce19112f314cd991
1 /* $NetBSD: mscp_subr.c,v 1.40 2009/05/12 13:16:17 cegger Exp $ */
2 /*
3 * Copyright (c) 1988 Regents of the University of California.
4 * All rights reserved.
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
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.
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.
33 * @(#)mscp.c 7.5 (Berkeley) 12/16/90
37 * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
39 * This code is derived from software contributed to Berkeley by
40 * Chris Torek.
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.
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.
70 * @(#)mscp.c 7.5 (Berkeley) 12/16/90
74 * MSCP generic driver routines
77 #include <sys/cdefs.h>
78 __KERNEL_RCSID(0, "$NetBSD: mscp_subr.c,v 1.40 2009/05/12 13:16:17 cegger Exp $");
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 #include <sys/kmem.h>
88 #include <sys/bus.h>
89 #include <machine/sid.h>
91 #include <dev/mscp/mscp.h>
92 #include <dev/mscp/mscpreg.h>
93 #include <dev/mscp/mscpvar.h>
95 #include "ra.h"
96 #include "mt.h"
98 #define b_forw b_hash.le_next
100 int mscp_match(device_t, cfdata_t, void *);
101 void mscp_attach(device_t, device_t, void *);
102 void mscp_start(struct mscp_softc *);
103 int mscp_init(struct mscp_softc *);
104 void mscp_initds(struct mscp_softc *);
105 int mscp_waitstep(struct mscp_softc *, int, int);
107 CFATTACH_DECL(mscpbus, sizeof(struct mscp_softc),
108 mscp_match, mscp_attach, NULL, NULL);
110 #define READ_SA (bus_space_read_2(mi->mi_iot, mi->mi_sah, 0))
111 #define READ_IP (bus_space_read_2(mi->mi_iot, mi->mi_iph, 0))
112 #define WRITE_IP(x) bus_space_write_2(mi->mi_iot, mi->mi_iph, 0, (x))
113 #define WRITE_SW(x) bus_space_write_2(mi->mi_iot, mi->mi_swh, 0, (x))
115 struct mscp slavereply;
117 #define NITEMS 4
119 static inline void
120 mscp_free_workitems(struct mscp_softc *mi)
122 struct mscp_work *mw;
124 while (!SLIST_EMPTY(&mi->mi_freelist)) {
125 mw = SLIST_FIRST(&mi->mi_freelist);
126 SLIST_REMOVE_HEAD(&mi->mi_freelist, mw_list);
127 kmem_free(mw, sizeof(*mw));
132 * This function is for delay during init. Some MSCP clone card (Dilog)
133 * can't handle fast read from its registers, and therefore need
134 * a delay between them.
137 #define DELAYTEN 1000
139 mscp_waitstep(struct mscp_softc *mi, int mask, int result)
141 int status = 1;
143 if ((READ_SA & mask) != result) {
144 volatile int count = 0;
145 while ((READ_SA & mask) != result) {
146 DELAY(10000);
147 count += 1;
148 if (count > DELAYTEN)
149 break;
151 if (count > DELAYTEN)
152 status = 0;
154 return status;
158 mscp_match(device_t parent, cfdata_t match, void *aux)
160 struct mscp_attach_args *ma = aux;
162 #if NRA || NRX
163 if (ma->ma_type & MSCPBUS_DISK)
164 return 1;
165 #endif
166 #if NMT
167 if (ma->ma_type & MSCPBUS_TAPE)
168 return 1;
169 #endif
170 return 0;
173 void
174 mscp_attach(device_t parent, device_t self, void *aux)
176 struct mscp_attach_args *ma = aux;
177 struct mscp_softc *mi = device_private(self);
178 struct mscp *mp2;
179 volatile struct mscp *mp;
180 volatile int i;
181 int timeout, error, next = 0;
183 mi->mi_mc = ma->ma_mc;
184 mi->mi_me = NULL;
185 mi->mi_type = ma->ma_type;
186 mi->mi_uda = ma->ma_uda;
187 mi->mi_dmat = ma->ma_dmat;
188 mi->mi_dmam = ma->ma_dmam;
189 mi->mi_iot = ma->ma_iot;
190 mi->mi_iph = ma->ma_iph;
191 mi->mi_sah = ma->ma_sah;
192 mi->mi_swh = ma->ma_swh;
193 mi->mi_ivec = ma->ma_ivec;
194 mi->mi_adapnr = ma->ma_adapnr;
195 mi->mi_ctlrnr = ma->ma_ctlrnr;
196 *ma->ma_softc = mi;
198 mutex_init(&mi->mi_mtx, MUTEX_DEFAULT, IPL_VM);
199 SLIST_INIT(&mi->mi_freelist);
201 error = workqueue_create(&mi->mi_wq, "mscp_wq", mscp_worker, NULL,
202 PRI_NONE, IPL_VM, 0);
203 if (error != 0) {
204 aprint_error_dev(&mi->mi_dev, "could not create workqueue");
205 return;
208 /* Stick some items on the free list to be used in autoconf */
209 for (i = 0; i < NITEMS; i++) {
210 struct mscp_work *mw;
212 if ((mw = kmem_zalloc(sizeof(*mw), KM_SLEEP)) == NULL) {
213 mscp_free_workitems(mi);
214 aprint_error_dev(&mi->mi_dev,
215 "failed to allocate memory for work items");
216 return;
219 SLIST_INSERT_HEAD(&mi->mi_freelist, mw, mw_list);
223 * Go out to init the bus, so that we can give commands
224 * to its devices.
226 mi->mi_cmd.mri_size = NCMD;
227 mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc;
228 mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd;
229 mi->mi_rsp.mri_size = NRSP;
230 mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc;
231 mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp;
232 bufq_alloc(&mi->mi_resq, "fcfs", 0);
234 if (mscp_init(mi)) {
235 aprint_error_dev(&mi->mi_dev, "can't init, controller hung\n");
236 return;
238 for (i = 0; i < NCMD; i++) {
239 mi->mi_mxiuse |= (1 << i);
240 if (bus_dmamap_create(mi->mi_dmat, (64*1024), 16, (64*1024),
241 0, BUS_DMA_NOWAIT, &mi->mi_xi[i].mxi_dmam)) {
242 printf("Couldn't alloc dmamap %d\n", i);
243 return;
248 #if NRA
249 if (ma->ma_type & MSCPBUS_DISK) {
250 extern struct mscp_device ra_device;
252 mi->mi_me = &ra_device;
254 #endif
255 #if NMT
256 if (ma->ma_type & MSCPBUS_TAPE) {
257 extern struct mscp_device mt_device;
259 mi->mi_me = &mt_device;
261 #endif
263 * Go out and search for sub-units on this MSCP bus,
264 * and call config_found for each found.
266 findunit:
267 mp = mscp_getcp(mi, MSCP_DONTWAIT);
268 if (mp == NULL)
269 panic("mscpattach: no packets");
270 mp->mscp_opcode = M_OP_GETUNITST;
271 mp->mscp_unit = next;
272 mp->mscp_modifier = M_GUM_NEXTUNIT;
273 *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
274 slavereply.mscp_opcode = 0;
276 i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
277 mp = &slavereply;
278 timeout = 1000;
279 while (timeout-- > 0) {
280 DELAY(10000);
281 if (mp->mscp_opcode)
282 goto gotit;
284 printf("%s: no response to Get Unit Status request\n",
285 device_xname(&mi->mi_dev));
286 return;
288 gotit: /*
289 * Got a slave response. If the unit is there, use it.
291 switch (mp->mscp_status & M_ST_MASK) {
293 case M_ST_SUCCESS: /* worked */
294 case M_ST_AVAILABLE: /* found another drive */
295 break; /* use it */
297 case M_ST_OFFLINE:
299 * Figure out why it is off line. It may be because
300 * it is nonexistent, or because it is spun down, or
301 * for some other reason.
303 switch (mp->mscp_status & ~M_ST_MASK) {
305 case M_OFFLINE_UNKNOWN:
307 * No such drive, and there are none with
308 * higher unit numbers either, if we are
309 * using M_GUM_NEXTUNIT.
311 mi->mi_ierr = 3;
312 return;
314 case M_OFFLINE_UNMOUNTED:
316 * The drive is not spun up. Use it anyway.
318 * N.B.: this seems to be a common occurrance
319 * after a power failure. The first attempt
320 * to bring it on line seems to spin it up
321 * (and thus takes several minutes). Perhaps
322 * we should note here that the on-line may
323 * take longer than usual.
325 break;
327 default:
329 * In service, or something else equally unusable.
331 printf("%s: unit %d off line: ", device_xname(&mi->mi_dev),
332 mp->mscp_unit);
333 mp2 = __UNVOLATILE(mp);
334 mscp_printevent(mp2);
335 next++;
336 goto findunit;
338 break;
340 default:
341 aprint_error_dev(&mi->mi_dev, "unable to get unit status: ");
342 mscp_printevent(__UNVOLATILE(mp));
343 return;
347 * If we get a lower number, we have circulated around all
348 * devices and are finished, otherwise try to find next unit.
349 * We shouldn't ever get this, it's a workaround.
351 if (mp->mscp_unit < next)
352 return;
354 next = mp->mscp_unit + 1;
355 goto findunit;
360 * The ctlr gets initialised, normally after boot but may also be
361 * done if the ctlr gets in an unknown state. Returns 1 if init
362 * fails, 0 otherwise.
365 mscp_init(struct mscp_softc *mi)
367 struct mscp *mp;
368 volatile int i;
369 int status, count;
370 unsigned int j = 0;
373 * While we are thinking about it, reset the next command
374 * and response indicies.
376 mi->mi_cmd.mri_next = 0;
377 mi->mi_rsp.mri_next = 0;
379 mi->mi_flags |= MSC_IGNOREINTR;
381 if ((mi->mi_type & MSCPBUS_KDB) == 0)
382 WRITE_IP(0); /* Kick off */;
384 status = mscp_waitstep(mi, MP_STEP1, MP_STEP1);/* Wait to it wakes up */
385 if (status == 0)
386 return 1; /* Init failed */
387 if (READ_SA & MP_ERR) {
388 (*mi->mi_mc->mc_saerror)(device_parent(&mi->mi_dev), 0);
389 return 1;
392 /* step1 */
393 WRITE_SW(MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) |
394 MP_IE | (mi->mi_ivec >> 2));
395 status = mscp_waitstep(mi, STEP1MASK, STEP1GOOD);
396 if (status == 0) {
397 (*mi->mi_mc->mc_saerror)(device_parent(&mi->mi_dev), 0);
398 return 1;
401 /* step2 */
402 WRITE_SW(((mi->mi_dmam->dm_segs[0].ds_addr & 0xffff) +
403 offsetof(struct mscp_pack, mp_ca.ca_rspdsc[0])) |
404 (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0));
405 status = mscp_waitstep(mi, STEP2MASK, STEP2GOOD(mi->mi_ivec >> 2));
406 if (status == 0) {
407 (*mi->mi_mc->mc_saerror)(device_parent(&mi->mi_dev), 0);
408 return 1;
411 /* step3 */
412 WRITE_SW((mi->mi_dmam->dm_segs[0].ds_addr >> 16));
413 status = mscp_waitstep(mi, STEP3MASK, STEP3GOOD);
414 if (status == 0) {
415 (*mi->mi_mc->mc_saerror)(device_parent(&mi->mi_dev), 0);
416 return 1;
418 i = READ_SA & 0377;
419 printf(": version %d model %d\n", i & 15, i >> 4);
421 #define BURST 4 /* XXX */
422 if (mi->mi_type & MSCPBUS_UDA) {
423 WRITE_SW(MP_GO | (BURST - 1) << 2);
424 printf("%s: DMA burst size set to %d\n",
425 device_xname(&mi->mi_dev), BURST);
427 WRITE_SW(MP_GO);
429 mscp_initds(mi);
430 mi->mi_flags &= ~MSC_IGNOREINTR;
433 * Set up all necessary info in the bus softc struct, get a
434 * mscp packet and set characteristics for this controller.
436 mi->mi_credits = MSCP_MINCREDITS + 1;
437 mp = mscp_getcp(mi, MSCP_DONTWAIT);
439 mi->mi_credits = 0;
440 mp->mscp_opcode = M_OP_SETCTLRC;
441 mp->mscp_unit = mp->mscp_modifier = mp->mscp_flags =
442 mp->mscp_sccc.sccc_version = mp->mscp_sccc.sccc_hosttimo =
443 mp->mscp_sccc.sccc_time = mp->mscp_sccc.sccc_time1 =
444 mp->mscp_sccc.sccc_errlgfl = 0;
445 mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | M_CF_THIS;
446 *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
447 i = READ_IP;
449 count = 0;
450 while (count < DELAYTEN) {
451 if (((volatile int)mi->mi_flags & MSC_READY) != 0)
452 break;
453 if ((j = READ_SA) & MP_ERR)
454 goto out;
455 DELAY(10000);
456 count += 1;
458 if (count == DELAYTEN) {
459 out:
460 aprint_error_dev(&mi->mi_dev, "couldn't set ctlr characteristics, sa=%x\n", j);
461 return 1;
463 return 0;
467 * Initialise the various data structures that control the mscp protocol.
469 void
470 mscp_initds(struct mscp_softc *mi)
472 struct mscp_pack *ud = mi->mi_uda;
473 struct mscp *mp;
474 int i;
476 for (i = 0, mp = ud->mp_rsp; i < NRSP; i++, mp++) {
477 ud->mp_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT |
478 (mi->mi_dmam->dm_segs[0].ds_addr +
479 offsetof(struct mscp_pack, mp_rsp[i].mscp_cmdref));
480 mp->mscp_addr = &ud->mp_ca.ca_rspdsc[i];
481 mp->mscp_msglen = MSCP_MSGLEN;
483 for (i = 0, mp = ud->mp_cmd; i < NCMD; i++, mp++) {
484 ud->mp_ca.ca_cmddsc[i] = MSCP_INT |
485 (mi->mi_dmam->dm_segs[0].ds_addr +
486 offsetof(struct mscp_pack, mp_cmd[i].mscp_cmdref));
487 mp->mscp_addr = &ud->mp_ca.ca_cmddsc[i];
488 mp->mscp_msglen = MSCP_MSGLEN;
489 if (mi->mi_type & MSCPBUS_TAPE)
490 mp->mscp_vcid = 1;
494 static void mscp_kickaway(struct mscp_softc *);
496 void
497 mscp_intr(struct mscp_softc *mi)
499 struct mscp_pack *ud = mi->mi_uda;
501 if (mi->mi_flags & MSC_IGNOREINTR)
502 return;
504 * Check for response and command ring transitions.
506 if (ud->mp_ca.ca_rspint) {
507 ud->mp_ca.ca_rspint = 0;
508 mscp_dorsp(mi);
510 if (ud->mp_ca.ca_cmdint) {
511 ud->mp_ca.ca_cmdint = 0;
512 MSCP_DOCMD(mi);
516 * If there are any not-yet-handled request, try them now.
518 if (bufq_peek(mi->mi_resq))
519 mscp_kickaway(mi);
523 mscp_print(void *aux, const char *name)
525 struct drive_attach_args *da = aux;
526 struct mscp *mp = da->da_mp;
527 int type = mp->mscp_guse.guse_mediaid;
529 if (name) {
530 aprint_normal("%c%c", MSCP_MID_CHAR(2, type),
531 MSCP_MID_CHAR(1, type));
532 if (MSCP_MID_ECH(0, type))
533 aprint_normal("%c", MSCP_MID_CHAR(0, type));
534 aprint_normal("%d at %s drive %d", MSCP_MID_NUM(type), name,
535 mp->mscp_unit);
537 return UNCONF;
541 * common strategy routine for all types of MSCP devices.
543 void
544 mscp_strategy(struct buf *bp, device_t usc)
546 struct mscp_softc *mi = (void *)usc;
547 int s = spluba();
549 bufq_put(mi->mi_resq, bp);
550 mscp_kickaway(mi);
551 splx(s);
555 void
556 mscp_kickaway(struct mscp_softc *mi)
558 struct buf *bp;
559 struct mscp *mp;
560 int next;
562 while ((bp = bufq_peek(mi->mi_resq)) != NULL) {
564 * Ok; we are ready to try to start a xfer. Get a MSCP packet
565 * and try to start...
567 if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) {
568 if (mi->mi_credits > MSCP_MINCREDITS)
569 printf("%s: command ring too small\n",
570 device_xname(device_parent(&mi->mi_dev)));
572 * By some (strange) reason we didn't get a MSCP packet.
573 * Just return and wait for free packets.
575 return;
578 if ((next = (ffs(mi->mi_mxiuse) - 1)) < 0)
579 panic("no mxi buffers");
580 mi->mi_mxiuse &= ~(1 << next);
581 if (mi->mi_xi[next].mxi_inuse)
582 panic("mxi inuse");
584 * Set up the MSCP packet and ask the ctlr to start.
586 mp->mscp_opcode =
587 (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
588 mp->mscp_cmdref = next;
589 mi->mi_xi[next].mxi_bp = bp;
590 mi->mi_xi[next].mxi_mp = mp;
591 mi->mi_xi[next].mxi_inuse = 1;
592 bp->b_resid = next;
593 (*mi->mi_me->me_fillin)(bp, mp);
594 (*mi->mi_mc->mc_go)(device_parent(&mi->mi_dev),
595 &mi->mi_xi[next]);
596 (void)bufq_get(mi->mi_resq);
600 void
601 mscp_dgo(struct mscp_softc *mi, struct mscp_xi *mxi)
603 volatile int i;
604 struct mscp *mp;
607 * Fill in the MSCP packet and move the buffer to the I/O wait queue.
609 mp = mxi->mxi_mp;
610 mp->mscp_seq.seq_buffer = mxi->mxi_dmam->dm_segs[0].ds_addr;
612 *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
613 i = READ_IP;
616 #ifdef DIAGNOSTIC
618 * Dump the entire contents of an MSCP packet in hex. Mainly useful
619 * for debugging....
621 void
622 mscp_hexdump(struct mscp *mp)
624 long *p = (long *) mp;
625 int i = mp->mscp_msglen;
627 if (i > 256) /* sanity */
628 i = 256;
629 i /= sizeof (*p); /* ASSUMES MULTIPLE OF sizeof(long) */
630 while (--i >= 0)
631 printf("0x%x ", (int)*p++);
632 printf("\n");
634 #endif
637 * MSCP error reporting
641 * Messages for the various subcodes.
643 static char unknown_msg[] = "unknown subcode";
646 * Subcodes for Success (0)
648 static const char *succ_msgs[] = {
649 "normal", /* 0 */
650 "spin down ignored", /* 1 = Spin-Down Ignored */
651 "still connected", /* 2 = Still Connected */
652 unknown_msg,
653 "dup. unit #", /* 4 = Duplicate Unit Number */
654 unknown_msg,
655 unknown_msg,
656 unknown_msg,
657 "already online", /* 8 = Already Online */
658 unknown_msg,
659 unknown_msg,
660 unknown_msg,
661 unknown_msg,
662 unknown_msg,
663 unknown_msg,
664 unknown_msg,
665 "still online", /* 16 = Still Online */
669 * Subcodes for Invalid Command (1)
671 static const char *icmd_msgs[] = {
672 "invalid msg length", /* 0 = Invalid Message Length */
676 * Subcodes for Command Aborted (2)
678 /* none known */
681 * Subcodes for Unit Offline (3)
683 static const char *offl_msgs[] = {
684 "unknown drive", /* 0 = Unknown, or online to other ctlr */
685 "not mounted", /* 1 = Unmounted, or RUN/STOP at STOP */
686 "inoperative", /* 2 = Unit Inoperative */
687 unknown_msg,
688 "duplicate", /* 4 = Duplicate Unit Number */
689 unknown_msg,
690 unknown_msg,
691 unknown_msg,
692 "in diagnosis", /* 8 = Disabled by FS or diagnostic */
696 * Subcodes for Unit Available (4)
698 /* none known */
701 * Subcodes for Media Format Error (5)
703 static const char *media_fmt_msgs[] = {
704 "fct unread - edc", /* 0 = FCT unreadable */
705 "invalid sector header",/* 1 = Invalid Sector Header */
706 "not 512 sectors", /* 2 = Not 512 Byte Sectors */
707 "not formatted", /* 3 = Not Formatted */
708 "fct ecc", /* 4 = FCT ECC */
712 * Subcodes for Write Protected (6)
713 * N.B.: Code 6 subcodes are 7 bits higher than other subcodes
714 * (i.e., bits 12-15).
716 static const char *wrprot_msgs[] = {
717 unknown_msg,
718 "software", /* 1 = Software Write Protect */
719 "hardware", /* 2 = Hardware Write Protect */
723 * Subcodes for Compare Error (7)
725 /* none known */
728 * Subcodes for Data Error (8)
730 static const char *data_msgs[] = {
731 "forced error", /* 0 = Forced Error (software) */
732 unknown_msg,
733 "header compare", /* 2 = Header Compare Error */
734 "sync timeout", /* 3 = Sync Timeout Error */
735 unknown_msg,
736 unknown_msg,
737 unknown_msg,
738 "uncorrectable ecc", /* 7 = Uncorrectable ECC */
739 "1 symbol ecc", /* 8 = 1 bit ECC */
740 "2 symbol ecc", /* 9 = 2 bit ECC */
741 "3 symbol ecc", /* 10 = 3 bit ECC */
742 "4 symbol ecc", /* 11 = 4 bit ECC */
743 "5 symbol ecc", /* 12 = 5 bit ECC */
744 "6 symbol ecc", /* 13 = 6 bit ECC */
745 "7 symbol ecc", /* 14 = 7 bit ECC */
746 "8 symbol ecc", /* 15 = 8 bit ECC */
750 * Subcodes for Host Buffer Access Error (9)
752 static const char *host_buffer_msgs[] = {
753 unknown_msg,
754 "odd xfer addr", /* 1 = Odd Transfer Address */
755 "odd xfer count", /* 2 = Odd Transfer Count */
756 "non-exist. memory", /* 3 = Non-Existent Memory */
757 "memory parity", /* 4 = Memory Parity Error */
761 * Subcodes for Controller Error (10)
763 static const char *cntlr_msgs[] = {
764 unknown_msg,
765 "serdes overrun", /* 1 = Serialiser/Deserialiser Overrun */
766 "edc", /* 2 = Error Detection Code? */
767 "inconsistent internal data struct",/* 3 = Internal Error */
771 * Subcodes for Drive Error (11)
773 static const char *drive_msgs[] = {
774 unknown_msg,
775 "sdi command timeout", /* 1 = SDI Command Timeout */
776 "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */
777 "positioner", /* 3 = Positioner Error */
778 "lost rd/wr ready", /* 4 = Lost R/W Ready Error */
779 "drive clock dropout", /* 5 = Lost Drive Clock */
780 "lost recvr ready", /* 6 = Lost Receiver Ready */
781 "drive detected error", /* 7 = Drive Error */
782 "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
786 * The following table correlates message codes with the
787 * decoding strings.
789 struct code_decode {
790 const char *cdc_msg;
791 int cdc_nsubcodes;
792 const char **cdc_submsgs;
793 } code_decode[] = {
794 #define SC(m) sizeof (m) / sizeof (m[0]), m
795 {"success", SC(succ_msgs)},
796 {"invalid command", SC(icmd_msgs)},
797 {"command aborted", 0, 0},
798 {"unit offline", SC(offl_msgs)},
799 {"unit available", 0, 0},
800 {"media format error", SC(media_fmt_msgs)},
801 {"write protected", SC(wrprot_msgs)},
802 {"compare error", 0, 0},
803 {"data error", SC(data_msgs)},
804 {"host buffer access error", SC(host_buffer_msgs)},
805 {"controller error", SC(cntlr_msgs)},
806 {"drive error", SC(drive_msgs)},
807 #undef SC
811 * Print the decoded error event from an MSCP error datagram.
813 void
814 mscp_printevent(struct mscp *mp)
816 int event = mp->mscp_event;
817 struct code_decode *cdc;
818 int c, sc;
819 const char *cm, *scm;
822 * The code is the lower six bits of the event number (aka
823 * status). If that is 6 (write protect), the subcode is in
824 * bits 12-15; otherwise, it is in bits 5-11.
825 * I WONDER WHAT THE OTHER BITS ARE FOR. IT SURE WOULD BE
826 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
828 c = event & M_ST_MASK;
829 sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff;
830 if (c >= sizeof code_decode / sizeof code_decode[0])
831 cm = "- unknown code", scm = "??";
832 else {
833 cdc = &code_decode[c];
834 cm = cdc->cdc_msg;
835 if (sc >= cdc->cdc_nsubcodes)
836 scm = unknown_msg;
837 else
838 scm = cdc->cdc_submsgs[sc];
840 printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc);
843 static const char *codemsg[16] = {
844 "lbn", "code 1", "code 2", "code 3",
845 "code 4", "code 5", "rbn", "code 7",
846 "code 8", "code 9", "code 10", "code 11",
847 "code 12", "code 13", "code 14", "code 15"
850 * Print the code and logical block number for an error packet.
851 * THIS IS PROBABLY PECULIAR TO DISK DRIVES. IT SURE WOULD BE
852 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
855 mscp_decodeerror(const char *name, struct mscp *mp, struct mscp_softc *mi)
857 int issoft;
859 * We will get three sdi errors of type 11 after autoconfig
860 * is finished; depending of searching for non-existing units.
861 * How can we avoid this???
863 if (((mp->mscp_event & M_ST_MASK) == 11) && (mi->mi_ierr++ < 3))
864 return 1;
866 * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and
867 * the logical block number. Code 0 is a regular block; code 6
868 * is a replacement block. The remaining codes are currently
869 * undefined. The code is in the upper four bits of the header
870 * (bits 0-27 are the lbn).
872 issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT);
873 #define BADCODE(h) (codemsg[(unsigned)(h) >> 28])
874 #define BADLBN(h) ((h) & 0xfffffff)
876 printf("%s: drive %d %s error datagram%s:", name, mp->mscp_unit,
877 issoft ? "soft" : "hard",
878 mp->mscp_flags & M_LF_CONT ? " (continuing)" : "");
879 switch (mp->mscp_format & 0377) {
881 case M_FM_CTLRERR: /* controller error */
882 break;
884 case M_FM_BUSADDR: /* host memory access error */
885 printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr);
886 break;
888 case M_FM_DISKTRN:
889 printf(" unit %d: level %d retry %d, %s %d:",
890 mp->mscp_unit,
891 mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry,
892 BADCODE(mp->mscp_erd.erd_hdr),
893 (int)BADLBN(mp->mscp_erd.erd_hdr));
894 break;
896 case M_FM_SDI:
897 printf(" unit %d: %s %d:", mp->mscp_unit,
898 BADCODE(mp->mscp_erd.erd_hdr),
899 (int)BADLBN(mp->mscp_erd.erd_hdr));
900 break;
902 case M_FM_SMLDSK:
903 printf(" unit %d: small disk error, cyl %d:",
904 mp->mscp_unit, mp->mscp_erd.erd_sdecyl);
905 break;
907 case M_FM_TAPETRN:
908 printf(" unit %d: tape transfer error, grp 0x%x event 0%o:",
909 mp->mscp_unit, mp->mscp_erd.erd_sdecyl, mp->mscp_event);
910 break;
912 case M_FM_STIERR:
913 printf(" unit %d: STI error, event 0%o:", mp->mscp_unit,
914 mp->mscp_event);
915 break;
917 default:
918 printf(" unit %d: unknown error, format 0x%x:",
919 mp->mscp_unit, mp->mscp_format);
921 mscp_printevent(mp);
922 return 0;
923 #undef BADCODE
924 #undef BADLBN