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