This source file includes following definitions.
- rfxmatch
- rfxattach
- rfx_ioctl
- rfx_mmap
- rfx_alloc_screen
- rfx_free_screen
- rfx_show_screen
- rfx_burner
- rfx_setcolor
- rfx_getcmap
- rfx_putcmap
- rfx_loadcmap
- rfx_initialize
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/buf.h>
38 #include <sys/device.h>
39 #include <sys/ioctl.h>
40 #include <sys/malloc.h>
41 #include <sys/mman.h>
42 #include <sys/tty.h>
43 #include <sys/conf.h>
44
45 #include <uvm/uvm_extern.h>
46
47 #include <machine/autoconf.h>
48 #include <machine/pmap.h>
49 #include <machine/cpu.h>
50 #include <machine/conf.h>
51 #include <machine/openfirm.h>
52
53 #include <dev/wscons/wsconsio.h>
54 #include <dev/wscons/wsdisplayvar.h>
55 #include <dev/rasops/rasops.h>
56 #include <machine/fbvar.h>
57
58 #include <dev/sbus/sbusvar.h>
59
60 #include <dev/ic/bt463reg.h>
61
62
63
64
65 struct rfx_config {
66 u_int16_t unknown;
67 u_int16_t version;
68 u_int32_t scanline;
69 u_int32_t maxwidth;
70 u_int32_t maxheight;
71 u_int32_t width;
72 u_int32_t height;
73 };
74
75
76
77
78
79 #define RFX_RAMDAC_ADDR 0x00020000
80 #define RFX_RAMDAC_SIZE 0x00000004
81
82 #define RFX_CONTROL_ADDR 0x00040000
83 #define RFX_CONTROL_SIZE 0x000000e0
84
85 #define RFX_INIT_ADDR 0x00018000
86 #define RFX_INIT_OFFSET 0x0000001c
87 #define RFX_INIT_SIZE 0x00008000
88
89 #define RFX_VRAM_ADDR 0x00100000
90
91
92
93
94
95 #define RFX_VIDCTRL_REG 0x10
96 #define RFX_VSYNC_ENABLE 0x00000001
97 #define RFX_VIDEO_DISABLE 0x00000002
98
99
100
101
102 struct rfx_cmap {
103 u_int8_t red[256];
104 u_int8_t green[256];
105 u_int8_t blue[256];
106 };
107
108 struct rfx_softc {
109 struct sunfb sc_sunfb;
110
111 bus_space_tag_t sc_bustag;
112 bus_addr_t sc_paddr;
113
114 struct intrhand sc_ih;
115
116 struct rfx_cmap sc_cmap;
117 volatile u_int8_t *sc_ramdac;
118 volatile u_int32_t *sc_ctrl;
119
120 int sc_nscreens;
121 };
122
123 int rfx_alloc_screen(void *, const struct wsscreen_descr *, void **,
124 int *, int *, long *);
125 void rfx_burner(void *, u_int, u_int);
126 void rfx_free_screen(void *, void *);
127 int rfx_ioctl(void *, u_long, caddr_t, int, struct proc *);
128 int rfx_show_screen(void *, void *, int, void (*cb)(void *, int, int),
129 void *);
130 paddr_t rfx_mmap(void *, off_t, int);
131
132 int rfx_getcmap(struct rfx_cmap *, struct wsdisplay_cmap *);
133 int rfx_initialize(struct rfx_softc *, struct sbus_attach_args *,
134 struct rfx_config *);
135 int rfx_intr(void *);
136 void rfx_loadcmap(struct rfx_softc *, int, int);
137 int rfx_putcmap(struct rfx_cmap *, struct wsdisplay_cmap *);
138 void rfx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
139
140 struct wsdisplay_accessops rfx_accessops = {
141 rfx_ioctl,
142 rfx_mmap,
143 rfx_alloc_screen,
144 rfx_free_screen,
145 rfx_show_screen,
146 NULL,
147 NULL,
148 NULL,
149 rfx_burner,
150 };
151
152 int rfxmatch(struct device *, void *, void *);
153 void rfxattach(struct device *, struct device *, void *);
154
155 #if defined(OpenBSD)
156 struct cfattach rfx_ca = {
157 sizeof (struct rfx_softc), rfxmatch, rfxattach
158 };
159
160 struct cfdriver rfx_cd = {
161 NULL, "rfx", DV_DULL
162 };
163 #else
164 CFATTACH_DECL(rfx, sizeof (struct rfx_softc), rfxmatch, rfxattach, NULL, NULL);
165 #endif
166
167
168
169
170 int
171 rfxmatch(struct device *parent, void *vcf, void *aux)
172 {
173 struct sbus_attach_args *sa = aux;
174 const char *device = sa->sa_name;
175
176
177 while (*device != ',' && *device != '\0')
178 device++;
179 if (*device == '\0')
180 device = sa->sa_name;
181 else
182 device++;
183
184 if (strncmp(device, "RasterFLEX", strlen("RasterFLEX")) != 0)
185 return (0);
186
187
188 if (strcmp(device, "RasterFLEX-TV") == 0)
189 return (0);
190
191 return (1);
192 }
193
194
195
196
197 void
198 rfxattach(struct device *parent, struct device *self, void *args)
199 {
200 struct rfx_softc *sc = (struct rfx_softc *)self;
201 struct sbus_attach_args *sa = args;
202 const char *device = sa->sa_name;
203 struct rfx_config cf;
204 bus_space_tag_t bt;
205 bus_space_handle_t bh;
206 int node, cflen, isconsole = 0;
207
208
209 while (*device != ',' && *device != '\0')
210 device++;
211 if (*device == '\0')
212 device = sa->sa_name;
213 else
214 device++;
215
216 printf(": %s", device);
217
218 if (sa->sa_nreg == 0) {
219 printf("\n%s: no SBus registers!\n", self->dv_xname);
220 return;
221 }
222
223 bt = sa->sa_bustag;
224 node = sa->sa_node;
225 isconsole = node == fbnode;
226
227
228
229
230 cflen = getproplen(node, "configuration");
231 if (cflen != sizeof cf) {
232 printf(", unknown %d bytes conf. structure", cflen);
233
234 cf.version = 0;
235 cf.scanline = 2048;
236 cf.width = 1152;
237 cf.height = 900;
238 } else {
239 OF_getprop(node, "configuration", &cf, cflen);
240 printf(", revision %d", cf.version);
241 }
242
243
244
245
246
247 sc->sc_bustag = bt;
248 sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);
249
250 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + RFX_RAMDAC_ADDR,
251 RFX_RAMDAC_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
252 printf("\n%s: couldn't map ramdac registers\n", self->dv_xname);
253 return;
254 }
255 sc->sc_ramdac = (u_int8_t *)bus_space_vaddr(bt, bh);
256
257 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + RFX_CONTROL_ADDR,
258 RFX_CONTROL_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
259 printf("\n%s: couldn't map control registers\n", self->dv_xname);
260 return;
261 }
262 sc->sc_ctrl = (u_int32_t *)bus_space_vaddr(bt, bh);
263
264 #if 0
265 sc->sc_ih.ih_fun = rfx_intr;
266 sc->sc_ih.ih_arg = sc;
267 intr_establish(ca->ca_ra.ra_intr[0].int_pri, &sc->sc_ih, IPL_FB);
268 #endif
269
270
271
272
273
274
275
276
277
278 sc->sc_sunfb.sf_depth = 8;
279 sc->sc_sunfb.sf_width = cf.width;
280 sc->sc_sunfb.sf_height = cf.height;
281 sc->sc_sunfb.sf_linebytes = cf.scanline;
282 sc->sc_sunfb.sf_fbsize = cf.height * cf.scanline;
283
284 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
285
286 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + RFX_VRAM_ADDR,
287 round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR,
288 0, &bh) != 0) {
289 printf("\n%s: couldn't map video memory\n", self->dv_xname);
290 return;
291 }
292 sc->sc_sunfb.sf_ro.ri_bits = bus_space_vaddr(bt, bh);
293 sc->sc_sunfb.sf_ro.ri_hw = sc;
294
295
296
297
298
299 if (!isconsole) {
300 if (rfx_initialize(sc, sa, &cf) != 0)
301 return;
302 }
303
304 fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);
305
306 bzero(&sc->sc_cmap, sizeof(sc->sc_cmap));
307 fbwscons_setcolormap(&sc->sc_sunfb, rfx_setcolor);
308
309 if (isconsole) {
310 fbwscons_console_init(&sc->sc_sunfb, -1);
311 }
312
313
314 rfx_burner(sc, 1, 0);
315
316 fbwscons_attach(&sc->sc_sunfb, &rfx_accessops, isconsole);
317 }
318
319
320
321
322
323 int
324 rfx_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
325 {
326 struct rfx_softc *sc = v;
327 struct wsdisplay_cmap *cm;
328 struct wsdisplay_fbinfo *wdf;
329 int error;
330
331 switch (cmd) {
332 case WSDISPLAYIO_GTYPE:
333 *(u_int *)data = WSDISPLAY_TYPE_RFLEX;
334 break;
335 case WSDISPLAYIO_GINFO:
336 wdf = (struct wsdisplay_fbinfo *)data;
337 wdf->height = sc->sc_sunfb.sf_height;
338 wdf->width = sc->sc_sunfb.sf_width;
339 wdf->depth = sc->sc_sunfb.sf_depth;
340 wdf->cmsize = 256;
341 break;
342 case WSDISPLAYIO_LINEBYTES:
343 *(u_int *)data = sc->sc_sunfb.sf_linebytes;
344 break;
345
346 case WSDISPLAYIO_GETCMAP:
347 cm = (struct wsdisplay_cmap *)data;
348 error = rfx_getcmap(&sc->sc_cmap, cm);
349 if (error != 0)
350 return (error);
351 break;
352 case WSDISPLAYIO_PUTCMAP:
353 cm = (struct wsdisplay_cmap *)data;
354 error = rfx_putcmap(&sc->sc_cmap, cm);
355 if (error != 0)
356 return (error);
357 rfx_loadcmap(sc, cm->index, cm->count);
358 break;
359
360 case WSDISPLAYIO_SVIDEO:
361 case WSDISPLAYIO_GVIDEO:
362 break;
363
364 default:
365 return (-1);
366 }
367
368 return (0);
369 }
370
371 paddr_t
372 rfx_mmap(void *v, off_t offset, int prot)
373 {
374 struct rfx_softc *sc = v;
375
376 if (offset & PGOFSET)
377 return (-1);
378
379 if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
380 return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
381 RFX_VRAM_ADDR + offset, prot, BUS_SPACE_MAP_LINEAR));
382 }
383
384 return (-1);
385 }
386
387 int
388 rfx_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
389 int *curxp, int *curyp, long *attrp)
390 {
391 struct rfx_softc *sc = v;
392
393 if (sc->sc_nscreens > 0)
394 return (ENOMEM);
395
396 *cookiep = &sc->sc_sunfb.sf_ro;
397 *curyp = 0;
398 *curxp = 0;
399 sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro,
400 WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp);
401 sc->sc_nscreens++;
402 return (0);
403 }
404
405 void
406 rfx_free_screen(void *v, void *cookie)
407 {
408 struct rfx_softc *sc = v;
409
410 sc->sc_nscreens--;
411 }
412
413 int
414 rfx_show_screen(void *v, void *cookie, int waitok,
415 void (*cb)(void *, int, int), void *cbarg)
416 {
417 return (0);
418 }
419
420 void
421 rfx_burner(void *v, u_int on, u_int flags)
422 {
423 struct rfx_softc *sc = v;
424
425 if (on) {
426 sc->sc_ctrl[RFX_VIDCTRL_REG] &= ~RFX_VIDEO_DISABLE;
427 sc->sc_ctrl[RFX_VIDCTRL_REG] |= RFX_VSYNC_ENABLE;
428 } else {
429 sc->sc_ctrl[RFX_VIDCTRL_REG] |= RFX_VIDEO_DISABLE;
430 if (flags & WSDISPLAY_BURN_VBLANK)
431 sc->sc_ctrl[RFX_VIDCTRL_REG] &= ~RFX_VSYNC_ENABLE;
432 }
433 }
434
435
436
437
438
439 void
440 rfx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
441 {
442 struct rfx_softc *sc = v;
443
444 sc->sc_cmap.red[index] = r;
445 sc->sc_cmap.green[index] = g;
446 sc->sc_cmap.blue[index] = b;
447
448 rfx_loadcmap(sc, index, 1);
449 }
450
451 int
452 rfx_getcmap(struct rfx_cmap *cm, struct wsdisplay_cmap *rcm)
453 {
454 u_int index = rcm->index, count = rcm->count;
455 int error;
456
457 if (index >= 256 || count > 256 - index)
458 return (EINVAL);
459
460 if ((error = copyout(cm->red + index, rcm->red, count)) != 0)
461 return (error);
462 if ((error = copyout(cm->green + index, rcm->green, count)) != 0)
463 return (error);
464 if ((error = copyout(cm->blue + index, rcm->blue, count)) != 0)
465 return (error);
466
467 return (0);
468 }
469
470 int
471 rfx_putcmap(struct rfx_cmap *cm, struct wsdisplay_cmap *rcm)
472 {
473 u_int index = rcm->index, count = rcm->count;
474 u_int8_t red[256], green[256], blue[256];
475 int error;
476
477 if (index >= 256 || count > 256 - index)
478 return (EINVAL);
479
480 if ((error = copyin(rcm->red, red, count)) != 0)
481 return (error);
482 if ((error = copyin(rcm->green, green, count)) != 0)
483 return (error);
484 if ((error = copyin(rcm->blue, blue, count)) != 0)
485 return (error);
486
487 bcopy(red, cm->red + index, count);
488 bcopy(green, cm->green + index, count);
489 bcopy(blue, cm->blue + index, count);
490
491 return (0);
492 }
493
494 void
495 rfx_loadcmap(struct rfx_softc *sc, int start, int ncolors)
496 {
497 u_int8_t *r, *g, *b;
498
499 r = sc->sc_cmap.red + start;
500 g = sc->sc_cmap.green + start;
501 b = sc->sc_cmap.blue + start;
502
503 start += BT463_IREG_CPALETTE_RAM;
504 sc->sc_ramdac[BT463_REG_ADDR_LOW] = start & 0xff;
505 sc->sc_ramdac[BT463_REG_ADDR_HIGH] = (start >> 8) & 0xff;
506
507 while (ncolors-- != 0) {
508 sc->sc_ramdac[BT463_REG_CMAP_DATA] = *r++;
509 sc->sc_ramdac[BT463_REG_CMAP_DATA] = *g++;
510 sc->sc_ramdac[BT463_REG_CMAP_DATA] = *b++;
511 }
512 }
513
514
515
516
517
518 int
519 rfx_initialize(struct rfx_softc *sc, struct sbus_attach_args *sa,
520 struct rfx_config *cf)
521 {
522 u_int32_t *data, offset, value;
523 size_t cnt;
524 bus_space_handle_t bh;
525 int error;
526
527
528
529
530 if ((error = sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset +
531 RFX_INIT_ADDR, RFX_INIT_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh)) != 0) {
532 printf("\n%s: couldn't map initialization data\n",
533 sc->sc_sunfb.sf_dev.dv_xname);
534 return error;
535 }
536 data = (u_int32_t *)bus_space_vaddr(sa->sa_bustag, bh);
537
538
539
540
541 data += RFX_INIT_OFFSET / sizeof(u_int32_t);
542 cnt = (RFX_INIT_SIZE - RFX_INIT_OFFSET) / sizeof(u_int32_t);
543 cnt >>= 1;
544
545
546
547
548 while (cnt != 0) {
549 offset = *data++;
550 value = *data++;
551
552 if (offset == (u_int32_t)-1 && value == (u_int32_t)-1)
553 break;
554
555
556 if (cf->version <= 1) {
557 offset = letoh32(offset);
558 value = letoh32(offset);
559 }
560
561 if (offset & (1 << 31)) {
562 offset = (offset & ~(1 << 31)) - RFX_RAMDAC_ADDR;
563 if (offset < RFX_RAMDAC_SIZE)
564 sc->sc_ramdac[offset] = value >> 24;
565 } else {
566 offset -= RFX_CONTROL_ADDR;
567 if (offset < RFX_CONTROL_SIZE)
568 sc->sc_ctrl[offset >> 2] = value;
569 }
570
571 cnt--;
572 }
573
574 #ifdef DEBUG
575 if (cnt != 0)
576 printf("%s: incoherent initialization data!\n");
577 #endif
578
579 bus_space_unmap(sa->sa_bustag, bh, RFX_INIT_SIZE);
580
581 return 0;
582 }