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