diff options
Diffstat (limited to 'lkm/syscons/daemon/daemon_saver.c')
| -rw-r--r-- | lkm/syscons/daemon/daemon_saver.c | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/lkm/syscons/daemon/daemon_saver.c b/lkm/syscons/daemon/daemon_saver.c new file mode 100644 index 0000000000000..59e99f0fe328d --- /dev/null +++ b/lkm/syscons/daemon/daemon_saver.c @@ -0,0 +1,369 @@ +/*- + * Copyright (c) 1997 Sandro Sigala, Brescia, Italy. + * Copyright (c) 1997 Chris Shenton + * Copyright (c) 1995 S ren Schmidt + * 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 + * in this position and unchanged. + * 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 ``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 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. + * + * $Id: daemon_saver.c,v 1.10 1998/09/15 18:16:38 sos Exp $ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/exec.h> +#include <sys/sysent.h> +#include <sys/lkm.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> + +#include <machine/md_var.h> +#include <machine/pc/display.h> + +#include <saver.h> + +#define CONSOLE_VECT(x, y) \ + (window + (y)*cur_console->xsize + (x)) + +#define DAEMON_MAX_WIDTH 32 +#define DAEMON_MAX_HEIGHT 19 + +MOD_MISC(daemon_saver); + +static char *message; +static int messagelen; +static u_short *window; + +/* Who is the author of this ASCII pic? */ + +static char *daemon_pic[] = { + " , ,", + " /( )`", + " \\ \\___ / |", + " /- _ `-/ '", + " (/\\/ \\ \\ /\\", + " / / | ` \\", + " O O ) / |", + " `-^--'`< '", + " (_.) _ ) /", + " `.___/` /", + " `-----' /", + "<----. __ / __ \\", + "<----|====O)))==) \\) /====", + "<----' `--' `.__,' \\", + " | |", + " \\ / /\\", + " ______( (_ / \\______/", + " ,' ,-----' |", + " `--{__________)", + NULL +}; + +static char *daemon_attr[] = { + " R R", + " RR RR", + " R RRRR R R", + " RR W RRR R", + " RWWW W R RR", + " W W W R R", + " B B W R R", + " WWWWWWRR R", + " RRRR R R R", + " RRRRRRR R", + " RRRRRRR R", + "YYYYYY RR R RR R", + "YYYYYYYYYYRRRRYYR RR RYYYY", + "YYYYYY RRRR RRRRRR R", + " R R", + " R R RR", + " CCCCCCR RR R RRRRRRRR", + " CC CCCCCCC C", + " CCCCCCCCCCCCCCC", + NULL +}; + +/* + * Reverse a graphics character, or return unaltered if no mirror; + * should do alphanumerics too, but I'm too lazy. <cshenton@it.hq.nasa.gov> + */ + +static char +xflip_symbol(char symbol) +{ + static const char lchars[] = "`'(){}[]\\/<>"; + static const char rchars[] = "'`)(}{][/\\><"; + int pos; + + for (pos = 0; lchars[pos] != '\0'; pos++) + if (lchars[pos] == symbol) + return rchars[pos]; + + return symbol; +} + +static void +clear_daemon(int xpos, int ypos, int dxdir, int xoff, int yoff, + int xlen, int ylen) +{ + int y; + + if (xlen <= 0) + return; + for (y = yoff; y < ylen; y++) + fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20], + CONSOLE_VECT(xpos + xoff, ypos + y), xlen - xoff); +} + +static void +draw_daemon(int xpos, int ypos, int dxdir, int xoff, int yoff, + int xlen, int ylen) +{ + int x, y; + int px; + int attr; + + for (y = yoff; y < ylen; y++) { + if (dxdir < 0) + px = xoff; + else + px = DAEMON_MAX_WIDTH - xlen; + if (px >= strlen(daemon_pic[y])) + continue; + for (x = xoff; (x < xlen) && (daemon_pic[y][px] != '\0'); x++, px++) { + switch (daemon_attr[y][px]) { + case 'R': attr = (FG_LIGHTRED|BG_BLACK)<<8; break; + case 'Y': attr = (FG_YELLOW|BG_BLACK)<<8; break; + case 'B': attr = (FG_LIGHTBLUE|BG_BLACK)<<8; break; + case 'W': attr = (FG_LIGHTGREY|BG_BLACK)<<8; break; + case 'C': attr = (FG_CYAN|BG_BLACK)<<8; break; + default: attr = (FG_WHITE|BG_BLACK)<<8; break; + } + if (dxdir < 0) { /* Moving left */ + *CONSOLE_VECT(xpos + x, ypos + y) = + scr_map[daemon_pic[y][px]]|attr; + } else { /* Moving right */ + *CONSOLE_VECT(xpos + DAEMON_MAX_WIDTH - px - 1, ypos + y) = + scr_map[xflip_symbol(daemon_pic[y][px])]|attr; + } + } + } +} + +static void +clear_string(int xpos, int ypos, int xoff, char *s, int len) +{ + if (len <= 0) + return; + fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20], + CONSOLE_VECT(xpos + xoff, ypos), len - xoff); +} + +static void +draw_string(int xpos, int ypos, int xoff, char *s, int len) +{ + int x; + + for (x = xoff; x < len; x++) + *CONSOLE_VECT(xpos + x, ypos) = + scr_map[s[x]]|(FG_LIGHTGREEN|BG_BLACK)<<8; +} + +static void +daemon_saver(int blank) +{ + static int txpos = 10, typos = 10; + static int txdir = -1, tydir = -1; + static int dxpos = 0, dypos = 0; + static int dxdir = 1, dydir = 1; + static int moved_daemon = 0; + static int xoff, yoff, toff; + static int xlen, ylen, tlen; + scr_stat *scp = cur_console; + int min, max; + + if (blank) { + if (!ISTEXTSC(scp)) + return; + if (scrn_blanked == 0) { + scp->status |= SAVER_RUNNING; + window = (u_short *)(*biosvidsw.adapter)(scp->adp)->va_window; + /* clear the screen and set the border color */ + fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20], + window, scp->xsize * scp->ysize); + set_border(scp, 0); + xlen = ylen = tlen = 0; + } + if (scrn_blanked++ < 2) + return; + scrn_blanked = 1; + + clear_daemon(dxpos, dypos, dxdir, xoff, yoff, xlen, ylen); + clear_string(txpos, typos, toff, (char *)message, tlen); + + if (++moved_daemon) { + /* + * The daemon picture may be off the screen, if + * screen size is chagened while the screen + * saver is inactive. Make sure the origin of + * the picture is between min and max. + */ + if (scp->xsize <= DAEMON_MAX_WIDTH) { + /* + * If the screen width is too narrow, we + * allow part of the picture go off + * the screen so that the daemon won't + * flip too often. + */ + min = scp->xsize - DAEMON_MAX_WIDTH - 10; + max = 10; + } else { + min = 0; + max = scp->xsize - DAEMON_MAX_WIDTH; + } + if (dxpos <= min) { + dxpos = min; + dxdir = 1; + } else if (dxpos >= max) { + dxpos = max; + dxdir = -1; + } + + if (scp->ysize <= DAEMON_MAX_HEIGHT) { + min = scp->ysize - DAEMON_MAX_HEIGHT - 10; + max = 10; + } else { + min = 0; + max = scp->ysize - DAEMON_MAX_HEIGHT; + } + if (dypos <= min) { + dypos = min; + dydir = 1; + } else if (dypos >= max) { + dypos = max; + dydir = -1; + } + + moved_daemon = -1; + dxpos += dxdir; dypos += dydir; + + /* clip the picture */ + xoff = 0; + xlen = DAEMON_MAX_WIDTH; + if (dxpos + xlen <= 0) + xlen = 0; + else if (dxpos < 0) + xoff = -dxpos; + if (dxpos >= scp->xsize) + xlen = 0; + else if (dxpos + xlen > scp->xsize) + xlen = scp->xsize - dxpos; + yoff = 0; + ylen = DAEMON_MAX_HEIGHT; + if (dypos + ylen <= 0) + ylen = 0; + else if (dypos < 0) + yoff = -dypos; + if (dypos >= scp->ysize) + ylen = 0; + else if (dypos + ylen > scp->ysize) + ylen = scp->ysize - dypos; + } + + if (scp->xsize <= messagelen) { + min = scp->xsize - messagelen - 10; + max = 10; + } else { + min = 0; + max = scp->xsize - messagelen; + } + if (txpos <= min) { + txpos = min; + txdir = 1; + } else if (txpos >= max) { + txpos = max; + txdir = -1; + } + if (typos <= 0) { + typos = 0; + tydir = 1; + } else if (typos >= scp->ysize - 1) { + typos = scp->ysize - 1; + tydir = -1; + } + txpos += txdir; typos += tydir; + + toff = 0; + tlen = messagelen; + if (txpos + tlen <= 0) + tlen = 0; + else if (txpos < 0) + toff = -txpos; + if (txpos >= scp->xsize) + tlen = 0; + else if (txpos + tlen > scp->xsize) + tlen = scp->xsize - txpos; + + draw_daemon(dxpos, dypos, dxdir, xoff, yoff, xlen, ylen); + draw_string(txpos, typos, toff, (char *)message, tlen); + } else { + if (scrn_blanked > 0) { + set_border(scp, scp->border); + scrn_blanked = 0; + scp->status &= ~SAVER_RUNNING; + } + } +} + +static int +daemon_saver_load(struct lkm_table *lkmtp, int cmd) +{ + int err; + + messagelen = strlen(hostname) + 3 + strlen(ostype) + 1 + + strlen(osrelease); + message = malloc(messagelen + 1, M_DEVBUF, M_WAITOK); + sprintf(message, "%s - %s %s", hostname, ostype, osrelease); + + err = add_scrn_saver(daemon_saver); + if (err != 0) + free(message, M_DEVBUF); + return err; +} + +static int +daemon_saver_unload(struct lkm_table *lkmtp, int cmd) +{ + int err; + + err = remove_scrn_saver(daemon_saver); + if (err == 0) + free(message, M_DEVBUF); + return err; +} + +int +daemon_saver_mod(struct lkm_table *lkmtp, int cmd, int ver) +{ + MOD_DISPATCH(daemon_saver, lkmtp, cmd, ver, + daemon_saver_load, daemon_saver_unload, lkm_nullcmd); +} |
