xref: /onnv-gate/usr/src/uts/i86pc/os/graphics.c (revision 1372:19fa0899b5f5)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*1372Ssetje  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <sys/types.h>
300Sstevel@tonic-gate #include <sys/systm.h>
310Sstevel@tonic-gate #include <sys/bootconf.h>
320Sstevel@tonic-gate #include <sys/thread.h>
330Sstevel@tonic-gate #include <sys/ddi.h>
340Sstevel@tonic-gate #include <sys/sunddi.h>
350Sstevel@tonic-gate #include <vm/seg_kmem.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #define	VIDEOMEM	0xa0000
380Sstevel@tonic-gate 
390Sstevel@tonic-gate extern void outb(int, uchar_t);
400Sstevel@tonic-gate 
410Sstevel@tonic-gate static int graphics_mode;
42*1372Ssetje static int cursor_y = 309;
43*1372Ssetje static int cursor_x = 136;
44*1372Ssetje 
45*1372Ssetje #define	BAR_STEPS 46
46*1372Ssetje 
47*1372Ssetje static uchar_t bar[BAR_STEPS];
480Sstevel@tonic-gate static kthread_t *progressbar_tid;
490Sstevel@tonic-gate static kmutex_t pbar_lock;
500Sstevel@tonic-gate static kcondvar_t pbar_cv;
510Sstevel@tonic-gate static char *videomem = (caddr_t)VIDEOMEM;
520Sstevel@tonic-gate static int videomem_size;
530Sstevel@tonic-gate 
54*1372Ssetje /* select the plane(s) to draw to */
550Sstevel@tonic-gate static void
56*1372Ssetje mapmask(int plane)
570Sstevel@tonic-gate {
580Sstevel@tonic-gate 	outb(0x3c4, 2);
59*1372Ssetje 	outb(0x3c5, plane);
600Sstevel@tonic-gate }
610Sstevel@tonic-gate 
620Sstevel@tonic-gate static void
630Sstevel@tonic-gate bitmask(int value)
640Sstevel@tonic-gate {
650Sstevel@tonic-gate 	outb(0x3ce, 8);
660Sstevel@tonic-gate 	outb(0x3cf, value);
670Sstevel@tonic-gate }
680Sstevel@tonic-gate 
690Sstevel@tonic-gate static void
700Sstevel@tonic-gate progressbar_show(void)
710Sstevel@tonic-gate {
72*1372Ssetje 	int j, k, offset;
730Sstevel@tonic-gate 	uchar_t *mem, *ptr;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	offset = cursor_y * 80 + cursor_x / 8;
760Sstevel@tonic-gate 	mem = (uchar_t *)videomem + offset;
770Sstevel@tonic-gate 
78*1372Ssetje 	bitmask(0xff);
79*1372Ssetje 	mapmask(0xff); /* write to all planes at once? */
80*1372Ssetje 	for (j = 0; j < 4; j++) {   /* bar height: 4 pixels */
81*1372Ssetje 		ptr = mem + j * 80;
82*1372Ssetje 		for (k = 0; k < BAR_STEPS; k++, ptr++)
83*1372Ssetje 			*ptr = bar[k];
840Sstevel@tonic-gate 	}
85*1372Ssetje 	bitmask(0x00);
860Sstevel@tonic-gate }
870Sstevel@tonic-gate 
880Sstevel@tonic-gate /*
890Sstevel@tonic-gate  * Initialize a rectangle area for progress bar
900Sstevel@tonic-gate  *
910Sstevel@tonic-gate  * Multiboot has initialized graphics mode to 640x480
920Sstevel@tonic-gate  * with 16 colors.
930Sstevel@tonic-gate  */
940Sstevel@tonic-gate void
950Sstevel@tonic-gate progressbar_init()
960Sstevel@tonic-gate {
970Sstevel@tonic-gate 	int i;
980Sstevel@tonic-gate 	char cons[10];
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	/* see if we are in graphics mode */
1010Sstevel@tonic-gate 	if (BOP_GETPROPLEN(bootops, "console") != sizeof ("graphics"))
1020Sstevel@tonic-gate 		return;
1030Sstevel@tonic-gate 	(void) BOP_GETPROP(bootops, "console", cons);
1040Sstevel@tonic-gate 	if (strncmp(cons, "graphics", strlen("graphics")) != 0)
1050Sstevel@tonic-gate 		return;
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	graphics_mode = 1;
1080Sstevel@tonic-gate 
109*1372Ssetje 	for (i = 0; i < BAR_STEPS; i++) {
110*1372Ssetje 		bar[i] = 0x00;
1110Sstevel@tonic-gate 	}
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	progressbar_show();
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate static void
1170Sstevel@tonic-gate progressbar_step()
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate 	static int limit = 0;
120*1372Ssetje 
121*1372Ssetje 	bar[limit] = 0xff;
1220Sstevel@tonic-gate 
123*1372Ssetje 	if (limit > 3)
124*1372Ssetje 		bar[limit - 4] = 0x00;
125*1372Ssetje 	else
126*1372Ssetje 		bar[limit + BAR_STEPS - 4] = 0x00;
127*1372Ssetje 
1280Sstevel@tonic-gate 	limit++;
129*1372Ssetje 	if (limit == BAR_STEPS)
1300Sstevel@tonic-gate 		limit = 0;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	progressbar_show();
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate /*ARGSUSED*/
1360Sstevel@tonic-gate static void
1370Sstevel@tonic-gate progressbar_thread(void *arg)
1380Sstevel@tonic-gate {
1390Sstevel@tonic-gate 	clock_t end;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	mutex_enter(&pbar_lock);
1420Sstevel@tonic-gate 	while (graphics_mode) {
1430Sstevel@tonic-gate 		progressbar_step();
144*1372Ssetje 		end = ddi_get_lbolt() + drv_usectohz(150000);
1450Sstevel@tonic-gate 		(void) cv_timedwait(&pbar_cv, &pbar_lock, end);
1460Sstevel@tonic-gate 	}
1470Sstevel@tonic-gate 	mutex_exit(&pbar_lock);
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate void
1510Sstevel@tonic-gate progressbar_start(void)
1520Sstevel@tonic-gate {
1530Sstevel@tonic-gate 	extern pri_t minclsyspri;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	if (graphics_mode == 0)
1560Sstevel@tonic-gate 		return;
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	/* map video memory to kernel heap */
1590Sstevel@tonic-gate 	videomem_size = ptob(btopr(38400));	/* 640 x 480 / 8 bytes */
1600Sstevel@tonic-gate 	videomem = vmem_alloc(heap_arena, videomem_size, VM_SLEEP);
1610Sstevel@tonic-gate 	if (videomem == NULL) {
1620Sstevel@tonic-gate 		cmn_err(CE_NOTE, "!failed to start progress bar");
1630Sstevel@tonic-gate 		graphics_mode = 0;
1640Sstevel@tonic-gate 		return;
1650Sstevel@tonic-gate 	}
1660Sstevel@tonic-gate 	hat_devload(kas.a_hat, videomem, videomem_size,
1670Sstevel@tonic-gate 	    btop(VIDEOMEM), (PROT_READ | PROT_WRITE),
1680Sstevel@tonic-gate 	    HAT_LOAD_NOCONSIST | HAT_LOAD_LOCK);
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	progressbar_tid = thread_create(NULL, 0, progressbar_thread,
1710Sstevel@tonic-gate 	    NULL, 0, &p0, TS_RUN, minclsyspri);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate void
1750Sstevel@tonic-gate progressbar_stop(void)
1760Sstevel@tonic-gate {
1770Sstevel@tonic-gate 	if (graphics_mode == 0)
1780Sstevel@tonic-gate 		return;
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	graphics_mode = 0;
1810Sstevel@tonic-gate 	mutex_enter(&pbar_lock);
1820Sstevel@tonic-gate 	cv_signal(&pbar_cv);
1830Sstevel@tonic-gate 	mutex_exit(&pbar_lock);
1840Sstevel@tonic-gate 	if (progressbar_tid != NULL)
1850Sstevel@tonic-gate 		thread_join(progressbar_tid->t_did);
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	/* unmap video memory */
1880Sstevel@tonic-gate 	hat_unload(kas.a_hat, videomem, videomem_size, HAT_UNLOAD_UNLOCK);
1890Sstevel@tonic-gate 	vmem_free(heap_arena, videomem, videomem_size);
1900Sstevel@tonic-gate }
191