xref: /original-bsd/sys/vax/datakit/kmc.c (revision 07d71086)
1 /*
2  * kmc.c from 5.0 (on ihwld) hacked for 4.2
3  * Bob Van Valzah  2/7/84
4  */
5 
6 /* @(#)kmc.c	1.3 */
7 /*
8  * KMC11 microprocessor driver
9  */
10 
11 #include "kmc.h"
12 #if NKMC > 0
13 
14 #include "syslog.h"
15 #include "param.h"
16 #include "ioctl.h"
17 #include "tty.h"
18 #include "kmcreg.h"
19 #include "buf.h"
20 #include "dir.h"
21 #include "user.h"
22 #include "../vaxuba/ubavar.h"
23 #include "uio.h"
24 
25 #ifdef	DATAKIT
26 #include "dkitkmc.h"
27 #endif
28 #ifdef	RJE
29 #include "vpm.h"
30 #endif
31 
32 #define ushort u_short
33 
34 int	kmc_cnt = NKMC;
35 
36 struct kmc {
37 	struct clist k_inq;
38 	short	k_stat;
39 	char	k_type;
40 	short	k_arg[3];
41 	int	(*k_rint)();
42 	int	(*k_init)();
43 	int	(*k_reset)();
44 } kmc[NKMC];
45 
46 #define	KMC11A	1
47 #define	KMC11B	2
48 #define	KASIZE	1024
49 #define	KBSIZE	4096
50 
51 #define	RUN	(1<<7)
52 #define	MCLR	(1<<6)
53 #define	CWRT	(1<<5)
54 #define	LUB	(1<<4)
55 #define	LUA	(1<<3)
56 #define	ROMO	(1<<2)
57 #define	ROMI	(1<<1)
58 #define	STEP	(1<<0)
59 
60 #define RDYO	0200
61 #define RDYI	020
62 #define RQI	0200
63 #define IEI	01
64 #define IEO	020
65 
66 #define	STYPE	017
67 #define SRUN	020
68 #define SRINT	040
69 #define	SOPEN	0100
70 #define	SLOAD	0200
71 #define	SINIT	0400
72 #define	SRESET	01000
73 
74 
75 struct kmcdevice {
76 union {
77 	char	b[8];
78 	unsigned short	w[4];
79 } un;
80 };
81 
82 #define	bsel0	un.b[0]
83 #define	bsel1	un.b[1]
84 #define	bsel2	un.b[2]
85 #define	bsel3	un.b[3]
86 #define	bsel4	un.b[4]
87 #define	bsel5	un.b[5]
88 #define	bsel6	un.b[6]
89 #define	bsel7	un.b[7]
90 #define	sel0	un.w[0]
91 #define	sel2	un.w[1]
92 #define	sel4	un.w[2]
93 #define	sel6	un.w[3]
94 
95 int rkmcdebug = 0;
96 
97 int	kmcprobe(), kmcattach(), kmcxint();
98 struct	uba_device *kmcdinfo[NKMC];
99 
100 u_short kmcstd[] = { 0 };
101 struct uba_driver kmcdriver =
102 	{ kmcprobe, 0, kmcattach, 0, kmcstd, "kmc", kmcdinfo };
103 
104 kmcprobe(reg)
105 caddr_t reg;
106 {	register int br, cvec;	/* don't touch */
107 	register struct kmcdevice *kp = (struct kmcdevice *)reg;
108 	register s;
109 
110 #ifdef lint
111 	br = 0; cvec = br; br = cvec;
112 #endif
113 	s = spl7();
114 	kp->bsel1 = MCLR;
115 	splx(s);
116 	kp->bsel1 = ROMI;
117 	kp->sel4 = 0200;		/* bus request */
118 	kp->sel6 = 0121111;		/* mov csr4,obr */
119 	kp->bsel1 = ROMI|STEP;
120 	DELAY(50);
121 	kp->bsel1 = 0;
122 	return(1);
123 }
124 
125 kmcattach(ui)
126 register struct uba_device *ui;
127 {
128 	switch(ui->ui_flags & 03) {
129 #if NVPM>0
130 		case 0:
131 			vpminit(ui);
132 			break;
133 #endif
134 #if NDKITKMC>0
135 		case 1:
136 			dkkmc_attach(ui);
137 			break;
138 #endif
139 		default:
140 			log(LOG_ERR, "kmc%d: no protocol %d\n", ui->ui_unit,
141 			    ui->ui_flags);
142 			break;
143 	}
144 }
145 
146 /*ARGSUSED*/
147 kmcopen(dev, flag)
148 {
149 	register struct kmcdevice *kp;
150 	register struct kmc *tp;
151 	register sav;
152 
153 	dev = minor(dev);
154 	if (dev>=kmc_cnt || (tp = &kmc[dev])->k_stat&SOPEN) {
155 		return (ENXIO);
156 	}
157 	tp->k_stat |= SOPEN;
158 	if (tp->k_type==0) {
159 		kp = ((struct kmcdevice *)kmcdinfo[dev]->ui_addr);
160 		kp->bsel1 = ROMO;
161 		kp->sel4 = 0;
162 		sav = kp->sel6;
163 		kp->sel6 = ~sav;
164 		if (kp->sel6 != sav) {
165 			tp->k_type = KMC11B;
166 			kp->sel6 = sav;
167 		} else
168 			tp->k_type = KMC11A;
169 		kp->bsel1 = 0;
170 	}
171 	return (0);
172 }
173 
174 kmcclose(dev)
175 {
176 	dev = minor(dev);
177 	kmc[dev].k_stat &= ~SOPEN;
178 }
179 
180 kmcread(dev, uio)
181 	dev_t dev;
182 	struct uio *uio;
183 {
184 	register struct kmcdevice *kp;
185 	register ad;
186 	register int error = 0;
187 	int	dsize;
188 	ushort	sav;
189 
190 	dev = minor(dev);
191 	if (kmc[dev].k_stat&SRUN)
192 		return (0);
193 	dsize = (kmc[dev].k_type==KMC11A)?KASIZE:KBSIZE;
194 	kp = ((struct kmcdevice *)kmcdinfo[dev]->ui_addr);
195 	kp->bsel1 = 0;
196 	do {
197 		ad = uio->uio_offset;
198 		if (ad<dsize*2) {
199 			if (ad&1) {
200 				return (ENXIO);
201 			}
202 			ad >>= 1;
203 			kp->bsel1 = ROMO;
204 			kp->sel4 = ad;
205 			if ((error=ureadc(kp->bsel6, uio)) < 0)
206 				break;
207 			if ((error=ureadc(kp->bsel7, uio)) < 0)
208 				break;
209 			kp->bsel1 = 0;
210 		} else if (ad -= dsize*2, ad<dsize) {
211 			kp->bsel1 = ROMO;
212 			kp->sel4 = 0;
213 			sav = kp->sel6;
214 			kp->bsel1 = ROMI;
215 			kp->sel6 = 010000|(ad&0377);	/* mov ad,mar */
216 			kp->bsel1 = ROMI|STEP;
217 			kp->bsel1 = ROMI;
218 			kp->sel6 = 04000|((ad>>8)&0377);	/* mov %ad,%mar */
219 			kp->bsel1 = ROMI|STEP;
220 			kp->bsel1 = ROMI;
221 			kp->sel6 = 055222;	/* mov mem,csr2|mar++ */
222 			kp->bsel1 = ROMI|STEP;
223 			if ((error=ureadc(kp->bsel2, uio)) < 0)
224 				break;
225 			kp->bsel1 = ROMI;
226 			kp->sel6 = sav;
227 			kp->bsel1 = 0;
228 		} else
229 			break;
230 	} while (!error && uio->uio_resid);
231 	return (error);
232 }
233 
234 kmcwrite(dev, uio)
235 	dev_t dev;
236 	struct uio *uio;
237 {
238 	register struct kmcdevice *kp;
239 	register ad;
240 	int	dsize;
241 	short	ins;
242 	ushort	sav;
243 
244 	dev = minor(dev);
245 	if (kmc[dev].k_stat&SRUN)
246 		return (0);
247 	dsize = (kmc[dev].k_type==KMC11A)?KASIZE:KBSIZE;
248 	kp = ((struct kmcdevice *)kmcdinfo[dev]->ui_addr);
249 	kp->bsel1 = 0;
250 	while (uio->uio_resid) {
251 		ad = uio->uio_offset;
252 		if (ad<dsize*2) {
253 			if (ad&1) {
254 				return (ENXIO);
255 			}
256 			kp->bsel1 = ROMO;
257 			kp->sel4 = ad>>1;
258 			lobyte(ins) = uwritec(uio);
259 			hibyte(ins) = uwritec(uio);
260 			kp->sel6 = ins;
261 			kp->bsel1 |= CWRT;
262 			kp->bsel1 = 0;
263 		} else if (ad -= dsize*2, ad<dsize) {
264 			kp->bsel1 = ROMO;
265 			kp->sel4 = 0;
266 			sav = kp->sel6;
267 			kp->bsel1 = ROMI;
268 			kp->sel6 = 010000|(ad&0377);	/* mov ad,mar */
269 			kp->bsel1 = ROMI|STEP;
270 			kp->bsel1 = ROMI;
271 			kp->sel6 = 04000|((ad>>8)&0377);	/* mov %ad,%mar */
272 			kp->bsel1 = ROMI|STEP;
273 			kp->bsel1 = ROMI;
274 			kp->bsel2 = uwritec(uio);
275 			kp->sel6 = 0136440;	/* mov csr2,mem|mar++ */
276 			kp->bsel1 = ROMI|STEP;
277 			kp->bsel1 = ROMI;
278 			kp->sel6 = sav;
279 			kp->bsel1 = 0;
280 		} else
281 			break;
282 	}
283 	return (0);
284 }
285 
286 /*ARGSUSED*/
287 kmcioctl(dev, cmd, kk, mode)
288 	dev_t dev;
289 	struct kmcntl *kk;
290 {
291 	register struct kmcdevice *kp;
292 	register struct kmc *tp;
293 	short	csr[4];
294 	ushort	sav;
295 
296 	if (rkmcdebug) log(LOG_ERR, "kmcioctl: cmd=%d, kk->kmd=%d, kk->kcsr=0x%x, kk->kval=%d\n",
297 		cmd, kk->kmd, kk->kcsr, kk->kval);
298 	dev = minor(dev);
299 	if (cmd != KCSETA) {
300 		return (EINVAL);
301 	}
302 	kp = ((struct kmcdevice *)kmcdinfo[dev]->ui_addr);
303 	tp = &kmc[dev];
304 	switch (kk->kmd) {
305 	case KMCLR:
306 	case KRESET:
307 		spl7();
308 		kp->bsel1 = MCLR;
309 		spl0();
310 	case KSTOP:
311 		tp->k_stat &= ~SRUN;
312 		kp->bsel1 = 0;
313 		if (kk->kmd == KRESET) {
314 			tp->k_stat = 0;
315 			while(getc(&tp->k_inq) >= 0) ;
316 			if (tp->k_stat&SINIT)
317 				(*tp->k_init)(dev);
318 		}
319 		return (0);
320 	case KMS:
321 		if (tp->k_stat&SRUN)
322 			break;
323 		kp->bsel1 = ROMI|ROMO;
324 		sav = kp->sel6;
325 		kp->bsel1 = ROMI;
326 		kp->sel6 = kk->kval;
327 		kp->bsel1 = ROMI|STEP;
328 		kp->bsel1 = ROMI;
329 		kp->sel6 = sav;
330 		kp->bsel1 = 0;
331 		goto lcsr;
332 	case KSTEP:
333 		if (tp->k_stat&SRUN)
334 			break;
335 		kp->bsel1 |= STEP;
336 		kp->bsel1 = 0;
337 	case KCSR:
338 	lcsr:
339 		csr[0] = kp->sel0;
340 		csr[1] = kp->sel2;
341 		csr[2] = kp->sel4;
342 		csr[3] = kp->sel6;
343 		if (copyout((caddr_t)csr, (caddr_t)kk->kcsr, sizeof csr))
344 			return (EFAULT);
345 		return (0);
346 	case KWRCR:
347 		if (tp->k_stat&SRINT)
348 			break;
349 		kp->sel6 = kk->kval;
350 		return (0);
351 	case KRUN:
352 		if (tp->k_stat&SRUN)
353 			break;
354 		tp->k_stat &= ~STYPE;
355 		tp->k_stat |= (kk->kval&STYPE)|SRUN;
356 		kp->bsel1 |= RUN;
357 		if (tp->k_stat&SRINT) {
358 			spl5();
359 			kmcrint(dev);
360 			spl0();
361 		}
362 		if (tp->k_stat&SRESET)
363 			(*tp->k_reset)(dev);
364 		return (0);
365 	case KLU:
366 		kp->bsel1 = kk->kval&(LUA|LUB);
367 		return (0);
368 	}
369 	if (rkmcdebug) log(LOG_ERR, "kmcioctl: EIO exit, tp->k_stat=0x%x\n", tp->k_stat);
370 	return (EIO);
371 }
372 
373 kmcrint(dev)
374 {
375 	register struct kmcdevice *kp;
376 	register struct kmc *tp;
377 
378 	dev = minor(dev);
379 	kp = ((struct kmcdevice *)kmcdinfo[dev]->ui_addr);
380 	tp = &kmc[dev];
381 	kp->sel0 &= ~IEI;
382 	while (kp->sel2&RDYI) {
383 		if ((tp->k_stat&SLOAD) ||
384 		  q_to_b(&tp->k_inq, (char *)tp->k_arg, sizeof(tp->k_arg)) == sizeof(tp->k_arg)) {
385 			kp->sel2 = tp->k_arg[0]|RDYI;
386 			kp->sel4 = tp->k_arg[1];
387 			kp->sel6 = tp->k_arg[2];
388 			tp->k_stat &= ~SLOAD;
389 		} else {
390 			log(LOG_ERR, "Bad kmc %d load\n", dev);
391 		}
392 		if (tp->k_inq.c_cc==0) {
393 			kp->sel0 &= ~RQI;
394 			kp->sel2 &= ~RDYI;
395 			return;
396 		}
397 		kp->sel2 &= ~RDYI;
398 	}
399 	if ((tp->k_stat&SLOAD) || tp->k_inq.c_cc)
400 		kp->sel0 |= IEI|RQI;
401 }
402 
403 kmcxint(dev)
404 {
405 	register struct kmcdevice *kp;
406 	register struct kmc *tp;
407 	int p1, p2, p3, p4;
408 
409 	dev = minor(dev);
410 	kp = ((struct kmcdevice *)kmcdinfo[dev]->ui_addr);
411 	tp = &kmc[dev];
412 	kp->sel0 &= ~IEO;
413 	while(kp->sel2&RDYO) {
414 		p1 = (dev<<6)|(kp->bsel3&077);
415 		p2 = kp->bsel2&017;
416 		p3 = kp->sel4;
417 		p4 = kp->sel6;
418 		kp->sel2 &= ~RDYO;
419 		if (tp->k_stat&SRINT)
420 			(*tp->k_rint)(p1, p2, p3, p4);
421 	}
422 	kp->sel0 |= IEO;
423 }
424 
425 kmcload(dev, p1, p2, p3)
426 {
427 	register struct kmcdevice *kp;
428 	register struct kmc *tp;
429 	register unit;
430 	register sps;
431 
432 	dev = minor(dev);
433 	unit = (dev>>6)&03;
434 	tp = &kmc[unit];
435 	if (!(tp->k_stat&SRUN))
436 		return(-1);
437 	kp = ((struct kmcdevice *)kmcdinfo[unit]->ui_addr);	/* RAV unit is suspect */
438 	sps = spl5();
439 	if (tp->k_stat&SLOAD) {
440 		b_to_q((char *)tp->k_arg, sizeof(tp->k_arg), &tp->k_inq);
441 		tp->k_stat &= ~SLOAD;
442 	}
443 	kp->sel0 |= RQI;
444 	tp->k_arg[0] = (p1&017)|((dev&077)<<8);
445 	tp->k_arg[1] = p2;
446 	tp->k_arg[2] = p3;
447 	if (tp->k_inq.c_cc)
448 		b_to_q((char *)tp->k_arg, sizeof(tp->k_arg), &tp->k_inq);
449 	else
450 		tp->k_stat |= SLOAD;
451 	kmcrint(unit);
452 	splx(sps);
453 	return(tp->k_inq.c_cc);
454 }
455 
456 kmcset(dev, type, rint)
457 int (*rint)();
458 {
459 	register struct kmcdevice *kp;
460 	register struct kmc *tp;
461 	register unit;
462 
463 	dev = minor(dev);
464 	unit = (dev>>6)&03;
465 	kp = ((struct kmcdevice *)kmcdinfo[unit]->ui_addr);	/* RAV unit is suspect */
466 	tp = &kmc[unit];
467 	if ((tp->k_stat&(STYPE|SRUN|SOPEN))!=((type&STYPE)|SRUN))
468 		return (1);
469 	tp->k_stat |= SRINT;
470 	tp->k_rint = rint;
471 	kp->sel0 |= IEO;
472 	return(0);
473 }
474 
475 kmcdclr(dev)
476 register dev;
477 {
478 	register struct kmc *tp;
479 	register struct kmcdevice *kp;
480 
481 	dev = minor(dev);
482 	if (dev < 0 || dev >= kmc_cnt)
483 		return;
484 	tp = &kmc[dev];
485 	while (getc(&tp->k_inq) >= 0) ;
486 	kp = ((struct kmcdevice *)kmcdinfo[dev]->ui_addr);
487 	kp->sel0 = 0;
488 	kp->sel2 = 0;
489 }
490 
491 kmcreset(dev)
492 {
493 	register struct kmc *tp;
494 	register struct kmcdevice *kp;
495 	register s;
496 
497 	dev = minor(dev);
498 	tp = &kmc[dev];
499 	kp = ((struct kmcdevice *)kmcdinfo[dev]->ui_addr);
500 	s = spl7();
501 	kp->bsel1 = MCLR;
502 	splx(s);
503 	kp->bsel1 = 0;
504 	tp->k_stat = 0;
505 	while(getc(&tp->k_inq)>=0);
506 }
507 
508 kmcifset(dev, init)
509 int (*init)();
510 {
511 	register struct kmc *tp;
512 	register unit;
513 
514 	dev = minor(dev);
515 	unit = (dev>>6)&03;
516 	if (unit < 0 || unit >= kmc_cnt)
517 		return;
518 	tp = &kmc[unit];
519 	if (init==NULL) {
520 		tp->k_init = NULL;
521 		tp->k_stat &= ~SINIT;
522 	} else {
523 		tp->k_init = init;
524 		tp->k_stat |= SINIT;
525 	}
526 }
527 
528 kmcrfset(dev, reset)
529 int (*reset)();
530 {
531 	register struct kmc *tp;
532 	register unit;
533 
534 	dev = minor(dev);
535 	unit = (dev>>6)&03;
536 	if (unit < 0 || unit >= kmc_cnt)
537 		return;
538 	tp = &kmc[unit];
539 	if (reset==NULL) {
540 		tp->k_reset = NULL;
541 		tp->k_stat &= ~SRESET;
542 	} else {
543 		tp->k_reset = reset;
544 		tp->k_stat |= SRESET;
545 	}
546 }
547 #endif
548