1 /*- 2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer as 10 * the first lines of this file unmodified. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include "opt_splash.h" 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/malloc.h> 36 #include <sys/linker.h> 37 #include <sys/fbio.h> 38 #include <sys/kernel.h> 39 #include <sys/module.h> 40 41 #include <dev/fb/fbreg.h> 42 #include <dev/fb/splashreg.h> 43 44 MODULE_VERSION(splash, 1); 45 46 /* video adapter and image decoder */ 47 static video_adapter_t *splash_adp; 48 static splash_decoder_t *splash_decoder; 49 50 /* decoder candidates */ 51 static int decoders; 52 static splash_decoder_t **decoder_set; 53 #define DECODER_ARRAY_DELTA 4 54 55 /* console driver callback */ 56 static int (*splash_callback)(int, void *); 57 static void *splash_arg; 58 59 static int 60 splash_find_data(splash_decoder_t *decoder) 61 { 62 caddr_t image_module; 63 void *ptr; 64 size_t sz; 65 66 if (decoder->data_type == NULL) 67 return (0); 68 69 image_module = preload_search_by_type(decoder->data_type); 70 if (image_module == NULL) 71 return (ENOENT); 72 73 ptr = preload_fetch_addr(image_module); 74 sz = preload_fetch_size(image_module); 75 if (ptr == NULL || sz == 0) 76 return (ENOENT); 77 78 if (bootverbose) 79 printf("splash: image@%p, size:%zu\n", ptr, sz); 80 81 decoder->data = ptr; 82 decoder->data_size = sz; 83 return (0); 84 } 85 86 static int 87 splash_test(splash_decoder_t *decoder) 88 { 89 if (splash_find_data(decoder)) 90 return ENOENT; /* XXX */ 91 if (*decoder->init && (*decoder->init)(splash_adp)) { 92 decoder->data = NULL; 93 decoder->data_size = 0; 94 return ENODEV; /* XXX */ 95 } 96 if (bootverbose) 97 printf("splash: image decoder found: %s\n", decoder->name); 98 return 0; 99 } 100 101 static void 102 splash_new(splash_decoder_t *decoder) 103 { 104 splash_decoder = decoder; 105 if (splash_callback != NULL) 106 (*splash_callback)(SPLASH_INIT, splash_arg); 107 } 108 109 int 110 splash_register(splash_decoder_t *decoder) 111 { 112 splash_decoder_t **p; 113 int error; 114 int i; 115 116 if (splash_adp != NULL) { 117 /* 118 * If the video card has already been initialized, test 119 * this decoder immediately. 120 */ 121 error = splash_test(decoder); 122 if (error == 0) { 123 /* replace the current decoder with new one */ 124 if (splash_decoder != NULL) 125 error = splash_term(splash_adp); 126 if (error == 0) 127 splash_new(decoder); 128 } 129 return error; 130 } else { 131 /* register the decoder for later use */ 132 for (i = 0; i < decoders; ++i) { 133 if (decoder_set[i] == NULL) 134 break; 135 } 136 if ((i >= decoders) && (decoders % DECODER_ARRAY_DELTA) == 0) { 137 p = malloc(sizeof(*p)*(decoders + DECODER_ARRAY_DELTA), 138 M_DEVBUF, M_NOWAIT); 139 if (p == NULL) 140 return ENOMEM; 141 if (decoder_set != NULL) { 142 bcopy(decoder_set, p, sizeof(*p)*decoders); 143 free(decoder_set, M_DEVBUF); 144 } 145 decoder_set = p; 146 i = decoders++; 147 } 148 decoder_set[i] = decoder; 149 } 150 151 return 0; 152 } 153 154 int 155 splash_unregister(splash_decoder_t *decoder) 156 { 157 int error; 158 159 if (splash_decoder == decoder) { 160 if ((error = splash_term(splash_adp)) != 0) 161 return error; 162 } 163 return 0; 164 } 165 166 int 167 splash_init(video_adapter_t *adp, int (*callback)(int, void *), void *arg) 168 { 169 int i; 170 171 splash_adp = adp; 172 splash_callback = callback; 173 splash_arg = arg; 174 175 splash_decoder = NULL; 176 for (i = 0; i < decoders; ++i) { 177 if (decoder_set[i] == NULL) 178 continue; 179 if (splash_test(decoder_set[i]) == 0) { 180 splash_new(decoder_set[i]); 181 break; 182 } 183 decoder_set[i] = NULL; 184 } 185 for (++i; i < decoders; ++i) { 186 decoder_set[i] = NULL; 187 } 188 return 0; 189 } 190 191 int 192 splash_term(video_adapter_t *adp) 193 { 194 int error = 0; 195 196 if (splash_adp != adp) 197 return EINVAL; 198 if (splash_decoder != NULL) { 199 if (splash_callback != NULL) 200 error = (*splash_callback)(SPLASH_TERM, splash_arg); 201 if (error == 0 && splash_decoder->term) 202 error = (*splash_decoder->term)(adp); 203 if (error == 0) 204 splash_decoder = NULL; 205 } 206 return error; 207 } 208 209 int 210 splash(video_adapter_t *adp, int on) 211 { 212 if (splash_decoder != NULL) 213 return (*splash_decoder->splash)(adp, on); 214 return ENODEV; 215 } 216