xref: /freebsd/sys/dev/fb/splash.c (revision 380a989b3223d455375b4fae70fd0b9bdd43bafb)
1 /*-
2  * $Id:$
3  */
4 
5 #include "splash.h"
6 
7 #if NSPLASH > 0
8 
9 #include <sys/param.h>
10 #include <sys/systm.h>
11 #include <sys/kernel.h>
12 #include <sys/malloc.h>
13 #include <sys/linker.h>
14 
15 #include <machine/console.h>
16 
17 #include <dev/fb/fbreg.h>
18 #include <dev/fb/splashreg.h>
19 
20 /* video adapter and image decoder */
21 static video_adapter_t	*splash_adp;
22 static splash_decoder_t	*splash_decoder;
23 
24 /* decoder candidates */
25 static int		decoders;
26 static splash_decoder_t **decoder_set;
27 #define DECODER_ARRAY_DELTA 4
28 
29 /* splash image data file */
30 static void		*splash_image_data;
31 static size_t		splash_image_size;
32 
33 /* console driver callback */
34 static int		(*splash_callback)(int);
35 
36 static int
37 splash_find_image(void)
38 {
39         caddr_t image_module;
40 	caddr_t p;
41 
42 	if (splash_image_data == NULL) {
43 		image_module = preload_search_by_type(SPLASH_IMAGE);
44 		if (image_module == NULL)
45 			return ENOENT;
46 		p = preload_search_info(image_module, MODINFO_ADDR);
47 		if (p == NULL)
48 			return ENOENT;
49 		splash_image_data = *(void **)p;
50 		p = preload_search_info(image_module, MODINFO_SIZE);
51 		if (p == NULL)
52 			return ENOENT;
53 		splash_image_size = *(size_t *)p;
54 	}
55 	return 0;
56 }
57 
58 static int
59 splash_test(splash_decoder_t *decoder)
60 {
61 	if ((*decoder->init)(splash_adp, splash_image_data, splash_image_size))
62 		return ENODEV;	/* XXX */
63 	if (bootverbose)
64 		printf("splash: image decoder found: %s\n", decoder->name);
65 	splash_decoder = decoder;
66 	if (splash_callback != NULL)
67 		(*splash_callback)(SPLASH_INIT);
68 	return 0;
69 }
70 
71 int
72 splash_register(splash_decoder_t *decoder)
73 {
74 	splash_decoder_t **p;
75 	int i;
76 
77 	/* only one decoder can be active */
78 	if (splash_decoder != NULL)
79 		return ENODEV;	/* XXX */
80 
81 	/* if the splash image is not in memory, abort */
82 	splash_find_image();
83 	if (bootverbose)
84 		printf("splash: image@%p, size:%u\n",
85 		       splash_image_data, splash_image_size);
86 	if (splash_image_data == NULL)
87 		return ENOENT;
88 
89 	/*
90 	 * If the video card has aleady been initialized, test this
91 	 * decoder immediately.
92 	 */
93 	if (splash_adp != NULL)
94 		return splash_test(decoder);
95 
96 	/* register the decoder for later use */
97 	for (i = 0; i < decoders; ++i) {
98 		if (decoder_set[i] == NULL)
99 			break;
100 	}
101 	if ((i >= decoders) && (decoders % DECODER_ARRAY_DELTA) == 0) {
102 		p = malloc(sizeof(*p)*(decoders + DECODER_ARRAY_DELTA),
103 			   M_DEVBUF, M_NOWAIT);
104 		if (p == NULL)
105 			return ENOMEM;
106 		if (decoder_set != NULL)
107 			bcopy(decoder_set, p, sizeof(*p)*decoders);
108 		free(decoder_set, M_DEVBUF);
109 		decoder_set = p;
110 		i = decoders++;
111 	}
112 	decoder_set[i] = decoder;
113 	return 0;
114 }
115 
116 int
117 splash_unregister(splash_decoder_t *decoder)
118 {
119 	int error;
120 	int i;
121 
122 	if (splash_decoder == decoder) {
123 		if ((error = splash_term(splash_adp)) != 0)
124 			return error;
125 	}
126 	for (i = 0; i < decoders; ++i) {
127 		if (decoder_set[i] == decoder) {
128 			decoder_set[i] = NULL;
129 			break;
130 		}
131 	}
132 	return 0;
133 }
134 
135 int
136 splash_init(video_adapter_t *adp, int (*callback)(int))
137 {
138 	int i;
139 
140 	splash_adp = adp;
141 	splash_callback = callback;
142 
143 	/* try registered decoders with this adapter and loaded image */
144 	splash_decoder = NULL;
145 	splash_find_image();
146 	if (splash_image_data == NULL)
147 		return 0;
148 	for (i = 0; i < decoders; ++i) {
149 		if (decoder_set[i] == NULL)
150 			continue;
151 		if (splash_test(decoder_set[i]) == 0)
152 			break;
153 	}
154 	return 0;
155 }
156 
157 int
158 splash_term(video_adapter_t *adp)
159 {
160 	int error = 0;
161 
162 	if (splash_decoder != NULL) {
163 		if (splash_callback != NULL)
164 			error = (*splash_callback)(SPLASH_TERM);
165 		if (error == 0)
166 			error = (*splash_decoder->term)(adp);
167 		if (error == 0)
168 			splash_decoder = NULL;
169 	}
170 	return error;
171 }
172 
173 int
174 splash(video_adapter_t *adp, int on)
175 {
176 	if (splash_decoder != NULL)
177 		return (*splash_decoder->splash)(adp, on);
178 	return ENODEV;
179 }
180 
181 #endif /* NSPLASH > 0 */
182