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 caddr_t p; 64 65 if (decoder->data_type == NULL) 66 return 0; 67 image_module = preload_search_by_type(decoder->data_type); 68 if (image_module == NULL) 69 return ENOENT; 70 p = preload_search_info(image_module, MODINFO_ADDR); 71 if (p == NULL) 72 return ENOENT; 73 decoder->data = *(void **)p; 74 p = preload_search_info(image_module, MODINFO_SIZE); 75 if (p == NULL) 76 return ENOENT; 77 decoder->data_size = *(size_t *)p; 78 if (bootverbose) 79 printf("splash: image@%p, size:%lu\n", 80 (void *)decoder->data, (long)decoder->data_size); 81 return 0; 82 } 83 84 static int 85 splash_test(splash_decoder_t *decoder) 86 { 87 if (splash_find_data(decoder)) 88 return ENOENT; /* XXX */ 89 if (*decoder->init && (*decoder->init)(splash_adp)) { 90 decoder->data = NULL; 91 decoder->data_size = 0; 92 return ENODEV; /* XXX */ 93 } 94 if (bootverbose) 95 printf("splash: image decoder found: %s\n", decoder->name); 96 return 0; 97 } 98 99 static void 100 splash_new(splash_decoder_t *decoder) 101 { 102 splash_decoder = decoder; 103 if (splash_callback != NULL) 104 (*splash_callback)(SPLASH_INIT, splash_arg); 105 } 106 107 int 108 splash_register(splash_decoder_t *decoder) 109 { 110 splash_decoder_t **p; 111 int error; 112 int i; 113 114 if (splash_adp != NULL) { 115 /* 116 * If the video card has aleady been initialized, test 117 * this decoder immediately. 118 */ 119 error = splash_test(decoder); 120 if (error == 0) { 121 /* replace the current decoder with new one */ 122 if (splash_decoder != NULL) 123 error = splash_term(splash_adp); 124 if (error == 0) 125 splash_new(decoder); 126 } 127 return error; 128 } else { 129 /* register the decoder for later use */ 130 for (i = 0; i < decoders; ++i) { 131 if (decoder_set[i] == NULL) 132 break; 133 } 134 if ((i >= decoders) && (decoders % DECODER_ARRAY_DELTA) == 0) { 135 p = malloc(sizeof(*p)*(decoders + DECODER_ARRAY_DELTA), 136 M_DEVBUF, M_NOWAIT); 137 if (p == NULL) 138 return ENOMEM; 139 if (decoder_set != NULL) { 140 bcopy(decoder_set, p, sizeof(*p)*decoders); 141 free(decoder_set, M_DEVBUF); 142 } 143 decoder_set = p; 144 i = decoders++; 145 } 146 decoder_set[i] = decoder; 147 } 148 149 return 0; 150 } 151 152 int 153 splash_unregister(splash_decoder_t *decoder) 154 { 155 int error; 156 157 if (splash_decoder == decoder) { 158 if ((error = splash_term(splash_adp)) != 0) 159 return error; 160 } 161 return 0; 162 } 163 164 int 165 splash_init(video_adapter_t *adp, int (*callback)(int, void *), void *arg) 166 { 167 int i; 168 169 splash_adp = adp; 170 splash_callback = callback; 171 splash_arg = arg; 172 173 splash_decoder = NULL; 174 for (i = 0; i < decoders; ++i) { 175 if (decoder_set[i] == NULL) 176 continue; 177 if (splash_test(decoder_set[i]) == 0) { 178 splash_new(decoder_set[i]); 179 break; 180 } 181 decoder_set[i] = NULL; 182 } 183 for (++i; i < decoders; ++i) { 184 decoder_set[i] = NULL; 185 } 186 return 0; 187 } 188 189 int 190 splash_term(video_adapter_t *adp) 191 { 192 int error = 0; 193 194 if (splash_adp != adp) 195 return EINVAL; 196 if (splash_decoder != NULL) { 197 if (splash_callback != NULL) 198 error = (*splash_callback)(SPLASH_TERM, splash_arg); 199 if (error == 0 && splash_decoder->term) 200 error = (*splash_decoder->term)(adp); 201 if (error == 0) 202 splash_decoder = NULL; 203 } 204 return error; 205 } 206 207 int 208 splash(video_adapter_t *adp, int on) 209 { 210 if (splash_decoder != NULL) 211 return (*splash_decoder->splash)(adp, on); 212 return ENODEV; 213 } 214