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