xref: /original-bsd/sys/pmax/dev/pm.c (revision d4dfefc4)
1 /*-
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ralph Campbell and Rick Macklem.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)pm.c	7.8 (Berkeley) 11/15/92
11  */
12 
13 /*
14  *  devGraphics.c --
15  *
16  *     	This file contains machine-dependent routines for the graphics device.
17  *
18  *	Copyright (C) 1989 Digital Equipment Corporation.
19  *	Permission to use, copy, modify, and distribute this software and
20  *	its documentation for any purpose and without fee is hereby granted,
21  *	provided that the above copyright notice appears in all copies.
22  *	Digital Equipment Corporation makes no representations about the
23  *	suitability of this software for any purpose.  It is provided "as is"
24  *	without express or implied warranty.
25  *
26  * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c,
27  *	v 9.2 90/02/13 22:16:24 shirriff Exp $ SPRITE (DECWRL)";
28  */
29 
30 #include <pm.h>
31 #include <dc.h>
32 #if NPM > 0
33 #if NDC == 0
34 pm needs dc device
35 #else
36 
37 #include <sys/param.h>
38 #include <sys/time.h>
39 #include <sys/kernel.h>
40 #include <sys/ioctl.h>
41 #include <sys/file.h>
42 #include <sys/errno.h>
43 #include <sys/proc.h>
44 #include <sys/mman.h>
45 
46 #include <vm/vm.h>
47 
48 #include <machine/machConst.h>
49 #include <machine/dc7085cons.h>
50 #include <machine/pmioctl.h>
51 
52 #include <pmax/pmax/kn01.h>
53 #include <pmax/pmax/pmaxtype.h>
54 #include <pmax/pmax/cons.h>
55 
56 #include <pmax/dev/device.h>
57 #include <pmax/dev/pmreg.h>
58 #include <pmax/dev/fbreg.h>
59 
60 /*
61  * These need to be mapped into user space.
62  */
63 struct fbuaccess pmu;
64 struct pmax_fb pmfb;
65 static u_short curReg;		/* copy of PCCRegs.cmdr since it's read only */
66 
67 /*
68  * Forward references.
69  */
70 extern void fbScroll();
71 
72 static void pmScreenInit();
73 static void pmLoadCursor();
74 static void pmRestoreCursorColor();
75 static void pmCursorColor();
76 void pmPosCursor();
77 static void pmInitColorMap();
78 static void pmVDACInit();
79 static void pmLoadColorMap();
80 
81 extern void dcPutc(), fbKbdEvent(), fbMouseEvent(), fbMouseButtons();
82 void pmKbdEvent(), pmMouseEvent(), pmMouseButtons();
83 extern void (*dcDivertXInput)();
84 extern void (*dcMouseEvent)();
85 extern void (*dcMouseButtons)();
86 extern int pmax_boardtype;
87 extern u_short defCursor[32];
88 extern struct consdev cn_tab;
89 
90 int	pmprobe();
91 struct	driver pmdriver = {
92 	"pm", pmprobe, 0, 0,
93 };
94 
95 /*
96  * Test to see if device is present.
97  * Return true if found and initialized ok.
98  */
99 /*ARGSUSED*/
100 pmprobe(cp)
101 	register struct pmax_ctlr *cp;
102 {
103 	register struct pmax_fb *fp = &pmfb;
104 
105 	if (pmax_boardtype != DS_PMAX)
106 		return (0);
107 	if (!fp->initialized && !pminit())
108 		return (0);
109 	if (fp->isMono)
110 		printf("pm0 (monochrome display)\n");
111 	else
112 		printf("pm0 (color display)\n");
113 	return (1);
114 }
115 
116 /*ARGSUSED*/
117 pmopen(dev, flag)
118 	dev_t dev;
119 	int flag;
120 {
121 	register struct pmax_fb *fp = &pmfb;
122 	int s;
123 
124 	if (!fp->initialized)
125 		return (ENXIO);
126 	if (fp->GraphicsOpen)
127 		return (EBUSY);
128 
129 	fp->GraphicsOpen = 1;
130 	if (!fp->isMono)
131 		pmInitColorMap();
132 	/*
133 	 * Set up event queue for later
134 	 */
135 	fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
136 	fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
137 	fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
138 	fp->fbu->scrInfo.qe.tcNext = 0;
139 	fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
140 	s = spltty();
141 	dcDivertXInput = pmKbdEvent;
142 	dcMouseEvent = pmMouseEvent;
143 	dcMouseButtons = pmMouseButtons;
144 	splx(s);
145 	return (0);
146 }
147 
148 /*ARGSUSED*/
149 pmclose(dev, flag)
150 	dev_t dev;
151 	int flag;
152 {
153 	register struct pmax_fb *fp = &pmfb;
154 	int s;
155 
156 	if (!fp->GraphicsOpen)
157 		return (EBADF);
158 
159 	fp->GraphicsOpen = 0;
160 	if (!fp->isMono)
161 		pmInitColorMap();
162 	s = spltty();
163 	dcDivertXInput = (void (*)())0;
164 	dcMouseEvent = (void (*)())0;
165 	dcMouseButtons = (void (*)())0;
166 	splx(s);
167 	pmScreenInit();
168 	vmUserUnmap();
169 	bzero((caddr_t)fp->fr_addr,
170 		(fp->isMono ? 1024 / 8 : 1024) * 864);
171 	pmPosCursor(fp->col * 8, fp->row * 15);
172 	return (0);
173 }
174 
175 /*ARGSUSED*/
176 pmioctl(dev, cmd, data, flag)
177 	dev_t dev;
178 	caddr_t data;
179 {
180 	register PCCRegs *pcc = (PCCRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_PCC);
181 	register struct pmax_fb *fp = &pmfb;
182 	int s;
183 
184 	switch (cmd) {
185 	case QIOCGINFO:
186 	    {
187 		caddr_t addr;
188 		extern caddr_t vmUserMap();
189 
190 		/*
191 		 * Map the all the data the user needs access to into
192 		 * user space.
193 		 */
194 		addr = vmUserMap(sizeof(struct fbuaccess), (unsigned)fp->fbu);
195 		if (addr == (caddr_t)0)
196 			goto mapError;
197 		*(PM_Info **)data = &((struct fbuaccess *)addr)->scrInfo;
198 		fp->fbu->scrInfo.qe.events = ((struct fbuaccess *)addr)->events;
199 		fp->fbu->scrInfo.qe.tcs = ((struct fbuaccess *)addr)->tcs;
200 		/*
201 		 * Map the plane mask into the user's address space.
202 		 */
203 		addr = vmUserMap(4, (unsigned)
204 			MACH_PHYS_TO_UNCACHED(KN01_PHYS_COLMASK_START));
205 		if (addr == (caddr_t)0)
206 			goto mapError;
207 		fp->fbu->scrInfo.planemask = (char *)addr;
208 		/*
209 		 * Map the frame buffer into the user's address space.
210 		 */
211 		addr = vmUserMap(fp->isMono ? 256*1024 : 1024*1024,
212 			(unsigned)fp->fr_addr);
213 		if (addr == (caddr_t)0)
214 			goto mapError;
215 		fp->fbu->scrInfo.bitmap = (char *)addr;
216 		break;
217 
218 	mapError:
219 		vmUserUnmap();
220 		printf("Cannot map shared data structures\n");
221 		return (EIO);
222 	    }
223 
224 	case QIOCPMSTATE:
225 		/*
226 		 * Set mouse state.
227 		 */
228 		fp->fbu->scrInfo.mouse = *(pmCursor *)data;
229 		pmPosCursor(fp->fbu->scrInfo.mouse.x, fp->fbu->scrInfo.mouse.y);
230 		break;
231 
232 	case QIOCINIT:
233 		/*
234 		 * Initialize the screen.
235 		 */
236 		pmScreenInit();
237 		break;
238 
239 	case QIOCKPCMD:
240 	    {
241 		pmKpCmd *kpCmdPtr;
242 		unsigned char *cp;
243 
244 		kpCmdPtr = (pmKpCmd *)data;
245 		if (kpCmdPtr->nbytes == 0)
246 			kpCmdPtr->cmd |= 0x80;
247 		if (!fp->GraphicsOpen)
248 			kpCmdPtr->cmd |= 1;
249 		(*fp->KBDPutc)(fp->kbddev, (int)kpCmdPtr->cmd);
250 		cp = &kpCmdPtr->par[0];
251 		for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) {
252 			if (kpCmdPtr->nbytes == 1)
253 				*cp |= 0x80;
254 			(*fp->KBDPutc)(fp->kbddev, (int)*cp);
255 		}
256 		break;
257 	    }
258 
259 	case QIOCADDR:
260 		*(PM_Info **)data = &fp->fbu->scrInfo;
261 		break;
262 
263 	case QIOWCURSOR:
264 		pmLoadCursor((unsigned short *)data);
265 		break;
266 
267 	case QIOWCURSORCOLOR:
268 		pmCursorColor((unsigned int *)data);
269 		break;
270 
271 	case QIOSETCMAP:
272 		pmLoadColorMap((ColorMap *)data);
273 		break;
274 
275 	case QIOKERNLOOP:
276 		s = spltty();
277 		dcDivertXInput = pmKbdEvent;
278 		dcMouseEvent = pmMouseEvent;
279 		dcMouseButtons = pmMouseButtons;
280 		splx(s);
281 		break;
282 
283 	case QIOKERNUNLOOP:
284 		s = spltty();
285 		dcDivertXInput = (void (*)())0;
286 		dcMouseEvent = (void (*)())0;
287 		dcMouseButtons = (void (*)())0;
288 		splx(s);
289 		break;
290 
291 	case QIOVIDEOON:
292 		if (!fp->isMono)
293 			pmRestoreCursorColor();
294 		curReg |= PCC_ENPA;
295 		curReg &= ~PCC_FOPB;
296 		pcc->cmdr = curReg;
297 		break;
298 
299 	case QIOVIDEOOFF:
300 		if (!fp->isMono)
301 			pmVDACInit();
302 		curReg |= PCC_FOPB;
303 		curReg &= ~PCC_ENPA;
304 		pcc->cmdr = curReg;
305 		break;
306 
307 	default:
308 		printf("pm0: Unknown ioctl command %x\n", cmd);
309 		return (EINVAL);
310 	}
311 	return (0);
312 }
313 
314 pmselect(dev, flag, p)
315 	dev_t dev;
316 	int flag;
317 	struct proc *p;
318 {
319 	struct pmax_fb *fp = &pmfb;
320 
321 	switch (flag) {
322 	case FREAD:
323 		if (fp->fbu->scrInfo.qe.eHead != fp->fbu->scrInfo.qe.eTail)
324 			return (1);
325 		selrecord(p, &fp->selp);
326 		break;
327 	}
328 
329 	return (0);
330 }
331 
332 static u_char	bg_RGB[3];	/* background color for the cursor */
333 static u_char	fg_RGB[3];	/* foreground color for the cursor */
334 
335 /*
336  * Test to see if device is present.
337  * Return true if found and initialized ok.
338  */
339 pminit()
340 {
341 	register PCCRegs *pcc = (PCCRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_PCC);
342 	register struct pmax_fb *fp = &pmfb;
343 
344 	fp->isMono = *(volatile u_short *)MACH_PHYS_TO_UNCACHED(KN01_SYS_CSR) &
345 		KN01_CSR_MONO;
346 	fp->fr_addr = (char *)MACH_PHYS_TO_UNCACHED(KN01_PHYS_FBUF_START);
347 	fp->fbu = &pmu;
348 	fp->posCursor = pmPosCursor;
349 	fp->KBDPutc = dcPutc;
350 	fp->kbddev = makedev(DCDEV, DCKBD_PORT);
351 	if (fp->isMono) {
352 		/* check for no frame buffer */
353 		if (badaddr((char *)fp->fr_addr, 4))
354 			return (0);
355 	}
356 
357 	/*
358 	 * Initialize the screen.
359 	 */
360 	pcc->cmdr = PCC_FOPB | PCC_VBHI;
361 
362 	/*
363 	 * Initialize the cursor register.
364 	 */
365 	pcc->cmdr = curReg = PCC_ENPA | PCC_ENPB;
366 
367 	/*
368 	 * Initialize screen info.
369 	 */
370 	fp->fbu->scrInfo.max_row = 56;
371 	fp->fbu->scrInfo.max_col = 80;
372 	fp->fbu->scrInfo.max_x = 1024;
373 	fp->fbu->scrInfo.max_y = 864;
374 	fp->fbu->scrInfo.max_cur_x = 1023;
375 	fp->fbu->scrInfo.max_cur_y = 863;
376 	fp->fbu->scrInfo.version = 11;
377 	fp->fbu->scrInfo.mthreshold = 4;
378 	fp->fbu->scrInfo.mscale = 2;
379 	fp->fbu->scrInfo.min_cur_x = -15;
380 	fp->fbu->scrInfo.min_cur_y = -15;
381 	fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
382 	fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
383 	fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
384 	fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
385 	fp->fbu->scrInfo.qe.tcNext = 0;
386 
387 	/*
388 	 * Initialize the color map, the screen, and the mouse.
389 	 */
390 	pmInitColorMap();
391 	pmScreenInit();
392 	fbScroll(fp);
393 
394 	fp->initialized = 1;
395 	if (cn_tab.cn_fb == (struct pmax_fb *)0)
396 		cn_tab.cn_fb = fp;
397 	return (1);
398 }
399 
400 /*
401  * ----------------------------------------------------------------------------
402  *
403  * pmScreenInit --
404  *
405  *	Initialize the screen.
406  *
407  * Results:
408  *	None.
409  *
410  * Side effects:
411  *	The screen is initialized.
412  *
413  * ----------------------------------------------------------------------------
414  */
415 static void
416 pmScreenInit()
417 {
418 	register struct pmax_fb *fp = &pmfb;
419 
420 	/*
421 	 * Home the cursor.
422 	 * We want an LSI terminal emulation.  We want the graphics
423 	 * terminal to scroll from the bottom. So start at the bottom.
424 	 */
425 	fp->row = 55;
426 	fp->col = 0;
427 
428 	/*
429 	 * Load the cursor with the default values
430 	 *
431 	 */
432 	pmLoadCursor(defCursor);
433 }
434 
435 /*
436  * ----------------------------------------------------------------------------
437  *
438  * pmLoadCursor --
439  *
440  *	Routine to load the cursor Sprite pattern.
441  *
442  * Results:
443  *	None.
444  *
445  * Side effects:
446  *	The cursor is loaded into the hardware cursor.
447  *
448  * ----------------------------------------------------------------------------
449  */
450 static void
451 pmLoadCursor(cur)
452 	unsigned short *cur;
453 {
454 	register PCCRegs *pcc = (PCCRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_PCC);
455 	register int i;
456 
457 	curReg |= PCC_LODSA;
458 	pcc->cmdr = curReg;
459 	for (i = 0; i < 32; i++) {
460 		pcc->memory = cur[i];
461 		MachEmptyWriteBuffer();
462 	}
463 	curReg &= ~PCC_LODSA;
464 	pcc->cmdr = curReg;
465 }
466 
467 /*
468  * ----------------------------------------------------------------------------
469  *
470  * pmRestoreCursorColor --
471  *
472  *	Routine to restore the color of the cursor.
473  *
474  * Results:
475  *	None.
476  *
477  * Side effects:
478  *	None.
479  *
480  * ----------------------------------------------------------------------------
481  */
482 static void
483 pmRestoreCursorColor()
484 {
485 	register VDACRegs *vdac = (VDACRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_VDAC);
486 	register int i;
487 
488 	vdac->overWA = 0x04;
489 	MachEmptyWriteBuffer();
490 	for (i = 0; i < 3; i++) {
491 		vdac->over = bg_RGB[i];
492 		MachEmptyWriteBuffer();
493 	}
494 
495 	vdac->overWA = 0x08;
496 	MachEmptyWriteBuffer();
497 	vdac->over = 0x00;
498 	MachEmptyWriteBuffer();
499 	vdac->over = 0x00;
500 	MachEmptyWriteBuffer();
501 	vdac->over = 0x7f;
502 	MachEmptyWriteBuffer();
503 
504 	vdac->overWA = 0x0c;
505 	MachEmptyWriteBuffer();
506 	for (i = 0; i < 3; i++) {
507 		vdac->over = fg_RGB[i];
508 		MachEmptyWriteBuffer();
509 	}
510 }
511 
512 /*
513  * ----------------------------------------------------------------------------
514  *
515  * pmCursorColor --
516  *
517  *	Set the color of the cursor.
518  *
519  * Results:
520  *	None.
521  *
522  * Side effects:
523  *	None.
524  *
525  * ----------------------------------------------------------------------------
526  */
527 static void
528 pmCursorColor(color)
529 	unsigned int color[];
530 {
531 	register int i, j;
532 
533 	for (i = 0; i < 3; i++)
534 		bg_RGB[i] = (u_char)(color[i] >> 8);
535 
536 	for (i = 3, j = 0; i < 6; i++, j++)
537 		fg_RGB[j] = (u_char)(color[i] >> 8);
538 
539 	pmRestoreCursorColor();
540 }
541 
542 /*
543  * ----------------------------------------------------------------------------
544  *
545  * pmInitColorMap --
546  *
547  *	Initialize the color map.
548  *
549  * Results:
550  *	None.
551  *
552  * Side effects:
553  *	The colormap is initialized appropriately whether it is color or
554  *	monochrome.
555  *
556  * ----------------------------------------------------------------------------
557  */
558 static void
559 pmInitColorMap()
560 {
561 	register VDACRegs *vdac = (VDACRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_VDAC);
562 	struct pmax_fb *fp = &pmfb;
563 	register int i;
564 
565 	*(volatile char *)MACH_PHYS_TO_UNCACHED(KN01_PHYS_COLMASK_START) = 0xff;
566 	MachEmptyWriteBuffer();
567 
568 	if (fp->isMono) {
569 		vdac->mapWA = 0; MachEmptyWriteBuffer();
570 		for (i = 0; i < 256; i++) {
571 			vdac->map = (i < 128) ? 0x00 : 0xff;
572 			MachEmptyWriteBuffer();
573 			vdac->map = (i < 128) ? 0x00 : 0xff;
574 			MachEmptyWriteBuffer();
575 			vdac->map = (i < 128) ? 0x00 : 0xff;
576 			MachEmptyWriteBuffer();
577 		}
578 	} else {
579 		vdac->mapWA = 0; MachEmptyWriteBuffer();
580 		vdac->map = 0; MachEmptyWriteBuffer();
581 		vdac->map = 0; MachEmptyWriteBuffer();
582 		vdac->map = 0; MachEmptyWriteBuffer();
583 
584 		for (i = 1; i < 256; i++) {
585 			vdac->map = 0xff; MachEmptyWriteBuffer();
586 			vdac->map = 0xff; MachEmptyWriteBuffer();
587 			vdac->map = 0xff; MachEmptyWriteBuffer();
588 		}
589 	}
590 
591 	for (i = 0; i < 3; i++) {
592 		bg_RGB[i] = 0x00;
593 		fg_RGB[i] = 0xff;
594 	}
595 	pmRestoreCursorColor();
596 }
597 
598 /*
599  * ----------------------------------------------------------------------------
600  *
601  * pmVDACInit --
602  *
603  *	Initialize the VDAC.
604  *
605  * Results:
606  *	None.
607  *
608  * Side effects:
609  *	None.
610  *
611  * ----------------------------------------------------------------------------
612  */
613 static void
614 pmVDACInit()
615 {
616 	register VDACRegs *vdac = (VDACRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_VDAC);
617 
618 	/*
619 	 *
620 	 * Initialize the VDAC
621 	 */
622 	vdac->overWA = 0x04; MachEmptyWriteBuffer();
623 	vdac->over = 0x00; MachEmptyWriteBuffer();
624 	vdac->over = 0x00; MachEmptyWriteBuffer();
625 	vdac->over = 0x00; MachEmptyWriteBuffer();
626 	vdac->overWA = 0x08; MachEmptyWriteBuffer();
627 	vdac->over = 0x00; MachEmptyWriteBuffer();
628 	vdac->over = 0x00; MachEmptyWriteBuffer();
629 	vdac->over = 0x7f; MachEmptyWriteBuffer();
630 	vdac->overWA = 0x0c; MachEmptyWriteBuffer();
631 	vdac->over = 0xff; MachEmptyWriteBuffer();
632 	vdac->over = 0xff; MachEmptyWriteBuffer();
633 	vdac->over = 0xff; MachEmptyWriteBuffer();
634 }
635 
636 /*
637  * ----------------------------------------------------------------------------
638  *
639  * pmLoadColorMap --
640  *
641  *	Load the color map.
642  *
643  * Results:
644  *	None.
645  *
646  * Side effects:
647  *	The color map is loaded.
648  *
649  * ----------------------------------------------------------------------------
650  */
651 static void
652 pmLoadColorMap(ptr)
653 	ColorMap *ptr;
654 {
655 	register VDACRegs *vdac = (VDACRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_VDAC);
656 
657 	if (ptr->index > 256)
658 		return;
659 
660 	vdac->mapWA = ptr->index; MachEmptyWriteBuffer();
661 	vdac->map = ptr->Entry.red; MachEmptyWriteBuffer();
662 	vdac->map = ptr->Entry.green; MachEmptyWriteBuffer();
663 	vdac->map = ptr->Entry.blue; MachEmptyWriteBuffer();
664 }
665 
666 /*
667  *----------------------------------------------------------------------
668  *
669  * pmPosCursor --
670  *
671  *	Postion the cursor.
672  *
673  * Results:
674  *	None.
675  *
676  * Side effects:
677  *	None.
678  *
679  *----------------------------------------------------------------------
680  */
681 void
682 pmPosCursor(x, y)
683 	register int x, y;
684 {
685 	register PCCRegs *pcc = (PCCRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_PCC);
686 	register struct pmax_fb *fp = &pmfb;
687 
688 	if (y < fp->fbu->scrInfo.min_cur_y || y > fp->fbu->scrInfo.max_cur_y)
689 		y = fp->fbu->scrInfo.max_cur_y;
690 	if (x < fp->fbu->scrInfo.min_cur_x || x > fp->fbu->scrInfo.max_cur_x)
691 		x = fp->fbu->scrInfo.max_cur_x;
692 	fp->fbu->scrInfo.cursor.x = x;		/* keep track of real cursor */
693 	fp->fbu->scrInfo.cursor.y = y;		/* position, indep. of mouse */
694 	pcc->xpos = PCC_X_OFFSET + x;
695 	pcc->ypos = PCC_Y_OFFSET + y;
696 }
697 
698 /*
699  * pm keyboard and mouse input. Just punt to the generic ones in fb.c
700  */
701 void
702 pmKbdEvent(ch)
703 	int ch;
704 {
705 	fbKbdEvent(ch, &pmfb);
706 }
707 
708 void
709 pmMouseEvent(newRepPtr)
710 	MouseReport *newRepPtr;
711 {
712 	fbMouseEvent(newRepPtr, &pmfb);
713 }
714 
715 void
716 pmMouseButtons(newRepPtr)
717 	MouseReport *newRepPtr;
718 {
719 	fbMouseButtons(newRepPtr, &pmfb);
720 }
721 #endif /* NDC */
722 #endif /* NPM */
723