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