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