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
kmcprobe(reg)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
kmcattach(ui)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*/
kmcopen(dev,flag)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
kmcclose(dev)173 kmcclose(dev)
174 {
175 dev = minor(dev);
176 kmc[dev].k_stat &= ~SOPEN;
177 }
178
kmcread(dev,uio)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
kmcwrite(dev,uio)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*/
kmcioctl(dev,cmd,kk,mode)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
kmcrint(dev)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
kmcxint(dev)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
kmcload(dev,p1,p2,p3)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
kmcdclr(dev)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
kmcreset(dev)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