xref: /freebsd/sys/dev/fb/splash.c (revision 617b90803690a7ece8e76a49803385516bac380b)
1617b9080SKazutaka YOKOTA /*-
2617b9080SKazutaka YOKOTA  * $Id:$
3617b9080SKazutaka YOKOTA  */
4617b9080SKazutaka YOKOTA 
5617b9080SKazutaka YOKOTA #include "splash.h"
6617b9080SKazutaka YOKOTA 
7617b9080SKazutaka YOKOTA #if NSPLASH > 0
8617b9080SKazutaka YOKOTA 
9617b9080SKazutaka YOKOTA #include <sys/param.h>
10617b9080SKazutaka YOKOTA #include <sys/systm.h>
11617b9080SKazutaka YOKOTA #include <sys/kernel.h>
12617b9080SKazutaka YOKOTA #include <sys/malloc.h>
13617b9080SKazutaka YOKOTA #include <sys/linker.h>
14617b9080SKazutaka YOKOTA 
15617b9080SKazutaka YOKOTA #include <machine/console.h>
16617b9080SKazutaka YOKOTA 
17617b9080SKazutaka YOKOTA #include <dev/fb/fbreg.h>
18617b9080SKazutaka YOKOTA #include <dev/fb/splashreg.h>
19617b9080SKazutaka YOKOTA 
20617b9080SKazutaka YOKOTA /* video adapter and image decoder */
21617b9080SKazutaka YOKOTA static video_adapter_t	*splash_adp;
22617b9080SKazutaka YOKOTA static splash_decoder_t	*splash_decoder;
23617b9080SKazutaka YOKOTA 
24617b9080SKazutaka YOKOTA /* decoder candidates */
25617b9080SKazutaka YOKOTA static int		decoders;
26617b9080SKazutaka YOKOTA static splash_decoder_t **decoder_set;
27617b9080SKazutaka YOKOTA #define DECODER_ARRAY_DELTA 4
28617b9080SKazutaka YOKOTA 
29617b9080SKazutaka YOKOTA /* splash image data file */
30617b9080SKazutaka YOKOTA static void		*splash_image_data;
31617b9080SKazutaka YOKOTA static size_t		splash_image_size;
32617b9080SKazutaka YOKOTA 
33617b9080SKazutaka YOKOTA /* console driver callback */
34617b9080SKazutaka YOKOTA static int		(*splash_callback)(int);
35617b9080SKazutaka YOKOTA 
36617b9080SKazutaka YOKOTA static int
37617b9080SKazutaka YOKOTA splash_find_image(void)
38617b9080SKazutaka YOKOTA {
39617b9080SKazutaka YOKOTA         caddr_t image_module;
40617b9080SKazutaka YOKOTA 	caddr_t p;
41617b9080SKazutaka YOKOTA 
42617b9080SKazutaka YOKOTA 	if (splash_image_data == NULL) {
43617b9080SKazutaka YOKOTA 		image_module = preload_search_by_type(SPLASH_IMAGE);
44617b9080SKazutaka YOKOTA 		if (image_module == NULL)
45617b9080SKazutaka YOKOTA 			return ENOENT;
46617b9080SKazutaka YOKOTA 		p = preload_search_info(image_module, MODINFO_ADDR);
47617b9080SKazutaka YOKOTA 		if (p == NULL)
48617b9080SKazutaka YOKOTA 			return ENOENT;
49617b9080SKazutaka YOKOTA 		splash_image_data = *(void **)p;
50617b9080SKazutaka YOKOTA 		p = preload_search_info(image_module, MODINFO_SIZE);
51617b9080SKazutaka YOKOTA 		if (p == NULL)
52617b9080SKazutaka YOKOTA 			return ENOENT;
53617b9080SKazutaka YOKOTA 		splash_image_size = *(size_t *)p;
54617b9080SKazutaka YOKOTA 	}
55617b9080SKazutaka YOKOTA 	return 0;
56617b9080SKazutaka YOKOTA }
57617b9080SKazutaka YOKOTA 
58617b9080SKazutaka YOKOTA static int
59617b9080SKazutaka YOKOTA splash_test(splash_decoder_t *decoder)
60617b9080SKazutaka YOKOTA {
61617b9080SKazutaka YOKOTA 	if ((*decoder->init)(splash_adp, splash_image_data, splash_image_size))
62617b9080SKazutaka YOKOTA 		return ENODEV;	/* XXX */
63617b9080SKazutaka YOKOTA 	if (bootverbose)
64617b9080SKazutaka YOKOTA 		printf("splash: image decoder found: %s\n", decoder->name);
65617b9080SKazutaka YOKOTA 	splash_decoder = decoder;
66617b9080SKazutaka YOKOTA 	if (splash_callback != NULL)
67617b9080SKazutaka YOKOTA 		(*splash_callback)(SPLASH_INIT);
68617b9080SKazutaka YOKOTA 	return 0;
69617b9080SKazutaka YOKOTA }
70617b9080SKazutaka YOKOTA 
71617b9080SKazutaka YOKOTA int
72617b9080SKazutaka YOKOTA splash_register(splash_decoder_t *decoder)
73617b9080SKazutaka YOKOTA {
74617b9080SKazutaka YOKOTA 	splash_decoder_t **p;
75617b9080SKazutaka YOKOTA 	int i;
76617b9080SKazutaka YOKOTA 
77617b9080SKazutaka YOKOTA 	/* only one decoder can be active */
78617b9080SKazutaka YOKOTA 	if (splash_decoder != NULL)
79617b9080SKazutaka YOKOTA 		return ENODEV;	/* XXX */
80617b9080SKazutaka YOKOTA 
81617b9080SKazutaka YOKOTA 	/* if the splash image is not in memory, abort */
82617b9080SKazutaka YOKOTA 	splash_find_image();
83617b9080SKazutaka YOKOTA 	if (bootverbose)
84617b9080SKazutaka YOKOTA 		printf("splash: image@%p, size:%u\n",
85617b9080SKazutaka YOKOTA 		       splash_image_data, splash_image_size);
86617b9080SKazutaka YOKOTA 	if (splash_image_data == NULL)
87617b9080SKazutaka YOKOTA 		return ENOENT;
88617b9080SKazutaka YOKOTA 
89617b9080SKazutaka YOKOTA 	/*
90617b9080SKazutaka YOKOTA 	 * If the video card has aleady been initialized, test this
91617b9080SKazutaka YOKOTA 	 * decoder immediately.
92617b9080SKazutaka YOKOTA 	 */
93617b9080SKazutaka YOKOTA 	if (splash_adp != NULL)
94617b9080SKazutaka YOKOTA 		return splash_test(decoder);
95617b9080SKazutaka YOKOTA 
96617b9080SKazutaka YOKOTA 	/* register the decoder for later use */
97617b9080SKazutaka YOKOTA 	for (i = 0; i < decoders; ++i) {
98617b9080SKazutaka YOKOTA 		if (decoder_set[i] == NULL)
99617b9080SKazutaka YOKOTA 			break;
100617b9080SKazutaka YOKOTA 	}
101617b9080SKazutaka YOKOTA 	if ((i >= decoders) && (decoders % DECODER_ARRAY_DELTA) == 0) {
102617b9080SKazutaka YOKOTA 		p = malloc(sizeof(*p)*(decoders + DECODER_ARRAY_DELTA),
103617b9080SKazutaka YOKOTA 			   M_DEVBUF, M_NOWAIT);
104617b9080SKazutaka YOKOTA 		if (p == NULL)
105617b9080SKazutaka YOKOTA 			return ENOMEM;
106617b9080SKazutaka YOKOTA 		if (decoder_set != NULL)
107617b9080SKazutaka YOKOTA 			bcopy(decoder_set, p, sizeof(*p)*decoders);
108617b9080SKazutaka YOKOTA 		free(decoder_set, M_DEVBUF);
109617b9080SKazutaka YOKOTA 		decoder_set = p;
110617b9080SKazutaka YOKOTA 		i = decoders++;
111617b9080SKazutaka YOKOTA 	}
112617b9080SKazutaka YOKOTA 	decoder_set[i] = decoder;
113617b9080SKazutaka YOKOTA 	return 0;
114617b9080SKazutaka YOKOTA }
115617b9080SKazutaka YOKOTA 
116617b9080SKazutaka YOKOTA int
117617b9080SKazutaka YOKOTA splash_unregister(splash_decoder_t *decoder)
118617b9080SKazutaka YOKOTA {
119617b9080SKazutaka YOKOTA 	int error;
120617b9080SKazutaka YOKOTA 	int i;
121617b9080SKazutaka YOKOTA 
122617b9080SKazutaka YOKOTA 	if (splash_decoder == decoder) {
123617b9080SKazutaka YOKOTA 		if ((error = splash_term(splash_adp)) != 0)
124617b9080SKazutaka YOKOTA 			return error;
125617b9080SKazutaka YOKOTA 	}
126617b9080SKazutaka YOKOTA 	for (i = 0; i < decoders; ++i) {
127617b9080SKazutaka YOKOTA 		if (decoder_set[i] == decoder) {
128617b9080SKazutaka YOKOTA 			decoder_set[i] = NULL;
129617b9080SKazutaka YOKOTA 			break;
130617b9080SKazutaka YOKOTA 		}
131617b9080SKazutaka YOKOTA 	}
132617b9080SKazutaka YOKOTA 	return 0;
133617b9080SKazutaka YOKOTA }
134617b9080SKazutaka YOKOTA 
135617b9080SKazutaka YOKOTA int
136617b9080SKazutaka YOKOTA splash_init(video_adapter_t *adp, int (*callback)(int))
137617b9080SKazutaka YOKOTA {
138617b9080SKazutaka YOKOTA 	int i;
139617b9080SKazutaka YOKOTA 
140617b9080SKazutaka YOKOTA 	splash_adp = adp;
141617b9080SKazutaka YOKOTA 	splash_callback = callback;
142617b9080SKazutaka YOKOTA 
143617b9080SKazutaka YOKOTA 	/* try registered decoders with this adapter and loaded image */
144617b9080SKazutaka YOKOTA 	splash_decoder = NULL;
145617b9080SKazutaka YOKOTA 	splash_find_image();
146617b9080SKazutaka YOKOTA 	if (splash_image_data == NULL)
147617b9080SKazutaka YOKOTA 		return 0;
148617b9080SKazutaka YOKOTA 	for (i = 0; i < decoders; ++i) {
149617b9080SKazutaka YOKOTA 		if (decoder_set[i] == NULL)
150617b9080SKazutaka YOKOTA 			continue;
151617b9080SKazutaka YOKOTA 		if (splash_test(decoder_set[i]) == 0)
152617b9080SKazutaka YOKOTA 			break;
153617b9080SKazutaka YOKOTA 	}
154617b9080SKazutaka YOKOTA 	return 0;
155617b9080SKazutaka YOKOTA }
156617b9080SKazutaka YOKOTA 
157617b9080SKazutaka YOKOTA int
158617b9080SKazutaka YOKOTA splash_term(video_adapter_t *adp)
159617b9080SKazutaka YOKOTA {
160617b9080SKazutaka YOKOTA 	int error = 0;
161617b9080SKazutaka YOKOTA 
162617b9080SKazutaka YOKOTA 	if (splash_decoder != NULL) {
163617b9080SKazutaka YOKOTA 		if (splash_callback != NULL)
164617b9080SKazutaka YOKOTA 			error = (*splash_callback)(SPLASH_TERM);
165617b9080SKazutaka YOKOTA 		if (error == 0)
166617b9080SKazutaka YOKOTA 			error = (*splash_decoder->term)(adp);
167617b9080SKazutaka YOKOTA 		if (error == 0)
168617b9080SKazutaka YOKOTA 			splash_decoder = NULL;
169617b9080SKazutaka YOKOTA 	}
170617b9080SKazutaka YOKOTA 	return error;
171617b9080SKazutaka YOKOTA }
172617b9080SKazutaka YOKOTA 
173617b9080SKazutaka YOKOTA int
174617b9080SKazutaka YOKOTA splash(video_adapter_t *adp, int on)
175617b9080SKazutaka YOKOTA {
176617b9080SKazutaka YOKOTA 	if (splash_decoder != NULL)
177617b9080SKazutaka YOKOTA 		return (*splash_decoder->splash)(adp, on);
178617b9080SKazutaka YOKOTA 	return ENODEV;
179617b9080SKazutaka YOKOTA }
180617b9080SKazutaka YOKOTA 
181617b9080SKazutaka YOKOTA #endif /* NSPLASH > 0 */
182