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