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