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