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