1617b9080SKazutaka YOKOTA /*- 2559e7c1bSKazutaka YOKOTA * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 3559e7c1bSKazutaka YOKOTA * All rights reserved. 4559e7c1bSKazutaka YOKOTA * 5559e7c1bSKazutaka YOKOTA * Redistribution and use in source and binary forms, with or without 6559e7c1bSKazutaka YOKOTA * modification, are permitted provided that the following conditions 7559e7c1bSKazutaka YOKOTA * are met: 8559e7c1bSKazutaka YOKOTA * 1. Redistributions of source code must retain the above copyright 9559e7c1bSKazutaka YOKOTA * notice, this list of conditions and the following disclaimer as 10559e7c1bSKazutaka YOKOTA * the first lines of this file unmodified. 11559e7c1bSKazutaka YOKOTA * 2. Redistributions in binary form must reproduce the above copyright 12559e7c1bSKazutaka YOKOTA * notice, this list of conditions and the following disclaimer in the 13559e7c1bSKazutaka YOKOTA * documentation and/or other materials provided with the distribution. 14559e7c1bSKazutaka YOKOTA * 15559e7c1bSKazutaka YOKOTA * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16559e7c1bSKazutaka YOKOTA * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17559e7c1bSKazutaka YOKOTA * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18559e7c1bSKazutaka YOKOTA * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19559e7c1bSKazutaka YOKOTA * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20559e7c1bSKazutaka YOKOTA * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21559e7c1bSKazutaka YOKOTA * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22559e7c1bSKazutaka YOKOTA * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23559e7c1bSKazutaka YOKOTA * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24559e7c1bSKazutaka YOKOTA * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25559e7c1bSKazutaka YOKOTA * 26617b9080SKazutaka YOKOTA */ 27617b9080SKazutaka YOKOTA 28aad970f1SDavid E. O'Brien #include <sys/cdefs.h> 29aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 30aad970f1SDavid E. O'Brien 310426db70SKazutaka YOKOTA #include "opt_splash.h" 320426db70SKazutaka YOKOTA 33617b9080SKazutaka YOKOTA #include <sys/param.h> 34617b9080SKazutaka YOKOTA #include <sys/systm.h> 35617b9080SKazutaka YOKOTA #include <sys/malloc.h> 36617b9080SKazutaka YOKOTA #include <sys/linker.h> 376e8394b8SKazutaka YOKOTA #include <sys/fbio.h> 38932a24dfSPoul-Henning Kamp #include <sys/kernel.h> 39fe12f24bSPoul-Henning Kamp #include <sys/module.h> 40617b9080SKazutaka YOKOTA 41617b9080SKazutaka YOKOTA #include <dev/fb/fbreg.h> 42617b9080SKazutaka YOKOTA #include <dev/fb/splashreg.h> 43617b9080SKazutaka YOKOTA 4436d4f7c1SPeter Wemm MODULE_VERSION(splash, 1); 4536d4f7c1SPeter Wemm 46617b9080SKazutaka YOKOTA /* video adapter and image decoder */ 47617b9080SKazutaka YOKOTA static video_adapter_t *splash_adp; 48617b9080SKazutaka YOKOTA static splash_decoder_t *splash_decoder; 49617b9080SKazutaka YOKOTA 50617b9080SKazutaka YOKOTA /* decoder candidates */ 51617b9080SKazutaka YOKOTA static int decoders; 52617b9080SKazutaka YOKOTA static splash_decoder_t **decoder_set; 53617b9080SKazutaka YOKOTA #define DECODER_ARRAY_DELTA 4 54617b9080SKazutaka YOKOTA 55617b9080SKazutaka YOKOTA /* console driver callback */ 566e8394b8SKazutaka YOKOTA static int (*splash_callback)(int, void *); 576e8394b8SKazutaka YOKOTA static void *splash_arg; 58617b9080SKazutaka YOKOTA 59617b9080SKazutaka YOKOTA static int 60559e7c1bSKazutaka YOKOTA splash_find_data(splash_decoder_t *decoder) 61617b9080SKazutaka YOKOTA { 62617b9080SKazutaka YOKOTA caddr_t image_module; 63*01f7b6daSMarcel Moolenaar void *ptr; 64*01f7b6daSMarcel Moolenaar size_t sz; 65617b9080SKazutaka YOKOTA 66559e7c1bSKazutaka YOKOTA if (decoder->data_type == NULL) 67*01f7b6daSMarcel Moolenaar return (0); 68*01f7b6daSMarcel Moolenaar 69559e7c1bSKazutaka YOKOTA image_module = preload_search_by_type(decoder->data_type); 70617b9080SKazutaka YOKOTA if (image_module == NULL) 71*01f7b6daSMarcel Moolenaar return (ENOENT); 72*01f7b6daSMarcel Moolenaar 73*01f7b6daSMarcel Moolenaar ptr = preload_fetch_addr(image_module); 74*01f7b6daSMarcel Moolenaar sz = preload_fetch_size(image_module); 75*01f7b6daSMarcel Moolenaar if (ptr == NULL || sz == 0) 76*01f7b6daSMarcel Moolenaar return (ENOENT); 77*01f7b6daSMarcel Moolenaar 78559e7c1bSKazutaka YOKOTA if (bootverbose) 79*01f7b6daSMarcel Moolenaar printf("splash: image@%p, size:%zu\n", ptr, sz); 80*01f7b6daSMarcel Moolenaar 81*01f7b6daSMarcel Moolenaar decoder->data = ptr; 82*01f7b6daSMarcel Moolenaar decoder->data_size = sz; 83*01f7b6daSMarcel Moolenaar return (0); 84617b9080SKazutaka YOKOTA } 85617b9080SKazutaka YOKOTA 86617b9080SKazutaka YOKOTA static int 87617b9080SKazutaka YOKOTA splash_test(splash_decoder_t *decoder) 88617b9080SKazutaka YOKOTA { 89559e7c1bSKazutaka YOKOTA if (splash_find_data(decoder)) 90559e7c1bSKazutaka YOKOTA return ENOENT; /* XXX */ 91d8add747SNick Hibma if (*decoder->init && (*decoder->init)(splash_adp)) { 92559e7c1bSKazutaka YOKOTA decoder->data = NULL; 93559e7c1bSKazutaka YOKOTA decoder->data_size = 0; 94617b9080SKazutaka YOKOTA return ENODEV; /* XXX */ 95559e7c1bSKazutaka YOKOTA } 96617b9080SKazutaka YOKOTA if (bootverbose) 97617b9080SKazutaka YOKOTA printf("splash: image decoder found: %s\n", decoder->name); 98559e7c1bSKazutaka YOKOTA return 0; 99559e7c1bSKazutaka YOKOTA } 100559e7c1bSKazutaka YOKOTA 101559e7c1bSKazutaka YOKOTA static void 102559e7c1bSKazutaka YOKOTA splash_new(splash_decoder_t *decoder) 103559e7c1bSKazutaka YOKOTA { 104617b9080SKazutaka YOKOTA splash_decoder = decoder; 105617b9080SKazutaka YOKOTA if (splash_callback != NULL) 1066e8394b8SKazutaka YOKOTA (*splash_callback)(SPLASH_INIT, splash_arg); 107617b9080SKazutaka YOKOTA } 108617b9080SKazutaka YOKOTA 109617b9080SKazutaka YOKOTA int 110617b9080SKazutaka YOKOTA splash_register(splash_decoder_t *decoder) 111617b9080SKazutaka YOKOTA { 112617b9080SKazutaka YOKOTA splash_decoder_t **p; 113559e7c1bSKazutaka YOKOTA int error; 114617b9080SKazutaka YOKOTA int i; 115617b9080SKazutaka YOKOTA 116559e7c1bSKazutaka YOKOTA if (splash_adp != NULL) { 117617b9080SKazutaka YOKOTA /* 118559e7c1bSKazutaka YOKOTA * If the video card has aleady been initialized, test 119559e7c1bSKazutaka YOKOTA * this decoder immediately. 120617b9080SKazutaka YOKOTA */ 121559e7c1bSKazutaka YOKOTA error = splash_test(decoder); 122559e7c1bSKazutaka YOKOTA if (error == 0) { 123559e7c1bSKazutaka YOKOTA /* replace the current decoder with new one */ 124559e7c1bSKazutaka YOKOTA if (splash_decoder != NULL) 125559e7c1bSKazutaka YOKOTA error = splash_term(splash_adp); 126559e7c1bSKazutaka YOKOTA if (error == 0) 127559e7c1bSKazutaka YOKOTA splash_new(decoder); 128559e7c1bSKazutaka YOKOTA } 129559e7c1bSKazutaka YOKOTA return error; 130559e7c1bSKazutaka YOKOTA } else { 131617b9080SKazutaka YOKOTA /* register the decoder for later use */ 132617b9080SKazutaka YOKOTA for (i = 0; i < decoders; ++i) { 133617b9080SKazutaka YOKOTA if (decoder_set[i] == NULL) 134617b9080SKazutaka YOKOTA break; 135617b9080SKazutaka YOKOTA } 136617b9080SKazutaka YOKOTA if ((i >= decoders) && (decoders % DECODER_ARRAY_DELTA) == 0) { 137617b9080SKazutaka YOKOTA p = malloc(sizeof(*p)*(decoders + DECODER_ARRAY_DELTA), 138617b9080SKazutaka YOKOTA M_DEVBUF, M_NOWAIT); 139617b9080SKazutaka YOKOTA if (p == NULL) 140617b9080SKazutaka YOKOTA return ENOMEM; 14111b5621eSKazutaka YOKOTA if (decoder_set != NULL) { 142617b9080SKazutaka YOKOTA bcopy(decoder_set, p, sizeof(*p)*decoders); 143617b9080SKazutaka YOKOTA free(decoder_set, M_DEVBUF); 14411b5621eSKazutaka YOKOTA } 145617b9080SKazutaka YOKOTA decoder_set = p; 146617b9080SKazutaka YOKOTA i = decoders++; 147617b9080SKazutaka YOKOTA } 148617b9080SKazutaka YOKOTA decoder_set[i] = decoder; 149559e7c1bSKazutaka YOKOTA } 150559e7c1bSKazutaka YOKOTA 151617b9080SKazutaka YOKOTA return 0; 152617b9080SKazutaka YOKOTA } 153617b9080SKazutaka YOKOTA 154617b9080SKazutaka YOKOTA int 155617b9080SKazutaka YOKOTA splash_unregister(splash_decoder_t *decoder) 156617b9080SKazutaka YOKOTA { 157617b9080SKazutaka YOKOTA int error; 158617b9080SKazutaka YOKOTA 159617b9080SKazutaka YOKOTA if (splash_decoder == decoder) { 160617b9080SKazutaka YOKOTA if ((error = splash_term(splash_adp)) != 0) 161617b9080SKazutaka YOKOTA return error; 162617b9080SKazutaka YOKOTA } 163617b9080SKazutaka YOKOTA return 0; 164617b9080SKazutaka YOKOTA } 165617b9080SKazutaka YOKOTA 166617b9080SKazutaka YOKOTA int 1676e8394b8SKazutaka YOKOTA splash_init(video_adapter_t *adp, int (*callback)(int, void *), void *arg) 168617b9080SKazutaka YOKOTA { 169617b9080SKazutaka YOKOTA int i; 170617b9080SKazutaka YOKOTA 171617b9080SKazutaka YOKOTA splash_adp = adp; 172617b9080SKazutaka YOKOTA splash_callback = callback; 1736e8394b8SKazutaka YOKOTA splash_arg = arg; 174617b9080SKazutaka YOKOTA 175617b9080SKazutaka YOKOTA splash_decoder = NULL; 176617b9080SKazutaka YOKOTA for (i = 0; i < decoders; ++i) { 177617b9080SKazutaka YOKOTA if (decoder_set[i] == NULL) 178617b9080SKazutaka YOKOTA continue; 179559e7c1bSKazutaka YOKOTA if (splash_test(decoder_set[i]) == 0) { 180559e7c1bSKazutaka YOKOTA splash_new(decoder_set[i]); 181617b9080SKazutaka YOKOTA break; 182617b9080SKazutaka YOKOTA } 183559e7c1bSKazutaka YOKOTA decoder_set[i] = NULL; 184559e7c1bSKazutaka YOKOTA } 185559e7c1bSKazutaka YOKOTA for (++i; i < decoders; ++i) { 186559e7c1bSKazutaka YOKOTA decoder_set[i] = NULL; 187559e7c1bSKazutaka YOKOTA } 188617b9080SKazutaka YOKOTA return 0; 189617b9080SKazutaka YOKOTA } 190617b9080SKazutaka YOKOTA 191617b9080SKazutaka YOKOTA int 192617b9080SKazutaka YOKOTA splash_term(video_adapter_t *adp) 193617b9080SKazutaka YOKOTA { 194617b9080SKazutaka YOKOTA int error = 0; 195617b9080SKazutaka YOKOTA 1966e8394b8SKazutaka YOKOTA if (splash_adp != adp) 1976e8394b8SKazutaka YOKOTA return EINVAL; 198617b9080SKazutaka YOKOTA if (splash_decoder != NULL) { 199617b9080SKazutaka YOKOTA if (splash_callback != NULL) 2006e8394b8SKazutaka YOKOTA error = (*splash_callback)(SPLASH_TERM, splash_arg); 201d8add747SNick Hibma if (error == 0 && splash_decoder->term) 202617b9080SKazutaka YOKOTA error = (*splash_decoder->term)(adp); 203617b9080SKazutaka YOKOTA if (error == 0) 204617b9080SKazutaka YOKOTA splash_decoder = NULL; 205617b9080SKazutaka YOKOTA } 206617b9080SKazutaka YOKOTA return error; 207617b9080SKazutaka YOKOTA } 208617b9080SKazutaka YOKOTA 209617b9080SKazutaka YOKOTA int 210617b9080SKazutaka YOKOTA splash(video_adapter_t *adp, int on) 211617b9080SKazutaka YOKOTA { 212617b9080SKazutaka YOKOTA if (splash_decoder != NULL) 213617b9080SKazutaka YOKOTA return (*splash_decoder->splash)(adp, on); 214617b9080SKazutaka YOKOTA return ENODEV; 215617b9080SKazutaka YOKOTA } 216