1 /* vd.c 7.5 86/12/19 */ 2 3 /* 4 * Stand alone driver for the VDDC controller 5 * TAHOE Version, Oct 1983. 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 #define VDUNIT(x) (minor(x) & 0x3) 20 #define VDCTLR(x) (minor(x) >> 2) 21 22 fmt_mdcb mdcb; 23 fmt_dcb dcb; 24 25 /* 26 * Drive specific information. 27 */ 28 struct dkinfo { 29 char configured; 30 fs_tab info; 31 } dkinfo[NVD][16]; 32 33 /* 34 * Controller specific information. 35 */ 36 struct vdinfo { 37 u_short vd_flags; 38 #define VDF_INIT 0x1 /* controller initialized */ 39 #define VDF_BUSY 0x2 /* controller running */ 40 u_short vd_type; /* smd or smde */ 41 char *vd_name; 42 } vdinfo[NVD]; 43 44 static char junk[1024]; 45 46 #define VDADDR(ctlr) ((cdr *)vddcaddr[(ctlr)]) 47 48 vdopen(io) 49 register struct iob *io; 50 { 51 register int ctlr = VDCTLR(io->i_unit), unit = VDUNIT(io->i_unit); 52 struct vdinfo *vd; 53 register int i, j; 54 55 /* Make sure controller number is in range */ 56 if (ctlr >= NVD) { 57 printf( 58 "dk%d: invalid controller (only configured for %d vd's)\n", 59 io->i_unit, NVD); 60 _stop(""); 61 } 62 /* check file system for validity */ 63 if ((unsigned)io->i_boff >= 8) { 64 printf("dk%d: invalid partition number (%d)\n", 65 io->i_unit, io->i_boff); 66 _stop(""); 67 } 68 vd = &vdinfo[ctlr]; 69 if ((vd->vd_flags&VDF_INIT) == 0) { 70 vdinit(io); /* initialize controller/drive */ 71 vd->vd_flags |= VDF_INIT; 72 for (j = 0; j < 16; j++) 73 dkinfo[ctlr][j].configured = 0; 74 } 75 if (!dkinfo[ctlr][unit].configured) { 76 vdconfigure_drive(io); 77 dkinfo[ctlr][unit].configured = 1; 78 } 79 io->i_boff = dkinfo[ctlr][unit].info.partition[io->i_boff].par_start; 80 } 81 82 vdinit(io) 83 register struct iob *io; 84 { 85 register int ctlr = VDCTLR(io->i_unit), unit = VDUNIT(io->i_unit); 86 register cdr *ctlr_addr = VDADDR(ctlr); 87 register struct vdinfo *vd = &vdinfo[ctlr]; 88 89 /* Check to see if controller is really there */ 90 if (badaddr(ctlr_addr, 2)) { 91 printf("dk%d: vd%d csr doesn't respond\n", io->i_unit, ctlr); 92 _stop(""); 93 } 94 /* Probe further to find what kind of controller it is */ 95 ctlr_addr->cdr_reset = 0xffffffff; 96 DELAY(1000000); 97 if (ctlr_addr->cdr_reset != 0xffffffff) { 98 vd->vd_type = SMDCTLR; 99 vd->vd_name = "smd"; 100 DELAY(1000000); 101 } else { 102 vd->vd_type = SMD_ECTLR; 103 vd->vd_name = "smde"; 104 ctlr_addr->cdr_reserved = 0x0; 105 DELAY(3000000); 106 } 107 if (vd->vd_type == SMD_ECTLR) { 108 ctlr_addr->cdr_csr = 0; 109 ctlr_addr->mdcb_tcf = AM_ENPDA; 110 ctlr_addr->dcb_tcf = AM_ENPDA; 111 ctlr_addr->trail_tcf = AM_ENPDA; 112 ctlr_addr->data_tcf = AM_ENPDA; 113 ctlr_addr->cdr_ccf = CCF_STS | XMD_32BIT | BSZ_16WRD | 114 CCF_ENP | CCF_EPE /* | CCF_EDE */ | CCF_ECE | CCF_ERR; 115 } 116 if (vdnotrailer(io, INIT, 8) & HRDERR) { 117 vdprint_error(io->i_unit, "init error", 118 dcb.operrsta, dcb.err_code); 119 _stop(""); 120 } 121 if (vdnotrailer(io, DIAG, 8) & HRDERR) { 122 vdprint_error(io->i_unit, "diagnostic error", 123 dcb.operrsta, dcb.err_code); 124 _stop(""); 125 } 126 } 127 128 vdconfigure_drive(io) 129 register struct iob *io; 130 { 131 register int ctlr = VDCTLR(io->i_unit), unit = VDUNIT(io->i_unit); 132 register fs_tab *file_sys; 133 register struct dkinfo *dk = &dkinfo[ctlr][unit]; 134 dskadr daddr; 135 register int i; 136 137 for (i = 0; i < nvddrv; i++) { 138 dk->info = vdst[i]; 139 if (vdinfo[ctlr].vd_type == SMDCTLR) 140 if (dk->info.nsec != 32) 141 continue; 142 vdconfigure(io, 0); 143 daddr.cylinder = dk->info.ncyl - 2; 144 daddr.track = dk->info.ntrak - 1; 145 daddr.sector = dk->info.nsec - 1; 146 io->i_ma = junk; 147 io->i_cc = dk->info.secsize; 148 if ((vdaccess(io, &daddr, RD) & HRDERR) == 0) 149 return; 150 } 151 printf("dk%d: unknown drive type\n", io->i_unit); 152 _stop(""); 153 } 154 155 vdstart_drive(io) 156 register struct iob *io; 157 { 158 register int ctlr = VDCTLR(io->i_unit), unit = VDUNIT(io->i_unit); 159 int ounit = io->i_unit; 160 161 io->i_unit &= ~3; 162 if (vdnotrailer(io, VDSTART, 62) & HRDERR) { 163 vdprint_error(io->i_unit, "start error", 164 dcb.operrsta, dcb.err_code); 165 _stop(""); 166 } 167 vdinfo[ctlr].vd_flags |= VDF_BUSY; 168 io->i_unit = ounit; 169 DELAY(62000000); 170 } 171 172 /* 173 * This routine actually configures a particular drive. 174 * 175 * If the controller is an SMD/E controller then the number of sectors per 176 * track is loaded into the appropriate register, otherwise it is left 177 * alone because the old SMD controller requires a constant 32 sectors 178 * per track for it's drives. (an error would be returned if the value is 179 * loaded.) 180 */ 181 vdconfigure(io, pass) 182 register struct iob *io; 183 int pass; 184 { 185 register int ctlr = VDCTLR(io->i_unit), unit = VDUNIT(io->i_unit); 186 register cdr *ctlr_addr = VDADDR(ctlr); 187 188 dcb.opcode = RSTCFG; /* command */ 189 dcb.intflg = NOINT; 190 dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 191 dcb.operrsta = 0; 192 dcb.devselect = (char)unit; 193 dcb.trail.rstrail.ncyl = dkinfo[ctlr][unit].info.ncyl; 194 dcb.trail.rstrail.nsurfaces = dkinfo[ctlr][unit].info.ntrak; 195 if (vdinfo[ctlr].vd_type == SMD_ECTLR) { 196 dcb.trailcnt = (char)5; 197 dcb.trail.rstrail.nsectors = dkinfo[ctlr][unit].info.nsec; 198 dcb.trail.rstrail.slip_sec = dkinfo[ctlr][unit].info.nslip; 199 dcb.trail.rstrail.recovery = 0x18f; 200 } else 201 dcb.trailcnt = (char)2; 202 mdcb.firstdcb = &dcb; 203 mdcb.vddcstat = 0; 204 VDDC_ATTENTION(ctlr_addr, &mdcb, vdinfo[ctlr].vd_type); 205 if (!vdpoll(ctlr_addr,&dcb,10,vdinfo[ctlr].vd_type)) { 206 if (pass == 0) { 207 VDDC_RESET(ctlr_addr, vdinfo[ctlr].vd_type); 208 vdconfigure(io, 1); 209 } else 210 _stop(" during drive configuration.\n"); 211 } 212 if (dcb.operrsta & HRDERR) { 213 if (vdinfo[ctlr].vd_type == SMD_ECTLR && 214 (ctlr_addr->cdr_status[io->i_unit] & STA_US) == 0) { 215 printf("dk%d: ", io->i_unit); 216 _stop("nonexistent drive"); 217 } 218 if ((dcb.operrsta & (NOTCYLERR|DRVNRDY)) == 0) { 219 vdprint_error(io->i_unit, "configuration error", 220 dcb.operrsta, dcb.err_code); 221 _stop(""); 222 } 223 if (pass == 0) { 224 vdstart_drive(io); 225 vdconfigure(io, 1); 226 } 227 } 228 } 229 230 /* 231 * Strategy is called to do the actual I/O to the disk drives. 232 * 233 * Some simple checks are made to make sure we don't do anything rediculous, 234 * If everything is sane then the request is issued. 235 * 236 * If no errors occured then the original byte count is returned, 237 * otherwise -1 is returned to indicate an error occured. 238 */ 239 vdstrategy(io, func) 240 register struct iob *io; 241 register int func; 242 { 243 dskadr daddr; 244 register int ctlr = VDCTLR(io->i_unit), unit = VDUNIT(io->i_unit); 245 register fs_tab *u_info = &dkinfo[ctlr][unit].info; 246 register int op = (func == READ) ? RD : WD; 247 register int blk; 248 249 if (io->i_cc == 0 || io->i_cc > 65535) { 250 printf("dk%d: invalid transfer size %d\n", io->i_unit, 251 io->i_cc); 252 _stop(""); 253 } 254 blk = io->i_bn * DEV_BSIZE / u_info->secsize; 255 daddr.sector = blk % u_info->nsec; 256 daddr.track = (blk / u_info->nsec) % u_info->ntrak; 257 daddr.cylinder = (blk/u_info->nsec) / u_info->ntrak; 258 if (vdaccess(io, &daddr, op) & HRDERR) { 259 vdprint_error(io->i_unit, "i/o error", dcb.operrsta, 260 dcb.err_code); 261 io->i_error = EIO; 262 return (-1); 263 } 264 mtpr(PADC, 0); 265 return (io->i_cc); 266 } 267 268 vdprint_error(unit, str, status, smde_status) 269 int unit; 270 char *str; 271 u_long status; 272 u_long smde_status; 273 { 274 register struct vdstatus *sp; 275 276 printf("dk%d: %s; status %b", unit, str, status, ERRBITS); 277 if (smde_status) 278 printf(", code %x", smde_status); 279 printf("\n"); 280 } 281 282 vdnotrailer(io, function, time) 283 register struct iob *io; 284 register int function, time; 285 { 286 register int ctlr = VDCTLR(io->i_unit); 287 register cdr *ctlr_addr = VDADDR(ctlr); 288 289 dcb.opcode = function; /* command */ 290 dcb.intflg = NOINT; 291 dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 292 dcb.operrsta = 0; 293 dcb.devselect = (char)VDUNIT(io->i_unit); 294 dcb.trailcnt = (char)0; 295 mdcb.firstdcb = &dcb; 296 mdcb.vddcstat = 0; 297 VDDC_ATTENTION(ctlr_addr, &mdcb, vdinfo[ctlr].vd_type); 298 if (!vdpoll(ctlr_addr, &dcb, time, vdinfo[ctlr].vd_type)) 299 _stop(" during initialization operation.\n"); 300 return dcb.operrsta; 301 } 302 303 vdaccess(io, daddr, func) 304 register struct iob *io; 305 dskadr *daddr; 306 int func; 307 { 308 register int ctlr = VDCTLR(io->i_unit); 309 register cdr *ctlr_addr = VDADDR(ctlr); 310 311 dcb.opcode = (short)func; /* format sector command */ 312 dcb.intflg = NOINT; 313 dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 314 dcb.operrsta = 0; 315 dcb.devselect = (char)VDUNIT(io->i_unit); 316 dcb.trailcnt = (char)(sizeof(trrw) / 4); 317 dcb.trail.rwtrail.memadr = io->i_ma; 318 dcb.trail.rwtrail.wcount = ((io->i_cc + 1) / sizeof(short)); 319 dcb.trail.rwtrail.disk.cylinder = daddr->cylinder; 320 dcb.trail.rwtrail.disk.track = daddr->track; 321 dcb.trail.rwtrail.disk.sector = daddr->sector; 322 mdcb.firstdcb = &dcb; 323 mdcb.vddcstat = 0; 324 VDDC_ATTENTION(ctlr_addr, &mdcb, vdinfo[ctlr].vd_type); 325 if (!vdpoll(ctlr_addr, &dcb, 60, vdinfo[ctlr].vd_type)) 326 _stop(" during i/o operation.\n"); 327 return (dcb.operrsta); 328 } 329 330 /* 331 * Dump the MDCB and DCB for diagnostic purposes. This 332 * routine is called whenever a fatal error is encountered. 333 */ 334 vdprintdcb(ptr) 335 register long *ptr; 336 { 337 register long i, trailer_count; 338 339 printf("mdcb: %lx %lx %lx %lx\n", ptr[0], ptr[1], ptr[2], ptr[3]); 340 if (ptr = (long *)*ptr) { 341 printf("dcb:"); 342 trailer_count = ptr[3] & 0xff; 343 for (i=0; i<7+trailer_count; i++) { 344 uncache(&ptr[i]); 345 printf(" %lx", ptr[i]); 346 } 347 } 348 printf("\n"); 349 DELAY(5000000); 350 } 351 352 /* 353 * Poll controller until operation completes 354 * or timeout expires. 355 */ 356 vdpoll(addr, dcb, t, type) 357 register cdr *addr; 358 register fmt_dcb *dcb; 359 register int t, type; 360 { 361 362 t *= 1000; 363 for (;;) { 364 uncache(&dcb->operrsta); 365 if (dcb->operrsta & (DCBCMP|DCBABT)) 366 break; 367 if (--t <= 0) { 368 printf("vd: controller timeout"); 369 VDDC_ABORT(addr, type); 370 DELAY(30000); 371 uncache(&dcb->operrsta); 372 return (0); 373 } 374 DELAY(1000); 375 } 376 if (type == SMD_ECTLR) { 377 for (;;) { 378 uncache(&addr->cdr_csr); 379 if ((addr->cdr_csr & CS_GO) == 0) 380 break; 381 DELAY(50); 382 } 383 DELAY(300); 384 uncache(&dcb->err_code); 385 } 386 DELAY(200); 387 uncache(&dcb->operrsta); 388 return (1); 389 } 390