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