1433d6423SLionel Sambuc #include <minix/fb.h>
2433d6423SLionel Sambuc #include <minix/chardriver.h>
3433d6423SLionel Sambuc #include <minix/drivers.h>
4433d6423SLionel Sambuc #include <minix/ds.h>
5433d6423SLionel Sambuc #include <minix/sysutil.h>
6433d6423SLionel Sambuc #include <minix/type.h>
7433d6423SLionel Sambuc #include <minix/vm.h>
8433d6423SLionel Sambuc #include <sys/ioc_fb.h>
9433d6423SLionel Sambuc #include <assert.h>
10433d6423SLionel Sambuc #include <sys/ioctl.h>
11433d6423SLionel Sambuc #include <sys/mman.h>
12433d6423SLionel Sambuc #include <stdio.h>
13433d6423SLionel Sambuc #include <stdlib.h>
14433d6423SLionel Sambuc #include <stdint.h>
15433d6423SLionel Sambuc #include <dev/videomode/videomode.h>
16433d6423SLionel Sambuc #include <dev/videomode/edidvar.h>
17433d6423SLionel Sambuc #include <dev/videomode/edidreg.h>
18433d6423SLionel Sambuc
19433d6423SLionel Sambuc #include "logos.h"
20433d6423SLionel Sambuc #include "fb_edid.h"
21433d6423SLionel Sambuc #include "fb.h"
22433d6423SLionel Sambuc
23433d6423SLionel Sambuc /*
24433d6423SLionel Sambuc * Function prototypes for the fb driver.
25433d6423SLionel Sambuc */
26433d6423SLionel Sambuc static int fb_open(devminor_t minor, int access, endpoint_t user_endpt);
27433d6423SLionel Sambuc static int fb_close(devminor_t minor);
28433d6423SLionel Sambuc static ssize_t fb_read(devminor_t minor, u64_t pos, endpoint_t ep,
29433d6423SLionel Sambuc cp_grant_id_t gid, size_t size, int flags, cdev_id_t id);
30433d6423SLionel Sambuc static ssize_t fb_write(devminor_t minor, u64_t pos, endpoint_t ep,
31433d6423SLionel Sambuc cp_grant_id_t gid, size_t size, int flags, cdev_id_t id);
32433d6423SLionel Sambuc static int fb_ioctl(devminor_t minor, unsigned long request, endpoint_t ep,
33433d6423SLionel Sambuc cp_grant_id_t gid, int flags, endpoint_t user_ep, cdev_id_t id);
34433d6423SLionel Sambuc static void paint_bootlogo(int minor);
35433d6423SLionel Sambuc static void paint_restartlogo(int minor);
36433d6423SLionel Sambuc static void paint_centered(int minor, char *data, int width, int height);
37433d6423SLionel Sambuc static int do_get_varscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid);
38433d6423SLionel Sambuc static int do_put_varscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid);
39433d6423SLionel Sambuc static int do_get_fixscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid);
40433d6423SLionel Sambuc static int do_pan_display(int minor, endpoint_t ep, cp_grant_id_t gid);
41433d6423SLionel Sambuc static int keep_displaying_restarted(void);
42433d6423SLionel Sambuc
43433d6423SLionel Sambuc /* Entry points to the fb driver. */
44433d6423SLionel Sambuc static struct chardriver fb_tab =
45433d6423SLionel Sambuc {
46433d6423SLionel Sambuc .cdr_open = fb_open,
47433d6423SLionel Sambuc .cdr_close = fb_close,
48433d6423SLionel Sambuc .cdr_read = fb_read,
49433d6423SLionel Sambuc .cdr_write = fb_write,
50433d6423SLionel Sambuc .cdr_ioctl = fb_ioctl
51433d6423SLionel Sambuc };
52433d6423SLionel Sambuc
53433d6423SLionel Sambuc /** Represents the /dev/fb device. */
54433d6423SLionel Sambuc static int has_restarted = 0;
55433d6423SLionel Sambuc static u64_t has_restarted_t1, has_restarted_t2;
56433d6423SLionel Sambuc
57433d6423SLionel Sambuc static int open_counter[FB_DEV_NR]; /* Open count */
58433d6423SLionel Sambuc
59433d6423SLionel Sambuc static int
fb_open(devminor_t minor,int UNUSED (access),endpoint_t UNUSED (user_endpt))60433d6423SLionel Sambuc fb_open(devminor_t minor, int UNUSED(access), endpoint_t UNUSED(user_endpt))
61433d6423SLionel Sambuc {
62433d6423SLionel Sambuc int r;
63433d6423SLionel Sambuc static int initialized = 0;
64433d6423SLionel Sambuc static struct edid_info info;
65433d6423SLionel Sambuc static struct edid_info *infop = NULL;
66433d6423SLionel Sambuc
67433d6423SLionel Sambuc if (minor < 0 || minor >= FB_DEV_NR) return ENXIO;
68433d6423SLionel Sambuc
69433d6423SLionel Sambuc if (!initialized) {
70433d6423SLionel Sambuc r = fb_edid_read(minor, &info);
71433d6423SLionel Sambuc infop = (r == 0) ? &info : NULL;
72433d6423SLionel Sambuc }
73433d6423SLionel Sambuc
74433d6423SLionel Sambuc if (arch_fb_init(minor, infop) == OK) {
75433d6423SLionel Sambuc open_counter[minor]++;
76433d6423SLionel Sambuc if (!initialized) {
77433d6423SLionel Sambuc if (has_restarted) {
78433d6423SLionel Sambuc read_frclock_64(&has_restarted_t1);
79433d6423SLionel Sambuc paint_restartlogo(minor);
80433d6423SLionel Sambuc } else {
81433d6423SLionel Sambuc paint_bootlogo(minor);
82433d6423SLionel Sambuc }
83433d6423SLionel Sambuc initialized = 1;
84433d6423SLionel Sambuc }
85433d6423SLionel Sambuc return OK;
86433d6423SLionel Sambuc }
87433d6423SLionel Sambuc return ENXIO;
88433d6423SLionel Sambuc }
89433d6423SLionel Sambuc
90433d6423SLionel Sambuc static int
fb_close(devminor_t minor)91433d6423SLionel Sambuc fb_close(devminor_t minor)
92433d6423SLionel Sambuc {
93433d6423SLionel Sambuc if (minor < 0 || minor >= FB_DEV_NR) return ENXIO;
94433d6423SLionel Sambuc assert(open_counter[minor] > 0);
95433d6423SLionel Sambuc open_counter[minor]--;
96433d6423SLionel Sambuc return OK;
97433d6423SLionel Sambuc }
98433d6423SLionel Sambuc
99433d6423SLionel Sambuc static ssize_t
fb_read(devminor_t minor,u64_t pos,endpoint_t ep,cp_grant_id_t gid,size_t size,int UNUSED (flags),cdev_id_t UNUSED (id))100433d6423SLionel Sambuc fb_read(devminor_t minor, u64_t pos, endpoint_t ep, cp_grant_id_t gid,
101433d6423SLionel Sambuc size_t size, int UNUSED(flags), cdev_id_t UNUSED(id))
102433d6423SLionel Sambuc {
103433d6423SLionel Sambuc struct device dev;
104433d6423SLionel Sambuc int r;
105433d6423SLionel Sambuc
106433d6423SLionel Sambuc if (minor < 0 || minor >= FB_DEV_NR) return ENXIO;
107433d6423SLionel Sambuc assert(open_counter[minor] > 0);
108433d6423SLionel Sambuc
109433d6423SLionel Sambuc arch_get_device(minor, &dev);
110433d6423SLionel Sambuc
111433d6423SLionel Sambuc if (size == 0 || pos >= dev.dv_size) return 0;
112433d6423SLionel Sambuc if (pos + size > dev.dv_size)
113433d6423SLionel Sambuc size = (size_t)(dev.dv_size - pos);
114433d6423SLionel Sambuc
115433d6423SLionel Sambuc r = sys_safecopyto(ep, gid, 0, (vir_bytes)(dev.dv_base + (size_t)pos),
116433d6423SLionel Sambuc size);
117433d6423SLionel Sambuc
118433d6423SLionel Sambuc return (r != OK) ? r : size;
119433d6423SLionel Sambuc }
120433d6423SLionel Sambuc
121433d6423SLionel Sambuc static int
fb_ioctl(devminor_t minor,unsigned long request,endpoint_t ep,cp_grant_id_t gid,int UNUSED (flags),endpoint_t UNUSED (user_ep),cdev_id_t UNUSED (id))122433d6423SLionel Sambuc fb_ioctl(devminor_t minor, unsigned long request, endpoint_t ep,
123433d6423SLionel Sambuc cp_grant_id_t gid, int UNUSED(flags), endpoint_t UNUSED(user_ep),
124433d6423SLionel Sambuc cdev_id_t UNUSED(id))
125433d6423SLionel Sambuc {
126433d6423SLionel Sambuc /* Process I/O control requests */
127433d6423SLionel Sambuc int r;
128433d6423SLionel Sambuc
129433d6423SLionel Sambuc if (minor < 0 || minor >= FB_DEV_NR) return ENXIO;
130433d6423SLionel Sambuc
131433d6423SLionel Sambuc switch(request) {
132433d6423SLionel Sambuc case FBIOGET_VSCREENINFO:
133433d6423SLionel Sambuc r = do_get_varscreeninfo(minor, ep, gid);
134433d6423SLionel Sambuc return r;
135433d6423SLionel Sambuc case FBIOPUT_VSCREENINFO:
136433d6423SLionel Sambuc r = do_put_varscreeninfo(minor, ep, gid);
137433d6423SLionel Sambuc return r;
138433d6423SLionel Sambuc case FBIOGET_FSCREENINFO:
139433d6423SLionel Sambuc r = do_get_fixscreeninfo(minor, ep, gid);
140433d6423SLionel Sambuc return r;
141433d6423SLionel Sambuc case FBIOPAN_DISPLAY:
142433d6423SLionel Sambuc r = do_pan_display(minor, ep, gid);
143433d6423SLionel Sambuc return r;
144433d6423SLionel Sambuc }
145433d6423SLionel Sambuc
146433d6423SLionel Sambuc return ENOTTY;
147433d6423SLionel Sambuc }
148433d6423SLionel Sambuc
149433d6423SLionel Sambuc static int
do_get_varscreeninfo(int minor,endpoint_t ep,cp_grant_id_t gid)150433d6423SLionel Sambuc do_get_varscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid)
151433d6423SLionel Sambuc {
152433d6423SLionel Sambuc int r;
153433d6423SLionel Sambuc struct fb_var_screeninfo fbvs;
154433d6423SLionel Sambuc
155433d6423SLionel Sambuc if ((r = arch_get_varscreeninfo(minor, &fbvs)) == OK) {
156433d6423SLionel Sambuc r = sys_safecopyto(ep, gid, 0, (vir_bytes) &fbvs, sizeof(fbvs));
157433d6423SLionel Sambuc }
158433d6423SLionel Sambuc
159433d6423SLionel Sambuc return r;
160433d6423SLionel Sambuc }
161433d6423SLionel Sambuc
162433d6423SLionel Sambuc static int
do_put_varscreeninfo(int minor,endpoint_t ep,cp_grant_id_t gid)163433d6423SLionel Sambuc do_put_varscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid)
164433d6423SLionel Sambuc {
165433d6423SLionel Sambuc int r;
166433d6423SLionel Sambuc struct fb_var_screeninfo fbvs_copy;
167433d6423SLionel Sambuc
168433d6423SLionel Sambuc if (has_restarted && keep_displaying_restarted()) {
169433d6423SLionel Sambuc return EAGAIN;
170433d6423SLionel Sambuc }
171433d6423SLionel Sambuc
172433d6423SLionel Sambuc if ((r = sys_safecopyfrom(ep, gid, 0, (vir_bytes) &fbvs_copy,
173433d6423SLionel Sambuc sizeof(fbvs_copy))) != OK) {
174433d6423SLionel Sambuc return r;
175433d6423SLionel Sambuc }
176433d6423SLionel Sambuc
177433d6423SLionel Sambuc return arch_put_varscreeninfo(minor, &fbvs_copy);
178433d6423SLionel Sambuc }
179433d6423SLionel Sambuc
180433d6423SLionel Sambuc static int
do_pan_display(int minor,endpoint_t ep,cp_grant_id_t gid)181433d6423SLionel Sambuc do_pan_display(int minor, endpoint_t ep, cp_grant_id_t gid)
182433d6423SLionel Sambuc {
183433d6423SLionel Sambuc int r;
184433d6423SLionel Sambuc struct fb_var_screeninfo fbvs_copy;
185433d6423SLionel Sambuc
186433d6423SLionel Sambuc if (has_restarted && keep_displaying_restarted()) {
187433d6423SLionel Sambuc return EAGAIN;
188433d6423SLionel Sambuc }
189433d6423SLionel Sambuc
190433d6423SLionel Sambuc if ((r = sys_safecopyfrom(ep, gid, 0, (vir_bytes) &fbvs_copy,
191433d6423SLionel Sambuc sizeof(fbvs_copy))) != OK) {
192433d6423SLionel Sambuc return r;
193433d6423SLionel Sambuc }
194433d6423SLionel Sambuc
195433d6423SLionel Sambuc return arch_pan_display(minor, &fbvs_copy);
196433d6423SLionel Sambuc }
197433d6423SLionel Sambuc
198433d6423SLionel Sambuc static int
do_get_fixscreeninfo(int minor,endpoint_t ep,cp_grant_id_t gid)199433d6423SLionel Sambuc do_get_fixscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid)
200433d6423SLionel Sambuc {
201433d6423SLionel Sambuc int r;
202433d6423SLionel Sambuc struct fb_fix_screeninfo fbfs;
203433d6423SLionel Sambuc
204433d6423SLionel Sambuc if ((r = arch_get_fixscreeninfo(minor, &fbfs)) == OK) {
205433d6423SLionel Sambuc r = sys_safecopyto(ep, gid, 0, (vir_bytes) &fbfs, sizeof(fbfs));
206433d6423SLionel Sambuc }
207433d6423SLionel Sambuc
208433d6423SLionel Sambuc return r;
209433d6423SLionel Sambuc }
210433d6423SLionel Sambuc
211433d6423SLionel Sambuc static ssize_t
fb_write(devminor_t minor,u64_t pos,endpoint_t ep,cp_grant_id_t gid,size_t size,int UNUSED (flags),cdev_id_t UNUSED (id))212433d6423SLionel Sambuc fb_write(devminor_t minor, u64_t pos, endpoint_t ep, cp_grant_id_t gid,
213433d6423SLionel Sambuc size_t size, int UNUSED(flags), cdev_id_t UNUSED(id))
214433d6423SLionel Sambuc {
215433d6423SLionel Sambuc struct device dev;
216433d6423SLionel Sambuc int r;
217433d6423SLionel Sambuc
218433d6423SLionel Sambuc if (minor < 0 || minor >= FB_DEV_NR) return ENXIO;
219433d6423SLionel Sambuc assert(open_counter[minor] > 0);
220433d6423SLionel Sambuc
221433d6423SLionel Sambuc if (has_restarted && keep_displaying_restarted())
222433d6423SLionel Sambuc return EAGAIN;
223433d6423SLionel Sambuc
224433d6423SLionel Sambuc arch_get_device(minor, &dev);
225433d6423SLionel Sambuc
226433d6423SLionel Sambuc if (size == 0 || pos >= dev.dv_size) return 0;
227433d6423SLionel Sambuc if (pos + size > dev.dv_size)
228433d6423SLionel Sambuc size = (size_t)(dev.dv_size - pos);
229433d6423SLionel Sambuc
230433d6423SLionel Sambuc r = sys_safecopyfrom(ep, gid, 0,
231433d6423SLionel Sambuc (vir_bytes)(dev.dv_base + (size_t)pos), size);
232433d6423SLionel Sambuc
233433d6423SLionel Sambuc return (r != OK) ? r : size;
234433d6423SLionel Sambuc }
235433d6423SLionel Sambuc
236433d6423SLionel Sambuc static int
sef_cb_lu_state_save(int UNUSED (result),int UNUSED (flags))237*e1f889d2SCristiano Giuffrida sef_cb_lu_state_save(int UNUSED(result), int UNUSED(flags))
238*e1f889d2SCristiano Giuffrida {
239433d6423SLionel Sambuc /* Save the state. */
240433d6423SLionel Sambuc ds_publish_u32("open_counter", open_counter[0], DSF_OVERWRITE);
241433d6423SLionel Sambuc
242433d6423SLionel Sambuc return OK;
243433d6423SLionel Sambuc }
244433d6423SLionel Sambuc
245433d6423SLionel Sambuc static int
lu_state_restore()246433d6423SLionel Sambuc lu_state_restore() {
247433d6423SLionel Sambuc /* Restore the state. */
248433d6423SLionel Sambuc u32_t value;
249433d6423SLionel Sambuc
250433d6423SLionel Sambuc ds_retrieve_u32("open_counter", &value);
251433d6423SLionel Sambuc ds_delete_u32("open_counter");
252433d6423SLionel Sambuc open_counter[0] = (int) value;
253433d6423SLionel Sambuc
254433d6423SLionel Sambuc return OK;
255433d6423SLionel Sambuc }
256433d6423SLionel Sambuc
257433d6423SLionel Sambuc static int
sef_cb_init(int type,sef_init_info_t * UNUSED (info))258433d6423SLionel Sambuc sef_cb_init(int type, sef_init_info_t *UNUSED(info))
259433d6423SLionel Sambuc {
260433d6423SLionel Sambuc /* Initialize the fb driver. */
261433d6423SLionel Sambuc int do_announce_driver = TRUE;
262433d6423SLionel Sambuc
263433d6423SLionel Sambuc open_counter[0] = 0;
264433d6423SLionel Sambuc switch(type) {
265433d6423SLionel Sambuc case SEF_INIT_FRESH:
266433d6423SLionel Sambuc printf("framebuffer fresh: pid %d\n", getpid());
267433d6423SLionel Sambuc break;
268433d6423SLionel Sambuc
269433d6423SLionel Sambuc case SEF_INIT_LU:
270433d6423SLionel Sambuc /* Restore the state. */
271433d6423SLionel Sambuc lu_state_restore();
272433d6423SLionel Sambuc do_announce_driver = FALSE;
273433d6423SLionel Sambuc
274433d6423SLionel Sambuc printf("framebuffer: I'm a new version!\n");
275433d6423SLionel Sambuc break;
276433d6423SLionel Sambuc
277433d6423SLionel Sambuc case SEF_INIT_RESTART:
278433d6423SLionel Sambuc printf("framebuffer restarted: pid %d\n", getpid());
279433d6423SLionel Sambuc has_restarted = 1;
280433d6423SLionel Sambuc break;
281433d6423SLionel Sambuc }
282433d6423SLionel Sambuc
283433d6423SLionel Sambuc /* Announce we are up when necessary. */
284433d6423SLionel Sambuc if (do_announce_driver) {
285433d6423SLionel Sambuc chardriver_announce();
286433d6423SLionel Sambuc }
287433d6423SLionel Sambuc
288433d6423SLionel Sambuc /* Initialization completed successfully. */
289433d6423SLionel Sambuc return OK;
290433d6423SLionel Sambuc }
291433d6423SLionel Sambuc
292*e1f889d2SCristiano Giuffrida static void
sef_local_startup()293*e1f889d2SCristiano Giuffrida sef_local_startup()
294*e1f889d2SCristiano Giuffrida {
295*e1f889d2SCristiano Giuffrida /* Register init callbacks. Use the same function for all event types */
296*e1f889d2SCristiano Giuffrida sef_setcb_init_fresh(sef_cb_init);
297*e1f889d2SCristiano Giuffrida sef_setcb_init_lu(sef_cb_init);
298*e1f889d2SCristiano Giuffrida sef_setcb_init_restart(sef_cb_init);
299*e1f889d2SCristiano Giuffrida
300*e1f889d2SCristiano Giuffrida /* Register live update callbacks */
301*e1f889d2SCristiano Giuffrida sef_setcb_lu_state_save(sef_cb_lu_state_save);
302*e1f889d2SCristiano Giuffrida
303*e1f889d2SCristiano Giuffrida /* Let SEF perform startup. */
304*e1f889d2SCristiano Giuffrida sef_startup();
305*e1f889d2SCristiano Giuffrida }
306*e1f889d2SCristiano Giuffrida
307433d6423SLionel Sambuc int
main(int argc,char * argv[])308433d6423SLionel Sambuc main(int argc, char *argv[])
309433d6423SLionel Sambuc {
310433d6423SLionel Sambuc env_setargs(argc, argv);
311433d6423SLionel Sambuc fb_edid_args_parse();
312433d6423SLionel Sambuc
313433d6423SLionel Sambuc sef_local_startup();
314433d6423SLionel Sambuc chardriver_task(&fb_tab);
315433d6423SLionel Sambuc return OK;
316433d6423SLionel Sambuc }
317433d6423SLionel Sambuc
318433d6423SLionel Sambuc static int
keep_displaying_restarted()319433d6423SLionel Sambuc keep_displaying_restarted()
320433d6423SLionel Sambuc {
321433d6423SLionel Sambuc u64_t delta;
322433d6423SLionel Sambuc u32_t micro_delta;
323433d6423SLionel Sambuc
324433d6423SLionel Sambuc read_frclock_64(&has_restarted_t2);
325433d6423SLionel Sambuc delta = delta_frclock_64(has_restarted_t1, has_restarted_t2);
326433d6423SLionel Sambuc micro_delta = frclock_64_to_micros(delta);
327433d6423SLionel Sambuc
328433d6423SLionel Sambuc #define DISPLAY_1SEC 1000000 /* 1 second in microseconds */
329433d6423SLionel Sambuc if (micro_delta < DISPLAY_1SEC) {
330433d6423SLionel Sambuc return 1;
331433d6423SLionel Sambuc }
332433d6423SLionel Sambuc
333433d6423SLionel Sambuc has_restarted = 0;
334433d6423SLionel Sambuc return 0;
335433d6423SLionel Sambuc }
336433d6423SLionel Sambuc
337433d6423SLionel Sambuc static void
paint_bootlogo(int minor)338433d6423SLionel Sambuc paint_bootlogo(int minor)
339433d6423SLionel Sambuc {
340433d6423SLionel Sambuc paint_centered(minor, bootlogo_data, bootlogo_width, bootlogo_height);
341433d6423SLionel Sambuc }
342433d6423SLionel Sambuc
343433d6423SLionel Sambuc static void
paint_restartlogo(int minor)344433d6423SLionel Sambuc paint_restartlogo(int minor)
345433d6423SLionel Sambuc {
346433d6423SLionel Sambuc paint_centered(minor, restartlogo_data, restartlogo_width,
347433d6423SLionel Sambuc restartlogo_height);
348433d6423SLionel Sambuc }
349433d6423SLionel Sambuc
350433d6423SLionel Sambuc static void
paint_centered(int minor,char * data,int width,int height)351433d6423SLionel Sambuc paint_centered(int minor, char *data, int width, int height)
352433d6423SLionel Sambuc {
353433d6423SLionel Sambuc u8_t pixel[3];
354433d6423SLionel Sambuc u32_t i, min_x, min_y, max_x, max_y, x_painted = 0, rows = 0;
355433d6423SLionel Sambuc int r, bytespp;
356433d6423SLionel Sambuc struct device dev;
357433d6423SLionel Sambuc struct fb_var_screeninfo fbvs;
358433d6423SLionel Sambuc
359433d6423SLionel Sambuc /* Put display in a known state to simplify positioning code below */
360433d6423SLionel Sambuc if ((r = arch_get_varscreeninfo(minor, &fbvs)) != OK) {
361433d6423SLionel Sambuc printf("fb: unable to get screen info: %d\n", r);
362433d6423SLionel Sambuc }
363433d6423SLionel Sambuc fbvs.yoffset = 0;
364433d6423SLionel Sambuc if ((r = arch_pan_display(minor, &fbvs)) != OK) {
365433d6423SLionel Sambuc printf("fb: unable to pan display: %d\n", r);
366433d6423SLionel Sambuc }
367433d6423SLionel Sambuc
368433d6423SLionel Sambuc arch_get_device(minor, &dev);
369433d6423SLionel Sambuc
370433d6423SLionel Sambuc /* Paint on a white canvas */
371433d6423SLionel Sambuc bytespp = fbvs.bits_per_pixel / 8;
372433d6423SLionel Sambuc for (i = 0; i < fbvs.xres * fbvs.yres * bytespp; i+= bytespp)
373433d6423SLionel Sambuc *((u32_t *)((u32_t) dev.dv_base + i)) = 0x00FFFFFF;
374433d6423SLionel Sambuc
375433d6423SLionel Sambuc /* First seek to start */
376433d6423SLionel Sambuc min_x = fbvs.xres / 2 - width / 2;
377433d6423SLionel Sambuc max_x = fbvs.xres / 2 + width / 2;
378433d6423SLionel Sambuc min_y = fbvs.yres / 2 - height / 2;
379433d6423SLionel Sambuc max_y = fbvs.yres / 2 + height / 2;
380433d6423SLionel Sambuc i = min_x * fbvs.xres + min_y;
381433d6423SLionel Sambuc
382433d6423SLionel Sambuc /* Add the image data */
383433d6423SLionel Sambuc for (i = ((min_y * fbvs.xres) + min_x) * bytespp; rows < height;) {
384433d6423SLionel Sambuc GET_PIXEL(data, pixel);
385433d6423SLionel Sambuc
386433d6423SLionel Sambuc ((unsigned char *)((u32_t) dev.dv_base + i))[0] = pixel[2];
387433d6423SLionel Sambuc ((unsigned char *)((u32_t) dev.dv_base + i))[1] = pixel[1];
388433d6423SLionel Sambuc ((unsigned char *)((u32_t) dev.dv_base + i))[2] = pixel[0];
389433d6423SLionel Sambuc ((unsigned char *)((u32_t) dev.dv_base + i))[3] = 0;
390433d6423SLionel Sambuc
391433d6423SLionel Sambuc x_painted++;/* Keep tab of how many row pixels we've painted */
392433d6423SLionel Sambuc if (x_painted == width) {
393433d6423SLionel Sambuc /* We've reached the end of the row, carriage return
394433d6423SLionel Sambuc * and go to next line.
395433d6423SLionel Sambuc */
396433d6423SLionel Sambuc x_painted = 0;
397433d6423SLionel Sambuc rows++;
398433d6423SLionel Sambuc i = (((min_y + rows) * fbvs.xres) + min_x) * 4;
399433d6423SLionel Sambuc } else {
400433d6423SLionel Sambuc i += 4;
401433d6423SLionel Sambuc }
402433d6423SLionel Sambuc }
403433d6423SLionel Sambuc }
404433d6423SLionel Sambuc
405