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