Commit | Line | Data |
---|---|---|
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 | ||
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 |