1 /* $NetBSD: xafb.c,v 1.14 2007/03/04 06:00:26 christos Exp $ */
4 * Copyright (c) 2000 Tsubai Masanari. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /* "xa" frame buffer driver. Currently supports 1280x1024x8 only. */
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: xafb.c,v 1.14 2007/03/04 06:00:26 christos Exp $");
34 #include <sys/param.h>
36 #include <sys/device.h>
37 #include <sys/ioctl.h>
38 #include <sys/malloc.h>
39 #include <sys/systm.h>
41 #include <uvm/uvm_extern.h>
43 #include <machine/adrsmap.h>
44 #include <machine/apcall.h>
46 #include <machine/wsconsio.h>
47 #include <dev/wscons/wsdisplayvar.h>
48 #include <dev/rasops/rasops.h>
50 #include <newsmips/apbus/apbusvar.h>
54 volatile uint32_t index
;
56 volatile uint32_t zero
;
60 volatile uint32_t rgb
;
63 struct xafb_devconfig
{
64 uint8_t *dc_fbbase
; /* VRAM base address */
65 paddr_t dc_fbpaddr
; /* VRAM physical address */
66 struct xafb_reg
*dc_reg
; /* register address */
67 struct rasops_info dc_ri
;
72 struct xafb_devconfig
*sc_dc
;
74 uint8_t sc_cmap_red
[256];
75 uint8_t sc_cmap_green
[256];
76 uint8_t sc_cmap_blue
[256];
79 int xafb_match(device_t
, cfdata_t
, void *);
80 void xafb_attach(device_t
, device_t
, void *);
82 int xafb_common_init(struct xafb_devconfig
*);
83 int xafb_is_console(void);
85 int xafb_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
86 paddr_t
xafb_mmap(void *, void *, off_t
, int);
87 int xafb_alloc_screen(void *, const struct wsscreen_descr
*, void **, int *,
89 void xafb_free_screen(void *, void *);
90 int xafb_show_screen(void *, void *, int, void (*) (void *, int, int), void *);
92 int xafb_cnattach(void);
93 int xafb_getcmap(struct xafb_softc
*, struct wsdisplay_cmap
*);
94 int xafb_putcmap(struct xafb_softc
*, struct wsdisplay_cmap
*);
96 static inline void xafb_setcolor(struct xafb_devconfig
*, int, int, int, int);
98 CFATTACH_DECL_NEW(xafb
, sizeof(struct xafb_softc
),
99 xafb_match
, xafb_attach
, NULL
, NULL
);
101 struct xafb_devconfig xafb_console_dc
;
103 struct wsdisplay_accessops xafb_accessops
= {
112 struct wsscreen_descr xafb_stdscreen
= {
120 const struct wsscreen_descr
*xafb_scrlist
[] = {
124 struct wsscreen_list xafb_screenlist
= {
125 __arraycount(xafb_scrlist
), xafb_scrlist
129 xafb_match(device_t parent
, cfdata_t cf
, void *aux
)
131 struct apbus_attach_args
*apa
= aux
;
133 if (strcmp(apa
->apa_name
, "xa") != 0)
140 xafb_attach(device_t parent
, device_t self
, void *aux
)
142 struct xafb_softc
*sc
= device_private(self
);
143 struct apbus_attach_args
*apa
= aux
;
144 struct wsemuldisplaydev_attach_args wsa
;
145 struct xafb_devconfig
*dc
;
146 struct rasops_info
*ri
;
150 console
= xafb_is_console();
153 dc
= &xafb_console_dc
;
157 dc
= malloc(sizeof(struct xafb_devconfig
), M_DEVBUF
,
159 dc
->dc_fbpaddr
= (paddr_t
)0x10000000;
160 dc
->dc_fbbase
= (void *)MIPS_PHYS_TO_KSEG1(dc
->dc_fbpaddr
);
161 dc
->dc_reg
= (void *)(apa
->apa_hwbase
+ 0x3000);
162 if (xafb_common_init(dc
) != 0) {
163 aprint_error(": couldn't initialize device\n");
170 (*ri
->ri_ops
.eraserows
)(ri
, 0, ri
->ri_rows
, 0);
174 for (i
= 0; i
< 256; i
++) {
175 sc
->sc_cmap_red
[i
] = i
;
176 sc
->sc_cmap_green
[i
] = i
;
177 sc
->sc_cmap_blue
[i
] = i
;
180 aprint_normal(": %d x %d, %dbpp\n",
181 ri
->ri_width
, ri
->ri_height
, ri
->ri_depth
);
183 wsa
.console
= console
;
184 wsa
.scrdata
= &xafb_screenlist
;
185 wsa
.accessops
= &xafb_accessops
;
186 wsa
.accesscookie
= sc
;
188 config_found(self
, &wsa
, wsemuldisplaydevprint
);
192 xafb_setcolor(struct xafb_devconfig
*dc
, int index
, int r
, int g
, int b
)
194 volatile struct xafb_reg
*reg
= dc
->dc_reg
;
204 xafb_common_init(struct xafb_devconfig
*dc
)
206 struct rasops_info
*ri
= &dc
->dc_ri
;
209 for (i
= 0; i
< 256; i
++)
210 xafb_setcolor(dc
, i
, i
, i
, i
);
212 /* initialize rasops */
214 ri
->ri_height
= 1024;
216 ri
->ri_stride
= 2048;
217 ri
->ri_bits
= (void *)dc
->dc_fbbase
;
218 ri
->ri_flg
= RI_FORCEMONO
| RI_FULLCLEAR
;
220 rasops_init(ri
, 44, 100);
223 ri
->ri_devcmap
[0] = 0; /* bg */
224 ri
->ri_devcmap
[1] = 0xffffffff; /* fg */
226 xafb_stdscreen
.nrows
= ri
->ri_rows
;
227 xafb_stdscreen
.ncols
= ri
->ri_cols
;
228 xafb_stdscreen
.textops
= &ri
->ri_ops
;
229 xafb_stdscreen
.capabilities
= ri
->ri_caps
;
235 xafb_is_console(void)
237 volatile uint32_t *dipsw
= (void *)NEWS5000_DIP_SWITCH
;
239 if (*dipsw
& 1) /* XXX right? */
246 xafb_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
248 struct xafb_softc
*sc
= v
;
249 struct xafb_devconfig
*dc
= sc
->sc_dc
;
250 struct newsmips_wsdisplay_fbinfo
*nwdf
= (void *)data
;
251 struct wsdisplay_fbinfo
*wdf
= (void *)data
;
254 case WSDISPLAYIO_GTYPE
:
255 *(int *)data
= WSDISPLAY_TYPE_UNKNOWN
; /* XXX */
258 case NEWSMIPS_WSDISPLAYIO_GINFO
:
259 nwdf
->stride
= dc
->dc_ri
.ri_stride
;
261 case WSDISPLAYIO_GINFO
:
262 wdf
->height
= dc
->dc_ri
.ri_height
;
263 wdf
->width
= dc
->dc_ri
.ri_width
;
264 wdf
->depth
= dc
->dc_ri
.ri_depth
;
268 case WSDISPLAYIO_GETCMAP
:
269 return xafb_getcmap(sc
, (struct wsdisplay_cmap
*)data
);
271 case WSDISPLAYIO_PUTCMAP
:
272 return xafb_putcmap(sc
, (struct wsdisplay_cmap
*)data
);
274 /* case WSDISPLAYIO_SVIDEO: */
280 xafb_mmap(void *v
, void *vs
, off_t offset
, int prot
)
282 struct xafb_softc
*sc
= v
;
283 struct xafb_devconfig
*dc
= sc
->sc_dc
;
284 struct rasops_info
*ri
= &dc
->dc_ri
;
286 if (offset
>= (ri
->ri_stride
* ri
->ri_height
) || offset
< 0)
289 return mips_btop(dc
->dc_fbpaddr
+ offset
);
293 xafb_alloc_screen(void *v
, const struct wsscreen_descr
*scrdesc
,
294 void **cookiep
, int *ccolp
, int *crowp
, long *attrp
)
296 struct xafb_softc
*sc
= v
;
297 struct rasops_info
*ri
= &sc
->sc_dc
->dc_ri
;
300 if (sc
->sc_nscreens
> 0)
305 (*ri
->ri_ops
.allocattr
)(ri
, 0, 0, 0, &defattr
);
313 xafb_free_screen(void *v
, void *cookie
)
315 struct xafb_softc
*sc
= v
;
317 if (sc
->sc_dc
== &xafb_console_dc
)
318 panic("xafb_free_screen: console");
324 xafb_show_screen(void *v
, void *cookie
, int waitok
,
325 void (*cb
)(void *, int, int), void *cbarg
)
334 struct xafb_devconfig
*dc
= &xafb_console_dc
;
335 struct rasops_info
*ri
= &dc
->dc_ri
;
339 if (!xafb_is_console())
342 dc
->dc_fbpaddr
= (paddr_t
)0x10000000;
343 dc
->dc_fbbase
= (void *)MIPS_PHYS_TO_KSEG1(dc
->dc_fbpaddr
);
344 dc
->dc_reg
= (void *)0xb4903000; /* XXX */
345 xafb_common_init(dc
);
347 crow
= 0; /* XXX current cursor pos */
349 (*ri
->ri_ops
.allocattr
)(ri
, 0, 0, 0, &defattr
);
350 wsdisplay_cnattach(&xafb_stdscreen
, &dc
->dc_ri
, 0, crow
, defattr
);
356 xafb_getcmap(struct xafb_softc
*sc
, struct wsdisplay_cmap
*cm
)
358 u_int index
= cm
->index
;
359 u_int count
= cm
->count
;
362 if (index
>= 256 || count
> 256 || index
+ count
> 256)
365 error
= copyout(&sc
->sc_cmap_red
[index
], cm
->red
, count
);
368 error
= copyout(&sc
->sc_cmap_green
[index
], cm
->green
, count
);
371 error
= copyout(&sc
->sc_cmap_blue
[index
], cm
->blue
, count
);
379 xafb_putcmap(struct xafb_softc
*sc
, struct wsdisplay_cmap
*cm
)
381 u_int index
= cm
->index
;
382 u_int count
= cm
->count
;
384 u_char rbuf
[256], gbuf
[256], bbuf
[256];
387 if (cm
->index
>= 256 || cm
->count
> 256 ||
388 (cm
->index
+ cm
->count
) > 256)
390 error
= copyin(cm
->red
, &rbuf
[index
], count
);
393 error
= copyin(cm
->green
, &gbuf
[index
], count
);
396 error
= copyin(cm
->blue
, &bbuf
[index
], count
);
400 memcpy(&sc
->sc_cmap_red
[index
], &rbuf
[index
], count
);
401 memcpy(&sc
->sc_cmap_green
[index
], &gbuf
[index
], count
);
402 memcpy(&sc
->sc_cmap_blue
[index
], &bbuf
[index
], count
);
404 r
= &sc
->sc_cmap_red
[index
];
405 g
= &sc
->sc_cmap_green
[index
];
406 b
= &sc
->sc_cmap_blue
[index
];
407 for (i
= 0; i
< count
; i
++)
408 xafb_setcolor(sc
->sc_dc
, index
++, *r
++, *g
++, *b
++);