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