1617b9080SKazutaka YOKOTA /*- 2*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*718cf2ccSPedro F. Giffuni * 4559e7c1bSKazutaka YOKOTA * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 5559e7c1bSKazutaka YOKOTA * All rights reserved. 6559e7c1bSKazutaka YOKOTA * 7559e7c1bSKazutaka YOKOTA * Redistribution and use in source and binary forms, with or without 8559e7c1bSKazutaka YOKOTA * modification, are permitted provided that the following conditions 9559e7c1bSKazutaka YOKOTA * are met: 10559e7c1bSKazutaka YOKOTA * 1. Redistributions of source code must retain the above copyright 11559e7c1bSKazutaka YOKOTA * notice, this list of conditions and the following disclaimer as 12559e7c1bSKazutaka YOKOTA * the first lines of this file unmodified. 13559e7c1bSKazutaka YOKOTA * 2. Redistributions in binary form must reproduce the above copyright 14559e7c1bSKazutaka YOKOTA * notice, this list of conditions and the following disclaimer in the 15559e7c1bSKazutaka YOKOTA * documentation and/or other materials provided with the distribution. 16559e7c1bSKazutaka YOKOTA * 17559e7c1bSKazutaka YOKOTA * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18559e7c1bSKazutaka YOKOTA * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19559e7c1bSKazutaka YOKOTA * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20559e7c1bSKazutaka YOKOTA * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21559e7c1bSKazutaka YOKOTA * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22559e7c1bSKazutaka YOKOTA * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23559e7c1bSKazutaka YOKOTA * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24559e7c1bSKazutaka YOKOTA * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25559e7c1bSKazutaka YOKOTA * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26559e7c1bSKazutaka YOKOTA * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27559e7c1bSKazutaka YOKOTA * 28617b9080SKazutaka YOKOTA */ 29617b9080SKazutaka YOKOTA 30aad970f1SDavid E. O'Brien #include <sys/cdefs.h> 31aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 32aad970f1SDavid E. O'Brien 330426db70SKazutaka YOKOTA #include "opt_splash.h" 340426db70SKazutaka YOKOTA 35617b9080SKazutaka YOKOTA #include <sys/param.h> 36617b9080SKazutaka YOKOTA #include <sys/systm.h> 37617b9080SKazutaka YOKOTA #include <sys/malloc.h> 38617b9080SKazutaka YOKOTA #include <sys/linker.h> 396e8394b8SKazutaka YOKOTA #include <sys/fbio.h> 40932a24dfSPoul-Henning Kamp #include <sys/kernel.h> 41fe12f24bSPoul-Henning Kamp #include <sys/module.h> 42617b9080SKazutaka YOKOTA 43617b9080SKazutaka YOKOTA #include <dev/fb/fbreg.h> 44617b9080SKazutaka YOKOTA #include <dev/fb/splashreg.h> 45617b9080SKazutaka YOKOTA 4636d4f7c1SPeter Wemm MODULE_VERSION(splash, 1); 4736d4f7c1SPeter Wemm 48617b9080SKazutaka YOKOTA /* video adapter and image decoder */ 49617b9080SKazutaka YOKOTA static video_adapter_t *splash_adp; 50617b9080SKazutaka YOKOTA static splash_decoder_t *splash_decoder; 51617b9080SKazutaka YOKOTA 52617b9080SKazutaka YOKOTA /* decoder candidates */ 53617b9080SKazutaka YOKOTA static int decoders; 54617b9080SKazutaka YOKOTA static splash_decoder_t **decoder_set; 55617b9080SKazutaka YOKOTA #define DECODER_ARRAY_DELTA 4 56617b9080SKazutaka YOKOTA 57617b9080SKazutaka YOKOTA /* console driver callback */ 586e8394b8SKazutaka YOKOTA static int (*splash_callback)(int, void *); 596e8394b8SKazutaka YOKOTA static void *splash_arg; 60617b9080SKazutaka YOKOTA 61617b9080SKazutaka YOKOTA static int 62559e7c1bSKazutaka YOKOTA splash_find_data(splash_decoder_t *decoder) 63617b9080SKazutaka YOKOTA { 64617b9080SKazutaka YOKOTA caddr_t image_module; 6501f7b6daSMarcel Moolenaar void *ptr; 6601f7b6daSMarcel Moolenaar size_t sz; 67617b9080SKazutaka YOKOTA 68559e7c1bSKazutaka YOKOTA if (decoder->data_type == NULL) 6901f7b6daSMarcel Moolenaar return (0); 7001f7b6daSMarcel Moolenaar 71559e7c1bSKazutaka YOKOTA image_module = preload_search_by_type(decoder->data_type); 72617b9080SKazutaka YOKOTA if (image_module == NULL) 7301f7b6daSMarcel Moolenaar return (ENOENT); 7401f7b6daSMarcel Moolenaar 7501f7b6daSMarcel Moolenaar ptr = preload_fetch_addr(image_module); 7601f7b6daSMarcel Moolenaar sz = preload_fetch_size(image_module); 7701f7b6daSMarcel Moolenaar if (ptr == NULL || sz == 0) 7801f7b6daSMarcel Moolenaar return (ENOENT); 7901f7b6daSMarcel Moolenaar 80559e7c1bSKazutaka YOKOTA if (bootverbose) 8101f7b6daSMarcel Moolenaar printf("splash: image@%p, size:%zu\n", ptr, sz); 8201f7b6daSMarcel Moolenaar 8301f7b6daSMarcel Moolenaar decoder->data = ptr; 8401f7b6daSMarcel Moolenaar decoder->data_size = sz; 8501f7b6daSMarcel Moolenaar return (0); 86617b9080SKazutaka YOKOTA } 87617b9080SKazutaka YOKOTA 88617b9080SKazutaka YOKOTA static int 89617b9080SKazutaka YOKOTA splash_test(splash_decoder_t *decoder) 90617b9080SKazutaka YOKOTA { 91559e7c1bSKazutaka YOKOTA if (splash_find_data(decoder)) 92559e7c1bSKazutaka YOKOTA return ENOENT; /* XXX */ 93d8add747SNick Hibma if (*decoder->init && (*decoder->init)(splash_adp)) { 94559e7c1bSKazutaka YOKOTA decoder->data = NULL; 95559e7c1bSKazutaka YOKOTA decoder->data_size = 0; 96617b9080SKazutaka YOKOTA return ENODEV; /* XXX */ 97559e7c1bSKazutaka YOKOTA } 98617b9080SKazutaka YOKOTA if (bootverbose) 99617b9080SKazutaka YOKOTA printf("splash: image decoder found: %s\n", decoder->name); 100559e7c1bSKazutaka YOKOTA return 0; 101559e7c1bSKazutaka YOKOTA } 102559e7c1bSKazutaka YOKOTA 103559e7c1bSKazutaka YOKOTA static void 104559e7c1bSKazutaka YOKOTA splash_new(splash_decoder_t *decoder) 105559e7c1bSKazutaka YOKOTA { 106617b9080SKazutaka YOKOTA splash_decoder = decoder; 107617b9080SKazutaka YOKOTA if (splash_callback != NULL) 1086e8394b8SKazutaka YOKOTA (*splash_callback)(SPLASH_INIT, splash_arg); 109617b9080SKazutaka YOKOTA } 110617b9080SKazutaka YOKOTA 111617b9080SKazutaka YOKOTA int 112617b9080SKazutaka YOKOTA splash_register(splash_decoder_t *decoder) 113617b9080SKazutaka YOKOTA { 114617b9080SKazutaka YOKOTA splash_decoder_t **p; 115559e7c1bSKazutaka YOKOTA int error; 116617b9080SKazutaka YOKOTA int i; 117617b9080SKazutaka YOKOTA 118559e7c1bSKazutaka YOKOTA if (splash_adp != NULL) { 119617b9080SKazutaka YOKOTA /* 120453130d9SPedro F. Giffuni * If the video card has already been initialized, test 121559e7c1bSKazutaka YOKOTA * this decoder immediately. 122617b9080SKazutaka YOKOTA */ 123559e7c1bSKazutaka YOKOTA error = splash_test(decoder); 124559e7c1bSKazutaka YOKOTA if (error == 0) { 125559e7c1bSKazutaka YOKOTA /* replace the current decoder with new one */ 126559e7c1bSKazutaka YOKOTA if (splash_decoder != NULL) 127559e7c1bSKazutaka YOKOTA error = splash_term(splash_adp); 128559e7c1bSKazutaka YOKOTA if (error == 0) 129559e7c1bSKazutaka YOKOTA splash_new(decoder); 130559e7c1bSKazutaka YOKOTA } 131559e7c1bSKazutaka YOKOTA return error; 132559e7c1bSKazutaka YOKOTA } else { 133617b9080SKazutaka YOKOTA /* register the decoder for later use */ 134617b9080SKazutaka YOKOTA for (i = 0; i < decoders; ++i) { 135617b9080SKazutaka YOKOTA if (decoder_set[i] == NULL) 136617b9080SKazutaka YOKOTA break; 137617b9080SKazutaka YOKOTA } 138617b9080SKazutaka YOKOTA if ((i >= decoders) && (decoders % DECODER_ARRAY_DELTA) == 0) { 139617b9080SKazutaka YOKOTA p = malloc(sizeof(*p)*(decoders + DECODER_ARRAY_DELTA), 140617b9080SKazutaka YOKOTA M_DEVBUF, M_NOWAIT); 141617b9080SKazutaka YOKOTA if (p == NULL) 142617b9080SKazutaka YOKOTA return ENOMEM; 14311b5621eSKazutaka YOKOTA if (decoder_set != NULL) { 144617b9080SKazutaka YOKOTA bcopy(decoder_set, p, sizeof(*p)*decoders); 145617b9080SKazutaka YOKOTA free(decoder_set, M_DEVBUF); 14611b5621eSKazutaka YOKOTA } 147617b9080SKazutaka YOKOTA decoder_set = p; 148617b9080SKazutaka YOKOTA i = decoders++; 149617b9080SKazutaka YOKOTA } 150617b9080SKazutaka YOKOTA decoder_set[i] = decoder; 151559e7c1bSKazutaka YOKOTA } 152559e7c1bSKazutaka YOKOTA 153617b9080SKazutaka YOKOTA return 0; 154617b9080SKazutaka YOKOTA } 155617b9080SKazutaka YOKOTA 156617b9080SKazutaka YOKOTA int 157617b9080SKazutaka YOKOTA splash_unregister(splash_decoder_t *decoder) 158617b9080SKazutaka YOKOTA { 159617b9080SKazutaka YOKOTA int error; 160617b9080SKazutaka YOKOTA 161617b9080SKazutaka YOKOTA if (splash_decoder == decoder) { 162617b9080SKazutaka YOKOTA if ((error = splash_term(splash_adp)) != 0) 163617b9080SKazutaka YOKOTA return error; 164617b9080SKazutaka YOKOTA } 165617b9080SKazutaka YOKOTA return 0; 166617b9080SKazutaka YOKOTA } 167617b9080SKazutaka YOKOTA 168617b9080SKazutaka YOKOTA int 1696e8394b8SKazutaka YOKOTA splash_init(video_adapter_t *adp, int (*callback)(int, void *), void *arg) 170617b9080SKazutaka YOKOTA { 171617b9080SKazutaka YOKOTA int i; 172617b9080SKazutaka YOKOTA 173617b9080SKazutaka YOKOTA splash_adp = adp; 174617b9080SKazutaka YOKOTA splash_callback = callback; 1756e8394b8SKazutaka YOKOTA splash_arg = arg; 176617b9080SKazutaka YOKOTA 177617b9080SKazutaka YOKOTA splash_decoder = NULL; 178617b9080SKazutaka YOKOTA for (i = 0; i < decoders; ++i) { 179617b9080SKazutaka YOKOTA if (decoder_set[i] == NULL) 180617b9080SKazutaka YOKOTA continue; 181559e7c1bSKazutaka YOKOTA if (splash_test(decoder_set[i]) == 0) { 182559e7c1bSKazutaka YOKOTA splash_new(decoder_set[i]); 183617b9080SKazutaka YOKOTA break; 184617b9080SKazutaka YOKOTA } 185559e7c1bSKazutaka YOKOTA decoder_set[i] = NULL; 186559e7c1bSKazutaka YOKOTA } 187559e7c1bSKazutaka YOKOTA for (++i; i < decoders; ++i) { 188559e7c1bSKazutaka YOKOTA decoder_set[i] = NULL; 189559e7c1bSKazutaka YOKOTA } 190617b9080SKazutaka YOKOTA return 0; 191617b9080SKazutaka YOKOTA } 192617b9080SKazutaka YOKOTA 193617b9080SKazutaka YOKOTA int 194617b9080SKazutaka YOKOTA splash_term(video_adapter_t *adp) 195617b9080SKazutaka YOKOTA { 196617b9080SKazutaka YOKOTA int error = 0; 197617b9080SKazutaka YOKOTA 1986e8394b8SKazutaka YOKOTA if (splash_adp != adp) 1996e8394b8SKazutaka YOKOTA return EINVAL; 200617b9080SKazutaka YOKOTA if (splash_decoder != NULL) { 201617b9080SKazutaka YOKOTA if (splash_callback != NULL) 2026e8394b8SKazutaka YOKOTA error = (*splash_callback)(SPLASH_TERM, splash_arg); 203d8add747SNick Hibma if (error == 0 && splash_decoder->term) 204617b9080SKazutaka YOKOTA error = (*splash_decoder->term)(adp); 205617b9080SKazutaka YOKOTA if (error == 0) 206617b9080SKazutaka YOKOTA splash_decoder = NULL; 207617b9080SKazutaka YOKOTA } 208617b9080SKazutaka YOKOTA return error; 209617b9080SKazutaka YOKOTA } 210617b9080SKazutaka YOKOTA 211617b9080SKazutaka YOKOTA int 212617b9080SKazutaka YOKOTA splash(video_adapter_t *adp, int on) 213617b9080SKazutaka YOKOTA { 214617b9080SKazutaka YOKOTA if (splash_decoder != NULL) 215617b9080SKazutaka YOKOTA return (*splash_decoder->splash)(adp, on); 216617b9080SKazutaka YOKOTA return ENODEV; 217617b9080SKazutaka YOKOTA } 218