17a19b7edSDag-Erling Smørgrav /*- 27a19b7edSDag-Erling Smørgrav * Copyright (c) 1999 Michael Smith <msmith@freebsd.org> 37a19b7edSDag-Erling Smørgrav * Copyright (c) 1999 Kazutaka YOKOTA <yokota@freebsd.org> 47a19b7edSDag-Erling Smørgrav * Copyright (c) 1999 Dag-Erling Co�dan Sm�rgrav 57a19b7edSDag-Erling Smørgrav * All rights reserved. 67a19b7edSDag-Erling Smørgrav * 77a19b7edSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 87a19b7edSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 97a19b7edSDag-Erling Smørgrav * are met: 107a19b7edSDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 117a19b7edSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer 127a19b7edSDag-Erling Smørgrav * in this position and unchanged. 137a19b7edSDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 147a19b7edSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 157a19b7edSDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 167a19b7edSDag-Erling Smørgrav * 3. The name of the author may not be used to endorse or promote products 177a19b7edSDag-Erling Smørgrav * derived from this software without specific prior written permission 187a19b7edSDag-Erling Smørgrav * 197a19b7edSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 207a19b7edSDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 217a19b7edSDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 227a19b7edSDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 237a19b7edSDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 247a19b7edSDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 257a19b7edSDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 267a19b7edSDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 277a19b7edSDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 287a19b7edSDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 297a19b7edSDag-Erling Smørgrav * 307a19b7edSDag-Erling Smørgrav * $Id$ 317a19b7edSDag-Erling Smørgrav */ 327a19b7edSDag-Erling Smørgrav 337a19b7edSDag-Erling Smørgrav #include <sys/param.h> 347a19b7edSDag-Erling Smørgrav #include <sys/systm.h> 357a19b7edSDag-Erling Smørgrav #include <sys/kernel.h> 367a19b7edSDag-Erling Smørgrav #include <sys/linker.h> 377a19b7edSDag-Erling Smørgrav 387a19b7edSDag-Erling Smørgrav #include <machine/console.h> 397a19b7edSDag-Erling Smørgrav 407a19b7edSDag-Erling Smørgrav #include <dev/fb/fbreg.h> 417a19b7edSDag-Erling Smørgrav #include <dev/fb/splashreg.h> 427a19b7edSDag-Erling Smørgrav 437a19b7edSDag-Erling Smørgrav #define FADE_TIMEOUT 300 /* sec */ 447a19b7edSDag-Erling Smørgrav 457a19b7edSDag-Erling Smørgrav static int splash_mode = -1; 467a19b7edSDag-Erling Smørgrav static int splash_on = FALSE; 477a19b7edSDag-Erling Smørgrav 487a19b7edSDag-Erling Smørgrav static int pcx_start(video_adapter_t *adp); 497a19b7edSDag-Erling Smørgrav static int pcx_end(video_adapter_t *adp); 507a19b7edSDag-Erling Smørgrav static int pcx_splash(video_adapter_t *adp, int on); 517a19b7edSDag-Erling Smørgrav static int pcx_init(const char *data, int sdepth); 527a19b7edSDag-Erling Smørgrav static int pcx_draw(video_adapter_t *adp); 537a19b7edSDag-Erling Smørgrav 547a19b7edSDag-Erling Smørgrav static splash_decoder_t pcx_decoder = { 557a19b7edSDag-Erling Smørgrav "splash_pcx", pcx_start, pcx_end, pcx_splash, SPLASH_IMAGE, 567a19b7edSDag-Erling Smørgrav }; 577a19b7edSDag-Erling Smørgrav 587a19b7edSDag-Erling Smørgrav SPLASH_DECODER(splash_pcx, pcx_decoder); 597a19b7edSDag-Erling Smørgrav 607a19b7edSDag-Erling Smørgrav static struct 617a19b7edSDag-Erling Smørgrav { 627a19b7edSDag-Erling Smørgrav int width, height, bpsl; 637a19b7edSDag-Erling Smørgrav int bpp, planes, zlen; 647a19b7edSDag-Erling Smørgrav const u_char *zdata, *palette; 657a19b7edSDag-Erling Smørgrav } pcx_info; 667a19b7edSDag-Erling Smørgrav 677a19b7edSDag-Erling Smørgrav static int 687a19b7edSDag-Erling Smørgrav pcx_start(video_adapter_t *adp) 697a19b7edSDag-Erling Smørgrav { 707a19b7edSDag-Erling Smørgrav static int modes[] = { 717a19b7edSDag-Erling Smørgrav M_VGA_CG320, 727a19b7edSDag-Erling Smørgrav M_VESA_CG640x480, 737a19b7edSDag-Erling Smørgrav M_VESA_CG800x600, 747a19b7edSDag-Erling Smørgrav M_VESA_CG1024x768, 757a19b7edSDag-Erling Smørgrav -1, 767a19b7edSDag-Erling Smørgrav }; 777a19b7edSDag-Erling Smørgrav video_info_t info; 787a19b7edSDag-Erling Smørgrav int i; 797a19b7edSDag-Erling Smørgrav 807a19b7edSDag-Erling Smørgrav if (pcx_decoder.data == NULL 817a19b7edSDag-Erling Smørgrav || pcx_decoder.data_size <= 0 827a19b7edSDag-Erling Smørgrav || pcx_init((u_char *)pcx_decoder.data, pcx_decoder.data_size)) 837a19b7edSDag-Erling Smørgrav return ENODEV; 847a19b7edSDag-Erling Smørgrav 857a19b7edSDag-Erling Smørgrav if (bootverbose) 867a19b7edSDag-Erling Smørgrav printf("splash_pcx: image good:\n" 877a19b7edSDag-Erling Smørgrav " width = %d\n" 887a19b7edSDag-Erling Smørgrav " height = %d\n" 897a19b7edSDag-Erling Smørgrav " depth = %d\n" 907a19b7edSDag-Erling Smørgrav " planes = %d\n", 917a19b7edSDag-Erling Smørgrav pcx_info.width, pcx_info.height, 927a19b7edSDag-Erling Smørgrav pcx_info.bpp, pcx_info.planes); 937a19b7edSDag-Erling Smørgrav 947a19b7edSDag-Erling Smørgrav for (i = 0; modes[i] >= 0; ++i) { 957a19b7edSDag-Erling Smørgrav if (get_mode_info(adp, modes[i], &info) != 0) 967a19b7edSDag-Erling Smørgrav continue; 977a19b7edSDag-Erling Smørgrav if (bootverbose) 987a19b7edSDag-Erling Smørgrav printf("splash_pcx: considering mode %d:\n" 997a19b7edSDag-Erling Smørgrav " vi_width = %d\n" 1007a19b7edSDag-Erling Smørgrav " vi_height = %d\n" 1017a19b7edSDag-Erling Smørgrav " vi_depth = %d\n" 1027a19b7edSDag-Erling Smørgrav " vi_planes = %d\n", 1037a19b7edSDag-Erling Smørgrav modes[i], 1047a19b7edSDag-Erling Smørgrav info.vi_width, info.vi_height, 1057a19b7edSDag-Erling Smørgrav info.vi_depth, info.vi_planes); 1067a19b7edSDag-Erling Smørgrav if (info.vi_width >= pcx_info.width 1077a19b7edSDag-Erling Smørgrav && info.vi_height >= pcx_info.height 1087a19b7edSDag-Erling Smørgrav && info.vi_depth == pcx_info.bpp 1097a19b7edSDag-Erling Smørgrav && info.vi_planes == pcx_info.planes) 1107a19b7edSDag-Erling Smørgrav break; 1117a19b7edSDag-Erling Smørgrav } 1127a19b7edSDag-Erling Smørgrav 1137a19b7edSDag-Erling Smørgrav splash_mode = modes[i]; 1147a19b7edSDag-Erling Smørgrav if (splash_mode == -1) 1157a19b7edSDag-Erling Smørgrav return ENODEV; 1167a19b7edSDag-Erling Smørgrav if (bootverbose) 1177a19b7edSDag-Erling Smørgrav printf("pcx_splash: selecting mode %d\n", splash_mode); 1187a19b7edSDag-Erling Smørgrav return 0; 1197a19b7edSDag-Erling Smørgrav } 1207a19b7edSDag-Erling Smørgrav 1217a19b7edSDag-Erling Smørgrav static int 1227a19b7edSDag-Erling Smørgrav pcx_end(video_adapter_t *adp) 1237a19b7edSDag-Erling Smørgrav { 1247a19b7edSDag-Erling Smørgrav /* nothing to do */ 1257a19b7edSDag-Erling Smørgrav return 0; 1267a19b7edSDag-Erling Smørgrav } 1277a19b7edSDag-Erling Smørgrav 1287a19b7edSDag-Erling Smørgrav static int 1297a19b7edSDag-Erling Smørgrav pcx_splash(video_adapter_t *adp, int on) 1307a19b7edSDag-Erling Smørgrav { 1317a19b7edSDag-Erling Smørgrav if (on) { 1327a19b7edSDag-Erling Smørgrav if (!splash_on) { 1337a19b7edSDag-Erling Smørgrav if (set_video_mode(adp, splash_mode) || pcx_draw(adp)) 1347a19b7edSDag-Erling Smørgrav return 1; 1357a19b7edSDag-Erling Smørgrav splash_on = TRUE; 1367a19b7edSDag-Erling Smørgrav } 1377a19b7edSDag-Erling Smørgrav return 0; 1387a19b7edSDag-Erling Smørgrav } else { 1397a19b7edSDag-Erling Smørgrav splash_on = FALSE; 1407a19b7edSDag-Erling Smørgrav return 0; 1417a19b7edSDag-Erling Smørgrav } 1427a19b7edSDag-Erling Smørgrav } 1437a19b7edSDag-Erling Smørgrav 1447a19b7edSDag-Erling Smørgrav struct pcxheader { 1457a19b7edSDag-Erling Smørgrav u_char manufactor; 1467a19b7edSDag-Erling Smørgrav u_char version; 1477a19b7edSDag-Erling Smørgrav u_char encoding; 1487a19b7edSDag-Erling Smørgrav u_char bpp; 1497a19b7edSDag-Erling Smørgrav u_short xmin, ymin, xmax, ymax; 1507a19b7edSDag-Erling Smørgrav u_short hres, vres; 1517a19b7edSDag-Erling Smørgrav u_char colormap[48]; 1527a19b7edSDag-Erling Smørgrav u_char rsvd; 1537a19b7edSDag-Erling Smørgrav u_char nplanes; 1547a19b7edSDag-Erling Smørgrav u_short bpsl; 1557a19b7edSDag-Erling Smørgrav u_short palinfo; 1567a19b7edSDag-Erling Smørgrav u_short hsize, vsize; 1577a19b7edSDag-Erling Smørgrav }; 1587a19b7edSDag-Erling Smørgrav 1597a19b7edSDag-Erling Smørgrav #define MAXSCANLINE 1024 1607a19b7edSDag-Erling Smørgrav 1617a19b7edSDag-Erling Smørgrav static int 1627a19b7edSDag-Erling Smørgrav pcx_init(const char *data, int size) 1637a19b7edSDag-Erling Smørgrav { 1647a19b7edSDag-Erling Smørgrav const struct pcxheader *hdr; 1657a19b7edSDag-Erling Smørgrav 1667a19b7edSDag-Erling Smørgrav hdr = (const struct pcxheader *)data; 1677a19b7edSDag-Erling Smørgrav 1687a19b7edSDag-Erling Smørgrav if (size < 128 + 1 + 1 + 768 1697a19b7edSDag-Erling Smørgrav || hdr->manufactor != 10 1707a19b7edSDag-Erling Smørgrav || hdr->version != 5 1717a19b7edSDag-Erling Smørgrav || hdr->encoding != 1 1727a19b7edSDag-Erling Smørgrav || hdr->nplanes != 1 1737a19b7edSDag-Erling Smørgrav || hdr->bpp != 8 1747a19b7edSDag-Erling Smørgrav || hdr->bpsl > MAXSCANLINE 1757a19b7edSDag-Erling Smørgrav || data[size-769] != 12) { 1767a19b7edSDag-Erling Smørgrav printf("splash_pcx: invalid PCX image\n"); 1777a19b7edSDag-Erling Smørgrav return 1; 1787a19b7edSDag-Erling Smørgrav } 1797a19b7edSDag-Erling Smørgrav pcx_info.width = hdr->xmax - hdr->xmin + 1; 1807a19b7edSDag-Erling Smørgrav pcx_info.height = hdr->ymax - hdr->ymin + 1; 1817a19b7edSDag-Erling Smørgrav pcx_info.bpsl = hdr->bpsl; 1827a19b7edSDag-Erling Smørgrav pcx_info.bpp = hdr->bpp; 1837a19b7edSDag-Erling Smørgrav pcx_info.planes = hdr->nplanes; 1847a19b7edSDag-Erling Smørgrav pcx_info.zlen = size - (128 + 1 + 768); 1857a19b7edSDag-Erling Smørgrav pcx_info.zdata = data + 128; 1867a19b7edSDag-Erling Smørgrav pcx_info.palette = data + size - 768; 1877a19b7edSDag-Erling Smørgrav return 0; 1887a19b7edSDag-Erling Smørgrav } 1897a19b7edSDag-Erling Smørgrav 1907a19b7edSDag-Erling Smørgrav static int 1917a19b7edSDag-Erling Smørgrav pcx_draw(video_adapter_t *adp) 1927a19b7edSDag-Erling Smørgrav { 1937a19b7edSDag-Erling Smørgrav u_char *vidmem; 1947a19b7edSDag-Erling Smørgrav int swidth, sheight, sbpsl, sdepth, splanes; 1957a19b7edSDag-Erling Smørgrav int banksize, origin; 1967a19b7edSDag-Erling Smørgrav int c, i, j, pos, scan, x, y; 1977a19b7edSDag-Erling Smørgrav u_char line[MAXSCANLINE]; 1987a19b7edSDag-Erling Smørgrav 1997a19b7edSDag-Erling Smørgrav if (pcx_info.zlen < 1) 2007a19b7edSDag-Erling Smørgrav return 1; 2017a19b7edSDag-Erling Smørgrav 2027a19b7edSDag-Erling Smørgrav load_palette(adp, pcx_info.palette); 2037a19b7edSDag-Erling Smørgrav 2047a19b7edSDag-Erling Smørgrav vidmem = (u_char *)adp->va_window; 2057a19b7edSDag-Erling Smørgrav swidth = adp->va_info.vi_width; 2067a19b7edSDag-Erling Smørgrav sheight = adp->va_info.vi_height; 2077a19b7edSDag-Erling Smørgrav sbpsl = adp->va_line_width; 2087a19b7edSDag-Erling Smørgrav sdepth = adp->va_info.vi_depth; 2097a19b7edSDag-Erling Smørgrav splanes = adp->va_info.vi_planes; 2107a19b7edSDag-Erling Smørgrav banksize = adp->va_info.vi_window_size; 2117a19b7edSDag-Erling Smørgrav 2127a19b7edSDag-Erling Smørgrav for (origin = 0; origin < sheight*sbpsl; origin += banksize) { 2137a19b7edSDag-Erling Smørgrav set_origin(adp, origin); 2147a19b7edSDag-Erling Smørgrav bzero(vidmem, banksize); 2157a19b7edSDag-Erling Smørgrav } 2167a19b7edSDag-Erling Smørgrav 2177a19b7edSDag-Erling Smørgrav x = (swidth - pcx_info.width) / 2; 2187a19b7edSDag-Erling Smørgrav y = (sheight - pcx_info.height) / 2; 2197a19b7edSDag-Erling Smørgrav origin = 0; 2207a19b7edSDag-Erling Smørgrav pos = y * sbpsl + x; 2217a19b7edSDag-Erling Smørgrav while (pos > banksize) { 2227a19b7edSDag-Erling Smørgrav pos -= banksize; 2237a19b7edSDag-Erling Smørgrav origin += banksize; 2247a19b7edSDag-Erling Smørgrav } 2257a19b7edSDag-Erling Smørgrav set_origin(adp, origin); 2267a19b7edSDag-Erling Smørgrav 2277a19b7edSDag-Erling Smørgrav for (scan = i = 0; scan < pcx_info.height; ++scan, ++y, pos += sbpsl) { 2287a19b7edSDag-Erling Smørgrav for (j = 0; j < pcx_info.bpsl && i < pcx_info.zlen; ++i) { 2297a19b7edSDag-Erling Smørgrav if ((pcx_info.zdata[i] & 0xc0) == 0xc0) { 2307a19b7edSDag-Erling Smørgrav c = pcx_info.zdata[i++] & 0x3f; 2317a19b7edSDag-Erling Smørgrav if (i >= pcx_info.zlen) 2327a19b7edSDag-Erling Smørgrav return 1; 2337a19b7edSDag-Erling Smørgrav } else { 2347a19b7edSDag-Erling Smørgrav c = 1; 2357a19b7edSDag-Erling Smørgrav } 2367a19b7edSDag-Erling Smørgrav if (j + c > pcx_info.bpsl) 2377a19b7edSDag-Erling Smørgrav return 1; 2387a19b7edSDag-Erling Smørgrav while (c--) 2397a19b7edSDag-Erling Smørgrav line[j++] = pcx_info.zdata[i]; 2407a19b7edSDag-Erling Smørgrav } 2417a19b7edSDag-Erling Smørgrav 2427a19b7edSDag-Erling Smørgrav if (pos > banksize) { 2437a19b7edSDag-Erling Smørgrav origin += banksize; 2447a19b7edSDag-Erling Smørgrav pos -= banksize; 2457a19b7edSDag-Erling Smørgrav set_origin(adp, origin); 2467a19b7edSDag-Erling Smørgrav } 2477a19b7edSDag-Erling Smørgrav 2487a19b7edSDag-Erling Smørgrav if (pos + pcx_info.width > banksize) { 2497a19b7edSDag-Erling Smørgrav /* scanline crosses bank boundary */ 2507a19b7edSDag-Erling Smørgrav j = banksize - pos; 2517a19b7edSDag-Erling Smørgrav bcopy(line, vidmem + pos, j); 2527a19b7edSDag-Erling Smørgrav origin += banksize; 2537a19b7edSDag-Erling Smørgrav pos -= banksize; 2547a19b7edSDag-Erling Smørgrav set_origin(adp, origin); 2557a19b7edSDag-Erling Smørgrav bcopy(line + j, vidmem, pcx_info.width - j); 2567a19b7edSDag-Erling Smørgrav } else { 2577a19b7edSDag-Erling Smørgrav bcopy(line, vidmem + pos, pcx_info.width); 2587a19b7edSDag-Erling Smørgrav } 2597a19b7edSDag-Erling Smørgrav } 2607a19b7edSDag-Erling Smørgrav 2617a19b7edSDag-Erling Smørgrav return 0; 2627a19b7edSDag-Erling Smørgrav } 263