1 /* vd.c 7.1 86/01/12 */ 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/vddcreg.h" 14 #undef VDGENDATA 15 #include "saio.h" 16 17 #define NVD 4 /* Max number of controllers */ 18 19 #define TRUE 1 20 #define FALSE 0 21 #define VDUNIT(x) (minor(x) & 0x3) 22 #define VDCTLR(x) (minor(x) >> 2) 23 24 /* 25 ** MDCB 26 */ 27 28 fmt_mdcb mdcb; 29 30 /* 31 ** DCB 32 */ 33 34 fmt_dcb dcb; 35 36 /* 37 ** Unit specific information. 38 */ 39 40 struct { 41 char configured; 42 fs_tab info; 43 }unit_info[NVD][16]; 44 45 /* 46 ** Controller specific information. 47 */ 48 49 struct { 50 unsigned char ctlr_type; 51 char *ctlr_name; 52 unsigned char initialized; 53 unsigned char ctlr_started; 54 } ctlr_info[NVD]; 55 56 static char junk[1024]; 57 58 59 /* 60 ** 61 */ 62 63 vdopen(io) 64 register struct iob *io; 65 { 66 register int ctlr = VDCTLR(io->i_unit); 67 register int unit = VDUNIT(io->i_unit); 68 register int i, j; 69 70 /* Make sure controller number is in range */ 71 if(ctlr >= NVD) { 72 printf("vd%d: Unit number can't be greater than %x!\n", 73 io->i_unit, (NVD * 4) - 1); 74 _stop(""); 75 } 76 /* check file system for validity */ 77 if((io->i_boff < 0) || (io->i_boff > 5)) { 78 printf("vd%d: File system #%d, should be less than #6.\n", 79 io->i_unit, io->i_boff); 80 _stop(""); 81 } 82 if(!ctlr_info[ctlr].initialized) { 83 vdinit(io); /* initialize controller/drive */ 84 ctlr_info[ctlr].initialized = TRUE; 85 for(i=0; i<NVD; i++) 86 for(j=0; j<16; j++) 87 unit_info[i][j].configured = FALSE; 88 } 89 if(!unit_info[ctlr][unit].configured) { 90 vdconfigure_drive(io); 91 unit_info[ctlr][unit].configured = TRUE; 92 } 93 io->i_boff = unit_info[ctlr][unit].info.partition[io->i_boff].par_start; 94 } 95 96 97 /* 98 ** 99 */ 100 101 vdinit(io) 102 register struct iob *io; 103 { 104 register int ctlr = VDCTLR(io->i_unit); 105 register int unit = VDUNIT(io->i_unit); 106 register cdr *ctlr_addr = (cdr *)(vddcaddr[ctlr]+IOBASE); 107 register char *ctlr_type; 108 109 /* Check to see if controller is really there */ 110 if(badaddr(ctlr_addr, 2)) { 111 printf("vd%d: Controller %d is non-existant!\n", 112 io->i_unit, ctlr); 113 _stop(""); 114 } 115 /* Probe further to find what kind of controller it is */ 116 ctlr_addr->cdr_reset = 0xffffffff; 117 DELAY(1000000); 118 /* Probe further to find what kind of controller it is */ 119 if(ctlr_addr->cdr_reset != 0xffffffff) { 120 ctlr_info[ctlr].ctlr_type = SMDCTLR; 121 ctlr_info[ctlr].ctlr_name = "SMD"; 122 DELAY(1000000); 123 } 124 else { 125 ctlr_info[ctlr].ctlr_type = SMD_ECTLR; 126 ctlr_info[ctlr].ctlr_name = "SMD/E"; 127 ctlr_addr->cdr_reserved = 0x0; 128 DELAY(3000000); 129 } 130 if(ctlr_info[ctlr].ctlr_type == SMD_ECTLR) { 131 ctlr_addr->cdr_csr = 0; 132 ctlr_addr->mdcb_tcf = AM_ENPDA; 133 ctlr_addr->dcb_tcf = AM_ENPDA; 134 ctlr_addr->trail_tcf = AM_ENPDA; 135 ctlr_addr->data_tcf = AM_ENPDA; 136 ctlr_addr->cdr_ccf = CCF_STS | XMD_32BIT | BSZ_16WRD | 137 CCF_ENP | CCF_EPE /* | CCF_EDE */ | CCF_ECE | CCF_ERR; 138 } 139 if(vdaccess_with_no_trailer(io, INIT, 8) & HRDERR) { 140 vdprint_error(io->i_unit, "Initialization error", 141 dcb.operrsta,dcb.err_code); 142 _stop(""); 143 } 144 if(vdaccess_with_no_trailer(io, DIAG, 8) & HRDERR) { 145 vdprint_error(io->i_unit, "Diagnostic error", 146 dcb.operrsta, dcb.err_code); 147 _stop(""); 148 } 149 } 150 151 152 /* 153 ** 154 */ 155 156 vdconfigure_drive(io) 157 register struct iob *io; 158 { 159 register int ctlr = VDCTLR(io->i_unit); 160 register int unit = VDUNIT(io->i_unit); 161 register fs_tab *file_sys; 162 dskadr daddr; 163 register int i; 164 165 for(i=0; i < nvddrv; i++) { 166 unit_info[ctlr][unit].info = vdst[i]; 167 if(ctlr_info[ctlr].ctlr_type == SMDCTLR) 168 if(unit_info[ctlr][unit].info.nsec != 32) 169 continue; 170 vdconfigure(io, 0); 171 daddr.cylinder = unit_info[ctlr][unit].info.ncyl - 2; 172 daddr.track = unit_info[ctlr][unit].info.ntrak - 1; 173 daddr.sector = unit_info[ctlr][unit].info.nsec - 1; 174 io->i_ma = junk; 175 io->i_cc = unit_info[ctlr][unit].info.secsize; 176 if(!(vdaccess(io, &daddr, RD) & HRDERR)) 177 return; 178 } 179 printf("vd%d: Unrecognizable drive; controller %d, unit %d!\n", 180 io->i_unit, ctlr, unit); 181 _stop(""); 182 } 183 184 185 /* 186 ** 187 */ 188 189 vdstart_drive(io) 190 register struct iob *io; 191 { 192 register int ctlr = VDCTLR(io->i_unit); 193 register int unit = VDUNIT(io->i_unit); 194 register int io_unit_save = io->i_unit; 195 196 if(ctlr_info[ctlr].ctlr_started) { 197 DELAY(5500000); 198 return TRUE; 199 } 200 io->i_unit &= ~3; 201 if(vdaccess_with_no_trailer(io, VDSTART, ((unit * 6) + 62)) & HRDERR) { 202 vdprint_error(io->i_unit, "Start error", 203 dcb.operrsta, dcb.err_code); 204 _stop(""); 205 } 206 ctlr_info[ctlr].ctlr_started = TRUE; 207 io->i_unit = io_unit_save; 208 DELAY((unit * 5500000) + 62000000); 209 return TRUE; 210 } 211 212 213 /* 214 ** This routine actually configures a particular drive. 215 ** 216 ** If the controller is an SMD/E controller then the number of sectors per 217 ** track is loaded into the appropriate register, otherwise it is left 218 ** alone because the old SMD controller requires a constant 32 sectors 219 ** per track for it's drives. (an error would be returned if the value is 220 ** loaded.) 221 ** 222 ** In the stand-alone spirit of things the system is halted if an error 223 ** occurs during this operation. 224 */ 225 226 vdconfigure(io, pass) 227 register struct iob *io; 228 int pass; 229 { 230 register int ctlr = VDCTLR(io->i_unit); 231 register int unit = VDUNIT(io->i_unit); 232 register cdr *ctlr_addr = (cdr *)(vddcaddr[ctlr]+IOBASE); 233 234 dcb.opcode = RSTCFG; /* command */ 235 dcb.intflg = NOINT; 236 dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 237 dcb.operrsta = 0; 238 dcb.devselect = (char)unit; 239 dcb.trail.rstrail.ncyl = unit_info[ctlr][unit].info.ncyl; 240 dcb.trail.rstrail.nsurfaces = unit_info[ctlr][unit].info.ntrak; 241 if(ctlr_info[ctlr].ctlr_type == SMD_ECTLR) { 242 dcb.trailcnt = (char)4; 243 dcb.trail.rstrail.nsectors = unit_info[ctlr][unit].info.nsec; 244 dcb.trail.rstrail.slip_sec = unit_info[ctlr][unit].info.nslip; 245 } 246 else 247 dcb.trailcnt = (char)2; 248 mdcb.firstdcb = &dcb; 249 mdcb.vddcstat = 0; 250 VDDC_ATTENTION(ctlr_addr, &mdcb, ctlr_info[ctlr].ctlr_type); 251 POLLTILLDONE(ctlr_addr,&dcb,5,ctlr_info[ctlr].ctlr_type); 252 if(vdtimeout <= 0) 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 = (cdr *)(vddcaddr[ctlr]+IOBASE); 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 POLLTILLDONE(ctlr_addr,&dcb,time,ctlr_info[ctlr].ctlr_type); 369 if(vdtimeout <= 0) 370 _stop(" during initialization operation.\n"); 371 return dcb.operrsta; 372 } 373 374 375 /* 376 ** 377 */ 378 379 vdaccess(io, daddr, func) 380 register struct iob *io; 381 dskadr *daddr; 382 int func; 383 { 384 register int ctlr = VDCTLR(io->i_unit); 385 register cdr *ctlr_addr = (cdr *)(vddcaddr[ctlr]+IOBASE); 386 387 dcb.opcode = (short)func; /* format sector command */ 388 dcb.intflg = NOINT; 389 dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 390 dcb.operrsta = 0; 391 dcb.devselect = (char)VDUNIT(io->i_unit); 392 dcb.trailcnt = (char)(sizeof(trrw) / 4); 393 dcb.trail.rwtrail.memadr = io->i_ma; 394 dcb.trail.rwtrail.wcount = ((io->i_cc + 1) / sizeof(short)); 395 dcb.trail.rwtrail.disk.cylinder = daddr->cylinder; 396 dcb.trail.rwtrail.disk.track = daddr->track; 397 dcb.trail.rwtrail.disk.sector = daddr->sector; 398 mdcb.firstdcb = &dcb; 399 mdcb.vddcstat = 0; 400 VDDC_ATTENTION(ctlr_addr, &mdcb, ctlr_info[ctlr].ctlr_type); 401 POLLTILLDONE(ctlr_addr, &dcb, 60, ctlr_info[ctlr].ctlr_type); 402 if(vdtimeout <= 0) 403 _stop(" during I/O operation.\n"); 404 return dcb.operrsta; 405 } 406 407 /* 408 ** Print_dcb() dumps the MDCB and DCB for diagnostic purposes. This 409 ** routine is called whenever a fatal error is encountered. 410 */ 411 412 vdprintdcb(ptr) 413 register long *ptr; 414 { 415 register long i; 416 register long trailer_count; 417 418 printf("Dump of MDCB: "); 419 for(i=0; i<4; i++) 420 printf(" %lx", *(ptr+i)); 421 if(ptr = (long *)*ptr) { 422 printf(" and DCB:"); 423 trailer_count = *(ptr+3) & 0xff; 424 for(i=0; i<7+trailer_count; i++) { 425 uncache(ptr+i); 426 printf(" %lx", *(ptr+i)); 427 } 428 } 429 printf("\n"); 430 for(i=0; i<5000000; i++) ; 431 } 432 433