BSD 4_4 release
[unix-history] / usr / src / sys / vax / datakit / new / kmc.c
CommitLineData
586a8972
MK
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
ad787160
C
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"
586a8972
MK
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
34int kmc_cnt = NKMC;
35
36struct 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
75struct kmcdevice {
76union {
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
95int rkmcdebug = 0;
96
97int kmcprobe(), kmcattach(), kmcxint();
98struct uba_device *kmcdinfo[NKMC];
99
100u_short kmcstd[] = { 0 };
101struct uba_driver kmcdriver =
102 { kmcprobe, 0, kmcattach, 0, kmcstd, "kmc", kmcdinfo };
103
104kmcprobe(reg)
105caddr_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
125kmcattach(ui)
126register 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*/
147kmcopen(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
174kmcclose(dev)
175{
176 dev = minor(dev);
177 kmc[dev].k_stat &= ~SOPEN;
178}
179
180kmcread(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
234kmcwrite(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*/
287kmcioctl(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
373kmcrint(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
403kmcxint(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
425kmcload(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
456kmcset(dev, type, rint)
457int (*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
475kmcdclr(dev)
476register 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
491kmcreset(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
508kmcifset(dev, init)
509int (*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
528kmcrfset(dev, reset)
529int (*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