xref: /illumos-gate/usr/src/uts/i86pc/os/graphics.c (revision 4da99751)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5843e1988Sjohnlev  * Common Development and Distribution License (the "License").
6843e1988Sjohnlev  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2248633f18SJan Setje-Eilers  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/systm.h>
287c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
297c478bd9Sstevel@tonic-gate #include <sys/thread.h>
307c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
317c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
327c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h>
3348633f18SJan Setje-Eilers #include <sys/file.h>
3448633f18SJan Setje-Eilers #include <sys/kd.h>
3548633f18SJan Setje-Eilers #include <sys/sunldi.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #define	VIDEOMEM	0xa0000
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate extern void outb(int, uchar_t);
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate static int graphics_mode;
421fac5a60Ssetje static int cursor_y = 309;
431fac5a60Ssetje static int cursor_x = 136;
441fac5a60Ssetje 
451fac5a60Ssetje #define	BAR_STEPS 46
461fac5a60Ssetje 
471fac5a60Ssetje static uchar_t bar[BAR_STEPS];
487c478bd9Sstevel@tonic-gate static kthread_t *progressbar_tid;
497c478bd9Sstevel@tonic-gate static kmutex_t pbar_lock;
507c478bd9Sstevel@tonic-gate static kcondvar_t pbar_cv;
517c478bd9Sstevel@tonic-gate static char *videomem = (caddr_t)VIDEOMEM;
527c478bd9Sstevel@tonic-gate static int videomem_size;
537c478bd9Sstevel@tonic-gate 
541fac5a60Ssetje /* select the plane(s) to draw to */
557c478bd9Sstevel@tonic-gate static void
mapmask(int plane)561fac5a60Ssetje mapmask(int plane)
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate 	outb(0x3c4, 2);
591fac5a60Ssetje 	outb(0x3c5, plane);
607c478bd9Sstevel@tonic-gate }
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate static void
bitmask(int value)637c478bd9Sstevel@tonic-gate bitmask(int value)
647c478bd9Sstevel@tonic-gate {
657c478bd9Sstevel@tonic-gate 	outb(0x3ce, 8);
667c478bd9Sstevel@tonic-gate 	outb(0x3cf, value);
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate static void
progressbar_show(void)707c478bd9Sstevel@tonic-gate progressbar_show(void)
717c478bd9Sstevel@tonic-gate {
721fac5a60Ssetje 	int j, k, offset;
737c478bd9Sstevel@tonic-gate 	uchar_t *mem, *ptr;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	offset = cursor_y * 80 + cursor_x / 8;
767c478bd9Sstevel@tonic-gate 	mem = (uchar_t *)videomem + offset;
777c478bd9Sstevel@tonic-gate 
781fac5a60Ssetje 	bitmask(0xff);
791fac5a60Ssetje 	mapmask(0xff); /* write to all planes at once? */
801fac5a60Ssetje 	for (j = 0; j < 4; j++) {   /* bar height: 4 pixels */
811fac5a60Ssetje 		ptr = mem + j * 80;
821fac5a60Ssetje 		for (k = 0; k < BAR_STEPS; k++, ptr++)
831fac5a60Ssetje 			*ptr = bar[k];
847c478bd9Sstevel@tonic-gate 	}
851fac5a60Ssetje 	bitmask(0x00);
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * Initialize a rectangle area for progress bar
907c478bd9Sstevel@tonic-gate  *
917c478bd9Sstevel@tonic-gate  * Multiboot has initialized graphics mode to 640x480
927c478bd9Sstevel@tonic-gate  * with 16 colors.
937c478bd9Sstevel@tonic-gate  */
947c478bd9Sstevel@tonic-gate void
progressbar_init()957c478bd9Sstevel@tonic-gate progressbar_init()
967c478bd9Sstevel@tonic-gate {
977c478bd9Sstevel@tonic-gate 	int i;
987c478bd9Sstevel@tonic-gate 	char cons[10];
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	/* see if we are in graphics mode */
1017c478bd9Sstevel@tonic-gate 	if (BOP_GETPROPLEN(bootops, "console") != sizeof ("graphics"))
1027c478bd9Sstevel@tonic-gate 		return;
1037c478bd9Sstevel@tonic-gate 	(void) BOP_GETPROP(bootops, "console", cons);
1047c478bd9Sstevel@tonic-gate 	if (strncmp(cons, "graphics", strlen("graphics")) != 0)
1057c478bd9Sstevel@tonic-gate 		return;
1068f982633SToomas Soome 	if (BOP_GETPROPLEN(bootops, "efi-systab") > 0)
1078f982633SToomas Soome 		return;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	graphics_mode = 1;
1107c478bd9Sstevel@tonic-gate 
1111fac5a60Ssetje 	for (i = 0; i < BAR_STEPS; i++) {
1121fac5a60Ssetje 		bar[i] = 0x00;
1137c478bd9Sstevel@tonic-gate 	}
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	progressbar_show();
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate static void
progressbar_step()1197c478bd9Sstevel@tonic-gate progressbar_step()
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	static int limit = 0;
1227c478bd9Sstevel@tonic-gate 
1231fac5a60Ssetje 	bar[limit] = 0xff;
1241fac5a60Ssetje 
1251fac5a60Ssetje 	if (limit > 3)
1261fac5a60Ssetje 		bar[limit - 4] = 0x00;
1271fac5a60Ssetje 	else
1281fac5a60Ssetje 		bar[limit + BAR_STEPS - 4] = 0x00;
1291fac5a60Ssetje 
1307c478bd9Sstevel@tonic-gate 	limit++;
1311fac5a60Ssetje 	if (limit == BAR_STEPS)
1327c478bd9Sstevel@tonic-gate 		limit = 0;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	progressbar_show();
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1387c478bd9Sstevel@tonic-gate static void
progressbar_thread(void * arg)1397c478bd9Sstevel@tonic-gate progressbar_thread(void *arg)
1407c478bd9Sstevel@tonic-gate {
141d3d50737SRafael Vanoni 	clock_t end = drv_usectohz(150000);
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	mutex_enter(&pbar_lock);
1447c478bd9Sstevel@tonic-gate 	while (graphics_mode) {
1457c478bd9Sstevel@tonic-gate 		progressbar_step();
146d3d50737SRafael Vanoni 		(void) cv_reltimedwait(&pbar_cv, &pbar_lock, end,
147d3d50737SRafael Vanoni 		    TR_CLOCK_TICK);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 	mutex_exit(&pbar_lock);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate void
progressbar_start(void)1537c478bd9Sstevel@tonic-gate progressbar_start(void)
1547c478bd9Sstevel@tonic-gate {
155843e1988Sjohnlev #if !defined(__xpv)
1567c478bd9Sstevel@tonic-gate 	extern pri_t minclsyspri;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	if (graphics_mode == 0)
1597c478bd9Sstevel@tonic-gate 		return;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	/* map video memory to kernel heap */
1627c478bd9Sstevel@tonic-gate 	videomem_size = ptob(btopr(38400));	/* 640 x 480 / 8 bytes */
1637c478bd9Sstevel@tonic-gate 	videomem = vmem_alloc(heap_arena, videomem_size, VM_SLEEP);
1647c478bd9Sstevel@tonic-gate 	if (videomem == NULL) {
1657c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "!failed to start progress bar");
1667c478bd9Sstevel@tonic-gate 		graphics_mode = 0;
1677c478bd9Sstevel@tonic-gate 		return;
1687c478bd9Sstevel@tonic-gate 	}
1697c478bd9Sstevel@tonic-gate 	hat_devload(kas.a_hat, videomem, videomem_size,
1707c478bd9Sstevel@tonic-gate 	    btop(VIDEOMEM), (PROT_READ | PROT_WRITE),
1717c478bd9Sstevel@tonic-gate 	    HAT_LOAD_NOCONSIST | HAT_LOAD_LOCK);
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	progressbar_tid = thread_create(NULL, 0, progressbar_thread,
1747c478bd9Sstevel@tonic-gate 	    NULL, 0, &p0, TS_RUN, minclsyspri);
175843e1988Sjohnlev #endif
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate void
progressbar_stop(void)1797c478bd9Sstevel@tonic-gate progressbar_stop(void)
1807c478bd9Sstevel@tonic-gate {
181843e1988Sjohnlev #if !defined(__xpv)
1827c478bd9Sstevel@tonic-gate 	if (graphics_mode == 0)
1837c478bd9Sstevel@tonic-gate 		return;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	graphics_mode = 0;
1867c478bd9Sstevel@tonic-gate 	mutex_enter(&pbar_lock);
1877c478bd9Sstevel@tonic-gate 	cv_signal(&pbar_cv);
1887c478bd9Sstevel@tonic-gate 	mutex_exit(&pbar_lock);
1897c478bd9Sstevel@tonic-gate 	if (progressbar_tid != NULL)
1907c478bd9Sstevel@tonic-gate 		thread_join(progressbar_tid->t_did);
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	/* unmap video memory */
1937c478bd9Sstevel@tonic-gate 	hat_unload(kas.a_hat, videomem, videomem_size, HAT_UNLOAD_UNLOCK);
1947c478bd9Sstevel@tonic-gate 	vmem_free(heap_arena, videomem, videomem_size);
195843e1988Sjohnlev #endif
1967c478bd9Sstevel@tonic-gate }
19748633f18SJan Setje-Eilers 
19848633f18SJan Setje-Eilers /*ARGSUSED*/
19948633f18SJan Setje-Eilers void
progressbar_key_abort(ldi_ident_t li)20048633f18SJan Setje-Eilers progressbar_key_abort(ldi_ident_t li)
20148633f18SJan Setje-Eilers {
20248633f18SJan Setje-Eilers #if !defined(__xpv)
20348633f18SJan Setje-Eilers 	char *fbpath;
20448633f18SJan Setje-Eilers 	int ret;
20548633f18SJan Setje-Eilers 	ldi_handle_t hdl;
20648633f18SJan Setje-Eilers 
20748633f18SJan Setje-Eilers 	extern char *consconfig_get_plat_fbpath(void);
20848633f18SJan Setje-Eilers 
20948633f18SJan Setje-Eilers 	if (graphics_mode == 0)
21048633f18SJan Setje-Eilers 		return;
21148633f18SJan Setje-Eilers 
21248633f18SJan Setje-Eilers 	fbpath = consconfig_get_plat_fbpath();
21348633f18SJan Setje-Eilers 
21448633f18SJan Setje-Eilers 	if (ldi_open_by_name(fbpath, FWRITE, kcred, &hdl, li) != 0) {
21548633f18SJan Setje-Eilers 		cmn_err(CE_NOTE, "!ldi_open_by_name failed");
21648633f18SJan Setje-Eilers 	} else {
21748633f18SJan Setje-Eilers 		if (ldi_ioctl(hdl, KDSETMODE, KD_RESETTEXT, FKIOCTL,
21848633f18SJan Setje-Eilers 		    kcred, &ret)
21948633f18SJan Setje-Eilers 		    != 0)
22048633f18SJan Setje-Eilers 				cmn_err(CE_NOTE,
22148633f18SJan Setje-Eilers 				    "!ldi_ioctl for KD_RESETTEXT failed");
222*4da99751SToomas Soome 		(void) ldi_close(hdl, 0, kcred);
22348633f18SJan Setje-Eilers 	}
22448633f18SJan Setje-Eilers #endif
22548633f18SJan Setje-Eilers }
226