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