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