1285766Scem/*- 2285766Scem * Copyright (c) 2015 Conrad Meyer <cse.cem@gmail.com> 3285766Scem * All rights reserved. 4285766Scem * 5285766Scem * Redistribution and use in source and binary forms, with or without 6285766Scem * modification, are permitted provided that the following conditions 7285766Scem * are met: 8285766Scem * 1. Redistributions of source code must retain the above copyright 9285766Scem * notice, this list of conditions and the following disclaimer. 10285766Scem * 2. Redistributions in binary form must reproduce the above copyright 11285766Scem * notice, this list of conditions and the following disclaimer in the 12285766Scem * documentation and/or other materials provided with the distribution. 13285766Scem * 14285766Scem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15285766Scem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16285766Scem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17285766Scem * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18285766Scem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19285766Scem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20285766Scem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21285766Scem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22285766Scem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23285766Scem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24285766Scem * SUCH DAMAGE. 25285766Scem */ 26285766Scem 27285766Scem#include <sys/cdefs.h> 28285766Scem__FBSDID("$FreeBSD: releng/11.0/sys/dev/vt/vt_cpulogos.c 286997 2015-08-21 15:21:56Z cem $"); 29285766Scem 30285766Scem#include <sys/param.h> 31285766Scem#include <sys/callout.h> 32285766Scem#include <sys/cons.h> 33285766Scem#include <sys/kernel.h> 34285766Scem#include <sys/smp.h> 35285766Scem#include <sys/systm.h> 36285766Scem#include <sys/terminal.h> 37285766Scem 38285766Scem#include <dev/vt/vt.h> 39285766Scem 40285766Scemextern const unsigned char vt_beastie_vga16[]; 41285766Scemextern const unsigned char vt_beastie2_vga16[]; 42285766Scemextern const unsigned char vt_orb_vga16[]; 43285766Scem 44285766Scemstatic struct callout vt_splash_cpu_callout; 45285766Scem 46285766Scemstatic inline unsigned char 47285766Scemvt_vga2bsd(unsigned char vga) 48285766Scem{ 49285766Scem static const unsigned char lut[8] = { 50285766Scem 0, 51285766Scem 4, /* 1 and 4 swap */ 52285766Scem 2, 53285766Scem 6, /* 3 and 6 swap */ 54285766Scem 1, /* 4 and 1 swap */ 55285766Scem 5, 56285766Scem 3, /* 6 and 3 swap */ 57285766Scem 7, 58285766Scem }; 59285766Scem unsigned int bright; 60285766Scem 61285766Scem bright = (vga & 0x8); 62285766Scem return (lut[vga & 0x7] | bright); 63285766Scem} 64285766Scem 65285766Scemstatic void 66285766Scemvt_draw_2_vga16_px(struct vt_device *vd, vt_axis_t x, vt_axis_t y, 67285766Scem unsigned char color) 68285766Scem{ 69285766Scem 70285766Scem vd->vd_driver->vd_setpixel(vd, x, y, vt_vga2bsd(color >> 4)); 71285766Scem vd->vd_driver->vd_setpixel(vd, x + 1, y, vt_vga2bsd(color & 0xf)); 72285766Scem} 73285766Scem 74285766Scemstatic void 75285766Scemvt_draw_1_logo(struct vt_device *vd, vt_axis_t top, vt_axis_t left) 76285766Scem{ 77285766Scem const unsigned char rle_sent = 0x16, *data; 78285766Scem unsigned int xy, run, runcolor, i; 79285766Scem 80285766Scem switch (vt_splash_cpu_style) { 81285766Scem case VT_LOGOS_DRAW_ALT_BEASTIE: 82285766Scem data = vt_beastie2_vga16; 83285766Scem break; 84285766Scem case VT_LOGOS_DRAW_ORB: 85285766Scem data = vt_orb_vga16; 86285766Scem break; 87285766Scem case VT_LOGOS_DRAW_BEASTIE: 88285766Scem /* FALLTHROUGH */ 89285766Scem default: 90285766Scem data = vt_beastie_vga16; 91285766Scem break; 92285766Scem } 93285766Scem 94285766Scem /* Decode basic RLE (gets us to 30-40% of uncompressed data size): */ 95285766Scem for (i = 0, xy = 0; xy < vt_logo_sprite_height * vt_logo_sprite_width;) { 96285766Scem if (data[i] == rle_sent) { 97285766Scem runcolor = data[i + 1]; 98285766Scem run = data[i + 2]; 99285766Scem 100285766Scem for (; run; run--, xy += 2) 101285766Scem vt_draw_2_vga16_px(vd, 102285766Scem left + (xy % vt_logo_sprite_width), 103285766Scem top + (xy / vt_logo_sprite_width), 104285766Scem runcolor); 105285766Scem 106285766Scem i += 3; 107285766Scem } else { 108285766Scem vt_draw_2_vga16_px(vd, left + (xy % vt_logo_sprite_width), 109285766Scem top + (xy / vt_logo_sprite_width), data[i]); 110285766Scem 111285766Scem i++; 112285766Scem xy += 2; 113285766Scem } 114285766Scem } 115285766Scem} 116285766Scem 117285766Scemvoid 118285766Scemvtterm_draw_cpu_logos(struct vt_device *vd) 119285766Scem{ 120285766Scem unsigned int ncpu, i; 121285766Scem vt_axis_t left; 122285766Scem 123285766Scem if (vt_splash_ncpu) 124285766Scem ncpu = vt_splash_ncpu; 125285766Scem else { 126285766Scem ncpu = mp_ncpus; 127285766Scem if (ncpu < 1) 128285766Scem ncpu = 1; 129285766Scem } 130285766Scem 131285766Scem if (vd->vd_driver->vd_drawrect) 132285766Scem vd->vd_driver->vd_drawrect(vd, 0, 0, vd->vd_width, 133285766Scem vt_logo_sprite_height, 1, TC_BLACK); 134285766Scem /* 135285766Scem * Blank is okay because we only ever draw beasties on full screen 136285766Scem * refreshes. 137285766Scem */ 138285766Scem else if (vd->vd_driver->vd_blank) 139285766Scem vd->vd_driver->vd_blank(vd, TC_BLACK); 140285766Scem 141285766Scem ncpu = MIN(ncpu, vd->vd_width / vt_logo_sprite_width); 142285766Scem for (i = 0, left = 0; i < ncpu; left += vt_logo_sprite_width, i++) 143285766Scem vt_draw_1_logo(vd, 0, left); 144285766Scem} 145285766Scem 146285766Scemstatic void 147285766Scemvt_fini_logos(void *dummy __unused) 148285766Scem{ 149285766Scem struct vt_device *vd; 150285766Scem struct vt_window *vw; 151285766Scem struct terminal *tm; 152285766Scem struct vt_font *vf; 153285766Scem struct winsize wsz; 154285766Scem term_pos_t size; 155286997Scem unsigned int i; 156285766Scem 157285766Scem if (!vt_draw_logo_cpus) 158285766Scem return; 159285766Scem if (!vty_enabled(VTY_VT)) 160285766Scem return; 161285766Scem if (!vt_splash_cpu) 162285766Scem return; 163285766Scem 164286997Scem vd = &vt_consdev; 165286997Scem VT_LOCK(vd); 166286997Scem if ((vd->vd_flags & (VDF_DEAD | VDF_TEXTMODE)) != 0) { 167286997Scem VT_UNLOCK(vd); 168285766Scem return; 169286997Scem } 170285766Scem vt_draw_logo_cpus = 0; 171285766Scem VT_UNLOCK(vd); 172285766Scem 173286997Scem for (i = 0; i < VT_MAXWINDOWS; i++) { 174286997Scem vw = vd->vd_windows[i]; 175286997Scem if (vw == NULL) 176286997Scem continue; 177286997Scem tm = vw->vw_terminal; 178286997Scem vf = vw->vw_font; 179286997Scem if (vf == NULL) 180286997Scem continue; 181285766Scem 182286997Scem vt_termsize(vd, vf, &size); 183286997Scem vt_winsize(vd, vf, &wsz); 184285766Scem 185286997Scem /* Resize screen buffer and terminal. */ 186286997Scem terminal_mute(tm, 1); 187286997Scem vtbuf_grow(&vw->vw_buf, &size, vw->vw_buf.vb_history_size); 188286997Scem terminal_set_winsize_blank(tm, &wsz, 0, NULL); 189286997Scem terminal_set_cursor(tm, &vw->vw_buf.vb_cursor); 190286997Scem terminal_mute(tm, 0); 191285766Scem 192286997Scem VT_LOCK(vd); 193286997Scem vt_compute_drawable_area(vw); 194286997Scem 195286997Scem if (vd->vd_curwindow == vw) { 196286997Scem vd->vd_flags |= VDF_INVALID; 197286997Scem vt_resume_flush_timer(vd, 0); 198286997Scem } 199286997Scem VT_UNLOCK(vd); 200285766Scem } 201285766Scem} 202285766Scem 203285766Scemstatic void 204285766Scemvt_init_logos(void *dummy) 205285766Scem{ 206285766Scem struct vt_device *vd; 207285766Scem struct vt_window *vw; 208285766Scem struct terminal *tm; 209285766Scem struct vt_font *vf; 210285766Scem struct winsize wsz; 211285766Scem term_pos_t size; 212285766Scem 213285766Scem if (!vty_enabled(VTY_VT)) 214285766Scem return; 215285766Scem if (!vt_splash_cpu) 216285766Scem return; 217285766Scem 218285766Scem tm = &vt_consterm; 219285766Scem vw = tm->tm_softc; 220285766Scem if (vw == NULL) 221285766Scem return; 222285766Scem vd = vw->vw_device; 223285766Scem if (vd == NULL) 224285766Scem return; 225285766Scem vf = vw->vw_font; 226285766Scem if (vf == NULL) 227285766Scem return; 228285766Scem 229285766Scem VT_LOCK(vd); 230285766Scem KASSERT((vd->vd_flags & VDF_INITIALIZED) != 0, 231285766Scem ("vd %p not initialized", vd)); 232285766Scem 233285766Scem if ((vd->vd_flags & (VDF_DEAD | VDF_TEXTMODE)) != 0) 234285766Scem goto out; 235285766Scem if (vd->vd_height <= vt_logo_sprite_height) 236285766Scem goto out; 237285766Scem 238285766Scem vt_draw_logo_cpus = 1; 239285766Scem VT_UNLOCK(vd); 240285766Scem 241285766Scem vt_termsize(vd, vf, &size); 242285766Scem vt_winsize(vd, vf, &wsz); 243285766Scem 244285766Scem /* Resize screen buffer and terminal. */ 245285766Scem terminal_mute(tm, 1); 246285766Scem vtbuf_grow(&vw->vw_buf, &size, vw->vw_buf.vb_history_size); 247285766Scem terminal_set_winsize_blank(tm, &wsz, 0, NULL); 248285766Scem terminal_set_cursor(tm, &vw->vw_buf.vb_cursor); 249285766Scem terminal_mute(tm, 0); 250285766Scem 251285766Scem VT_LOCK(vd); 252285766Scem vt_compute_drawable_area(vw); 253285766Scem 254285766Scem if (vd->vd_curwindow == vw) { 255285766Scem vd->vd_flags |= VDF_INVALID; 256285766Scem vt_resume_flush_timer(vd, 0); 257285766Scem } 258285766Scem 259285766Scem callout_init(&vt_splash_cpu_callout, 1); 260285766Scem callout_reset(&vt_splash_cpu_callout, vt_splash_cpu_duration * hz, 261285766Scem vt_fini_logos, NULL); 262285766Scem 263285766Scemout: 264285766Scem VT_UNLOCK(vd); 265285766Scem} 266285766ScemSYSINIT(vt_logos, SI_SUB_CPU + 1, SI_ORDER_ANY, vt_init_logos, NULL); 267