mscp_subr.c revision 1.26 1 /* $NetBSD: mscp_subr.c,v 1.26 2005/02/04 02:10:43 perry 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.26 2005/02/04 02:10:43 perry 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(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 = (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