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

Defined functions

mbaddtape defined in line 369; used 1 times
mbainit defined in line 435; never used
mbasetup defined in line 395; used 2 times
mbintr defined in line 207; used 2 times
mbstart defined in line 126; used 2 times
mbustart defined in line 45; used 6 times

Defined variables

mbsr_bits defined in line 34; used 1 times

Defined macros

mbunit defined in line 32; used 2 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1527
Valid CSS Valid XHTML 1.0 Strict