xafb.c revision 1.5.6.2 1 /* $NetBSD: xafb.c,v 1.5.6.2 2004/08/05 20:23:05 skrll Exp $ */
2
3 /*-
4 * Copyright (c) 2000 Tsubai Masanari. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
16 *
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.
27 */
28
29 /* "xa" frame buffer driver. Currently supports 1280x1024x8 only. */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: xafb.c,v 1.5.6.2 2004/08/05 20:23:05 skrll Exp $");
33
34 #include <sys/param.h>
35 #include <sys/buf.h>
36 #include <sys/device.h>
37 #include <sys/ioctl.h>
38 #include <sys/malloc.h>
39 #include <sys/systm.h>
40
41 #include <uvm/uvm_extern.h>
42
43 #include <machine/adrsmap.h>
44 #include <machine/apcall.h>
45
46 #include <machine/wsconsio.h>
47 #include <dev/wscons/wsdisplayvar.h>
48 #include <dev/rasops/rasops.h>
49
50 #include <newsmips/apbus/apbusvar.h>
51
52 struct xafb_reg {
53 volatile u_int r0;
54 volatile u_int index;
55 volatile u_int r2;
56 volatile u_int zero;
57 volatile u_int r4;
58 volatile u_int r5;
59 volatile u_int r6;
60 volatile u_int rgb;
61 };
62
63 struct xafb_devconfig {
64 volatile u_char *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;
68 };
69
70 struct xafb_softc {
71 struct device sc_dev;
72 struct xafb_devconfig *sc_dc;
73 int sc_nscreens;
74 u_char sc_cmap_red[256];
75 u_char sc_cmap_green[256];
76 u_char sc_cmap_blue[256];
77 };
78
79 int xafb_match __P((struct device *, struct cfdata *, void *));
80 void xafb_attach __P((struct device *, struct device *, void *));
81
82 int xafb_common_init __P((struct xafb_devconfig *));
83 int xafb_is_console __P((void));
84
85 int xafb_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
86 paddr_t xafb_mmap __P((void *, off_t, int));
87 int xafb_alloc_screen __P((void *, const struct wsscreen_descr *,
88 void **, int *, int *, long *));
89 void xafb_free_screen __P((void *, void *));
90 int xafb_show_screen __P((void *, void *, int,
91 void (*) (void *, int, int), void *));
92
93 int xafb_cnattach __P((void));
94 int xafb_getcmap __P((struct xafb_softc *, struct wsdisplay_cmap *));
95 int xafb_putcmap __P((struct xafb_softc *, struct wsdisplay_cmap *));
96
97 static __inline void xafb_setcolor(struct xafb_devconfig *, int, int, int, int);
98
99 CFATTACH_DECL(xafb, sizeof(struct xafb_softc),
100 xafb_match, xafb_attach, NULL, NULL);
101
102 struct xafb_devconfig xafb_console_dc;
103
104 struct wsdisplay_accessops xafb_accessops = {
105 xafb_ioctl,
106 xafb_mmap,
107 xafb_alloc_screen,
108 xafb_free_screen,
109 xafb_show_screen,
110 NULL /* load_font */
111 };
112
113 struct wsscreen_descr xafb_stdscreen = {
114 "std",
115 0, 0,
116 0,
117 0, 0,
118 WSSCREEN_REVERSE
119 };
120
121 const struct wsscreen_descr *xafb_scrlist[] = {
122 &xafb_stdscreen
123 };
124
125 struct wsscreen_list xafb_screenlist = {
126 sizeof(xafb_scrlist) / sizeof(xafb_scrlist[0]), xafb_scrlist
127 };
128
129 int
130 xafb_match(parent, match, aux)
131 struct device *parent;
132 struct cfdata *match;
133 void *aux;
134 {
135 struct apbus_attach_args *apa = aux;
136
137 if (strcmp(apa->apa_name, "xa") != 0)
138 return 0;
139
140 return 1;
141 }
142
143 void
144 xafb_attach(parent, self, aux)
145 struct device *parent, *self;
146 void *aux;
147 {
148 struct xafb_softc *sc = (void *)self;
149 struct apbus_attach_args *apa = aux;
150 struct wsemuldisplaydev_attach_args wsa;
151 struct xafb_devconfig *dc;
152 struct rasops_info *ri;
153 int console, i;
154
155 console = xafb_is_console();
156
157 if (console) {
158 dc = &xafb_console_dc;
159 ri = &dc->dc_ri;
160 sc->sc_nscreens = 1;
161 } else {
162 dc = malloc(sizeof(struct xafb_devconfig), M_DEVBUF, M_WAITOK);
163 bzero(dc, sizeof(struct xafb_devconfig));
164 dc->dc_fbpaddr = (paddr_t)0x10000000;
165 dc->dc_fbbase = (void *)MIPS_PHYS_TO_KSEG1(dc->dc_fbpaddr);
166 dc->dc_reg = (void *)(apa->apa_hwbase + 0x3000);
167 if (xafb_common_init(dc) != 0) {
168 printf(": couldn't initialize device\n");
169 return;
170 }
171
172 ri = &dc->dc_ri;
173
174 /* clear screen */
175 (*ri->ri_ops.eraserows)(ri, 0, ri->ri_rows, 0);
176 }
177 sc->sc_dc = dc;
178
179 for (i = 0; i < 256; i++) {
180 sc->sc_cmap_red[i] = i;
181 sc->sc_cmap_green[i] = i;
182 sc->sc_cmap_blue[i] = i;
183 }
184
185 printf(": %d x %d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth);
186
187 wsa.console = console;
188 wsa.scrdata = &xafb_screenlist;
189 wsa.accessops = &xafb_accessops;
190 wsa.accesscookie = sc;
191
192 config_found(self, &wsa, wsemuldisplaydevprint);
193 }
194
195 void
196 xafb_setcolor(dc, index, r, g, b)
197 struct xafb_devconfig *dc;
198 int index, r, g, b;
199 {
200 volatile struct xafb_reg *reg = dc->dc_reg;
201
202 reg->index = index;
203 reg->zero = 0;
204 reg->rgb = r;
205 reg->rgb = g;
206 reg->rgb = b;
207 }
208
209 int
210 xafb_common_init(dc)
211 struct xafb_devconfig *dc;
212 {
213 struct rasops_info *ri = &dc->dc_ri;
214 int i;
215
216 for (i = 0; i < 256; i++)
217 xafb_setcolor(dc, i, i, i, i);
218
219 /* initialize rasops */
220 ri->ri_width = 1280;
221 ri->ri_height = 1024;
222 ri->ri_depth = 8;
223 ri->ri_stride = 2048;
224 ri->ri_bits = (void *)dc->dc_fbbase;
225 ri->ri_flg = RI_FORCEMONO | RI_FULLCLEAR;
226
227 rasops_init(ri, 44, 100);
228
229 /* mono */
230 ri->ri_devcmap[0] = 0; /* bg */
231 ri->ri_devcmap[1] = 0xffffffff; /* fg */
232
233 xafb_stdscreen.nrows = ri->ri_rows;
234 xafb_stdscreen.ncols = ri->ri_cols;
235 xafb_stdscreen.textops = &ri->ri_ops;
236 xafb_stdscreen.capabilities = ri->ri_caps;
237
238 return 0;
239 }
240
241 int
242 xafb_is_console()
243 {
244 volatile u_int *dipsw = (void *)NEWS5000_DIP_SWITCH;
245
246 if (*dipsw & 1) /* XXX right? */
247 return 1;
248
249 return 0;
250 }
251
252 int
253 xafb_ioctl(v, cmd, data, flag, p)
254 void *v;
255 u_long cmd;
256 caddr_t data;
257 int flag;
258 struct proc *p;
259 {
260 struct xafb_softc *sc = v;
261 struct xafb_devconfig *dc = sc->sc_dc;
262 struct newsmips_wsdisplay_fbinfo *nwdf = (void *)data;
263 struct wsdisplay_fbinfo *wdf = (void *)data;
264
265 switch (cmd) {
266 case WSDISPLAYIO_GTYPE:
267 *(int *)data = WSDISPLAY_TYPE_UNKNOWN; /* XXX */
268 return 0;
269
270 case NEWSMIPS_WSDISPLAYIO_GINFO:
271 nwdf->stride = dc->dc_ri.ri_stride;
272 /* FALLTHROUGH */
273 case WSDISPLAYIO_GINFO:
274 wdf->height = dc->dc_ri.ri_height;
275 wdf->width = dc->dc_ri.ri_width;
276 wdf->depth = dc->dc_ri.ri_depth;
277 wdf->cmsize = 256;
278 return 0;
279
280 case WSDISPLAYIO_GETCMAP:
281 return xafb_getcmap(sc, (struct wsdisplay_cmap *)data);
282
283 case WSDISPLAYIO_PUTCMAP:
284 return xafb_putcmap(sc, (struct wsdisplay_cmap *)data);
285
286 /* case WSDISPLAYIO_SVIDEO: */
287 }
288 return EPASSTHROUGH;
289 }
290
291 paddr_t
292 xafb_mmap(v, offset, prot)
293 void *v;
294 off_t offset;
295 int prot;
296 {
297 struct xafb_softc *sc = v;
298 struct xafb_devconfig *dc = sc->sc_dc;
299 struct rasops_info *ri = &dc->dc_ri;
300
301 if (offset >= (ri->ri_stride * ri->ri_height) || offset < 0)
302 return -1;
303
304 return mips_btop(dc->dc_fbpaddr + offset);
305 }
306
307 int
308 xafb_alloc_screen(v, scrdesc, cookiep, ccolp, crowp, attrp)
309 void *v;
310 const struct wsscreen_descr *scrdesc;
311 void **cookiep;
312 int *ccolp, *crowp;
313 long *attrp;
314 {
315 struct xafb_softc *sc = v;
316 struct rasops_info *ri = &sc->sc_dc->dc_ri;
317 long defattr;
318
319 if (sc->sc_nscreens > 0)
320 return ENOMEM;
321
322 *cookiep = ri;
323 *ccolp = *crowp = 0;
324 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
325 *attrp = defattr;
326 sc->sc_nscreens++;
327
328 return 0;
329 }
330
331 void
332 xafb_free_screen(v, cookie)
333 void *v;
334 void *cookie;
335 {
336 struct xafb_softc *sc = v;
337
338 if (sc->sc_dc == &xafb_console_dc)
339 panic("xafb_free_screen: console");
340
341 sc->sc_nscreens--;
342 }
343
344 int
345 xafb_show_screen(v, cookie, waitok, cb, cbarg)
346 void *v;
347 void *cookie;
348 int waitok;
349 void (*cb) __P((void *, int, int));
350 void *cbarg;
351 {
352 return 0;
353 }
354
355 int
356 xafb_cnattach()
357 {
358 struct xafb_devconfig *dc = &xafb_console_dc;
359 struct rasops_info *ri = &dc->dc_ri;
360 long defattr;
361 int crow = 0;
362
363 if (!xafb_is_console())
364 return -1;
365
366 dc->dc_fbpaddr = (paddr_t)0x10000000;
367 dc->dc_fbbase = (void *)MIPS_PHYS_TO_KSEG1(dc->dc_fbpaddr);
368 dc->dc_reg = (void *)0xb4903000; /* XXX */
369 xafb_common_init(dc);
370
371 crow = 0; /* XXX current cursor pos */
372
373 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
374 wsdisplay_cnattach(&xafb_stdscreen, &dc->dc_ri, 0, crow, defattr);
375
376 return 0;
377 }
378
379 int
380 xafb_getcmap(sc, cm)
381 struct xafb_softc *sc;
382 struct wsdisplay_cmap *cm;
383 {
384 u_int index = cm->index;
385 u_int count = cm->count;
386 int error;
387
388 if (index >= 256 || count > 256 || index + count > 256)
389 return EINVAL;
390
391 error = copyout(&sc->sc_cmap_red[index], cm->red, count);
392 if (error)
393 return error;
394 error = copyout(&sc->sc_cmap_green[index], cm->green, count);
395 if (error)
396 return error;
397 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
398 if (error)
399 return error;
400
401 return 0;
402 }
403
404 int
405 xafb_putcmap(sc, cm)
406 struct xafb_softc *sc;
407 struct wsdisplay_cmap *cm;
408 {
409 u_int index = cm->index;
410 u_int count = cm->count;
411 int i, error;
412 u_char rbuf[256], gbuf[256], bbuf[256];
413 u_char *r, *g, *b;
414
415 if (cm->index >= 256 || cm->count > 256 ||
416 (cm->index + cm->count) > 256)
417 return EINVAL;
418 error = copyin(cm->red, &rbuf[index], count);
419 if (error)
420 return error;
421 error = copyin(cm->green, &gbuf[index], count);
422 if (error)
423 return error;
424 error = copyin(cm->blue, &bbuf[index], count);
425 if (error)
426 return error;
427
428 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
429 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
430 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
431
432 r = &sc->sc_cmap_red[index];
433 g = &sc->sc_cmap_green[index];
434 b = &sc->sc_cmap_blue[index];
435 for (i = 0; i < count; i++)
436 xafb_setcolor(sc->sc_dc, index++, *r++, *g++, *b++);
437 return 0;
438 }
439