|
|
1.1 ! root 1: /* uda.c 6.1 83/07/29 */ ! 2: ! 3: #include "ra.h" ! 4: #if NUDA > 0 ! 5: /* ! 6: * UDA50/RAxx disk device driver ! 7: * ! 8: * Restrictions: ! 9: * Unit numbers must be less than 8. ! 10: * ! 11: * TO DO: ! 12: * write dump code ! 13: */ ! 14: #include "../machine/pte.h" ! 15: ! 16: #include "../h/param.h" ! 17: #include "../h/systm.h" ! 18: #include "../h/buf.h" ! 19: #include "../h/conf.h" ! 20: #include "../h/dir.h" ! 21: #include "../h/user.h" ! 22: #include "../h/map.h" ! 23: #include "../h/vm.h" ! 24: #include "../h/dk.h" ! 25: #include "../h/cmap.h" ! 26: #include "../h/uio.h" ! 27: ! 28: #include "../vax/cpu.h" ! 29: #include "../vaxuba/ubareg.h" ! 30: #include "../vaxuba/ubavar.h" ! 31: ! 32: #define NRSPL2 3 /* log2 number of response packets */ ! 33: #define NCMDL2 3 /* log2 number of command packets */ ! 34: #define NRSP (1<<NRSPL2) ! 35: #define NCMD (1<<NCMDL2) ! 36: ! 37: #include "../vaxuba/udareg.h" ! 38: #include "../vax/mscp.h" ! 39: ! 40: struct uda_softc { ! 41: short sc_state; /* state of controller */ ! 42: short sc_mapped; /* Unibus map allocated for uda struct? */ ! 43: int sc_ubainfo; /* Unibus mapping info */ ! 44: struct uda *sc_uda; /* Unibus address of uda struct */ ! 45: int sc_ivec; /* interrupt vector address */ ! 46: short sc_credits; /* transfer credits */ ! 47: short sc_lastcmd; /* pointer into command ring */ ! 48: short sc_lastrsp; /* pointer into response ring */ ! 49: } uda_softc[NUDA]; ! 50: ! 51: /* ! 52: * Controller states ! 53: */ ! 54: #define S_IDLE 0 /* hasn't been initialized */ ! 55: #define S_STEP1 1 /* doing step 1 init */ ! 56: #define S_STEP2 2 /* doing step 2 init */ ! 57: #define S_STEP3 3 /* doing step 3 init */ ! 58: #define S_SCHAR 4 /* doing "set controller characteristics" */ ! 59: #define S_RUN 5 /* running */ ! 60: ! 61: struct uda { ! 62: struct udaca uda_ca; /* communications area */ ! 63: struct mscp uda_rsp[NRSP]; /* response packets */ ! 64: struct mscp uda_cmd[NCMD]; /* command packets */ ! 65: } uda[NUDA]; ! 66: ! 67: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ ! 68: struct size { ! 69: daddr_t nblocks; ! 70: daddr_t blkoff; ! 71: } ra_sizes[8] ={ ! 72: 15884, 0, /* A=blk 0 thru 15883 */ ! 73: 33440, 15884, /* B=blk 15884 thru 49323 */ ! 74: -1, 0, /* C=blk 0 thru end */ ! 75: 15884, 340670, /* D=blk 340670 thru 356553 */ ! 76: 55936, 356554, /* E=blk 356554 thru 412489 */ ! 77: -1, 412490, /* F=blk 412490 thru end */ ! 78: 82080, 49324, /* G=blk 49324 thru 131403 */ ! 79: -1, 131404, /* H=blk 131404 thru end */ ! 80: }; ! 81: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ ! 82: ! 83: int udaerror = 0; /* causes hex dump of packets */ ! 84: int udadebug = 0; ! 85: #define printd if (udadebug) printf ! 86: ! 87: daddr_t radsize[NRA]; /* disk size, from ONLINE end packet */ ! 88: ! 89: int udprobe(), udslave(), udattach(), udintr(); ! 90: struct mscp *udgetcp(); ! 91: struct uba_ctlr *udminfo[NUDA]; ! 92: struct uba_device *uddinfo[NRA]; ! 93: struct uba_device *udip[NUDA][8]; /* 8 == max number of drives */ ! 94: ! 95: u_short udstd[] = { 0772150, 0772550, 0777550, 0 }; ! 96: struct uba_driver udadriver = ! 97: { udprobe, udslave, udattach, 0, udstd, "ra", uddinfo, "uda", udminfo, 0 }; ! 98: struct buf rudbuf[NRA]; ! 99: struct buf udutab[NRA]; ! 100: struct buf udwtab[NUDA]; /* I/O wait queue, per controller */ ! 101: ! 102: #define b_qsize b_resid /* queue size per drive, in udutab */ ! 103: #define b_ubinfo b_resid /* Unibus mapping info, per buffer */ ! 104: ! 105: udprobe(reg, ctlr) ! 106: caddr_t reg; ! 107: int ctlr; ! 108: { ! 109: register int br, cvec; ! 110: register struct uda_softc *sc = &uda_softc[ctlr]; ! 111: ! 112: #ifdef lint ! 113: br = 0; cvec = br; br = cvec; reg = reg; ! 114: udreset(0); udintr(0); ! 115: #endif ! 116: /* SHOULD CHECK THAT IT REALLY IS A UDA */ ! 117: br = 0x15; ! 118: cvec = sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); ! 119: return(sizeof (struct udadevice)); ! 120: } ! 121: ! 122: udslave(ui, reg) ! 123: struct uba_device *ui; ! 124: caddr_t reg; ! 125: { ! 126: /* ! 127: * TOO HARD TO FIND OUT IF DISK IS THERE UNTIL ! 128: * INITIALIZED. WE'LL FIND OUT WHEN WE FIRST ! 129: * TRY TO ACCESS IT. ! 130: */ ! 131: #ifdef lint ! 132: ui = ui; reg = reg; ! 133: #endif ! 134: return(1); ! 135: } ! 136: ! 137: udattach(ui) ! 138: register struct uba_device *ui; ! 139: { ! 140: ! 141: if (ui->ui_dk >= 0) ! 142: dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256); /* approx */ ! 143: ui->ui_flags = 0; ! 144: udip[ui->ui_ctlr][ui->ui_slave] = ui; ! 145: radsize[ui->ui_unit] = (daddr_t)0xffffff; /* max possible size */ ! 146: } ! 147: ! 148: /* ! 149: * Open a UDA. Initialize the device and ! 150: * set the unit online. ! 151: */ ! 152: udopen(dev, flag) ! 153: dev_t dev; ! 154: int flag; ! 155: { ! 156: register int unit; ! 157: register struct uba_device *ui; ! 158: register struct uda_softc *sc; ! 159: int s; ! 160: ! 161: #ifdef lint ! 162: flag = flag; ! 163: #endif ! 164: unit = minor(dev) >> 3; ! 165: if (unit >= NRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0) ! 166: return (ENXIO); ! 167: sc = &uda_softc[ui->ui_ctlr]; ! 168: s = spl5(); ! 169: if (sc->sc_state != S_RUN) { ! 170: if (sc->sc_state == S_IDLE) ! 171: udinit(ui->ui_ctlr); ! 172: /* wait for initialization to complete */ ! 173: sleep((caddr_t)ui->ui_mi, 0); ! 174: if (sc->sc_state != S_RUN) ! 175: return (EIO); ! 176: } ! 177: splx(s); ! 178: /* SHOULD PROBABLY FORCE AN ONLINE ATTEMPT ! 179: TO SEE IF DISK IS REALLY THERE */ ! 180: return (0); ! 181: } ! 182: ! 183: /* ! 184: * Initialize a UDA. Set up UBA mapping registers, ! 185: * initialize data structures, and start hardware ! 186: * initialization sequence. ! 187: */ ! 188: udinit(d) ! 189: int d; ! 190: { ! 191: register struct uda_softc *sc; ! 192: register struct uda *ud; ! 193: struct udadevice *udaddr; ! 194: struct uba_ctlr *um; ! 195: ! 196: sc = &uda_softc[d]; ! 197: um = udminfo[d]; ! 198: um->um_tab.b_active++; ! 199: ud = &uda[d]; ! 200: udaddr = (struct udadevice *)um->um_addr; ! 201: if (sc->sc_mapped == 0) { ! 202: /* ! 203: * Map the communications area and command ! 204: * and response packets into Unibus address ! 205: * space. ! 206: */ ! 207: sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)ud, ! 208: sizeof (struct uda), 0); ! 209: sc->sc_uda = (struct uda *)(sc->sc_ubainfo & 0x3ffff); ! 210: sc->sc_mapped = 1; ! 211: } ! 212: ! 213: /* ! 214: * Start the hardware initialization sequence. ! 215: */ ! 216: udaddr->udaip = 0; /* start initialization */ ! 217: while ((udaddr->udasa & UDA_STEP1) == 0) ! 218: ; ! 219: udaddr->udasa = UDA_ERR|(NCMDL2<<11)|(NRSPL2<<8)|UDA_IE|(sc->sc_ivec/4); ! 220: /* ! 221: * Initialization continues in interrupt routine. ! 222: */ ! 223: sc->sc_state = S_STEP1; ! 224: sc->sc_credits = 0; ! 225: } ! 226: ! 227: udstrategy(bp) ! 228: register struct buf *bp; ! 229: { ! 230: register struct uba_device *ui; ! 231: register struct uba_ctlr *um; ! 232: register struct buf *dp; ! 233: register int unit; ! 234: int xunit = minor(bp->b_dev) & 07; ! 235: daddr_t sz, maxsz; ! 236: int s; ! 237: ! 238: sz = (bp->b_bcount+511) >> 9; ! 239: unit = dkunit(bp); ! 240: if (unit >= NRA) ! 241: goto bad; ! 242: ui = uddinfo[unit]; ! 243: um = ui->ui_mi; ! 244: if (ui == 0 || ui->ui_alive == 0) ! 245: goto bad; ! 246: if ((maxsz = ra_sizes[xunit].nblocks) < 0) ! 247: maxsz = radsize[unit] - ra_sizes[xunit].blkoff; ! 248: if (bp->b_blkno < 0 || bp->b_blkno+sz > maxsz || ! 249: ra_sizes[xunit].blkoff >= radsize[unit]) ! 250: goto bad; ! 251: s = spl5(); ! 252: /* ! 253: * Link the buffer onto the drive queue ! 254: */ ! 255: dp = &udutab[ui->ui_unit]; ! 256: if (dp->b_actf == 0) ! 257: dp->b_actf = bp; ! 258: else ! 259: dp->b_actl->av_forw = bp; ! 260: dp->b_actl = bp; ! 261: bp->av_forw = 0; ! 262: /* ! 263: * Link the drive onto the controller queue ! 264: */ ! 265: if (dp->b_active == 0) { ! 266: dp->b_forw = NULL; ! 267: if (um->um_tab.b_actf == NULL) ! 268: um->um_tab.b_actf = dp; ! 269: else ! 270: um->um_tab.b_actl->b_forw = dp; ! 271: um->um_tab.b_actl = dp; ! 272: dp->b_active = 1; ! 273: } ! 274: if (um->um_tab.b_active == 0) { ! 275: #if defined(VAX750) ! 276: if (cpu == VAX_750 ! 277: && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) { ! 278: if (um->um_ubinfo != 0) ! 279: printf("udastrat: ubinfo 0x%x\n",um->um_ubinfo); ! 280: else ! 281: um->um_ubinfo = ! 282: uballoc(um->um_ubanum, (caddr_t)0, 0, ! 283: UBA_NEEDBDP); ! 284: } ! 285: #endif ! 286: (void) udstart(um); ! 287: } ! 288: splx(s); ! 289: return; ! 290: ! 291: bad: ! 292: bp->b_flags |= B_ERROR; ! 293: iodone(bp); ! 294: return; ! 295: } ! 296: ! 297: udstart(um) ! 298: register struct uba_ctlr *um; ! 299: { ! 300: register struct buf *bp, *dp; ! 301: register struct mscp *mp; ! 302: register struct uda_softc *sc; ! 303: register struct uba_device *ui; ! 304: struct udadevice *udaddr; ! 305: int i; ! 306: ! 307: sc = &uda_softc[um->um_ctlr]; ! 308: ! 309: loop: ! 310: if ((dp = um->um_tab.b_actf) == NULL) { ! 311: /* ! 312: * Release uneeded UBA resources and return ! 313: */ ! 314: um->um_tab.b_active = 0; ! 315: return (0); ! 316: } ! 317: if ((bp = dp->b_actf) == NULL) { ! 318: /* ! 319: * No more requests for this drive, remove ! 320: * from controller queue and look at next drive. ! 321: * We know we're at the head of the controller queue. ! 322: */ ! 323: dp->b_active = 0; ! 324: um->um_tab.b_actf = dp->b_forw; ! 325: goto loop; ! 326: } ! 327: um->um_tab.b_active++; ! 328: udaddr = (struct udadevice *)um->um_addr; ! 329: if ((udaddr->udasa&UDA_ERR) || sc->sc_state != S_RUN) { ! 330: harderr(bp, "ra"); ! 331: printf("udasa %o, state %d\n", udaddr->udasa&0xffff, sc->sc_state); ! 332: udinit(um->um_ctlr); ! 333: /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE UDRESET */ ! 334: return (0); ! 335: } ! 336: ui = uddinfo[dkunit(bp)]; ! 337: /* ! 338: * If no credits, can't issue any commands ! 339: * until some outstanding commands complete. ! 340: */ ! 341: if (sc->sc_credits < 2) ! 342: return (0); ! 343: if ((mp = udgetcp(um)) == NULL) ! 344: return (0); ! 345: sc->sc_credits--; /* committed to issuing a command */ ! 346: if (ui->ui_flags == 0) { /* not online */ ! 347: mp->mscp_opcode = M_OP_ONLIN; ! 348: mp->mscp_unit = ui->ui_slave; ! 349: dp->b_active = 2; ! 350: um->um_tab.b_actf = dp->b_forw; /* remove from controller q */ ! 351: printd("uda: bring unit %d online\n", ui->ui_slave); ! 352: *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; ! 353: i = udaddr->udaip; ! 354: goto loop; ! 355: } ! 356: switch (cpu) { ! 357: case VAX_780: ! 358: i = UBA_NEEDBDP|UBA_CANTWAIT; ! 359: break; ! 360: ! 361: case VAX_750: ! 362: i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT; ! 363: break; ! 364: ! 365: case VAX_730: ! 366: i = UBA_CANTWAIT; ! 367: break; ! 368: } ! 369: if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) { ! 370: mp->mscp_opcode = M_OP_GTUNT; ! 371: mp->mscp_unit = ui->ui_slave; ! 372: *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; ! 373: i = udaddr->udaip; /* initiate polling */ ! 374: return(1); /* wait for interrupt */ ! 375: } ! 376: mp->mscp_cmdref = (long)bp; /* pointer to get back */ ! 377: mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; ! 378: mp->mscp_unit = ui->ui_slave; ! 379: mp->mscp_lbn = bp->b_blkno + ra_sizes[minor(bp->b_dev)&7].blkoff; ! 380: mp->mscp_bytecnt = bp->b_bcount; ! 381: mp->mscp_buffer = (i & 0x3ffff) | (((i>>28)&0xf)<<24); ! 382: #if defined(VAX750) ! 383: if (cpu == VAX_750) ! 384: i &= 0xfffffff; /* mask off bdp */ ! 385: #endif ! 386: bp->b_ubinfo = i; /* save mapping info */ ! 387: *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; ! 388: i = udaddr->udaip; /* initiate polling */ ! 389: if (ui->ui_dk >= 0) { ! 390: dk_busy |= 1<<ui->ui_dk; ! 391: dp->b_qsize++; ! 392: dk_xfer[ui->ui_dk]++; ! 393: dk_wds[ui->ui_dk] += bp->b_bcount>>6; ! 394: } ! 395: ! 396: /* ! 397: * Move drive to the end of the controller queue ! 398: */ ! 399: if (dp->b_forw != NULL) { ! 400: um->um_tab.b_actf = dp->b_forw; ! 401: um->um_tab.b_actl->b_forw = dp; ! 402: um->um_tab.b_actl = dp; ! 403: dp->b_forw = NULL; ! 404: } ! 405: /* ! 406: * Move buffer to I/O wait queue ! 407: */ ! 408: dp->b_actf = bp->av_forw; ! 409: dp = &udwtab[um->um_ctlr]; ! 410: bp->av_forw = dp; ! 411: bp->av_back = dp->av_back; ! 412: dp->av_back->av_forw = bp; ! 413: dp->av_back = bp; ! 414: goto loop; ! 415: } ! 416: ! 417: /* ! 418: * UDA interrupt routine. ! 419: */ ! 420: udintr(d) ! 421: int d; ! 422: { ! 423: register struct uba_ctlr *um = udminfo[d]; ! 424: register struct udadevice *udaddr = (struct udadevice *)um->um_addr; ! 425: struct buf *bp; ! 426: register int i; ! 427: register struct uda_softc *sc = &uda_softc[d]; ! 428: register struct uda *ud = &uda[d]; ! 429: struct uda *uud; ! 430: struct mscp *mp; ! 431: ! 432: printd("udintr: state %d, udasa %o\n", sc->sc_state, udaddr->udasa); ! 433: switch (sc->sc_state) { ! 434: case S_IDLE: ! 435: printf("uda%d: random interrupt ignored\n", d); ! 436: return; ! 437: ! 438: case S_STEP1: ! 439: #define STEP1MASK 0174377 ! 440: #define STEP1GOOD (UDA_STEP2|UDA_IE|(NCMDL2<<3)|NRSPL2) ! 441: if ((udaddr->udasa&STEP1MASK) != STEP1GOOD) { ! 442: sc->sc_state = S_IDLE; ! 443: wakeup((caddr_t)um); ! 444: return; ! 445: } ! 446: udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)| ! 447: (cpu == VAX_780 ? UDA_PI : 0); ! 448: sc->sc_state = S_STEP2; ! 449: return; ! 450: ! 451: case S_STEP2: ! 452: #define STEP2MASK 0174377 ! 453: #define STEP2GOOD (UDA_STEP3|UDA_IE|(sc->sc_ivec/4)) ! 454: if ((udaddr->udasa&STEP2MASK) != STEP2GOOD) { ! 455: sc->sc_state = S_IDLE; ! 456: wakeup((caddr_t)um); ! 457: return; ! 458: } ! 459: udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)>>16; ! 460: sc->sc_state = S_STEP3; ! 461: return; ! 462: ! 463: case S_STEP3: ! 464: #define STEP3MASK 0174000 ! 465: #define STEP3GOOD UDA_STEP4 ! 466: if ((udaddr->udasa&STEP3MASK) != STEP3GOOD) { ! 467: sc->sc_state = S_IDLE; ! 468: wakeup((caddr_t)um); ! 469: return; ! 470: } ! 471: udaddr->udasa = UDA_GO; ! 472: sc->sc_state = S_SCHAR; ! 473: ! 474: /* ! 475: * Initialize the data structures. ! 476: */ ! 477: uud = sc->sc_uda; ! 478: for (i = 0; i < NRSP; i++) { ! 479: ud->uda_ca.ca_rspdsc[i] = UDA_OWN|UDA_INT| ! 480: (long)&uud->uda_rsp[i].mscp_cmdref; ! 481: ud->uda_rsp[i].mscp_dscptr = &ud->uda_ca.ca_rspdsc[i]; ! 482: ud->uda_rsp[i].mscp_header.uda_msglen = sizeof (struct mscp); ! 483: } ! 484: for (i = 0; i < NCMD; i++) { ! 485: ud->uda_ca.ca_cmddsc[i] = UDA_INT| ! 486: (long)&uud->uda_cmd[i].mscp_cmdref; ! 487: ud->uda_cmd[i].mscp_dscptr = &ud->uda_ca.ca_cmddsc[i]; ! 488: ud->uda_cmd[i].mscp_header.uda_msglen = sizeof (struct mscp); ! 489: } ! 490: bp = &udwtab[d]; ! 491: bp->av_forw = bp->av_back = bp; ! 492: sc->sc_lastcmd = 0; ! 493: sc->sc_lastrsp = 0; ! 494: if ((mp = udgetcp(um)) == NULL) { ! 495: sc->sc_state = S_IDLE; ! 496: wakeup((caddr_t)um); ! 497: return; ! 498: } ! 499: mp->mscp_opcode = M_OP_STCON; ! 500: mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; ! 501: *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; ! 502: i = udaddr->udaip; /* initiate polling */ ! 503: return; ! 504: ! 505: case S_SCHAR: ! 506: case S_RUN: ! 507: break; ! 508: ! 509: default: ! 510: printf("uda%d: interrupt in unknown state %d ignored\n", ! 511: d, sc->sc_state); ! 512: return; ! 513: } ! 514: ! 515: if (udaddr->udasa&UDA_ERR) { ! 516: printf("uda%d: fatal error (%o)\n", d, udaddr->udasa&0xffff); ! 517: udaddr->udaip = 0; ! 518: wakeup((caddr_t)um); ! 519: } ! 520: ! 521: /* ! 522: * Check for a buffer purge request. ! 523: */ ! 524: if (ud->uda_ca.ca_bdp) { ! 525: /* ! 526: * THIS IS A KLUDGE. ! 527: * Maybe we should change the entire ! 528: * UBA interface structure. ! 529: */ ! 530: int s = spl7(); ! 531: ! 532: i = um->um_ubinfo; ! 533: printd("uda: purge bdp %d\n", ud->uda_ca.ca_bdp); ! 534: um->um_ubinfo = ud->uda_ca.ca_bdp<<28; ! 535: ubapurge(um); ! 536: um->um_ubinfo = i; ! 537: (void) splx(s); ! 538: ud->uda_ca.ca_bdp = 0; ! 539: udaddr->udasa = 0; /* signal purge complete */ ! 540: } ! 541: ! 542: /* ! 543: * Check for response ring transition. ! 544: */ ! 545: if (ud->uda_ca.ca_rspint) { ! 546: ud->uda_ca.ca_rspint = 0; ! 547: for (i = sc->sc_lastrsp;; i++) { ! 548: i %= NRSP; ! 549: if (ud->uda_ca.ca_rspdsc[i]&UDA_OWN) ! 550: break; ! 551: udrsp(um, ud, sc, i); ! 552: ud->uda_ca.ca_rspdsc[i] |= UDA_OWN; ! 553: } ! 554: sc->sc_lastrsp = i; ! 555: } ! 556: ! 557: /* ! 558: * Check for command ring transition. ! 559: */ ! 560: if (ud->uda_ca.ca_cmdint) { ! 561: printd("uda: command ring transition\n"); ! 562: ud->uda_ca.ca_cmdint = 0; ! 563: } ! 564: (void) udstart(um); ! 565: } ! 566: ! 567: /* ! 568: * Process a response packet ! 569: */ ! 570: udrsp(um, ud, sc, i) ! 571: register struct uba_ctlr *um; ! 572: register struct uda *ud; ! 573: register struct uda_softc *sc; ! 574: int i; ! 575: { ! 576: register struct mscp *mp; ! 577: struct uba_device *ui; ! 578: struct buf *dp, *bp; ! 579: int st; ! 580: ! 581: mp = &ud->uda_rsp[i]; ! 582: mp->mscp_header.uda_msglen = sizeof (struct mscp); ! 583: sc->sc_credits += mp->mscp_header.uda_credits & 0xf; ! 584: if ((mp->mscp_header.uda_credits & 0xf0) > 0x10) ! 585: return; ! 586: /* ! 587: * If it's an error log message (datagram), ! 588: * pass it on for more extensive processing. ! 589: */ ! 590: if ((mp->mscp_header.uda_credits & 0xf0) == 0x10) { ! 591: uderror(um, (struct mslg *)mp); ! 592: return; ! 593: } ! 594: if (mp->mscp_unit >= 8) ! 595: return; ! 596: if ((ui = udip[um->um_ctlr][mp->mscp_unit]) == 0) ! 597: return; ! 598: st = mp->mscp_status&M_ST_MASK; ! 599: switch (mp->mscp_opcode) { ! 600: case M_OP_STCON|M_OP_END: ! 601: if (st == M_ST_SUCC) ! 602: sc->sc_state = S_RUN; ! 603: else ! 604: sc->sc_state = S_IDLE; ! 605: um->um_tab.b_active = 0; ! 606: wakeup((caddr_t)um); ! 607: break; ! 608: ! 609: case M_OP_ONLIN|M_OP_END: ! 610: /* ! 611: * Link the drive onto the controller queue ! 612: */ ! 613: dp = &udutab[ui->ui_unit]; ! 614: dp->b_forw = NULL; ! 615: if (um->um_tab.b_actf == NULL) ! 616: um->um_tab.b_actf = dp; ! 617: else ! 618: um->um_tab.b_actl->b_forw = dp; ! 619: um->um_tab.b_actl = dp; ! 620: if (st == M_ST_SUCC) { ! 621: ui->ui_flags = 1; /* mark it online */ ! 622: radsize[ui->ui_unit] = (daddr_t)mp->mscp_untsize; ! 623: printd("uda: unit %d online\n", mp->mscp_unit); ! 624: #ifdef notdef ! 625: printf("uda%d: online, size=%d\n", ! 626: mp->mscp_unit, (daddr_t)mp->mscp_untsize); ! 627: #endif ! 628: } else { ! 629: harderr(dp->b_actf, "ra"); ! 630: printf("OFFLINE\n"); ! 631: while (bp = dp->b_actf) { ! 632: dp->b_actf = bp->av_forw; ! 633: bp->b_flags |= B_ERROR; ! 634: iodone(bp); ! 635: } ! 636: } ! 637: dp->b_active = 1; ! 638: break; ! 639: ! 640: case M_OP_AVATN: ! 641: printd("uda: unit %d attention\n", mp->mscp_unit); ! 642: ui->ui_flags = 0; /* it went offline and we didn't notice */ ! 643: break; ! 644: ! 645: case M_OP_READ|M_OP_END: ! 646: case M_OP_WRITE|M_OP_END: ! 647: bp = (struct buf *)mp->mscp_cmdref; ! 648: ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo); ! 649: /* ! 650: * Unlink buffer from I/O wait queue. ! 651: */ ! 652: bp->av_back->av_forw = bp->av_forw; ! 653: bp->av_forw->av_back = bp->av_back; ! 654: #if defined(VAX750) ! 655: if (cpu == VAX_750 ! 656: && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) { ! 657: if (um->um_ubinfo == 0) ! 658: printf("udintr: um_ubinfo == 0\n"); ! 659: else ! 660: ubarelse(um->um_ubanum, &um->um_ubinfo); ! 661: } ! 662: #endif ! 663: dp = &udutab[ui->ui_unit]; ! 664: if (ui->ui_dk >= 0) ! 665: if (--dp->b_qsize == 0) ! 666: dk_busy &= ~(1<<ui->ui_dk); ! 667: if (st == M_ST_OFFLN || st == M_ST_AVLBL) { ! 668: ui->ui_flags = 0; /* mark unit offline */ ! 669: /* ! 670: * Link the buffer onto the front of the drive queue ! 671: */ ! 672: if ((bp->av_forw = dp->b_actf) == 0) ! 673: dp->b_actl = bp; ! 674: dp->b_actf = bp; ! 675: /* ! 676: * Link the drive onto the controller queue ! 677: */ ! 678: if (dp->b_active == 0) { ! 679: dp->b_forw = NULL; ! 680: if (um->um_tab.b_actf == NULL) ! 681: um->um_tab.b_actf = dp; ! 682: else ! 683: um->um_tab.b_actl->b_forw = dp; ! 684: um->um_tab.b_actl = dp; ! 685: dp->b_active = 1; ! 686: } ! 687: #if defined(VAX750) ! 688: if (cpu == VAX750 && um->um_ubinfo == 0) ! 689: um->um_ubinfo = ! 690: uballoc(um->um_ubanum, (caddr_t)0, 0, ! 691: UBA_NEEDBDP); ! 692: #endif ! 693: return; ! 694: } ! 695: if (st != M_ST_SUCC) { ! 696: harderr(bp, "ra"); ! 697: printf("status %o\n", mp->mscp_status); ! 698: bp->b_flags |= B_ERROR; ! 699: } ! 700: bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; ! 701: iodone(bp); ! 702: break; ! 703: ! 704: case M_OP_GTUNT|M_OP_END: ! 705: break; ! 706: ! 707: default: ! 708: printf("uda: unknown packet\n"); ! 709: } ! 710: } ! 711: ! 712: ! 713: /* ! 714: * Process an error log message ! 715: * ! 716: * For now, just log the error on the console. ! 717: * Only minimal decoding is done, only "useful" ! 718: * information is printed. Eventually should ! 719: * send message to an error logger. ! 720: */ ! 721: uderror(um, mp) ! 722: register struct uba_ctlr *um; ! 723: register struct mslg *mp; ! 724: { ! 725: printf("uda%d: %s error, ", um->um_ctlr, ! 726: mp->mslg_flags&M_LF_SUCC ? "soft" : "hard"); ! 727: switch (mp->mslg_format) { ! 728: case M_FM_CNTERR: ! 729: printf("controller error, event 0%o\n", mp->mslg_event); ! 730: break; ! 731: ! 732: case M_FM_BUSADDR: ! 733: printf("host memory access error, event 0%o, addr 0%o\n", ! 734: mp->mslg_event, mp->mslg_busaddr); ! 735: break; ! 736: ! 737: case M_FM_DISKTRN: ! 738: printf("disk transfer error, unit %d, grp 0x%x, hdr 0x%x\n", ! 739: mp->mslg_unit, mp->mslg_group, mp->mslg_hdr); ! 740: break; ! 741: ! 742: case M_FM_SDI: ! 743: printf("SDI error, unit %d, event 0%o, hdr 0x%x\n", ! 744: mp->mslg_unit, mp->mslg_event, mp->mslg_hdr); ! 745: break; ! 746: ! 747: case M_FM_SMLDSK: ! 748: printf("small disk error, unit %d, event 0%o, cyl %d\n", ! 749: mp->mslg_unit, mp->mslg_event, mp->mslg_sdecyl); ! 750: break; ! 751: ! 752: default: ! 753: printf("unknown error, unit %d, format 0%o, event 0%o\n", ! 754: mp->mslg_unit, mp->mslg_format, mp->mslg_event); ! 755: } ! 756: ! 757: if (udaerror) { ! 758: register long *p = (long *)mp; ! 759: register int i; ! 760: ! 761: for (i = 0; i < mp->mslg_header.uda_msglen; i += sizeof(*p)) ! 762: printf("%x ", *p++); ! 763: printf("\n"); ! 764: } ! 765: } ! 766: ! 767: ! 768: /* ! 769: * Find an unused command packet ! 770: */ ! 771: struct mscp * ! 772: udgetcp(um) ! 773: struct uba_ctlr *um; ! 774: { ! 775: register struct mscp *mp; ! 776: register struct udaca *cp; ! 777: register struct uda_softc *sc; ! 778: register int i; ! 779: ! 780: cp = &uda[um->um_ctlr].uda_ca; ! 781: sc = &uda_softc[um->um_ctlr]; ! 782: i = sc->sc_lastcmd; ! 783: if ((cp->ca_cmddsc[i] & (UDA_OWN|UDA_INT)) == UDA_INT) { ! 784: cp->ca_cmddsc[i] &= ~UDA_INT; ! 785: mp = &uda[um->um_ctlr].uda_cmd[i]; ! 786: mp->mscp_unit = mp->mscp_modifier = 0; ! 787: mp->mscp_opcode = mp->mscp_flags = 0; ! 788: mp->mscp_bytecnt = mp->mscp_buffer = 0; ! 789: mp->mscp_errlgfl = mp->mscp_copyspd = 0; ! 790: sc->sc_lastcmd = (i + 1) % NCMD; ! 791: return(mp); ! 792: } ! 793: return(NULL); ! 794: } ! 795: ! 796: udread(dev, uio) ! 797: dev_t dev; ! 798: struct uio *uio; ! 799: { ! 800: register int unit = minor(dev) >> 3; ! 801: ! 802: if (unit >= NRA) ! 803: return (ENXIO); ! 804: return (physio(udstrategy, &rudbuf[unit], dev, B_READ, minphys, uio)); ! 805: } ! 806: ! 807: udwrite(dev, uio) ! 808: dev_t dev; ! 809: struct uio *uio; ! 810: { ! 811: register int unit = minor(dev) >> 3; ! 812: ! 813: if (unit >= NRA) ! 814: return (ENXIO); ! 815: return (physio(udstrategy, &rudbuf[unit], dev, B_WRITE, minphys, uio)); ! 816: } ! 817: ! 818: udreset(uban) ! 819: int uban; ! 820: { ! 821: register struct uba_ctlr *um; ! 822: register struct uba_device *ui; ! 823: register struct buf *bp, *dp; ! 824: register int unit; ! 825: struct buf *nbp; ! 826: int d; ! 827: ! 828: for (d = 0; d < NUDA; d++) { ! 829: if ((um = udminfo[d]) == 0 || um->um_ubanum != uban || ! 830: um->um_alive == 0) ! 831: continue; ! 832: printf(" uda%d", d); ! 833: um->um_tab.b_active = 0; ! 834: um->um_tab.b_actf = um->um_tab.b_actl = 0; ! 835: uda_softc[d].sc_state = S_IDLE; ! 836: for (unit = 0; unit < NRA; unit++) { ! 837: if ((ui = uddinfo[unit]) == 0) ! 838: continue; ! 839: if (ui->ui_alive == 0 || ui->ui_mi != um) ! 840: continue; ! 841: udutab[unit].b_active = 0; ! 842: udutab[unit].b_qsize = 0; ! 843: } ! 844: for (bp = udwtab[d].av_forw; bp != &udwtab[d]; bp = nbp) { ! 845: nbp = bp->av_forw; ! 846: bp->b_ubinfo = 0; ! 847: /* ! 848: * Link the buffer onto the drive queue ! 849: */ ! 850: dp = &udutab[dkunit(bp)]; ! 851: if (dp->b_actf == 0) ! 852: dp->b_actf = bp; ! 853: else ! 854: dp->b_actl->av_forw = bp; ! 855: dp->b_actl = bp; ! 856: bp->av_forw = 0; ! 857: /* ! 858: * Link the drive onto the controller queue ! 859: */ ! 860: if (dp->b_active == 0) { ! 861: dp->b_forw = NULL; ! 862: if (um->um_tab.b_actf == NULL) ! 863: um->um_tab.b_actf = dp; ! 864: else ! 865: um->um_tab.b_actl->b_forw = dp; ! 866: um->um_tab.b_actl = dp; ! 867: dp->b_active = 1; ! 868: } ! 869: } ! 870: udinit(d); ! 871: } ! 872: } ! 873: ! 874: uddump() ! 875: { ! 876: return(ENXIO); ! 877: } ! 878: ! 879: udsize(dev) ! 880: dev_t dev; ! 881: { ! 882: int unit = minor(dev) >> 3; ! 883: struct uba_device *ui; ! 884: ! 885: if (unit >= NRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0) ! 886: return (-1); ! 887: return (ra_sizes[minor(dev) & 07].nblocks); /* XXX */ ! 888: } ! 889: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.