|
|
1.1 ! root 1: /* ! 2: ** Stand alone driver for the VDDC controller ! 3: ** TAHOE Version, Oct 1983. ! 4: ** ! 5: */ ! 6: ! 7: #include "../machine/mtpr.h" ! 8: #include "../h/param.h" ! 9: #include "../h/inode.h" ! 10: #include "../h/fs.h" ! 11: #define VDGENDATA 1 ! 12: #include "../vba/vddc.h" ! 13: #undef VDGENDATA ! 14: #include "../stand/saio.h" ! 15: ! 16: #define NVD 4 /* Max number of controllers */ ! 17: ! 18: #define TRUE 1 ! 19: #define FALSE 0 ! 20: #define VDUNIT(x) (minor(x) & 0x3) ! 21: #define VDCTLR(x) (minor(x) >> 2) ! 22: ! 23: /* ! 24: ** MDCB ! 25: */ ! 26: ! 27: fmt_mdcb mdcb; ! 28: ! 29: /* ! 30: ** DCB ! 31: */ ! 32: ! 33: fmt_dcb dcb; ! 34: ! 35: /* ! 36: ** Unit specific information. ! 37: */ ! 38: ! 39: struct { ! 40: char configured; ! 41: fs_tab info; ! 42: }unit_info[NVD][16]; ! 43: ! 44: /* ! 45: ** Controller specific information. ! 46: */ ! 47: ! 48: struct { ! 49: unsigned char ctlr_type; ! 50: char *ctlr_name; ! 51: unsigned char initialized; ! 52: unsigned char ctlr_started; ! 53: } ctlr_info[NVD]; ! 54: ! 55: static char junk[1024]; ! 56: ! 57: ! 58: /* ! 59: ** ! 60: */ ! 61: ! 62: vdopen(io) ! 63: register struct iob *io; ! 64: { ! 65: register int ctlr = VDCTLR(io->i_unit); ! 66: register int unit = VDUNIT(io->i_unit); ! 67: register int i, j; ! 68: ! 69: /* Make sure controller number is in range */ ! 70: if(ctlr >= NVD) { ! 71: printf("vd%d: Unit number can't be greater than %x!\n", ! 72: io->i_unit, (NVD * 4) - 1); ! 73: _stop(""); ! 74: } ! 75: /* check file system for validity */ ! 76: if((io->i_boff < 0) || (io->i_boff > 5)) { ! 77: printf("vd%d: File system #%d, should be less than #6.\n", ! 78: io->i_unit, io->i_boff); ! 79: _stop(""); ! 80: } ! 81: if(!ctlr_info[ctlr].initialized) { ! 82: vdinit(io); /* initialize controller/drive */ ! 83: ctlr_info[ctlr].initialized = TRUE; ! 84: for(i=0; i<NVD; i++) ! 85: for(j=0; j<16; j++) ! 86: unit_info[i][j].configured = FALSE; ! 87: } ! 88: if(!unit_info[ctlr][unit].configured) { ! 89: vdconfigure_drive(io); ! 90: unit_info[ctlr][unit].configured = TRUE; ! 91: } ! 92: io->i_boff = unit_info[ctlr][unit].info.partition[io->i_boff].par_start; ! 93: } ! 94: ! 95: ! 96: /* ! 97: ** ! 98: */ ! 99: ! 100: vdinit(io) ! 101: register struct iob *io; ! 102: { ! 103: register int ctlr = VDCTLR(io->i_unit); ! 104: register int unit = VDUNIT(io->i_unit); ! 105: register cdr *ctlr_addr = (cdr *)(vddcaddr[ctlr]+IOBASE); ! 106: register char *ctlr_type; ! 107: ! 108: /* Check to see if controller is really there */ ! 109: if(badaddr(ctlr_addr, 2)) { ! 110: printf("vd%d: Controller %d is non-existant!\n", ! 111: io->i_unit, ctlr); ! 112: _stop(""); ! 113: } ! 114: /* Probe further to find what kind of controller it is */ ! 115: ctlr_addr->cdr_reset = 0xffffffff; ! 116: DELAY(1000000); ! 117: /* Probe further to find what kind of controller it is */ ! 118: if(ctlr_addr->cdr_reset != 0xffffffff) { ! 119: ctlr_info[ctlr].ctlr_type = SMDCTLR; ! 120: ctlr_info[ctlr].ctlr_name = "SMD"; ! 121: DELAY(1000000); ! 122: } ! 123: else { ! 124: ctlr_info[ctlr].ctlr_type = SMD_ECTLR; ! 125: ctlr_info[ctlr].ctlr_name = "SMD/E"; ! 126: ctlr_addr->cdr_reserved = 0x0; ! 127: DELAY(3000000); ! 128: } ! 129: if(ctlr_info[ctlr].ctlr_type == SMD_ECTLR) { ! 130: ctlr_addr->cdr_csr = 0; ! 131: ctlr_addr->mdcb_tcf = AM_ENPDA; ! 132: ctlr_addr->dcb_tcf = AM_ENPDA; ! 133: ctlr_addr->trail_tcf = AM_ENPDA; ! 134: ctlr_addr->data_tcf = AM_ENPDA; ! 135: ctlr_addr->cdr_ccf = CCF_STS | XMD_32BIT | BSZ_16WRD | ! 136: CCF_ENP | CCF_EPE /* | CCF_EDE */ | CCF_ECE | CCF_ERR; ! 137: } ! 138: if(vdaccess_with_no_trailer(io, INIT, 8) & HRDERR) { ! 139: vdprint_error(io->i_unit, "Initialization error", ! 140: dcb.operrsta,dcb.err_code); ! 141: _stop(""); ! 142: } ! 143: if(vdaccess_with_no_trailer(io, DIAG, 8) & HRDERR) { ! 144: vdprint_error(io->i_unit, "Diagnostic error", ! 145: dcb.operrsta, dcb.err_code); ! 146: _stop(""); ! 147: } ! 148: } ! 149: ! 150: ! 151: /* ! 152: ** ! 153: */ ! 154: ! 155: vdconfigure_drive(io) ! 156: register struct iob *io; ! 157: { ! 158: register int ctlr = VDCTLR(io->i_unit); ! 159: register int unit = VDUNIT(io->i_unit); ! 160: register fs_tab *file_sys; ! 161: dskadr daddr; ! 162: register int i; ! 163: ! 164: for(i=0; i < nvddrv; i++) { ! 165: unit_info[ctlr][unit].info = vdst[i]; ! 166: if(ctlr_info[ctlr].ctlr_type == SMDCTLR) ! 167: if(unit_info[ctlr][unit].info.nsec != 32) ! 168: continue; ! 169: vdconfigure(io, 0); ! 170: daddr.cylinder = unit_info[ctlr][unit].info.ncyl - 2; ! 171: daddr.track = unit_info[ctlr][unit].info.ntrak - 1; ! 172: daddr.sector = unit_info[ctlr][unit].info.nsec - 1; ! 173: io->i_ma = junk; ! 174: io->i_cc = unit_info[ctlr][unit].info.secsize; ! 175: if(!(vdaccess(io, &daddr, RD) & HRDERR)) ! 176: return; ! 177: } ! 178: printf("vd%d: Unrecognizable drive; controller %d, unit %d!\n", ! 179: io->i_unit, ctlr, unit); ! 180: _stop(""); ! 181: } ! 182: ! 183: ! 184: /* ! 185: ** ! 186: */ ! 187: ! 188: vdstart_drive(io) ! 189: register struct iob *io; ! 190: { ! 191: register int ctlr = VDCTLR(io->i_unit); ! 192: register int unit = VDUNIT(io->i_unit); ! 193: register int io_unit_save = io->i_unit; ! 194: ! 195: if(ctlr_info[ctlr].ctlr_started) { ! 196: DELAY(5500000); ! 197: return TRUE; ! 198: } ! 199: io->i_unit &= ~3; ! 200: if(vdaccess_with_no_trailer(io, VDSTART, ((unit * 6) + 62)) & HRDERR) { ! 201: vdprint_error(io->i_unit, "Start error", ! 202: dcb.operrsta, dcb.err_code); ! 203: _stop(""); ! 204: } ! 205: ctlr_info[ctlr].ctlr_started = TRUE; ! 206: io->i_unit = io_unit_save; ! 207: DELAY((unit * 5500000) + 62000000); ! 208: return TRUE; ! 209: } ! 210: ! 211: ! 212: /* ! 213: ** This routine actually configures a particular drive. ! 214: ** ! 215: ** If the controller is an SMD/E controller then the number of sectors per ! 216: ** track is loaded into the appropriate register, otherwise it is left ! 217: ** alone because the old SMD controller requires a constant 32 sectors ! 218: ** per track for it's drives. (an error would be returned if the value is ! 219: ** loaded.) ! 220: ** ! 221: ** In the stand-alone spirit of things the system is halted if an error ! 222: ** occurs during this operation. ! 223: */ ! 224: ! 225: vdconfigure(io, pass) ! 226: register struct iob *io; ! 227: int pass; ! 228: { ! 229: register int ctlr = VDCTLR(io->i_unit); ! 230: register int unit = VDUNIT(io->i_unit); ! 231: register cdr *ctlr_addr = (cdr *)(vddcaddr[ctlr]+IOBASE); ! 232: ! 233: dcb.opcode = RSTCFG; /* command */ ! 234: dcb.intflg = NOINT; ! 235: dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ ! 236: dcb.operrsta = 0; ! 237: dcb.devselect = (char)unit; ! 238: dcb.trail.rstrail.ncyl = unit_info[ctlr][unit].info.ncyl; ! 239: dcb.trail.rstrail.nsurfaces = unit_info[ctlr][unit].info.ntrak; ! 240: if(ctlr_info[ctlr].ctlr_type == SMD_ECTLR) { ! 241: dcb.trailcnt = (char)4; ! 242: dcb.trail.rstrail.nsectors = unit_info[ctlr][unit].info.nsec; ! 243: dcb.trail.rstrail.slip_sec = unit_info[ctlr][unit].info.nslip; ! 244: } ! 245: else ! 246: dcb.trailcnt = (char)2; ! 247: mdcb.firstdcb = &dcb; ! 248: mdcb.vddcstat = 0; ! 249: VDDC_ATTENTION(ctlr_addr, &mdcb, ctlr_info[ctlr].ctlr_type); ! 250: POLLTILLDONE(ctlr_addr,&dcb,5,ctlr_info[ctlr].ctlr_type); ! 251: if(vdtimeout <= 0) ! 252: _stop(" during drive configuration.\n"); ! 253: if(dcb.operrsta & (NOTCYLERR | DRVNRDY)) ! 254: if(!pass) { ! 255: vdstart_drive(io); ! 256: vdconfigure(io, 1); ! 257: } ! 258: if(dcb.operrsta & HRDERR) { ! 259: vdprint_error(io->i_unit, "Configuration error", ! 260: dcb.operrsta, dcb.err_code); ! 261: _stop(""); ! 262: } ! 263: } ! 264: ! 265: ! 266: /* ! 267: ** Strategy is called to the actual I/O to the disk drives. ! 268: ** ! 269: ** Some simple checks are made to make sure we don't do anything rediculus, ! 270: ** If everything is sane then the request is issued. ! 271: ** ! 272: ** If no errors occured then the original byte count is returned, ! 273: ** otherwise -1 is returned to indicate an error occured. ! 274: */ ! 275: ! 276: vdstrategy(io, func) ! 277: register struct iob *io; ! 278: register int func; ! 279: { ! 280: dskadr daddr; ! 281: register int ctlr = VDCTLR(io->i_unit); ! 282: register int unit = VDUNIT(io->i_unit); ! 283: register fs_tab *u_info = &unit_info[ctlr][unit].info; ! 284: register int op = (func == READ) ? RD : WD; ! 285: register int blk; ! 286: ! 287: if(io->i_cc == 0) ! 288: _stop("vd: Can't transfer zero length records!\n"); ! 289: if(io->i_cc > 0xffff) ! 290: _stop("vd: Can't transfer greater than 2 to the 16th bytes!\n"); ! 291: blk = io->i_bn * DEV_BSIZE / u_info->secsize; ! 292: daddr.sector = blk % u_info->nsec; ! 293: daddr.track = (blk / u_info->nsec) % u_info->ntrak; ! 294: daddr.cylinder = (blk/u_info->nsec) / u_info->ntrak; ! 295: if(vdaccess(io, &daddr, op) & HRDERR) { ! 296: vdprint_error(io->i_unit,"I/O error",dcb.operrsta,dcb.err_code); ! 297: return(-1); ! 298: } ! 299: mtpr(0,PADC); ! 300: return(io->i_cc); ! 301: } ! 302: ! 303: ! 304: ! 305: /* ! 306: ** ! 307: */ ! 308: ! 309: vdprint_error(unit, str, status, smde_status) ! 310: int unit; ! 311: char *str; ! 312: unsigned long status; ! 313: unsigned long smde_status; ! 314: { ! 315: printf("vd%d: %s; ", unit, str); ! 316: if(status & DRVNRDY) ! 317: printf("Drive is not ready"); ! 318: else if(status & INVDADR) ! 319: printf("Invalid disk address issued"); ! 320: else if(status & DNEMEM) ! 321: printf("Non-existent memory error"); ! 322: else if(status & PARERR) ! 323: printf("Main memory parity error"); ! 324: else if(status & OPABRT) ! 325: printf("Program aborted operation"); ! 326: else if(status & WPTERR) ! 327: printf("Drive is write protected"); ! 328: else if(status & DSEEKERR) ! 329: printf("Disk seek error"); ! 330: else if(status & UCDATERR) ! 331: printf("Uncorrectable data error"); ! 332: else if(status & CTLRERR) ! 333: printf("Controller faulted"); ! 334: else if(status & NOTCYLERR) ! 335: printf("Not on cylinder error"); ! 336: else if(status & INVCMD) ! 337: printf("Invalid command issued to controller"); ! 338: else ! 339: printf("Controller error"); ! 340: printf("! Status = 0x%x", status); ! 341: if(smde_status) ! 342: printf(" Error code = %x", smde_status); ! 343: printf("\n"); ! 344: } ! 345: ! 346: ! 347: /* ! 348: ** ! 349: */ ! 350: ! 351: vdaccess_with_no_trailer(io, function, time) ! 352: register struct iob *io; ! 353: register int function, time; ! 354: { ! 355: register int ctlr = VDCTLR(io->i_unit); ! 356: register cdr *ctlr_addr = (cdr *)(vddcaddr[ctlr]+IOBASE); ! 357: ! 358: dcb.opcode = function; /* command */ ! 359: dcb.intflg = NOINT; ! 360: dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ ! 361: dcb.operrsta = 0; ! 362: dcb.devselect = (char)VDUNIT(io->i_unit); ! 363: dcb.trailcnt = (char)0; ! 364: mdcb.firstdcb = &dcb; ! 365: mdcb.vddcstat = 0; ! 366: VDDC_ATTENTION(ctlr_addr, &mdcb, ctlr_info[ctlr].ctlr_type); ! 367: POLLTILLDONE(ctlr_addr,&dcb,time,ctlr_info[ctlr].ctlr_type); ! 368: if(vdtimeout <= 0) ! 369: _stop(" during initialization operation.\n"); ! 370: return dcb.operrsta; ! 371: } ! 372: ! 373: ! 374: /* ! 375: ** ! 376: */ ! 377: ! 378: vdaccess(io, daddr, func) ! 379: register struct iob *io; ! 380: dskadr *daddr; ! 381: int func; ! 382: { ! 383: register int ctlr = VDCTLR(io->i_unit); ! 384: register cdr *ctlr_addr = (cdr *)(vddcaddr[ctlr]+IOBASE); ! 385: ! 386: dcb.opcode = (short)func; /* format sector command */ ! 387: dcb.intflg = NOINT; ! 388: dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ ! 389: dcb.operrsta = 0; ! 390: dcb.devselect = (char)VDUNIT(io->i_unit); ! 391: dcb.trailcnt = (char)(sizeof(trrw) / 4); ! 392: dcb.trail.rwtrail.memadr = io->i_ma; ! 393: dcb.trail.rwtrail.wcount = ((io->i_cc + 1) / sizeof(short)); ! 394: dcb.trail.rwtrail.disk.cylinder = daddr->cylinder; ! 395: dcb.trail.rwtrail.disk.track = daddr->track; ! 396: dcb.trail.rwtrail.disk.sector = daddr->sector; ! 397: mdcb.firstdcb = &dcb; ! 398: mdcb.vddcstat = 0; ! 399: VDDC_ATTENTION(ctlr_addr, &mdcb, ctlr_info[ctlr].ctlr_type); ! 400: POLLTILLDONE(ctlr_addr, &dcb, 60, ctlr_info[ctlr].ctlr_type); ! 401: if(vdtimeout <= 0) ! 402: _stop(" during I/O operation.\n"); ! 403: return dcb.operrsta; ! 404: } ! 405: ! 406: /* ! 407: ** Print_dcb() dumps the MDCB and DCB for diagnostic purposes. This ! 408: ** routine is called whenever a fatal error is encountered. ! 409: */ ! 410: ! 411: vdprintdcb(ptr) ! 412: register long *ptr; ! 413: { ! 414: register long i; ! 415: register long trailer_count; ! 416: ! 417: printf("Dump of MDCB: "); ! 418: for(i=0; i<4; i++) ! 419: printf(" %lx", *(ptr+i)); ! 420: if(ptr = (long *)*ptr) { ! 421: printf(" and DCB:"); ! 422: trailer_count = *(ptr+3) & 0xff; ! 423: for(i=0; i<7+trailer_count; i++) { ! 424: uncache(ptr+i); ! 425: printf(" %lx", *(ptr+i)); ! 426: } ! 427: } ! 428: printf("\n"); ! 429: for(i=0; i<5000000; i++) ; ! 430: } ! 431:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.