Annotation of src/sys/arch/i386/xbox/xboxfb.c, Revision 1.4
1.4 ! jmcneill 1: /* $NetBSD: xboxfb.c,v 1.3 2007/01/05 04:13:09 jmcneill Exp $ */
1.1 jmcneill 2:
3: /*
4: * Copyright (c) 2006 Andrew Gillham
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. The name of the author may not be used to endorse or promote products
16: * derived from this software without specific prior written permission.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28: */
29:
30: /*
31: * A console driver for the Xbox.
32: */
33:
34: #include <sys/cdefs.h>
35: #include <sys/param.h>
36: #include <sys/systm.h>
37: #include <sys/kernel.h>
38: #include <sys/device.h>
39: #include <sys/malloc.h>
40: #include <sys/callout.h>
41: #include <sys/lwp.h>
42: #include <sys/kauth.h>
43:
44: #include <uvm/uvm_extern.h>
45: /* #include <machine/autoconf.h> */
46: #include <machine/bus.h>
47: #include <machine/xbox.h>
48:
49: #include <dev/pci/pcivar.h>
50: #include <dev/pci/pcireg.h>
51: #include <dev/pci/pcidevs.h>
52: #include <dev/pci/pciio.h>
53:
54: #include <dev/wscons/wsdisplayvar.h>
55: #include <dev/wscons/wsconsio.h>
56: #include <dev/wsfont/wsfont.h>
57: #include <dev/rasops/rasops.h>
58: #include <dev/wscons/wsdisplay_vconsvar.h>
59:
60: #include "opt_wsemul.h"
61:
1.2 jmcneill 62: MALLOC_DEFINE(M_XBOXFB, "xboxfb", "xboxfb shadow framebuffer");
63:
1.1 jmcneill 64: #define SCREEN_WIDTH 640
65: #define SCREEN_HEIGHT 480
66: #define SCREEN_BPP 32
67: #define SCREEN_SIZE (SCREEN_WIDTH*SCREEN_HEIGHT*SCREEN_BPP)
68:
69: #define FONT_HEIGHT 16
70: #define FONT_WIDTH 8
71:
72: #define CHAR_HEIGHT 16
73: #define CHAR_WIDTH 10
74:
75: /*
76: #define XBOX_RAM_SIZE (arch_i386_xbox_memsize * 1024 * 1024)
77: #define XBOX_FB_SIZE (0x400000)
78: #define XBOX_FB_START (0xF0000000 | (XBOX_RAM_SIZE - XBOX_FB_SIZE))
79: #define XBOX_FB_START_PTR (0xFD600800)
80: */
81:
1.3 jmcneill 82: static char *xboxfb_console_shadowbits;
83: static bus_space_handle_t xboxfb_console_memh;
84:
1.1 jmcneill 85: struct xboxfb_softc {
86: struct device sc_dev;
87: struct vcons_data vd;
88:
89: bus_space_tag_t sc_memt;
90: bus_space_handle_t sc_memh;
91:
92: vaddr_t fbva;
93: paddr_t fbpa;
94:
95: void *sc_ih;
96:
97: size_t memsize;
98:
99: int bits_per_pixel;
100: int width, height, linebytes;
101:
102: int sc_mode;
103: uint32_t sc_bg;
1.2 jmcneill 104:
105: char *sc_shadowbits;
1.1 jmcneill 106: };
107:
108: static struct vcons_screen xboxfb_console_screen;
109:
110: static int xboxfb_match(struct device *, struct cfdata *, void *);
111: static void xboxfb_attach(struct device *, struct device *, void *);
112:
113: CFATTACH_DECL(xboxfb, sizeof(struct xboxfb_softc), xboxfb_match,
114: xboxfb_attach, NULL, NULL);
115:
116: /* static void xboxfb_init(struct xboxfb_softc *); */
117:
118: /* static void xboxfb_cursor(void *, int, int, int); */
119: /* static void xboxfb_copycols(void *, int, int, int, int); */
120: /* static void xboxfb_erasecols(void *, int, int, int, long); */
121: /* static void xboxfb_copyrows(void *, int, int, int); */
122: /* static void xboxfb_eraserows(void *, int, int, long); */
123:
124: struct wsscreen_descr xboxfb_defaultscreen = {
125: "default",
126: 0, 0,
127: NULL,
128: 8, 16,
129: WSSCREEN_WSCOLORS,
130: NULL,
131: };
132:
133: const struct wsscreen_descr *_xboxfb_scrlist[] = {
134: &xboxfb_defaultscreen,
135: };
136:
137: struct wsscreen_list xboxfb_screenlist = {
138: sizeof(_xboxfb_scrlist) / sizeof(struct wsscreen_descr *),
139: _xboxfb_scrlist
140: };
141:
142: static int xboxfb_ioctl(void *, void *, u_long, caddr_t, int,
143: struct lwp *);
144: static paddr_t xboxfb_mmap(void *, void *, off_t, int);
145: static void xboxfb_init_screen(void *, struct vcons_screen *, int,
146: long *);
147:
148: struct wsdisplay_accessops xboxfb_accessops = {
149: xboxfb_ioctl,
150: xboxfb_mmap,
151: NULL, /* alloc_screen */
152: NULL, /* free_screen */
153: NULL, /* show_screen */
154: NULL, /* load_font */
155: NULL, /* pollc */
156: NULL, /* scroll */
157: };
158:
159: static int
160: xboxfb_match(struct device *parent, struct cfdata *match, void *aux)
161: {
162: struct pci_attach_args *pa = (struct pci_attach_args *)aux;
163:
164: /* Don't match on non-Xbox i386 */
165: if (!arch_i386_is_xbox) {
166: return (0);
167: }
168:
169: if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY ||
170: PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA)
171: return 0;
172: if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NVIDIA) &&
173: (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NVIDIA_XBOXFB))
174: return 100;
175: return 0;
176: };
177:
178: static void
179: xboxfb_attach(struct device *parent, struct device *self, void *aux)
180: {
181: struct xboxfb_softc *sc = (void *)self;
182: struct wsemuldisplaydev_attach_args aa;
183: struct rasops_info *ri;
184: int console;
185: ulong defattr = 0;
186: uint32_t bg, fg, ul;
187:
1.3 jmcneill 188: sc->sc_memt = X86_BUS_SPACE_MEM;
189: sc->sc_memh = xboxfb_console_memh;
1.1 jmcneill 190: sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
191: sc->width = SCREEN_WIDTH;
192: sc->height = SCREEN_HEIGHT;
193: sc->bits_per_pixel = SCREEN_BPP;
194: sc->fbpa = XBOX_FB_START;
195:
1.3 jmcneill 196: aprint_normal(": %dx%d, %d bit framebuffer console\n",
1.1 jmcneill 197: sc->width, sc->height, sc->bits_per_pixel);
198:
199: sc->fbva = (vaddr_t)bus_space_vaddr(sc->sc_memt, sc->sc_memh);
200: if (sc->fbva == 0)
201: return;
202:
1.3 jmcneill 203: sc->sc_shadowbits = xboxfb_console_shadowbits;
1.2 jmcneill 204: if (sc->sc_shadowbits == NULL) {
205: aprint_error(": unable to allocate %d bytes for shadowfb\n",
206: XBOX_FB_SIZE);
207: return;
208: }
209:
210: ri = &xboxfb_console_screen.scr_ri;
211:
1.1 jmcneill 212: vcons_init(&sc->vd, sc, &xboxfb_defaultscreen, &xboxfb_accessops);
213: sc->vd.init_screen = xboxfb_init_screen;
214:
215: /* yes, we're the console */
216: console = 1;
217:
218: if (console) {
219: vcons_init_screen(&sc->vd, &xboxfb_console_screen, 1,
220: &defattr);
1.3 jmcneill 221: xboxfb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
222: }
1.1 jmcneill 223:
224: rasops_unpack_attr(defattr, &fg, &bg, &ul);
225: sc->sc_bg = ri->ri_devcmap[bg];
226:
227: aa.console = console;
228: aa.scrdata = &xboxfb_screenlist;
229: aa.accessops = &xboxfb_accessops;
230: aa.accesscookie = &sc->vd;
231:
232: config_found(self, &aa, wsemuldisplaydevprint);
233: }
234:
235: /*
236: * respond to ioctl requests
237: */
238:
239: static int
240: xboxfb_ioctl(void *v, void*vs, u_long cmd, caddr_t data, int flag,
241: struct lwp *l)
242: {
243: struct vcons_data *vd = v;
1.4 ! jmcneill 244: struct xboxfb_softc *sc = vd->cookie;
1.1 jmcneill 245: struct wsdisplay_fbinfo *wdf;
246: struct vcons_screen *ms = vd->active;
247:
248: switch (cmd) {
249: case WSDISPLAYIO_GTYPE:
250: *(u_int *)data = WSDISPLAY_TYPE_PCIMISC;
1.4 ! jmcneill 251: return 0;
1.1 jmcneill 252:
253: case WSDISPLAYIO_GINFO:
254: wdf = (void *)data;
255: wdf->height = ms->scr_ri.ri_height;
256: wdf->width = ms->scr_ri.ri_width;
257: wdf->depth = ms->scr_ri.ri_depth;
258: wdf->cmsize = 256;
1.4 ! jmcneill 259: return 0;
1.1 jmcneill 260:
261: case WSDISPLAYIO_GETCMAP:
1.4 ! jmcneill 262: return EINVAL;
1.1 jmcneill 263:
264: case WSDISPLAYIO_PUTCMAP:
1.4 ! jmcneill 265: return EINVAL;
! 266:
! 267: case WSDISPLAYIO_LINEBYTES:
! 268: *(u_int *)data = SCREEN_WIDTH * 4;
! 269: return 0;
1.1 jmcneill 270:
271: case WSDISPLAYIO_SMODE:
1.4 ! jmcneill 272: {
! 273: int new_mode = *(int *)data;
! 274: if (new_mode != sc->sc_mode) {
! 275: sc->sc_mode = new_mode;
! 276: if (new_mode == WSDISPLAYIO_MODE_EMUL)
! 277: vcons_redraw_screen(vd->active);
! 278: }
! 279: }
! 280: return 0;
1.1 jmcneill 281: }
282: return EPASSTHROUGH;
283: }
284:
285: static paddr_t
286: xboxfb_mmap(void *v, void *vs, off_t offset, int prot)
287: {
1.4 ! jmcneill 288: struct vcons_data *vd;
! 289: struct xboxfb_softc *sc;
! 290: paddr_t pa;
! 291:
! 292: vd = (struct vcons_data *)v;
! 293: sc = (struct xboxfb_softc *)vd->cookie;
! 294:
! 295: if (offset >= 0 && offset < XBOX_FB_SIZE) {
! 296: pa = bus_space_mmap(X86_BUS_SPACE_MEM, XBOX_FB_START,
! 297: offset, prot, BUS_SPACE_MAP_LINEAR);
! 298: return pa;
! 299: }
! 300:
1.1 jmcneill 301: return (-1);
302: }
303:
304: static void
305: xboxfb_init_screen(void *cookie, struct vcons_screen *scr,
306: int existing, long *defattr)
307: {
308: struct xboxfb_softc *sc = cookie;
309: struct rasops_info *ri = &scr->scr_ri;
310:
1.3 jmcneill 311: if (scr == &xboxfb_console_screen)
312: return;
313:
1.1 jmcneill 314: ri->ri_depth = sc->bits_per_pixel;
315: ri->ri_width = sc->width;
316: ri->ri_height = sc->height;
317: ri->ri_stride = sc->width * (sc->bits_per_pixel / 8);
1.2 jmcneill 318: ri->ri_flg = RI_CENTER;
1.1 jmcneill 319:
1.3 jmcneill 320: if (xboxfb_console_shadowbits != NULL) {
321: ri->ri_hwbits = bus_space_vaddr(sc->sc_memt, sc->sc_memh);
322: ri->ri_bits = sc->sc_shadowbits;
323: } else
324: ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh);
1.1 jmcneill 325:
326: if (existing) {
327: ri->ri_flg |= RI_CLEAR;
328: }
329:
330: rasops_init(ri, sc->height/8, sc->width/8);
331: ri->ri_caps = WSSCREEN_WSCOLORS;
332:
333: rasops_reconfig(ri, sc->height / ri->ri_font->fontheight,
334: sc->width / ri->ri_font->fontwidth);
335:
336: ri->ri_hw = scr;
337: }
338:
339: int
340: xboxfb_cnattach(void)
341: {
1.3 jmcneill 342: static int ncalls = 0;
343: struct rasops_info *ri = &xboxfb_console_screen.scr_ri;
344: long defattr;
345:
346: /* We can't attach if we're not running on an Xbox... */
347: if (!arch_i386_is_xbox)
348: return 1;
349:
350: /* XXX jmcneill
351: * Console initialization is called multiple times on i386; the first
352: * two being too early for us to use malloc or bus_space_map. Defer
353: * initialization under these subsystems are ready.
354: */
355: ++ncalls;
356: if (ncalls < 3)
357: return -1;
358:
359: xboxfb_console_shadowbits = malloc(XBOX_FB_SIZE, M_XBOXFB, M_NOWAIT);
360:
361: if (xboxfb_console_shadowbits == NULL)
362: aprint_error("xboxfb_cnattach: failed to allocate shadowfb\n");
363:
364: if (bus_space_map(X86_BUS_SPACE_MEM, XBOX_FB_START, XBOX_FB_SIZE,
365: BUS_SPACE_MAP_LINEAR, &xboxfb_console_memh)) {
366: aprint_error("xboxfb_cnattach: failed to map memory.\n");
367: return 1;
368: }
369:
370: wsfont_init();
371: ri->ri_width = SCREEN_WIDTH;
372: ri->ri_height = SCREEN_HEIGHT;
373: ri->ri_depth = SCREEN_BPP;
374: ri->ri_stride = ri->ri_width * ri->ri_depth / 8;
375: ri->ri_flg = RI_CENTER;
376: ri->ri_bits = xboxfb_console_shadowbits;
377: ri->ri_hwbits = bus_space_vaddr(X86_BUS_SPACE_MEM,
378: xboxfb_console_memh);
379: if (ri->ri_hwbits == NULL) {
380: aprint_error("xboxfb_cnattach: bus_space_vaddr failed\n");
381: return 1;
382: }
383:
384: /* clear screen */
385: memset(ri->ri_bits, 0, XBOX_FB_SIZE);
386: memset(ri->ri_hwbits, 0, XBOX_FB_SIZE);
387:
388: rasops_init(ri, ri->ri_height / 8, ri->ri_width / 8);
389: ri->ri_caps = WSSCREEN_WSCOLORS;
390: rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight,
391: ri->ri_width / ri->ri_font->fontwidth);
392:
393: xboxfb_defaultscreen.nrows = ri->ri_rows;
394: xboxfb_defaultscreen.ncols = ri->ri_cols;
395: xboxfb_defaultscreen.textops = &ri->ri_ops;
396: xboxfb_defaultscreen.capabilities = ri->ri_caps;
397: ri->ri_ops.allocattr(ri, 0, 0, 0, &defattr);
398:
399: wsdisplay_preattach(&xboxfb_defaultscreen, ri, 0, 0, defattr);
400:
401: return 0;
1.1 jmcneill 402: }
CVSweb <webmaster@jp.NetBSD.org>