1 /* $NetBSD: mscp_subr.c,v 1.49 2024/02/10 08:24:51 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.49 2024/02/10 08:24:51 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 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_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 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 indices. 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 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 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 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 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 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 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 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 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 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