mscp_subr.c revision 1.35 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