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
55084Sjohnlev * Common Development and Distribution License (the "License").
65084Sjohnlev * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
228960SJan.Setje-Eilers@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/systm.h>
280Sstevel@tonic-gate #include <sys/bootconf.h>
290Sstevel@tonic-gate #include <sys/thread.h>
300Sstevel@tonic-gate #include <sys/ddi.h>
310Sstevel@tonic-gate #include <sys/sunddi.h>
320Sstevel@tonic-gate #include <vm/seg_kmem.h>
338960SJan.Setje-Eilers@Sun.COM #include <sys/file.h>
348960SJan.Setje-Eilers@Sun.COM #include <sys/kd.h>
358960SJan.Setje-Eilers@Sun.COM #include <sys/sunldi.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;
421372Ssetje static int cursor_y = 309;
431372Ssetje static int cursor_x = 136;
441372Ssetje
451372Ssetje #define BAR_STEPS 46
461372Ssetje
471372Ssetje 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
541372Ssetje /* select the plane(s) to draw to */
550Sstevel@tonic-gate static void
mapmask(int plane)561372Ssetje mapmask(int plane)
570Sstevel@tonic-gate {
580Sstevel@tonic-gate outb(0x3c4, 2);
591372Ssetje outb(0x3c5, plane);
600Sstevel@tonic-gate }
610Sstevel@tonic-gate
620Sstevel@tonic-gate static void
bitmask(int value)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
progressbar_show(void)700Sstevel@tonic-gate progressbar_show(void)
710Sstevel@tonic-gate {
721372Ssetje 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
781372Ssetje bitmask(0xff);
791372Ssetje mapmask(0xff); /* write to all planes at once? */
801372Ssetje for (j = 0; j < 4; j++) { /* bar height: 4 pixels */
811372Ssetje ptr = mem + j * 80;
821372Ssetje for (k = 0; k < BAR_STEPS; k++, ptr++)
831372Ssetje *ptr = bar[k];
840Sstevel@tonic-gate }
851372Ssetje 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
progressbar_init()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
1091372Ssetje for (i = 0; i < BAR_STEPS; i++) {
1101372Ssetje 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
progressbar_step()1170Sstevel@tonic-gate progressbar_step()
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate static int limit = 0;
1201372Ssetje
1211372Ssetje bar[limit] = 0xff;
1220Sstevel@tonic-gate
1231372Ssetje if (limit > 3)
1241372Ssetje bar[limit - 4] = 0x00;
1251372Ssetje else
1261372Ssetje bar[limit + BAR_STEPS - 4] = 0x00;
1271372Ssetje
1280Sstevel@tonic-gate limit++;
1291372Ssetje 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
progressbar_thread(void * arg)1370Sstevel@tonic-gate progressbar_thread(void *arg)
1380Sstevel@tonic-gate {
139*11066Srafael.vanoni@sun.com clock_t end = drv_usectohz(150000);
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate mutex_enter(&pbar_lock);
1420Sstevel@tonic-gate while (graphics_mode) {
1430Sstevel@tonic-gate progressbar_step();
144*11066Srafael.vanoni@sun.com (void) cv_reltimedwait(&pbar_cv, &pbar_lock, end,
145*11066Srafael.vanoni@sun.com TR_CLOCK_TICK);
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate mutex_exit(&pbar_lock);
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate
1500Sstevel@tonic-gate void
progressbar_start(void)1510Sstevel@tonic-gate progressbar_start(void)
1520Sstevel@tonic-gate {
1535084Sjohnlev #if !defined(__xpv)
1540Sstevel@tonic-gate extern pri_t minclsyspri;
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate if (graphics_mode == 0)
1570Sstevel@tonic-gate return;
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate /* map video memory to kernel heap */
1600Sstevel@tonic-gate videomem_size = ptob(btopr(38400)); /* 640 x 480 / 8 bytes */
1610Sstevel@tonic-gate videomem = vmem_alloc(heap_arena, videomem_size, VM_SLEEP);
1620Sstevel@tonic-gate if (videomem == NULL) {
1630Sstevel@tonic-gate cmn_err(CE_NOTE, "!failed to start progress bar");
1640Sstevel@tonic-gate graphics_mode = 0;
1650Sstevel@tonic-gate return;
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate hat_devload(kas.a_hat, videomem, videomem_size,
1680Sstevel@tonic-gate btop(VIDEOMEM), (PROT_READ | PROT_WRITE),
1690Sstevel@tonic-gate HAT_LOAD_NOCONSIST | HAT_LOAD_LOCK);
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate progressbar_tid = thread_create(NULL, 0, progressbar_thread,
1720Sstevel@tonic-gate NULL, 0, &p0, TS_RUN, minclsyspri);
1735084Sjohnlev #endif
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate void
progressbar_stop(void)1770Sstevel@tonic-gate progressbar_stop(void)
1780Sstevel@tonic-gate {
1795084Sjohnlev #if !defined(__xpv)
1800Sstevel@tonic-gate if (graphics_mode == 0)
1810Sstevel@tonic-gate return;
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate graphics_mode = 0;
1840Sstevel@tonic-gate mutex_enter(&pbar_lock);
1850Sstevel@tonic-gate cv_signal(&pbar_cv);
1860Sstevel@tonic-gate mutex_exit(&pbar_lock);
1870Sstevel@tonic-gate if (progressbar_tid != NULL)
1880Sstevel@tonic-gate thread_join(progressbar_tid->t_did);
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate /* unmap video memory */
1910Sstevel@tonic-gate hat_unload(kas.a_hat, videomem, videomem_size, HAT_UNLOAD_UNLOCK);
1920Sstevel@tonic-gate vmem_free(heap_arena, videomem, videomem_size);
1935084Sjohnlev #endif
1940Sstevel@tonic-gate }
1958960SJan.Setje-Eilers@Sun.COM
1968960SJan.Setje-Eilers@Sun.COM /*ARGSUSED*/
1978960SJan.Setje-Eilers@Sun.COM void
progressbar_key_abort(ldi_ident_t li)1988960SJan.Setje-Eilers@Sun.COM progressbar_key_abort(ldi_ident_t li)
1998960SJan.Setje-Eilers@Sun.COM {
2008960SJan.Setje-Eilers@Sun.COM #if !defined(__xpv)
2018960SJan.Setje-Eilers@Sun.COM char *fbpath;
2028960SJan.Setje-Eilers@Sun.COM int ret;
2038960SJan.Setje-Eilers@Sun.COM ldi_handle_t hdl;
2048960SJan.Setje-Eilers@Sun.COM
2058960SJan.Setje-Eilers@Sun.COM extern char *consconfig_get_plat_fbpath(void);
2068960SJan.Setje-Eilers@Sun.COM
2078960SJan.Setje-Eilers@Sun.COM if (graphics_mode == 0)
2088960SJan.Setje-Eilers@Sun.COM return;
2098960SJan.Setje-Eilers@Sun.COM
2108960SJan.Setje-Eilers@Sun.COM fbpath = consconfig_get_plat_fbpath();
2118960SJan.Setje-Eilers@Sun.COM
2128960SJan.Setje-Eilers@Sun.COM if (ldi_open_by_name(fbpath, FWRITE, kcred, &hdl, li) != 0) {
2138960SJan.Setje-Eilers@Sun.COM cmn_err(CE_NOTE, "!ldi_open_by_name failed");
2148960SJan.Setje-Eilers@Sun.COM } else {
2158960SJan.Setje-Eilers@Sun.COM if (ldi_ioctl(hdl, KDSETMODE, KD_RESETTEXT, FKIOCTL,
2168960SJan.Setje-Eilers@Sun.COM kcred, &ret)
2178960SJan.Setje-Eilers@Sun.COM != 0)
2188960SJan.Setje-Eilers@Sun.COM cmn_err(CE_NOTE,
2198960SJan.Setje-Eilers@Sun.COM "!ldi_ioctl for KD_RESETTEXT failed");
2208960SJan.Setje-Eilers@Sun.COM (void) ldi_close(hdl, NULL, kcred);
2218960SJan.Setje-Eilers@Sun.COM }
2228960SJan.Setje-Eilers@Sun.COM #endif
2238960SJan.Setje-Eilers@Sun.COM }
224