125968Syokota/*-
225968Syokota * Copyright (c) 1997 Sandro Sigala, Brescia, Italy.
326081Syokota * Copyright (c) 1997 Chris Shenton
425968Syokota * Copyright (c) 1995 S ren Schmidt
525968Syokota * All rights reserved.
625968Syokota *
725968Syokota * Redistribution and use in source and binary forms, with or without
825968Syokota * modification, are permitted provided that the following conditions
925968Syokota * are met:
1025968Syokota * 1. Redistributions of source code must retain the above copyright
1125968Syokota *    notice, this list of conditions and the following disclaimer
1225968Syokota *    in this position and unchanged.
1325968Syokota * 2. Redistributions in binary form must reproduce the above copyright
1425968Syokota *    notice, this list of conditions and the following disclaimer in the
1525968Syokota *    documentation and/or other materials provided with the distribution.
1625968Syokota *
1725968Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1825968Syokota * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1925968Syokota * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2025968Syokota * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2125968Syokota * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2225968Syokota * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2325968Syokota * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2425968Syokota * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2525968Syokota * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2625968Syokota * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2725968Syokota *
2850477Speter * $FreeBSD$
2925968Syokota */
3025968Syokota
3125968Syokota#include <sys/param.h>
3225968Syokota#include <sys/systm.h>
3340885Speter#include <sys/module.h>
3427427Syokota#include <sys/malloc.h>
35193066Sjamie#include <sys/jail.h>
3626893Syokota#include <sys/kernel.h>
3726893Syokota#include <sys/sysctl.h>
3848104Syokota#include <sys/consio.h>
3948104Syokota#include <sys/fbio.h>
4025968Syokota
4132571Sbde#include <machine/pc/display.h>
4225968Syokota
4348104Syokota#include <dev/fb/fbreg.h>
4448104Syokota#include <dev/fb/splashreg.h>
4548104Syokota#include <dev/syscons/syscons.h>
4625968Syokota
4725968Syokota#define DAEMON_MAX_WIDTH	32
4825968Syokota#define DAEMON_MAX_HEIGHT	19
4925968Syokota
5072797Snyanstatic u_char *message;
5127427Syokotastatic int messagelen;
5242504Syokotastatic int blanked;
53146238Snyanstatic int attr_mask;
5427427Syokota
55146238Snyan#define	ATTR(attr)	(((attr) & attr_mask) << 8)
56146238Snyan
5726081Syokota/* Who is the author of this ASCII pic? */
5826081Syokota
5972797Snyanstatic u_char *daemon_pic[] = {
6025968Syokota        "             ,        ,",
6125968Syokota	"            /(        )`",
6225968Syokota	"            \\ \\___   / |",
6325968Syokota	"            /- _  `-/  '",
6425968Syokota	"           (/\\/ \\ \\   /\\",
6525968Syokota	"           / /   | `    \\",
6625968Syokota	"           O O   ) /    |",
6725968Syokota	"           `-^--'`<     '",
6825968Syokota	"          (_.)  _  )   /",
6925968Syokota	"           `.___/`    /",
7025968Syokota	"             `-----' /",
7125968Syokota	"<----.     __ / __   \\",
7225968Syokota	"<----|====O)))==) \\) /====",
7325968Syokota	"<----'    `--' `.__,' \\",
7425968Syokota	"             |        |",
7525968Syokota	"              \\       /       /\\",
7625968Syokota	"         ______( (_  / \\______/",
7725968Syokota	"       ,'  ,-----'   |",
7825968Syokota	"       `--{__________)",
7925968Syokota	NULL
8025968Syokota};
8125968Syokota
8272797Snyanstatic u_char *daemon_attr[] = {
8325968Syokota        "             R        R",
8425968Syokota	"            RR        RR",
8525968Syokota	"            R RRRR   R R",
8625968Syokota	"            RR W  RRR  R",
8725968Syokota	"           RWWW W R   RR",
8825968Syokota	"           W W   W R    R",
8925968Syokota	"           B B   W R    R",
9025968Syokota	"           WWWWWWRR     R",
9125968Syokota	"          RRRR  R  R   R",
9225968Syokota	"           RRRRRRR    R",
9325968Syokota	"             RRRRRRR R",
9425968Syokota	"YYYYYY     RR R RR   R",
9525968Syokota	"YYYYYYYYYYRRRRYYR RR RYYYY",
9625968Syokota	"YYYYYY    RRRR RRRRRR R",
9725968Syokota	"             R        R",
9825968Syokota	"              R       R       RR",
9925968Syokota	"         CCCCCCR RR  R RRRRRRRR",
10025968Syokota	"       CC  CCCCCCC   C",
10125968Syokota	"       CCCCCCCCCCCCCCC",
10225968Syokota	NULL
10325968Syokota};
10425968Syokota
10526081Syokota/*
10626081Syokota * Reverse a graphics character, or return unaltered if no mirror;
10726081Syokota * should do alphanumerics too, but I'm too lazy. <cshenton@it.hq.nasa.gov>
10826081Syokota */
10925968Syokota
11072797Snyanstatic u_char
11172797Snyanxflip_symbol(u_char symbol)
11226081Syokota{
11372797Snyan	static const u_char lchars[] = "`'(){}[]\\/<>";
11472797Snyan	static const u_char rchars[] = "'`)(}{][/\\><";
11526081Syokota	int pos;
11626081Syokota
11726081Syokota	for (pos = 0; lchars[pos] != '\0'; pos++)
11826081Syokota		if (lchars[pos] == symbol)
11926081Syokota			return rchars[pos];
12026081Syokota
12126081Syokota	return symbol;
12226081Syokota}
12326081Syokota
12425968Syokotastatic void
12548104Syokotaclear_daemon(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
12630725Syokota	    int xlen, int ylen)
12725968Syokota{
12830725Syokota	int y;
12930725Syokota
13030725Syokota	if (xlen <= 0)
13130725Syokota		return;
13248104Syokota	for (y = yoff; y < ylen; y++) {
13348104Syokota		sc_vtb_erase(&sc->cur_scp->scr,
13448104Syokota			     (ypos + y)*sc->cur_scp->xsize + xpos + xoff,
13548104Syokota			     xlen - xoff,
136146238Snyan			     sc->scr_map[0x20], ATTR(FG_LIGHTGREY | BG_BLACK));
13748104Syokota	}
13830725Syokota}
13930725Syokota
14030725Syokotastatic void
14148104Syokotadraw_daemon(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
14230725Syokota	    int xlen, int ylen)
14330725Syokota{
14425968Syokota	int x, y;
14530725Syokota	int px;
14625968Syokota	int attr;
14725968Syokota
14830725Syokota	for (y = yoff; y < ylen; y++) {
14930725Syokota		if (dxdir < 0)
15030725Syokota			px = xoff;
15130725Syokota		else
15230725Syokota			px = DAEMON_MAX_WIDTH - xlen;
15330725Syokota		if (px >= strlen(daemon_pic[y]))
15430725Syokota			continue;
15530725Syokota		for (x = xoff; (x < xlen) && (daemon_pic[y][px] != '\0'); x++, px++) {
15630725Syokota			switch (daemon_attr[y][px]) {
157146238Snyan			case 'R': attr = FG_LIGHTRED | BG_BLACK; break;
158146238Snyan			case 'Y': attr = FG_YELLOW | BG_BLACK; break;
159146238Snyan			case 'B': attr = FG_LIGHTBLUE | BG_BLACK; break;
160146238Snyan			case 'W': attr = FG_LIGHTGREY | BG_BLACK; break;
161146238Snyan			case 'C': attr = FG_CYAN | BG_BLACK; break;
162146238Snyan			default: attr = FG_WHITE | BG_BLACK; break;
16325968Syokota			}
16426081Syokota			if (dxdir < 0) {	/* Moving left */
16548104Syokota				sc_vtb_putc(&sc->cur_scp->scr,
16648104Syokota					    (ypos + y)*sc->cur_scp->xsize
16748104Syokota						 + xpos + x,
16848104Syokota					    sc->scr_map[daemon_pic[y][px]],
169146238Snyan					    ATTR(attr));
17026081Syokota			} else {		/* Moving right */
17148104Syokota				sc_vtb_putc(&sc->cur_scp->scr,
17248104Syokota					    (ypos + y)*sc->cur_scp->xsize
17348104Syokota						+ xpos + DAEMON_MAX_WIDTH
17448104Syokota						- px - 1,
17548104Syokota					    sc->scr_map[xflip_symbol(daemon_pic[y][px])],
176146238Snyan					    ATTR(attr));
17726081Syokota			}
17825968Syokota		}
17930725Syokota	}
18025968Syokota}
18125968Syokota
18225968Syokotastatic void
18348104Syokotaclear_string(sc_softc_t *sc, int xpos, int ypos, int xoff, char *s, int len)
18425968Syokota{
18530725Syokota	if (len <= 0)
18630725Syokota		return;
18748104Syokota	sc_vtb_erase(&sc->cur_scp->scr,
18848104Syokota		     ypos*sc->cur_scp->xsize + xpos + xoff, len - xoff,
189146238Snyan		     sc->scr_map[0x20], ATTR(FG_LIGHTGREY | BG_BLACK));
19030725Syokota}
19130725Syokota
19230725Syokotastatic void
19372797Snyandraw_string(sc_softc_t *sc, int xpos, int ypos, int xoff, u_char *s, int len)
19430725Syokota{
19525968Syokota	int x;
19625968Syokota
197146238Snyan	for (x = xoff; x < len; x++)
19848104Syokota		sc_vtb_putc(&sc->cur_scp->scr,
19948104Syokota			    ypos*sc->cur_scp->xsize + xpos + x,
200146238Snyan			    sc->scr_map[s[x]], ATTR(FG_LIGHTGREEN | BG_BLACK));
20125968Syokota}
20225968Syokota
20342504Syokotastatic int
20442504Syokotadaemon_saver(video_adapter_t *adp, int blank)
20525968Syokota{
20626081Syokota	static int txpos = 10, typos = 10;
20726081Syokota	static int txdir = -1, tydir = -1;
20825968Syokota	static int dxpos = 0, dypos = 0;
20925968Syokota	static int dxdir = 1, dydir = 1;
21025968Syokota	static int moved_daemon = 0;
21130725Syokota	static int xoff, yoff, toff;
21230725Syokota	static int xlen, ylen, tlen;
21348104Syokota	sc_softc_t *sc;
21448104Syokota	scr_stat *scp;
21530725Syokota	int min, max;
21625968Syokota
21748104Syokota	sc = sc_find_softc(adp, NULL);
21848104Syokota	if (sc == NULL)
21948104Syokota		return EAGAIN;
22048104Syokota	scp = sc->cur_scp;
22148104Syokota
22225968Syokota	if (blank) {
22343673Sdes		if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
22442749Syokota			return EAGAIN;
22542504Syokota		if (blanked == 0) {
22630725Syokota			/* clear the screen and set the border color */
22748104Syokota			sc_vtb_clear(&scp->scr, sc->scr_map[0x20],
228146238Snyan				     ATTR(FG_LIGHTGREY | BG_BLACK));
229174985Swkoszek			vidd_set_hw_cursor(adp, -1, -1);
23056043Syokota			sc_set_border(scp, 0);
23130725Syokota			xlen = ylen = tlen = 0;
23230725Syokota		}
23342504Syokota		if (blanked++ < 2)
23442504Syokota			return 0;
23542504Syokota		blanked = 1;
23625968Syokota
23748104Syokota 		clear_daemon(sc, dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
23872797Snyan		clear_string(sc, txpos, typos, toff, message, tlen);
23930725Syokota
24025968Syokota		if (++moved_daemon) {
24130725Syokota			/*
24230725Syokota			 * The daemon picture may be off the screen, if
24330725Syokota			 * screen size is chagened while the screen
24430725Syokota			 * saver is inactive. Make sure the origin of
24530725Syokota			 * the picture is between min and max.
24630725Syokota			 */
24730725Syokota			if (scp->xsize <= DAEMON_MAX_WIDTH) {
24830725Syokota				/*
24930725Syokota				 * If the screen width is too narrow, we
25030725Syokota				 * allow part of the picture go off
25130725Syokota				 * the screen so that the daemon won't
25230725Syokota				 * flip too often.
25330725Syokota				 */
25430725Syokota				min = scp->xsize - DAEMON_MAX_WIDTH - 10;
25530725Syokota				max = 10;
25625968Syokota			} else {
25730725Syokota				min = 0;
25830725Syokota				max = scp->xsize - DAEMON_MAX_WIDTH;
25925968Syokota			}
26030725Syokota			if (dxpos <= min) {
26130725Syokota				dxpos = min;
26230725Syokota				dxdir = 1;
26330725Syokota			} else if (dxpos >= max) {
26430725Syokota				dxpos = max;
26530725Syokota				dxdir = -1;
26630725Syokota			}
26730725Syokota
26830725Syokota			if (scp->ysize <= DAEMON_MAX_HEIGHT) {
26930725Syokota				min = scp->ysize - DAEMON_MAX_HEIGHT - 10;
27030725Syokota				max = 10;
27125968Syokota			} else {
27230725Syokota				min = 0;
27330725Syokota				max = scp->ysize - DAEMON_MAX_HEIGHT;
27425968Syokota			}
27530725Syokota			if (dypos <= min) {
27630725Syokota				dypos = min;
27730725Syokota				dydir = 1;
27830725Syokota			} else if (dypos >= max) {
27930725Syokota				dypos = max;
28030725Syokota				dydir = -1;
28130725Syokota			}
28230725Syokota
28325968Syokota			moved_daemon = -1;
28425968Syokota			dxpos += dxdir; dypos += dydir;
28530725Syokota
28630725Syokota			/* clip the picture */
28730725Syokota			xoff = 0;
28830725Syokota			xlen = DAEMON_MAX_WIDTH;
28930725Syokota			if (dxpos + xlen <= 0)
29030725Syokota				xlen = 0;
29130725Syokota			else if (dxpos < 0)
29230725Syokota				xoff = -dxpos;
29330725Syokota			if (dxpos >= scp->xsize)
29430725Syokota				xlen = 0;
29530725Syokota			else if (dxpos + xlen > scp->xsize)
29630725Syokota				xlen = scp->xsize - dxpos;
29730725Syokota			yoff = 0;
29830725Syokota			ylen = DAEMON_MAX_HEIGHT;
29930725Syokota			if (dypos + ylen <= 0)
30030725Syokota				ylen = 0;
30130725Syokota			else if (dypos < 0)
30230725Syokota				yoff = -dypos;
30330725Syokota			if (dypos >= scp->ysize)
30430725Syokota				ylen = 0;
30530725Syokota			else if (dypos + ylen > scp->ysize)
30630725Syokota				ylen = scp->ysize - dypos;
30725968Syokota		}
30825968Syokota
30930725Syokota		if (scp->xsize <= messagelen) {
31030725Syokota			min = scp->xsize - messagelen - 10;
31130725Syokota			max = 10;
31225968Syokota		} else {
31330725Syokota			min = 0;
31430725Syokota			max = scp->xsize - messagelen;
31525968Syokota		}
31630725Syokota		if (txpos <= min) {
31730725Syokota			txpos = min;
31830725Syokota			txdir = 1;
31930725Syokota		} else if (txpos >= max) {
32030725Syokota			txpos = max;
32130725Syokota			txdir = -1;
32225968Syokota		}
32330725Syokota		if (typos <= 0) {
32430725Syokota			typos = 0;
32530725Syokota			tydir = 1;
32630725Syokota		} else if (typos >= scp->ysize - 1) {
32730725Syokota			typos = scp->ysize - 1;
32830725Syokota			tydir = -1;
32930725Syokota		}
33025968Syokota		txpos += txdir; typos += tydir;
33125968Syokota
33230725Syokota		toff = 0;
33330725Syokota		tlen = messagelen;
33430725Syokota		if (txpos + tlen <= 0)
33530725Syokota			tlen = 0;
33630725Syokota		else if (txpos < 0)
33730725Syokota			toff = -txpos;
33830725Syokota		if (txpos >= scp->xsize)
33930725Syokota			tlen = 0;
34030725Syokota		else if (txpos + tlen > scp->xsize)
34130725Syokota			tlen = scp->xsize - txpos;
34230725Syokota
34348104Syokota 		draw_daemon(sc, dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
34472797Snyan		draw_string(sc, txpos, typos, toff, message, tlen);
345146238Snyan	} else
34642504Syokota		blanked = 0;
347146238Snyan
34842504Syokota	return 0;
34925968Syokota}
35025968Syokota
35125968Syokotastatic int
35242504Syokotadaemon_init(video_adapter_t *adp)
35325968Syokota{
354197062Sjhb	size_t hostlen;
355180291Srwatson
356193066Sjamie	mtx_lock(&prison0.pr_mtx);
357197062Sjhb	for (;;) {
358197062Sjhb		hostlen = strlen(prison0.pr_hostname);
359197062Sjhb		mtx_unlock(&prison0.pr_mtx);
360197062Sjhb
361197062Sjhb		messagelen = hostlen + 3 + strlen(ostype) + 1 +
362197062Sjhb		    strlen(osrelease);
363197062Sjhb		message = malloc(messagelen + 1, M_DEVBUF, M_WAITOK);
364197062Sjhb		mtx_lock(&prison0.pr_mtx);
365197062Sjhb		if (hostlen < strlen(prison0.pr_hostname)) {
366197062Sjhb			free(message, M_DEVBUF);
367197062Sjhb			continue;
368197062Sjhb		}
369197062Sjhb		break;
370197062Sjhb	}
371194118Sjamie	sprintf(message, "%s - %s %s", prison0.pr_hostname, ostype, osrelease);
372193066Sjamie	mtx_unlock(&prison0.pr_mtx);
37342504Syokota	blanked = 0;
374146238Snyan	switch (adp->va_mode) {
375146238Snyan	case M_PC98_80x25:
376146238Snyan	case M_PC98_80x30:
377146238Snyan		attr_mask = ~FG_UNDERLINE;
378146238Snyan		break;
379146238Snyan	default:
380146238Snyan		attr_mask = ~0;
381146238Snyan		break;
382146238Snyan	}
383146238Snyan
38442504Syokota	return 0;
38525968Syokota}
38625968Syokota
38725968Syokotastatic int
38842504Syokotadaemon_term(video_adapter_t *adp)
38925968Syokota{
39042504Syokota	free(message, M_DEVBUF);
39142504Syokota	return 0;
39225968Syokota}
39325968Syokota
39442504Syokotastatic scrn_saver_t daemon_module = {
39542504Syokota	"daemon_saver", daemon_init, daemon_term, daemon_saver, NULL,
39642504Syokota};
39742504Syokota
39842504SyokotaSAVER_MODULE(daemon_saver, daemon_module);
399