📄 xd.c
字号:
/* * @(#)xd.c 1.1 92/07/30 Copyright (c) 1985 by Sun Microsystems, Inc. */#ifndef lintstatic char sccsid[] = "@(#)xd.c 1.1 92/07/30 SMI";#endif/* Standalone driver for Xylogics 7053 (formerly 751) */#include <mon/cpu.addrs.h>#include <stand/saio.h>#include <stand/param.h>#include <sys/dkbad.h>#include <sun/dklabel.h>#include <sun/dkio.h>#include <ufs/fsdir.h>#include <sundev/xdcreg.h>#include <sundev/xdreg.h>#include <stand/xderr.h> /* shorter error messages */extern char msg_nolabel[];struct xdparam { unsigned short xd_boff; /* Cyl # starting partition */ unsigned short xd_nsect; /* Sect/track */ unsigned short xd_ncyl; /* Cyl/disk */ unsigned short xd_nhead; /* Heads/cyl */ unsigned short xd_bhead; /* Base head # for removable disk */ unsigned short xd_drive; /* Xylogics drive type ID */ int xd_nblk; int xd_badaddr; /* Disk block # of bad-block table */ struct dkbad xd_bad; unsigned char xd_unit;};#define CYL(p) (p*xdp->xd_nsect*xdp->xd_nhead) /* cyl to block conv */#define NSTD 4#define TIMEOUT 0xfffffunsigned long xdstd[NSTD] = { 0xee80, 0xee90, 0xeea0, 0xeeb0 };#ifdef BOOTBLOCK#define XD_MAXSIZE DEV_BSIZE#else BOOTBLOCK#define XD_MAXSIZE (4 * MAXBSIZE)#endif BOOTBLOCK/* * Structure of our DMA area */struct xddma { struct xdiopb xdiopb; char xdblock[XD_MAXSIZE]; /* R/W data */};/* * What resources we need to run */struct devinfo xdinfo = { sizeof (struct xddevice), sizeof (struct xddma), sizeof (struct xdparam), NSTD, xdstd, MAP_MBIO, XD_MAXSIZE, /* transfer size */};/* * What facilities we export to the world */int xdopen(), xdstrategy();extern int xxboot(), xxprobe();extern int nullsys();struct boottab xddriver = { "xd", xxprobe, xxboot, xdopen, nullsys, xdstrategy, "xd: Xylogics 7053 disk", &xdinfo,}; /* * Open a xdlogics disk. */xdopen(sip) register struct saioreq *sip;{ register struct xdparam *xdp; register struct xddevice *xdaddr; register struct xdiopb *xd; struct dk_label *label; u_short ppart;#ifndef BOOTBLOCK int xdspin();#endif !BOOTBLOCK xdp = (struct xdparam *)sip->si_devdata; xdaddr = (struct xddevice *)sip->si_devaddr; xd = &((struct xddma *)sip->si_dmaaddr)->xdiopb; xdp->xd_unit = sip->si_unit & 0x03; ppart = (sip->si_unit >> 2) & 1;#ifndef BOOTBLOCK /* Verify that xd is really present */ if (peekc((char *)&xdaddr->xd_csr) == -1) return (-1);#endif !BOOTBLOCK /* reset controller */ xdaddr->xd_csr = XD_RST; DELAY(300); xdp->xd_boff = 0; /* Don't offset block numbers */ xdp->xd_nsect = 2; xdp->xd_nhead = 2; xdp->xd_ncyl = 2; xdp->xd_bad.bt_mbz = -1;#ifndef BOOTBLOCK /* * Wait for disk to spin up, if necessary. */ if (!isspinning(xdspin, (char *)sip, 0)) return (-1);#endif !BOOTBLOCK label = (struct dk_label *) ((struct xddma *)sip->si_dmaaddr)->xdblock; label->dkl_magic = 0; if (xdcmd(XD_READ, sip, 0, (char *)label, 1)) goto badopen; if (chklabel(label)) goto badopen; if (ppart != label->dkl_ppart) goto badopen; goto foundlabel;badopen: printf(msg_nolabel); return (-1);foundlabel: xdp->xd_nhead = label->dkl_nhead; xdp->xd_nsect = label->dkl_nsect; xdp->xd_ncyl = label->dkl_ncyl + label->dkl_acyl; xdp->xd_boff = label->dkl_map[sip->si_boff].dkl_cylno; xdp->xd_nblk = label->dkl_map[sip->si_boff].dkl_nblk;#ifndef BOOTBLOCK if (xdp->xd_nblk == 0) return (-1);#endif BOOTBLOCK if (xdcmd(XD_WPAR, sip, 0, 0, 0)) printf("xd: init error %x\n", xd->xd_errno); /* * Fetch bad block info. */ xdp->xd_badaddr = ((int)xdp->xd_ncyl * xdp->xd_nhead - 1) * xdp->xd_nsect; if (xdcmd(XD_READ, sip, xdp->xd_badaddr, (char *)&xdp->xd_bad, 1)) printf("xd: no bad block info\n"); return (0);}xdstrategy(sip, rw) struct saioreq *sip; int rw;{ register int cmd = (rw == WRITE) ? XD_WRITE : XD_READ; register int boff; register struct xdparam *xdp = (struct xdparam *)sip->si_devdata; register short nsect;#ifndef BOOTBLOCK char *ma; int i, bn;#endif BOOTBLOCK boff = CYL(xdp->xd_boff);#ifdef BOOTBLOCK /* assert si_cc == DEV_BSIZE */ if (xdcmd(cmd, sip, sip->si_bn + boff, sip->si_ma, 1)) return (-1); return (sip->si_cc);#else BOOTBLOCK nsect = sip->si_cc / DEV_BSIZE; if (sip->si_bn + nsect > xdp->xd_nblk) nsect = xdp->xd_nblk - sip->si_bn; if (nsect <= 0) return (0); if (xdcmd(cmd, sip, sip->si_bn+boff, sip->si_ma, nsect) == 0) return (nsect*DEV_BSIZE); /* * Large transfer failed, now do one at a time */ bn = sip->si_bn + boff; ma = sip->si_ma; for (i = 0; i < nsect; i++) { if (xdcmd(cmd, sip, bn, ma, 1)) return (-1); bn++; ma += DEV_BSIZE; } return (nsect*DEV_BSIZE);#endif BOOTBLOCK}#ifndef BOOTBLOCK/* * This routine is called from isspinning() as the test condition. *//*ARGSUSED*/intxdspin(sip, dummy) struct saioreq *sip; int dummy;{#ifdef notdef register struct xdparam *xdp = (struct xdparam *)sip->si_devdata;#endif notdef register struct xdiopb *xd = &((struct xddma *)sip->si_dmaaddr)->xdiopb; (void) xdcmd(XD_RESTORE, sip, 0, (char *)0, 0); return ((xd->xd_dstat & XD_READY) ? 1 : 0);}#endif !BOOTBLOCKxdcmd(cmd, sip, bno, buf, nsect) int cmd; struct saioreq *sip; register int bno; char *buf; int nsect;{ register int i, t; register struct xdparam *xdp = (struct xdparam *)sip->si_devdata; register struct xdiopb *xd = &((struct xddma *)sip->si_dmaaddr)->xdiopb; register struct xddevice *xdaddr = (struct xddevice *)sip->si_devaddr; register char *bp = ((struct xddma *)sip->si_dmaaddr)->xdblock; unsigned short cylno, sect, head; int error, errcnt = 0; int timeout = 0; cylno = bno / CYL(1); sect = bno % xdp->xd_nsect; head = (bno / xdp->xd_nsect) % xdp->xd_nhead; /* If destination buffer is in DVMA space, use it directly */ if (buf >= DVMA_BASE) { bp = buf; /* Non-DVMA Buffer, if writing copy it into our DVMA buffer. */ } else if (cmd == XD_WRITE) { bcopy(buf, bp, nsect*DEV_BSIZE); }retry: bzero((char *)xd, sizeof (struct xdiopb)); xd->xd_cmd = cmd >> 8; switch (cmd) { case XD_WPAR: xd->xd_subfunc = XD_DRIVE; xd->xd_drparam = 0; xd->xd_nsect = (short) ((xdp->xd_nsect - 1) << 8); xd->xd_cylinder = xdp->xd_ncyl - 1; xd->xd_head = xdp->xd_nhead - 1; xd->xd_sector = xdp->xd_nsect - 1; break; default: xd->xd_subfunc = 0; xd->xd_nsect = nsect; xd->xd_cylinder = cylno; xd->xd_head = head; xd->xd_sector = sect; xd->xd_bufaddr = (int) (MB_DMA_ADDR(bp)); } xd->xd_unit = xdp->xd_unit & 3; xd->xd_intpri = 0; /* disable interrupt */ xd->xd_bufmod = XD_ADDRMOD24; /* standard supervisory */ t = (int) (MB_DMA_ADDR(xd)); xdaddr->xd_iopbaddr1 = (int) t; xdaddr->xd_iopbaddr2 = (int) t >> 8; xdaddr->xd_iopbaddr3 = (int) t >> 16; xdaddr->xd_iopbaddr4 = (int) t >> 24; xdaddr->xd_modifier = XD_ADDRMOD24; xdaddr->xd_csr = XD_AIO; while (!(xdaddr->xd_csr & XD_RIO) && timeout < TIMEOUT) timeout++; if (timeout == TIMEOUT) { printf("disk ctlr timeout\n"); xdaddr->xd_csr = XD_RST; /* reset the controller */ return(-1); } if (xdaddr->xd_csr & XD_FERR) { xdaddr->xd_csr = XD_RST; DELAY(300); xd->xd_iserr = 1; } xdaddr->xd_csr = XD_CLRIO; /* clear rio bit */ xdaddr->xd_csr = XD_CLRBS; /* release register */ if (xd->xd_iserr && xd->xd_errno != XDE_FECC) { if (nsect != 1) /* only try hard on single sectors */ return (-1); error = xd->xd_errno; if ((i = xdfwd(xdp, cylno, head, sect)) != 0) return xdcmd(cmd, sip, i, buf, 1); /* Attempt to reset the error condition */ if (cmd != XD_RESTORE) { xdaddr->xd_csr = XD_RST; /* reset the controller */ DELAY(300); /* and then the drive */ (void) xdcmd(XD_RESTORE, sip, 0, (char *)0, 1); } if (++errcnt < 5) goto retry; if (bno != 0) /* drive type probe */ printf("xd: error %x bno %d\n", error, bno); return (-1); /* Error */ } /* If user buffer not in DVMA space, copy data to it */ if (cmd == XD_READ && buf < DVMA_BASE) bcopy(bp, buf, nsect*DEV_BSIZE); return (0);}xdfwd(xdp, cn, tn, sn) register struct xdparam *xdp; int cn, tn, sn;{ register struct dkbad *bt = &xdp->xd_bad; register int i; if (bt->bt_mbz != 0) /* not initialized */ return (0); for (i=0; i<126; i++) /* FIXME constant */ if (bt->bt_bad[i].bt_cyl == cn && bt->bt_bad[i].bt_trksec == (tn<<8)+sn) { return (xdp->xd_badaddr - i - 1); } return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -