|
|
1.1 ! root 1: #include "ra.h" ! 2: #if NUDA > 0 ! 3: /* ! 4: * UDA50/RAxx disk device driver ! 5: * this should really be two drivers! ! 6: * can only handle unit numbers less than 8 for now ! 7: */ ! 8: ! 9: #include "../h/param.h" ! 10: #include "../h/systm.h" ! 11: #include "../h/buf.h" ! 12: #include "../h/conf.h" ! 13: #include "../h/dir.h" ! 14: #include "../h/user.h" ! 15: #include "../h/pte.h" ! 16: #include "../h/map.h" ! 17: #include "../h/vm.h" ! 18: #include "../h/ubareg.h" ! 19: #include "../h/ubavar.h" ! 20: #include "../h/dk.h" ! 21: #include "../h/cpu.h" ! 22: #include "../h/cmap.h" ! 23: #include "../h/trace.h" ! 24: #include "../h/file.h" ! 25: ! 26: int udadebug = 0; ! 27: #define printd if(udadebug&1)printf ! 28: ! 29: /* ! 30: * Parameters for the communications area ! 31: */ ! 32: ! 33: #define NRSPL2 5 ! 34: #define NCMDL2 5 ! 35: #define NRSP (1<<NRSPL2) ! 36: #define NCMD (1<<NCMDL2) ! 37: ! 38: #include "../h/udareg.h" ! 39: #include "../h/udaioc.h" ! 40: #include "../h/mscp.h" ! 41: ! 42: #define SECTOR 512 /* size of an MSCP logical block */ ! 43: #define MAXUNIT 8 /* largest unit number we can handle */ ! 44: ! 45: struct uda_softc { ! 46: short sc_state; /* state of controller */ ! 47: short sc_flags; ! 48: struct udadevice *sc_addr; ! 49: int sc_ubainfo; /* Unibus mapping info */ ! 50: struct uda *sc_uda; /* Unibus address of uda struct */ ! 51: int sc_ivec; /* interrupt vector address */ ! 52: short sc_credits; /* transfer credits */ ! 53: short sc_lastcmd; /* pointer into command ring */ ! 54: short sc_lastrsp; /* pointer into response ring */ ! 55: short sc_ctime; /* controller timeout interval */ ! 56: } uda_softc[NUDA]; ! 57: ! 58: /* ! 59: * sc_flags ! 60: */ ! 61: ! 62: #define SCCRED 01 /* someone waiting for credits */ ! 63: #define SCMAP 02 /* control structure is mapped */ ! 64: #define SCFIRST 04 /* allow packets without credit */ ! 65: ! 66: /* ! 67: * Controller states ! 68: */ ! 69: #define S_IDLE 0 /* hasn't been initialized */ ! 70: #define S_STEP1 1 /* doing step 1 init */ ! 71: #define S_STEP2 2 /* doing step 2 init */ ! 72: #define S_STEP3 3 /* doing step 3 init */ ! 73: #define S_SCHAR 4 /* doing "set controller characteristics" */ ! 74: #define S_RUN 5 /* running */ ! 75: ! 76: /* ! 77: * communication area, per controller ! 78: * mapped into UNIBUS space ! 79: */ ! 80: ! 81: struct uda { ! 82: struct udaca uda_ca; /* communications area */ ! 83: struct mscp uda_rsp[NRSP]; /* response packets */ ! 84: struct mscp uda_cmd[NCMD]; /* command packets */ ! 85: } uda[NUDA]; ! 86: ! 87: /* ! 88: * a word to the wise: ! 89: * part of the minor device number selects a drive number ! 90: * this is not necessarily the same as the physical unit number ! 91: * in an attempt to clear this up, the former is referred to ! 92: * as the `dev unit,' the latter as the `real unit' ! 93: * most places use the real unit ! 94: */ ! 95: #define NPART 8 /* 8 disk partitions */ ! 96: #define PART(x) ((x) & 07) /* minor device -> partition */ ! 97: #define DUNIT(x) (((x) >> 3) & 07) /* minor device -> dev unit */ ! 98: ! 99: #define HUGE 0x7fffffff ! 100: ! 101: struct size { ! 102: daddr_t nblocks; ! 103: daddr_t blkoff; ! 104: } ra_sizes[NPART] ={ ! 105: 10240, 0, /* like emulex */ ! 106: 20480, 10240, /* ra81 has 891072 blocks */ ! 107: 249848, 30720, ! 108: 249848, 280568, ! 109: 249848, 530416, ! 110: 110808, 780264, ! 111: 749544, 30720, /* slices 2,3,4 */ ! 112: HUGE, 0, /* whole drive */ ! 113: }; ! 114: ! 115: /* device flags (ui_flags) */ ! 116: #define DUP 1 /* up */ ! 117: #define DGTUNIT 2 /* needs GTUNIT */ ! 118: ! 119: #define ui_offl ui_type ! 120: #define MAXOFFL 10 ! 121: ! 122: /* per unit stuff */ ! 123: struct ud_unit ud_units[MAXUNIT]; /* per real unit */ ! 124: int ud_open[NRA]; /* per dev unit */ ! 125: ! 126: char ud_rflags; /* replacement flags. should be per controller */ ! 127: #define RPLOCK 01 /* someone is doing a replacement */ ! 128: #define RPWANT 02 /* somebody else wants to */ ! 129: #define RPDONE 04 /* replacement finished */ ! 130: ! 131: int ud_rret; /* status returned from replacement */ ! 132: ! 133: int udprobe(), udslave(), udattach(), udintr(); ! 134: struct mscp *udgetcp(); ! 135: struct uba_ctlr *udminfo[NUDA]; ! 136: struct uba_device *uddinfo[NRA]; /* per dev unit */ ! 137: struct uba_device *udip[NUDA][MAXUNIT]; /* (ctlr, realunit) -> device */ ! 138: ! 139: u_short udstd[] = { 0777550, 0 }; ! 140: struct uba_driver udadriver = ! 141: { udprobe, udslave, udattach, 0, udstd, "ra", uddinfo, "uda", udminfo, 0 }; ! 142: struct buf rudbuf[NRA]; /* raw io buffer header */ ! 143: struct buf rctbuf[NRA]; /* buffer for RCT io */ ! 144: struct buf udutab[NRA]; /* drive queues */ ! 145: struct buf udwtab[NUDA]; /* I/O wait queue, per controller */ ! 146: ! 147: #define b_qsize b_resid /* queue size per drive, in udutab */ ! 148: #define b_ubinfo b_resid /* Unibus mapping info, per buffer */ ! 149: ! 150: udprobe(reg, ctlr) ! 151: caddr_t reg; ! 152: int ctlr; ! 153: { register int br, cvec; ! 154: register struct uda_softc *sc = &uda_softc[ctlr]; ! 155: ! 156: #ifdef lint ! 157: br = 0; cvec = br; br = cvec; reg = reg; ! 158: udread(0); udwrite(0); udreset(0); udintr(0); ! 159: #endif ! 160: /* SHOULD CHECK THAT IT REALLY IS A UDA */ ! 161: br = 0x15; ! 162: cvec = sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); ! 163: sc->sc_addr = (struct udadevice *)reg; ! 164: return(1); ! 165: } ! 166: ! 167: udslave(ui, reg) ! 168: struct uba_device *ui; ! 169: caddr_t reg; ! 170: { ! 171: /* ! 172: * TOO HARD TO FIND OUT IF DISK IS THERE UNTIL ! 173: * INITIALIZED. WE'LL FIND OUT WHEN WE FIRST ! 174: * TRY TO ACCESS IT. ! 175: */ ! 176: #ifdef lint ! 177: ui = ui; reg = reg; ! 178: #endif ! 179: return(1); ! 180: } ! 181: ! 182: udattach(ui) ! 183: register struct uba_device *ui; ! 184: { ! 185: ! 186: if (ui->ui_dk > 0) ! 187: dk_mspw[ui->ui_dk] = 1.0 / (60 * 51 * 256); /* approx */ ! 188: ui->ui_flags = 0; ! 189: udip[ui->ui_ctlr][ui->ui_slave] = ui; ! 190: printf("\n"); /* we're expected to babble */ ! 191: ud_units[ui->ui_unit].radsize = (daddr_t)HUGE; ! 192: } ! 193: ! 194: udopen(dev) ! 195: dev_t dev; ! 196: { ! 197: register int unit; ! 198: ! 199: unit = DUNIT(minor(dev)); ! 200: if (unit >= NRA) { ! 201: u.u_error = ENXIO; ! 202: return; ! 203: } ! 204: ud_open[unit] |= 1 << PART(minor(dev)); ! 205: } ! 206: ! 207: udclose(dev) ! 208: dev_t dev; ! 209: { ! 210: register int unit; ! 211: register struct mscp *mp; ! 212: struct uba_device *ui; ! 213: struct uba_ctlr *um; ! 214: struct uda_softc *sc; ! 215: ! 216: unit = DUNIT(minor(dev)); ! 217: ud_open[unit] &=~ (1 << PART(minor(dev))); ! 218: if (ud_open[unit]) ! 219: return; ! 220: /* ! 221: * last close on this drive ! 222: * put it offline ! 223: */ ! 224: ui = uddinfo[unit]; ! 225: if (ui->ui_flags == 0) ! 226: return; ! 227: um = ui->ui_mi; ! 228: sc = &uda_softc[um->um_ctlr]; ! 229: if (udcredit(sc, 1) == 0) ! 230: return; ! 231: if ((mp = udgetcp(um)) == NULL) ! 232: return; ! 233: mp->mscp_opcode = M_OP_AVAIL; ! 234: mp->mscp_unit = ui->ui_slave; ! 235: mp->mscp_modifier = 0; ! 236: mp->mscp_cmdref = (long)mp; /* any old number */ ! 237: udsend(mp, sc); ! 238: ui->ui_flags = 0; /* drive is offline now */ ! 239: } ! 240: ! 241: /* ! 242: * Initialize a UDA. Set up UBA mapping registers, ! 243: * initialize data structures, and perform hardware ! 244: * initialization sequence. ! 245: */ ! 246: ! 247: udinit(d) ! 248: { ! 249: register struct uda_softc *sc; ! 250: register struct uba_ctlr *um; ! 251: register struct buf *bp; ! 252: register struct mscp *mp; ! 253: register int i; ! 254: int s; ! 255: ! 256: sc = &uda_softc[d]; ! 257: um = udminfo[d]; ! 258: um->um_tab.b_active++; ! 259: if ((sc->sc_flags & SCMAP) == 0) { ! 260: sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)&uda[d], ! 261: sizeof (struct uda), 0); ! 262: sc->sc_uda = (struct uda *)(sc->sc_ubainfo & 0x3ffff); ! 263: sc->sc_flags |= SCMAP; ! 264: } ! 265: for (i = 0; i < NRA; i++) ! 266: if (uddinfo[i] && uddinfo[i]->ui_mi == um) ! 267: uddinfo[i]->ui_flags = 0; ! 268: if (udhwinit(d) == 0) ! 269: return; ! 270: sc->sc_state = S_SCHAR; ! 271: bp = &udwtab[d]; ! 272: bp->av_forw = bp->av_back = bp; ! 273: sc->sc_lastcmd = 0; ! 274: sc->sc_lastrsp = 0; ! 275: s = spl5(); ! 276: if ((mp = udgetcp(um)) == NULL) ! 277: panic("uda: no packets"); ! 278: mp->mscp_opcode = M_OP_STCON; ! 279: mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; ! 280: sc->sc_flags |= SCFIRST; ! 281: udsend(mp, sc); ! 282: splx(s); ! 283: return; ! 284: } ! 285: ! 286: /* ! 287: * hardware initialization handshake ! 288: * for simplicity, don't bother with init interrupts ! 289: * returns nonzero if ok ! 290: */ ! 291: ! 292: #define UDA_STEPS (UDA_ERR|UDA_STEP4|UDA_STEP3|UDA_STEP2|UDA_STEP1) ! 293: ! 294: udhwinit(d) ! 295: int d; ! 296: { ! 297: register struct uda_softc *sc; ! 298: register struct udadevice *udaddr; ! 299: register int i; ! 300: register struct uda *ud; ! 301: register struct uda *uud; ! 302: time_t out; ! 303: ! 304: sc = &uda_softc[d]; ! 305: udaddr = sc->sc_addr; ! 306: out = time + 1; ! 307: udaddr->udaip = 0; /* start initialization */ ! 308: while((udaddr->udasa & UDA_STEP1) == 0 && time <= out) ! 309: ; ! 310: if((udaddr->udasa & UDA_STEPS) != UDA_STEP1) { ! 311: porterror(udaddr->udasa, d); ! 312: return (0); ! 313: } ! 314: sc->sc_state = S_STEP1; ! 315: sc->sc_credits = 0; ! 316: udaddr->udasa = UDA_ERR|(NCMDL2<<11)|(NRSPL2<<8)|(sc->sc_ivec/4); ! 317: /* no diagnostic wrap, no interrupts during initialization */ ! 318: out = time + 11; ! 319: while((udaddr->udasa & UDA_STEP2) == 0 && time <= out) ! 320: ; ! 321: if((udaddr->udasa & UDA_STEPS) != UDA_STEP2) { ! 322: porterror(udaddr->udasa, d); ! 323: return (0); ! 324: } ! 325: sc->sc_state = S_STEP2; ! 326: /* assert that &ringbase & 03 == 0 */ ! 327: udaddr->udasa = (short)&sc->sc_uda->uda_ca.ca_ringbase | UDA_PI; ! 328: out = time + 11; ! 329: while((udaddr->udasa & UDA_STEP3) == 0 && time <= out) ! 330: ; ! 331: if((udaddr->udasa & UDA_STEPS) != UDA_STEP3) { ! 332: porterror(udaddr->udasa, d); ! 333: return (0); ! 334: } ! 335: sc->sc_state = S_STEP3; ! 336: udaddr->udasa = ((long)&sc->sc_uda->uda_ca.ca_ringbase) >> 16; ! 337: out = time + 11; ! 338: while((udaddr->udasa & UDA_STEP4) == 0 && time <= out) ! 339: ; ! 340: if((udaddr->udasa & UDA_STEPS) != UDA_STEP4) { ! 341: porterror(udaddr->udasa, d); ! 342: return (0); ! 343: } ! 344: udaddr->udasa = (3<<2)|UDA_LF; ! 345: /* (3+1) double words per burst, last fail packets */ ! 346: uud = sc->sc_uda; ! 347: ud = &uda[d]; ! 348: for (i = 0; i < NRSP; i++) { ! 349: ud->uda_ca.ca_rspdsc[i] = UDA_OWN|UDA_INT| ! 350: (long)&uud->uda_rsp[i].mscp_cmdref; ! 351: ud->uda_rsp[i].mscp_dscptr = &ud->uda_ca.ca_rspdsc[i]; ! 352: ud->uda_rsp[i].mscp_header.uda_msglen = ! 353: sizeof(struct mscp); ! 354: } ! 355: for (i = 0; i < NCMD; i++) { ! 356: ud->uda_ca.ca_cmddsc[i] = UDA_INT| ! 357: (long)&uud->uda_cmd[i].mscp_cmdref; ! 358: ud->uda_cmd[i].mscp_dscptr = &ud->uda_ca.ca_cmddsc[i]; ! 359: ud->uda_cmd[i].mscp_header.uda_msglen = ! 360: sizeof(struct mscp); ! 361: } ! 362: udaddr->udasa = UDA_GO; /* finish init */ ! 363: return (1); ! 364: } ! 365: ! 366: static char *pmesg[] = { ! 367: "(error 0?)", ! 368: "data read", ! 369: "data write", ! 370: "parity", ! 371: "ram parity", ! 372: "rom parity", ! 373: "ring read", ! 374: "ring write", ! 375: "interrupt master", ! 376: "host timeout", ! 377: "credit limit", ! 378: "unibus master", ! 379: "diag controller", ! 380: "instruction loop timeout", ! 381: "invalid connection id", ! 382: "interrupt write", ! 383: "maint region", ! 384: "maint load", ! 385: "ram", ! 386: "init sequence", ! 387: "protocol incompat", ! 388: "purge/poll", ! 389: }; ! 390: ! 391: porterror(sa, d) ! 392: short sa; ! 393: int d; ! 394: { ! 395: register struct uda_softc *sc; ! 396: int n; ! 397: ! 398: sc = &uda_softc[d]; ! 399: printf("uda%d port error, sa x%x ", d, sa); ! 400: if(!(sa & UDA_ERR)) { ! 401: printf("(time out?), state %d\n", sc->sc_state); ! 402: sc->sc_state = S_IDLE; ! 403: return; ! 404: } ! 405: n = (sa & 0x3ff); ! 406: if(n > sizeof(pmesg)/sizeof(pmesg[0])) ! 407: printf("(?)\n"); ! 408: else ! 409: printf("%s\n", pmesg[n]); ! 410: sc->sc_state = S_IDLE; ! 411: } ! 412: ! 413: udstrategy(bp) ! 414: register struct buf *bp; ! 415: { ! 416: register struct uba_device *ui; ! 417: register struct uba_ctlr *um; ! 418: register struct buf *dp; ! 419: register int unit; ! 420: int part = PART(minor(bp->b_dev)); ! 421: daddr_t sz, maxsz; ! 422: int s; ! 423: ! 424: sz = (bp->b_bcount+(SECTOR-1)) / SECTOR; ! 425: unit = dkunit(bp); ! 426: if (unit >= NRA) { ! 427: bp->b_flags |= B_ERROR; ! 428: iodone(bp); ! 429: return; ! 430: } ! 431: ui = uddinfo[unit]; ! 432: um = ui->ui_mi; ! 433: if (ui == 0 || ui->ui_alive == 0) { ! 434: bp->b_flags |= B_ERROR; ! 435: iodone(bp); ! 436: return; ! 437: } ! 438: maxsz = ud_units[unit].radsize - ra_sizes[part].blkoff; ! 439: if (maxsz > ra_sizes[part].nblocks) ! 440: maxsz = ra_sizes[part].nblocks; ! 441: if (bp != &rctbuf[unit]) { ! 442: if (bp->b_blkno == maxsz) { ! 443: bp->b_resid = bp->b_bcount; ! 444: iodone(bp); ! 445: return; ! 446: } ! 447: if (bp->b_blkno < 0 || bp->b_blkno+sz > maxsz) { ! 448: bp->b_flags |= B_ERROR; ! 449: iodone(bp); ! 450: return; ! 451: } ! 452: } ! 453: s = spl5(); ! 454: /* ! 455: * Link the buffer onto the drive queue ! 456: */ ! 457: dp = &udutab[ui->ui_unit]; ! 458: if (dp->b_actf == 0) ! 459: dp->b_actf = bp; ! 460: else ! 461: dp->b_actl->av_forw = bp; ! 462: dp->b_actl = bp; ! 463: bp->av_forw = NULL; ! 464: /* ! 465: * Link the drive onto the controller queue (why bother?) ! 466: */ ! 467: if (dp->b_active == 0) { ! 468: dp->b_forw = NULL; ! 469: if (um->um_tab.b_actf == NULL) ! 470: um->um_tab.b_actf = dp; ! 471: else ! 472: um->um_tab.b_actl->b_forw = dp; ! 473: um->um_tab.b_actl = dp; ! 474: dp->b_active = 1; ! 475: } ! 476: if (um->um_tab.b_active == 0) ! 477: (void) udstart(um); ! 478: splx(s); ! 479: } ! 480: ! 481: udstart(um) ! 482: register struct uba_ctlr *um; ! 483: { ! 484: register struct buf *bp, *dp; ! 485: register struct mscp *mp; ! 486: register struct udadevice *udaddr; ! 487: register struct uda_softc *sc; ! 488: register struct uba_device *ui; ! 489: int i; ! 490: ! 491: sc = &uda_softc[um->um_ctlr]; ! 492: ! 493: loop: ! 494: if ((dp = um->um_tab.b_actf) == NULL) { ! 495: /* ! 496: * Release uneeded UBA resources and return ! 497: */ ! 498: um->um_tab.b_active = 0; ! 499: return (0); ! 500: } ! 501: if ((bp = dp->b_actf) == NULL) { ! 502: /* ! 503: * No more requests for this drive, remove ! 504: * from controller queue and look at next drive. ! 505: * We know we're at the head of the controller queue. ! 506: */ ! 507: dp->b_active = 0; ! 508: um->um_tab.b_actf = dp->b_forw; ! 509: goto loop; ! 510: } ! 511: um->um_tab.b_active++; ! 512: udaddr = sc->sc_addr; ! 513: if ((udaddr->udasa&UDA_ERR) || sc->sc_state != S_RUN) { ! 514: if(sc->sc_state != S_IDLE) { ! 515: harderr(bp, "ra"); ! 516: printf("uda%d udasa x%x, state %d\n", ! 517: um->um_ctlr, udaddr->udasa&0xffff, sc->sc_state); ! 518: } ! 519: udinit(um->um_ctlr); ! 520: /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE UDRESET */ ! 521: return (0); ! 522: } ! 523: ui = uddinfo[dkunit(bp)]; ! 524: /* ! 525: * get a packet, fill it in, and send it ! 526: */ ! 527: if (udcredit(sc, 0) == 0) ! 528: return (0); ! 529: if ((mp = udgetcp(um)) == NULL) ! 530: return (0); ! 531: if (ui->ui_flags == 0) { /* not online */ ! 532: if (++ui->ui_offl > MAXOFFL) { ! 533: ui->ui_offl = 0; ! 534: printf("uda%d ra%d offline\n", um->um_ctlr, ui->ui_slave); ! 535: bp->b_flags |= B_ERROR; ! 536: iodone(bp); ! 537: dp->b_actf = bp->av_forw; ! 538: if (dp->b_forw) { ! 539: um->um_tab.b_actf = dp->b_forw; ! 540: um->um_tab.b_actl->b_forw = dp; ! 541: um->um_tab.b_actl = dp; ! 542: dp->b_forw = NULL; ! 543: } ! 544: goto loop; ! 545: } ! 546: mp->mscp_opcode = M_OP_ONLIN; ! 547: mp->mscp_unit = ui->ui_slave; ! 548: dp->b_active = 2; /* MAGIC */ ! 549: um->um_tab.b_actf = dp->b_forw; /* remove from controller q */ ! 550: printd("uda: bring unit %d online\n", ui->ui_slave); ! 551: udsend(mp, sc); ! 552: goto loop; ! 553: } ! 554: ui->ui_offl = 0; ! 555: if(ui->ui_flags & DGTUNIT) { ! 556: mp->mscp_opcode = M_OP_GTUNT; ! 557: mp->mscp_unit = ui->ui_slave; ! 558: udsend(mp, sc); ! 559: ui->ui_flags &= ~DGTUNIT; ! 560: goto loop; ! 561: } ! 562: if ((i = ubasetup(um->um_ubanum, bp, UBA_WANTBDP|UBA_CANTWAIT)) == 0) { ! 563: /* this is issued just to get an interrupt */ ! 564: /* to try ubasetup again, a doubtful procedure */ ! 565: mp->mscp_opcode = M_OP_GTUNT; ! 566: mp->mscp_unit = ui->ui_slave; ! 567: udsend(mp, sc); ! 568: return(1); /* wait for interrupt */ ! 569: } ! 570: mp->mscp_cmdref = (long)bp; /* pointer to get back */ ! 571: mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; ! 572: mp->mscp_unit = ui->ui_slave; ! 573: mp->mscp_lbn = bp->b_blkno + ra_sizes[PART(minor(bp->b_dev))].blkoff; ! 574: mp->mscp_bytecnt = bp->b_bcount; ! 575: /* address; datapath number in high byte */ ! 576: mp->mscp_buffer = (i & 0x3ffff) | (((i>>28)&0xf)<<24); ! 577: bp->b_ubinfo = i; /* save mapping info */ ! 578: udsend(mp, sc); ! 579: if (ui->ui_dk >= 0) { ! 580: dk_busy |= 1<<ui->ui_dk; ! 581: dp->b_qsize++; ! 582: dk_xfer[ui->ui_dk]++; ! 583: dk_wds[ui->ui_dk] += bp->b_bcount>>6; ! 584: /* the way initialization is done now, this is useless */ ! 585: } ! 586: ! 587: /* ! 588: * Move drive to the end of the controller queue ! 589: */ ! 590: if (dp->b_forw != NULL) { ! 591: um->um_tab.b_actf = dp->b_forw; ! 592: um->um_tab.b_actl->b_forw = dp; ! 593: um->um_tab.b_actl = dp; ! 594: dp->b_forw = NULL; ! 595: } ! 596: /* ! 597: * Move buffer to I/O wait queue ! 598: */ ! 599: dp->b_actf = bp->av_forw; ! 600: dp = &udwtab[um->um_ctlr]; ! 601: bp->av_forw = dp; ! 602: bp->av_back = dp->av_back; ! 603: dp->av_back->av_forw = bp; ! 604: dp->av_back = bp; ! 605: goto loop; ! 606: } ! 607: ! 608: /* ! 609: * UDA interrupt routine. ! 610: */ ! 611: udintr(d) ! 612: int d; ! 613: { ! 614: register struct uba_ctlr *um; ! 615: register struct udadevice *udaddr; ! 616: register int i; ! 617: register struct uda_softc *sc; ! 618: register struct uda *ud; ! 619: ! 620: if (d < 0 || d >= NUDA) ! 621: panic("udintr"); ! 622: um = udminfo[d]; ! 623: sc = &uda_softc[d]; ! 624: ud = &uda[d]; ! 625: udaddr = sc->sc_addr; ! 626: switch (sc->sc_state) { ! 627: case S_IDLE: ! 628: printf("uda%d: random intr, status x%x\n", udaddr->udasa); ! 629: return; ! 630: ! 631: case S_SCHAR: ! 632: case S_RUN: ! 633: break; ! 634: ! 635: default: ! 636: printf("uda%d: intr in unknown state %d ignored\n", ! 637: d, sc->sc_state); ! 638: porterror(udaddr->udasa, d); ! 639: return; ! 640: } ! 641: ! 642: trace(TR_UDRESP, 0, udaddr->udasa); ! 643: if (udaddr->udasa&UDA_ERR) { ! 644: printf("uda%d: fatal error, udasa x%x\n", ! 645: d, udaddr->udasa&0xffff); ! 646: udaddr->udaip = 0; ! 647: sc->sc_state = S_IDLE; ! 648: } ! 649: if (ud->uda_ca.ca_bdp == 0 ! 650: && ud->uda_ca.ca_rspint == 0 ! 651: && ud->uda_ca.ca_cmdint == 0) ! 652: printf("uda%d: spurious intr\n", um->um_ctlr); ! 653: /* ! 654: * buffer purge request ! 655: */ ! 656: if (ud->uda_ca.ca_bdp) { ! 657: /* ! 658: * THIS IS A KLUDGE. ! 659: * Maybe we should change the entire ! 660: * UBA interface structure. ! 661: */ ! 662: int s = spl7(); ! 663: ! 664: i = um->um_ubinfo; ! 665: printd("uda%d purge bdp %d\n", um->um_ctlr, ud->uda_ca.ca_bdp); ! 666: um->um_ubinfo = ud->uda_ca.ca_bdp<<28; ! 667: ubapurge(um); ! 668: um->um_ubinfo = i; ! 669: (void) splx(s); ! 670: ud->uda_ca.ca_bdp = 0; ! 671: udaddr->udasa = 0; /* signal purge complete */ ! 672: } ! 673: /* ! 674: * response ring transition ! 675: */ ! 676: if (ud->uda_ca.ca_rspint) { ! 677: ud->uda_ca.ca_rspint = 0; ! 678: for (i = sc->sc_lastrsp;; i++) { ! 679: i %= NRSP; ! 680: if (ud->uda_ca.ca_rspdsc[i]&UDA_OWN) ! 681: break; ! 682: udrsp(um, ud, sc, i); ! 683: ud->uda_ca.ca_rspdsc[i] |= UDA_OWN; ! 684: } ! 685: sc->sc_lastrsp = i; ! 686: } ! 687: /* ! 688: * command ring transition ! 689: */ ! 690: if (ud->uda_ca.ca_cmdint) { ! 691: printf("uda%d command ring transition\n", um->um_ctlr); ! 692: ud->uda_ca.ca_cmdint = 0; ! 693: } ! 694: (void) udstart(um); ! 695: } ! 696: ! 697: /* ! 698: * send a packet to the uda ! 699: */ ! 700: ! 701: udsend(mp, sc) ! 702: struct mscp *mp; ! 703: struct uda_softc *sc; ! 704: { ! 705: register short junk; ! 706: ! 707: if ((sc->sc_flags & SCFIRST) == 0) { ! 708: if (sc->sc_credits < 2) ! 709: panic("udsend no credits"); ! 710: sc->sc_credits--; ! 711: } ! 712: trace(TR_UDCMND, mp->mscp_opcode, mp->mscp_cmdref); ! 713: *((long *)mp->mscp_dscptr) |= UDA_OWN | UDA_INT; ! 714: junk = sc->sc_addr->udaip; /* trigger polling */ ! 715: } ! 716: ! 717: /* ! 718: * check whether a packet may be sent ! 719: * wait until possible if desired ! 720: * call at spl6, and stay there until you've sent the packet ! 721: * else your credit may be stolen ! 722: */ ! 723: ! 724: udcredit(sc, wait) ! 725: register struct uda_softc *sc; ! 726: int wait; ! 727: { ! 728: ! 729: if (wait == 0 && sc->sc_credits < 2) ! 730: return (0); ! 731: while (sc->sc_credits < 2) { ! 732: sc->sc_flags |= SCCRED; ! 733: sleep((caddr_t)&sc->sc_credits, PRIBIO); ! 734: } ! 735: return (1); ! 736: } ! 737: ! 738: /* ! 739: * Process a response packet ! 740: */ ! 741: udrsp(um, ud, sc, i) ! 742: register struct uba_ctlr *um; ! 743: register struct uda *ud; ! 744: register struct uda_softc *sc; ! 745: int i; ! 746: { ! 747: register struct mscp *mp; ! 748: register struct uba_device *ui; ! 749: register struct buf *dp, *bp; ! 750: register int st; ! 751: struct ud_unit *up; ! 752: ! 753: mp = &ud->uda_rsp[i]; ! 754: st = mp->mscp_status; ! 755: trace(TR_UDRESP, mp->mscp_cmdref, mp->mscp_status); ! 756: printd("udrsp: 0x%x,st=x%x\n", mp->mscp_opcode, st); ! 757: mp->mscp_header.uda_msglen = sizeof (struct mscp); ! 758: sc->sc_credits += mp->mscp_header.uda_credits & 0xf; ! 759: sc->sc_flags &=~ SCFIRST; ! 760: if (sc->sc_flags & SCCRED) { ! 761: sc->sc_flags &=~ SCCRED; ! 762: wakeup((caddr_t)&sc->sc_credits); ! 763: } ! 764: if((mp->mscp_header.uda_credits & 0xf0) > 0x10) /* credits only */ ! 765: return; ! 766: /* ! 767: * If it's an error log message (datagram), ! 768: * pass it on for more extensive processing. ! 769: */ ! 770: if ((mp->mscp_header.uda_credits & 0xf0) == 0x10) { ! 771: uderror(um, (struct mslg *)mp); ! 772: return; ! 773: } ! 774: if (mp->mscp_unit >= MAXUNIT) ! 775: return; ! 776: ui = udip[um->um_ctlr][mp->mscp_unit]; ! 777: switch (mp->mscp_opcode) { ! 778: case M_OP_STCON|M_OP_END: ! 779: if ((st & M_ST_MASK) == M_ST_SUCC) { ! 780: sc->sc_state = S_RUN; ! 781: printf("uda%d run\n", um->um_ctlr); ! 782: } ! 783: else { ! 784: sc->sc_state = S_IDLE; ! 785: printf("uda%d: can't set ctlr char, status x%x\n", ! 786: um->um_ctlr, st); ! 787: } ! 788: sc->sc_ctime = mp->mscp_un.mscp_setcntchar.Mscp_hsttmo; ! 789: um->um_tab.b_active = 0; ! 790: break; ! 791: ! 792: case M_OP_ONLIN|M_OP_END: ! 793: /* ! 794: * Link the drive onto the controller queue ! 795: */ ! 796: if(ui == 0) { ! 797: bad: ! 798: printf("uda%d ra%d op x%x st x%x unexpected\n", ! 799: um->um_ctlr, mp->mscp_unit, mp->mscp_opcode, st); ! 800: return; ! 801: } ! 802: dp = &udutab[ui->ui_unit]; ! 803: dp->b_forw = NULL; ! 804: if (um->um_tab.b_actf == NULL) ! 805: um->um_tab.b_actf = dp; ! 806: else ! 807: um->um_tab.b_actl->b_forw = dp; ! 808: um->um_tab.b_actl = dp; ! 809: if ((st & M_ST_MASK) == M_ST_SUCC) { ! 810: ui->ui_flags = DUP; /* mark it online */ ! 811: ud_units[ui->ui_unit].radsize = (daddr_t)mp->mscp_untsize; ! 812: } else { ! 813: printf("uda%d ra%d online failed; status x%x\n", ! 814: um->um_ctlr, mp->mscp_unit, st); ! 815: while (bp = dp->b_actf) { ! 816: dp->b_actf = bp->av_forw; ! 817: bp->b_flags |= B_ERROR; ! 818: iodone(bp); ! 819: } ! 820: } ! 821: ui->ui_flags |= DGTUNIT; ! 822: dp->b_active = 1; ! 823: break; ! 824: ! 825: case M_OP_AVATN: /* is this the only kind of attn? */ ! 826: if(ui == 0) ! 827: goto bad; ! 828: ui->ui_flags = 0; /* it went offline, get status */ ! 829: break; ! 830: ! 831: case M_OP_READ|M_OP_END: ! 832: case M_OP_WRITE|M_OP_END: ! 833: if(ui == 0) ! 834: goto bad; ! 835: for (bp = udwtab[um->um_ctlr].b_actf; bp; bp = bp->av_forw) ! 836: if (bp == (struct buf *)mp->mscp_cmdref) ! 837: break; ! 838: if (bp == NULL) { ! 839: printf("uda%d ra%d: unknown cmdref x%x\n", ! 840: um->um_ctlr, mp->mscp_unit, mp->mscp_cmdref); ! 841: return; ! 842: } ! 843: ubarelse(um->um_ubanum, (int *)&bp->b_resid); ! 844: /* ! 845: * Unlink buffer from I/O wait queue. ! 846: */ ! 847: bp->av_back->av_forw = bp->av_forw; ! 848: bp->av_forw->av_back = bp->av_back; ! 849: dp = &udutab[ui->ui_unit]; ! 850: /* do we have drive queues just to gather statistics? */ ! 851: if (ui->ui_dk >= 0) ! 852: if (--dp->b_qsize == 0) ! 853: dk_busy &= ~(1<<ui->ui_dk); ! 854: if (st == M_ST_OFFLN || st == M_ST_AVLBL) { ! 855: ui->ui_flags = DGTUNIT; /* mark unit offline, GTUNT */ ! 856: /* ! 857: * Link the buffer onto the front of the drive queue ! 858: */ ! 859: if ((bp->av_forw = dp->b_actf) == 0) ! 860: dp->b_actl = bp; ! 861: dp->b_actf = bp; ! 862: /* ! 863: * Link the drive onto the controller queue ! 864: */ ! 865: if (dp->b_active == 0) { ! 866: dp->b_forw = NULL; ! 867: if (um->um_tab.b_actf == NULL) ! 868: um->um_tab.b_actf = dp; ! 869: else ! 870: um->um_tab.b_actl->b_forw = dp; ! 871: um->um_tab.b_actl = dp; ! 872: dp->b_active = 1; ! 873: } ! 874: return; ! 875: } ! 876: if ((st & M_ST_MASK) != M_ST_SUCC) { ! 877: harderr(bp, "ra"); ! 878: printf("uda%d; status x%x\n", um->um_ctlr, st); ! 879: bp->b_flags |= B_ERROR; ! 880: } ! 881: bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; ! 882: iodone(bp); ! 883: break; ! 884: ! 885: case M_OP_GTUNT|M_OP_END: ! 886: if(ui == 0) ! 887: goto bad; ! 888: up = ud_units + ui->ui_unit; ! 889: ui->ui_flags &= ~DGTUNIT; ! 890: up->rctsize = mp->mscp_rctsize; ! 891: up->medium = mp->mscp_mediaid; ! 892: up->tracksz = mp->mscp_track; ! 893: up->groupsz = mp->mscp_group; ! 894: up->cylsz = mp->mscp_cylinder; ! 895: up->rbns = mp->mscp_rbns; ! 896: up->copies = mp->mscp_rctcpys; ! 897: break; ! 898: ! 899: case M_OP_REPLC|M_OP_END: ! 900: if (ui == 0) ! 901: goto bad; ! 902: ud_rret = 0; ! 903: if ((st & M_ST_MASK) != M_ST_SUCC) { ! 904: printf("uda%d ra%d bad replace, status x%x\n", ! 905: um->um_ctlr, mp->mscp_unit, st); ! 906: ud_rret = EIO; ! 907: } ! 908: ud_rflags |= RPDONE; ! 909: wakeup((caddr_t)&ud_rret); ! 910: break; ! 911: ! 912: case M_OP_AVAIL|M_OP_END: ! 913: break; ! 914: ! 915: default: ! 916: printf("uda%d ra%d unknown packet type x%x\n", ! 917: um->um_ctlr, mp->mscp_unit, mp->mscp_opcode); ! 918: } ! 919: } ! 920: ! 921: ! 922: /* ! 923: * Process an error log message ! 924: * ! 925: * For now, just log the error on the console. ! 926: * Only minimal decoding is done, only "useful" ! 927: * information is printed. Eventually should ! 928: * send message to an error logger. ! 929: */ ! 930: ! 931: static char *events[] = { ! 932: "ok", ! 933: "inv cmd", ! 934: "op aborted", ! 935: "offline", ! 936: "available", ! 937: "med fmt", ! 938: "write prot", ! 939: "comp err", ! 940: "data err", ! 941: "host buf access err", ! 942: "cntl err", ! 943: "drive err", ! 944: }; ! 945: #define MAXEVT 0xb ! 946: ! 947: uderror(um, mp) ! 948: register struct uba_ctlr *um; ! 949: register struct mslg *mp; ! 950: { ! 951: register u_short *sp; /* for sdi crap */ ! 952: ! 953: printf("uda%d ra%d seq %d: %s err; fmt x%x ev x%x fl x%x\n", ! 954: um->um_ctlr, mp->mslg_unit, mp->mslg_seqnum, ! 955: mp->mslg_flags&(M_LF_SUCC|M_LF_CONT) ? "soft" : "hard", ! 956: mp->mslg_format, mp->mslg_event, mp->mslg_flags); ! 957: if ((mp->mslg_event & M_ST_MASK) <= MAXEVT) ! 958: printf("%s; ", events[mp->mslg_event & M_ST_MASK]); ! 959: switch (mp->mslg_format) { ! 960: case M_FM_CNTERR: ! 961: /* now the thing should be marked disastrously bad */ ! 962: printf("oops\n"); ! 963: break; ! 964: ! 965: case M_FM_BUSADDR: ! 966: printf("host mem access; addr x%x\n", ! 967: *((long *)&mp->mslg_busaddr[0])); ! 968: break; ! 969: ! 970: case M_FM_DISKTRN: ! 971: printf("%sbn %d; lev x%x, retry x%x\n", ! 972: (mp->mslg_hdr & 0xf0000000) == 0 ? "l" : "r", ! 973: mp->mslg_hdr & 0x0fffffff, ! 974: mp->mslg_level, mp->mslg_retry); ! 975: break; ! 976: ! 977: case M_FM_SDI: ! 978: printf("%sbn %d;", ! 979: (mp->mslg_hdr & 0xf0000000) == 0 ? "l" : "r", ! 980: mp->mslg_hdr & 0x0fffffff); ! 981: /* ! 982: * print the bytes in the same order used ! 983: * by the dec diagnostics ! 984: */ ! 985: sp = (u_short *)&mp->mslg_sdi[3]; ! 986: while (sp > (u_short *)mp->mslg_sdi) ! 987: printf(" %x", *--sp); ! 988: printf(" xx\n"); ! 989: break; ! 990: ! 991: case M_FM_SMLDSK: ! 992: printf("cyl %d\n", mp->mslg_sdecyl); ! 993: break; ! 994: } ! 995: } ! 996: ! 997: /* ! 998: * Find an unused command packet ! 999: * more exactly, return the next command packet if possible, ! 1000: * return NULL if we can't ! 1001: * the device insists that entries in the ring be used in sequence ! 1002: */ ! 1003: struct mscp * ! 1004: udgetcp(um) ! 1005: struct uba_ctlr *um; ! 1006: { ! 1007: register struct mscp *mp; ! 1008: register struct udaca *cp; ! 1009: register struct uda_softc *sc; ! 1010: register int i; ! 1011: ! 1012: cp = &uda[um->um_ctlr].uda_ca; ! 1013: sc = &uda_softc[um->um_ctlr]; ! 1014: i = sc->sc_lastcmd; ! 1015: if ((cp->ca_cmddsc[i] & (UDA_OWN|UDA_INT)) == UDA_INT) { ! 1016: cp->ca_cmddsc[i] &= ~UDA_INT; ! 1017: mp = &uda[um->um_ctlr].uda_cmd[i]; ! 1018: mp->mscp_unit = mp->mscp_modifier = 0; ! 1019: mp->mscp_opcode = mp->mscp_flags = 0; ! 1020: mp->mscp_bytecnt = mp->mscp_buffer = 0; ! 1021: mp->mscp_errlgfl = mp->mscp_copyspd = 0; ! 1022: sc->sc_lastcmd = (i + 1) % NCMD; ! 1023: return(mp); ! 1024: } ! 1025: return(NULL); ! 1026: } ! 1027: ! 1028: udaphys(bp) ! 1029: struct buf *bp; ! 1030: { ! 1031: if(bp->b_bcount > 65536) ! 1032: bp->b_bcount = 65536; ! 1033: } ! 1034: ! 1035: udread(dev) ! 1036: dev_t dev; ! 1037: { ! 1038: int unit = DUNIT(minor(dev)); ! 1039: ! 1040: if (unit >= NRA) ! 1041: u.u_error = ENXIO; ! 1042: else ! 1043: physio(udstrategy, &rudbuf[unit], dev, B_READ, udaphys); ! 1044: } ! 1045: ! 1046: udwrite(dev) ! 1047: dev_t dev; ! 1048: { ! 1049: int unit = DUNIT(minor(dev)); ! 1050: ! 1051: if (unit >= NRA) ! 1052: u.u_error = ENXIO; ! 1053: else ! 1054: physio(udstrategy, &rudbuf[unit], dev, B_WRITE, udaphys); ! 1055: } ! 1056: ! 1057: udioctl(dev, cmd, addr, flag) ! 1058: dev_t dev; ! 1059: caddr_t addr; ! 1060: { ! 1061: register int unit; ! 1062: register union arg { ! 1063: struct ud_rctbuf r; ! 1064: struct ud_repl b; ! 1065: } *uap; ! 1066: register struct ud_unit *uu; ! 1067: register int i; ! 1068: ! 1069: unit = DUNIT(minor(dev)); ! 1070: if (unit >= NRA) { ! 1071: u.u_error = ENXIO; ! 1072: return; ! 1073: } ! 1074: if ((uddinfo[unit]->ui_flags & (DGTUNIT | DUP)) != DUP) { ! 1075: /* should bring it online here */ ! 1076: u.u_error = EIO; ! 1077: return; ! 1078: } ! 1079: uu = &ud_units[unit]; ! 1080: uap = (union arg *)addr; ! 1081: switch(cmd) { ! 1082: default: ! 1083: u.u_error = ENOTTY; ! 1084: return; ! 1085: ! 1086: case UIOCHAR: ! 1087: if (copyout((caddr_t)uu, addr, sizeof(struct ud_unit))) ! 1088: u.u_error = EFAULT; ! 1089: return; ! 1090: ! 1091: case UIORRCT: ! 1092: if(uap->r.lbn < 0 || uap->r.lbn > uu->rctsize) { ! 1093: u.u_error = EIO; ! 1094: return; ! 1095: } ! 1096: /* ! 1097: * try different copies until one works ! 1098: */ ! 1099: for (i = 0; i < uu->copies; i++) { ! 1100: u.u_count = SECTOR; /* block size on disk */ ! 1101: u.u_offset = (uap->r.lbn + uu->radsize) * (daddr_t)SECTOR; ! 1102: u.u_offset += i * uu->rctsize * (daddr_t)SECTOR; ! 1103: u.u_base = uap->r.buf; ! 1104: u.u_segflg = 0; ! 1105: u.u_error = 0; ! 1106: physio(udstrategy, &rctbuf[unit], dev, B_READ, udaphys); ! 1107: if (u.u_error == 0) ! 1108: break; ! 1109: } ! 1110: return; ! 1111: ! 1112: case UIOWRCT: ! 1113: if ((flag & FWRITE) == 0) { ! 1114: u.u_error = EBADF; ! 1115: return; ! 1116: } ! 1117: if(uap->r.lbn < 0 || uap->r.lbn > uu->rctsize) { ! 1118: u.u_error = EIO; ! 1119: return; ! 1120: } ! 1121: /* ! 1122: * write every copy we can ! 1123: * should do read-after-write crap ! 1124: */ ! 1125: for (i = 0; i < uu->copies; i++) { ! 1126: u.u_count = SECTOR; /* block size on disk */ ! 1127: u.u_offset = (uap->r.lbn + uu->radsize) * (daddr_t)SECTOR; ! 1128: u.u_offset += i * uu->rctsize * (daddr_t)SECTOR; ! 1129: u.u_base = uap->r.buf; ! 1130: u.u_segflg = 0; ! 1131: physio(udstrategy, &rctbuf[unit], dev, B_WRITE, udaphys); ! 1132: u.u_error = 0; ! 1133: } ! 1134: return; ! 1135: ! 1136: case UIOREPL: ! 1137: if ((flag & FWRITE) == 0) { ! 1138: u.u_error = EBADF; ! 1139: return; ! 1140: } ! 1141: udreplace(dev, uap->b.lbn, uap->b.replbn, uap->b.prim); ! 1142: return; ! 1143: } ! 1144: } ! 1145: ! 1146: udreplace(dev, badlbn, replbn, prim) ! 1147: int dev; ! 1148: daddr_t badlbn; ! 1149: daddr_t replbn; ! 1150: int prim; ! 1151: { ! 1152: register struct mscp *mp; ! 1153: register struct uba_ctlr *um; ! 1154: register int unit; ! 1155: struct uda_softc *sc; ! 1156: ! 1157: unit = DUNIT(minor(dev)); ! 1158: um = uddinfo[unit]->ui_mi; ! 1159: sc = &uda_softc[um->um_ctlr]; ! 1160: spl6(); ! 1161: while (ud_rflags & RPLOCK) { ! 1162: ud_rflags |= RPWANT; ! 1163: sleep((caddr_t)&ud_rflags, PZERO + 1); ! 1164: } ! 1165: ud_rflags = RPLOCK; ! 1166: printf("uda%d ra%d replace %D with %D\n", ! 1167: um->um_ctlr, unit, badlbn, replbn); ! 1168: udcredit(sc, 1); ! 1169: if ((mp = udgetcp(um)) == NULL) { ! 1170: u.u_error = EIO; ! 1171: goto out; ! 1172: } ! 1173: mp->mscp_cmdref = 42; /* anything you like */ ! 1174: mp->mscp_unit = unit; ! 1175: mp->mscp_opcode = M_OP_REPLC; ! 1176: mp->mscp_rbn = replbn; ! 1177: mp->mscp_lbn = badlbn; ! 1178: mp->mscp_modifier = prim ? M_MD_PRIMR : 0; ! 1179: udsend(mp, sc); ! 1180: while ((ud_rflags & RPDONE) == 0) ! 1181: sleep((caddr_t)&ud_rret, PZERO); ! 1182: u.u_error = ud_rret; ! 1183: out: ! 1184: if (ud_rflags & RPWANT) ! 1185: wakeup((caddr_t)&ud_rflags); ! 1186: ud_rflags = 0; ! 1187: spl0(); ! 1188: } ! 1189: ! 1190: udreset(uban) ! 1191: int uban; ! 1192: { ! 1193: register struct uba_ctlr *um; ! 1194: register struct uba_device *ui; ! 1195: register struct buf *bp, *dp; ! 1196: register int unit; ! 1197: struct buf *nbp; ! 1198: int d; ! 1199: ! 1200: for (d = 0; d < NUDA; d++) { ! 1201: if ((um = udminfo[d]) == 0 || um->um_ubanum != uban || ! 1202: um->um_alive == 0) ! 1203: continue; ! 1204: printf(" uda%d", d); ! 1205: um->um_tab.b_active = 0; ! 1206: um->um_tab.b_actf = um->um_tab.b_actl = 0; ! 1207: uda_softc[d].sc_state = S_IDLE; ! 1208: for (unit = 0; unit < NRA; unit++) { ! 1209: if ((ui = uddinfo[unit]) == 0) ! 1210: continue; ! 1211: if (ui->ui_alive == 0 || ui->ui_mi != um) ! 1212: continue; ! 1213: udutab[unit].b_active = 0; ! 1214: udutab[unit].b_qsize = 0; ! 1215: } ! 1216: for (bp = udwtab[d].av_forw; bp != &udwtab[d]; bp = nbp) { ! 1217: nbp = bp->av_forw; ! 1218: ubarelse(uban, (int *)&bp->b_ubinfo); ! 1219: /* ! 1220: * Link the buffer onto the drive queue ! 1221: */ ! 1222: dp = &udutab[dkunit(bp)]; ! 1223: if (dp->b_actf == 0) ! 1224: dp->b_actf = bp; ! 1225: else ! 1226: dp->b_actl->av_forw = bp; ! 1227: dp->b_actl = bp; ! 1228: bp->av_forw = 0; ! 1229: /* ! 1230: * Link the drive onto the controller queue ! 1231: */ ! 1232: if (dp->b_active == 0) { ! 1233: dp->b_forw = NULL; ! 1234: if (um->um_tab.b_actf == NULL) ! 1235: um->um_tab.b_actf = dp; ! 1236: else ! 1237: um->um_tab.b_actl->b_forw = dp; ! 1238: um->um_tab.b_actl = dp; ! 1239: dp->b_active = 1; ! 1240: } ! 1241: } ! 1242: udinit(d); ! 1243: } ! 1244: } ! 1245: ! 1246: /* ! 1247: * crash dumps ! 1248: */ ! 1249: ! 1250: #define DBSIZE 64 ! 1251: ! 1252: #define ca_Rspdsc ca_rspdsc[0] ! 1253: #define ca_Cmddsc ca_rspdsc[1] ! 1254: #define uda_Rsp uda_rsp[0] ! 1255: #define uda_Cmd uda_cmd[0] ! 1256: ! 1257: uddump(dev) ! 1258: dev_t dev; ! 1259: { ! 1260: struct udadevice *udaddr; ! 1261: struct uda *ud_ubaddr; ! 1262: char *start; ! 1263: int num, blk, unit; ! 1264: int maxsz; ! 1265: int blkoff; ! 1266: register struct uba_regs *uba; ! 1267: register struct uba_device *ui; ! 1268: register struct uda *udp; ! 1269: register struct pte *io; ! 1270: register int i; ! 1271: ! 1272: unit = DUNIT(minor(dev)); ! 1273: if (unit >= NRA) ! 1274: return (ENXIO); ! 1275: #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) ! 1276: ui = phys(struct uba_device *, uddinfo[unit]); ! 1277: if (ui->ui_alive == 0) ! 1278: return (ENXIO); ! 1279: uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; ! 1280: ubainit(uba); ! 1281: udaddr = (struct udadevice *)ui->ui_physaddr; ! 1282: DELAY(2000000); ! 1283: udp = phys(struct uda *, &uda[ui->ui_ctlr]); ! 1284: ! 1285: num = btoc(sizeof(struct uda)) + 1; ! 1286: io = &uba->uba_map[NUBMREG-num]; ! 1287: for(i = 0; i<num; i++) ! 1288: *(int *)io++ = UBAMR_MRV|(btop(udp)+i); ! 1289: ud_ubaddr = (struct uda *)(((int)udp & PGOFSET)|((NUBMREG-num)<<9)); ! 1290: ! 1291: udaddr->udaip = 0; ! 1292: while ((udaddr->udasa & UDA_STEP1) == 0) ! 1293: if(udaddr->udasa & UDA_ERR) return(EFAULT); ! 1294: udaddr->udasa = UDA_ERR; ! 1295: while ((udaddr->udasa & UDA_STEP2) == 0) ! 1296: if(udaddr->udasa & UDA_ERR) return(EFAULT); ! 1297: udaddr->udasa = (short)&ud_ubaddr->uda_ca.ca_ringbase; ! 1298: while ((udaddr->udasa & UDA_STEP3) == 0) ! 1299: if(udaddr->udasa & UDA_ERR) return(EFAULT); ! 1300: udaddr->udasa = (short)(((int)&ud_ubaddr->uda_ca.ca_ringbase) >> 16); ! 1301: while ((udaddr->udasa & UDA_STEP4) == 0) ! 1302: if(udaddr->udasa & UDA_ERR) return(EFAULT); ! 1303: udaddr->udasa = UDA_GO; ! 1304: udp->uda_ca.ca_Rspdsc = (long)&ud_ubaddr->uda_Rsp.mscp_cmdref; ! 1305: udp->uda_ca.ca_Cmddsc = (long)&ud_ubaddr->uda_Cmd.mscp_cmdref; ! 1306: udp->uda_Cmd.mscp_cntflgs = 0; ! 1307: udp->uda_Cmd.mscp_version = 0; ! 1308: if (dudcmd(M_OP_STCON, udp, udaddr) == 0) ! 1309: return(EFAULT); ! 1310: udp->uda_Cmd.mscp_unit = ui->ui_slave; ! 1311: if (dudcmd(M_OP_ONLIN, udp, udaddr) == 0) ! 1312: return(EFAULT); ! 1313: num = physmem; ! 1314: start = 0; ! 1315: maxsz = ra_sizes[PART(minor(dev))].nblocks; ! 1316: blkoff = ra_sizes[PART(minor(dev))].blkoff; ! 1317: if(maxsz < 0) ! 1318: maxsz = ud_units[unit].radsize-blkoff; ! 1319: if (dumplo < 0 || dumplo + num >= maxsz) ! 1320: return (EINVAL); ! 1321: blkoff += dumplo; ! 1322: while (num > 0) { ! 1323: blk = num > DBSIZE ? DBSIZE : num; ! 1324: io = uba->uba_map; ! 1325: for (i = 0; i < blk; i++) ! 1326: *(int *)io++ = (btop(start)+i) | UBAMR_MRV; ! 1327: *(int *)io = 0; ! 1328: udp->uda_Cmd.mscp_lbn = btop(start) + blkoff; ! 1329: udp->uda_Cmd.mscp_unit = ui->ui_slave; ! 1330: udp->uda_Cmd.mscp_bytecnt = blk*NBPG; ! 1331: udp->uda_Cmd.mscp_buffer = 0; ! 1332: if (dudcmd(M_OP_WRITE, udp, udaddr) == 0) { ! 1333: return(EIO); ! 1334: } ! 1335: start += blk*NBPG; ! 1336: num -= blk; ! 1337: } ! 1338: return (0); ! 1339: } ! 1340: ! 1341: static ! 1342: dudcmd(op, udp, udaddr) ! 1343: int op; ! 1344: register struct uda *udp; ! 1345: struct udadevice *udaddr; ! 1346: { ! 1347: int i; ! 1348: ! 1349: udp->uda_Cmd.mscp_opcode = op; ! 1350: udp->uda_Rsp.mscp_header.uda_msglen = sizeof (struct mscp); ! 1351: udp->uda_Cmd.mscp_header.uda_msglen = sizeof (struct mscp); ! 1352: udp->uda_ca.ca_Rspdsc |= UDA_OWN|UDA_INT; ! 1353: udp->uda_ca.ca_Cmddsc |= UDA_OWN|UDA_INT; ! 1354: i = udaddr->udaip; ! 1355: for (;;) { ! 1356: if (udp->uda_ca.ca_cmdint) ! 1357: udp->uda_ca.ca_cmdint = 0; ! 1358: if (udp->uda_ca.ca_rspint) ! 1359: break; ! 1360: } ! 1361: udp->uda_ca.ca_rspint = 0; ! 1362: if (udp->uda_Rsp.mscp_opcode != (op|M_OP_END) || ! 1363: (udp->uda_Rsp.mscp_status&M_ST_MASK) != M_ST_SUCC) { ! 1364: if(udaddr->udasa&UDA_ERR) ! 1365: printf("error: udasa 0x%x\ndump ", udaddr->udasa); ! 1366: printf("error: com %d opc 0x%x stat 0x%x\ndump ", ! 1367: op, ! 1368: udp->uda_Rsp.mscp_opcode, ! 1369: udp->uda_Rsp.mscp_status); ! 1370: return(0); ! 1371: } ! 1372: return(1); ! 1373: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.