summaryrefslogtreecommitdiffstats
path: root/sys/dev/vt/vt_cpulogos.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/vt/vt_cpulogos.c')
-rw-r--r--sys/dev/vt/vt_cpulogos.c266
1 files changed, 266 insertions, 0 deletions
diff --git a/sys/dev/vt/vt_cpulogos.c b/sys/dev/vt/vt_cpulogos.c
new file mode 100644
index 0000000..af604a8
--- /dev/null
+++ b/sys/dev/vt/vt_cpulogos.c
@@ -0,0 +1,266 @@
+/*-
+ * Copyright (c) 2015 Conrad Meyer <cse.cem@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/callout.h>
+#include <sys/cons.h>
+#include <sys/kernel.h>
+#include <sys/smp.h>
+#include <sys/systm.h>
+#include <sys/terminal.h>
+
+#include <dev/vt/vt.h>
+
+extern const unsigned char vt_beastie_vga16[];
+extern const unsigned char vt_beastie2_vga16[];
+extern const unsigned char vt_orb_vga16[];
+
+static struct callout vt_splash_cpu_callout;
+
+static inline unsigned char
+vt_vga2bsd(unsigned char vga)
+{
+ static const unsigned char lut[8] = {
+ 0,
+ 4, /* 1 and 4 swap */
+ 2,
+ 6, /* 3 and 6 swap */
+ 1, /* 4 and 1 swap */
+ 5,
+ 3, /* 6 and 3 swap */
+ 7,
+ };
+ unsigned int bright;
+
+ bright = (vga & 0x8);
+ return (lut[vga & 0x7] | bright);
+}
+
+static void
+vt_draw_2_vga16_px(struct vt_device *vd, vt_axis_t x, vt_axis_t y,
+ unsigned char color)
+{
+
+ vd->vd_driver->vd_setpixel(vd, x, y, vt_vga2bsd(color >> 4));
+ vd->vd_driver->vd_setpixel(vd, x + 1, y, vt_vga2bsd(color & 0xf));
+}
+
+static void
+vt_draw_1_logo(struct vt_device *vd, vt_axis_t top, vt_axis_t left)
+{
+ const unsigned char rle_sent = 0x16, *data;
+ unsigned int xy, run, runcolor, i;
+
+ switch (vt_splash_cpu_style) {
+ case VT_LOGOS_DRAW_ALT_BEASTIE:
+ data = vt_beastie2_vga16;
+ break;
+ case VT_LOGOS_DRAW_ORB:
+ data = vt_orb_vga16;
+ break;
+ case VT_LOGOS_DRAW_BEASTIE:
+ /* FALLTHROUGH */
+ default:
+ data = vt_beastie_vga16;
+ break;
+ }
+
+ /* Decode basic RLE (gets us to 30-40% of uncompressed data size): */
+ for (i = 0, xy = 0; xy < vt_logo_sprite_height * vt_logo_sprite_width;) {
+ if (data[i] == rle_sent) {
+ runcolor = data[i + 1];
+ run = data[i + 2];
+
+ for (; run; run--, xy += 2)
+ vt_draw_2_vga16_px(vd,
+ left + (xy % vt_logo_sprite_width),
+ top + (xy / vt_logo_sprite_width),
+ runcolor);
+
+ i += 3;
+ } else {
+ vt_draw_2_vga16_px(vd, left + (xy % vt_logo_sprite_width),
+ top + (xy / vt_logo_sprite_width), data[i]);
+
+ i++;
+ xy += 2;
+ }
+ }
+}
+
+void
+vtterm_draw_cpu_logos(struct vt_device *vd)
+{
+ unsigned int ncpu, i;
+ vt_axis_t left;
+
+ if (vt_splash_ncpu)
+ ncpu = vt_splash_ncpu;
+ else {
+ ncpu = mp_ncpus;
+ if (ncpu < 1)
+ ncpu = 1;
+ }
+
+ if (vd->vd_driver->vd_drawrect)
+ vd->vd_driver->vd_drawrect(vd, 0, 0, vd->vd_width,
+ vt_logo_sprite_height, 1, TC_BLACK);
+ /*
+ * Blank is okay because we only ever draw beasties on full screen
+ * refreshes.
+ */
+ else if (vd->vd_driver->vd_blank)
+ vd->vd_driver->vd_blank(vd, TC_BLACK);
+
+ ncpu = MIN(ncpu, vd->vd_width / vt_logo_sprite_width);
+ for (i = 0, left = 0; i < ncpu; left += vt_logo_sprite_width, i++)
+ vt_draw_1_logo(vd, 0, left);
+}
+
+static void
+vt_fini_logos(void *dummy __unused)
+{
+ struct vt_device *vd;
+ struct vt_window *vw;
+ struct terminal *tm;
+ struct vt_font *vf;
+ struct winsize wsz;
+ term_pos_t size;
+
+ if (!vt_draw_logo_cpus)
+ return;
+ if (!vty_enabled(VTY_VT))
+ return;
+ if (!vt_splash_cpu)
+ return;
+
+ tm = &vt_consterm;
+ vw = tm->tm_softc;
+ if (vw == NULL)
+ return;
+ vd = vw->vw_device;
+ if (vd == NULL)
+ return;
+ vf = vw->vw_font;
+ if (vf == NULL)
+ return;
+
+ VT_LOCK(vd);
+ if ((vd->vd_flags & (VDF_DEAD | VDF_TEXTMODE)) != 0)
+ goto out;
+
+ vt_draw_logo_cpus = 0;
+ VT_UNLOCK(vd);
+
+ vt_termsize(vd, vf, &size);
+ vt_winsize(vd, vf, &wsz);
+
+ /* Resize screen buffer and terminal. */
+ terminal_mute(tm, 1);
+ vtbuf_grow(&vw->vw_buf, &size, vw->vw_buf.vb_history_size);
+ terminal_set_winsize_blank(tm, &wsz, 0, NULL);
+ terminal_set_cursor(tm, &vw->vw_buf.vb_cursor);
+ terminal_mute(tm, 0);
+
+ VT_LOCK(vd);
+ vt_compute_drawable_area(vw);
+
+ if (vd->vd_curwindow == vw) {
+ vd->vd_flags |= VDF_INVALID;
+ vt_resume_flush_timer(vd, 0);
+ }
+
+out:
+ VT_UNLOCK(vd);
+}
+
+static void
+vt_init_logos(void *dummy)
+{
+ struct vt_device *vd;
+ struct vt_window *vw;
+ struct terminal *tm;
+ struct vt_font *vf;
+ struct winsize wsz;
+ term_pos_t size;
+
+ if (!vty_enabled(VTY_VT))
+ return;
+ if (!vt_splash_cpu)
+ return;
+
+ tm = &vt_consterm;
+ vw = tm->tm_softc;
+ if (vw == NULL)
+ return;
+ vd = vw->vw_device;
+ if (vd == NULL)
+ return;
+ vf = vw->vw_font;
+ if (vf == NULL)
+ return;
+
+ VT_LOCK(vd);
+ KASSERT((vd->vd_flags & VDF_INITIALIZED) != 0,
+ ("vd %p not initialized", vd));
+
+ if ((vd->vd_flags & (VDF_DEAD | VDF_TEXTMODE)) != 0)
+ goto out;
+ if (vd->vd_height <= vt_logo_sprite_height)
+ goto out;
+
+ vt_draw_logo_cpus = 1;
+ VT_UNLOCK(vd);
+
+ vt_termsize(vd, vf, &size);
+ vt_winsize(vd, vf, &wsz);
+
+ /* Resize screen buffer and terminal. */
+ terminal_mute(tm, 1);
+ vtbuf_grow(&vw->vw_buf, &size, vw->vw_buf.vb_history_size);
+ terminal_set_winsize_blank(tm, &wsz, 0, NULL);
+ terminal_set_cursor(tm, &vw->vw_buf.vb_cursor);
+ terminal_mute(tm, 0);
+
+ VT_LOCK(vd);
+ vt_compute_drawable_area(vw);
+
+ if (vd->vd_curwindow == vw) {
+ vd->vd_flags |= VDF_INVALID;
+ vt_resume_flush_timer(vd, 0);
+ }
+
+ callout_init(&vt_splash_cpu_callout, 1);
+ callout_reset(&vt_splash_cpu_callout, vt_splash_cpu_duration * hz,
+ vt_fini_logos, NULL);
+
+out:
+ VT_UNLOCK(vd);
+}
+SYSINIT(vt_logos, SI_SUB_CPU + 1, SI_ORDER_ANY, vt_init_logos, NULL);
OpenPOWER on IntegriCloud