1 /* $NetBSD: lunafb.c,v 1.20 2009/03/16 23:11:11 dsl Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
34 __KERNEL_RCSID(0, "$NetBSD: lunafb.c,v 1.20 2009/03/16 23:11:11 dsl Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
39 #include <sys/device.h>
40 #include <sys/ioctl.h>
41 #include <sys/malloc.h>
45 #include <sys/errno.h>
48 #include <uvm/uvm_extern.h>
50 #include <dev/rcons/raster.h>
51 #include <dev/wscons/wsconsio.h>
52 #include <dev/wscons/wscons_raster.h>
53 #include <dev/wscons/wsdisplayvar.h>
55 #include <machine/cpu.h>
56 #include <machine/autoconf.h>
59 u_int8_t bt_addr
; /* map address register */
60 u_int8_t bt_cmap
; /* colormap data register */
64 u_int8_t bt_addr
; /* map address register */
66 u_int8_t bt_cmap
; /* colormap data register */
68 u_int8_t bt_ctrl
; /* control register */
70 u_int8_t bt_omap
; /* overlay (cursor) map register */
74 #define OMFB_RFCNT 0xB1000000 /* video h-origin/v-origin */
75 #define OMFB_PLANEMASK 0xB1040000 /* planemask register */
76 #define OMFB_FB_WADDR 0xB1080008 /* common plane */
77 #define OMFB_FB_RADDR 0xB10C0008 /* plane #0 */
78 #define OMFB_ROPFUNC 0xB12C0000 /* ROP function code */
79 #define OMFB_RAMDAC 0xC1100000 /* Bt454/Bt458 RAMDAC */
80 #define OMFB_SIZE (0xB1300000 - 0xB1080000 + PAGE_SIZE)
82 struct om_hwdevconfig
{
83 int dc_wid
; /* width of frame buffer */
84 int dc_ht
; /* height of frame buffer */
85 int dc_depth
; /* depth, bits per pixel */
86 int dc_rowbytes
; /* bytes in a FB scan line */
87 int dc_cmsize
; /* colormap size */
88 vaddr_t dc_videobase
; /* base of flat frame buffer */
89 struct raster dc_raster
; /* raster description */
90 struct rcons dc_rcons
; /* raster blitter control info */
95 u_int8_t r
[CMAP_SIZE
];
96 u_int8_t g
[CMAP_SIZE
];
97 u_int8_t b
[CMAP_SIZE
];
101 struct device sc_dev
; /* base device */
102 struct om_hwdevconfig
*sc_dc
; /* device configuration */
103 struct hwcmap sc_cmap
; /* software copy of colormap */
107 static int omgetcmap(struct omfb_softc
*, struct wsdisplay_cmap
*);
108 static int omsetcmap(struct omfb_softc
*, struct wsdisplay_cmap
*);
110 static struct om_hwdevconfig omfb_console_dc
;
111 static void omfb_getdevconfig(paddr_t
, struct om_hwdevconfig
*);
113 extern struct wsdisplay_emulops omfb_emulops
;
115 static struct wsscreen_descr omfb_stdscreen
= {
122 static const struct wsscreen_descr
*_omfb_scrlist
[] = {
126 static const struct wsscreen_list omfb_screenlist
= {
127 sizeof(_omfb_scrlist
) / sizeof(struct wsscreen_descr
*), _omfb_scrlist
130 static int omfbioctl(void *, void *, u_long
, void *, int,
132 static paddr_t
omfbmmap(void *, void *, off_t
, int);
133 static int omfb_alloc_screen(void *, const struct wsscreen_descr
*,
134 void **, int *, int *, long *);
135 static void omfb_free_screen(void *, void *);
136 static int omfb_show_screen(void *, void *, int,
137 void (*) (void *, int, int), void *);
139 static const struct wsdisplay_accessops omfb_accessops
= {
148 static int omfbmatch(struct device
*, struct cfdata
*, void *);
149 static void omfbattach(struct device
*, struct device
*, void *);
151 CFATTACH_DECL(fb
, sizeof(struct omfb_softc
),
152 omfbmatch
, omfbattach
, NULL
, NULL
);
153 extern struct cfdriver fb_cd
;
155 extern int hwplanemask
; /* hardware planemask; retrieved at boot */
157 static int omfb_console
;
158 int omfb_cnattach(void);
161 omfbmatch(struct device
*parent
, struct cfdata
*cf
, void *aux
)
163 struct mainbus_attach_args
*ma
= aux
;
165 if (strcmp(ma
->ma_name
, fb_cd
.cd_name
))
167 #if 0 /* XXX badaddr() bombs if no framebuffer is installed */
168 if (badaddr((void *)ma
->ma_addr
, 4))
171 if (hwplanemask
== 0)
178 omfbattach(struct device
*parent
, struct device
*self
, void *args
)
180 struct omfb_softc
*sc
= (struct omfb_softc
*)self
;
181 struct wsemuldisplaydev_attach_args waa
;
184 sc
->sc_dc
= &omfb_console_dc
;
188 sc
->sc_dc
= (struct om_hwdevconfig
*)
189 malloc(sizeof(struct om_hwdevconfig
), M_DEVBUF
, M_WAITOK
);
190 omfb_getdevconfig(OMFB_FB_WADDR
, sc
->sc_dc
);
192 printf(": %d x %d, %dbpp\n", sc
->sc_dc
->dc_wid
, sc
->sc_dc
->dc_ht
,
193 sc
->sc_dc
->dc_depth
);
195 #if 0 /* WHITE on BLACK */
197 memset(cm
, 255, sizeof(struct hwcmap
));
198 cm
->r
[0] = cm
->g
[0] = cm
->b
[0] = 0;
200 waa
.console
= omfb_console
;
201 waa
.scrdata
= &omfb_screenlist
;
202 waa
.accessops
= &omfb_accessops
;
203 waa
.accesscookie
= sc
;
205 config_found(self
, &waa
, wsemuldisplaydevprint
);
211 struct om_hwdevconfig
*dc
= &omfb_console_dc
;
214 omfb_getdevconfig(OMFB_FB_WADDR
, dc
);
215 (*omfb_emulops
.allocattr
)(&dc
->dc_rcons
, 0, 0, 0, &defattr
);
216 wsdisplay_cnattach(&omfb_stdscreen
, &dc
->dc_rcons
, 0, 0, defattr
);
222 omfbioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
224 struct omfb_softc
*sc
= v
;
225 struct om_hwdevconfig
*dc
= sc
->sc_dc
;
228 case WSDISPLAYIO_GTYPE
:
229 *(u_int
*)data
= 0x19990927;
232 case WSDISPLAYIO_GINFO
:
233 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
234 wsd_fbip
->height
= dc
->dc_ht
;
235 wsd_fbip
->width
= dc
->dc_wid
;
236 wsd_fbip
->depth
= dc
->dc_depth
;
237 wsd_fbip
->cmsize
= dc
->dc_cmsize
;
241 case WSDISPLAYIO_GETCMAP
:
242 return omgetcmap(sc
, (struct wsdisplay_cmap
*)data
);
244 case WSDISPLAYIO_PUTCMAP
:
245 return omsetcmap(sc
, (struct wsdisplay_cmap
*)data
);
247 case WSDISPLAYIO_SVIDEO
:
248 case WSDISPLAYIO_GVIDEO
:
249 case WSDISPLAYIO_GCURPOS
:
250 case WSDISPLAYIO_SCURPOS
:
251 case WSDISPLAYIO_GCURMAX
:
252 case WSDISPLAYIO_GCURSOR
:
253 case WSDISPLAYIO_SCURSOR
:
256 return (EPASSTHROUGH
);
260 * Return the address that would map the given device at the given
261 * offset, allowing for the given protection, or return -1 for error.
264 omfbmmap(void *v
, void *vs
, off_t offset
, int prot
)
266 struct omfb_softc
*sc
= v
;
268 if (offset
>= OMFB_SIZE
|| offset
< 0)
270 return m68k_btop(m68k_trunc_page(sc
->sc_dc
->dc_videobase
) + offset
);
274 omgetcmap(struct omfb_softc
*sc
, struct wsdisplay_cmap
*p
)
276 u_int index
= p
->index
, count
= p
->count
;
279 cmsize
= sc
->sc_dc
->dc_cmsize
;
280 if (index
>= cmsize
|| count
> cmsize
- index
)
283 error
= copyout(&sc
->sc_cmap
.r
[index
], p
->red
, count
);
286 error
= copyout(&sc
->sc_cmap
.g
[index
], p
->green
, count
);
289 error
= copyout(&sc
->sc_cmap
.b
[index
], p
->blue
, count
);
294 omsetcmap(struct omfb_softc
*sc
, struct wsdisplay_cmap
*p
)
297 u_int index
= p
->index
, count
= p
->count
;
298 int cmsize
, i
, error
;
300 cmsize
= sc
->sc_dc
->dc_cmsize
;
301 if (index
>= cmsize
|| (index
+ count
) > cmsize
)
304 error
= copyin(p
->red
, &cmap
.r
[index
], count
);
307 error
= copyin(p
->green
, &cmap
.g
[index
], count
);
310 error
= copyin(p
->blue
, &cmap
.b
[index
], count
);
314 memcpy(&sc
->sc_cmap
.r
[index
], &cmap
.r
[index
], count
);
315 memcpy(&sc
->sc_cmap
.g
[index
], &cmap
.g
[index
], count
);
316 memcpy(&sc
->sc_cmap
.b
[index
], &cmap
.b
[index
], count
);
317 if (hwplanemask
== 0x0f) {
318 struct bt454
*odac
= (struct bt454
*)OMFB_RAMDAC
;
319 odac
->bt_addr
= index
;
320 for (i
= index
; i
< count
; i
++) {
321 odac
->bt_cmap
= sc
->sc_cmap
.r
[i
];
322 odac
->bt_cmap
= sc
->sc_cmap
.g
[i
];
323 odac
->bt_cmap
= sc
->sc_cmap
.b
[i
];
326 else if (hwplanemask
== 0xff) {
327 struct bt458
*ndac
= (struct bt458
*)OMFB_RAMDAC
;
328 ndac
->bt_addr
= index
;
329 for (i
= index
; i
< count
; i
++) {
330 ndac
->bt_cmap
= sc
->sc_cmap
.r
[i
];
331 ndac
->bt_cmap
= sc
->sc_cmap
.g
[i
];
332 ndac
->bt_cmap
= sc
->sc_cmap
.b
[i
];
339 omfb_getdevconfig(paddr_t paddr
, struct om_hwdevconfig
*dc
)
345 struct { short h
, v
; } p
;
349 switch (hwplanemask
) {
351 bpp
= 8; /* XXX check monochrome bit in DIPSW */
355 bpp
= 4; /* XXX check monochrome bit in DIPSW */
364 dc
->dc_rowbytes
= 2048 / 8;
365 dc
->dc_cmsize
= (bpp
== 1) ? 0 : 1 << bpp
;
366 dc
->dc_videobase
= paddr
;
368 #if 0 /* WHITE on BLACK XXX experiment resulted in WHITE on SKYBLUE... */
369 if (hwplanemask
== 0x0f) {
370 /* XXX Need Bt454 initialization */
371 struct bt454
*odac
= (struct bt454
*)OMFB_RAMDAC
;
376 for (i
= 1; i
< 16; i
++) {
382 else if (hwplanemask
== 0xff) {
383 struct bt458
*ndac
= (struct bt458
*)OMFB_RAMDAC
;
385 ndac
->bt_addr
= 0x04;
386 ndac
->bt_ctrl
= 0xff; /* all planes will be read */
387 ndac
->bt_ctrl
= 0x00; /* all planes have non-blink */
388 ndac
->bt_ctrl
= 0x43; /* pallete enabled, ovly plane */
389 ndac
->bt_ctrl
= 0x00; /* no test mode */
394 for (i
= 1; i
< 256; i
++) {
402 /* adjust h/v orgin on screen */
405 *(u_int32_t
*)OMFB_RFCNT
= rfcnt
.u
; /* single write of 0x007ffe6 */
407 /* clear the screen */
408 *(u_int32_t
*)OMFB_PLANEMASK
= 0xff;
409 ((u_int32_t
*)OMFB_ROPFUNC
)[5] = ~0; /* ROP copy */
410 for (i
= 0; i
< dc
->dc_ht
* dc
->dc_rowbytes
/sizeof(u_int32_t
); i
++)
411 *((u_int32_t
*)dc
->dc_videobase
+ i
) = 0;
412 *(u_int32_t
*)OMFB_PLANEMASK
= 0x01;
414 /* initialize the raster */
415 rap
= &dc
->dc_raster
;
416 rap
->width
= dc
->dc_wid
;
417 rap
->height
= dc
->dc_ht
;
418 rap
->depth
= dc
->dc_depth
;
419 rap
->linelongs
= dc
->dc_rowbytes
/ sizeof(u_int32_t
);
420 rap
->pixels
= (u_int32_t
*)dc
->dc_videobase
;
422 /* initialize the raster console blitter */
425 rcp
->rc_crow
= rcp
->rc_ccol
= -1;
426 rcp
->rc_crowp
= &rcp
->rc_crow
;
427 rcp
->rc_ccolp
= &rcp
->rc_ccol
;
428 rcons_init(rcp
, 34, 80);
430 omfb_stdscreen
.nrows
= dc
->dc_rcons
.rc_maxrow
;
431 omfb_stdscreen
.ncols
= dc
->dc_rcons
.rc_maxcol
;
435 omfb_alloc_screen(void *v
, const struct wsscreen_descr
*type
, void **cookiep
, int *curxp
, int *curyp
, long *attrp
)
437 struct omfb_softc
*sc
= v
;
440 if (sc
->nscreens
> 0)
443 *cookiep
= &sc
->sc_dc
->dc_rcons
; /* one and only for now */
446 (*omfb_emulops
.allocattr
)(&sc
->sc_dc
->dc_rcons
, 0, 0, 0, &defattr
);
453 omfb_free_screen(void *v
, void *cookie
)
455 struct omfb_softc
*sc
= v
;
457 if (sc
->sc_dc
== &omfb_console_dc
)
458 panic("omfb_free_screen: console");
464 omfb_show_screen(void *v
, void *cookie
, int waitok
, void (*cb
)(void *, int, int), void *cbarg
)