xref: /original-bsd/sys/pmax/dev/xcfb.c (revision 3705696b)
1 /*-
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  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  *	@(#)xcfb.c	8.1 (Berkeley) 06/10/93
11  */
12 
13 /*
14  * Mach Operating System
15  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
16  * All Rights Reserved.
17  *
18  * Permission to use, copy, modify and distribute this software and its
19  * documentation is hereby granted, provided that both the copyright
20  * notice and this permission notice appear in all copies of the
21  * software, derivative works or modified versions, and any portions
22  * thereof, and that both notices appear in supporting documentation.
23  *
24  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
25  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
26  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
27  *
28  * Carnegie Mellon requests users of this software to return to
29  *
30  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
31  *  School of Computer Science
32  *  Carnegie Mellon University
33  *  Pittsburgh PA 15213-3890
34  *
35  * any improvements or extensions that they make and grant Carnegie the
36  * rights to redistribute these changes.
37  */
38 /*
39  *  devGraphics.c --
40  *
41  *     	This file contains machine-dependent routines for the graphics device.
42  *
43  *	Copyright (C) 1989 Digital Equipment Corporation.
44  *	Permission to use, copy, modify, and distribute this software and
45  *	its documentation for any purpose and without fee is hereby granted,
46  *	provided that the above copyright notice appears in all copies.
47  *	Digital Equipment Corporation makes no representations about the
48  *	suitability of this software for any purpose.  It is provided "as is"
49  *	without express or implied warranty.
50  *
51  * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c,
52  *	v 9.2 90/02/13 22:16:24 shirriff Exp $ SPRITE (DECWRL)";
53  */
54 
55 #include <xcfb.h>
56 #include <dtop.h>
57 #if NXCFB > 0
58 #if NDTOP == 0
59 xcfb needs dtop device
60 #else
61 
62 #include <sys/param.h>
63 #include <sys/time.h>
64 #include <sys/kernel.h>
65 #include <sys/ioctl.h>
66 #include <sys/file.h>
67 #include <sys/errno.h>
68 #include <sys/proc.h>
69 #include <sys/mman.h>
70 
71 #include <vm/vm.h>
72 
73 #include <machine/machConst.h>
74 #include <machine/pmioctl.h>
75 
76 #include <pmax/pmax/maxine.h>
77 #include <pmax/pmax/cons.h>
78 #include <pmax/pmax/pmaxtype.h>
79 
80 #include <pmax/dev/device.h>
81 #include <pmax/dev/xcfbreg.h>
82 #include <pmax/dev/dtopreg.h>
83 #include <pmax/dev/fbreg.h>
84 
85 /*
86  * These need to be mapped into user space.
87  */
88 struct fbuaccess xcfbu;
89 struct pmax_fb xcfbfb;
90 
91 /*
92  * Forward references.
93  */
94 static void xcfbScreenInit();
95 static void xcfbLoadCursor();
96 static void xcfbRestoreCursorColor();
97 static void xcfbCursorColor();
98 void xcfbPosCursor();
99 static void xcfbInitColorMap();
100 static void xcfbLoadColorMap();
101 static u_int ims332_read_register();
102 static void ims332_write_register();
103 static void ims332_load_colormap_entry();
104 static void ims332_video_off();
105 static void ims332_video_on();
106 
107 void xcfbKbdEvent(), xcfbMouseEvent(), xcfbMouseButtons();
108 extern void dtopKBDPutc();
109 extern void (*dtopDivertXInput)();
110 extern void (*dtopMouseEvent)();
111 extern void (*dtopMouseButtons)();
112 extern int pmax_boardtype;
113 extern u_short defCursor[32];
114 extern struct consdev cn_tab;
115 
116 int	xcfbprobe();
117 struct	driver xcfbdriver = {
118 	"xcfb", xcfbprobe, 0, 0,
119 };
120 
121 /*
122  * Test to see if device is present.
123  * Return true if found and initialized ok.
124  */
125 /*ARGSUSED*/
126 xcfbprobe(cp)
127 	register struct pmax_ctlr *cp;
128 {
129 	register struct pmax_fb *fp = &xcfbfb;
130 
131 	if (pmax_boardtype != DS_MAXINE)
132 		return (0);
133 	if (!fp->initialized && !xcfbinit())
134 		return (0);
135 	printf("xcfb0 (color display)\n");
136 	return (1);
137 }
138 
139 /*ARGSUSED*/
140 xcfbopen(dev, flag)
141 	dev_t dev;
142 	int flag;
143 {
144 	register struct pmax_fb *fp = &xcfbfb;
145 	int s;
146 
147 	if (!fp->initialized)
148 		return (ENXIO);
149 	if (fp->GraphicsOpen)
150 		return (EBUSY);
151 
152 	fp->GraphicsOpen = 1;
153 	xcfbInitColorMap();
154 	/*
155 	 * Set up event queue for later
156 	 */
157 	fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
158 	fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
159 	fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
160 	fp->fbu->scrInfo.qe.tcNext = 0;
161 	fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
162 	s = spltty();
163 	dtopDivertXInput = xcfbKbdEvent;
164 	dtopMouseEvent = xcfbMouseEvent;
165 	dtopMouseButtons = xcfbMouseButtons;
166 	splx(s);
167 	return (0);
168 }
169 
170 /*ARGSUSED*/
171 xcfbclose(dev, flag)
172 	dev_t dev;
173 	int flag;
174 {
175 	register struct pmax_fb *fp = &xcfbfb;
176 	int s;
177 
178 	if (!fp->GraphicsOpen)
179 		return (EBADF);
180 
181 	fp->GraphicsOpen = 0;
182 	xcfbInitColorMap();
183 	s = spltty();
184 	dtopDivertXInput = (void (*)())0;
185 	dtopMouseEvent = (void (*)())0;
186 	dtopMouseButtons = (void (*)())0;
187 	splx(s);
188 	xcfbScreenInit();
189 	bzero((caddr_t)fp->fr_addr, 1024 * 768);
190 	xcfbPosCursor(fp->col * 8, fp->row * 15);
191 	return (0);
192 }
193 
194 /*ARGSUSED*/
195 xcfbioctl(dev, cmd, data, flag, p)
196 	dev_t dev;
197 	caddr_t data;
198 	struct proc *p;
199 {
200 	register struct pmax_fb *fp = &xcfbfb;
201 	int s;
202 
203 	switch (cmd) {
204 	case QIOCGINFO:
205 		return (fbmmap(fp, dev, data, p));
206 
207 	case QIOCPMSTATE:
208 		/*
209 		 * Set mouse state.
210 		 */
211 		fp->fbu->scrInfo.mouse = *(pmCursor *)data;
212 		xcfbPosCursor(fp->fbu->scrInfo.mouse.x, fp->fbu->scrInfo.mouse.y);
213 		break;
214 
215 	case QIOCINIT:
216 		/*
217 		 * Initialize the screen.
218 		 */
219 		xcfbScreenInit();
220 		break;
221 
222 	case QIOCKPCMD:
223 	    {
224 		pmKpCmd *kpCmdPtr;
225 		unsigned char *cp;
226 
227 		kpCmdPtr = (pmKpCmd *)data;
228 		if (kpCmdPtr->nbytes == 0)
229 			kpCmdPtr->cmd |= 0x80;
230 		if (!fp->GraphicsOpen)
231 			kpCmdPtr->cmd |= 1;
232 		(*fp->KBDPutc)(fp->kbddev, (int)kpCmdPtr->cmd);
233 		cp = &kpCmdPtr->par[0];
234 		for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) {
235 			if (kpCmdPtr->nbytes == 1)
236 				*cp |= 0x80;
237 			(*fp->KBDPutc)(fp->kbddev, (int)*cp);
238 		}
239 		break;
240 	    }
241 
242 	case QIOCADDR:
243 		*(PM_Info **)data = &fp->fbu->scrInfo;
244 		break;
245 
246 	case QIOWCURSOR:
247 		xcfbLoadCursor((unsigned short *)data);
248 		break;
249 
250 	case QIOWCURSORCOLOR:
251 		xcfbCursorColor((unsigned int *)data);
252 		break;
253 
254 	case QIOSETCMAP:
255 		xcfbLoadColorMap((ColorMap *)data);
256 		break;
257 
258 	case QIOKERNLOOP:
259 		s = spltty();
260 		dtopDivertXInput = xcfbKbdEvent;
261 		dtopMouseEvent = xcfbMouseEvent;
262 		dtopMouseButtons = xcfbMouseButtons;
263 		splx(s);
264 		break;
265 
266 	case QIOKERNUNLOOP:
267 		s = spltty();
268 		dtopDivertXInput = (void (*)())0;
269 		dtopMouseEvent = (void (*)())0;
270 		dtopMouseButtons = (void (*)())0;
271 		splx(s);
272 		break;
273 
274 	case QIOVIDEOON:
275 		xcfbRestoreCursorColor();
276 		ims332_video_on();
277 		break;
278 
279 	case QIOVIDEOOFF:
280 		ims332_video_off();
281 		break;
282 
283 	default:
284 		printf("xcfb0: Unknown ioctl command %x\n", cmd);
285 		return (EINVAL);
286 	}
287 	return (0);
288 }
289 
290 /*
291  * Return the physical page number that corresponds to byte offset 'off'.
292  */
293 /*ARGSUSED*/
294 xcfbmap(dev, off, prot)
295 	dev_t dev;
296 {
297 	int len;
298 
299 	len = pmax_round_page(((vm_offset_t)&xcfbu & PGOFSET) + sizeof(xcfbu));
300 	if (off < len)
301 		return pmax_btop(MACH_CACHED_TO_PHYS(&xcfbu) + off);
302 	off -= len;
303 	if (off >= xcfbfb.fr_size)
304 		return (-1);
305 	return pmax_btop(MACH_UNCACHED_TO_PHYS(xcfbfb.fr_addr) + off);
306 }
307 
308 xcfbselect(dev, flag, p)
309 	dev_t dev;
310 	int flag;
311 	struct proc *p;
312 {
313 	struct pmax_fb *fp = &xcfbfb;
314 
315 	switch (flag) {
316 	case FREAD:
317 		if (fp->fbu->scrInfo.qe.eHead != fp->fbu->scrInfo.qe.eTail)
318 			return (1);
319 		selrecord(p, &fp->selp);
320 		break;
321 	}
322 
323 	return (0);
324 }
325 
326 static u_char	cursor_RGB[6];	/* cursor color 2 & 3 */
327 
328 /*
329  *	Routines for the Inmos IMS-G332 Colour video controller
330  * 	Author: Alessandro Forin, Carnegie Mellon University
331  */
332 static u_int
333 ims332_read_register(regno)
334 {
335 	register u_char *regs = (u_char *)IMS332_ADDRESS;
336 	unsigned char *rptr;
337 	register u_int val, v1;
338 
339 	/* spec sez: */
340 	rptr = regs + 0x80000 + (regno << 4);
341 	val = *((volatile u_short *) rptr );
342 	v1  = *((volatile u_short *) regs );
343 
344 	return (val & 0xffff) | ((v1 & 0xff00) << 8);
345 }
346 
347 static void
348 ims332_write_register(regno, val)
349 	register unsigned int val;
350 {
351 	register u_char *regs = (u_char *)IMS332_ADDRESS;
352 	u_char *wptr;
353 
354 	/* spec sez: */
355 	wptr = regs + 0xa0000 + (regno << 4);
356 	*((volatile u_int *)(regs)) = (val >> 8) & 0xff00;
357 	*((volatile u_short *)(wptr)) = val;
358 }
359 
360 #define	assert_ims332_reset_bit(r)	*r &= ~0x40
361 #define	deassert_ims332_reset_bit(r)	*r |=  0x40
362 
363 /*
364  * Color map
365  */
366 static void
367 xcfbLoadColorMap(ptr)
368 	ColorMap *ptr;
369 {
370 	register int i;
371 
372 	if (ptr->index > 256)
373 		return;
374 	ims332_load_colormap_entry(ptr->index, ptr);
375 }
376 
377 static void
378 ims332_load_colormap_entry(entry, map)
379 	ColorMap *map;
380 {
381 	/* ?? stop VTG */
382 	ims332_write_register(IMS332_REG_LUT_BASE + (entry & 0xff),
383 			      (map->Entry.blue << 16) |
384 			      (map->Entry.green << 8) |
385 			      (map->Entry.red));
386 }
387 
388 static void
389 xcfbInitColorMap()
390 {
391 	register int i;
392 	ColorMap m;
393 
394 	m.Entry.red = m.Entry.green = m.Entry.blue = 0;
395 	ims332_load_colormap_entry(0, &m);
396 
397 	m.Entry.red = m.Entry.green = m.Entry.blue = 0xff;
398 	for (i = 1; i < 256; i++)
399 		ims332_load_colormap_entry(i, &m);
400 
401 	for (i = 0; i < 3; i++) {
402 		cursor_RGB[i] = 0x00;
403 		cursor_RGB[i + 3] = 0xff;
404 	}
405 	xcfbRestoreCursorColor();
406 }
407 
408 /*
409  * Video on/off
410  *
411  * It is unfortunate that X11 goes backward with white@0
412  * and black@1.  So we must stash away the zero-th entry
413  * and fix it while screen is off.  Also must remember
414  * it, sigh.
415  */
416 static struct {
417 	u_int	save;
418 	int	off;
419 } xcfb_vstate;
420 
421 static void
422 ims332_video_off()
423 {
424 	register u_int csr;
425 
426 	if (xcfb_vstate.off)
427 		return;
428 
429 	xcfb_vstate.save = ims332_read_register(IMS332_REG_LUT_BASE);
430 
431 	ims332_write_register(IMS332_REG_LUT_BASE, 0);
432 
433 	ims332_write_register(IMS332_REG_COLOR_MASK, 0);
434 
435 	/* cursor now */
436 	csr = ims332_read_register(IMS332_REG_CSR_A);
437 	csr |= IMS332_CSR_A_DISABLE_CURSOR;
438 	ims332_write_register(IMS332_REG_CSR_A, csr);
439 
440 	xcfb_vstate.off = 1;
441 }
442 
443 static void
444 ims332_video_on()
445 {
446 	register u_int csr;
447 
448 	if (!xcfb_vstate.off)
449 		return;
450 
451 	ims332_write_register(IMS332_REG_LUT_BASE, xcfb_vstate.save);
452 
453 	ims332_write_register(IMS332_REG_COLOR_MASK, 0xffffffff);
454 
455 	/* cursor now */
456 	csr = ims332_read_register(IMS332_REG_CSR_A);
457 	csr &= ~IMS332_CSR_A_DISABLE_CURSOR;
458 	ims332_write_register(IMS332_REG_CSR_A, csr);
459 
460 	xcfb_vstate.off = 0;
461 }
462 
463 /*
464  * Cursor
465  */
466 void
467 xcfbPosCursor(x, y)
468 	register int x, y;
469 {
470 	register struct pmax_fb *fp = &xcfbfb;
471 
472 	if (y < fp->fbu->scrInfo.min_cur_y || y > fp->fbu->scrInfo.max_cur_y)
473 		y = fp->fbu->scrInfo.max_cur_y;
474 	if (x < fp->fbu->scrInfo.min_cur_x || x > fp->fbu->scrInfo.max_cur_x)
475 		x = fp->fbu->scrInfo.max_cur_x;
476 	fp->fbu->scrInfo.cursor.x = x;		/* keep track of real cursor */
477 	fp->fbu->scrInfo.cursor.y = y;		/* position, indep. of mouse */
478 	ims332_write_register(IMS332_REG_CURSOR_LOC,
479 		((x & 0xfff) << 12) | (y & 0xfff));
480 }
481 
482 /*
483  * xcfbRestoreCursorColor
484  */
485 static void
486 xcfbRestoreCursorColor()
487 {
488 
489 	/* Bg is color[0], Fg is color[1] */
490 	ims332_write_register(IMS332_REG_CURSOR_LUT_0,
491 			      (cursor_RGB[2] << 16) |
492 			      (cursor_RGB[1] << 8) |
493 			      (cursor_RGB[0]));
494 	ims332_write_register(IMS332_REG_CURSOR_LUT_1, 0x7f0000);
495 	ims332_write_register(IMS332_REG_CURSOR_LUT_2,
496 			      (cursor_RGB[5] << 16) |
497 			      (cursor_RGB[4] << 8) |
498 			      (cursor_RGB[3]));
499 }
500 
501 /*
502  * ----------------------------------------------------------------------------
503  *
504  * xcfbCursorColor --
505  *
506  *	Set the color of the cursor.
507  *
508  * Results:
509  *	None.
510  *
511  * Side effects:
512  *	None.
513  *
514  * ----------------------------------------------------------------------------
515  */
516 static void
517 xcfbCursorColor(color)
518 	unsigned int color[];
519 {
520 	register int i, j;
521 
522 	for (i = 0; i < 6; i++)
523 		cursor_RGB[i] = (u_char)(color[i] >> 8);
524 
525 	xcfbRestoreCursorColor();
526 }
527 
528 static void
529 xcfbLoadCursor(cursor)
530 	u_short *cursor;
531 {
532 	register int i, j, k, pos;
533 	register u_short ap, bp, out;
534 
535 	/*
536 	 * Fill in the cursor sprite using the A and B planes, as provided
537 	 * for the pmax.
538 	 * XXX This will have to change when the X server knows that this
539 	 * is not a pmax display.
540 	 */
541 	pos = 0;
542 	for (k = 0; k < 16; k++) {
543 		ap = *cursor;
544 		bp = *(cursor + 16);
545 		j = 0;
546 		while (j < 2) {
547 			out = 0;
548 			for (i = 0; i < 8; i++) {
549 				out = ((out >> 2) & 0x3fff) |
550 					((ap & 0x1) << 15) |
551 					((bp & 0x1) << 14);
552 				ap >>= 1;
553 				bp >>= 1;
554 			}
555 			ims332_write_register(IMS332_REG_CURSOR_RAM + pos, out);
556 			pos++;
557 			j++;
558 		}
559 		while (j < 8) {
560 			ims332_write_register(IMS332_REG_CURSOR_RAM + pos, 0);
561 			pos++;
562 			j++;
563 		}
564 		cursor++;
565 	}
566 	while (pos < 512) {
567 		ims332_write_register(IMS332_REG_CURSOR_RAM + pos, 0);
568 		pos++;
569 	}
570 }
571 
572 /*
573  * Initialization
574  */
575 int
576 xcfbinit()
577 {
578 	register u_int *reset = (u_int *)IMS332_RESET_ADDRESS;
579 	register struct pmax_fb *fp = &xcfbfb;
580 
581 	fp->isMono = 0;
582 
583 	/*
584 	 * Or Cached? A comment in the Mach driver suggests that the X server
585 	 * runs faster in cached address space, but the X server is going
586 	 * to blow away the data cache whenever it updates the screen, so..
587 	 */
588 	fp->fr_addr = (char *)
589 		MACH_PHYS_TO_UNCACHED(XINE_PHYS_CFB_START + VRAM_OFFSET);
590 	fp->fr_size = 0x100000;
591 	/*
592 	 * Must be in Uncached space since the fbuaccess structure is
593 	 * mapped into the user's address space uncached.
594 	 */
595 	fp->fbu = (struct fbuaccess *)
596 		MACH_PHYS_TO_UNCACHED(MACH_CACHED_TO_PHYS(&xcfbu));
597 	fp->posCursor = xcfbPosCursor;
598 	fp->KBDPutc = dtopKBDPutc;
599 	fp->kbddev = makedev(DTOPDEV, DTOPKBD_PORT);
600 
601 	/*
602 	 * Initialize the screen.
603 	 */
604 #ifdef notdef
605 	assert_ims332_reset_bit(reset);
606 	DELAY(1);	/* specs sez 50ns.. */
607 	deassert_ims332_reset_bit(reset);
608 
609 	/* CLOCKIN appears to receive a 6.25 Mhz clock --> PLL 12 for 75Mhz monitor */
610 	ims332_write_register(IMS332_REG_BOOT, 12 | IMS332_BOOT_CLOCK_PLL);
611 
612 	/* initialize VTG */
613 	ims332_write_register(IMS332_REG_CSR_A,
614 				IMS332_BPP_8 | IMS332_CSR_A_DISABLE_CURSOR);
615 	DELAY(50);	/* spec does not say */
616 
617 	/* datapath registers (values taken from prom's settings) */
618 
619 	ims332_write_register(IMS332_REG_HALF_SYNCH, 0x10);
620 	ims332_write_register(IMS332_REG_BACK_PORCH, 0x21);
621 	ims332_write_register(IMS332_REG_DISPLAY, 0x100);
622 	ims332_write_register(IMS332_REG_SHORT_DIS, 0x5d);
623 	ims332_write_register(IMS332_REG_BROAD_PULSE, 0x9f);
624 	ims332_write_register(IMS332_REG_V_SYNC, 0xc);
625 	ims332_write_register(IMS332_REG_V_PRE_EQUALIZE, 2);
626 	ims332_write_register(IMS332_REG_V_POST_EQUALIZE, 2);
627 	ims332_write_register(IMS332_REG_V_BLANK, 0x2a);
628 	ims332_write_register(IMS332_REG_V_DISPLAY, 0x600);
629 	ims332_write_register(IMS332_REG_LINE_TIME, 0x146);
630 	ims332_write_register(IMS332_REG_LINE_START, 0x10);
631 	ims332_write_register(IMS332_REG_MEM_INIT, 0xa);
632 	ims332_write_register(IMS332_REG_XFER_DELAY, 0xa);
633 
634 	ims332_write_register(IMS332_REG_COLOR_MASK, 0xffffff);
635 #endif
636 
637 	/*
638 	 * Initialize screen info.
639 	 */
640 	fp->fbu->scrInfo.max_row = 50;
641 	fp->fbu->scrInfo.max_col = 80;
642 	fp->fbu->scrInfo.max_x = 1024;
643 	fp->fbu->scrInfo.max_y = 768;
644 	fp->fbu->scrInfo.max_cur_x = 1008;
645 	fp->fbu->scrInfo.max_cur_y = 752;
646 	fp->fbu->scrInfo.version = 11;
647 	fp->fbu->scrInfo.mthreshold = 4;
648 	fp->fbu->scrInfo.mscale = 2;
649 	fp->fbu->scrInfo.min_cur_x = -15;
650 	fp->fbu->scrInfo.min_cur_y = -15;
651 	fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
652 	fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
653 	fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
654 	fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
655 	fp->fbu->scrInfo.qe.tcNext = 0;
656 
657 	xcfbInitColorMap();
658 
659 	ims332_write_register(IMS332_REG_CSR_A,
660 		IMS332_BPP_8 | IMS332_CSR_A_DMA_DISABLE | IMS332_CSR_A_VTG_ENABLE);
661 
662 	xcfbScreenInit();
663 	fbScroll(fp);
664 
665 	fp->initialized = 1;
666 	if (cn_tab.cn_fb == (struct pmax_fb *)0)
667 		cn_tab.cn_fb = fp;
668 	return (1);
669 }
670 
671 /*
672  * ----------------------------------------------------------------------------
673  *
674  * xcfbScreenInit --
675  *
676  *	Initialize the screen.
677  *
678  * Results:
679  *	None.
680  *
681  * Side effects:
682  *	The screen is initialized.
683  *
684  * ----------------------------------------------------------------------------
685  */
686 static void
687 xcfbScreenInit()
688 {
689 	register struct pmax_fb *fp = &xcfbfb;
690 
691 	/*
692 	 * Home the cursor.
693 	 * We want an LSI terminal emulation.  We want the graphics
694 	 * terminal to scroll from the bottom. So start at the bottom.
695 	 */
696 	fp->row = 49;
697 	fp->col = 0;
698 
699 	/*
700 	 * Load the cursor with the default values
701 	 *
702 	 */
703 	xcfbLoadCursor(defCursor);
704 }
705 
706 /*
707  * xcfb keyboard and mouse input. Just punt to the generic ones in fb.c
708  */
709 void
710 xcfbKbdEvent(ch)
711 	int ch;
712 {
713 	fbKbdEvent(ch, &xcfbfb);
714 }
715 
716 void
717 xcfbMouseEvent(newRepPtr)
718 	MouseReport *newRepPtr;
719 {
720 	fbMouseEvent(newRepPtr, &xcfbfb);
721 }
722 
723 void
724 xcfbMouseButtons(newRepPtr)
725 	MouseReport *newRepPtr;
726 {
727 	fbMouseButtons(newRepPtr, &xcfbfb);
728 }
729 #endif /* NDTOP */
730 #endif /* NXCFB */
731