1 /* $NetBSD: mscp_subr.c,v 1.17 2001/04/12 20:13:27 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), 16, (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 WRITE_SW((mi->mi_dmam->dm_segs[0].ds_addr >> 16)); 345 status = mscp_waitstep(mi, STEP3MASK, STEP3GOOD); 346 if (status == 0) { 347 (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0); 348 return 1; 349 } 350 i = READ_SA & 0377; 351 printf(": version %d model %d\n", i & 15, i >> 4); 352 353 #define BURST 4 /* XXX */ 354 if (mi->mi_type & MSCPBUS_UDA) { 355 WRITE_SW(MP_GO | (BURST - 1) << 2); 356 printf("%s: DMA burst size set to %d\n", 357 mi->mi_dev.dv_xname, BURST); 358 } 359 WRITE_SW(MP_GO); 360 361 mscp_initds(mi); 362 mi->mi_flags &= ~MSC_IGNOREINTR; 363 364 /* 365 * Set up all necessary info in the bus softc struct, get a 366 * mscp packet and set characteristics for this controller. 367 */ 368 mi->mi_credits = MSCP_MINCREDITS + 1; 369 mp = mscp_getcp(mi, MSCP_DONTWAIT); 370 371 mi->mi_credits = 0; 372 mp->mscp_opcode = M_OP_SETCTLRC; 373 mp->mscp_unit = mp->mscp_modifier = mp->mscp_flags = 374 mp->mscp_sccc.sccc_version = mp->mscp_sccc.sccc_hosttimo = 375 mp->mscp_sccc.sccc_time = mp->mscp_sccc.sccc_time1 = 376 mp->mscp_sccc.sccc_errlgfl = 0; 377 mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | M_CF_THIS; 378 *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 379 i = READ_IP; 380 381 count = 0; 382 while (count < DELAYTEN) { 383 if (((volatile int)mi->mi_flags & MSC_READY) != 0) 384 break; 385 if ((j = READ_SA) & MP_ERR) 386 goto out; 387 DELAY(10000); 388 count += 1; 389 } 390 if (count == DELAYTEN) { 391 out: 392 printf("%s: couldn't set ctlr characteristics, sa=%x\n", 393 mi->mi_dev.dv_xname, j); 394 return 1; 395 } 396 return 0; 397 } 398 399 /* 400 * Initialise the various data structures that control the mscp protocol. 401 */ 402 void 403 mscp_initds(mi) 404 struct mscp_softc *mi; 405 { 406 struct mscp_pack *ud = mi->mi_uda; 407 struct mscp *mp; 408 int i; 409 410 for (i = 0, mp = ud->mp_rsp; i < NRSP; i++, mp++) { 411 ud->mp_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT | 412 (mi->mi_dmam->dm_segs[0].ds_addr + 413 offsetof(struct mscp_pack, mp_rsp[i].mscp_cmdref)); 414 mp->mscp_addr = &ud->mp_ca.ca_rspdsc[i]; 415 mp->mscp_msglen = MSCP_MSGLEN; 416 } 417 for (i = 0, mp = ud->mp_cmd; i < NCMD; i++, mp++) { 418 ud->mp_ca.ca_cmddsc[i] = MSCP_INT | 419 (mi->mi_dmam->dm_segs[0].ds_addr + 420 offsetof(struct mscp_pack, mp_cmd[i].mscp_cmdref)); 421 mp->mscp_addr = &ud->mp_ca.ca_cmddsc[i]; 422 mp->mscp_msglen = MSCP_MSGLEN; 423 if (mi->mi_type & MSCPBUS_TAPE) 424 mp->mscp_vcid = 1; 425 } 426 } 427 428 static void mscp_kickaway(struct mscp_softc *); 429 430 void 431 mscp_intr(mi) 432 struct mscp_softc *mi; 433 { 434 struct mscp_pack *ud = mi->mi_uda; 435 436 if (mi->mi_flags & MSC_IGNOREINTR) 437 return; 438 /* 439 * Check for response and command ring transitions. 440 */ 441 if (ud->mp_ca.ca_rspint) { 442 ud->mp_ca.ca_rspint = 0; 443 mscp_dorsp(mi); 444 } 445 if (ud->mp_ca.ca_cmdint) { 446 ud->mp_ca.ca_cmdint = 0; 447 MSCP_DOCMD(mi); 448 } 449 450 /* 451 * If there are any not-yet-handled request, try them now. 452 */ 453 if (BUFQ_FIRST(&mi->mi_resq)) 454 mscp_kickaway(mi); 455 } 456 457 int 458 mscp_print(aux, name) 459 void *aux; 460 const char *name; 461 { 462 struct drive_attach_args *da = aux; 463 struct mscp *mp = da->da_mp; 464 int type = mp->mscp_guse.guse_mediaid; 465 466 if (name) { 467 printf("%c%c", MSCP_MID_CHAR(2, type), MSCP_MID_CHAR(1, type)); 468 if (MSCP_MID_ECH(0, type)) 469 printf("%c", MSCP_MID_CHAR(0, type)); 470 printf("%d at %s drive %d", MSCP_MID_NUM(type), name, 471 mp->mscp_unit); 472 } 473 return UNCONF; 474 } 475 476 /* 477 * common strategy routine for all types of MSCP devices. 478 */ 479 void 480 mscp_strategy(bp, usc) 481 struct buf *bp; 482 struct device *usc; 483 { 484 struct mscp_softc *mi = (void *)usc; 485 int s = spluba(); 486 487 BUFQ_INSERT_TAIL(&mi->mi_resq, bp); 488 mscp_kickaway(mi); 489 splx(s); 490 } 491 492 493 void 494 mscp_kickaway(mi) 495 struct mscp_softc *mi; 496 { 497 struct buf *bp; 498 struct mscp *mp; 499 int next; 500 501 while ((bp = BUFQ_FIRST(&mi->mi_resq)) != NULL) { 502 /* 503 * Ok; we are ready to try to start a xfer. Get a MSCP packet 504 * and try to start... 505 */ 506 if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) { 507 if (mi->mi_credits > MSCP_MINCREDITS) 508 printf("%s: command ring too small\n", 509 mi->mi_dev.dv_parent->dv_xname); 510 /* 511 * By some (strange) reason we didn't get a MSCP packet. 512 * Just return and wait for free packets. 513 */ 514 return; 515 } 516 517 if ((next = (ffs(mi->mi_mxiuse) - 1)) < 0) 518 panic("no mxi buffers"); 519 mi->mi_mxiuse &= ~(1 << next); 520 if (mi->mi_xi[next].mxi_inuse) 521 panic("mxi inuse"); 522 /* 523 * Set up the MSCP packet and ask the ctlr to start. 524 */ 525 mp->mscp_opcode = 526 (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE; 527 mp->mscp_cmdref = next; 528 mi->mi_xi[next].mxi_bp = bp; 529 mi->mi_xi[next].mxi_mp = mp; 530 mi->mi_xi[next].mxi_inuse = 1; 531 bp->b_resid = next; 532 (*mi->mi_me->me_fillin)(bp, mp); 533 (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, &mi->mi_xi[next]); 534 BUFQ_REMOVE(&mi->mi_resq, bp); 535 } 536 } 537 538 void 539 mscp_dgo(mi, mxi) 540 struct mscp_softc *mi; 541 struct mscp_xi *mxi; 542 { 543 volatile int i; 544 struct mscp *mp; 545 546 /* 547 * Fill in the MSCP packet and move the buffer to the I/O wait queue. 548 */ 549 mp = mxi->mxi_mp; 550 mp->mscp_seq.seq_buffer = mxi->mxi_dmam->dm_segs[0].ds_addr; 551 552 *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 553 i = READ_IP; 554 } 555 556 #ifdef DIAGNOSTIC 557 /* 558 * Dump the entire contents of an MSCP packet in hex. Mainly useful 559 * for debugging.... 560 */ 561 void 562 mscp_hexdump(mp) 563 struct mscp *mp; 564 { 565 long *p = (long *) mp; 566 int i = mp->mscp_msglen; 567 568 if (i > 256) /* sanity */ 569 i = 256; 570 i /= sizeof (*p); /* ASSUMES MULTIPLE OF sizeof(long) */ 571 while (--i >= 0) 572 printf("0x%x ", (int)*p++); 573 printf("\n"); 574 } 575 #endif 576 577 /* 578 * MSCP error reporting 579 */ 580 581 /* 582 * Messages for the various subcodes. 583 */ 584 static char unknown_msg[] = "unknown subcode"; 585 586 /* 587 * Subcodes for Success (0) 588 */ 589 static char *succ_msgs[] = { 590 "normal", /* 0 */ 591 "spin down ignored", /* 1 = Spin-Down Ignored */ 592 "still connected", /* 2 = Still Connected */ 593 unknown_msg, 594 "dup. unit #", /* 4 = Duplicate Unit Number */ 595 unknown_msg, 596 unknown_msg, 597 unknown_msg, 598 "already online", /* 8 = Already Online */ 599 unknown_msg, 600 unknown_msg, 601 unknown_msg, 602 unknown_msg, 603 unknown_msg, 604 unknown_msg, 605 unknown_msg, 606 "still online", /* 16 = Still Online */ 607 }; 608 609 /* 610 * Subcodes for Invalid Command (1) 611 */ 612 static char *icmd_msgs[] = { 613 "invalid msg length", /* 0 = Invalid Message Length */ 614 }; 615 616 /* 617 * Subcodes for Command Aborted (2) 618 */ 619 /* none known */ 620 621 /* 622 * Subcodes for Unit Offline (3) 623 */ 624 static char *offl_msgs[] = { 625 "unknown drive", /* 0 = Unknown, or online to other ctlr */ 626 "not mounted", /* 1 = Unmounted, or RUN/STOP at STOP */ 627 "inoperative", /* 2 = Unit Inoperative */ 628 unknown_msg, 629 "duplicate", /* 4 = Duplicate Unit Number */ 630 unknown_msg, 631 unknown_msg, 632 unknown_msg, 633 "in diagnosis", /* 8 = Disabled by FS or diagnostic */ 634 }; 635 636 /* 637 * Subcodes for Unit Available (4) 638 */ 639 /* none known */ 640 641 /* 642 * Subcodes for Media Format Error (5) 643 */ 644 static char *media_fmt_msgs[] = { 645 "fct unread - edc", /* 0 = FCT unreadable */ 646 "invalid sector header",/* 1 = Invalid Sector Header */ 647 "not 512 sectors", /* 2 = Not 512 Byte Sectors */ 648 "not formatted", /* 3 = Not Formatted */ 649 "fct ecc", /* 4 = FCT ECC */ 650 }; 651 652 /* 653 * Subcodes for Write Protected (6) 654 * N.B.: Code 6 subcodes are 7 bits higher than other subcodes 655 * (i.e., bits 12-15). 656 */ 657 static char *wrprot_msgs[] = { 658 unknown_msg, 659 "software", /* 1 = Software Write Protect */ 660 "hardware", /* 2 = Hardware Write Protect */ 661 }; 662 663 /* 664 * Subcodes for Compare Error (7) 665 */ 666 /* none known */ 667 668 /* 669 * Subcodes for Data Error (8) 670 */ 671 static char *data_msgs[] = { 672 "forced error", /* 0 = Forced Error (software) */ 673 unknown_msg, 674 "header compare", /* 2 = Header Compare Error */ 675 "sync timeout", /* 3 = Sync Timeout Error */ 676 unknown_msg, 677 unknown_msg, 678 unknown_msg, 679 "uncorrectable ecc", /* 7 = Uncorrectable ECC */ 680 "1 symbol ecc", /* 8 = 1 bit ECC */ 681 "2 symbol ecc", /* 9 = 2 bit ECC */ 682 "3 symbol ecc", /* 10 = 3 bit ECC */ 683 "4 symbol ecc", /* 11 = 4 bit ECC */ 684 "5 symbol ecc", /* 12 = 5 bit ECC */ 685 "6 symbol ecc", /* 13 = 6 bit ECC */ 686 "7 symbol ecc", /* 14 = 7 bit ECC */ 687 "8 symbol ecc", /* 15 = 8 bit ECC */ 688 }; 689 690 /* 691 * Subcodes for Host Buffer Access Error (9) 692 */ 693 static char *host_buffer_msgs[] = { 694 unknown_msg, 695 "odd xfer addr", /* 1 = Odd Transfer Address */ 696 "odd xfer count", /* 2 = Odd Transfer Count */ 697 "non-exist. memory", /* 3 = Non-Existent Memory */ 698 "memory parity", /* 4 = Memory Parity Error */ 699 }; 700 701 /* 702 * Subcodes for Controller Error (10) 703 */ 704 static char *cntlr_msgs[] = { 705 unknown_msg, 706 "serdes overrun", /* 1 = Serialiser/Deserialiser Overrun */ 707 "edc", /* 2 = Error Detection Code? */ 708 "inconsistant internal data struct",/* 3 = Internal Error */ 709 }; 710 711 /* 712 * Subcodes for Drive Error (11) 713 */ 714 static char *drive_msgs[] = { 715 unknown_msg, 716 "sdi command timeout", /* 1 = SDI Command Timeout */ 717 "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */ 718 "positioner", /* 3 = Positioner Error */ 719 "lost rd/wr ready", /* 4 = Lost R/W Ready Error */ 720 "drive clock dropout", /* 5 = Lost Drive Clock */ 721 "lost recvr ready", /* 6 = Lost Receiver Ready */ 722 "drive detected error", /* 7 = Drive Error */ 723 "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */ 724 }; 725 726 /* 727 * The following table correlates message codes with the 728 * decoding strings. 729 */ 730 struct code_decode { 731 char *cdc_msg; 732 int cdc_nsubcodes; 733 char **cdc_submsgs; 734 } code_decode[] = { 735 #define SC(m) sizeof (m) / sizeof (m[0]), m 736 {"success", SC(succ_msgs)}, 737 {"invalid command", SC(icmd_msgs)}, 738 {"command aborted", 0, 0}, 739 {"unit offline", SC(offl_msgs)}, 740 {"unit available", 0, 0}, 741 {"media format error", SC(media_fmt_msgs)}, 742 {"write protected", SC(wrprot_msgs)}, 743 {"compare error", 0, 0}, 744 {"data error", SC(data_msgs)}, 745 {"host buffer access error", SC(host_buffer_msgs)}, 746 {"controller error", SC(cntlr_msgs)}, 747 {"drive error", SC(drive_msgs)}, 748 #undef SC 749 }; 750 751 /* 752 * Print the decoded error event from an MSCP error datagram. 753 */ 754 void 755 mscp_printevent(mp) 756 struct mscp *mp; 757 { 758 int event = mp->mscp_event; 759 struct code_decode *cdc; 760 int c, sc; 761 char *cm, *scm; 762 763 /* 764 * The code is the lower six bits of the event number (aka 765 * status). If that is 6 (write protect), the subcode is in 766 * bits 12-15; otherwise, it is in bits 5-11. 767 * I WONDER WHAT THE OTHER BITS ARE FOR. IT SURE WOULD BE 768 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. 769 */ 770 c = event & M_ST_MASK; 771 sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff; 772 if (c >= sizeof code_decode / sizeof code_decode[0]) 773 cm = "- unknown code", scm = "??"; 774 else { 775 cdc = &code_decode[c]; 776 cm = cdc->cdc_msg; 777 if (sc >= cdc->cdc_nsubcodes) 778 scm = unknown_msg; 779 else 780 scm = cdc->cdc_submsgs[sc]; 781 } 782 printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc); 783 } 784 785 static char *codemsg[16] = { 786 "lbn", "code 1", "code 2", "code 3", 787 "code 4", "code 5", "rbn", "code 7", 788 "code 8", "code 9", "code 10", "code 11", 789 "code 12", "code 13", "code 14", "code 15" 790 }; 791 /* 792 * Print the code and logical block number for an error packet. 793 * THIS IS PROBABLY PECULIAR TO DISK DRIVES. IT SURE WOULD BE 794 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. 795 */ 796 int 797 mscp_decodeerror(name, mp, mi) 798 char *name; 799 struct mscp *mp; 800 struct mscp_softc *mi; 801 { 802 int issoft; 803 /* 804 * We will get three sdi errors of type 11 after autoconfig 805 * is finished; depending of searching for non-existing units. 806 * How can we avoid this??? 807 */ 808 if (((mp->mscp_event & M_ST_MASK) == 11) && (mi->mi_ierr++ < 3)) 809 return 1; 810 /* 811 * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and 812 * the logical block number. Code 0 is a regular block; code 6 813 * is a replacement block. The remaining codes are currently 814 * undefined. The code is in the upper four bits of the header 815 * (bits 0-27 are the lbn). 816 */ 817 issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT); 818 #define BADCODE(h) (codemsg[(unsigned)(h) >> 28]) 819 #define BADLBN(h) ((h) & 0xfffffff) 820 821 printf("%s: drive %d %s error datagram%s:", name, mp->mscp_unit, 822 issoft ? "soft" : "hard", 823 mp->mscp_flags & M_LF_CONT ? " (continuing)" : ""); 824 switch (mp->mscp_format & 0377) { 825 826 case M_FM_CTLRERR: /* controller error */ 827 break; 828 829 case M_FM_BUSADDR: /* host memory access error */ 830 printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr); 831 break; 832 833 case M_FM_DISKTRN: 834 printf(" unit %d: level %d retry %d, %s %d:", 835 mp->mscp_unit, 836 mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry, 837 BADCODE(mp->mscp_erd.erd_hdr), 838 (int)BADLBN(mp->mscp_erd.erd_hdr)); 839 break; 840 841 case M_FM_SDI: 842 printf(" unit %d: %s %d:", mp->mscp_unit, 843 BADCODE(mp->mscp_erd.erd_hdr), 844 (int)BADLBN(mp->mscp_erd.erd_hdr)); 845 break; 846 847 case M_FM_SMLDSK: 848 printf(" unit %d: small disk error, cyl %d:", 849 mp->mscp_unit, mp->mscp_erd.erd_sdecyl); 850 break; 851 852 case M_FM_TAPETRN: 853 printf(" unit %d: tape transfer error, grp 0x%x event 0%o:", 854 mp->mscp_unit, mp->mscp_erd.erd_sdecyl, mp->mscp_event); 855 break; 856 857 case M_FM_STIERR: 858 printf(" unit %d: STI error, event 0%o:", mp->mscp_unit, 859 mp->mscp_event); 860 break; 861 862 default: 863 printf(" unit %d: unknown error, format 0x%x:", 864 mp->mscp_unit, mp->mscp_format); 865 } 866 mscp_printevent(mp); 867 return 0; 868 #undef BADCODE 869 #undef BADLBN 870 } 871