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