|
|
1.1 ! root 1: /* vd.c 7.10 88/06/14 */ ! 2: ! 3: /* ! 4: * Stand alone driver for the VDDC/SMDE controller ! 5: */ ! 6: #include "../machine/mtpr.h" ! 7: ! 8: #include "param.h" ! 9: #include "inode.h" ! 10: #include "fs.h" ! 11: #include "buf.h" ! 12: #include "disklabel.h" ! 13: #include "saio.h" ! 14: ! 15: #include "../tahoevba/vdreg.h" ! 16: #include "../tahoevba/vbaparam.h" ! 17: ! 18: #define COMPAT_42 1 ! 19: ! 20: #define NVD 4 /* controllers */ ! 21: #define NDRIVE 8 /* drives per controller */ ! 22: ! 23: #define VDADDR(ctlr) ((struct vddevice *)vdaddrs[ctlr]) ! 24: long vdaddrs[NVD] = { 0xffff2000, 0xffff2100, 0xffff2200, 0xffff2300 }; ! 25: ! 26: u_char vdinit[NVD]; /* controller initialized */ ! 27: u_char vdtype[NVD]; /* controller type */ ! 28: u_char dkconfigured[NVD][NDRIVE]; /* unit configured */ ! 29: u_char dkflags[NVD][NDRIVE]; /* unit flags */ ! 30: ! 31: static struct disklabel dklabel[NVD][NDRIVE]; /* pack label */ ! 32: static struct mdcb mdcb; ! 33: static struct dcb dcb; ! 34: static char lbuf[DEV_BSIZE]; ! 35: ! 36: vdopen(io) ! 37: register struct iob *io; ! 38: { ! 39: register int ctlr = io->i_ctlr; ! 40: register struct dkinfo *dk; ! 41: register struct disklabel *lp, *dlp; ! 42: int error; ! 43: ! 44: if ((u_int)io->i_adapt) ! 45: return (EADAPT); ! 46: if ((u_int)ctlr >= NVD) ! 47: return (ECTLR); ! 48: if (!vdinit[ctlr] && (error = vdreset_ctlr(ctlr, io->i_unit))) ! 49: return (error); ! 50: lp = &dklabel[io->i_ctlr][io->i_unit]; ! 51: if (!dkconfigured[io->i_ctlr][io->i_unit]) { ! 52: struct iob tio; ! 53: ! 54: /* ! 55: * Read in the pack label. ! 56: */ ! 57: lp->d_secsize = 1024; ! 58: lp->d_nsectors = 72; ! 59: lp->d_ntracks = 24; ! 60: lp->d_ncylinders = 711; ! 61: lp->d_secpercyl = 72*24; ! 62: if (!vdreset_drive(io)) ! 63: return (ENXIO); ! 64: tio = *io; ! 65: tio.i_bn = LABELSECTOR; ! 66: tio.i_ma = lbuf; ! 67: tio.i_cc = DEV_BSIZE; ! 68: tio.i_flgs |= F_RDDATA; ! 69: if (vdstrategy(&tio, READ) != DEV_BSIZE) ! 70: return (ERDLAB); ! 71: dlp = (struct disklabel *)(lbuf + LABELOFFSET); ! 72: if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) ! 73: #ifdef COMPAT_42 ! 74: { ! 75: printf("dk%d: unlabeled\n", io->i_unit); ! 76: if (error = vdmaptype(io)) ! 77: return (error); ! 78: } ! 79: #else ! 80: return (EUNLAB); ! 81: #endif ! 82: else { ! 83: *lp = *dlp; ! 84: if (!vdreset_drive(io)) ! 85: return (ENXIO); ! 86: } ! 87: dkconfigured[io->i_ctlr][io->i_unit] = 1; ! 88: } ! 89: if (io->i_part < 0 || io->i_part >= lp->d_npartitions || ! 90: lp->d_partitions[io->i_part].p_size == 0) ! 91: return (EPART); ! 92: io->i_boff = ! 93: (lp->d_partitions[io->i_part].p_offset * lp->d_secsize) / DEV_BSIZE; ! 94: return (0); ! 95: } ! 96: ! 97: /* ! 98: * Reset and initialize the controller. ! 99: */ ! 100: vdreset_ctlr(ctlr, unit) ! 101: register int ctlr, unit; ! 102: { ! 103: register int i; ! 104: register struct vddevice *vdaddr = VDADDR(ctlr); ! 105: ! 106: if (badaddr(vdaddr, 2)) { ! 107: printf("vd%d: %x: invalid csr\n", ctlr, vdaddr); ! 108: return (ENXIO); ! 109: } ! 110: /* probe further to find what kind of controller it is */ ! 111: vdaddr->vdreset = 0xffffffff; ! 112: DELAY(1000000); ! 113: if (vdaddr->vdreset != 0xffffffff) { ! 114: vdtype[ctlr] = VDTYPE_VDDC; ! 115: DELAY(1000000); ! 116: } else { ! 117: vdtype[ctlr] = VDTYPE_SMDE; ! 118: vdaddr->vdrstclr = 0; ! 119: DELAY(3000000); ! 120: vdaddr->vdcsr = 0; ! 121: vdaddr->vdtcf_mdcb = AM_ENPDA; ! 122: vdaddr->vdtcf_dcb = AM_ENPDA; ! 123: vdaddr->vdtcf_trail = AM_ENPDA; ! 124: vdaddr->vdtcf_data = AM_ENPDA; ! 125: vdaddr->vdccf = CCF_SEN | CCF_DER | CCF_STS | ! 126: XMD_32BIT | BSZ_16WRD | ! 127: CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR; ! 128: } ! 129: if (!vdcmd(ctlr, 0, VDOP_INIT, 10) || ! 130: !vdcmd(ctlr, 0, VDOP_DIAG, 10)) { ! 131: vderror(unit, dcb.opcode == VDOP_INIT ? "init" : "diag", &dcb); ! 132: return (EIO); ! 133: } ! 134: vdinit[ctlr] = 1; ! 135: for (i = NDRIVE - 1; i >= 0; i--) ! 136: dkconfigured[ctlr][i] = 0; ! 137: return (0); ! 138: } ! 139: ! 140: /* ! 141: * Reset and configure a drive's parameters. ! 142: */ ! 143: vdreset_drive(io) ! 144: register struct iob *io; ! 145: { ! 146: register int ctlr = io->i_ctlr, slave = io->i_unit; ! 147: register struct disklabel *lp = &dklabel[io->i_ctlr][io->i_unit]; ! 148: register struct vddevice *vdaddr = VDADDR(ctlr); ! 149: int pass = 0, type = vdtype[ctlr], error; ! 150: int devflags = dkflags[ctlr][slave]; /* starts with 0 */ ! 151: ! 152: again: ! 153: dcb.opcode = VDOP_CONFIG; /* command */ ! 154: dcb.intflg = DCBINT_NONE; ! 155: dcb.nxtdcb = (struct dcb *)0; /* end of chain */ ! 156: dcb.operrsta = 0; ! 157: dcb.devselect = slave | devflags; ! 158: dcb.trail.rstrail.ncyl = lp->d_ncylinders; ! 159: dcb.trail.rstrail.nsurfaces = lp->d_ntracks; ! 160: if (type == VDTYPE_SMDE) { ! 161: dcb.trailcnt = sizeof (struct treset) / sizeof (long); ! 162: dcb.trail.rstrail.nsectors = lp->d_nsectors; ! 163: dcb.trail.rstrail.slip_sec = lp->d_trackskew; ! 164: dcb.trail.rstrail.recovery = VDRF_NORMAL; ! 165: } else ! 166: dcb.trailcnt = 2; /* XXX */ ! 167: mdcb.mdcb_head = &dcb; ! 168: mdcb.mdcb_status = 0; ! 169: VDGO(vdaddr, (u_long)&mdcb, type); ! 170: if (!vdpoll(vdaddr, &dcb, 10, type)) { ! 171: if (pass++ != 0) { ! 172: printf(" during drive configuration.\n"); ! 173: return (0); ! 174: } ! 175: VDRESET(vdaddr, type); ! 176: if (error = vdreset_ctlr(ctlr, io->i_unit)) ! 177: return (error); ! 178: goto again; ! 179: } ! 180: if ((dcb.operrsta & VDERR_HARD) == 0) { /* success */ ! 181: dkflags[ctlr][slave] = devflags; ! 182: return (1); ! 183: } ! 184: if (devflags == 0) { ! 185: devflags = VD_ESDI; ! 186: goto again; ! 187: } ! 188: if (type == VDTYPE_SMDE && (vdaddr->vdstatus[slave] & STA_US) == 0) { ! 189: printf("dk%d: nonexistent drive\n", io->i_unit); ! 190: return (0); ! 191: } ! 192: if ((dcb.operrsta & (DCBS_OCYL|DCBS_NRDY)) == 0) { ! 193: vderror(io->i_unit, "config", &dcb); ! 194: return (0); ! 195: } ! 196: devflags = 0; ! 197: if (pass++) /* give up */ ! 198: return (0); ! 199: /* ! 200: * Try to spin up drive with remote command. ! 201: */ ! 202: if (!vdcmd(ctlr, 0, VDOP_START, 62)) { ! 203: vderror(io->i_unit, "start", &dcb); ! 204: return (0); ! 205: } ! 206: DELAY(62000000); ! 207: goto again; ! 208: } ! 209: ! 210: vdcmd(ctlr, unit, cmd, time) ! 211: register int ctlr; ! 212: int unit, cmd, time; ! 213: { ! 214: register struct vddevice *vdaddr = VDADDR(ctlr); ! 215: ! 216: dcb.opcode = cmd; ! 217: dcb.intflg = DCBINT_NONE; ! 218: dcb.nxtdcb = (struct dcb *)0; /* end of chain */ ! 219: dcb.operrsta = 0; ! 220: dcb.devselect = unit | dkflags[ctlr][unit]; ! 221: dcb.trailcnt = 0; ! 222: mdcb.mdcb_head = &dcb; ! 223: mdcb.mdcb_status = 0; ! 224: VDGO(vdaddr, (u_long)&mdcb, vdtype[ctlr]); ! 225: if (!vdpoll(vdaddr, &dcb, time, vdtype[ctlr])) ! 226: _stop(" during initialization operation.\n"); ! 227: return ((dcb.operrsta & VDERR_HARD) == 0); ! 228: } ! 229: ! 230: vdstrategy(io, cmd) ! 231: register struct iob *io; ! 232: int cmd; ! 233: { ! 234: register struct disklabel *lp; ! 235: int ctlr, cn, tn, sn, slave, retries = 0; ! 236: daddr_t bn; ! 237: struct vddevice *vdaddr; ! 238: ! 239: if (io->i_cc == 0 || io->i_cc > 65535) { ! 240: printf("dk%d: invalid transfer size %d\n", io->i_unit, ! 241: io->i_cc); ! 242: io->i_error = EIO; ! 243: return (-1); ! 244: } ! 245: lp = &dklabel[io->i_ctlr][io->i_unit]; ! 246: bn = io->i_bn * (DEV_BSIZE / lp->d_secsize); ! 247: cn = bn / lp->d_secpercyl; ! 248: sn = bn % lp->d_secpercyl; ! 249: tn = sn / lp->d_nsectors; ! 250: sn = sn % lp->d_nsectors; ! 251: ! 252: top: ! 253: dcb.opcode = (cmd == READ ? VDOP_RD : VDOP_WD); ! 254: dcb.intflg = DCBINT_NONE; ! 255: dcb.nxtdcb = (struct dcb *)0; /* end of chain */ ! 256: dcb.operrsta = 0; ! 257: ctlr = io->i_ctlr; ! 258: slave = io->i_unit; ! 259: dcb.devselect = slave | dkflags[ctlr][slave]; ! 260: dcb.trailcnt = sizeof (struct trrw) / sizeof (int); ! 261: dcb.trail.rwtrail.memadr = (u_long)io->i_ma; ! 262: dcb.trail.rwtrail.wcount = (io->i_cc + 1) / sizeof (short); ! 263: dcb.trail.rwtrail.disk.cylinder = cn; ! 264: dcb.trail.rwtrail.disk.track = tn; ! 265: dcb.trail.rwtrail.disk.sector = sn; ! 266: mdcb.mdcb_head = &dcb; ! 267: mdcb.mdcb_status = 0; ! 268: vdaddr = VDADDR(ctlr); ! 269: VDGO(vdaddr, (u_long)&mdcb, vdtype[ctlr]); ! 270: if (!vdpoll(vdaddr, &dcb, 60, vdtype[ctlr])) ! 271: _stop(" during i/o operation.\n"); ! 272: if (dcb.operrsta & VDERR_HARD) { ! 273: if (retries++ == 0 && vdreset_ctlr(ctlr, io->i_unit) == 0 && ! 274: vdreset_drive(io)) ! 275: goto top; ! 276: vderror(io->i_unit, cmd == READ ? "read" : "write", &dcb); ! 277: io->i_error = EIO; ! 278: return (-1); ! 279: } ! 280: mtpr(PADC, 0); ! 281: return (io->i_cc); ! 282: } ! 283: ! 284: vderror(unit, cmd, dcb) ! 285: int unit; ! 286: char *cmd; ! 287: struct dcb *dcb; ! 288: { ! 289: ! 290: printf("dk%d: %s error; status %b", unit, cmd, ! 291: dcb->operrsta, VDERRBITS); ! 292: if (dcb->err_code) ! 293: printf(", code %x", dcb->err_code); ! 294: printf("\n"); ! 295: } ! 296: ! 297: /* ! 298: * Poll controller until operation ! 299: * completes or timeout expires. ! 300: */ ! 301: vdpoll(vdaddr, dcb, t, type) ! 302: register struct vddevice *vdaddr; ! 303: register struct dcb *dcb; ! 304: register int t, type; ! 305: { ! 306: ! 307: t *= 1000; ! 308: for (;;) { ! 309: uncache(&dcb->operrsta); ! 310: if (dcb->operrsta & (DCBS_DONE|DCBS_ABORT)) ! 311: break; ! 312: if (--t <= 0) { ! 313: printf("vd: controller timeout"); ! 314: VDABORT(vdaddr, type); ! 315: DELAY(30000); ! 316: uncache(&dcb->operrsta); ! 317: return (0); ! 318: } ! 319: DELAY(1000); ! 320: } ! 321: if (type == VDTYPE_SMDE) { ! 322: for (;;) { ! 323: uncache(&vdaddr->vdcsr); ! 324: if ((vdaddr->vdcsr & CS_GO) == 0) ! 325: break; ! 326: DELAY(50); ! 327: } ! 328: DELAY(300); ! 329: uncache(&dcb->err_code); ! 330: } ! 331: DELAY(200); ! 332: uncache(&dcb->operrsta); ! 333: return (1); ! 334: } ! 335: ! 336: #ifdef COMPAT_42 ! 337: struct dkcompat { ! 338: int nsectors; /* sectors per track */ ! 339: int ntracks; /* tracks per cylinder */ ! 340: int ncylinders; /* cylinders per drive */ ! 341: int secsize; /* sector size */ ! 342: #define NPART 2 ! 343: int poff[NPART]; /* [a+b] for bootstrapping */ ! 344: } dkcompat[] = { ! 345: { 64, 20, 842, 512, 0, 61440 }, /* 2361a eagle */ ! 346: { 48, 24, 711, 512, 0, 61056 }, /* xsd */ ! 347: { 44, 20, 842, 512, 0, 52800 }, /* eagle */ ! 348: { 64, 10, 823, 512, 0, 38400 }, /* fuji 360 */ ! 349: { 32, 24, 711, 512, 0, 40704 }, /* xfd */ ! 350: { 32, 19, 823, 512, 0, 40128 }, /* smd */ ! 351: { 32, 10, 823, 512, 0, 19200 }, /* fsd */ ! 352: { 18, 15, 1224, 1024, 0, 21600 }, /* mxd */ ! 353: }; ! 354: #define NDKCOMPAT (sizeof (dkcompat) / sizeof (dkcompat[0])) ! 355: ! 356: /* ! 357: * Identify and configure drive from above table ! 358: * by trying to read the last sector until a description ! 359: * is found for which we're successful. ! 360: */ ! 361: vdmaptype(io) ! 362: struct iob *io; ! 363: { ! 364: register struct disklabel *lp = &dklabel[io->i_ctlr][io->i_unit]; ! 365: register struct dkcompat *dp; ! 366: int i, ctlr, slave, type; ! 367: struct vddevice *vdaddr; ! 368: ! 369: ctlr = io->i_ctlr; ! 370: slave = io->i_unit; ! 371: vdaddr = VDADDR(ctlr); ! 372: type = vdtype[ctlr]; ! 373: for (dp = dkcompat; dp < &dkcompat[NDKCOMPAT]; dp++) { ! 374: if (type == VDTYPE_VDDC && dp->nsectors != 32) ! 375: continue; ! 376: lp->d_nsectors = dp->nsectors; ! 377: lp->d_ntracks = dp->ntracks; ! 378: lp->d_ncylinders = dp->ncylinders; ! 379: lp->d_secsize = dp->secsize; ! 380: if (!vdreset_drive(io)) /* set drive parameters */ ! 381: return (EIO); ! 382: dcb.opcode = VDOP_RD; ! 383: dcb.intflg = DCBINT_NONE; ! 384: dcb.nxtdcb = (struct dcb *)0; /* end of chain */ ! 385: dcb.devselect = slave | dkflags[ctlr][slave]; ! 386: dcb.operrsta = 0; ! 387: dcb.trailcnt = sizeof (struct trrw) / sizeof (long); ! 388: dcb.trail.rwtrail.memadr = (u_long)lbuf; ! 389: dcb.trail.rwtrail.wcount = lp->d_secsize / sizeof (short); ! 390: dcb.trail.rwtrail.disk.cylinder = dp->ncylinders - 2; ! 391: dcb.trail.rwtrail.disk.track = dp->ntracks - 1; ! 392: dcb.trail.rwtrail.disk.sector = dp->nsectors - 1; ! 393: mdcb.mdcb_head = &dcb; ! 394: mdcb.mdcb_status = 0; ! 395: VDGO(vdaddr, (u_long)&mdcb, type); ! 396: if (!vdpoll(vdaddr, &dcb, 60, type)) ! 397: _stop(" during i/o operation.\n"); ! 398: if (dcb.operrsta & VDERR_HARD) ! 399: continue; ! 400: /* simulate necessary parts of disk label */ ! 401: lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; ! 402: lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; ! 403: lp->d_npartitions = NPART; ! 404: for (i = 0; i < NPART; i++) { ! 405: lp->d_partitions[i].p_offset = dp->poff[i]; ! 406: lp->d_partitions[i].p_size = ! 407: lp->d_secperunit - dp->poff[i]; ! 408: } ! 409: return (0); ! 410: } ! 411: printf("dk%d: unknown drive type\n", io->i_unit); ! 412: return (ENXIO); ! 413: } ! 414: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.