xref: /csrg-svn/sys/pmax/dev/pm.c (revision 52130)
1*52130Smckusick /*
2*52130Smckusick  * Copyright (c) 1992 Regents of the University of California.
3*52130Smckusick  * All rights reserved.
4*52130Smckusick  *
5*52130Smckusick  * This code is derived from software contributed to Berkeley by
6*52130Smckusick  * Ralph Campbell.
7*52130Smckusick  *
8*52130Smckusick  * %sccs.include.redist.c%
9*52130Smckusick  *
10*52130Smckusick  *	@(#)pm.c	7.1 (Berkeley) 01/07/92
11*52130Smckusick  *
12*52130Smckusick  *  devGraphics.c --
13*52130Smckusick  *
14*52130Smckusick  *     	This file contains machine-dependent routines for the graphics device.
15*52130Smckusick  *
16*52130Smckusick  *	Copyright (C) 1989 Digital Equipment Corporation.
17*52130Smckusick  *	Permission to use, copy, modify, and distribute this software and
18*52130Smckusick  *	its documentation for any purpose and without fee is hereby granted,
19*52130Smckusick  *	provided that the above copyright notice appears in all copies.
20*52130Smckusick  *	Digital Equipment Corporation makes no representations about the
21*52130Smckusick  *	suitability of this software for any purpose.  It is provided "as is"
22*52130Smckusick  *	without express or implied warranty.
23*52130Smckusick  *
24*52130Smckusick  * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c,
25*52130Smckusick  *	v 9.2 90/02/13 22:16:24 shirriff Exp $ SPRITE (DECWRL)";
26*52130Smckusick  */
27*52130Smckusick 
28*52130Smckusick #include "pm.h"
29*52130Smckusick #if NPM > 0
30*52130Smckusick 
31*52130Smckusick #include "param.h"
32*52130Smckusick #include "time.h"
33*52130Smckusick #include "kernel.h"
34*52130Smckusick #include "ioctl.h"
35*52130Smckusick #include "file.h"
36*52130Smckusick #include "errno.h"
37*52130Smckusick #include "proc.h"
38*52130Smckusick #include "mman.h"
39*52130Smckusick #include "vm/vm.h"
40*52130Smckusick 
41*52130Smckusick #include "machine/machConst.h"
42*52130Smckusick #include "machine/machMon.h"
43*52130Smckusick #include "machine/dc7085cons.h"
44*52130Smckusick #include "machine/pmioctl.h"
45*52130Smckusick #include "machine/pmreg.h"
46*52130Smckusick 
47*52130Smckusick #include "device.h"
48*52130Smckusick #include "font.c"
49*52130Smckusick 
50*52130Smckusick /*
51*52130Smckusick  * Macro to translate from a time struct to milliseconds.
52*52130Smckusick  */
53*52130Smckusick #define TO_MS(tv) ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))
54*52130Smckusick 
55*52130Smckusick static u_short	curReg;		/* copy of PCCRegs.cmdr since it's read only */
56*52130Smckusick static int	isMono;		/* true if B&W frame buffer */
57*52130Smckusick static int	initialized;	/* true if 'probe' was successful */
58*52130Smckusick static int	GraphicsOpen;	/* true if the graphics device is open */
59*52130Smckusick static struct	proc *pm_selp;	/* process waiting for select */
60*52130Smckusick 
61*52130Smckusick /*
62*52130Smckusick  * These need to be mapped into user space.
63*52130Smckusick  */
64*52130Smckusick static struct pmuaccess {
65*52130Smckusick 	PM_Info		scrInfo;
66*52130Smckusick 	pmEvent		events[PM_MAXEVQ];
67*52130Smckusick 	pmTimeCoord	tcs[MOTION_BUFFER_SIZE];
68*52130Smckusick } pmu;
69*52130Smckusick 
70*52130Smckusick static u_char	bg_RGB[3];	/* background color for the cursor */
71*52130Smckusick static u_char	fg_RGB[3];	/* foreground color for the cursor */
72*52130Smckusick 
73*52130Smckusick /*
74*52130Smckusick  * The default cursor.
75*52130Smckusick  */
76*52130Smckusick unsigned short defCursor[32] = {
77*52130Smckusick /* plane A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
78*52130Smckusick 	      0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
79*52130Smckusick /* plane B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
80*52130Smckusick               0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
81*52130Smckusick 
82*52130Smckusick };
83*52130Smckusick 
84*52130Smckusick /*
85*52130Smckusick  * Font mask bits used by Blitc().
86*52130Smckusick  */
87*52130Smckusick static unsigned int fontmaskBits[16] = {
88*52130Smckusick 	0x00000000,
89*52130Smckusick 	0x00000001,
90*52130Smckusick 	0x00000100,
91*52130Smckusick 	0x00000101,
92*52130Smckusick 	0x00010000,
93*52130Smckusick 	0x00010001,
94*52130Smckusick 	0x00010100,
95*52130Smckusick 	0x00010101,
96*52130Smckusick 	0x01000000,
97*52130Smckusick 	0x01000001,
98*52130Smckusick 	0x01000100,
99*52130Smckusick 	0x01000101,
100*52130Smckusick 	0x01010000,
101*52130Smckusick 	0x01010001,
102*52130Smckusick 	0x01010100,
103*52130Smckusick 	0x01010101
104*52130Smckusick };
105*52130Smckusick 
106*52130Smckusick /*
107*52130Smckusick  * Forward references.
108*52130Smckusick  */
109*52130Smckusick static void ScreenInit();
110*52130Smckusick static void LoadCursor();
111*52130Smckusick static void RestoreCursorColor();
112*52130Smckusick static void CursorColor();
113*52130Smckusick static void InitColorMap();
114*52130Smckusick static void VDACInit();
115*52130Smckusick static void LoadColorMap();
116*52130Smckusick static void PosCursor();
117*52130Smckusick static void Scroll();
118*52130Smckusick static void Blitc();
119*52130Smckusick 
120*52130Smckusick extern void dcKBDPutc();
121*52130Smckusick 
122*52130Smckusick int	pmprobe();
123*52130Smckusick struct	driver pmdriver = {
124*52130Smckusick 	"pm", pmprobe, 0, 0,
125*52130Smckusick };
126*52130Smckusick 
127*52130Smckusick /*
128*52130Smckusick  * Test to see if device is present.
129*52130Smckusick  * Return true if found and initialized ok.
130*52130Smckusick  */
131*52130Smckusick /*ARGSUSED*/
132*52130Smckusick pmprobe(cp)
133*52130Smckusick 	register struct pmax_ctlr *cp;
134*52130Smckusick {
135*52130Smckusick 
136*52130Smckusick 	if (!initialized && !pminit())
137*52130Smckusick 		return (0);
138*52130Smckusick 	if (isMono)
139*52130Smckusick 		printf("pm0 (monochrome display)\n");
140*52130Smckusick 	else
141*52130Smckusick 		printf("pm0 (color display)\n");
142*52130Smckusick 	return (1);
143*52130Smckusick }
144*52130Smckusick 
145*52130Smckusick /*
146*52130Smckusick  * Test to see if device is present.
147*52130Smckusick  * Return true if found and initialized ok.
148*52130Smckusick  */
149*52130Smckusick pminit()
150*52130Smckusick {
151*52130Smckusick 	register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR;
152*52130Smckusick 
153*52130Smckusick 	isMono = *(u_short *)MACH_SYS_CSR_ADDR & MACH_CSR_MONO;
154*52130Smckusick 	if (isMono) {
155*52130Smckusick 		/* check for no frame buffer */
156*52130Smckusick 		if (badaddr((char *)MACH_UNCACHED_FRAME_BUFFER_ADDR, 4))
157*52130Smckusick 			return (0);
158*52130Smckusick 	}
159*52130Smckusick 
160*52130Smckusick 	/*
161*52130Smckusick 	 * Initialize the screen.
162*52130Smckusick 	 */
163*52130Smckusick #ifdef notdef
164*52130Smckusick 	DELAY(100000);		/* why? */
165*52130Smckusick #endif
166*52130Smckusick 	pcc->cmdr = PCC_FOPB | PCC_VBHI;
167*52130Smckusick 
168*52130Smckusick 	/*
169*52130Smckusick 	 * Initialize the cursor register.
170*52130Smckusick 	 */
171*52130Smckusick 	pcc->cmdr = curReg = PCC_ENPA | PCC_ENPB;
172*52130Smckusick 
173*52130Smckusick 	/*
174*52130Smckusick 	 * Initialize screen info.
175*52130Smckusick 	 */
176*52130Smckusick 	pmu.scrInfo.max_row = 56;
177*52130Smckusick 	pmu.scrInfo.max_col = 80;
178*52130Smckusick 	pmu.scrInfo.max_x = 1024;
179*52130Smckusick 	pmu.scrInfo.max_y = 864;
180*52130Smckusick 	pmu.scrInfo.max_cur_x = 1023;
181*52130Smckusick 	pmu.scrInfo.max_cur_y = 863;
182*52130Smckusick 	pmu.scrInfo.version = 11;
183*52130Smckusick 	pmu.scrInfo.mthreshold = 4;
184*52130Smckusick 	pmu.scrInfo.mscale = 2;
185*52130Smckusick 	pmu.scrInfo.min_cur_x = -15;
186*52130Smckusick 	pmu.scrInfo.min_cur_y = -15;
187*52130Smckusick 	pmu.scrInfo.qe.timestamp_ms = TO_MS(time);
188*52130Smckusick 	pmu.scrInfo.qe.eSize = PM_MAXEVQ;
189*52130Smckusick 	pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0;
190*52130Smckusick 	pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
191*52130Smckusick 	pmu.scrInfo.qe.tcNext = 0;
192*52130Smckusick 
193*52130Smckusick 	/*
194*52130Smckusick 	 * Initialize the color map, the screen, and the mouse.
195*52130Smckusick 	 */
196*52130Smckusick 	InitColorMap();
197*52130Smckusick 	ScreenInit();
198*52130Smckusick 	Scroll();
199*52130Smckusick 
200*52130Smckusick 	initialized = 1;
201*52130Smckusick 	return (1);
202*52130Smckusick }
203*52130Smckusick 
204*52130Smckusick /*
205*52130Smckusick  * ----------------------------------------------------------------------------
206*52130Smckusick  *
207*52130Smckusick  * ScreenInit --
208*52130Smckusick  *
209*52130Smckusick  *	Initialize the screen.
210*52130Smckusick  *
211*52130Smckusick  * Results:
212*52130Smckusick  *	None.
213*52130Smckusick  *
214*52130Smckusick  * Side effects:
215*52130Smckusick  *	The screen is initialized.
216*52130Smckusick  *
217*52130Smckusick  * ----------------------------------------------------------------------------
218*52130Smckusick  */
219*52130Smckusick static void
220*52130Smckusick ScreenInit()
221*52130Smckusick {
222*52130Smckusick 
223*52130Smckusick 	/*
224*52130Smckusick 	 * Home the cursor.
225*52130Smckusick 	 * We want an LSI terminal emulation.  We want the graphics
226*52130Smckusick 	 * terminal to scroll from the bottom. So start at the bottom.
227*52130Smckusick 	 */
228*52130Smckusick 	pmu.scrInfo.row = 55;
229*52130Smckusick 	pmu.scrInfo.col = 0;
230*52130Smckusick 
231*52130Smckusick 	/*
232*52130Smckusick 	 * Load the cursor with the default values
233*52130Smckusick 	 *
234*52130Smckusick 	 */
235*52130Smckusick 	LoadCursor(defCursor);
236*52130Smckusick }
237*52130Smckusick 
238*52130Smckusick /*
239*52130Smckusick  * ----------------------------------------------------------------------------
240*52130Smckusick  *
241*52130Smckusick  * LoadCursor --
242*52130Smckusick  *
243*52130Smckusick  *	Routine to load the cursor Sprite pattern.
244*52130Smckusick  *
245*52130Smckusick  * Results:
246*52130Smckusick  *	None.
247*52130Smckusick  *
248*52130Smckusick  * Side effects:
249*52130Smckusick  *	The cursor is loaded into the hardware cursor.
250*52130Smckusick  *
251*52130Smckusick  * ----------------------------------------------------------------------------
252*52130Smckusick  */
253*52130Smckusick static void
254*52130Smckusick LoadCursor(cur)
255*52130Smckusick 	unsigned short *cur;
256*52130Smckusick {
257*52130Smckusick 	register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR;
258*52130Smckusick 	register int i;
259*52130Smckusick 
260*52130Smckusick 	curReg |= PCC_LODSA;
261*52130Smckusick 	pcc->cmdr = curReg;
262*52130Smckusick 	for (i = 0; i < 32; i++) {
263*52130Smckusick 		pcc->memory = cur[i];
264*52130Smckusick 		MachEmptyWriteBuffer();
265*52130Smckusick 	}
266*52130Smckusick 	curReg &= ~PCC_LODSA;
267*52130Smckusick 	pcc->cmdr = curReg;
268*52130Smckusick }
269*52130Smckusick 
270*52130Smckusick /*
271*52130Smckusick  * ----------------------------------------------------------------------------
272*52130Smckusick  *
273*52130Smckusick  * RestoreCursorColor --
274*52130Smckusick  *
275*52130Smckusick  *	Routine to restore the color of the cursor.
276*52130Smckusick  *
277*52130Smckusick  * Results:
278*52130Smckusick  *	None.
279*52130Smckusick  *
280*52130Smckusick  * Side effects:
281*52130Smckusick  *	None.
282*52130Smckusick  *
283*52130Smckusick  * ----------------------------------------------------------------------------
284*52130Smckusick  */
285*52130Smckusick static void
286*52130Smckusick RestoreCursorColor()
287*52130Smckusick {
288*52130Smckusick 	register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR;
289*52130Smckusick 	register int i;
290*52130Smckusick 
291*52130Smckusick 	vdac->overWA = 0x04;
292*52130Smckusick 	MachEmptyWriteBuffer();
293*52130Smckusick 	for (i = 0; i < 3; i++) {
294*52130Smckusick 		vdac->over = bg_RGB[i];
295*52130Smckusick 		MachEmptyWriteBuffer();
296*52130Smckusick 	}
297*52130Smckusick 
298*52130Smckusick 	vdac->overWA = 0x08;
299*52130Smckusick 	MachEmptyWriteBuffer();
300*52130Smckusick 	vdac->over = 0x00;
301*52130Smckusick 	MachEmptyWriteBuffer();
302*52130Smckusick 	vdac->over = 0x00;
303*52130Smckusick 	MachEmptyWriteBuffer();
304*52130Smckusick 	vdac->over = 0x7f;
305*52130Smckusick 	MachEmptyWriteBuffer();
306*52130Smckusick 
307*52130Smckusick 	vdac->overWA = 0x0c;
308*52130Smckusick 	MachEmptyWriteBuffer();
309*52130Smckusick 	for (i = 0; i < 3; i++) {
310*52130Smckusick 		vdac->over = fg_RGB[i];
311*52130Smckusick 		MachEmptyWriteBuffer();
312*52130Smckusick 	}
313*52130Smckusick }
314*52130Smckusick 
315*52130Smckusick /*
316*52130Smckusick  * ----------------------------------------------------------------------------
317*52130Smckusick  *
318*52130Smckusick  * CursorColor --
319*52130Smckusick  *
320*52130Smckusick  *	Set the color of the cursor.
321*52130Smckusick  *
322*52130Smckusick  * Results:
323*52130Smckusick  *	None.
324*52130Smckusick  *
325*52130Smckusick  * Side effects:
326*52130Smckusick  *	None.
327*52130Smckusick  *
328*52130Smckusick  * ----------------------------------------------------------------------------
329*52130Smckusick  */
330*52130Smckusick static void
331*52130Smckusick CursorColor(color)
332*52130Smckusick 	unsigned int color[];
333*52130Smckusick {
334*52130Smckusick 	register int i, j;
335*52130Smckusick 
336*52130Smckusick 	for (i = 0; i < 3; i++)
337*52130Smckusick 		bg_RGB[i] = (u_char)(color[i] >> 8);
338*52130Smckusick 
339*52130Smckusick 	for (i = 3, j = 0; i < 6; i++, j++)
340*52130Smckusick 		fg_RGB[j] = (u_char)(color[i] >> 8);
341*52130Smckusick 
342*52130Smckusick 	RestoreCursorColor();
343*52130Smckusick }
344*52130Smckusick 
345*52130Smckusick /*
346*52130Smckusick  * ----------------------------------------------------------------------------
347*52130Smckusick  *
348*52130Smckusick  * InitColorMap --
349*52130Smckusick  *
350*52130Smckusick  *	Initialize the color map.
351*52130Smckusick  *
352*52130Smckusick  * Results:
353*52130Smckusick  *	None.
354*52130Smckusick  *
355*52130Smckusick  * Side effects:
356*52130Smckusick  *	The colormap is initialized appropriately whether it is color or
357*52130Smckusick  *	monochrome.
358*52130Smckusick  *
359*52130Smckusick  * ----------------------------------------------------------------------------
360*52130Smckusick  */
361*52130Smckusick static void
362*52130Smckusick InitColorMap()
363*52130Smckusick {
364*52130Smckusick 	register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR;
365*52130Smckusick 	register int i;
366*52130Smckusick 
367*52130Smckusick 	*(char *)MACH_PLANE_MASK_ADDR = 0xff;
368*52130Smckusick 	MachEmptyWriteBuffer();
369*52130Smckusick 
370*52130Smckusick 	if (isMono) {
371*52130Smckusick 		vdac->mapWA = 0; MachEmptyWriteBuffer();
372*52130Smckusick 		for (i = 0; i < 256; i++) {
373*52130Smckusick 			vdac->map = (i < 128) ? 0x00 : 0xff;
374*52130Smckusick 			MachEmptyWriteBuffer();
375*52130Smckusick 			vdac->map = (i < 128) ? 0x00 : 0xff;
376*52130Smckusick 			MachEmptyWriteBuffer();
377*52130Smckusick 			vdac->map = (i < 128) ? 0x00 : 0xff;
378*52130Smckusick 			MachEmptyWriteBuffer();
379*52130Smckusick 		}
380*52130Smckusick 	} else {
381*52130Smckusick 		vdac->mapWA = 0; MachEmptyWriteBuffer();
382*52130Smckusick 		vdac->map = 0; MachEmptyWriteBuffer();
383*52130Smckusick 		vdac->map = 0; MachEmptyWriteBuffer();
384*52130Smckusick 		vdac->map = 0; MachEmptyWriteBuffer();
385*52130Smckusick 
386*52130Smckusick 		for (i = 1; i < 256; i++) {
387*52130Smckusick 			vdac->map = 0xff; MachEmptyWriteBuffer();
388*52130Smckusick 			vdac->map = 0xff; MachEmptyWriteBuffer();
389*52130Smckusick 			vdac->map = 0xff; MachEmptyWriteBuffer();
390*52130Smckusick 		}
391*52130Smckusick 	}
392*52130Smckusick 
393*52130Smckusick 	for (i = 0; i < 3; i++) {
394*52130Smckusick 		bg_RGB[i] = 0x00;
395*52130Smckusick 		fg_RGB[i] = 0xff;
396*52130Smckusick 	}
397*52130Smckusick 	RestoreCursorColor();
398*52130Smckusick }
399*52130Smckusick 
400*52130Smckusick /*
401*52130Smckusick  * ----------------------------------------------------------------------------
402*52130Smckusick  *
403*52130Smckusick  * VDACInit --
404*52130Smckusick  *
405*52130Smckusick  *	Initialize the VDAC.
406*52130Smckusick  *
407*52130Smckusick  * Results:
408*52130Smckusick  *	None.
409*52130Smckusick  *
410*52130Smckusick  * Side effects:
411*52130Smckusick  *	None.
412*52130Smckusick  *
413*52130Smckusick  * ----------------------------------------------------------------------------
414*52130Smckusick  */
415*52130Smckusick static void
416*52130Smckusick VDACInit()
417*52130Smckusick {
418*52130Smckusick 	register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR;
419*52130Smckusick 
420*52130Smckusick 	/*
421*52130Smckusick 	 *
422*52130Smckusick 	 * Initialize the VDAC
423*52130Smckusick 	 */
424*52130Smckusick 	vdac->overWA = 0x04; MachEmptyWriteBuffer();
425*52130Smckusick 	vdac->over = 0x00; MachEmptyWriteBuffer();
426*52130Smckusick 	vdac->over = 0x00; MachEmptyWriteBuffer();
427*52130Smckusick 	vdac->over = 0x00; MachEmptyWriteBuffer();
428*52130Smckusick 	vdac->overWA = 0x08; MachEmptyWriteBuffer();
429*52130Smckusick 	vdac->over = 0x00; MachEmptyWriteBuffer();
430*52130Smckusick 	vdac->over = 0x00; MachEmptyWriteBuffer();
431*52130Smckusick 	vdac->over = 0x7f; MachEmptyWriteBuffer();
432*52130Smckusick 	vdac->overWA = 0x0c; MachEmptyWriteBuffer();
433*52130Smckusick 	vdac->over = 0xff; MachEmptyWriteBuffer();
434*52130Smckusick 	vdac->over = 0xff; MachEmptyWriteBuffer();
435*52130Smckusick 	vdac->over = 0xff; MachEmptyWriteBuffer();
436*52130Smckusick }
437*52130Smckusick 
438*52130Smckusick /*
439*52130Smckusick  * ----------------------------------------------------------------------------
440*52130Smckusick  *
441*52130Smckusick  * LoadColorMap --
442*52130Smckusick  *
443*52130Smckusick  *	Load the color map.
444*52130Smckusick  *
445*52130Smckusick  * Results:
446*52130Smckusick  *	None.
447*52130Smckusick  *
448*52130Smckusick  * Side effects:
449*52130Smckusick  *	The color map is loaded.
450*52130Smckusick  *
451*52130Smckusick  * ----------------------------------------------------------------------------
452*52130Smckusick  */
453*52130Smckusick static void
454*52130Smckusick LoadColorMap(ptr)
455*52130Smckusick 	ColorMap *ptr;
456*52130Smckusick {
457*52130Smckusick 	register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR;
458*52130Smckusick 
459*52130Smckusick 	if (ptr->index > 256)
460*52130Smckusick 		return;
461*52130Smckusick 
462*52130Smckusick 	vdac->mapWA = ptr->index; MachEmptyWriteBuffer();
463*52130Smckusick 	vdac->map = ptr->Entry.red; MachEmptyWriteBuffer();
464*52130Smckusick 	vdac->map = ptr->Entry.green; MachEmptyWriteBuffer();
465*52130Smckusick 	vdac->map = ptr->Entry.blue; MachEmptyWriteBuffer();
466*52130Smckusick }
467*52130Smckusick 
468*52130Smckusick /*
469*52130Smckusick  *----------------------------------------------------------------------
470*52130Smckusick  *
471*52130Smckusick  * pmKbdEvent --
472*52130Smckusick  *
473*52130Smckusick  *	Process a received character.
474*52130Smckusick  *
475*52130Smckusick  * Results:
476*52130Smckusick  *	None.
477*52130Smckusick  *
478*52130Smckusick  * Side effects:
479*52130Smckusick  *	Events added to the queue.
480*52130Smckusick  *
481*52130Smckusick  *----------------------------------------------------------------------
482*52130Smckusick  */
483*52130Smckusick void
484*52130Smckusick pmKbdEvent(ch)
485*52130Smckusick 	int ch;
486*52130Smckusick {
487*52130Smckusick 	register pmEvent *eventPtr;
488*52130Smckusick 	int i;
489*52130Smckusick 
490*52130Smckusick 	if (!GraphicsOpen)
491*52130Smckusick 		return;
492*52130Smckusick 
493*52130Smckusick 	/*
494*52130Smckusick 	 * See if there is room in the queue.
495*52130Smckusick 	 */
496*52130Smckusick 	i = PM_EVROUND(pmu.scrInfo.qe.eTail + 1);
497*52130Smckusick 	if (i == pmu.scrInfo.qe.eHead)
498*52130Smckusick 		return;
499*52130Smckusick 
500*52130Smckusick 	/*
501*52130Smckusick 	 * Add the event to the queue.
502*52130Smckusick 	 */
503*52130Smckusick 	eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
504*52130Smckusick 	eventPtr->type = BUTTON_RAW_TYPE;
505*52130Smckusick 	eventPtr->device = KEYBOARD_DEVICE;
506*52130Smckusick 	eventPtr->x = pmu.scrInfo.mouse.x;
507*52130Smckusick 	eventPtr->y = pmu.scrInfo.mouse.y;
508*52130Smckusick 	eventPtr->time = TO_MS(time);
509*52130Smckusick 	eventPtr->key = ch;
510*52130Smckusick 	pmu.scrInfo.qe.eTail = i;
511*52130Smckusick 	pmwakeup();
512*52130Smckusick }
513*52130Smckusick 
514*52130Smckusick /*
515*52130Smckusick  *----------------------------------------------------------------------
516*52130Smckusick  *
517*52130Smckusick  * pmMouseEvent --
518*52130Smckusick  *
519*52130Smckusick  *	Process a mouse event.
520*52130Smckusick  *
521*52130Smckusick  * Results:
522*52130Smckusick  *	None.
523*52130Smckusick  *
524*52130Smckusick  * Side effects:
525*52130Smckusick  *	An event is added to the event queue.
526*52130Smckusick  *
527*52130Smckusick  *----------------------------------------------------------------------
528*52130Smckusick  */
529*52130Smckusick void
530*52130Smckusick pmMouseEvent(newRepPtr)
531*52130Smckusick 	register MouseReport *newRepPtr;
532*52130Smckusick {
533*52130Smckusick 	unsigned milliSec;
534*52130Smckusick 	int i;
535*52130Smckusick 	pmEvent *eventPtr;
536*52130Smckusick 
537*52130Smckusick 	if (!GraphicsOpen)
538*52130Smckusick 		return;
539*52130Smckusick 
540*52130Smckusick 	milliSec = TO_MS(time);
541*52130Smckusick 
542*52130Smckusick 	/*
543*52130Smckusick 	 * Check to see if we have to accelerate the mouse
544*52130Smckusick 	 */
545*52130Smckusick 	if (pmu.scrInfo.mscale >= 0) {
546*52130Smckusick 		if (newRepPtr->dx >= pmu.scrInfo.mthreshold) {
547*52130Smckusick 			newRepPtr->dx +=
548*52130Smckusick 				(newRepPtr->dx - pmu.scrInfo.mthreshold) *
549*52130Smckusick 				pmu.scrInfo.mscale;
550*52130Smckusick 		}
551*52130Smckusick 		if (newRepPtr->dy >= pmu.scrInfo.mthreshold) {
552*52130Smckusick 			newRepPtr->dy +=
553*52130Smckusick 				(newRepPtr->dy - pmu.scrInfo.mthreshold) *
554*52130Smckusick 				pmu.scrInfo.mscale;
555*52130Smckusick 		}
556*52130Smckusick 	}
557*52130Smckusick 
558*52130Smckusick 	/*
559*52130Smckusick 	 * Update mouse position
560*52130Smckusick 	 */
561*52130Smckusick 	if (newRepPtr->state & MOUSE_X_SIGN) {
562*52130Smckusick 		pmu.scrInfo.mouse.x += newRepPtr->dx;
563*52130Smckusick 		if (pmu.scrInfo.mouse.x > pmu.scrInfo.max_cur_x)
564*52130Smckusick 			pmu.scrInfo.mouse.x = pmu.scrInfo.max_cur_x;
565*52130Smckusick 	} else {
566*52130Smckusick 		pmu.scrInfo.mouse.x -= newRepPtr->dx;
567*52130Smckusick 		if (pmu.scrInfo.mouse.x < pmu.scrInfo.min_cur_x)
568*52130Smckusick 			pmu.scrInfo.mouse.x = pmu.scrInfo.min_cur_x;
569*52130Smckusick 	}
570*52130Smckusick 	if (newRepPtr->state & MOUSE_Y_SIGN) {
571*52130Smckusick 		pmu.scrInfo.mouse.y -= newRepPtr->dy;
572*52130Smckusick 		if (pmu.scrInfo.mouse.y < pmu.scrInfo.min_cur_y)
573*52130Smckusick 			pmu.scrInfo.mouse.y = pmu.scrInfo.min_cur_y;
574*52130Smckusick 	} else {
575*52130Smckusick 		pmu.scrInfo.mouse.y += newRepPtr->dy;
576*52130Smckusick 		if (pmu.scrInfo.mouse.y > pmu.scrInfo.max_cur_y)
577*52130Smckusick 			pmu.scrInfo.mouse.y = pmu.scrInfo.max_cur_y;
578*52130Smckusick 	}
579*52130Smckusick 
580*52130Smckusick 	/*
581*52130Smckusick 	 * Move the hardware cursor.
582*52130Smckusick 	 */
583*52130Smckusick 	PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y);
584*52130Smckusick 
585*52130Smckusick 	/*
586*52130Smckusick 	 * Store the motion event in the motion buffer.
587*52130Smckusick 	 */
588*52130Smckusick 	pmu.tcs[pmu.scrInfo.qe.tcNext].time = milliSec;
589*52130Smckusick 	pmu.tcs[pmu.scrInfo.qe.tcNext].x = pmu.scrInfo.mouse.x;
590*52130Smckusick 	pmu.tcs[pmu.scrInfo.qe.tcNext].y = pmu.scrInfo.mouse.y;
591*52130Smckusick 	if (++pmu.scrInfo.qe.tcNext >= MOTION_BUFFER_SIZE)
592*52130Smckusick 		pmu.scrInfo.qe.tcNext = 0;
593*52130Smckusick 	if (pmu.scrInfo.mouse.y < pmu.scrInfo.mbox.bottom &&
594*52130Smckusick 	    pmu.scrInfo.mouse.y >=  pmu.scrInfo.mbox.top &&
595*52130Smckusick 	    pmu.scrInfo.mouse.x < pmu.scrInfo.mbox.right &&
596*52130Smckusick 	    pmu.scrInfo.mouse.x >=  pmu.scrInfo.mbox.left)
597*52130Smckusick 		return;
598*52130Smckusick 
599*52130Smckusick 	pmu.scrInfo.mbox.bottom = 0;
600*52130Smckusick 	if (PM_EVROUND(pmu.scrInfo.qe.eTail + 1) == pmu.scrInfo.qe.eHead)
601*52130Smckusick 		return;
602*52130Smckusick 
603*52130Smckusick 	i = PM_EVROUND(pmu.scrInfo.qe.eTail - 1);
604*52130Smckusick 	if ((pmu.scrInfo.qe.eTail != pmu.scrInfo.qe.eHead) &&
605*52130Smckusick 	    (i != pmu.scrInfo.qe.eHead)) {
606*52130Smckusick 		pmEvent *eventPtr;
607*52130Smckusick 
608*52130Smckusick 		eventPtr = &pmu.events[i];
609*52130Smckusick 		if (eventPtr->type == MOTION_TYPE) {
610*52130Smckusick 			eventPtr->x = pmu.scrInfo.mouse.x;
611*52130Smckusick 			eventPtr->y = pmu.scrInfo.mouse.y;
612*52130Smckusick 			eventPtr->time = milliSec;
613*52130Smckusick 			eventPtr->device = MOUSE_DEVICE;
614*52130Smckusick 			return;
615*52130Smckusick 		}
616*52130Smckusick 	}
617*52130Smckusick 	/*
618*52130Smckusick 	 * Put event into queue and wakeup any waiters.
619*52130Smckusick 	 */
620*52130Smckusick 	eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
621*52130Smckusick 	eventPtr->type = MOTION_TYPE;
622*52130Smckusick 	eventPtr->time = milliSec;
623*52130Smckusick 	eventPtr->x = pmu.scrInfo.mouse.x;
624*52130Smckusick 	eventPtr->y = pmu.scrInfo.mouse.y;
625*52130Smckusick 	eventPtr->device = MOUSE_DEVICE;
626*52130Smckusick 	pmu.scrInfo.qe.eTail = PM_EVROUND(pmu.scrInfo.qe.eTail + 1);
627*52130Smckusick 	pmwakeup();
628*52130Smckusick }
629*52130Smckusick 
630*52130Smckusick /*
631*52130Smckusick  *----------------------------------------------------------------------
632*52130Smckusick  *
633*52130Smckusick  * pmMouseButtons --
634*52130Smckusick  *
635*52130Smckusick  *	Process mouse buttons.
636*52130Smckusick  *
637*52130Smckusick  * Results:
638*52130Smckusick  *	None.
639*52130Smckusick  *
640*52130Smckusick  * Side effects:
641*52130Smckusick  *	None.
642*52130Smckusick  *
643*52130Smckusick  *----------------------------------------------------------------------
644*52130Smckusick  */
645*52130Smckusick void
646*52130Smckusick pmMouseButtons(newRepPtr)
647*52130Smckusick 	MouseReport *newRepPtr;
648*52130Smckusick {
649*52130Smckusick 	static char temp, oldSwitch, newSwitch;
650*52130Smckusick 	int i, j;
651*52130Smckusick 	pmEvent *eventPtr;
652*52130Smckusick 	static MouseReport lastRep;
653*52130Smckusick 
654*52130Smckusick 	if (!GraphicsOpen)
655*52130Smckusick 		return;
656*52130Smckusick 
657*52130Smckusick 	newSwitch = newRepPtr->state & 0x07;
658*52130Smckusick 	oldSwitch = lastRep.state & 0x07;
659*52130Smckusick 
660*52130Smckusick 	temp = oldSwitch ^ newSwitch;
661*52130Smckusick 	if (temp == 0)
662*52130Smckusick 		return;
663*52130Smckusick 	for (j = 1; j < 8; j <<= 1) {
664*52130Smckusick 		if ((j & temp) == 0)
665*52130Smckusick 			continue;
666*52130Smckusick 
667*52130Smckusick 		/*
668*52130Smckusick 		 * Check for room in the queue
669*52130Smckusick 		 */
670*52130Smckusick 		i = PM_EVROUND(pmu.scrInfo.qe.eTail+1);
671*52130Smckusick 		if (i == pmu.scrInfo.qe.eHead)
672*52130Smckusick 			return;
673*52130Smckusick 
674*52130Smckusick 		/*
675*52130Smckusick 		 * Put event into queue.
676*52130Smckusick 		 */
677*52130Smckusick 		eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
678*52130Smckusick 
679*52130Smckusick 		switch (j) {
680*52130Smckusick 		case RIGHT_BUTTON:
681*52130Smckusick 			eventPtr->key = EVENT_RIGHT_BUTTON;
682*52130Smckusick 			break;
683*52130Smckusick 
684*52130Smckusick 		case MIDDLE_BUTTON:
685*52130Smckusick 			eventPtr->key = EVENT_MIDDLE_BUTTON;
686*52130Smckusick 			break;
687*52130Smckusick 
688*52130Smckusick 		case LEFT_BUTTON:
689*52130Smckusick 			eventPtr->key = EVENT_LEFT_BUTTON;
690*52130Smckusick 		}
691*52130Smckusick 		if (newSwitch & j)
692*52130Smckusick 			eventPtr->type = BUTTON_DOWN_TYPE;
693*52130Smckusick 		else
694*52130Smckusick 			eventPtr->type = BUTTON_UP_TYPE;
695*52130Smckusick 		eventPtr->device = MOUSE_DEVICE;
696*52130Smckusick 
697*52130Smckusick 		eventPtr->time = TO_MS(time);
698*52130Smckusick 		eventPtr->x = pmu.scrInfo.mouse.x;
699*52130Smckusick 		eventPtr->y = pmu.scrInfo.mouse.y;
700*52130Smckusick 	}
701*52130Smckusick 	pmu.scrInfo.qe.eTail = i;
702*52130Smckusick 	pmwakeup();
703*52130Smckusick 
704*52130Smckusick 	lastRep = *newRepPtr;
705*52130Smckusick 	pmu.scrInfo.mswitches = newSwitch;
706*52130Smckusick }
707*52130Smckusick 
708*52130Smckusick /*
709*52130Smckusick  *----------------------------------------------------------------------
710*52130Smckusick  *
711*52130Smckusick  * PosCursor --
712*52130Smckusick  *
713*52130Smckusick  *	Postion the cursor.
714*52130Smckusick  *
715*52130Smckusick  * Results:
716*52130Smckusick  *	None.
717*52130Smckusick  *
718*52130Smckusick  * Side effects:
719*52130Smckusick  *	None.
720*52130Smckusick  *
721*52130Smckusick  *----------------------------------------------------------------------
722*52130Smckusick  */
723*52130Smckusick static void
724*52130Smckusick PosCursor(x, y)
725*52130Smckusick 	register int x, y;
726*52130Smckusick {
727*52130Smckusick 	register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR;
728*52130Smckusick 
729*52130Smckusick 	if (y < pmu.scrInfo.min_cur_y || y > pmu.scrInfo.max_cur_y)
730*52130Smckusick 		y = pmu.scrInfo.max_cur_y;
731*52130Smckusick 	if (x < pmu.scrInfo.min_cur_x || x > pmu.scrInfo.max_cur_x)
732*52130Smckusick 		x = pmu.scrInfo.max_cur_x;
733*52130Smckusick 	pmu.scrInfo.cursor.x = x;		/* keep track of real cursor */
734*52130Smckusick 	pmu.scrInfo.cursor.y = y;		/* position, indep. of mouse */
735*52130Smckusick 	pcc->xpos = PCC_X_OFFSET + x;
736*52130Smckusick 	pcc->ypos = PCC_Y_OFFSET + y;
737*52130Smckusick }
738*52130Smckusick 
739*52130Smckusick /*
740*52130Smckusick  *----------------------------------------------------------------------
741*52130Smckusick  *
742*52130Smckusick  * Scroll --
743*52130Smckusick  *
744*52130Smckusick  *	Scroll the screen.
745*52130Smckusick  *
746*52130Smckusick  * Results:
747*52130Smckusick  *	None.
748*52130Smckusick  *
749*52130Smckusick  * Side effects:
750*52130Smckusick  *	None.
751*52130Smckusick  *
752*52130Smckusick  *----------------------------------------------------------------------
753*52130Smckusick  */
754*52130Smckusick static void
755*52130Smckusick Scroll()
756*52130Smckusick {
757*52130Smckusick 	register int *dest, *src;
758*52130Smckusick 	register int *end;
759*52130Smckusick 	register int temp0, temp1, temp2, temp3;
760*52130Smckusick 	register int i, scanInc, lineCount;
761*52130Smckusick 	int line;
762*52130Smckusick 
763*52130Smckusick 	/*
764*52130Smckusick 	 * If the mouse is on we don't scroll so that the bit map remains sane.
765*52130Smckusick 	 */
766*52130Smckusick 	if (GraphicsOpen) {
767*52130Smckusick 		pmu.scrInfo.row = 0;
768*52130Smckusick 		return;
769*52130Smckusick 	}
770*52130Smckusick 
771*52130Smckusick 	/*
772*52130Smckusick 	 *  The following is an optimization to cause the scrolling
773*52130Smckusick 	 *  of text to be memory limited.  Basically the writebuffer is
774*52130Smckusick 	 *  4 words (32 bits ea.) long so to achieve maximum speed we
775*52130Smckusick 	 *  read and write in multiples of 4 words. We also limit the
776*52130Smckusick 	 *  size to be 80 characters for more speed.
777*52130Smckusick 	 */
778*52130Smckusick 	if (isMono) {
779*52130Smckusick 		lineCount = 5;
780*52130Smckusick 		line = 1920 * 2;
781*52130Smckusick 		scanInc = 44;
782*52130Smckusick 	} else {
783*52130Smckusick 		lineCount = 40;
784*52130Smckusick 		scanInc = 96;
785*52130Smckusick 		line = 1920 * 8;
786*52130Smckusick 	}
787*52130Smckusick 	src = (int *)(MACH_UNCACHED_FRAME_BUFFER_ADDR + line);
788*52130Smckusick 	dest = (int *)(MACH_UNCACHED_FRAME_BUFFER_ADDR);
789*52130Smckusick 	end = (int *)(MACH_UNCACHED_FRAME_BUFFER_ADDR + (60 * line) - line);
790*52130Smckusick 	do {
791*52130Smckusick 		i = 0;
792*52130Smckusick 		do {
793*52130Smckusick 			temp0 = src[0];
794*52130Smckusick 			temp1 = src[1];
795*52130Smckusick 			temp2 = src[2];
796*52130Smckusick 			temp3 = src[3];
797*52130Smckusick 			dest[0] = temp0;
798*52130Smckusick 			dest[1] = temp1;
799*52130Smckusick 			dest[2] = temp2;
800*52130Smckusick 			dest[3] = temp3;
801*52130Smckusick 			dest += 4;
802*52130Smckusick 			src += 4;
803*52130Smckusick 			i++;
804*52130Smckusick 		} while (i < lineCount);
805*52130Smckusick 		src += scanInc;
806*52130Smckusick 		dest += scanInc;
807*52130Smckusick 	} while (src < end);
808*52130Smckusick 
809*52130Smckusick 	/*
810*52130Smckusick 	 * Now zero out the last two lines
811*52130Smckusick 	 */
812*52130Smckusick 	bzero(MACH_UNCACHED_FRAME_BUFFER_ADDR + (pmu.scrInfo.row * line),
813*52130Smckusick 		3 * line);
814*52130Smckusick }
815*52130Smckusick 
816*52130Smckusick /*
817*52130Smckusick  *----------------------------------------------------------------------
818*52130Smckusick  *
819*52130Smckusick  * pmPutc --
820*52130Smckusick  *
821*52130Smckusick  *	Write a character to the console.
822*52130Smckusick  *
823*52130Smckusick  * Results:
824*52130Smckusick  *	None.
825*52130Smckusick  *
826*52130Smckusick  * Side effects:
827*52130Smckusick  *	None.
828*52130Smckusick  *
829*52130Smckusick  *----------------------------------------------------------------------
830*52130Smckusick  */
831*52130Smckusick pmPutc(c)
832*52130Smckusick 	register int c;
833*52130Smckusick {
834*52130Smckusick 	int s;
835*52130Smckusick 
836*52130Smckusick 	s = splhigh();	/* in case we do any printf's at interrupt time */
837*52130Smckusick 	if (initialized) {
838*52130Smckusick #ifdef DEBUG
839*52130Smckusick 		/*
840*52130Smckusick 		 * If the HELP key is pressed, wait for another
841*52130Smckusick 		 * HELP key press to start/stop output.
842*52130Smckusick 		 */
843*52130Smckusick 		if (dcKBDGetc() == LK_HELP) {
844*52130Smckusick 			while (dcKBDGetc() != LK_HELP)
845*52130Smckusick 				;
846*52130Smckusick 		}
847*52130Smckusick #endif
848*52130Smckusick 		Blitc(c);
849*52130Smckusick 	} else {
850*52130Smckusick 		void (*f)() = (void (*)())MACH_MON_PUTCHAR;
851*52130Smckusick 
852*52130Smckusick 		(*f)(c);
853*52130Smckusick 	}
854*52130Smckusick 	splx(s);
855*52130Smckusick }
856*52130Smckusick 
857*52130Smckusick /*
858*52130Smckusick  *----------------------------------------------------------------------
859*52130Smckusick  *
860*52130Smckusick  * Blitc --
861*52130Smckusick  *
862*52130Smckusick  *	Write a character to the screen.
863*52130Smckusick  *
864*52130Smckusick  * Results:
865*52130Smckusick  *	None.
866*52130Smckusick  *
867*52130Smckusick  * Side effects:
868*52130Smckusick  *	None.
869*52130Smckusick  *
870*52130Smckusick  *----------------------------------------------------------------------
871*52130Smckusick  */
872*52130Smckusick static void
873*52130Smckusick Blitc(c)
874*52130Smckusick 	register int c;
875*52130Smckusick {
876*52130Smckusick 	register char *bRow, *fRow;
877*52130Smckusick 	register int i;
878*52130Smckusick 	register int ote = isMono ? 256 : 1024; /* offset to table entry */
879*52130Smckusick 	int colMult = isMono ? 1 : 8;
880*52130Smckusick 
881*52130Smckusick 	c &= 0xff;
882*52130Smckusick 
883*52130Smckusick 	switch (c) {
884*52130Smckusick 	case '\t':
885*52130Smckusick 		for (i = 8 - (pmu.scrInfo.col & 0x7); i > 0; i--)
886*52130Smckusick 			Blitc(' ');
887*52130Smckusick 		break;
888*52130Smckusick 
889*52130Smckusick 	case '\r':
890*52130Smckusick 		pmu.scrInfo.col = 0;
891*52130Smckusick 		break;
892*52130Smckusick 
893*52130Smckusick 	case '\b':
894*52130Smckusick 		pmu.scrInfo.col--;
895*52130Smckusick 		if (pmu.scrInfo.col < 0)
896*52130Smckusick 			pmu.scrInfo.col = 0;
897*52130Smckusick 		break;
898*52130Smckusick 
899*52130Smckusick 	case '\n':
900*52130Smckusick 		if (pmu.scrInfo.row + 1 >= pmu.scrInfo.max_row)
901*52130Smckusick 			Scroll();
902*52130Smckusick 		else
903*52130Smckusick 			pmu.scrInfo.row++;
904*52130Smckusick 		pmu.scrInfo.col = 0;
905*52130Smckusick 		break;
906*52130Smckusick 
907*52130Smckusick 	case '\007':
908*52130Smckusick 		dcKBDPutc(LK_RING_BELL);
909*52130Smckusick 		break;
910*52130Smckusick 
911*52130Smckusick 	default:
912*52130Smckusick 		/*
913*52130Smckusick 		 * If the next character will wrap around then
914*52130Smckusick 		 * increment row counter or scroll screen.
915*52130Smckusick 		 */
916*52130Smckusick 		if (pmu.scrInfo.col >= pmu.scrInfo.max_col) {
917*52130Smckusick 			pmu.scrInfo.col = 0;
918*52130Smckusick 			if (pmu.scrInfo.row + 1 >= pmu.scrInfo.max_row)
919*52130Smckusick 				Scroll();
920*52130Smckusick 			else
921*52130Smckusick 				pmu.scrInfo.row++;
922*52130Smckusick 		}
923*52130Smckusick 		/*
924*52130Smckusick 		 * 0xA1 to 0xFD are the printable characters added with 8-bit
925*52130Smckusick 		 * support.
926*52130Smckusick 		 */
927*52130Smckusick 		if (c < ' ' || c > '~' && c < 0xA1 || c > 0xFD)
928*52130Smckusick 			break;
929*52130Smckusick 		bRow = (char *)(MACH_UNCACHED_FRAME_BUFFER_ADDR +
930*52130Smckusick 			(pmu.scrInfo.row * 15 & 0x3ff) * ote +
931*52130Smckusick 			pmu.scrInfo.col * colMult);
932*52130Smckusick 		i = c - ' ';
933*52130Smckusick 		/*
934*52130Smckusick 		 * This is to skip the (32) 8-bit
935*52130Smckusick 		 * control chars, as well as DEL
936*52130Smckusick 		 * and 0xA0 which aren't printable
937*52130Smckusick 		 */
938*52130Smckusick 		if (c > '~')
939*52130Smckusick 			i -= 34;
940*52130Smckusick 		i *= 15;
941*52130Smckusick 		fRow = (char *)((int)pmFont + i);
942*52130Smckusick 
943*52130Smckusick 		/* inline expansion for speed */
944*52130Smckusick 		if (isMono) {
945*52130Smckusick 			*bRow = *fRow++; bRow += ote;
946*52130Smckusick 			*bRow = *fRow++; bRow += ote;
947*52130Smckusick 			*bRow = *fRow++; bRow += ote;
948*52130Smckusick 			*bRow = *fRow++; bRow += ote;
949*52130Smckusick 			*bRow = *fRow++; bRow += ote;
950*52130Smckusick 			*bRow = *fRow++; bRow += ote;
951*52130Smckusick 			*bRow = *fRow++; bRow += ote;
952*52130Smckusick 			*bRow = *fRow++; bRow += ote;
953*52130Smckusick 			*bRow = *fRow++; bRow += ote;
954*52130Smckusick 			*bRow = *fRow++; bRow += ote;
955*52130Smckusick 			*bRow = *fRow++; bRow += ote;
956*52130Smckusick 			*bRow = *fRow++; bRow += ote;
957*52130Smckusick 			*bRow = *fRow++; bRow += ote;
958*52130Smckusick 			*bRow = *fRow++; bRow += ote;
959*52130Smckusick 			*bRow = *fRow++; bRow += ote;
960*52130Smckusick 		} else {
961*52130Smckusick 			register int j;
962*52130Smckusick 			register unsigned int *pInt;
963*52130Smckusick 
964*52130Smckusick 			pInt = (unsigned int *)bRow;
965*52130Smckusick 			for (j = 0; j < 15; j++) {
966*52130Smckusick 				/*
967*52130Smckusick 				 * fontmaskBits converts a nibble
968*52130Smckusick 				 * (4 bytes) to a long word
969*52130Smckusick 				 * containing 4 pixels corresponding
970*52130Smckusick 				 * to each bit in the nibble.  Thus
971*52130Smckusick 				 * we write two longwords for each
972*52130Smckusick 				 * byte in font.
973*52130Smckusick 				 *
974*52130Smckusick 				 * Remember the font is 8 bits wide
975*52130Smckusick 				 * and 15 bits high.
976*52130Smckusick 				 *
977*52130Smckusick 				 * We add 256 to the pointer to
978*52130Smckusick 				 * point to the pixel on the
979*52130Smckusick 				 * next scan line
980*52130Smckusick 				 * directly below the current
981*52130Smckusick 				 * pixel.
982*52130Smckusick 				 */
983*52130Smckusick 				pInt[0] = fontmaskBits[(*fRow) & 0xf];
984*52130Smckusick 				pInt[1] = fontmaskBits[((*fRow) >> 4) & 0xf];
985*52130Smckusick 				fRow++;
986*52130Smckusick 				pInt += 256;
987*52130Smckusick 			}
988*52130Smckusick 		}
989*52130Smckusick 		pmu.scrInfo.col++; /* increment column counter */
990*52130Smckusick 	}
991*52130Smckusick 	if (!GraphicsOpen)
992*52130Smckusick 		PosCursor(pmu.scrInfo.col * 8, pmu.scrInfo.row * 15);
993*52130Smckusick }
994*52130Smckusick 
995*52130Smckusick /*ARGSUSED*/
996*52130Smckusick pmopen(dev, flag)
997*52130Smckusick 	dev_t dev;
998*52130Smckusick 	int flag;
999*52130Smckusick {
1000*52130Smckusick 
1001*52130Smckusick 	if (!initialized)
1002*52130Smckusick 		return (ENXIO);
1003*52130Smckusick 	if (GraphicsOpen)
1004*52130Smckusick 		return (EBUSY);
1005*52130Smckusick 
1006*52130Smckusick 	GraphicsOpen = 1;
1007*52130Smckusick 	if (!isMono)
1008*52130Smckusick 		InitColorMap();
1009*52130Smckusick 	/*
1010*52130Smckusick 	 * Set up event queue for later
1011*52130Smckusick 	 */
1012*52130Smckusick 	pmu.scrInfo.qe.eSize = PM_MAXEVQ;
1013*52130Smckusick 	pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0;
1014*52130Smckusick 	pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
1015*52130Smckusick 	pmu.scrInfo.qe.tcNext = 0;
1016*52130Smckusick 	pmu.scrInfo.qe.timestamp_ms = TO_MS(time);
1017*52130Smckusick 	return (0);
1018*52130Smckusick }
1019*52130Smckusick 
1020*52130Smckusick /*ARGSUSED*/
1021*52130Smckusick pmclose(dev, flag)
1022*52130Smckusick 	dev_t dev;
1023*52130Smckusick 	int flag;
1024*52130Smckusick {
1025*52130Smckusick 
1026*52130Smckusick 	if (!GraphicsOpen)
1027*52130Smckusick 		return (EBADF);
1028*52130Smckusick 
1029*52130Smckusick 	GraphicsOpen = 0;
1030*52130Smckusick 	if (!isMono)
1031*52130Smckusick 		InitColorMap();
1032*52130Smckusick 	ScreenInit();
1033*52130Smckusick 	vmUserUnmap();
1034*52130Smckusick 	return (0);
1035*52130Smckusick }
1036*52130Smckusick 
1037*52130Smckusick /*ARGSUSED*/
1038*52130Smckusick pmioctl(dev, cmd, data, flag)
1039*52130Smckusick 	dev_t dev;
1040*52130Smckusick 	caddr_t data;
1041*52130Smckusick {
1042*52130Smckusick 	register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR;
1043*52130Smckusick 	extern int dcDivertXInput;
1044*52130Smckusick 
1045*52130Smckusick 	switch (cmd) {
1046*52130Smckusick 	case QIOCGINFO:
1047*52130Smckusick 	    {
1048*52130Smckusick 		caddr_t addr;
1049*52130Smckusick 		extern caddr_t vmUserMap();
1050*52130Smckusick 
1051*52130Smckusick 		/*
1052*52130Smckusick 		 * Map the all the data the user needs access to into
1053*52130Smckusick 		 * user space.
1054*52130Smckusick 		 */
1055*52130Smckusick 		addr = vmUserMap(sizeof(pmu), (unsigned)&pmu);
1056*52130Smckusick 		if (addr == (caddr_t)0)
1057*52130Smckusick 			goto mapError;
1058*52130Smckusick 		*(PM_Info **)data = &((struct pmuaccess *)addr)->scrInfo;
1059*52130Smckusick 		pmu.scrInfo.qe.events = ((struct pmuaccess *)addr)->events;
1060*52130Smckusick 		pmu.scrInfo.qe.tcs = ((struct pmuaccess *)addr)->tcs;
1061*52130Smckusick 		/*
1062*52130Smckusick 		 * Map the plane mask into the user's address space.
1063*52130Smckusick 		 */
1064*52130Smckusick 		addr = vmUserMap(4, (unsigned)MACH_PLANE_MASK_ADDR);
1065*52130Smckusick 		if (addr == (caddr_t)0)
1066*52130Smckusick 			goto mapError;
1067*52130Smckusick 		pmu.scrInfo.planemask = (char *)addr;
1068*52130Smckusick 		/*
1069*52130Smckusick 		 * Map the bitmap into the user's address space.
1070*52130Smckusick 		 */
1071*52130Smckusick 		addr = vmUserMap(isMono ? 256*1024 : 1024*1024,
1072*52130Smckusick 			(unsigned)MACH_UNCACHED_FRAME_BUFFER_ADDR);
1073*52130Smckusick 		if (addr == (caddr_t)0)
1074*52130Smckusick 			goto mapError;
1075*52130Smckusick 		pmu.scrInfo.bitmap = (char *)addr;
1076*52130Smckusick 		break;
1077*52130Smckusick 
1078*52130Smckusick 	mapError:
1079*52130Smckusick 		vmUserUnmap();
1080*52130Smckusick 		printf("Cannot map shared data structures\n");
1081*52130Smckusick 		return (EIO);
1082*52130Smckusick 	    }
1083*52130Smckusick 
1084*52130Smckusick 	case QIOCPMSTATE:
1085*52130Smckusick 		/*
1086*52130Smckusick 		 * Set mouse state.
1087*52130Smckusick 		 */
1088*52130Smckusick 		pmu.scrInfo.mouse = *(pmCursor *)data;
1089*52130Smckusick 		PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y);
1090*52130Smckusick 		break;
1091*52130Smckusick 
1092*52130Smckusick 	case QIOCINIT:
1093*52130Smckusick 		/*
1094*52130Smckusick 		 * Initialize the screen.
1095*52130Smckusick 		 */
1096*52130Smckusick 		ScreenInit();
1097*52130Smckusick 		break;
1098*52130Smckusick 
1099*52130Smckusick 	case QIOCKPCMD:
1100*52130Smckusick 	    {
1101*52130Smckusick 		pmKpCmd *kpCmdPtr;
1102*52130Smckusick 		unsigned char *cp;
1103*52130Smckusick 
1104*52130Smckusick 		kpCmdPtr = (pmKpCmd *)data;
1105*52130Smckusick 		if (kpCmdPtr->nbytes == 0)
1106*52130Smckusick 			kpCmdPtr->cmd |= 0x80;
1107*52130Smckusick 		if (!GraphicsOpen)
1108*52130Smckusick 			kpCmdPtr->cmd |= 1;
1109*52130Smckusick 		dcKBDPutc((int)kpCmdPtr->cmd);
1110*52130Smckusick 		cp = &kpCmdPtr->par[0];
1111*52130Smckusick 		for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) {
1112*52130Smckusick 			if (kpCmdPtr->nbytes == 1)
1113*52130Smckusick 				*cp |= 0x80;
1114*52130Smckusick 			dcKBDPutc((int)*cp);
1115*52130Smckusick 		}
1116*52130Smckusick 		break;
1117*52130Smckusick 	    }
1118*52130Smckusick 
1119*52130Smckusick 	case QIOCADDR:
1120*52130Smckusick 		*(PM_Info **)data = &pmu.scrInfo;
1121*52130Smckusick 		break;
1122*52130Smckusick 
1123*52130Smckusick 	case QIOWCURSOR:
1124*52130Smckusick 		LoadCursor((unsigned short *)data);
1125*52130Smckusick 		break;
1126*52130Smckusick 
1127*52130Smckusick 	case QIOWCURSORCOLOR:
1128*52130Smckusick 		CursorColor((unsigned int *)data);
1129*52130Smckusick 		break;
1130*52130Smckusick 
1131*52130Smckusick 	case QIOSETCMAP:
1132*52130Smckusick 		LoadColorMap((ColorMap *)data);
1133*52130Smckusick 		break;
1134*52130Smckusick 
1135*52130Smckusick 	case QIOKERNLOOP:
1136*52130Smckusick 		printf("pmioctl: QIOKERNLOOP\n"); /* XXX */
1137*52130Smckusick 		dcDivertXInput = 1;
1138*52130Smckusick 		break;
1139*52130Smckusick 
1140*52130Smckusick 	case QIOKERNUNLOOP:
1141*52130Smckusick 		printf("pmioctl: QIOKERNUNLOOP\n"); /* XXX */
1142*52130Smckusick 		dcDivertXInput = 0;
1143*52130Smckusick 		break;
1144*52130Smckusick 
1145*52130Smckusick 	case QIOVIDEOON:
1146*52130Smckusick 		if (!isMono)
1147*52130Smckusick 			RestoreCursorColor();
1148*52130Smckusick 		curReg |= PCC_ENPA;
1149*52130Smckusick 		curReg &= ~PCC_FOPB;
1150*52130Smckusick 		pcc->cmdr = curReg;
1151*52130Smckusick 		break;
1152*52130Smckusick 
1153*52130Smckusick 	case QIOVIDEOOFF:
1154*52130Smckusick 		if (!isMono)
1155*52130Smckusick 			VDACInit();
1156*52130Smckusick 		curReg |= PCC_FOPB;
1157*52130Smckusick 		curReg &= ~PCC_ENPA;
1158*52130Smckusick 		pcc->cmdr = curReg;
1159*52130Smckusick 		break;
1160*52130Smckusick 
1161*52130Smckusick 	default:
1162*52130Smckusick 		printf("pm0: Unknown command %x\n", cmd);
1163*52130Smckusick 		return (EINVAL);
1164*52130Smckusick 	}
1165*52130Smckusick 	return (0);
1166*52130Smckusick }
1167*52130Smckusick 
1168*52130Smckusick pmselect(dev, flag)
1169*52130Smckusick 	dev_t dev;
1170*52130Smckusick 	int flag;
1171*52130Smckusick {
1172*52130Smckusick 
1173*52130Smckusick 	switch (flag) {
1174*52130Smckusick 	case FREAD:
1175*52130Smckusick 		if (pmu.scrInfo.qe.eHead != pmu.scrInfo.qe.eTail)
1176*52130Smckusick 			return (1);
1177*52130Smckusick 		pm_selp = curproc;
1178*52130Smckusick 		break;
1179*52130Smckusick 	}
1180*52130Smckusick 
1181*52130Smckusick 	return (0);
1182*52130Smckusick }
1183*52130Smckusick 
1184*52130Smckusick static
1185*52130Smckusick pmwakeup()
1186*52130Smckusick {
1187*52130Smckusick 
1188*52130Smckusick 	if (pm_selp) {
1189*52130Smckusick 		selwakeup(pm_selp, 0);
1190*52130Smckusick 		pm_selp = 0;
1191*52130Smckusick 	}
1192*52130Smckusick }
1193*52130Smckusick #endif
1194