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