|
|
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.