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