|
|
1.1 ! root 1: #include "fsd.h" ! 2: #if NVD > 0 ! 3: /* ! 4: ** VDDC Driver - Versabus to SMD direct interface version. ! 5: ** Written for TAHOE vmunix, CCI-WDC 9/1/83. ! 6: ** Modified June 1984 to use scatter/gather. ! 7: */ ! 8: ! 9: #include "../h/param.h" ! 10: #include "../h/buf.h" ! 11: #include "../h/cmap.h" ! 12: #include "../h/conf.h" ! 13: #include "../h/dir.h" ! 14: #include "../h/dk.h" ! 15: #include "../h/map.h" ! 16: #include "../machine/mtpr.h" ! 17: #include "../machine/pte.h" ! 18: #include "../h/systm.h" ! 19: #include "../vba/vbavar.h" ! 20: #include "../h/user.h" ! 21: #include "../h/vmmac.h" ! 22: #include "../h/proc.h" ! 23: #include "../h/uio.h" ! 24: #include "../vba/vddc.h" ! 25: ! 26: int vddebug = 1; /* if = 1, error messages are printed on the console */ ! 27: int vdintflg = 0; /* if = 1, interrupts are handled by the driver, ! 28: * otherwise they are just ignored. (during setup) */ ! 29: ! 30: static struct size FSD[] = { ! 31: 9600, 0, /* minor 0/ 8/16/24 = fsd0a - fsd3a - cyl 0 - 59*/ ! 32: 12000, 9600, /* minor 1/ 9/17/25 = fsd0b - fsd3b - cyl 60 - 134*/ ! 33: 108480, 21600, /* minor 2/10/18/26 = fsd0c - fsd3c - cyl 135 - 812*/ ! 34: 1600, 130080, /* minor 3/11/19/27 = fsd0d - fsd3d - cyl 813 - 822*/ ! 35: 130080, 0, /* minor 4/12/20/28 = fsd0e - fsd3e - cyl 0 - 812*/ ! 36: 131680, 0, /* minor 5/13/21/29 = fsd0f - fsd3f - cyl 0 - 822*/ ! 37: 0, 0, /* Non existent minor device */ ! 38: 0, 0, /* Non existent minor device */ ! 39: 0, 0, /* Non existent minor device */ ! 40: 0, 0, /* Non existent minor device */ ! 41: 0, 0, /* Non existent minor device */ ! 42: 0, 0, /* Non existent minor device */ ! 43: 0, 0, /* Non existent minor device */ ! 44: 0, 0, /* Non existent minor device */ ! 45: 0, 0, /* Non existent minor device */ ! 46: 0, 0, /* Non existent minor device */ ! 47: }; ! 48: ! 49: static struct size SMD[]= { ! 50: 20064, 0, /* minor 32/40/48/56 = smd0a - smd3a cyl 0- 65 */ ! 51: 13680, 20064, /* minor 33/41/49/57 = smd0b - smd3b cyl 66- 110 */ ! 52: 214928, 33744, /* minor 34/42/50/58 = smd0c - smd3c cyl 111-817 */ ! 53: 1520, 248672, /* minor 35/43/51/59 = smd0d - smd3d cyl 818-822 */ ! 54: 248672, 0, /* minor 36/44/52/60 = smd0e - smd3e cyl 0-817 */ ! 55: 250192, 0, /* minor 37/45/53/61 = smd0f - smd3f cyl 0-822 */ ! 56: 0, 0, /* minor 38/46/54/62 = smd0g - smd3g */ ! 57: 0, 0, /* minor 39/47/55/63 = smd0h - smd3h */ ! 58: 0, 0, /* Non existent minor device */ ! 59: 0, 0, /* Non existent minor device */ ! 60: 0, 0, /* Non existent minor device */ ! 61: 0, 0, /* Non existent minor device */ ! 62: 0, 0, /* Non existent minor device */ ! 63: 0, 0, /* Non existent minor device */ ! 64: 0, 0, /* Non existent minor device */ ! 65: 0, 0, /* Non existent minor device */ ! 66: }; ! 67: ! 68: static struct size XFSD[] = { ! 69: 20352, 0, /* minor 64/72/80/88 = xfsd0a - xfsd3a cyl 0- 52 */ ! 70: 20352, 20352, /* minor 65/73/81/89 = xfsd0b - xfsd3b cyl 53- 105 */ ! 71: 230400, 40704, /* minor 66/74/82/90 = xfsd0c - xfsd3c cyl 106-705 */ ! 72: 1920, 271104, /* minor 67/75/83/91 = xfsd0d - xfsd3d cyl 706-710 */ ! 73: 271104, 0, /* minor 68/76/84/92 = xfsd0e - xfsd3e cyl 0-705 */ ! 74: 273024, 0, /* minor 69/77/85/93 = xfsd0f - xfsd3f cyl 0-710 */ ! 75: 0, 0, /* minor 70/78/86/94 = xfsd0g - xfsd3g */ ! 76: 0, 0, /* minor 71/79/87/95 = xfsd0h - xfsd3h */ ! 77: 0, 0, /* Non existent minor device */ ! 78: 0, 0, /* Non existent minor device */ ! 79: 0, 0, /* Non existent minor device */ ! 80: 0, 0, /* Non existent minor device */ ! 81: 0, 0, /* Non existent minor device */ ! 82: 0, 0, /* Non existent minor device */ ! 83: 0, 0, /* Non existent minor device */ ! 84: 0, 0, /* Non existent minor device */ ! 85: }; ! 86: ! 87: /* ! 88: /* ! 89: /* Layout of major/minor number assignments for the VDDC devices. ! 90: /* ! 91: /* 1 ! 92: /* 5 8 7 4 3 2 0 ! 93: /* +----------------+------+---+-----+ ! 94: /* | Major device # | TYPE | D | FLS | ! 95: /* +----------------+------+---+-----+ ! 96: /* | | |_____ File system # ( 0-7 ) ! 97: /* | |__________ Drive # (0-3) ! 98: /* |________________ Drive type ( 0-FSD, 1-SMD ) ! 99: /* ( 2-XFSD ) (obsolete) ! 100: /* ! 101: /********************************************************/ ! 102: ! 103: #define VDUNIT(x) ((minor(x) & 0x18) >> 3) ! 104: #define DRVTYPE(x) ((minor(x) & 0xe0) >> 5) (obsolete) ! 105: #define FLSYS(x) (minor(x) & 0x07) ! 106: #define PHYS(x) ( vtoph( &proc[2], (int) (x) ) ) ! 107: ! 108: ! 109: /* Drive types should be in order of drive capacity for auto-configuration */ ! 110: /* e.g: smallest capacity = drive type 0, highest capacity = type NXPDRV-1 */ ! 111: ! 112: struct vdst { ! 113: short nsect; ! 114: short ntrak; ! 115: short nspc; ! 116: short ncyl; ! 117: struct size *sizes; ! 118: short dtype; /* type as in byte 5 (drive) of iopb */ ! 119: char *name; /* drive name for autoconf */ ! 120: } vdst[] = { ! 121: ! 122: 16, 10, 16*10, 823, FSD, 0, "160 Mb FSD " , ! 123: 16, 19, 16*19, 823, SMD, 1, "300 Mb SMD " , ! 124: 16, 24, 16*24, 711, XFSD, 2, "340 Mb FSD " ! 125: }; ! 126: ! 127: ! 128: struct vba_ctlr *vdminfo[NVDDC]; ! 129: struct vba_device *vddinfo[NUNIT]; ! 130: ! 131: /* ! 132: ** Internal Functions ! 133: */ ! 134: int vdopen(); ! 135: int vdclose(); ! 136: int vdprobe(); /* See if VDDC is really there */ ! 137: int vd_setup(); /* Called from vdprobe */ ! 138: int vdslave(); /* See if drive is really there */ ! 139: int vdattach(); ! 140: int vddgo(); ! 141: int vdstrategy(); /* VDDC strategy routine */ ! 142: int vdstart(); /* Top level interface to device queue */ ! 143: int vdintr(); /* Top Level ISR */ ! 144: int vdread(); /* raw i/o read routine */ ! 145: int vdwrite(); /* raw i/o write routine */ ! 146: int vddump(); /* dump routine */ ! 147: int vdsize(); /* sizes for swapconfig */ ! 148: ! 149: long vdstd[] = { ! 150: 0x0f2000 }; ! 151: ! 152: struct vba_driver vddriver = ! 153: { ! 154: vdprobe, vdslave, vdattach, vddgo, vdstd, ! 155: "smd/fsd", vddinfo, "VSMD controller ", vdminfo ! 156: }; ! 157: ! 158: struct buf vdutab[NUNIT]; ! 159: struct buf rvdbuf[NUNIT]; ! 160: char vdbuf[SECTSIZ*2]; ! 161: extern char vdutl[]; ! 162: ! 163: /* ! 164: ** Disk Address ! 165: */ ! 166: struct dskadr { ! 167: char track; /* all 8 bits */ ! 168: char sector; /* low order 5 bits */ ! 169: short cylinder; /* low order 12 bits */ ! 170: }; ! 171: ! 172: /* ! 173: ** DCB Trailer Formats ! 174: **********************************/ ! 175: ! 176: /* ! 177: ** Read / Write Trailer ! 178: */ ! 179: struct trrw { ! 180: char *memadr; /* memory address */ ! 181: long wcount; /* 16 bit word count */ ! 182: struct dskadr disk; /* disk address */ ! 183: long scat[MAXBPTE*2+1]; /* gather/scatter trailer */ ! 184: }; ! 185: ! 186: /* ! 187: ** Format Trailer ! 188: */ ! 189: struct trfmt { ! 190: char *addr; /* data buffer to be filled on sector*/ ! 191: long nsectors; /* # of sectors to be formatted */ ! 192: struct dskadr disk; ! 193: struct dskadr hdr; ! 194: }; ! 195: ! 196: /* ! 197: ** Reset / Configure Trailer ! 198: */ ! 199: struct treset { ! 200: long ncyl; /* # cylinders */ ! 201: long nsurfaces; /* # surfaces */ ! 202: }; /* # of sectors is defined by VDDC */ ! 203: /* to be 32/track of 512 data bytes each */ ! 204: ! 205: /* ! 206: ** Seek Trailer ! 207: */ ! 208: struct trseek { ! 209: struct dskadr disk; ! 210: }; ! 211: ! 212: /* ! 213: ** DCB Format ! 214: */ ! 215: struct fmt_dcb { ! 216: struct fmt_dcb *nxtdcb; /* next dcb in chain or End of Chain */ ! 217: short intflg; /* interrupt settings and flags */ ! 218: short opcode; /* DCB Command code etc... */ ! 219: long operrsta; /* Error & Status info */ ! 220: short fill; /* not used */ ! 221: char devselect; /* Drive selection */ ! 222: char trailcnt; /* Trailer Word Count */ ! 223: long err_memadr; /* Error memory address */ ! 224: short fill2; ! 225: short err_wcount; /* Error word count */ ! 226: short err_track; /* Error track/sector */ ! 227: short err_cyl; /* Error cylinder adr */ ! 228: union { ! 229: struct trrw rwtrail; /* read/write trailer */ ! 230: struct trfmt fmtrail; /* format trailer */ ! 231: struct treset resetrail; /* reset/configure trailer */ ! 232: struct trseek seektrail; /* seek trailer */ ! 233: } trail; ! 234: }; ! 235: ! 236: /* ! 237: ** MDCB Format ! 238: */ ! 239: struct fmt_mdcb { ! 240: struct fmt_dcb *firstdcb; /* first dcb in chain */ ! 241: struct fmt_dcb *procdcb; /* dcb being processed */ ! 242: struct fmt_dcb *intdcb; /* dcb causing interrupt */ ! 243: long vddcstat; /* VDDC status */ ! 244: }mdcbx; ! 245: ! 246: /* ! 247: ** MDCB ! 248: */ ! 249: struct fmt_mdcb *mdcb = &mdcbx; ! 250: ! 251: /* ! 252: ** DCB ! 253: */ ! 254: ! 255: struct fmt_dcb dcbx[NVDDC]; ! 256: ! 257: int vdtimeout; ! 258: #define POLLTILLDONE(x) { vdtimeout = 1000*(x); \ ! 259: uncache((char *)&dcb->operrsta); \ ! 260: while (! (dcb->operrsta & DCBCMP)) { \ ! 261: DELAY(1000); \ ! 262: vdtimeout--; \ ! 263: uncache((char *)&dcb->operrsta); \ ! 264: if (vdtimeout <=0) { \ ! 265: printf("VDDC controller timeout\n"); \ ! 266: return(0); \ ! 267: } \ ! 268: } \ ! 269: } ! 270: ! 271: /* ! 272: ** See if the controller is really there. ! 273: ** if TRUE - initialize the controller. ! 274: */ ! 275: vdprobe(cntrl_vaddr) ! 276: caddr_t cntrl_vaddr; ! 277: { ! 278: if ( badaddr(cntrl_vaddr,2) ) return(0); /* no controller */ ! 279: else ! 280: if (vd_setup(cntrl_vaddr)) /* initialize the controller */ ! 281: return(1); ! 282: else return(0); /* initialization error */ ! 283: } ! 284: ! 285: vd_setup(cntrl_vaddr) ! 286: caddr_t cntrl_vaddr; ! 287: { ! 288: register struct fmt_dcb *dcb = &dcbx[0]; ! 289: int j; ! 290: ! 291: VDDC_RESET(cntrl_vaddr); /* Reset the controller */ ! 292: /* Burn some time ...... needed after accessing reset port */ ! 293: for (j=0; j<20; j++) ! 294: DELAY(1000); ! 295: ! 296: /* setup & issue INIT to initialize VDDC */ ! 297: ! 298: dcb->opcode = INIT; ! 299: dcb->nxtdcb = (struct fmt_dcb *)0; ! 300: dcb->intflg = NOINT; ! 301: mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); ! 302: dcb->operrsta = 0; ! 303: VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ ! 304: POLLTILLDONE(1) /* poll till done */ ! 305: if (dcb->operrsta & HRDERR) { ! 306: if (vddebug) ! 307: printf("VDDC INIT error. Status = %x\n",dcb->operrsta); ! 308: return(0); ! 309: } ! 310: /* setup & issue DIAGNOSE */ ! 311: ! 312: dcb->opcode = DIAG; ! 313: dcb->nxtdcb = (struct fmt_dcb *)0; ! 314: dcb->intflg = NOINT; ! 315: mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); ! 316: dcb->operrsta = 0; ! 317: VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ ! 318: POLLTILLDONE(1) /* poll till done */ ! 319: if (dcb->operrsta & HRDERR) { ! 320: if (vddebug) ! 321: printf("VDDC DIAGNOSE error. Status = %x\n",dcb->operrsta); ! 322: return(0); ! 323: } ! 324: /* Start drives command */ ! 325: /* ! 326: /* dcb->opcode = VDSTART; ! 327: /* dcb->nxtdcb = (struct fmt_dcb *)0; ! 328: /* dcb->intflg = NOINT; ! 329: /* mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); ! 330: /* dcb->operrsta = 0; ! 331: /* VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ ! 332: /* POLLTILLDONE(20) /* poll till done */ ! 333: /* if (dcb->operrsta & HRDERR) { ! 334: /* if (vddebug) ! 335: /* printf("VDDC START DRIVES error. Status = %x\n",dcb->operrsta); ! 336: /* return(0); ! 337: /* } ! 338: /**/ ! 339: return(1); ! 340: } ! 341: ! 342: /* ! 343: * See if a drive is really there ! 344: * Try to Reset/Configure the drive, then test its status. ! 345: */ ! 346: vdslave(ui,cntrl_vaddr) ! 347: register struct vba_device *ui; ! 348: register caddr_t cntrl_vaddr; ! 349: { ! 350: register struct fmt_dcb *dcb = &dcbx[0]; ! 351: register struct vdst *st; ! 352: int dsktype; ! 353: ! 354: /* ! 355: ** check drive status - see if drive exists. ! 356: */ ! 357: dcb->opcode = VDSTATUS; ! 358: dcb->intflg = NOINT; ! 359: dcb->operrsta = 0; ! 360: dcb->devselect = (char)ui->ui_slave; ! 361: dcb->trailcnt = (char)0; ! 362: mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); ! 363: mdcb->vddcstat = 0; ! 364: VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb)) /* do it */ ! 365: POLLTILLDONE(5) ! 366: /* ! 367: if (dcb->operrsta & HRDERR) { ! 368: if (vddebug) ! 369: printf("VDDC STATUS error. Status = %x, drive %d\n",dcb->operrsta,ui->ui_slave); ! 370: return(0); ! 371: } ! 372: */ ! 373: uncache((char *)&mdcb->vddcstat); ! 374: if (mdcb->vddcstat & DRVNRDY) return(0); /* not ready-> non existent */ ! 375: ! 376: /* ! 377: * drive is alive, now get its type! ! 378: * Seek on all drive types starting from the largest one. ! 379: * a sucessful seek to the last sector/cylinder/track verifies ! 380: * the drive type connected to this port. ! 381: */ ! 382: for (dsktype = NVDDRV-1; dsktype >= 0; dsktype--) { ! 383: st = &vdst[dsktype]; ! 384: dcb->opcode = RSTCFG; /* configure drive command */ ! 385: dcb->intflg = NOINT; ! 386: dcb->operrsta = 0; ! 387: dcb->trail.resetrail.ncyl = st->ncyl; ! 388: dcb->trail.resetrail.nsurfaces = st->ntrak; ! 389: dcb->devselect = (char)ui->ui_slave; ! 390: dcb->trailcnt = (char)2; ! 391: mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); ! 392: VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ ! 393: POLLTILLDONE(3) ! 394: if (dcb->operrsta & HRDERR) { ! 395: if (vddebug) ! 396: printf("VDDC RESET/CONFIGURE error. Status = %x\n",dcb->operrsta); ! 397: return(0); ! 398: } ! 399: mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); ! 400: dcb->intflg = NOINT; ! 401: dcb->opcode = RD; ! 402: dcb->operrsta = 0; ! 403: dcb->devselect = (char)ui->ui_slave; ! 404: dcb->trailcnt = (char)3; ! 405: dcb->trail.rwtrail.memadr = (char *)PHYS(vdbuf); ! 406: dcb->trail.rwtrail.wcount = SECTSIZ; ! 407: dcb->trail.rwtrail.disk.cylinder = st->ncyl -2; ! 408: dcb->trail.rwtrail.disk.track = st->ntrak -1; ! 409: dcb->trail.rwtrail.disk.sector = 0; ! 410: VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ ! 411: POLLTILLDONE(3) ! 412: if ( (dcb->operrsta & HRDERR) == 0) ! 413: /* found the drive type! */ ! 414: break; ! 415: } ! 416: if (dsktype < 0) { ! 417: /* If reached here, a drive which is not defined in the ! 418: * 'vdst' tables is connected. Cannot set it's type. ! 419: */ ! 420: printf("VDDC error, unrecognized drive type, drive %d\n",ui->ui_slave); ! 421: return(0); ! 422: } ! 423: ui->ui_type = dsktype; ! 424: vddriver.ud_dname = st->name; ! 425: return(1); ! 426: } ! 427: ! 428: vdattach(ui) ! 429: struct vba_device *ui; ! 430: { ! 431: } ! 432: ! 433: vddgo(um) ! 434: struct vba_ctlr *um; ! 435: { ! 436: } ! 437: ! 438: #define b_cylin b_resid ! 439: ! 440: vdstrategy(bp) ! 441: register struct buf *bp; ! 442: { ! 443: register struct vba_device *ui; ! 444: register struct vba_ctlr *um; ! 445: register int unit; ! 446: register struct buf *dp; ! 447: register struct size *sizep; ! 448: int index, blocks, s; ! 449: ! 450: vdintflg = 1; /* enable interrupts handling by the driver */ ! 451: blocks = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; ! 452: if (bp->b_bcount > NBPG*MAXBPTE) { ! 453: printf ("VDDC I/O length error: %d\n", bp->b_bcount); ! 454: goto bad1; ! 455: } ! 456: unit = VDUNIT(bp->b_dev); ! 457: ui = vddinfo[unit]; ! 458: if (ui == 0 || ui->ui_alive == 0) goto bad1; ! 459: index = FLSYS(bp->b_dev); /* get file system index */ ! 460: sizep = vdst[ui->ui_type].sizes; ! 461: if (bp->b_blkno < 0 || ! 462: (dkblock(bp)+blocks > sizep[index].nblocks)) /* disk overflow */ ! 463: goto bad1; ! 464: s = spl8(); ! 465: dp = &vdutab[ui->ui_unit]; ! 466: bp->b_resid = bp->b_blkno ; /* block # plays same role as ! 467: cylinder # for disksort, as long ! 468: as increasing blocks correspond to ! 469: increasing cylinders on disk */ ! 470: ! 471: disksort(dp, bp); ! 472: if (dp->b_active == 0) { /* unit is on controller queue */ ! 473: /* put the device on the controller queue */ ! 474: dp->b_forw = NULL; /* end of queue indicator */ ! 475: um = ui->ui_mi; /* get controller structure !! */ ! 476: if (um->um_tab.b_actf == NULL) /* controller queue is empty */ ! 477: um->um_tab.b_actf = dp; ! 478: else ! 479: um->um_tab.b_actl->b_forw = dp; /* add into queue */ ! 480: um->um_tab.b_actl = dp; /* update queue tail */ ! 481: dp->b_active ++; ! 482: } ! 483: bp = &ui->ui_mi->um_tab; /* controller structure addr */ ! 484: if (bp->b_actf && /* cntrl queue not empty */ ! 485: bp->b_active == 0) /* controller not active */ ! 486: (void) vdstart(ui->ui_mi);/* go start I/O */ ! 487: splx(s); ! 488: return; ! 489: ! 490: bad1: ! 491: bp->b_flags |= B_ERROR; ! 492: iodone(bp); ! 493: return; ! 494: } ! 495: ! 496: ! 497: /* ! 498: * Start up a transfer on a drive. ! 499: */ ! 500: vdstart(um) ! 501: register struct vba_ctlr *um; ! 502: { ! 503: register struct buf *bp, *dp; ! 504: register struct fmt_dcb *dcb = &dcbx[um->um_ctlr]; ! 505: struct size *sizep; /* Pointer to one of the tables */ ! 506: register struct vdst *st; ! 507: register int index ; /* Index in the relevant table */ ! 508: register int phadr; /* Buffer's physical address */ ! 509: register caddr_t cntrl_vaddr = um->um_addr; ! 510: register struct proc *this_proc; ! 511: register long phaddr, vaddr, length, i; ! 512: register long *longp; ! 513: int sblock, unit; ! 514: ! 515: loop: ! 516: /* ! 517: * Pull a request off the controller queue ! 518: */ ! 519: if ((dp = um->um_tab.b_actf) == NULL) ! 520: return ; ! 521: if ((bp = dp->b_actf) == NULL) { ! 522: dp->b_active = 0; /* device removed from ctlr queue */ ! 523: um->um_tab.b_actf = dp->b_forw; ! 524: goto loop; ! 525: } ! 526: /* ! 527: * Mark controller busy, and ! 528: * prepare a command packet for the controller. ! 529: */ ! 530: um->um_tab.b_active++; ! 531: unit = VDUNIT(bp->b_dev); ! 532: st = &vdst[vddinfo[unit]->ui_type]; ! 533: index = FLSYS(bp->b_dev); ! 534: sizep = st->sizes; ! 535: mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); ! 536: dcb->intflg = INTDUN; /* interrupt on completion */ ! 537: ! 538: dcb->operrsta = 0; ! 539: dcb->devselect = VDUNIT(bp->b_dev); ! 540: sblock = sizep[index].block0 + bp->b_blkno; ! 541: dcb->trail.rwtrail.disk.cylinder = (short)(sblock / st->nspc); ! 542: dcb->trail.rwtrail.disk.track=(char)((sblock % st->nspc) / st->nsect); ! 543: dcb->trail.rwtrail.disk.sector = (char)(sblock*2 % (st->nsect*2)); ! 544: if (bp->b_flags & B_DIRTY || bp->b_proc==0) this_proc = &proc[2]; ! 545: else this_proc = bp->b_proc; ! 546: phaddr = vtoph(this_proc, bp->b_un.b_addr); /* start addresses */ ! 547: vaddr = (int)bp->b_un.b_addr; ! 548: length = (bp->b_bcount+1) & ~1; /* total # of bytes */ ! 549: printf("\nvaddr=%x length=%x\n", vaddr, length); ! 550: dcb->trail.rwtrail.memadr = (char *)phaddr; /* default trailer */ ! 551: printf("%x ", dcb->trail.rwtrail.memadr); ! 552: i = imin ( NBPG-(phaddr&PGOFSET),length); /* bytes in this page */ ! 553: dcb->trail.rwtrail.wcount = i/2; ! 554: if (i != 0x400) printf("/%x ", i/2); ! 555: dcb->trailcnt = 3; ! 556: /* ! 557: * If all required bytes fit into one page frame, that's it. ! 558: * Otherwise we have to generate a scatter/gather trailer. ! 559: */ ! 560: length -= i; ! 561: vaddr += i; ! 562: longp = dcb->trail.rwtrail.scat; /* 1'st pair address */ ! 563: while (length > 0) { ! 564: i = imin ( NBPG-(phaddr&PGOFSET),length); ! 565: *longp++ = i/2; ! 566: *longp++ = vtoph (this_proc, vaddr); ! 567: vaddr += i; ! 568: length -= i; ! 569: dcb->trailcnt += 2; ! 570: } ! 571: *longp++ = 0; /* End of list */ ! 572: *longp = 0; /* End of list */ ! 573: /*********** ! 574: dcb->trailcnt +=2 ; ! 575: ***********/ ! 576: if (bp->b_flags & B_READ) { /* Read or read&scatter */ ! 577: if (dcb->trailcnt == 3) dcb->opcode = RD; ! 578: else dcb->opcode = RAS; ! 579: } else { /* Write or gather&write */ ! 580: if (dcb->trailcnt == 3) dcb->opcode = WD; ! 581: else dcb->opcode = GAW; ! 582: } ! 583: while (longp >= (long *)dcb) ! 584: printf("%x\n", *longp--); ! 585: ! 586: #ifdef VDDCPERF ! 587: scope_out(1); ! 588: #endif ! 589: ! 590: VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb)) /* do it */ ! 591: } ! 592: ! 593: ! 594: /* ! 595: * Handle a disk interrupt. ! 596: */ ! 597: vdintr(vdnum) ! 598: register vdnum; ! 599: { ! 600: register struct buf *bp, *dp; ! 601: register struct vba_ctlr *um = vdminfo[vdnum]; ! 602: register struct fmt_dcb *dcb = &dcbx[vdnum]; ! 603: register int cnt; ! 604: ! 605: #ifdef VDDCPERF ! 606: scope_out(2); ! 607: #endif ! 608: printf("vddc 1\n"); ! 609: if (intenable == 0 || vdintflg == 0) /* ignore all interrupts */ ! 610: return; ! 611: if (um->um_tab.b_active == NULL) return;/* unexpected interrupt */ ! 612: uncache((char *)&mdcb->intdcb); ! 613: uncache((char *)&dcb->operrsta); ! 614: if ( mdcb->intdcb != (struct fmt_dcb *)PHYS(dcb)) { /* dcb causing interrupt */ ! 615: printf("VDDC error - dcb causing interrupt (%x) is different from expected dcb (%x) Interrupt ignored\n", mdcb->intdcb,dcb); ! 616: return; ! 617: } ! 618: if (! (dcb->operrsta & DCBCMP)) { /* unexpected interrupt */ ! 619: printf("VDDC Unexpected interrupt, DCB completed not set. Status = %x\n",dcb->operrsta); ! 620: return; ! 621: } ! 622: dp = um->um_tab.b_actf; /* device queue head in ctlr queue */ ! 623: bp = dp->b_actf; /* first buffer in device queue */ ! 624: if (dcb->operrsta & HRDERR) { ! 625: printf("VDDC hard error - dcb status = %x\n",dcb->operrsta); ! 626: bp->b_flags |= B_ERROR; ! 627: } ! 628: else if (dcb->operrsta & SFTERR) ! 629: printf("Soft error on VDDC,status = %x, dev=%x, block # %d\n", ! 630: dcb->operrsta, bp->b_dev, bp->b_blkno); ! 631: ! 632: /* ! 633: * If this was a read, we have to purge the data cache for the ! 634: * rigth virtual pages. It could be nice to just change the ! 635: * relevant process's data key but this key is in PCB, in _u, ! 636: * which can be on the disk right now. And besides, what about ! 637: * reads into the system space? There's no key to change there. ! 638: */ ! 639: if (bp->b_flags & B_READ) { ! 640: printf("vddc 2\n"); ! 641: if (dcb->opcode == RAS) { /* Multiple pages read */ ! 642: printf("vddc 3\n"); ! 643: for (cnt=bp->b_bcount; cnt>=0; cnt -= NBPG) ! 644: mtpr ((caddr_t)bp->b_un.b_addr+cnt-1, P1DC); ! 645: if ( ((int)bp->b_un.b_addr & PGOFSET) != 0 ) ! 646: mtpr ((caddr_t)bp->b_un.b_addr, P1DC); ! 647: } else { /* Only one page read */ ! 648: mtpr ((caddr_t)bp->b_un.b_addr, P1DC); ! 649: printf("vddc 4\n"); ! 650: } ! 651: } ! 652: ! 653: um->um_tab.b_active = 0; ! 654: um->um_tab.b_errcnt = 0; ! 655: if (dp->b_forw != NULL) { /* more than 1 unit on queue */ ! 656: um->um_tab.b_actf = dp->b_forw; /* next device on ctlr queue */ ! 657: dp->b_forw = um->um_tab.b_actl->b_forw; /* be last in queue */ ! 658: um->um_tab.b_actl->b_forw = dp; /* last points now to dp */ ! 659: um->um_tab.b_actl = dp; /* pointer in ctlr structure */ ! 660: } ! 661: dp->b_errcnt = 0; ! 662: dp->b_actf = bp->av_forw; /* remove first from queue */ ! 663: bp->b_resid = 0; /* All data read here */ ! 664: ! 665: #ifdef VDDCPERF ! 666: scope_out(3); ! 667: #endif ! 668: ! 669: printf("vddc 5\n"); ! 670: iodone(bp); ! 671: printf("vddc 6\n"); ! 672: vdstart(um); /* start requests for next device on queue */ ! 673: printf("vddc 7\n"); ! 674: } ! 675: ! 676: ! 677: vdread(dev, uio) ! 678: dev_t dev; ! 679: struct uio *uio; ! 680: { ! 681: register int unit = VDUNIT(dev); ! 682: register int error; ! 683: ! 684: if (unit >= NUNIT) return ( ENXIO ); ! 685: else return ! 686: (physio(vdstrategy, &rvdbuf[unit], dev, B_READ, minphys, uio)); ! 687: } ! 688: ! 689: vdwrite(dev, uio) ! 690: dev_t dev; ! 691: struct uio *uio; ! 692: { ! 693: register int unit = VDUNIT(dev); ! 694: register int error; ! 695: ! 696: if (unit >= NUNIT) return (ENXIO); ! 697: else return ! 698: (physio(vdstrategy, &rvdbuf[unit], dev, B_WRITE,minphys, uio)); ! 699: } ! 700: ! 701: #define DUMPSIZE 32 /* Up to 32k at a time - controller limit */ ! 702: ! 703: vddump(dev) ! 704: dev_t dev; ! 705: /* ! 706: * Dump the main memory to the given device. ! 707: */ ! 708: { ! 709: register struct vba_ctlr *um; ! 710: register struct fmt_dcb *dcb = &dcbx[0]; ! 711: register struct vdst *st; ! 712: register int unit; ! 713: register caddr_t cntrl_vaddr ; ! 714: register struct size *sizep; /* Pointer to one of the tables */ ! 715: int index,sblock,blkcount,thiscount; ! 716: int memaddr; ! 717: ! 718: unit = VDUNIT(dev); ! 719: um = (vddinfo[unit])->ui_mi; ! 720: st = &vdst[(vddinfo[unit])->ui_type]; ! 721: dcb = &dcbx[um->um_ctlr]; ! 722: cntrl_vaddr = um->um_addr; ! 723: memaddr = 0x0; ! 724: index = FLSYS(dev); ! 725: sizep = st->sizes; ! 726: blkcount = maxfree - 2; /* In 1k byte pages */ ! 727: if (dumplo + blkcount > sizep[index].nblocks) return(EINVAL); ! 728: sblock = sizep[index].block0 + dumplo; ! 729: while (blkcount > 0) { ! 730: thiscount = MIN (blkcount, DUMPSIZE); ! 731: mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); ! 732: dcb->intflg = NOINT; ! 733: dcb->opcode = WD; ! 734: dcb->operrsta = 0; ! 735: dcb->devselect = unit; ! 736: dcb->trailcnt = (char)3; ! 737: dcb->trail.rwtrail.memadr = (char *)memaddr; ! 738: dcb->trail.rwtrail.wcount = thiscount*512; ! 739: dcb->trail.rwtrail.disk.cylinder= (short)(sblock/st->nspc); ! 740: dcb->trail.rwtrail.disk.track = (char)((sblock % st->nspc) ! 741: / st->nsect); ! 742: dcb->trail.rwtrail.disk.sector = (char)(sblock*2 % (st->nsect*2)); ! 743: VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ ! 744: POLLTILLDONE(5); ! 745: if (dcb->operrsta & HRDERR) { ! 746: if (vddebug) ! 747: printf("VDDC DUMP error. Status = %x\n", ! 748: dcb->operrsta); ! 749: return(EIO); ! 750: }; ! 751: blkcount -= thiscount; ! 752: memaddr += thiscount*NBPG; ! 753: sblock += thiscount; ! 754: } ! 755: return(0); ! 756: } ! 757: ! 758: vdopen(dev, flag) ! 759: register dev_t dev; ! 760: int flag; ! 761: { ! 762: register struct vba_device *ui; ! 763: register unit = VDUNIT(dev); ! 764: ! 765: ui = vddinfo[unit]; ! 766: if (ui == 0 || ui->ui_alive == 0 || ui->ui_type >= NVDDRV) ! 767: return ENXIO; ! 768: return 0; ! 769: } ! 770: ! 771: vdsize(dev) ! 772: register dev_t dev; ! 773: { ! 774: register struct vba_device *ui; ! 775: register unit = VDUNIT(dev); ! 776: ! 777: ui = vddinfo[unit]; ! 778: if (ui == 0 || ui->ui_alive == 0 || ui->ui_type >= NVDDRV) ! 779: return -1; ! 780: return vdst[ui->ui_type].sizes[FLSYS(dev)].nblocks; ! 781: } ! 782: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.