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 * 26c3aac50fSPeter Wemm * $FreeBSD$ 27617b9080SKazutaka YOKOTA */ 28617b9080SKazutaka YOKOTA 29617b9080SKazutaka YOKOTA #include <sys/param.h> 30617b9080SKazutaka YOKOTA #include <sys/systm.h> 31617b9080SKazutaka YOKOTA #include <sys/kernel.h> 32617b9080SKazutaka YOKOTA #include <sys/malloc.h> 33617b9080SKazutaka YOKOTA #include <sys/linker.h> 346e8394b8SKazutaka YOKOTA #include <sys/fbio.h> 35617b9080SKazutaka YOKOTA 36617b9080SKazutaka YOKOTA #include <dev/fb/fbreg.h> 37617b9080SKazutaka YOKOTA #include <dev/fb/splashreg.h> 38617b9080SKazutaka YOKOTA 3936d4f7c1SPeter Wemm MODULE_VERSION(splash, 1); 4036d4f7c1SPeter Wemm 41617b9080SKazutaka YOKOTA /* video adapter and image decoder */ 42617b9080SKazutaka YOKOTA static video_adapter_t *splash_adp; 43617b9080SKazutaka YOKOTA static splash_decoder_t *splash_decoder; 44617b9080SKazutaka YOKOTA 45617b9080SKazutaka YOKOTA /* decoder candidates */ 46617b9080SKazutaka YOKOTA static int decoders; 47617b9080SKazutaka YOKOTA static splash_decoder_t **decoder_set; 48617b9080SKazutaka YOKOTA #define DECODER_ARRAY_DELTA 4 49617b9080SKazutaka YOKOTA 50617b9080SKazutaka YOKOTA /* console driver callback */ 516e8394b8SKazutaka YOKOTA static int (*splash_callback)(int, void *); 526e8394b8SKazutaka YOKOTA static void *splash_arg; 53617b9080SKazutaka YOKOTA 54617b9080SKazutaka YOKOTA static int 55559e7c1bSKazutaka YOKOTA splash_find_data(splash_decoder_t *decoder) 56617b9080SKazutaka YOKOTA { 57617b9080SKazutaka YOKOTA caddr_t image_module; 58617b9080SKazutaka YOKOTA caddr_t p; 59617b9080SKazutaka YOKOTA 60559e7c1bSKazutaka YOKOTA if (decoder->data_type == NULL) 61559e7c1bSKazutaka YOKOTA return 0; 62559e7c1bSKazutaka YOKOTA image_module = preload_search_by_type(decoder->data_type); 63617b9080SKazutaka YOKOTA if (image_module == NULL) 64617b9080SKazutaka YOKOTA return ENOENT; 65617b9080SKazutaka YOKOTA p = preload_search_info(image_module, MODINFO_ADDR); 66617b9080SKazutaka YOKOTA if (p == NULL) 67617b9080SKazutaka YOKOTA return ENOENT; 68559e7c1bSKazutaka YOKOTA decoder->data = *(void **)p; 69617b9080SKazutaka YOKOTA p = preload_search_info(image_module, MODINFO_SIZE); 70617b9080SKazutaka YOKOTA if (p == NULL) 71617b9080SKazutaka YOKOTA return ENOENT; 72559e7c1bSKazutaka YOKOTA decoder->data_size = *(size_t *)p; 73559e7c1bSKazutaka YOKOTA if (bootverbose) 74e240133cSPeter Wemm printf("splash: image@%p, size:%lu\n", 75e240133cSPeter Wemm (void *)decoder->data, (long)decoder->data_size); 76617b9080SKazutaka YOKOTA return 0; 77617b9080SKazutaka YOKOTA } 78617b9080SKazutaka YOKOTA 79617b9080SKazutaka YOKOTA static int 80617b9080SKazutaka YOKOTA splash_test(splash_decoder_t *decoder) 81617b9080SKazutaka YOKOTA { 82559e7c1bSKazutaka YOKOTA if (splash_find_data(decoder)) 83559e7c1bSKazutaka YOKOTA return ENOENT; /* XXX */ 84d8add747SNick Hibma if (*decoder->init && (*decoder->init)(splash_adp)) { 85559e7c1bSKazutaka YOKOTA decoder->data = NULL; 86559e7c1bSKazutaka YOKOTA decoder->data_size = 0; 87617b9080SKazutaka YOKOTA return ENODEV; /* XXX */ 88559e7c1bSKazutaka YOKOTA } 89617b9080SKazutaka YOKOTA if (bootverbose) 90617b9080SKazutaka YOKOTA printf("splash: image decoder found: %s\n", decoder->name); 91559e7c1bSKazutaka YOKOTA return 0; 92559e7c1bSKazutaka YOKOTA } 93559e7c1bSKazutaka YOKOTA 94559e7c1bSKazutaka YOKOTA static void 95559e7c1bSKazutaka YOKOTA splash_new(splash_decoder_t *decoder) 96559e7c1bSKazutaka YOKOTA { 97617b9080SKazutaka YOKOTA splash_decoder = decoder; 98617b9080SKazutaka YOKOTA if (splash_callback != NULL) 996e8394b8SKazutaka YOKOTA (*splash_callback)(SPLASH_INIT, splash_arg); 100617b9080SKazutaka YOKOTA } 101617b9080SKazutaka YOKOTA 102617b9080SKazutaka YOKOTA int 103617b9080SKazutaka YOKOTA splash_register(splash_decoder_t *decoder) 104617b9080SKazutaka YOKOTA { 105617b9080SKazutaka YOKOTA splash_decoder_t **p; 106559e7c1bSKazutaka YOKOTA int error; 107617b9080SKazutaka YOKOTA int i; 108617b9080SKazutaka YOKOTA 109559e7c1bSKazutaka YOKOTA if (splash_adp != NULL) { 110617b9080SKazutaka YOKOTA /* 111559e7c1bSKazutaka YOKOTA * If the video card has aleady been initialized, test 112559e7c1bSKazutaka YOKOTA * this decoder immediately. 113617b9080SKazutaka YOKOTA */ 114559e7c1bSKazutaka YOKOTA error = splash_test(decoder); 115559e7c1bSKazutaka YOKOTA if (error == 0) { 116559e7c1bSKazutaka YOKOTA /* replace the current decoder with new one */ 117559e7c1bSKazutaka YOKOTA if (splash_decoder != NULL) 118559e7c1bSKazutaka YOKOTA error = splash_term(splash_adp); 119559e7c1bSKazutaka YOKOTA if (error == 0) 120559e7c1bSKazutaka YOKOTA splash_new(decoder); 121559e7c1bSKazutaka YOKOTA } 122559e7c1bSKazutaka YOKOTA return error; 123559e7c1bSKazutaka YOKOTA } else { 124617b9080SKazutaka YOKOTA /* register the decoder for later use */ 125617b9080SKazutaka YOKOTA for (i = 0; i < decoders; ++i) { 126617b9080SKazutaka YOKOTA if (decoder_set[i] == NULL) 127617b9080SKazutaka YOKOTA break; 128617b9080SKazutaka YOKOTA } 129617b9080SKazutaka YOKOTA if ((i >= decoders) && (decoders % DECODER_ARRAY_DELTA) == 0) { 130617b9080SKazutaka YOKOTA p = malloc(sizeof(*p)*(decoders + DECODER_ARRAY_DELTA), 131617b9080SKazutaka YOKOTA M_DEVBUF, M_NOWAIT); 132617b9080SKazutaka YOKOTA if (p == NULL) 133617b9080SKazutaka YOKOTA return ENOMEM; 13411b5621eSKazutaka YOKOTA if (decoder_set != NULL) { 135617b9080SKazutaka YOKOTA bcopy(decoder_set, p, sizeof(*p)*decoders); 136617b9080SKazutaka YOKOTA free(decoder_set, M_DEVBUF); 13711b5621eSKazutaka YOKOTA } 138617b9080SKazutaka YOKOTA decoder_set = p; 139617b9080SKazutaka YOKOTA i = decoders++; 140617b9080SKazutaka YOKOTA } 141617b9080SKazutaka YOKOTA decoder_set[i] = decoder; 142559e7c1bSKazutaka YOKOTA } 143559e7c1bSKazutaka YOKOTA 144617b9080SKazutaka YOKOTA return 0; 145617b9080SKazutaka YOKOTA } 146617b9080SKazutaka YOKOTA 147617b9080SKazutaka YOKOTA int 148617b9080SKazutaka YOKOTA splash_unregister(splash_decoder_t *decoder) 149617b9080SKazutaka YOKOTA { 150617b9080SKazutaka YOKOTA int error; 151617b9080SKazutaka YOKOTA 152617b9080SKazutaka YOKOTA if (splash_decoder == decoder) { 153617b9080SKazutaka YOKOTA if ((error = splash_term(splash_adp)) != 0) 154617b9080SKazutaka YOKOTA return error; 155617b9080SKazutaka YOKOTA } 156617b9080SKazutaka YOKOTA return 0; 157617b9080SKazutaka YOKOTA } 158617b9080SKazutaka YOKOTA 159617b9080SKazutaka YOKOTA int 1606e8394b8SKazutaka YOKOTA splash_init(video_adapter_t *adp, int (*callback)(int, void *), void *arg) 161617b9080SKazutaka YOKOTA { 162617b9080SKazutaka YOKOTA int i; 163617b9080SKazutaka YOKOTA 164617b9080SKazutaka YOKOTA splash_adp = adp; 165617b9080SKazutaka YOKOTA splash_callback = callback; 1666e8394b8SKazutaka YOKOTA splash_arg = arg; 167617b9080SKazutaka YOKOTA 168617b9080SKazutaka YOKOTA splash_decoder = NULL; 169617b9080SKazutaka YOKOTA for (i = 0; i < decoders; ++i) { 170617b9080SKazutaka YOKOTA if (decoder_set[i] == NULL) 171617b9080SKazutaka YOKOTA continue; 172559e7c1bSKazutaka YOKOTA if (splash_test(decoder_set[i]) == 0) { 173559e7c1bSKazutaka YOKOTA splash_new(decoder_set[i]); 174617b9080SKazutaka YOKOTA break; 175617b9080SKazutaka YOKOTA } 176559e7c1bSKazutaka YOKOTA decoder_set[i] = NULL; 177559e7c1bSKazutaka YOKOTA } 178559e7c1bSKazutaka YOKOTA for (++i; i < decoders; ++i) { 179559e7c1bSKazutaka YOKOTA decoder_set[i] = NULL; 180559e7c1bSKazutaka YOKOTA } 181617b9080SKazutaka YOKOTA return 0; 182617b9080SKazutaka YOKOTA } 183617b9080SKazutaka YOKOTA 184617b9080SKazutaka YOKOTA int 185617b9080SKazutaka YOKOTA splash_term(video_adapter_t *adp) 186617b9080SKazutaka YOKOTA { 187617b9080SKazutaka YOKOTA int error = 0; 188617b9080SKazutaka YOKOTA 1896e8394b8SKazutaka YOKOTA if (splash_adp != adp) 1906e8394b8SKazutaka YOKOTA return EINVAL; 191617b9080SKazutaka YOKOTA if (splash_decoder != NULL) { 192617b9080SKazutaka YOKOTA if (splash_callback != NULL) 1936e8394b8SKazutaka YOKOTA error = (*splash_callback)(SPLASH_TERM, splash_arg); 194d8add747SNick Hibma if (error == 0 && splash_decoder->term) 195617b9080SKazutaka YOKOTA error = (*splash_decoder->term)(adp); 196617b9080SKazutaka YOKOTA if (error == 0) 197617b9080SKazutaka YOKOTA splash_decoder = NULL; 198617b9080SKazutaka YOKOTA } 199617b9080SKazutaka YOKOTA return error; 200617b9080SKazutaka YOKOTA } 201617b9080SKazutaka YOKOTA 202617b9080SKazutaka YOKOTA int 203617b9080SKazutaka YOKOTA splash(video_adapter_t *adp, int on) 204617b9080SKazutaka YOKOTA { 205617b9080SKazutaka YOKOTA if (splash_decoder != NULL) 206617b9080SKazutaka YOKOTA return (*splash_decoder->splash)(adp, on); 207617b9080SKazutaka YOKOTA return ENODEV; 208617b9080SKazutaka YOKOTA } 209