xref: /csrg-svn/sys/tahoe/stand/vd.c (revision 30312)
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