xref: /csrg-svn/sys/tahoe/stand/vd.c (revision 25931)
1 /*	vd.c	7.2	86/01/21	*/
2 /*
3 ** Stand alone driver for the VDDC controller
4 **	TAHOE Version, Oct 1983.
5 **
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 
20 #define TRUE		1
21 #define	FALSE		0
22 #define VDUNIT(x)	(minor(x) & 0x3)
23 #define VDCTLR(x)	(minor(x) >> 2)
24 
25 /*
26 **	MDCB
27 */
28 
29 fmt_mdcb	mdcb;
30 
31 /*
32 **	DCB
33 */
34 
35 fmt_dcb		dcb;
36 
37 /*
38 ** Unit specific information.
39 */
40 
41 struct {
42 	char	configured;
43 	fs_tab	info;
44 }unit_info[NVD][16];
45 
46 /*
47 ** Controller specific information.
48 */
49 
50 struct {
51 	unsigned char	ctlr_type;
52 	char		*ctlr_name;
53 	unsigned char	initialized;
54 	unsigned char	ctlr_started;
55 } ctlr_info[NVD];
56 
57 static char	junk[1024];
58 
59 #define	VDADDR(ctlr)	((cdr *)(vddcaddr[(ctlr)]+VBIOBASE))
60 /*
61 **
62 */
63 
64 vdopen(io)
65 register struct iob	*io;
66 {
67 	register int	ctlr = VDCTLR(io->i_unit);
68 	register int	unit = VDUNIT(io->i_unit);
69 	register int	i, j;
70 
71 	/* Make sure controller number is in range */
72 	if(ctlr >= NVD) {
73 		printf("vd%d: Unit number can't be greater than %x!\n",
74 		    io->i_unit, (NVD * 4) - 1);
75 		_stop("");
76 	}
77 	/* check file system for validity */
78 	if((io->i_boff < 0) || (io->i_boff > 5)) {
79 		printf("vd%d: File system #%d, should be less than #6.\n",
80 		    io->i_unit, io->i_boff);
81 		_stop("");
82 	}
83 	if(!ctlr_info[ctlr].initialized) {
84 		vdinit(io);	/* initialize controller/drive */
85 		ctlr_info[ctlr].initialized = TRUE;
86 		for(i=0; i<NVD; i++)
87 			for(j=0; j<16; j++)
88 				unit_info[i][j].configured = FALSE;
89 	}
90 	if(!unit_info[ctlr][unit].configured) {
91 		vdconfigure_drive(io);
92 		unit_info[ctlr][unit].configured = TRUE;
93 	}
94 	io->i_boff = unit_info[ctlr][unit].info.partition[io->i_boff].par_start;
95 }
96 
97 
98 /*
99 **
100 */
101 
102 vdinit(io)
103 register struct iob	*io;
104 {
105 	register int	ctlr = VDCTLR(io->i_unit);
106 	register int	unit = VDUNIT(io->i_unit);
107 	register cdr	*ctlr_addr = VDADDR(ctlr);
108 	register char	*ctlr_type;
109 
110 	/* Check to see if controller is really there */
111 	if(badaddr(ctlr_addr, 2)) {
112 		printf("vd%d: Controller %d is non-existant!\n",
113 		    io->i_unit, ctlr);
114 		_stop("");
115 	}
116 	/* Probe further to find what kind of controller it is */
117 	ctlr_addr->cdr_reset = 0xffffffff;
118 	DELAY(1000000);
119 	/* Probe further to find what kind of controller it is */
120 	if(ctlr_addr->cdr_reset != 0xffffffff) {
121 		ctlr_info[ctlr].ctlr_type = SMDCTLR;
122 		ctlr_info[ctlr].ctlr_name = "SMD";
123 		DELAY(1000000);
124 	}
125 	else {
126 		ctlr_info[ctlr].ctlr_type = SMD_ECTLR;
127 		ctlr_info[ctlr].ctlr_name = "SMD/E";
128 		ctlr_addr->cdr_reserved = 0x0;
129 		DELAY(3000000);
130 	}
131 	if(ctlr_info[ctlr].ctlr_type == SMD_ECTLR) {
132 		ctlr_addr->cdr_csr =  0;
133 		ctlr_addr->mdcb_tcf = AM_ENPDA;
134 		ctlr_addr->dcb_tcf = AM_ENPDA;
135 		ctlr_addr->trail_tcf = AM_ENPDA;
136 		ctlr_addr->data_tcf = AM_ENPDA;
137 		ctlr_addr->cdr_ccf = CCF_STS | XMD_32BIT | BSZ_16WRD |
138 		    CCF_ENP | CCF_EPE /* | CCF_EDE */ | CCF_ECE | CCF_ERR;
139 	}
140 	if(vdaccess_with_no_trailer(io, INIT, 8) & HRDERR) {
141 		vdprint_error(io->i_unit, "Initialization error",
142 		    dcb.operrsta,dcb.err_code);
143 		_stop("");
144 	}
145 	if(vdaccess_with_no_trailer(io, DIAG, 8) & HRDERR) {
146 		vdprint_error(io->i_unit, "Diagnostic error",
147 		    dcb.operrsta, dcb.err_code);
148 		_stop("");
149 	}
150 }
151 
152 
153 /*
154 **
155 */
156 
157 vdconfigure_drive(io)
158 register struct iob	*io;
159 {
160 	register int	ctlr = VDCTLR(io->i_unit);
161 	register int	unit = VDUNIT(io->i_unit);
162 	register fs_tab	*file_sys;
163 	dskadr		daddr;
164 	register int	i;
165 
166 	for(i=0; i < nvddrv; i++) {
167 		unit_info[ctlr][unit].info = vdst[i];
168 		if(ctlr_info[ctlr].ctlr_type == SMDCTLR)
169 			if(unit_info[ctlr][unit].info.nsec != 32)
170 				continue;
171 		vdconfigure(io, 0);
172 		daddr.cylinder = unit_info[ctlr][unit].info.ncyl - 2;
173 		daddr.track = unit_info[ctlr][unit].info.ntrak - 1;
174 		daddr.sector = unit_info[ctlr][unit].info.nsec - 1;
175 		io->i_ma = junk;
176 		io->i_cc = unit_info[ctlr][unit].info.secsize;
177 		if(!(vdaccess(io, &daddr, RD) & HRDERR))
178 			return;
179 	}
180 	printf("vd%d: Unrecognizable drive; controller %d, unit %d!\n",
181 	    io->i_unit, ctlr, unit);
182 	_stop("");
183 }
184 
185 
186 /*
187 **
188 */
189 
190 vdstart_drive(io)
191 register struct iob	*io;
192 {
193 	register int	ctlr = VDCTLR(io->i_unit);
194 	register int	unit = VDUNIT(io->i_unit);
195 	register int	io_unit_save = io->i_unit;
196 
197 	if(ctlr_info[ctlr].ctlr_started) {
198 		DELAY(5500000);
199 		return TRUE;
200 	}
201 	io->i_unit &= ~3;
202 	if(vdaccess_with_no_trailer(io, VDSTART, ((unit * 6) + 62)) & HRDERR) {
203 		vdprint_error(io->i_unit, "Start error",
204 		    dcb.operrsta, dcb.err_code);
205 		_stop("");
206 	}
207 	ctlr_info[ctlr].ctlr_started = TRUE;
208 	io->i_unit = io_unit_save;
209 	DELAY((unit * 5500000) + 62000000);
210 	return TRUE;
211 }
212 
213 
214 /*
215 **  This routine actually configures a particular drive.
216 **
217 **  If the controller is an SMD/E controller then the number of sectors per
218 **  track is loaded into the appropriate register, otherwise it is left
219 **  alone because the old SMD controller requires a constant 32 sectors
220 **  per track for it's drives. (an error would be returned if the value is
221 **  loaded.)
222 **
223 **  In the stand-alone spirit of things the system is halted if an error
224 **  occurs during this operation.
225 */
226 
227 vdconfigure(io, pass)
228 register struct iob	*io;
229 int	pass;
230 {
231 	register int	ctlr = VDCTLR(io->i_unit);
232 	register int	unit = VDUNIT(io->i_unit);
233 	register cdr	*ctlr_addr = VDADDR(ctlr);
234 
235 	dcb.opcode = RSTCFG;		/* command */
236 	dcb.intflg = NOINT;
237 	dcb.nxtdcb = (fmt_dcb *)0;	/* end of chain */
238 	dcb.operrsta  = 0;
239 	dcb.devselect = (char)unit;
240 	dcb.trail.rstrail.ncyl = unit_info[ctlr][unit].info.ncyl;
241 	dcb.trail.rstrail.nsurfaces = unit_info[ctlr][unit].info.ntrak;
242 	if(ctlr_info[ctlr].ctlr_type == SMD_ECTLR) {
243 		dcb.trailcnt = (char)4;
244 		dcb.trail.rstrail.nsectors = unit_info[ctlr][unit].info.nsec;
245 		dcb.trail.rstrail.slip_sec = unit_info[ctlr][unit].info.nslip;
246 	}
247 	else
248 		dcb.trailcnt = (char)2;
249 	mdcb.firstdcb = &dcb;
250 	mdcb.vddcstat = 0;
251 	VDDC_ATTENTION(ctlr_addr, &mdcb, ctlr_info[ctlr].ctlr_type);
252 	if (!vdpoll(ctlr_addr,&dcb,5,ctlr_info[ctlr].ctlr_type))
253 		_stop(" during drive configuration.\n");
254 	if(dcb.operrsta & (NOTCYLERR | DRVNRDY))
255 		if(!pass) {
256 			vdstart_drive(io);
257 			vdconfigure(io, 1);
258 		}
259 	if(dcb.operrsta & HRDERR) {
260 		vdprint_error(io->i_unit, "Configuration error",
261 		    dcb.operrsta, dcb.err_code);
262 		_stop("");
263 	}
264 }
265 
266 
267 /*
268 **  Strategy is called to the actual I/O to the disk drives.
269 **
270 **  Some simple checks are made to make sure we don't do anything rediculus,
271 **  If everything is sane then the request is issued.
272 **
273 **  If no errors occured then the original byte count is returned,
274 **  otherwise -1 is returned to indicate an error occured.
275 */
276 
277 vdstrategy(io, func)
278 register struct iob	*io;
279 register int func;
280 {
281 	dskadr		daddr;
282 	register int	ctlr = VDCTLR(io->i_unit);
283 	register int	unit = VDUNIT(io->i_unit);
284 	register fs_tab	*u_info = &unit_info[ctlr][unit].info;
285 	register int	op = (func == READ) ? RD : WD;
286 	register int	blk;
287 
288 	if(io->i_cc == 0)
289 		_stop("vd: Can't transfer zero length records!\n");
290 	if(io->i_cc > 0xffff)
291 		_stop("vd: Can't transfer greater than 2 to the 16th bytes!\n");
292 	blk = io->i_bn * DEV_BSIZE / u_info->secsize;
293 	daddr.sector = blk % u_info->nsec;
294 	daddr.track = (blk / u_info->nsec) % u_info->ntrak;
295 	daddr.cylinder = (blk/u_info->nsec) / u_info->ntrak;
296 	if(vdaccess(io, &daddr, op) & HRDERR) {
297 		vdprint_error(io->i_unit,"I/O error",dcb.operrsta,dcb.err_code);
298 		return(-1);
299 	}
300 	mtpr(PADC, 0);
301 	return(io->i_cc);
302 }
303 
304 
305 
306 /*
307 **
308 */
309 
310 vdprint_error(unit, str, status, smde_status)
311 int		unit;
312 char		*str;
313 unsigned long	status;
314 unsigned long	smde_status;
315 {
316 	printf("vd%d: %s; ", unit, str);
317 	if(status & DRVNRDY)
318 		printf("Drive is not ready");
319 	else if(status & INVDADR)
320 		printf("Invalid disk address issued");
321 	else if(status & DNEMEM)
322 		printf("Non-existent memory error");
323 	else if(status & PARERR)
324 		printf("Main memory parity error");
325 	else if(status & OPABRT)
326 		printf("Program aborted operation");
327 	else if(status & WPTERR)
328 		printf("Drive is write protected");
329 	else if(status & DSEEKERR)
330 		printf("Disk seek error");
331 	else if(status & UCDATERR)
332 		printf("Uncorrectable data error");
333 	else if(status & CTLRERR)
334 		printf("Controller faulted");
335 	else if(status & NOTCYLERR)
336 		printf("Not on cylinder error");
337 	else if(status & INVCMD)
338 		printf("Invalid command issued to controller");
339 	else
340 		printf("Controller error");
341 	printf("!  Status = 0x%x", status);
342 	if(smde_status)
343 		printf("  Error code = %x", smde_status);
344 	printf("\n");
345 }
346 
347 
348 /*
349 **
350 */
351 
352 vdaccess_with_no_trailer(io, function, time)
353 register struct iob	*io;
354 register int		function, time;
355 {
356 	register int	ctlr = VDCTLR(io->i_unit);
357 	register cdr	*ctlr_addr = VDADDR(ctlr);
358 
359 	dcb.opcode = function;		/* command */
360 	dcb.intflg = NOINT;
361 	dcb.nxtdcb = (fmt_dcb *)0;	/* end of chain */
362 	dcb.operrsta  = 0;
363 	dcb.devselect = (char)VDUNIT(io->i_unit);
364 	dcb.trailcnt = (char)0;
365 	mdcb.firstdcb = &dcb;
366 	mdcb.vddcstat = 0;
367 	VDDC_ATTENTION(ctlr_addr, &mdcb, ctlr_info[ctlr].ctlr_type);
368 	if (!vdpoll(ctlr_addr,&dcb,time,ctlr_info[ctlr].ctlr_type))
369 		_stop(" during initialization operation.\n");
370 	return dcb.operrsta;
371 }
372 
373 
374 /*
375 **
376 */
377 
378 vdaccess(io, daddr, func)
379 register struct iob	*io;
380 dskadr			*daddr;
381 int			func;
382 {
383 	register int	ctlr = VDCTLR(io->i_unit);
384 	register cdr	*ctlr_addr = VDADDR(ctlr);
385 
386 	dcb.opcode = (short)func;		/* format sector command */
387 	dcb.intflg = NOINT;
388 	dcb.nxtdcb = (fmt_dcb *)0;	/* end of chain */
389 	dcb.operrsta  = 0;
390 	dcb.devselect = (char)VDUNIT(io->i_unit);
391 	dcb.trailcnt = (char)(sizeof(trrw) / 4);
392 	dcb.trail.rwtrail.memadr = io->i_ma;
393 	dcb.trail.rwtrail.wcount = ((io->i_cc + 1) / sizeof(short));
394 	dcb.trail.rwtrail.disk.cylinder = daddr->cylinder;
395 	dcb.trail.rwtrail.disk.track = daddr->track;
396 	dcb.trail.rwtrail.disk.sector = daddr->sector;
397 	mdcb.firstdcb = &dcb;
398 	mdcb.vddcstat = 0;
399 	VDDC_ATTENTION(ctlr_addr, &mdcb, ctlr_info[ctlr].ctlr_type);
400 	if (!vdpoll(ctlr_addr, &dcb, 60, ctlr_info[ctlr].ctlr_type))
401 		_stop(" during I/O operation.\n");
402 	return dcb.operrsta;
403 }
404 
405 /*
406 **	Print_dcb() dumps the MDCB and DCB for diagnostic purposes.  This
407 ** routine is called whenever a fatal error is encountered.
408 */
409 
410 vdprintdcb(ptr)
411 register long	*ptr;
412 {
413 	register long	i;
414 	register long	trailer_count;
415 
416 	printf("Dump of MDCB: ");
417 	for(i=0; i<4; i++)
418 		printf("  %lx", *(ptr+i));
419 	if(ptr = (long *)*ptr) {
420 		printf(" and DCB:");
421 		trailer_count = *(ptr+3) & 0xff;
422 		for(i=0; i<7+trailer_count; i++) {
423 			uncache(ptr+i);
424 			printf("  %lx", *(ptr+i));
425 		}
426 	}
427 	printf("\n");
428 	for(i=0; i<5000000; i++) ;
429 }
430 
431 /*
432  * Poll controller until operation completes
433  * or timeout expires.
434  */
435 vdpoll(addr, dcb, t, type)
436 	register cdr *addr;
437 	register fmt_dcb *dcb;
438 	register int t, type;
439 {
440 
441 	t *= 1000;
442 	uncache(&dcb->operrsta);
443 	while ((dcb->operrsta&(DCBCMP|DCBABT)) == 0) {
444 		DELAY(1000);
445 		uncache(&dcb->operrsta);
446 		if (--t <= 0) {
447 			printf("vd: controller timeout");
448 			VDDC_ABORT(addr, type);
449 			DELAY(30000);
450 			uncache(&dcb->operrsta);
451 			return (0);
452 		}
453 	}
454 	if (type == SMD_ECTLR) {
455 		uncache(&addr->cdr_csr);
456 		while (addr->cdr_csr&CS_GO) {
457 			DELAY(50);
458 			uncache(&addr->cdr_csr);
459 		}
460 		DELAY(300);
461 	}
462 	DELAY(200);
463 	uncache(&dcb->operrsta);
464 	return (1);
465 }
466