1: /* 2: * Copyright (c) 1982, 1986 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.1 (Berkeley) 6/5/86 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 "dk.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: iodone(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: 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: */ 152: if (((com = mi->mi_drv->mbd_dt) & MBDT_TAP) == 0) 153: if ((mi->mi_drv->mbd_ds & MBDS_DREADY) != MBDS_DREADY) { 154: if ((com & MBDT_TYPE) == 0) { 155: mi->mi_alive = 0; 156: printf("%s%d: nonexistent\n", mi->mi_driver->md_dname, 157: mbunit(bp->b_dev)); 158: } else 159: printf("%s%d: not ready\n", mi->mi_driver->md_dname, 160: mbunit(bp->b_dev)); 161: mi->mi_tab.b_actf = bp->av_forw; 162: mi->mi_tab.b_errcnt = 0; 163: mi->mi_tab.b_active = 0; 164: bp->b_flags |= B_ERROR; 165: iodone(bp); 166: goto loop; 167: } 168: /* 169: * We can do the operation; mark the massbus active 170: * and let the device start routine setup any necessary 171: * device state for the transfer (e.g. desired cylinder, etc 172: * on disks). 173: */ 174: mhp->mh_active = 1; 175: if (mi->mi_driver->md_start == (int (*)())0 || 176: (com = (*mi->mi_driver->md_start)(mi)) == 0) 177: com = (bp->b_flags & B_READ) ? MB_RCOM|MB_GO : MB_WCOM|MB_GO; 178: 179: /* 180: * Setup the massbus control and map registers and start 181: * the transfer. 182: */ 183: mbp = mi->mi_mba; 184: mbp->mba_sr = -1; /* conservative */ 185: if (bp->b_bcount >= 0) { 186: mbp->mba_var = mbasetup(mi) + mi->mi_tab.b_bdone; 187: mbp->mba_bcr = -(bp->b_bcount - mi->mi_tab.b_bdone); 188: } else { 189: mbp->mba_var = mbasetup(mi) - bp->b_bcount - mi->mi_tab.b_bdone - 1; 190: mbp->mba_bcr = bp->b_bcount + mi->mi_tab.b_bdone; 191: } 192: mi->mi_drv->mbd_cs1 = com; 193: if (mi->mi_dk >= 0) { 194: dk_busy |= 1 << mi->mi_dk; 195: dk_xfer[mi->mi_dk]++; 196: if (bp->b_bcount >= 0) 197: dk_wds[mi->mi_dk] += bp->b_bcount >> 6; 198: else 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_REPOSITION: /* driver started repositioning */ 276: /* 277: * Drive is repositioning, not doing data transfer. 278: * Free controller, but don't have to restart drive. 279: */ 280: mhp->mh_active = 0; 281: mhp->mh_actf = mi->mi_forw; 282: break; 283: 284: case MBD_RESTARTED: /* driver restarted op (ecc, e.g.) */ 285: /* 286: * Note that mhp->mh_active is still on. 287: */ 288: break; 289: 290: default: 291: panic("mbintr"); 292: } 293: } 294: /* 295: * Service drives which require attention 296: * after non-data-transfer operations. 297: */ 298: while (drive = ffs((long)as)) { 299: drive--; /* was 1 origin */ 300: as &= ~(1 << drive); 301: mi = mhp->mh_mbip[drive]; 302: if (mi == NULL || mi->mi_alive == 0) { 303: struct mba_device fnd; 304: struct mba_drv *mbd = &mhp->mh_mba->mba_drv[drive]; 305: int dt = mbd->mbd_dt & 0xffff; 306: 307: if (dt == 0 || dt == MBDT_MOH) 308: continue; 309: fnd.mi_mba = mhp->mh_mba; 310: fnd.mi_mbanum = mbanum; 311: fnd.mi_drive = drive; 312: if ((mi = mbaconfig(&fnd, dt)) == NULL) 313: continue; 314: /* 315: * If a tape, poke the slave attach routines. 316: * Otherwise, could be a disk which we want 317: * to swap on, so make a pass over the swap 318: * configuration table in case the size of 319: * the swap area must be determined by drive type. 320: */ 321: if (dt & MBDT_TAP) 322: mbaddtape(mi, drive); 323: else 324: swapconf(); 325: } 326: /* 327: * If driver has a handler for non-data transfer 328: * interrupts, give it a chance to tell us what to do. 329: */ 330: if (mi->mi_driver->md_ndint) { 331: switch ((*mi->mi_driver->md_ndint)(mi)) { 332: 333: case MBN_DONE: /* operation completed */ 334: mi->mi_tab.b_active = 0; 335: mi->mi_tab.b_errcnt = 0; 336: bp = mi->mi_tab.b_actf; 337: mi->mi_tab.b_actf = bp->av_forw; 338: iodone(bp); 339: /* fall into common code */ 340: case MBN_RETRY: /* operation continues */ 341: if (mi->mi_tab.b_actf) 342: mbustart(mi); 343: break; 344: case MBN_SKIP: /* ignore unsol. interrupt */ 345: break; 346: default: 347: panic("mbintr"); 348: } 349: } else 350: /* 351: * If there is no non-data transfer interrupt 352: * routine, then we should just 353: * restart the unit, leading to a mbstart() soon. 354: */ 355: mbustart(mi); 356: } 357: /* 358: * If there is an operation available and 359: * the massbus isn't active, get it going. 360: */ 361: if (mhp->mh_actf && !mhp->mh_active) 362: mbstart(mhp); 363: /* THHHHATS all folks... */ 364: } 365: 366: /* 367: * For autoconfig'ng tape drives on the fly. 368: */ 369: mbaddtape(mi, drive) 370: struct mba_device *mi; 371: int drive; 372: { 373: register struct mba_slave *ms; 374: 375: for (ms = mbsinit; ms->ms_driver; ms++) 376: if (ms->ms_driver == mi->mi_driver && ms->ms_alive == 0 && 377: (ms->ms_ctlr == mi->mi_unit || 378: ms->ms_ctlr == '?')) { 379: if ((*ms->ms_driver->md_slave)(mi, ms, drive)) { 380: printf("%s%d at %s%d slave %d\n", 381: ms->ms_driver->md_sname, 382: ms->ms_unit, 383: mi->mi_driver->md_dname, 384: mi->mi_unit, 385: ms->ms_slave); 386: ms->ms_alive = 1; 387: ms->ms_ctlr = mi->mi_unit; 388: } 389: } 390: } 391: 392: /* 393: * Setup the mapping registers for a transfer. 394: */ 395: mbasetup(mi) 396: register struct mba_device *mi; 397: { 398: register struct mba_regs *mbap = mi->mi_mba; 399: struct buf *bp = mi->mi_tab.b_actf; 400: register int npf; 401: unsigned v; 402: register struct pte *pte, *io; 403: int o; 404: struct proc *rp; 405: 406: v = btop(bp->b_un.b_addr); 407: o = (int)(bp->b_un.b_addr) & PGOFSET; 408: if (bp->b_bcount >= 0) 409: npf = btoc(bp->b_bcount + o); 410: else 411: npf = btoc(-(bp->b_bcount) + o); 412: rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; 413: if ((bp->b_flags & B_PHYS) == 0) 414: pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)]; 415: else if (bp->b_flags & B_UAREA) 416: pte = &rp->p_addr[v]; 417: else if (bp->b_flags & B_PAGET) 418: pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; 419: else 420: pte = vtopte(rp, v); 421: io = mbap->mba_map; 422: while (--npf >= 0) { 423: if (pte->pg_pfnum == 0) 424: panic("mba, zero entry"); 425: *(int *)io++ = pte++->pg_pfnum | PG_V; 426: } 427: *(int *)io++ = 0; 428: return (o); 429: } 430: 431: #if notdef 432: /* 433: * Init and interrupt enable a massbus adapter. 434: */ 435: mbainit(mp) 436: struct mba_regs *mp; 437: { 438: 439: mp->mba_cr = MBCR_INIT; 440: mp->mba_cr = MBCR_IE; 441: } 442: #endif 443: #endif