1 /* 2 * Copyright (c) 1987 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)mscp.c 7.2 (Berkeley) 05/31/88 7 */ 8 9 /* 10 * MSCP generic driver routines 11 */ 12 13 #include "param.h" 14 #include "buf.h" 15 #include "errno.h" 16 #include "dkstat.h" 17 #include "ioctl.h" 18 #include "disklabel.h" 19 #include "syslog.h" 20 21 #include "../vaxuba/ubavar.h" 22 23 #include "mscp.h" 24 #include "mscpvar.h" 25 26 #define PCMD PSWP /* priority for command packet waits */ 27 28 /* 29 * During transfers, mapping info is saved in the buffer's b_resid. 30 */ 31 #define b_info b_resid 32 33 /* 34 * Get a command packet. Second argument is true iff we are 35 * to wait if necessary. Return NULL if none are available and 36 * we cannot wait. 37 */ 38 struct mscp * 39 mscp_getcp(mi, canwait) 40 register struct mscp_info *mi; 41 int canwait; 42 { 43 #define mri (&mi->mi_cmd) 44 register struct mscp *mp; 45 register int i; 46 int s = spl5(); 47 48 again: 49 /* 50 * Ensure that we have some command credits, and 51 * that the next command packet is free. 52 */ 53 if (mi->mi_credits <= MSCP_MINCREDITS) { 54 if (!canwait) { 55 splx(s); 56 return (NULL); 57 } 58 mi->mi_wantcredits = 1; 59 sleep((caddr_t) &mi->mi_wantcredits, PCMD); 60 goto again; 61 } 62 i = mri->mri_next; 63 if (mri->mri_desc[i] & MSCP_OWN) { 64 if (!canwait) { 65 splx(s); 66 return (NULL); 67 } 68 mi->mi_wantcmd = 1; 69 sleep((caddr_t) &mi->mi_wantcmd, PCMD); 70 goto again; 71 } 72 mi->mi_credits--; 73 mri->mri_desc[i] &= ~MSCP_INT; 74 mri->mri_next = (mri->mri_next + 1) % mri->mri_size; 75 splx(s); 76 mp = &mri->mri_ring[i]; 77 78 /* 79 * Initialise some often-zero fields. 80 * ARE THE LAST TWO NECESSARY IN GENERAL? IT SURE WOULD BE 81 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. 82 */ 83 mp->mscp_msglen = MSCP_MSGLEN; 84 mp->mscp_flags = 0; 85 mp->mscp_modifier = 0; 86 mp->mscp_seq.seq_bytecount = 0; 87 mp->mscp_seq.seq_buffer = 0; 88 mp->mscp_seq.seq_mapbase = 0; 89 /*???*/ mp->mscp_sccc.sccc_errlgfl = 0; 90 /*???*/ mp->mscp_sccc.sccc_copyspd = 0; 91 return (mp); 92 #undef mri 93 } 94 95 #ifdef AVOID_EMULEX_BUG 96 int mscp_aeb_xor = 0x8000bb80; 97 #endif 98 99 /* 100 * Do a device go. The driver calls this once it has allocated 101 * resources for the transfer. Save the resource information in 102 * bp->b_ubinfo, and finish the MSCP packet. 103 * 104 * N.B.: If we were blocked for some time, the drive could have gone 105 * off line and might still be that way. We should probably handle 106 * such a case by changing this command into an on line request and 107 * not dequeuing the transfer after all. 108 */ 109 mscp_go(mi, mp, info) 110 register struct mscp_info *mi; 111 register struct mscp *mp; 112 int info; 113 { 114 register struct buf *bp, *dp; 115 116 /* 117 * Now is also the time to move the transfer off the 118 * controller and drive queues, and shuffle the drive 119 * queue on the controller queue. The idea is to try 120 * to keep as many drives busy as possible---to deal 121 * the controller's credits out to the drives in a `fair 122 * share' arrangement. (To do this fully would be more 123 * trouble than it is worth, though.) 124 */ 125 dp = mi->mi_tab->b_actf; 126 bp = dp->b_actf; 127 dp->b_actf = bp->av_forw; /* transfer off drive queue */ 128 mi->mi_tab->b_actf = dp->b_forw;/* drive off ctlr queue */ 129 APPEND(dp, mi->mi_tab, b_forw); /* then back again */ 130 131 /* 132 * Move the buffer to the I/O wait queue. 133 */ 134 bp->av_back = mi->mi_wtab.av_back; 135 bp->av_forw = &mi->mi_wtab; 136 mi->mi_wtab.av_back->av_forw = bp; 137 mi->mi_wtab.av_back = bp; 138 139 /* 140 * Save the mapping info, finish the command packet, and give 141 * it to the device. The device's dgo routine should then 142 * initiate polling. 143 */ 144 bp->b_info = info; 145 #ifdef AVOID_EMULEX_BUG 146 /* 147 * The Emulex SC41/MS will occasionally zero the lower half word 148 * of the command reference number. The upper half word remains 149 * intact. To keep running, we convert the buffer address into 150 * a small but nonzero integer that is unique over all pending 151 * transfers, and store that value in the upper half word. To 152 * catch occurrances of the bug (so that we can gripe to Emulex), 153 * we also put a nonzero value in the lower word. 154 */ 155 { 156 register u_int i = mi->mi_nextbp; 157 158 do { /* find a free value */ 159 if (mi->mi_bp[i] == 0) 160 goto found; 161 i = (i + 1) % AEB_MAX_BP; 162 } while (i != mi->mi_nextbp); 163 panic("mscp_go: AEB_MAX_BP too small"); 164 found: 165 mi->mi_bp[i++] = bp; 166 mi->mi_nextbp = i % AEB_MAX_BP; 167 mp->mscp_cmdref = (i << 16) ^ mscp_aeb_xor; 168 } 169 #else 170 mp->mscp_cmdref = (long) bp; 171 #endif 172 *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 173 } 174 175 /* 176 * Handle a response ring transition. 177 */ 178 mscp_dorsp(mi) 179 register struct mscp_info *mi; 180 { 181 register struct uba_device *ui; 182 register struct buf *bp; 183 register struct mscp *mp; 184 register int nextrsp; 185 struct mscp_driver *md = mi->mi_md; 186 char *ctlrname, *drivename; 187 int st, error, info; 188 189 ctlrname = md->md_mname; 190 drivename = md->md_dname; 191 nextrsp = mi->mi_rsp.mri_next; 192 loop: 193 if (mi->mi_rsp.mri_desc[nextrsp] & MSCP_OWN) { 194 /* 195 * No more responses. Remember the next expected 196 * response index. Check to see if we have some 197 * credits back, and wake up sleepers if so. 198 */ 199 mi->mi_rsp.mri_next = nextrsp; 200 if (mi->mi_wantcredits && mi->mi_credits > MSCP_MINCREDITS) { 201 mi->mi_wantcredits = 0; 202 wakeup((caddr_t) &mi->mi_wantcredits); 203 } 204 return; 205 } 206 207 /* 208 * Found a response. Update credit information. If there is 209 * nothing else to do, jump to `done' to get the next response. 210 */ 211 mp = &mi->mi_rsp.mri_ring[nextrsp]; 212 mi->mi_credits += MSCP_CREDITS(mp->mscp_msgtc); 213 switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { 214 215 case MSCPT_SEQ: 216 break; 217 218 case MSCPT_DATAGRAM: 219 (*md->md_dgram)(mi, mp); 220 goto done; 221 222 case MSCPT_CREDITS: 223 goto done; 224 225 case MSCPT_MAINTENANCE: 226 default: 227 printf("%s%d: unit %d: unknown message type 0x%x ignored\n", 228 ctlrname, mi->mi_ctlr, mp->mscp_unit, 229 MSCP_MSGTYPE(mp->mscp_msgtc)); 230 goto done; 231 } 232 233 /* 234 * Controllers are allowed to interrupt as any drive, so we 235 * must check the command before checking for a drive. 236 */ 237 if (mp->mscp_opcode == (M_OP_SETCTLRC | M_OP_END)) { 238 (*md->md_ctlrdone)(mi, mp); 239 goto done; 240 } 241 242 /* 243 * Find the drive info. If there is none, and this is an 244 * available attention response, try configuring a new drive. 245 */ 246 if (mp->mscp_unit > md->md_ndpc) { 247 printf("%s%d: unit %d out of range\n", 248 ctlrname, mi->mi_ctlr, mp->mscp_unit); 249 goto done; 250 } 251 if ((ui = mi->mi_ip[mp->mscp_unit]) == NULL) { 252 if ((*md->md_unconf)(mi, mp) != MSCP_DONE) { 253 printf("%s%d: unit %d not configured, ", 254 ctlrname, mi->mi_ctlr, mp->mscp_unit); 255 if (mp->mscp_opcode == M_OP_AVAILATTN) 256 printf("available attn"); 257 else 258 printf("stray response op 0x%x status 0x%x", 259 mp->mscp_opcode, mp->mscp_status); 260 printf(" ignored\n"); 261 } 262 goto done; 263 } 264 265 /* 266 * Handle individual responses. 267 */ 268 st = mp->mscp_status & M_ST_MASK; 269 error = 0; 270 switch (mp->mscp_opcode) { 271 272 case M_OP_END: 273 /* 274 * The controller presents a bogus END packet when 275 * a read/write command is given with an illegal 276 * block number. This is contrary to the MSCP 277 * specification (ENDs are to be given only for 278 * invalid commands), but that is the way of it. 279 */ 280 if (st == M_ST_INVALCMD && mp->mscp_cmdref != 0) { 281 printf("%s%d: bad lbn (%d)?\n", drivename, 282 ui->ui_unit, mp->mscp_seq.seq_lbn); 283 error = EIO; 284 goto rwend; 285 } 286 goto unknown; 287 288 case M_OP_ONLINE | M_OP_END: 289 /* 290 * Finished an ON LINE request. Call the driver to 291 * find out whether it succeeded. If so, mark it on 292 * line. 293 */ 294 if (ui->ui_flags & UNIT_ONLINE) { 295 printf("%s%d: duplicate ONLINE ignored\n", 296 drivename, ui->ui_unit); 297 break; 298 } 299 if ((*md->md_online)(ui, mp) == MSCP_DONE) 300 ui->ui_flags |= UNIT_ONLINE; 301 break; 302 303 case M_OP_GETUNITST | M_OP_END: 304 /* 305 * Got unit status. Call the driver to find out 306 * whether it succeeded, and if so, mark it. 307 */ 308 if ((*md->md_gotstatus)(ui, mp) == MSCP_DONE) 309 ui->ui_flags |= UNIT_HAVESTATUS; 310 break; 311 312 case M_OP_AVAILATTN: 313 /* 314 * The drive went offline and we did not notice. 315 * Mark it off line now, to force an on line request 316 * next, so we can make sure it is still the same 317 * drive. 318 * 319 * IF THE UDA DRIVER HAS A COMMAND AWAITING UNIBUS 320 * RESOURCES, THAT COMMAND MAY GO OUT BEFORE THE ON 321 * LINE. IS IT WORTH FIXING?? 322 */ 323 ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS); 324 #ifdef notyet 325 (*md->md_offline)(ui, mp); 326 #endif 327 break; 328 329 case M_OP_READ | M_OP_END: 330 case M_OP_WRITE | M_OP_END: 331 /* 332 * A transfer finished. Get the buffer, and release its 333 * map registers via ubadone(). If the command finished 334 * with an off line or available status, the drive went 335 * off line (the idiot controller does not tell us until 336 * it comes back *on* line, or until we try to use it). 337 */ 338 if (mp->mscp_cmdref == 0) { 339 /* 340 * No buffer means there is a bug somewhere! 341 */ 342 printf("%s%d: io done, but no buffer?\n", 343 drivename, ui->ui_unit); 344 mscp_hexdump(mp); 345 break; 346 } 347 348 rwend: 349 #ifdef AVOID_EMULEX_BUG 350 { 351 register u_short *p = (u_short *) &mp->mscp_cmdref; 352 353 /* 354 * Note any errors on the part of the controller. 355 * The lower word should be zero after exclusive 356 * or'ing with mscp_aeb_xor, and the upper should 357 * then be in the range [1..AEB_MAX_BP]. 358 */ 359 mp->mscp_cmdref ^= mscp_aeb_xor; 360 p[1]--; 361 if (p[1] >= AEB_MAX_BP) 362 panic("unrecoverable Emulex screwup"); 363 if (p[0] == 0) 364 mi->mi_ok++; 365 else { 366 /* 367 * Calculate the expected response, 368 * assuming p[1] is correct. The 369 * actual response is then the expected 370 * response xor p[0]. 371 */ 372 int sb = ((p[1] + 1) << 16) ^ mscp_aeb_xor; 373 374 log(LOG_WARNING, "\ 375 Emulex SC41/MS screwup: %s%d, got %d correct, then changed 0x%x to 0x%x\n", 376 ctlrname, mi->mi_ctlr, 377 mi->mi_ok, sb, sb ^ p[0]); 378 mi->mi_ok = 0; 379 } 380 /* convert index back to buffer, and mark free */ 381 bp = mi->mi_bp[p[1]]; 382 mi->mi_bp[p[1]] = 0; 383 } 384 #else 385 bp = (struct buf *) mp->mscp_cmdref; 386 #ifdef MSCP_PARANOIA 387 { 388 register struct buf *q = mi->mi_wtab.av_forw; 389 390 /* 391 * Ensure that this response corresponds to 392 * some outstanding request. If not, ignore 393 * it entirely. This will likely cause a 394 * Unibus reset soon, after which the controller 395 * just might behave. 396 */ 397 while (q != bp && q != &mi->mi_wtab) 398 q = q->av_forw; 399 if (q != bp) { 400 printf("%s%d: bad response packet ignored\n", 401 ctlrname, mi->mi_ctlr); 402 mscp_hexdump(mp); 403 goto out; 404 } 405 } 406 #endif MSCP_PARANOIA 407 #endif AVOID_EMULEX_BUG 408 409 /* 410 * Mark any error-due-to-bad-LBN (via `goto rwend'). 411 * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE 412 * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. 413 */ 414 if (error) { 415 bp->b_flags |= B_ERROR; 416 bp->b_error = error; 417 } 418 if (st == M_ST_OFFLINE || st == M_ST_AVAILABLE) { 419 ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS); 420 #ifdef notyet 421 (*md->md_offline)(ui, mp); 422 #endif 423 } 424 425 /* 426 * Unlink the transfer from the wait queue mi_wtab. 427 * If there are no more transfers on the drive queue 428 * for this drive, and it is a profiled disk, turn 429 * off its busy bit. 430 */ 431 bp->av_back->av_forw = bp->av_forw; 432 bp->av_forw->av_back = bp->av_back; 433 if (ui->ui_dk >= 0 && md->md_utab[ui->ui_unit].b_forw == NULL) 434 dk_busy &= ~(1 << ui->ui_dk); 435 436 /* 437 * If the transfer has something to do with bad 438 * block forwarding, let the driver handle the 439 * rest. 440 */ 441 if ((bp->b_flags & B_BAD) != 0 && md->md_bb != NULL) { 442 (*md->md_bb)(ui, mp, bp); 443 goto out; 444 } 445 446 /* 447 * If the transfer failed, give the driver a crack 448 * at fixing things up. 449 */ 450 if (st != M_ST_SUCCESS) { 451 switch ((*md->md_ioerr)(ui, mp, bp)) { 452 453 case MSCP_DONE: /* fixed */ 454 break; 455 456 case MSCP_RESTARTED: /* still working on it */ 457 goto out; 458 459 case MSCP_FAILED: /* no luck */ 460 diskerr(bp, drivename, "hard error", 461 LOG_PRINTF, -1, md->md_lab ? 462 &md->md_lab[ui->ui_unit] : md->md_lab); 463 mscp_printevent(mp); 464 bp->b_flags |= B_ERROR; 465 bp->b_error = EIO; 466 break; 467 } 468 } 469 470 /* 471 * Set the residual count and mark the transfer as 472 * done. If the I/O wait queue is now empty, release 473 * the shared BDP, if any. 474 */ 475 info = bp->b_info; /* we are about to clobber it */ 476 bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount; 477 (*md->md_iodone)(mi, bp, info); 478 out: 479 break; 480 481 case M_OP_REPLACE | M_OP_END: 482 /* 483 * A replace operation finished. Just let the driver 484 * handle it (if it does replaces). 485 */ 486 if (md->md_replace == NULL) 487 printf("%s%d: bogus REPLACE end\n", 488 drivename, ui->ui_unit); 489 else 490 (*md->md_replace)(ui, mp); 491 break; 492 493 default: 494 /* 495 * If it is not one of the above, we cannot handle it. 496 * (And we should not have received it, for that matter.) 497 */ 498 unknown: 499 printf("%s%d: unknown opcode 0x%x status 0x%x ignored\n", 500 mi->mi_md->md_dname, ui->ui_unit, 501 mp->mscp_opcode, mp->mscp_status); 502 mscp_hexdump(mp); 503 break; 504 } 505 506 /* 507 * If the drive needs to be put back in the controller queue, 508 * do that now. (`bp' below ought to be `dp', but they are all 509 * struct buf *.) Note that b_active was cleared in the driver; 510 * we presume that there is something to be done, hence reassert it. 511 */ 512 if (ui->ui_flags & UNIT_REQUEUE) { 513 bp = &md->md_utab[ui->ui_unit]; 514 if (bp->b_active) panic("mscp_dorsp requeue"); 515 APPEND(bp, mi->mi_tab, b_forw); 516 bp->b_active = 1; 517 ui->ui_flags &= ~UNIT_REQUEUE; 518 } 519 520 done: 521 /* 522 * Give back the response packet, and take a look at the next. 523 */ 524 mp->mscp_msglen = MSCP_MSGLEN; 525 mi->mi_rsp.mri_desc[nextrsp] |= MSCP_OWN; 526 nextrsp = (nextrsp + 1) % mi->mi_rsp.mri_size; 527 goto loop; 528 } 529 530 /* 531 * Dump the entire contents of an MSCP packet in hex. Mainly useful 532 * for debugging.... 533 */ 534 mscp_hexdump(mp) 535 register struct mscp *mp; 536 { 537 register long *p = (long *) mp; 538 register int i = mp->mscp_msglen; 539 540 if (i > 256) /* sanity */ 541 i = 256; 542 i /= sizeof (*p); /* ASSUMES MULTIPLE OF sizeof(long) */ 543 while (--i >= 0) 544 printf("0x%x ", *p++); 545 printf("\n"); 546 } 547 548 /* 549 * Requeue outstanding transfers, e.g., after bus reset. 550 * Also requeue any drives that have on line or unit status 551 * info pending. 552 */ 553 mscp_requeue(mi) 554 struct mscp_info *mi; 555 { 556 register struct uba_device *ui; 557 register struct mscp_driver *md = mi->mi_md; 558 register struct buf *bp, *dp; 559 register int unit; 560 struct buf *nextbp; 561 562 /* 563 * Clear the controller chain. Mark everything un-busy; we 564 * will soon fix any that are in fact busy. 565 */ 566 mi->mi_tab->b_actf = NULL; 567 mi->mi_tab->b_active = 0; 568 for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { 569 ui = md->md_dinfo[unit]; 570 if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) 571 continue; /* not ours */ 572 dp->b_forw = NULL; 573 dp->b_active = 0; 574 } 575 576 /* 577 * Scan the wait queue, linking buffers onto drive queues. 578 * Note that these must be put at the front of the drive queue, 579 * lest we reorder I/O operations. 580 */ 581 for (bp = mi->mi_wtab.av_back; bp != &mi->mi_wtab; bp = nextbp) { 582 nextbp = bp->av_back; 583 dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift]; 584 bp->av_forw = dp->b_actf; 585 if (dp->b_actf == NULL) 586 dp->b_actl = bp; 587 dp->b_actf = bp; 588 } 589 mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab; 590 591 /* 592 * Scan for drives waiting for on line or status responses, 593 * and for drives with pending transfers. Put these on the 594 * controller queue, and mark the controller busy. 595 */ 596 for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { 597 ui = md->md_dinfo[unit]; 598 if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) 599 continue; 600 ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE); 601 if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL) 602 continue; 603 ui->ui_flags &= ~UNIT_REQUEUE; 604 APPEND(dp, mi->mi_tab, b_forw); 605 dp->b_active = 1; 606 mi->mi_tab->b_active = 1; 607 } 608 609 #ifdef AVOID_EMULEX_BUG 610 /* 611 * ... and clear the index-to-buffer table. 612 */ 613 for (unit = 0; unit < AEB_MAX_BP; unit++) 614 mi->mi_bp[unit] = 0; 615 #endif 616 } 617 618 619 /* 620 * MSCP error reporting 621 */ 622 623 /* 624 * Messages for the various subcodes. 625 */ 626 static char unknown_msg[] = "unknown subcode"; 627 628 /* 629 * Subcodes for Success (0) 630 */ 631 static char *succ_msgs[] = { 632 "normal", /* 0 */ 633 "spin down ignored", /* 1 = Spin-Down Ignored */ 634 "still connected", /* 2 = Still Connected */ 635 unknown_msg, 636 "dup. unit #", /* 4 = Duplicate Unit Number */ 637 unknown_msg, 638 unknown_msg, 639 unknown_msg, 640 "already online", /* 8 = Already Online */ 641 unknown_msg, 642 unknown_msg, 643 unknown_msg, 644 unknown_msg, 645 unknown_msg, 646 unknown_msg, 647 unknown_msg, 648 "still online", /* 16 = Still Online */ 649 }; 650 651 /* 652 * Subcodes for Invalid Command (1) 653 */ 654 static char *icmd_msgs[] = { 655 "invalid msg length", /* 0 = Invalid Message Length */ 656 }; 657 658 /* 659 * Subcodes for Command Aborted (2) 660 */ 661 /* none known */ 662 663 /* 664 * Subcodes for Unit Offline (3) 665 */ 666 static char *offl_msgs[] = { 667 "unknown drive", /* 0 = Unknown, or online to other ctlr */ 668 "not mounted", /* 1 = Unmounted, or RUN/STOP at STOP */ 669 "inoperative", /* 2 = Unit Inoperative */ 670 unknown_msg, 671 "duplicate", /* 4 = Duplicate Unit Number */ 672 unknown_msg, 673 unknown_msg, 674 unknown_msg, 675 "in diagnosis", /* 8 = Disabled by FS or diagnostic */ 676 }; 677 678 /* 679 * Subcodes for Unit Available (4) 680 */ 681 /* none known */ 682 683 /* 684 * Subcodes for Media Format Error (5) 685 */ 686 static char *media_fmt_msgs[] = { 687 "fct unread - edc", /* 0 = FCT unreadable */ 688 "invalid sector header",/* 1 = Invalid Sector Header */ 689 "not 512 sectors", /* 2 = Not 512 Byte Sectors */ 690 "not formatted", /* 3 = Not Formatted */ 691 "fct ecc", /* 4 = FCT ECC */ 692 }; 693 694 /* 695 * Subcodes for Write Protected (6) 696 * N.B.: Code 6 subcodes are 7 bits higher than other subcodes 697 * (i.e., bits 12-15). 698 */ 699 static char *wrprot_msgs[] = { 700 unknown_msg, 701 "software", /* 1 = Software Write Protect */ 702 "hardware", /* 2 = Hardware Write Protect */ 703 }; 704 705 /* 706 * Subcodes for Compare Error (7) 707 */ 708 /* none known */ 709 710 /* 711 * Subcodes for Data Error (8) 712 */ 713 static char *data_msgs[] = { 714 "forced error", /* 0 = Forced Error (software) */ 715 unknown_msg, 716 "header compare", /* 2 = Header Compare Error */ 717 "sync timeout", /* 3 = Sync Timeout Error */ 718 unknown_msg, 719 unknown_msg, 720 unknown_msg, 721 "uncorrectable ecc", /* 7 = Uncorrectable ECC */ 722 "1 symbol ecc", /* 8 = 1 bit ECC */ 723 "2 symbol ecc", /* 9 = 2 bit ECC */ 724 "3 symbol ecc", /* 10 = 3 bit ECC */ 725 "4 symbol ecc", /* 11 = 4 bit ECC */ 726 "5 symbol ecc", /* 12 = 5 bit ECC */ 727 "6 symbol ecc", /* 13 = 6 bit ECC */ 728 "7 symbol ecc", /* 14 = 7 bit ECC */ 729 "8 symbol ecc", /* 15 = 8 bit ECC */ 730 }; 731 732 /* 733 * Subcodes for Host Buffer Access Error (9) 734 */ 735 static char *host_buffer_msgs[] = { 736 unknown_msg, 737 "odd xfer addr", /* 1 = Odd Transfer Address */ 738 "odd xfer count", /* 2 = Odd Transfer Count */ 739 "non-exist. memory", /* 3 = Non-Existent Memory */ 740 "memory parity", /* 4 = Memory Parity Error */ 741 }; 742 743 /* 744 * Subcodes for Controller Error (10) 745 */ 746 static char *cntlr_msgs[] = { 747 unknown_msg, 748 "serdes overrun", /* 1 = Serialiser/Deserialiser Overrun */ 749 "edc", /* 2 = Error Detection Code? */ 750 "inconsistant internal data struct",/* 3 = Internal Error */ 751 }; 752 753 /* 754 * Subcodes for Drive Error (11) 755 */ 756 static char *drive_msgs[] = { 757 unknown_msg, 758 "sdi command timeout", /* 1 = SDI Command Timeout */ 759 "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */ 760 "positioner", /* 3 = Positioner Error */ 761 "lost rd/wr ready", /* 4 = Lost R/W Ready Error */ 762 "drive clock dropout", /* 5 = Lost Drive Clock */ 763 "lost recvr ready", /* 6 = Lost Receiver Ready */ 764 "drive detected error", /* 7 = Drive Error */ 765 "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */ 766 }; 767 768 /* 769 * The following table correlates message codes with the 770 * decoding strings. 771 */ 772 struct code_decode { 773 char *cdc_msg; 774 int cdc_nsubcodes; 775 char **cdc_submsgs; 776 } code_decode[] = { 777 #define SC(m) sizeof (m) / sizeof (m[0]), m 778 "success", SC(succ_msgs), 779 "invalid command", SC(icmd_msgs), 780 "command aborted", 0, 0, 781 "unit offline", SC(offl_msgs), 782 "unit available", 0, 0, 783 "media format error", SC(media_fmt_msgs), 784 "write protected", SC(wrprot_msgs), 785 "compare error", 0, 0, 786 "data error", SC(data_msgs), 787 "host buffer access error", SC(host_buffer_msgs), 788 "controller error", SC(cntlr_msgs), 789 "drive error", SC(drive_msgs), 790 #undef SC 791 }; 792 793 /* 794 * Print the decoded error event from an MSCP error datagram. 795 */ 796 mscp_printevent(mp) 797 struct mscp *mp; 798 { 799 register int event = mp->mscp_event; 800 register struct code_decode *cdc; 801 int c, sc; 802 char *cm, *scm; 803 804 /* 805 * The code is the lower six bits of the event number (aka 806 * status). If that is 6 (write protect), the subcode is in 807 * bits 12-15; otherwise, it is in bits 5-11. 808 * I WONDER WHAT THE OTHER BITS ARE FOR. IT SURE WOULD BE 809 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. 810 */ 811 c = event & M_ST_MASK; 812 sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff; 813 if (c >= sizeof code_decode / sizeof code_decode[0]) 814 cm = "- unknown code", scm = "??"; 815 else { 816 cdc = &code_decode[c]; 817 cm = cdc->cdc_msg; 818 if (sc >= cdc->cdc_nsubcodes) 819 scm = unknown_msg; 820 else 821 scm = cdc->cdc_submsgs[sc]; 822 } 823 printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc); 824 } 825 826 /* 827 * Print the code and logical block number for an error packet. 828 * THIS IS PROBABLY PECULIAR TO DISK DRIVES. IT SURE WOULD BE 829 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. 830 */ 831 mscp_decodeerror(name, ctlr, mp) 832 char *name; 833 int ctlr; 834 register struct mscp *mp; 835 { 836 /* 837 * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and 838 * the logical block number. Code 0 is a regular block; code 6 839 * is a replacement block. The remaining codes are currently 840 * undefined. The code is in the upper four bits of the header 841 * (bits 0-27 are the lbn). 842 */ 843 int issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT); 844 static char *codemsg[16] = { 845 "lbn", "code 1", "code 2", "code 3", 846 "code 4", "code 5", "rbn", "code 7", 847 "code 8", "code 9", "code 10", "code 11", 848 "code 12", "code 13", "code 14", "code 15" 849 }; 850 #define BADCODE(h) (codemsg[(unsigned)(h) >> 28]) 851 #define BADLBN(h) ((h) & 0xfffffff) 852 853 printf("%s%d: %s error datagram%s:", name, ctlr, 854 issoft ? "soft" : "hard", 855 mp->mscp_flags & M_LF_CONT ? " (continuing)" : ""); 856 switch (mp->mscp_format & 0377) { 857 858 case M_FM_CTLRERR: /* controller error */ 859 break; 860 861 case M_FM_BUSADDR: /* host memory access error */ 862 printf(" memory addr 0x%x:", mp->mscp_erd.erd_busaddr); 863 break; 864 865 case M_FM_DISKTRN: 866 printf(" unit %d: level %d retry %d, %s %d:", 867 mp->mscp_unit, 868 mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry, 869 BADCODE(mp->mscp_erd.erd_hdr), 870 BADLBN(mp->mscp_erd.erd_hdr)); 871 break; 872 873 case M_FM_SDI: 874 printf(" unit %d: %s %d:", mp->mscp_unit, 875 BADCODE(mp->mscp_erd.erd_hdr), 876 BADLBN(mp->mscp_erd.erd_hdr)); 877 break; 878 879 case M_FM_SMLDSK: 880 printf(" unit %d: small disk error, cyl %d:", 881 mp->mscp_unit, mp->mscp_erd.erd_sdecyl); 882 break; 883 884 default: 885 printf(" unit %d: unknown error, format 0x%x:", 886 mp->mscp_unit, mp->mscp_format); 887 } 888 mscp_printevent(mp); 889 #undef BADCODE 890 #undef BADLBN 891 } 892