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