|
|
1.1 ! root 1: /* ! 2: * @(#)xy.c 1.1 86/02/03 Copyright (c) 1986 by Sun Microsystems, Inc. ! 3: */ ! 4: ! 5: /* Standalone driver for Xylogics 440/450 */ ! 6: ! 7: #include "saio.h" ! 8: #include "param.h" ! 9: #include "../h/dkbad.h" ! 10: #include "../sun/dklabel.h" ! 11: #include "../sun/dkio.h" ! 12: #include "../ufs/fsdir.h" ! 13: #include "../sundev/xycreg.h" ! 14: #include "../sundev/xyreg.h" ! 15: ! 16: extern char msg_nolabel[]; ! 17: ! 18: struct xyparam { ! 19: unsigned short xy_boff; /* Cyl # starting partition */ ! 20: unsigned short xy_nsect; /* Sect/track */ ! 21: unsigned short xy_ncyl; /* Cyl/disk */ ! 22: unsigned short xy_nhead; /* Heads/cyl */ ! 23: unsigned short xy_bhead; /* Base head # for removable disk */ ! 24: unsigned short xy_drive; /* Xylogics drive type ID */ ! 25: int xy_nblk; ! 26: int xy_badaddr; /* Disk block # of bad-block table */ ! 27: struct dkbad xy_bad; ! 28: unsigned char xy_unit; ! 29: }; ! 30: ! 31: #define CYL(p) (p*xyp->xy_nsect*xyp->xy_nhead) /* cyl to block conv */ ! 32: ! 33: #define NSTD 2 ! 34: unsigned long xystd[NSTD] = { 0xee40, 0xee48 }; ! 35: ! 36: /* ! 37: * Structure of our DMA area ! 38: */ ! 39: struct xydma { ! 40: struct xyiopb xyiopb; ! 41: char xyblock[MAXBSIZE]; /* R/W data */ ! 42: }; ! 43: ! 44: /* ! 45: * What resources we need to run ! 46: */ ! 47: struct devinfo xyinfo = { ! 48: sizeof (struct xydevice), ! 49: sizeof (struct xydma), ! 50: sizeof (struct xyparam), ! 51: NSTD, ! 52: xystd, ! 53: MAP_MBIO, ! 54: #ifdef BOOTBLOCK ! 55: DEV_BSIZE, ! 56: #else ! 57: DEV_BSIZE, /* MAXBSIZE, */ ! 58: #endif ! 59: }; ! 60: ! 61: /* ! 62: * What facilities we export to the world ! 63: */ ! 64: int xyopen(), xystrategy(); ! 65: extern int xxboot(), xxprobe(); ! 66: extern int nullsys(); ! 67: ! 68: struct boottab xydriver = { ! 69: "xy", xxprobe, xxboot, xyopen, nullsys, xystrategy, ! 70: "xy: Xylogics 440/450 disk", &xyinfo, ! 71: }; ! 72: ! 73: ! 74: /* ! 75: * Open a xylogics disk. ! 76: */ ! 77: xyopen(sip) ! 78: register struct saioreq *sip; ! 79: { ! 80: register struct xyparam *xyp; ! 81: register struct xydevice *xyaddr; ! 82: register struct xyiopb *xy; ! 83: struct dk_label *label; ! 84: register int i, t; ! 85: u_short ppart; ! 86: #ifndef BOOTBLOCK ! 87: int xyspin(); ! 88: #endif !BOOTBLOCK ! 89: ! 90: xyp = (struct xyparam *)sip->si_devdata; ! 91: xyaddr = (struct xydevice *)sip->si_devaddr; ! 92: xy = &((struct xydma *)sip->si_dmaaddr)->xyiopb; ! 93: ! 94: xyp->xy_unit = sip->si_unit & 0x03; ! 95: ppart = (sip->si_unit >> 2) & 1; ! 96: ! 97: /* reset controller */ ! 98: i = xyaddr->xy_resupd; ! 99: #ifdef lint ! 100: i = i; /* Avoid complaint about "set but not used" */ ! 101: #endif ! 102: DELAY(100); /* Allow for controller recovery time */ ! 103: ! 104: xyp->xy_boff = 0; /* Don't offset block numbers */ ! 105: xyp->xy_nsect = 2; ! 106: xyp->xy_nhead = 2; ! 107: xyp->xy_ncyl = 2; ! 108: xyp->xy_bad.bt_mbz = -1; ! 109: ! 110: #ifndef BOOTBLOCK ! 111: /* ! 112: * Wait for disk to spin up, if necessary. ! 113: */ ! 114: if (!isspinning(xyspin, (char *)sip, 0)) ! 115: return (-1); ! 116: #endif !BOOTBLOCK ! 117: ! 118: for (xyp->xy_drive = 0; xyp->xy_drive < NXYDRIVE; xyp->xy_drive++) { ! 119: label = (struct dk_label *) ! 120: ((struct xydma *)sip->si_dmaaddr)->xyblock; ! 121: label->dkl_magic = 0; ! 122: if (xycmd(XY_READ, sip, 0, (char *)label, 1)) ! 123: continue; ! 124: if (chklabel(label)) ! 125: continue; ! 126: if (ppart != label->dkl_ppart) ! 127: continue; ! 128: goto foundlabel; ! 129: } ! 130: printf(msg_nolabel); ! 131: return (-1); ! 132: ! 133: foundlabel: ! 134: xyp->xy_nhead = label->dkl_nhead; ! 135: xyp->xy_nsect = label->dkl_nsect; ! 136: xyp->xy_ncyl = label->dkl_ncyl + label->dkl_acyl; ! 137: xyp->xy_boff = label->dkl_map[sip->si_boff].dkl_cylno; ! 138: xyp->xy_nblk = label->dkl_map[sip->si_boff].dkl_nblk; ! 139: ! 140: bzero((char *)xy, sizeof (struct xyiopb)); ! 141: xy->xy_reloc = 1; ! 142: xy->xy_cmd = XY_INIT; ! 143: xy->xy_drive = xyp->xy_drive; ! 144: xy->xy_unit = xyp->xy_unit & 3; ! 145: xy->xy_head = xyp->xy_nhead - 1; ! 146: xy->xy_cylinder = xyp->xy_ncyl - 1; ! 147: xy->xy_sector = xyp->xy_nsect - 1; ! 148: xy->xy_bhead = label->dkl_bhead; ! 149: ! 150: t = XYREL(xyaddr, MB_DMA_ADDR(xy)); ! 151: xyaddr->xy_iopbrel[0] = t >> 8; ! 152: xyaddr->xy_iopbrel[1] = t; ! 153: xyaddr->xy_iopboff[0] = MB_DMA_ADDR(xy) >> 8; ! 154: xyaddr->xy_iopboff[1] = MB_DMA_ADDR(xy); ! 155: xyaddr->xy_csr = XY_GO; ! 156: ! 157: do { ! 158: DELAY(30); ! 159: } while (xyaddr->xy_csr & XY_BUSY); ! 160: if (xy->xy_iserr) ! 161: printf("xy: init error %x\n", xy->xy_errno); ! 162: /* ! 163: * Fetch bad block info. ! 164: */ ! 165: xyp->xy_badaddr = ((int)xyp->xy_ncyl * xyp->xy_nhead - 1) ! 166: * xyp->xy_nsect; ! 167: if (xycmd(XY_READ, sip, xyp->xy_badaddr, (char *)&xyp->xy_bad, 1)) ! 168: printf("xy: no bad block info\n"); ! 169: return (0); ! 170: } ! 171: ! 172: xystrategy(sip, rw) ! 173: struct saioreq *sip; ! 174: int rw; ! 175: { ! 176: register int cmd = (rw == WRITE) ? XY_WRITE : XY_READ; ! 177: register int boff; ! 178: register struct xyparam *xyp = (struct xyparam *)sip->si_devdata; ! 179: register short nsect; ! 180: #ifndef BOOTBLOCK ! 181: char *ma; ! 182: int i, bn; ! 183: #endif BOOTBLOCK ! 184: ! 185: boff = CYL(xyp->xy_boff); ! 186: #ifdef BOOTBLOCK ! 187: /* assert si_cc == DEV_BSIZE */ ! 188: if (xycmd(cmd, sip, sip->si_bn + boff, sip->si_ma, 1)) ! 189: return (-1); ! 190: return (sip->si_cc); ! 191: #else BOOTBLOCK ! 192: nsect = sip->si_cc / DEV_BSIZE; ! 193: if (sip->si_bn + nsect > xyp->xy_nblk) ! 194: nsect = xyp->xy_nblk - sip->si_bn; ! 195: if (nsect == 0) ! 196: return (0); ! 197: if (xycmd(cmd, sip, sip->si_bn+boff, sip->si_ma, nsect) == 0) ! 198: return (nsect*DEV_BSIZE); ! 199: /* ! 200: * Large transfer failed, now do one at a time ! 201: */ ! 202: bn = sip->si_bn + boff; ! 203: ma = sip->si_ma; ! 204: for (i = 0; i < nsect; i++) { ! 205: if (xycmd(cmd, sip, bn, ma, 1)) ! 206: return (-1); ! 207: bn++; ! 208: ma += DEV_BSIZE; ! 209: } ! 210: return (nsect*DEV_BSIZE); ! 211: #endif BOOTBLOCK ! 212: } ! 213: ! 214: #ifndef BOOTBLOCK ! 215: /* ! 216: * This routine is called from isspinning() as the test condition. ! 217: */ ! 218: int ! 219: xyspin(sip, dummy) ! 220: struct saioreq *sip; ! 221: int dummy; ! 222: { ! 223: register struct xyiopb *xy = &((struct xydma *)sip->si_dmaaddr)->xyiopb; ! 224: ! 225: (void) xycmd(XY_STATUS, sip, 0, (char *)0, 0); ! 226: return ((xy->xy_status & XY_READY) ? 0 : 1); ! 227: } ! 228: #endif !BOOTBLOCK ! 229: ! 230: xycmd(cmd, sip, bno, buf, nsect) ! 231: int cmd; ! 232: struct saioreq *sip; ! 233: register int bno; ! 234: char *buf; ! 235: int nsect; ! 236: { ! 237: register int i, t; ! 238: register struct xyparam *xyp = (struct xyparam *)sip->si_devdata; ! 239: register struct xyiopb *xy = &((struct xydma *)sip->si_dmaaddr)->xyiopb; ! 240: register struct xydevice *xyaddr = (struct xydevice *)sip->si_devaddr; ! 241: register char *bp = ((struct xydma *)sip->si_dmaaddr)->xyblock; ! 242: unsigned short cylno, sect, head; ! 243: int error, errcnt = 0; ! 244: ! 245: cylno = bno / CYL(1); ! 246: sect = bno % xyp->xy_nsect; ! 247: head = (bno / xyp->xy_nsect) % xyp->xy_nhead; ! 248: ! 249: if (cmd == XY_WRITE && buf != bp) /* Many just use common buf */ ! 250: bcopy(buf, bp, nsect*DEV_BSIZE); ! 251: ! 252: retry: ! 253: bzero((char *)xy, sizeof (struct xyiopb)); ! 254: xy->xy_reloc = 1; ! 255: xy->xy_autoup = 1; ! 256: xy->xy_cmd = cmd; ! 257: xy->xy_drive = xyp->xy_drive; ! 258: xy->xy_unit = xyp->xy_unit & 3; ! 259: xy->xy_eccmode = 2; /* means 0 on 440 */ ! 260: xy->xy_throttle = XY_THROTTLE; ! 261: xy->xy_sector = sect; ! 262: xy->xy_head = head; ! 263: xy->xy_cylinder = cylno; ! 264: xy->xy_nsect = nsect; ! 265: xy->xy_bufoff = XYOFF(MB_DMA_ADDR(bp)); ! 266: xy->xy_bufrel = XYREL(xyaddr, MB_DMA_ADDR(bp)); ! 267: ! 268: t = XYREL(xyaddr, MB_DMA_ADDR(xy)); ! 269: xyaddr->xy_iopbrel[0] = t >> 8; ! 270: xyaddr->xy_iopbrel[1] = t; ! 271: xyaddr->xy_iopboff[0] = MB_DMA_ADDR(xy) >> 8; ! 272: xyaddr->xy_iopboff[1] = MB_DMA_ADDR(xy); ! 273: xyaddr->xy_csr = XY_GO; ! 274: ! 275: do { ! 276: DELAY(30); ! 277: } while (xyaddr->xy_csr & XY_BUSY); ! 278: ! 279: if (xyaddr->xy_csr & XY_ERROR) { ! 280: xyaddr->xy_csr = XY_ERROR; ! 281: DELAY(100); ! 282: if (bno != 0) ! 283: printf("xy: hard error bno %d\n", bno); ! 284: if (cmd != XY_RESET) ! 285: (void) xycmd(XY_RESET, sip, 0, (char *)0, 0); ! 286: return (-1); ! 287: } ! 288: if (xy->xy_iserr && xy->xy_errno != 0x1F) { /* FIXME constant */ ! 289: if (nsect != 1) /* only try hard on single sectors */ ! 290: return (-1); ! 291: error = xy->xy_errno; ! 292: if ((i = xyfwd(xyp, cylno, head, sect)) != 0) ! 293: return xycmd(cmd, sip, i, buf, 1); ! 294: /* Attempt to reset the error condition */ ! 295: if (cmd != XY_RESET) ! 296: (void) xycmd(XY_RESET, sip, 0, (char *)0, 0); ! 297: if (++errcnt < 5) ! 298: goto retry; ! 299: if (bno != 0 || error != 5) /* drive type probe */ ! 300: printf("xy: error %x bno %d\n", error, bno); ! 301: return (-1); /* Error */ ! 302: } ! 303: ! 304: if (cmd == XY_READ && buf != bp) /* Many just use common buf */ ! 305: bcopy(bp, buf, nsect*DEV_BSIZE); ! 306: ! 307: return (0); ! 308: } ! 309: ! 310: xyfwd(xyp, cn, tn, sn) ! 311: register struct xyparam *xyp; ! 312: int cn, tn, sn; ! 313: { ! 314: register struct dkbad *bt = &xyp->xy_bad; ! 315: register int i; ! 316: ! 317: if (bt->bt_mbz != 0) /* not initialized */ ! 318: return (0); ! 319: for (i=0; i<126; i++) /* FIXME constant */ ! 320: if (bt->bt_bad[i].bt_cyl == cn && ! 321: bt->bt_bad[i].bt_trksec == (tn<<8)+sn) { ! 322: return (xyp->xy_badaddr - i - 1); ! 323: } ! 324: return (0); ! 325: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.