1 /* $NetBSD: fb_sbdio.c,v 1.7 2008/04/28 20:23:18 martin Exp $ */
4 * Copyright (c) 2004, 2005 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.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: fb_sbdio.c,v 1.7 2008/04/28 20:23:18 martin Exp $");
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
42 #include <uvm/uvm_extern.h> /* pmap function to remap FB */
44 #include <dev/wscons/wsconsio.h>
45 #include <dev/wscons/wsdisplayvar.h>
46 #include <dev/wsfont/wsfont.h>
47 #include <dev/rasops/rasops.h>
51 #include <machine/locore.h>
52 #include <machine/sbdiovar.h>
54 #include <machine/gareg.h>
55 #include <machine/gavar.h>
57 #include <machine/vmparam.h>
58 #include <machine/wired_map.h>
63 struct rasops_info
*sc_ri
;
68 int fb_sbdio_match(device_t
, cfdata_t
, void *);
69 void fb_sbdio_attach(device_t
, device_t
, void *);
71 CFATTACH_DECL_NEW(fb_sbdio
, sizeof(struct fb_softc
),
72 fb_sbdio_match
, fb_sbdio_attach
, NULL
, NULL
);
74 int _fb_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
75 paddr_t
_fb_mmap(void *, void *, off_t
, int);
76 int _fb_alloc_screen(void *, const struct wsscreen_descr
*, void **,
77 int *, int *, long *);
78 void _fb_free_screen(void *, void *);
79 int _fb_show_screen(void *, void *, int, void (*)(void *, int, int), void *);
80 void _fb_pollc(void *, int);
81 void fb_common_init(struct rasops_info
*, struct ga
*);
82 int fb_sbdio_cnattach(uint32_t, uint32_t, int);
83 void fb_pmap_enter(paddr_t
, paddr_t
, vaddr_t
*, vaddr_t
*);
85 struct wsscreen_descr _fb_std_screen
= {
92 const struct wsscreen_descr
*_fb_screen_table
[] = {
96 struct wsscreen_list _fb_screen_list
= {
98 sizeof(_fb_screen_table
) / sizeof(_fb_screen_table
[0]),
99 .screens
= _fb_screen_table
102 struct wsdisplay_accessops _fb_accessops
= {
105 .alloc_screen
= _fb_alloc_screen
,
106 .free_screen
= _fb_free_screen
,
107 .show_screen
= _fb_show_screen
,
113 static struct rasops_info fb_console_ri
;
114 static struct ga fb_console_ga
;
115 static paddr_t fb_consaddr
;
119 fb_sbdio_match(device_t parent
, cfdata_t cf
, void *aux
)
121 struct sbdio_attach_args
*sa
= aux
;
123 return strcmp(sa
->sa_name
, "fb") ? 0 : 1;
127 fb_sbdio_attach(device_t parent
, device_t self
, void *aux
)
129 struct fb_softc
*sc
= device_private(self
);
130 struct sbdio_attach_args
*sa
= aux
;
131 struct wsemuldisplaydev_attach_args wa
;
132 struct rasops_info
*ri
;
134 vaddr_t memva
, regva
;
140 console
= (sa
->sa_addr1
== fb_consaddr
);
142 /* already initialized in fb_cnattach() */
143 sc
->sc_ri
= ri
= &fb_console_ri
;
144 sc
->sc_ga
= &fb_console_ga
;
147 ri
= malloc(sizeof(struct rasops_info
), M_DEVBUF
,
150 printf(":can't allocate rasops memory\n");
153 ga
= malloc(sizeof(struct ga
), M_DEVBUF
, M_NOWAIT
| M_ZERO
);
155 printf(":can't allocate ga memory\n");
158 ga
->reg_paddr
= sa
->sa_addr2
;
159 ga
->flags
= sa
->sa_flags
;
160 fb_pmap_enter(sa
->sa_addr1
, sa
->sa_addr2
,
162 ri
->ri_bits
= (void *)memva
;
163 ga
->reg_addr
= regva
;
164 fb_common_init(ri
, ga
);
169 wa
.console
= console
;
170 wa
.scrdata
= &_fb_screen_list
;
171 wa
.accessops
= &_fb_accessops
;
172 wa
.accesscookie
= (void *)sc
;
174 config_found(self
, &wa
, wsdisplaydevprint
);
178 fb_common_init(struct rasops_info
*ri
, struct ga
*ga
)
180 int ga_active
, cookie
;
184 if (ga
->flags
== 0x0000 || ga
->flags
== 0x0001)
185 ga_active
= ga_init(ga
);
200 * When CLUT isn't initialized for NetBSD, use black-red pair.
202 ri
->ri_flg
= RI_CENTER
| RI_CLEAR
;
204 ri
->ri_flg
|= RI_FORCEMONO
;
208 ri
->ri_height
= 1024;
209 ri
->ri_stride
= 2048;
210 ri
->ri_hw
= (void *)ga
;
213 /* prefer 12 pixel wide font */
214 cookie
= wsfont_find(NULL
, 12, 0, 0, 0, 0);
216 cookie
= wsfont_find(NULL
, 0, 0, 0, 0, 0);
218 printf("sfb: font table is empty\n");
222 if (wsfont_lock(cookie
, &ri
->ri_font
)) {
223 printf("fb: can't lock font\n");
226 ri
->ri_wsfcookie
= cookie
;
228 rasops_init(ri
, 34, 80);
231 /* XXX no accelarated functions yet */
232 ri
->ri_ops
.putchar
= xxx_putchar
;
233 ri
->ri_ops
.erasecols
= xxx_erasecols
;
234 ri
->ri_ops
.copyrows
= xxx_copyrows
;
235 ri
->ri_ops
.eraserows
= xxx_eraserows
;
236 ir
->ri_do_cursor
= xxx_do_cursor
;
239 /* XXX shouldn't be global */
240 _fb_std_screen
.nrows
= ri
->ri_rows
;
241 _fb_std_screen
.ncols
= ri
->ri_cols
;
242 _fb_std_screen
.textops
= &ri
->ri_ops
;
243 _fb_std_screen
.capabilities
= ri
->ri_caps
;
247 fb_sbdio_cnattach(uint32_t mem
, uint32_t reg
, int flags
)
249 struct rasops_info
*ri
;
251 vaddr_t memva
, regva
;
259 fb_pmap_enter((paddr_t
)mem
, (paddr_t
)reg
, &memva
, ®va
);
260 ri
->ri_bits
= (void *)memva
;
261 ga
->reg_addr
= regva
;
263 fb_common_init(ri
, ga
);
265 (*ri
->ri_ops
.allocattr
)(ri
, 0, 0, 0, &defattr
);
266 wsdisplay_cnattach(&_fb_std_screen
, ri
, 0, 0, defattr
);
273 _fb_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
275 struct fb_softc
*sc
= v
;
276 struct wsdisplay_fbinfo
*fbinfo
= (void *)data
;
277 struct wsdisplay_cmap
*cmap
= (void *)data
;
278 struct rasops_info
*ri
= sc
->sc_ri
;
279 struct ga
*ga
= sc
->sc_ga
;
283 case WSDISPLAYIO_GTYPE
:
284 *(uint32_t *)data
= WSDISPLAY_TYPE_UNKNOWN
;
287 case WSDISPLAYIO_GINFO
:
288 fbinfo
->height
= ri
->ri_height
;
289 fbinfo
->width
= ri
->ri_width
;
290 fbinfo
->depth
= ri
->ri_depth
;
291 fbinfo
->cmsize
= 256;
295 case WSDISPLAYIO_LINEBYTES
:
296 *(u_int
*)data
= ri
->ri_stride
;
300 case WSDISPLAYIO_GETCMAP
:
301 if (ri
->ri_flg
== RI_FORCEMONO
)
304 for (i
= 0; i
< cmap
->count
; i
++) {
305 cmap
->red
[i
] = ga
->clut
[cmap
->index
+ i
][0];
306 cmap
->green
[i
] = ga
->clut
[cmap
->index
+ i
][1];
307 cmap
->blue
[i
] = ga
->clut
[cmap
->index
+ i
][2];
311 case WSDISPLAYIO_PUTCMAP
:
312 if (ri
->ri_flg
== RI_FORCEMONO
)
314 for (i
= 0; i
< cmap
->count
; i
++) {
315 ga
->clut
[cmap
->index
+ i
][0] = cmap
->red
[i
];
316 ga
->clut
[cmap
->index
+ i
][1] = cmap
->green
[i
];
317 ga
->clut
[cmap
->index
+ i
][2] = cmap
->blue
[i
];
327 _fb_mmap(void *v
, void *vs
, off_t offset
, int prot
)
330 if (offset
< 0 || offset
>= GA_FRB_SIZE
)
333 return mips_btop(GA_FRB_ADDR
+ offset
);
337 _fb_alloc_screen(void *v
, const struct wsscreen_descr
*type
, void **cookie
,
338 int *curx
, int *cury
, long *attr
)
340 struct fb_softc
*sc
= v
;
341 struct rasops_info
*ri
= sc
->sc_ri
;
345 if (sc
->sc_nscreens
> 0)
351 ri
->ri_ops
.allocattr(ri
, 0, 0, 0, &defattr
);
359 _fb_free_screen(void *v
, void *cookie
)
361 struct fb_softc
*sc
= v
;
367 _fb_show_screen(void *v
, void *cookie
, int waitok
,
368 void (*cb
)(void *, int, int), void *cbarg
)
375 _fb_pollc(void *v
, int on
)
378 /* no interrupt used. */
382 fb_pmap_enter(paddr_t fb_paddr
, paddr_t reg_paddr
,
383 vaddr_t
*fb_vaddr
, vaddr_t
*reg_vaddr
)
385 #ifdef WIRED_FB_TLB /* Make wired 16MPage for frame buffer */
387 vsize_t fb_off
, reg_off
, pgsize
;
389 pgsize
= MIPS3_WIRED_SIZE
;
390 fb_off
= fb_paddr
& MIPS3_WIRED_OFFMASK
;
391 reg_off
= reg_paddr
& MIPS3_WIRED_OFFMASK
;
392 fb_paddr
= fb_paddr
& ~MIPS3_WIRED_OFFMASK
;
393 reg_paddr
= reg_paddr
& ~MIPS3_WIRED_OFFMASK
;
396 if (mips3_wired_enter_page(va
, fb_paddr
, pgsize
) == false) {
397 printf("cannot allocate fb memory\n");
401 if (mips3_wired_enter_page(va
+ pgsize
, reg_paddr
, pgsize
) == false) {
402 printf("cannot allocate fb register\n");
406 *fb_vaddr
= va
+ fb_off
;
407 *reg_vaddr
= va
+ pgsize
+ reg_off
;
408 #else /* WIRED_FB_TLB */
415 va
= uvm_km_alloc(kernel_map
, epa
- pa
, 0, UVM_KMF_VAONLY
);
420 for (tva
= va
; pa
< epa
; pa
+= PAGE_SIZE
, tva
+= PAGE_SIZE
)
421 pmap_kenter_pa(tva
, pa
, VM_PROT_READ
| VM_PROT_WRITE
, 0);
423 pmap_update(pmap_kernel());
426 #endif /* WIRED_FB_TLB */