xref: /dragonfly/sys/dev/video/fb/splash.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
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  * $FreeBSD: src/sys/dev/fb/splash.c,v 1.8 2000/01/29 14:42:57 peter Exp $
27  * $DragonFly: src/sys/dev/video/fb/splash.c,v 1.6 2006/12/22 23:26:27 swildner Exp $
28  */
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/malloc.h>
34 #include <sys/linker.h>
35 #include <sys/fbio.h>
36 
37 #include "fbreg.h"
38 #include "splashreg.h"
39 
40 /* video adapter and image decoder */
41 static video_adapter_t        *splash_adp;
42 static splash_decoder_t       *splash_decoder;
43 
44 /* decoder candidates */
45 static int                    decoders;
46 static splash_decoder_t **decoder_set;
47 #define DECODER_ARRAY_DELTA 4
48 
49 /* console driver callback */
50 static int                    (*splash_callback)(int, void *);
51 static void                   *splash_arg;
52 
53 static int
splash_find_data(splash_decoder_t * decoder)54 splash_find_data(splash_decoder_t *decoder)
55 {
56         caddr_t image_module;
57           caddr_t p;
58 
59           if (decoder->data_type == NULL)
60                     return 0;
61           image_module = preload_search_by_type(decoder->data_type);
62           if (image_module == NULL)
63                     return ENOENT;
64           p = preload_search_info(image_module, MODINFO_ADDR);
65           if (p == NULL)
66                     return ENOENT;
67           decoder->data = *(void **)p;
68           p = preload_search_info(image_module, MODINFO_SIZE);
69           if (p == NULL)
70                     return ENOENT;
71           decoder->data_size = *(size_t *)p;
72           if (bootverbose)
73                     kprintf("splash: image@%p, size:%lu\n",
74                            (void *)decoder->data, (long)decoder->data_size);
75           return 0;
76 }
77 
78 static int
splash_test(splash_decoder_t * decoder)79 splash_test(splash_decoder_t *decoder)
80 {
81           if (splash_find_data(decoder))
82                     return ENOENT;      /* XXX */
83           if (*decoder->init && (*decoder->init)(splash_adp)) {
84                     decoder->data = NULL;
85                     decoder->data_size = 0;
86                     return ENODEV;      /* XXX */
87           }
88           if (bootverbose)
89                     kprintf("splash: image decoder found: %s\n", decoder->name);
90           return 0;
91 }
92 
93 static void
splash_new(splash_decoder_t * decoder)94 splash_new(splash_decoder_t *decoder)
95 {
96           splash_decoder = decoder;
97           if (splash_callback != NULL)
98                     (*splash_callback)(SPLASH_INIT, splash_arg);
99 }
100 
101 int
splash_register(splash_decoder_t * decoder)102 splash_register(splash_decoder_t *decoder)
103 {
104           splash_decoder_t **p;
105           int error;
106           int i;
107 
108           if (splash_adp != NULL) {
109                     /*
110                      * If the video card has aleady been initialized, test
111                      * this decoder immediately.
112                      */
113                     error = splash_test(decoder);
114                     if (error == 0) {
115                               /* replace the current decoder with new one */
116                               if (splash_decoder != NULL)
117                                         error = splash_term(splash_adp);
118                               if (error == 0)
119                                         splash_new(decoder);
120                     }
121                     return error;
122           } else {
123                     /* register the decoder for later use */
124                     for (i = 0; i < decoders; ++i) {
125                               if (decoder_set[i] == NULL)
126                                         break;
127                     }
128                     if ((i >= decoders) && (decoders % DECODER_ARRAY_DELTA) == 0) {
129                               p = kmalloc(sizeof(*p)*(decoders + DECODER_ARRAY_DELTA),
130                                         M_DEVBUF, M_NOWAIT);
131                               if (p == NULL)
132                                         return ENOMEM;
133                               if (decoder_set != NULL) {
134                                         bcopy(decoder_set, p, sizeof(*p)*decoders);
135                                         kfree(decoder_set, M_DEVBUF);
136                               }
137                               decoder_set = p;
138                               i = decoders++;
139                     }
140                     decoder_set[i] = decoder;
141           }
142 
143           return 0;
144 }
145 
146 int
splash_unregister(splash_decoder_t * decoder)147 splash_unregister(splash_decoder_t *decoder)
148 {
149           int error;
150 
151           if (splash_decoder == decoder) {
152                     if ((error = splash_term(splash_adp)) != 0)
153                               return error;
154           }
155           return 0;
156 }
157 
158 int
splash_init(video_adapter_t * adp,int (* callback)(int,void *),void * arg)159 splash_init(video_adapter_t *adp, int (*callback)(int, void *), void *arg)
160 {
161           int i;
162 
163           splash_adp = adp;
164           splash_callback = callback;
165           splash_arg = arg;
166 
167           splash_decoder = NULL;
168           for (i = 0; i < decoders; ++i) {
169                     if (decoder_set[i] == NULL)
170                               continue;
171                     if (splash_test(decoder_set[i]) == 0) {
172                               splash_new(decoder_set[i]);
173                               break;
174                     }
175                     decoder_set[i] = NULL;
176           }
177           for (++i; i < decoders; ++i) {
178                     decoder_set[i] = NULL;
179           }
180           return 0;
181 }
182 
183 int
splash_term(video_adapter_t * adp)184 splash_term(video_adapter_t *adp)
185 {
186           int error = 0;
187 
188           if (splash_adp != adp)
189                     return EINVAL;
190           if (splash_decoder != NULL) {
191                     if (splash_callback != NULL)
192                               error = (*splash_callback)(SPLASH_TERM, splash_arg);
193                     if (error == 0 && splash_decoder->term)
194                               error = (*splash_decoder->term)(adp);
195                     if (error == 0)
196                               splash_decoder = NULL;
197           }
198           return error;
199 }
200 
201 int
splash(video_adapter_t * adp,int on)202 splash(video_adapter_t *adp, int on)
203 {
204           if (splash_decoder != NULL)
205                     return (*splash_decoder->splash)(adp, on);
206           return ENODEV;
207 }
208