|
|
1.1 ! root 1: /* mba.c 6.1 83/07/29 */ ! 2: ! 3: #include "mba.h" ! 4: #if NMBA > 0 ! 5: /* ! 6: * Massbus driver, arbitrates a massbus among attached devices. ! 7: */ ! 8: #include "../machine/pte.h" ! 9: ! 10: #include "../h/param.h" ! 11: #include "../h/systm.h" ! 12: #include "../h/dk.h" ! 13: #include "../h/buf.h" ! 14: #include "../h/conf.h" ! 15: #include "../h/dir.h" ! 16: #include "../h/user.h" ! 17: #include "../h/proc.h" ! 18: #include "../h/map.h" ! 19: #include "../vax/mtpr.h" ! 20: #include "../h/vm.h" ! 21: ! 22: #include "../vaxmba/mbareg.h" ! 23: #include "../vaxmba/mbavar.h" ! 24: ! 25: char mbsr_bits[] = MBSR_BITS; ! 26: /* ! 27: * Start activity on a massbus device. ! 28: * We are given the device's mba_device structure and activate ! 29: * the device via the unit start routine. The unit start ! 30: * routine may indicate that it is finished (e.g. if the operation ! 31: * was a ``sense'' on a tape drive), that the (multi-ported) unit ! 32: * is busy (we will get an interrupt later), that it started the ! 33: * unit (e.g. for a non-data transfer operation), or that it has ! 34: * set up a data transfer operation and we should start the massbus adaptor. ! 35: */ ! 36: mbustart(mi) ! 37: register struct mba_device *mi; ! 38: { ! 39: register struct buf *bp; /* i/o operation at head of queue */ ! 40: register struct mba_hd *mhp; /* header for mba device is on */ ! 41: ! 42: loop: ! 43: /* ! 44: * Get the first thing to do off device queue. ! 45: */ ! 46: bp = mi->mi_tab.b_actf; ! 47: if (bp == NULL) ! 48: return; ! 49: /* ! 50: * Make sure the drive is still there before starting it up. ! 51: */ ! 52: if ((mi->mi_drv->mbd_dt & MBDT_TYPE) == 0) { ! 53: printf("%s%d: nonexistent\n", mi->mi_driver->md_dname, ! 54: dkunit(bp)); ! 55: mi->mi_alive = 0; ! 56: mi->mi_tab.b_actf = bp->av_forw; ! 57: mi->mi_tab.b_active = 0; ! 58: mi->mi_tab.b_errcnt = 0; ! 59: bp->b_flags |= B_ERROR; ! 60: iodone(bp); ! 61: goto loop; ! 62: } ! 63: /* ! 64: * Let the drivers unit start routine have at it ! 65: * and then process the request further, per its instructions. ! 66: */ ! 67: switch ((*mi->mi_driver->md_ustart)(mi)) { ! 68: ! 69: case MBU_NEXT: /* request is complete (e.g. ``sense'') */ ! 70: mi->mi_tab.b_active = 0; ! 71: mi->mi_tab.b_errcnt = 0; ! 72: mi->mi_tab.b_actf = bp->av_forw; ! 73: iodone(bp); ! 74: goto loop; ! 75: ! 76: case MBU_DODATA: /* all ready to do data transfer */ ! 77: /* ! 78: * Queue the device mba_device structure on the massbus ! 79: * mba_hd structure for processing as soon as the ! 80: * data path is available. ! 81: */ ! 82: mhp = mi->mi_hd; ! 83: mi->mi_forw = NULL; ! 84: if (mhp->mh_actf == NULL) ! 85: mhp->mh_actf = mi; ! 86: else ! 87: mhp->mh_actl->mi_forw = mi; ! 88: mhp->mh_actl = mi; ! 89: /* ! 90: * If data path is idle, start transfer now. ! 91: * In any case the device is ``active'' waiting for the ! 92: * data to transfer. ! 93: */ ! 94: mi->mi_tab.b_active = 1; ! 95: if (mhp->mh_active == 0) ! 96: mbstart(mhp); ! 97: return; ! 98: ! 99: case MBU_STARTED: /* driver started a non-data transfer */ ! 100: /* ! 101: * Mark device busy during non-data transfer ! 102: * and count this as a ``seek'' on the device. ! 103: */ ! 104: if (mi->mi_dk >= 0) { ! 105: dk_seek[mi->mi_dk]++; ! 106: dk_busy |= (1 << mi->mi_dk); ! 107: } ! 108: mi->mi_tab.b_active = 1; ! 109: return; ! 110: ! 111: case MBU_BUSY: /* dual port drive busy */ ! 112: /* ! 113: * We mark the device structure so that when an ! 114: * interrupt occurs we will know to restart the unit. ! 115: */ ! 116: mi->mi_tab.b_flags |= B_BUSY; ! 117: return; ! 118: ! 119: default: ! 120: panic("mbustart"); ! 121: } ! 122: } ! 123: ! 124: /* ! 125: * Start an i/o operation on the massbus specified by the argument. ! 126: * We peel the first operation off its queue and insure that the drive ! 127: * is present and on-line. We then use the drivers start routine ! 128: * (if any) to prepare the drive, setup the massbus map for the transfer ! 129: * and start the transfer. ! 130: */ ! 131: mbstart(mhp) ! 132: register struct mba_hd *mhp; ! 133: { ! 134: register struct mba_device *mi; ! 135: struct buf *bp; ! 136: register struct mba_regs *mbp; ! 137: register int com; ! 138: ! 139: loop: ! 140: /* ! 141: * Look for an operation at the front of the queue. ! 142: */ ! 143: if ((mi = mhp->mh_actf) == NULL) { ! 144: return; ! 145: } ! 146: if ((bp = mi->mi_tab.b_actf) == NULL) { ! 147: mhp->mh_actf = mi->mi_forw; ! 148: goto loop; ! 149: } ! 150: /* ! 151: * If this device isn't present and on-line, then ! 152: * we screwed up, and can't really do the operation. ! 153: * Only check for non-tapes because tape drivers check ! 154: * ONLINE themselves and because TU78 registers are ! 155: * different. ! 156: */ ! 157: if (((com = mi->mi_drv->mbd_dt) & MBDT_TAP) == 0) ! 158: if ((mi->mi_drv->mbd_ds & MBDS_DREADY) != MBDS_DREADY) { ! 159: if ((com & MBDT_TYPE) == 0) { ! 160: mi->mi_alive = 0; ! 161: printf("%s%d: nonexistent\n", mi->mi_driver->md_dname, ! 162: dkunit(bp)); ! 163: } else ! 164: printf("%s%d: not ready\n", mi->mi_driver->md_dname, ! 165: dkunit(bp)); ! 166: mi->mi_tab.b_actf = bp->av_forw; ! 167: mi->mi_tab.b_errcnt = 0; ! 168: mi->mi_tab.b_active = 0; ! 169: bp->b_flags |= B_ERROR; ! 170: iodone(bp); ! 171: goto loop; ! 172: } ! 173: /* ! 174: * We can do the operation; mark the massbus active ! 175: * and let the device start routine setup any necessary ! 176: * device state for the transfer (e.g. desired cylinder, etc ! 177: * on disks). ! 178: */ ! 179: mhp->mh_active = 1; ! 180: if (mi->mi_driver->md_start) { ! 181: if ((com = (*mi->mi_driver->md_start)(mi)) == 0) ! 182: com = (bp->b_flags & B_READ) ? ! 183: MB_RCOM|MB_GO : MB_WCOM|MB_GO; ! 184: } else ! 185: com = (bp->b_flags & B_READ) ? MB_RCOM|MB_GO : MB_WCOM|MB_GO; ! 186: ! 187: /* ! 188: * Setup the massbus control and map registers and start ! 189: * the transfer. ! 190: */ ! 191: mbp = mi->mi_mba; ! 192: mbp->mba_sr = -1; /* conservative */ ! 193: mbp->mba_var = mbasetup(mi); ! 194: mbp->mba_bcr = -bp->b_bcount; ! 195: mi->mi_drv->mbd_cs1 = com; ! 196: if (mi->mi_dk >= 0) { ! 197: dk_busy |= 1 << mi->mi_dk; ! 198: dk_xfer[mi->mi_dk]++; ! 199: dk_wds[mi->mi_dk] += bp->b_bcount >> 6; ! 200: } ! 201: } ! 202: ! 203: /* ! 204: * Take an interrupt off of massbus mbanum, ! 205: * and dispatch to drivers as appropriate. ! 206: */ ! 207: mbintr(mbanum) ! 208: int mbanum; ! 209: { ! 210: register struct mba_hd *mhp = &mba_hd[mbanum]; ! 211: register struct mba_regs *mbp = mhp->mh_mba; ! 212: register struct mba_device *mi; ! 213: register struct buf *bp; ! 214: register int drive; ! 215: int mbasr, as; ! 216: extern struct mba_device *mbaconfig(); ! 217: ! 218: /* ! 219: * Read out the massbus status register ! 220: * and attention status register and clear ! 221: * the bits in same by writing them back. ! 222: */ ! 223: mbasr = mbp->mba_sr; ! 224: mbp->mba_sr = mbasr; ! 225: #if VAX750 ! 226: if (mbasr&MBSR_CBHUNG) { ! 227: printf("mba%d: control bus hung\n", mbanum); ! 228: panic("cbhung"); ! 229: } ! 230: #endif ! 231: /* note: the mbd_as register is shared between drives */ ! 232: as = mbp->mba_drv[0].mbd_as & 0xff; ! 233: mbp->mba_drv[0].mbd_as = as; ! 234: ! 235: /* ! 236: * If the mba was active, process the data transfer ! 237: * complete interrupt; otherwise just process units which ! 238: * are now finished. ! 239: */ ! 240: if (mhp->mh_active) { ! 241: /* ! 242: * Clear attention status for drive whose data ! 243: * transfer related operation completed, ! 244: * and give the dtint driver ! 245: * routine a chance to say what is next. ! 246: */ ! 247: mi = mhp->mh_actf; ! 248: as &= ~(1 << mi->mi_drive); ! 249: dk_busy &= ~(1 << mi->mi_dk); ! 250: bp = mi->mi_tab.b_actf; ! 251: switch ((*mi->mi_driver->md_dtint)(mi, mbasr)) { ! 252: ! 253: case MBD_DONE: /* all done, for better or worse */ ! 254: /* ! 255: * Flush request from drive queue. ! 256: */ ! 257: mi->mi_tab.b_errcnt = 0; ! 258: mi->mi_tab.b_actf = bp->av_forw; ! 259: iodone(bp); ! 260: /* fall into... */ ! 261: case MBD_RETRY: /* attempt the operation again */ ! 262: /* ! 263: * Dequeue data transfer from massbus queue; ! 264: * if there is still a i/o request on the device ! 265: * queue then start the next operation on the device. ! 266: * (Common code for DONE and RETRY). ! 267: */ ! 268: mhp->mh_active = 0; ! 269: mi->mi_tab.b_active = 0; ! 270: mhp->mh_actf = mi->mi_forw; ! 271: if (mi->mi_tab.b_actf) ! 272: mbustart(mi); ! 273: break; ! 274: ! 275: case MBD_RESTARTED: /* driver restarted op (ecc, e.g.) ! 276: /* ! 277: * Note that mhp->mh_active is still on. ! 278: */ ! 279: break; ! 280: ! 281: default: ! 282: panic("mbintr"); ! 283: } ! 284: } ! 285: /* ! 286: * Service drives which require attention ! 287: * after non-data-transfer operations. ! 288: */ ! 289: while (drive = ffs(as)) { ! 290: drive--; /* was 1 origin */ ! 291: as &= ~(1 << drive); ! 292: mi = mhp->mh_mbip[drive]; ! 293: if (mi == NULL || mi->mi_alive == 0) { ! 294: struct mba_device fnd; ! 295: struct mba_drv *mbd = &mhp->mh_mba->mba_drv[drive]; ! 296: int dt = mbd->mbd_dt & 0xffff; ! 297: ! 298: if (dt == 0 || dt == MBDT_MOH) ! 299: continue; ! 300: fnd.mi_mba = mhp->mh_mba; ! 301: fnd.mi_mbanum = mbanum; ! 302: fnd.mi_drive = drive; ! 303: if ((mi = mbaconfig(&fnd, dt)) == NULL) ! 304: continue; ! 305: /* ! 306: * If a tape, poke the slave attach routines. ! 307: * Otherwise, could be a disk which we want ! 308: * to swap on, so make a pass over the swap ! 309: * configuration table in case the size of ! 310: * the swap area must be determined by drive type. ! 311: */ ! 312: if (dt & MBDT_TAP) ! 313: mbaddtape(mi, drive); ! 314: else ! 315: swapconf(); ! 316: } ! 317: /* ! 318: * If driver has a handler for non-data transfer ! 319: * interrupts, give it a chance to tell us what to do. ! 320: */ ! 321: if (mi->mi_driver->md_ndint) { ! 322: switch ((*mi->mi_driver->md_ndint)(mi)) { ! 323: ! 324: case MBN_DONE: /* operation completed */ ! 325: mi->mi_tab.b_active = 0; ! 326: mi->mi_tab.b_errcnt = 0; ! 327: bp = mi->mi_tab.b_actf; ! 328: mi->mi_tab.b_actf = bp->av_forw; ! 329: iodone(bp); ! 330: /* fall into common code */ ! 331: case MBN_RETRY: /* operation continues */ ! 332: if (mi->mi_tab.b_actf) ! 333: mbustart(mi); ! 334: break; ! 335: case MBN_SKIP: /* ignore unsol. interrupt */ ! 336: break; ! 337: default: ! 338: panic("mbintr"); ! 339: } ! 340: } else ! 341: /* ! 342: * If there is no non-data transfer interrupt ! 343: * routine, then we should just ! 344: * restart the unit, leading to a mbstart() soon. ! 345: */ ! 346: mbustart(mi); ! 347: } ! 348: /* ! 349: * If there is an operation available and ! 350: * the massbus isn't active, get it going. ! 351: */ ! 352: if (mhp->mh_actf && !mhp->mh_active) ! 353: mbstart(mhp); ! 354: /* THHHHATS all folks... */ ! 355: } ! 356: ! 357: /* ! 358: * For autoconfig'ng tape drives on the fly. ! 359: */ ! 360: mbaddtape(mi, drive) ! 361: struct mba_device *mi; ! 362: int drive; ! 363: { ! 364: register struct mba_slave *ms; ! 365: ! 366: for (ms = mbsinit; ms->ms_driver; ms++) ! 367: if (ms->ms_driver == mi->mi_driver && ms->ms_alive == 0 && ! 368: (ms->ms_ctlr == mi->mi_unit || ! 369: ms->ms_ctlr == '?')) { ! 370: if ((*ms->ms_driver->md_slave)(mi, ms, drive)) { ! 371: printf("%s%d at %s%d slave %d\n", ! 372: ms->ms_driver->md_sname, ! 373: ms->ms_unit, ! 374: mi->mi_driver->md_dname, ! 375: mi->mi_unit, ! 376: ms->ms_slave); ! 377: ms->ms_alive = 1; ! 378: ms->ms_ctlr = mi->mi_unit; ! 379: } ! 380: } ! 381: } ! 382: ! 383: /* ! 384: * Setup the mapping registers for a transfer. ! 385: */ ! 386: mbasetup(mi) ! 387: register struct mba_device *mi; ! 388: { ! 389: register struct mba_regs *mbap = mi->mi_mba; ! 390: struct buf *bp = mi->mi_tab.b_actf; ! 391: register int npf; ! 392: unsigned v; ! 393: register struct pte *pte, *io; ! 394: int o; ! 395: struct proc *rp; ! 396: ! 397: v = btop(bp->b_un.b_addr); ! 398: o = (int)bp->b_un.b_addr & PGOFSET; ! 399: npf = btoc(bp->b_bcount + o); ! 400: rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; ! 401: if ((bp->b_flags & B_PHYS) == 0) ! 402: pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)]; ! 403: else if (bp->b_flags & B_UAREA) ! 404: pte = &rp->p_addr[v]; ! 405: else if (bp->b_flags & B_PAGET) ! 406: pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; ! 407: else ! 408: pte = vtopte(rp, v); ! 409: io = mbap->mba_map; ! 410: while (--npf >= 0) { ! 411: if (pte->pg_pfnum == 0) ! 412: panic("mba, zero entry"); ! 413: *(int *)io++ = pte++->pg_pfnum | PG_V; ! 414: } ! 415: *(int *)io++ = 0; ! 416: return (o); ! 417: } ! 418: ! 419: #if notdef ! 420: /* ! 421: * Init and interrupt enable a massbus adapter. ! 422: */ ! 423: mbainit(mp) ! 424: struct mba_regs *mp; ! 425: { ! 426: ! 427: mp->mba_cr = MBCR_INIT; ! 428: mp->mba_cr = MBCR_IE; ! 429: } ! 430: #endif ! 431: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.