xref: /csrg-svn/sys/tahoe/stand/vd.c (revision 29567)
1 /*	vd.c	7.3	86/07/16	*/
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)]+VBIOBASE))
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 > 5) {
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 (vdaccess_with_no_trailer(io, INIT, 8) & HRDERR) {
117 		vdprint_error(io->i_unit, "init error",
118 		    dcb.operrsta,dcb.err_code);
119 		_stop("");
120 	}
121 	if (vdaccess_with_no_trailer(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 	if (vdinfo[ctlr].vd_flags&VDF_BUSY) {
162 		DELAY(5500000);
163 		return;
164 	}
165 	io->i_unit &= ~3;
166 	if (vdaccess_with_no_trailer(io, VDSTART, ((unit * 6) + 62)) & HRDERR) {
167 		vdprint_error(io->i_unit, "start error",
168 		    dcb.operrsta, dcb.err_code);
169 		_stop("");
170 	}
171 	vdinfo[ctlr].vd_flags |= VDF_BUSY;
172 	io->i_unit = ounit;
173 	DELAY((unit * 5500000) + 62000000);
174 }
175 
176 /*
177  * This routine actually configures a particular drive.
178  *
179  * If the controller is an SMD/E controller then the number of sectors per
180  * track is loaded into the appropriate register, otherwise it is left
181  * alone because the old SMD controller requires a constant 32 sectors
182  * per track for it's drives. (an error would be returned if the value is
183  * loaded.)
184  */
185 vdconfigure(io, pass)
186 	register struct iob *io;
187 	int pass;
188 {
189 	register int ctlr = VDCTLR(io->i_unit), unit = VDUNIT(io->i_unit);
190 	register cdr *ctlr_addr = VDADDR(ctlr);
191 
192 	dcb.opcode = RSTCFG;		/* command */
193 	dcb.intflg = NOINT;
194 	dcb.nxtdcb = (fmt_dcb *)0;	/* end of chain */
195 	dcb.operrsta  = 0;
196 	dcb.devselect = (char)unit;
197 	dcb.trail.rstrail.ncyl = dkinfo[ctlr][unit].info.ncyl;
198 	dcb.trail.rstrail.nsurfaces = dkinfo[ctlr][unit].info.ntrak;
199 	if (vdinfo[ctlr].vd_type == SMD_ECTLR) {
200 		dcb.trailcnt = (char)4;
201 		dcb.trail.rstrail.nsectors = dkinfo[ctlr][unit].info.nsec;
202 		dcb.trail.rstrail.slip_sec = dkinfo[ctlr][unit].info.nslip;
203 	} else
204 		dcb.trailcnt = (char)2;
205 	mdcb.firstdcb = &dcb;
206 	mdcb.vddcstat = 0;
207 	VDDC_ATTENTION(ctlr_addr, &mdcb, vdinfo[ctlr].vd_type);
208 	if (!vdpoll(ctlr_addr,&dcb,10,vdinfo[ctlr].vd_type))
209 		_stop(" during drive configuration.\n");
210 	if ((dcb.operrsta & (NOTCYLERR | DRVNRDY)) && !pass) {
211 		vdstart_drive(io);
212 		vdconfigure(io, 1);
213 	}
214 	if (dcb.operrsta & HRDERR) {
215 		vdprint_error(io->i_unit, "configuration error",
216 		    dcb.operrsta, dcb.err_code);
217 		_stop("");
218 	}
219 }
220 
221 /*
222  * Strategy is called to do the actual I/O to the disk drives.
223  *
224  * Some simple checks are made to make sure we don't do anything rediculus,
225  * If everything is sane then the request is issued.
226  *
227  * If no errors occured then the original byte count is returned,
228  * otherwise -1 is returned to indicate an error occured.
229  */
230 vdstrategy(io, func)
231 	register struct iob *io;
232 	register int func;
233 {
234 	dskadr daddr;
235 	register int ctlr = VDCTLR(io->i_unit), unit = VDUNIT(io->i_unit);
236 	register fs_tab	*u_info = &dkinfo[ctlr][unit].info;
237 	register int op = (func == READ) ? RD : WD;
238 	register int blk;
239 
240 	if (io->i_cc == 0 || io->i_cc > 65535) {
241 		printf("dk%d: invalid transfer size %d\n", io->i_unit,
242 		    io->i_cc);
243 		_stop("");
244 	}
245 	blk = io->i_bn * DEV_BSIZE / u_info->secsize;
246 	daddr.sector = blk % u_info->nsec;
247 	daddr.track = (blk / u_info->nsec) % u_info->ntrak;
248 	daddr.cylinder = (blk/u_info->nsec) / u_info->ntrak;
249 	if (vdaccess(io, &daddr, op) & HRDERR) {
250 		vdprint_error(io->i_unit, "i/o error", dcb.operrsta,
251 		    dcb.err_code);
252 		return (-1);
253 	}
254 	mtpr(PADC, 0);
255 	return (io->i_cc);
256 }
257 
258 struct	vdstatus {
259 	int	bit;
260 	char	*meaning;
261 } vdstatus[] = {
262 	{ DRVNRDY,	"drive not ready" },
263 	{ INVDADR,	"invalid disk address" },
264 	{ DNEMEM,	"non-existent memory" },
265 	{ PARERR,	"parity error" },
266 	{ OPABRT,	"operation aborted" },
267 	{ WPTERR,	"drive write protect" },
268 	{ DSEEKERR,	"seek error" },
269 	{ UCDATERR,	"uncorrectable data error" },
270 	{ CTLRERR,	"controller error" },
271 	{ NOTCYLERR,	"not on cylinder" },
272 	{ INVCMD,	"invalid controller command" },
273 	{ -1,		"controller error" }
274 };
275 #define	NVDSTATUS	(sizeof (vdstatus) / sizeof (vdstatus[0]))
276 
277 vdprint_error(unit, str, status, smde_status)
278 	int unit;
279 	char *str;
280 	u_long status;
281 	u_long smde_status;
282 {
283 	register struct vdstatus *sp;
284 
285 	printf("dk%d: %s; ", unit, str);
286 	for (sp = vdstatus; sp < &vdstatus[NVDSTATUS]; sp++)
287 		if (status & sp->bit) {
288 			printf("%s. status %x", sp->meaning, status);
289 			break;
290 		}
291 	if (smde_status)
292 		printf(", code %x", smde_status);
293 	printf("\n");
294 }
295 
296 vdaccess_with_no_trailer(io, function, time)
297 	register struct iob *io;
298 	register int function, time;
299 {
300 	register int ctlr = VDCTLR(io->i_unit);
301 	register cdr *ctlr_addr = VDADDR(ctlr);
302 
303 	dcb.opcode = function;		/* command */
304 	dcb.intflg = NOINT;
305 	dcb.nxtdcb = (fmt_dcb *)0;	/* end of chain */
306 	dcb.operrsta  = 0;
307 	dcb.devselect = (char)VDUNIT(io->i_unit);
308 	dcb.trailcnt = (char)0;
309 	mdcb.firstdcb = &dcb;
310 	mdcb.vddcstat = 0;
311 	VDDC_ATTENTION(ctlr_addr, &mdcb, vdinfo[ctlr].vd_type);
312 	if (!vdpoll(ctlr_addr, &dcb, time, vdinfo[ctlr].vd_type))
313 		_stop(" during initialization operation.\n");
314 	return dcb.operrsta;
315 }
316 
317 vdaccess(io, daddr, func)
318 	register struct iob *io;
319 	dskadr *daddr;
320 	int func;
321 {
322 	register int ctlr = VDCTLR(io->i_unit);
323 	register cdr *ctlr_addr = VDADDR(ctlr);
324 
325 	dcb.opcode = (short)func;	/* format sector command */
326 	dcb.intflg = NOINT;
327 	dcb.nxtdcb = (fmt_dcb *)0;	/* end of chain */
328 	dcb.operrsta  = 0;
329 	dcb.devselect = (char)VDUNIT(io->i_unit);
330 	dcb.trailcnt = (char)(sizeof(trrw) / 4);
331 	dcb.trail.rwtrail.memadr = io->i_ma;
332 	dcb.trail.rwtrail.wcount = ((io->i_cc + 1) / sizeof(short));
333 	dcb.trail.rwtrail.disk.cylinder = daddr->cylinder;
334 	dcb.trail.rwtrail.disk.track = daddr->track;
335 	dcb.trail.rwtrail.disk.sector = daddr->sector;
336 	mdcb.firstdcb = &dcb;
337 	mdcb.vddcstat = 0;
338 	VDDC_ATTENTION(ctlr_addr, &mdcb, vdinfo[ctlr].vd_type);
339 	if (!vdpoll(ctlr_addr, &dcb, 60, vdinfo[ctlr].vd_type))
340 		_stop(" during i/o operation.\n");
341 	return (dcb.operrsta);
342 }
343 
344 /*
345  * Dump the MDCB and DCB for diagnostic purposes.  This
346  * routine is called whenever a fatal error is encountered.
347  */
348 vdprintdcb(ptr)
349 	register long *ptr;
350 {
351 	register long i, trailer_count;
352 
353 	printf("mdcb: %lx %lx %lx %lx\n", ptr[0], ptr[1], ptr[2], ptr[3]);
354 	if (ptr = (long *)*ptr) {
355 		printf("dcb:");
356 		trailer_count = ptr[3] & 0xff;
357 		for (i=0; i<7+trailer_count; i++) {
358 			uncache(&ptr[i]);
359 			printf("  %lx", ptr[i]);
360 		}
361 	}
362 	printf("\n");
363 	DELAY(5000000);
364 }
365 
366 /*
367  * Poll controller until operation completes
368  * or timeout expires.
369  */
370 vdpoll(addr, dcb, t, type)
371 	register cdr *addr;
372 	register fmt_dcb *dcb;
373 	register int t, type;
374 {
375 
376 	t *= 1000;
377 	uncache(&dcb->operrsta);
378 	while ((dcb->operrsta&(DCBCMP|DCBABT)) == 0) {
379 		DELAY(1000);
380 		uncache(&dcb->operrsta);
381 		if (--t <= 0) {
382 			printf("vd: controller timeout");
383 			VDDC_ABORT(addr, type);
384 			DELAY(30000);
385 			uncache(&dcb->operrsta);
386 			return (0);
387 		}
388 	}
389 	if (type == SMD_ECTLR) {
390 		uncache(&addr->cdr_csr);
391 		while (addr->cdr_csr&CS_GO) {
392 			DELAY(50);
393 			uncache(&addr->cdr_csr);
394 		}
395 		DELAY(300);
396 	}
397 	DELAY(200);
398 	uncache(&dcb->operrsta);
399 	return (1);
400 }
401