FreeBSD/Linux Kernel Cross Reference
sys/dev/tc/mfb.c
1 /* $NetBSD: mfb.c,v 1.41 2003/12/20 07:10:00 nisimura Exp $ */
2
3 /*
4 * Copyright (c) 1998, 1999 Tohru Nishimura. 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. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Tohru Nishimura
17 * for the NetBSD Project.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: mfb.c,v 1.41 2003/12/20 07:10:00 nisimura Exp $");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/device.h>
40 #include <sys/malloc.h>
41 #include <sys/buf.h>
42 #include <sys/ioctl.h>
43
44 #include <machine/bus.h>
45 #include <machine/intr.h>
46
47 #include <dev/wscons/wsconsio.h>
48 #include <dev/wscons/wsdisplayvar.h>
49
50 #include <dev/rasops/rasops.h>
51 #include <dev/wsfont/wsfont.h>
52
53 #include <dev/tc/tcvar.h>
54 #include <dev/ic/bt431reg.h>
55
56 #include <uvm/uvm_extern.h>
57
58 #if defined(pmax)
59 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
60 #endif
61
62 #if defined(alpha)
63 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
64 #endif
65
66 /* Bt455 hardware registers, memory-mapped in 32bit stride */
67 #define bt_reg 0x0
68 #define bt_cmap 0x4
69 #define bt_clr 0x8
70 #define bt_ovly 0xc
71
72 /* Bt431 hardware registers, memory-mapped in 32bit stride */
73 #define bt_lo 0x0
74 #define bt_hi 0x4
75 #define bt_ram 0x8
76 #define bt_ctl 0xc
77
78 #define REGWRITE32(p,i,v) do { \
79 *(volatile u_int32_t *)((p) + (i)) = (v); tc_wmb(); \
80 } while (0)
81
82 #define SELECT455(p,r) do { \
83 REGWRITE32((p), bt_reg, (r)); \
84 REGWRITE32((p), bt_clr, 0); \
85 } while (0)
86
87 #define TWIN(x) ((x)|((x) << 8))
88 #define TWIN_LO(x) (twin = (x) & 0x00ff, twin << 8 | twin)
89 #define TWIN_HI(x) (twin = (x) & 0xff00, twin | twin >> 8)
90
91 #define SELECT431(p,r) do { \
92 REGWRITE32((p), bt_lo, TWIN(r)); \
93 REGWRITE32((p), bt_hi, 0); \
94 } while (0)
95
96 struct hwcursor64 {
97 struct wsdisplay_curpos cc_pos;
98 struct wsdisplay_curpos cc_hot;
99 struct wsdisplay_curpos cc_size;
100 struct wsdisplay_curpos cc_magic;
101 #define CURSOR_MAX_SIZE 64
102 u_int8_t cc_color[6];
103 u_int64_t cc_image[CURSOR_MAX_SIZE];
104 u_int64_t cc_mask[CURSOR_MAX_SIZE];
105 };
106
107 struct mfb_softc {
108 struct device sc_dev;
109 vaddr_t sc_vaddr;
110 size_t sc_size;
111 struct rasops_info *sc_ri;
112 struct hwcursor64 sc_cursor; /* software copy of cursor */
113 int sc_blanked;
114 int sc_curenb; /* cursor sprite enabled */
115 int sc_changed; /* need update of hardware */
116 int nscreens;
117 };
118
119 #define MX_MAGIC_X 360
120 #define MX_MAGIC_Y 36
121
122 #define MX_FB_OFFSET 0x200000
123 #define MX_FB_SIZE 0x200000
124 #define MX_BT455_OFFSET 0x100000
125 #define MX_BT431_OFFSET 0x180000
126 #define MX_IREQ_OFFSET 0x080000 /* Interrupt req. control */
127
128 static int mfbmatch(struct device *, struct cfdata *, void *);
129 static void mfbattach(struct device *, struct device *, void *);
130
131 CFATTACH_DECL(mfb, sizeof(struct mfb_softc),
132 mfbmatch, mfbattach, NULL, NULL);
133
134 static void mfb_common_init(struct rasops_info *);
135 static struct rasops_info mfb_console_ri;
136 static tc_addr_t mfb_consaddr;
137
138 static struct wsscreen_descr mfb_stdscreen = {
139 "std", 0, 0,
140 0, /* textops */
141 0, 0,
142 WSSCREEN_REVERSE
143 };
144
145 static const struct wsscreen_descr *_mfb_scrlist[] = {
146 &mfb_stdscreen,
147 };
148
149 static const struct wsscreen_list mfb_screenlist = {
150 sizeof(_mfb_scrlist) / sizeof(struct wsscreen_descr *), _mfb_scrlist
151 };
152
153 static int mfbioctl(void *, u_long, caddr_t, int, struct proc *);
154 static paddr_t mfbmmap(void *, off_t, int);
155
156 static int mfb_alloc_screen(void *, const struct wsscreen_descr *,
157 void **, int *, int *, long *);
158 static void mfb_free_screen(void *, void *);
159 static int mfb_show_screen(void *, void *, int,
160 void (*) (void *, int, int), void *);
161
162 static const struct wsdisplay_accessops mfb_accessops = {
163 mfbioctl,
164 mfbmmap,
165 mfb_alloc_screen,
166 mfb_free_screen,
167 mfb_show_screen,
168 0 /* load_font */
169 };
170
171 int mfb_cnattach(tc_addr_t);
172 static int mfbintr(void *);
173 static void mfbhwinit(caddr_t);
174
175 static int set_cursor(struct mfb_softc *, struct wsdisplay_cursor *);
176 static int get_cursor(struct mfb_softc *, struct wsdisplay_cursor *);
177 static void set_curpos(struct mfb_softc *, struct wsdisplay_curpos *);
178
179 /* bit order reverse */
180 static const u_int8_t flip[256] = {
181 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
182 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
183 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
184 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
185 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
186 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
187 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
188 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
189 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
190 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
191 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
192 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
193 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
194 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
195 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
196 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
197 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
198 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
199 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
200 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
201 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
202 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
203 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
204 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
205 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
206 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
207 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
208 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
209 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
210 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
211 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
212 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
213 };
214
215 static int
216 mfbmatch(parent, match, aux)
217 struct device *parent;
218 struct cfdata *match;
219 void *aux;
220 {
221 struct tc_attach_args *ta = aux;
222
223 if (strncmp("PMAG-AA ", ta->ta_modname, TC_ROM_LLEN) != 0)
224 return (0);
225
226 return (1);
227 }
228
229 static void
230 mfbattach(parent, self, aux)
231 struct device *parent, *self;
232 void *aux;
233 {
234 struct mfb_softc *sc = (struct mfb_softc *)self;
235 struct tc_attach_args *ta = aux;
236 struct rasops_info *ri;
237 struct wsemuldisplaydev_attach_args waa;
238 int console;
239 volatile register int junk;
240
241 console = (ta->ta_addr == mfb_consaddr);
242 if (console) {
243 sc->sc_ri = ri = &mfb_console_ri;
244 sc->nscreens = 1;
245 }
246 else {
247 MALLOC(ri, struct rasops_info *, sizeof(struct rasops_info),
248 M_DEVBUF, M_NOWAIT);
249 if (ri == NULL) {
250 printf(": can't alloc memory\n");
251 return;
252 }
253 memset(ri, 0, sizeof(struct rasops_info));
254
255 ri->ri_hw = (void *)ta->ta_addr;
256 mfb_common_init(ri);
257 sc->sc_ri = ri;
258 }
259 printf(": %dx%d, 1bpp\n", ri->ri_width, ri->ri_height);
260
261 sc->sc_vaddr = ta->ta_addr;
262 sc->sc_cursor.cc_magic.x = MX_MAGIC_X;
263 sc->sc_cursor.cc_magic.y = MX_MAGIC_Y;
264 sc->sc_blanked = sc->sc_curenb = 0;
265
266 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, mfbintr, sc);
267
268 /* clear any pending interrupts */
269 *(u_int8_t *)((caddr_t)ri->ri_hw + MX_IREQ_OFFSET) = 0;
270 junk = *(u_int8_t *)((caddr_t)ri->ri_hw + MX_IREQ_OFFSET);
271 *(u_int8_t *)((caddr_t)ri->ri_hw + MX_IREQ_OFFSET) = 1;
272
273 waa.console = console;
274 waa.scrdata = &mfb_screenlist;
275 waa.accessops = &mfb_accessops;
276 waa.accesscookie = sc;
277
278 config_found(self, &waa, wsemuldisplaydevprint);
279 }
280
281 static void
282 mfb_common_init(ri)
283 struct rasops_info *ri;
284 {
285 caddr_t base;
286 int cookie;
287
288 base = (caddr_t)ri->ri_hw;
289
290 /* initialize colormap and cursor hardware */
291 mfbhwinit(base);
292
293 ri->ri_flg = RI_CENTER | RI_FORCEMONO;
294 ri->ri_depth = 8; /* !! watch out !! */
295 ri->ri_width = 1280;
296 ri->ri_height = 1024;
297 ri->ri_stride = 2048;
298 ri->ri_bits = base + MX_FB_OFFSET;
299
300 /* clear the screen */
301 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
302
303 wsfont_init();
304 /* prefer 12 pixel wide font */
305 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_L2R,
306 WSDISPLAY_FONTORDER_L2R);
307 if (cookie <= 0)
308 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
309 WSDISPLAY_FONTORDER_L2R);
310 if (cookie <= 0) {
311 printf("mfb: font table is empty\n");
312 return;
313 }
314
315 if (wsfont_lock(cookie, &ri->ri_font)) {
316 printf("mfb: couldn't lock font\n");
317 return;
318 }
319 ri->ri_wsfcookie = cookie;
320
321 rasops_init(ri, 34, 80);
322
323 /* XXX shouldn't be global */
324 mfb_stdscreen.nrows = ri->ri_rows;
325 mfb_stdscreen.ncols = ri->ri_cols;
326 mfb_stdscreen.textops = &ri->ri_ops;
327 mfb_stdscreen.capabilities = ri->ri_caps;
328 }
329
330 static int
331 mfbioctl(v, cmd, data, flag, p)
332 void *v;
333 u_long cmd;
334 caddr_t data;
335 int flag;
336 struct proc *p;
337 {
338 struct mfb_softc *sc = v;
339 struct rasops_info *ri = sc->sc_ri;
340 int turnoff, s;
341
342 switch (cmd) {
343 case WSDISPLAYIO_GTYPE:
344 *(u_int *)data = WSDISPLAY_TYPE_MFB;
345 return (0);
346
347 case WSDISPLAYIO_GINFO:
348 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
349 wsd_fbip->height = ri->ri_height;
350 wsd_fbip->width = ri->ri_width;
351 wsd_fbip->depth = ri->ri_depth;
352 wsd_fbip->cmsize = 0;
353 #undef fbt
354 return (0);
355
356 case WSDISPLAYIO_GETCMAP:
357 case WSDISPLAYIO_PUTCMAP:
358 return (EPASSTHROUGH);
359
360 case WSDISPLAYIO_SVIDEO:
361 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
362 if ((sc->sc_blanked == 0) ^ turnoff) {
363 sc->sc_blanked = turnoff;
364 #if 0 /* XXX later XXX */
365 To turn off,
366 - assign Bt455 cmap[1].green with value 0 (black),
367 - assign Bt431 register #0 with value 0x04 to hide sprite cursor.
368 #endif /* XXX XXX XXX */
369 }
370 return (0);
371
372 case WSDISPLAYIO_GVIDEO:
373 *(u_int *)data = sc->sc_blanked ?
374 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
375 return (0);
376
377 case WSDISPLAYIO_GCURPOS:
378 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
379 return (0);
380
381 case WSDISPLAYIO_SCURPOS:
382 s = spltty();
383 set_curpos(sc, (struct wsdisplay_curpos *)data);
384 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
385 splx(s);
386 return (0);
387
388 case WSDISPLAYIO_GCURMAX:
389 ((struct wsdisplay_curpos *)data)->x =
390 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
391 return (0);
392
393 case WSDISPLAYIO_GCURSOR:
394 return get_cursor(sc, (struct wsdisplay_cursor *)data);
395
396 case WSDISPLAYIO_SCURSOR:
397 return set_cursor(sc, (struct wsdisplay_cursor *)data);
398
399 case WSDISPLAYIO_SMODE:
400 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
401 s = spltty();
402 sc->sc_curenb = 0;
403 sc->sc_blanked = 0;
404 sc->sc_changed |= WSDISPLAY_CURSOR_DOCUR;
405 splx(s);
406 }
407 return (0);
408 }
409 return (EPASSTHROUGH);
410 }
411
412 static paddr_t
413 mfbmmap(v, offset, prot)
414 void *v;
415 off_t offset;
416 int prot;
417 {
418 struct mfb_softc *sc = v;
419
420 if (offset >= MX_FB_SIZE || offset < 0)
421 return (-1);
422 return machine_btop(sc->sc_vaddr + MX_FB_OFFSET + offset);
423 }
424
425 static int
426 mfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
427 void *v;
428 const struct wsscreen_descr *type;
429 void **cookiep;
430 int *curxp, *curyp;
431 long *attrp;
432 {
433 struct mfb_softc *sc = v;
434 struct rasops_info *ri = sc->sc_ri;
435 long defattr;
436
437 if (sc->nscreens > 0)
438 return (ENOMEM);
439
440 *cookiep = ri; /* one and only for now */
441 *curxp = 0;
442 *curyp = 0;
443 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
444 *attrp = defattr;
445 sc->nscreens++;
446 return (0);
447 }
448
449 static void
450 mfb_free_screen(v, cookie)
451 void *v;
452 void *cookie;
453 {
454 struct mfb_softc *sc = v;
455
456 if (sc->sc_ri == &mfb_console_ri)
457 panic("mfb_free_screen: console");
458
459 sc->nscreens--;
460 }
461
462 static int
463 mfb_show_screen(v, cookie, waitok, cb, cbarg)
464 void *v;
465 void *cookie;
466 int waitok;
467 void (*cb)(void *, int, int);
468 void *cbarg;
469 {
470
471 return (0);
472 }
473
474 /* EXPORT */ int
475 mfb_cnattach(addr)
476 tc_addr_t addr;
477 {
478 struct rasops_info *ri;
479 long defattr;
480
481 ri = &mfb_console_ri;
482 ri->ri_hw = (void *)addr;
483 mfb_common_init(ri);
484 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
485 wsdisplay_cnattach(&mfb_stdscreen, ri, 0, 0, defattr);
486 mfb_consaddr = addr;
487 return (0);
488 }
489
490 static int
491 mfbintr(arg)
492 void *arg;
493 {
494 struct mfb_softc *sc = arg;
495 caddr_t base, vdac, curs;
496 int v;
497 volatile register int junk;
498
499 base = (caddr_t)sc->sc_ri->ri_hw;
500 junk = *(u_int8_t *)(base + MX_IREQ_OFFSET);
501 #if 0
502 *(u_int8_t *)(base + MX_IREQ_OFFSET) = 0;
503 #endif
504 if (sc->sc_changed == 0)
505 return (1);
506
507 vdac = base + MX_BT455_OFFSET;
508 curs = base + MX_BT431_OFFSET;
509 v = sc->sc_changed;
510 if (v & WSDISPLAY_CURSOR_DOCUR) {
511 int onoff;
512
513 onoff = (sc->sc_curenb) ? 0x4444 : 0x0404;
514 SELECT431(curs, BT431_REG_COMMAND);
515 REGWRITE32(curs, bt_ctl, onoff);
516 }
517 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
518 int x, y;
519 u_int32_t twin;
520
521 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
522 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
523
524 x += sc->sc_cursor.cc_magic.x;
525 y += sc->sc_cursor.cc_magic.y;
526
527 SELECT431(curs, BT431_REG_CURSOR_X_LOW);
528 REGWRITE32(curs, bt_ctl, TWIN_LO(x));
529 REGWRITE32(curs, bt_ctl, TWIN_HI(x));
530 REGWRITE32(curs, bt_ctl, TWIN_LO(y));
531 REGWRITE32(curs, bt_ctl, TWIN_HI(y));
532 }
533 if (v & WSDISPLAY_CURSOR_DOCMAP) {
534 u_int8_t *cp = sc->sc_cursor.cc_color;
535
536 SELECT455(vdac, 8);
537 REGWRITE32(vdac, bt_cmap, 0);
538 REGWRITE32(vdac, bt_cmap, cp[1]);
539 REGWRITE32(vdac, bt_cmap, 0);
540
541 REGWRITE32(vdac, bt_cmap, 0);
542 REGWRITE32(vdac, bt_cmap, cp[1]);
543 REGWRITE32(vdac, bt_cmap, 0);
544
545 REGWRITE32(vdac, bt_ovly, 0);
546 REGWRITE32(vdac, bt_ovly, cp[0]);
547 REGWRITE32(vdac, bt_ovly, 0);
548 }
549 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
550 u_int8_t *ip, *mp, img, msk;
551 int bcnt;
552
553 ip = (u_int8_t *)sc->sc_cursor.cc_image;
554 mp = (u_int8_t *)sc->sc_cursor.cc_mask;
555 bcnt = 0;
556 SELECT431(curs, BT431_REG_CRAM_BASE);
557
558 /* 64 pixel scan line is consisted with 16 byte cursor ram */
559 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
560 /* pad right half 32 pixel when smaller than 33 */
561 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
562 REGWRITE32(curs, bt_ram, 0);
563 }
564 else {
565 int half;
566
567 img = *ip++;
568 msk = *mp++;
569 img &= msk; /* cookie off image */
570 half = (flip[msk] << 8) | flip[img];
571 REGWRITE32(curs, bt_ram, half);
572 }
573 bcnt += 2;
574 }
575 /* pad unoccupied scan lines */
576 while (bcnt < CURSOR_MAX_SIZE * 16) {
577 REGWRITE32(curs, bt_ram, 0);
578 bcnt += 2;
579 }
580 }
581 sc->sc_changed = 0;
582 return (1);
583 }
584
585 static void
586 mfbhwinit(mfbbase)
587 caddr_t mfbbase;
588 {
589 caddr_t vdac, curs;
590 int i;
591
592 vdac = mfbbase + MX_BT455_OFFSET;
593 curs = mfbbase + MX_BT431_OFFSET;
594 SELECT431(curs, BT431_REG_COMMAND);
595 REGWRITE32(curs, bt_ctl, 0x0404);
596 REGWRITE32(curs, bt_ctl, 0); /* XLO */
597 REGWRITE32(curs, bt_ctl, 0); /* XHI */
598 REGWRITE32(curs, bt_ctl, 0); /* YLO */
599 REGWRITE32(curs, bt_ctl, 0); /* YHI */
600 REGWRITE32(curs, bt_ctl, 0); /* XWLO */
601 REGWRITE32(curs, bt_ctl, 0); /* XWHI */
602 REGWRITE32(curs, bt_ctl, 0); /* WYLO */
603 REGWRITE32(curs, bt_ctl, 0); /* WYLO */
604 REGWRITE32(curs, bt_ctl, 0); /* WWLO */
605 REGWRITE32(curs, bt_ctl, 0); /* WWHI */
606 REGWRITE32(curs, bt_ctl, 0); /* WHLO */
607 REGWRITE32(curs, bt_ctl, 0); /* WHHI */
608
609 /* 0: black, 1: white, 8,9: cursor mask, ovly: cursor image */
610 SELECT455(vdac, 0);
611 REGWRITE32(vdac, bt_cmap, 0);
612 REGWRITE32(vdac, bt_cmap, 0);
613 REGWRITE32(vdac, bt_cmap, 0);
614 REGWRITE32(vdac, bt_cmap, 0);
615 REGWRITE32(vdac, bt_cmap, 0xff);
616 REGWRITE32(vdac, bt_cmap, 0);
617 for (i = 2; i < 16; i++) {
618 REGWRITE32(vdac, bt_cmap, 0);
619 REGWRITE32(vdac, bt_cmap, 0);
620 REGWRITE32(vdac, bt_cmap, 0);
621 }
622 REGWRITE32(vdac, bt_ovly, 0);
623 REGWRITE32(vdac, bt_ovly, 0xff);
624 REGWRITE32(vdac, bt_ovly, 0);
625
626 SELECT431(curs, BT431_REG_CRAM_BASE);
627 for (i = 0; i < 512; i++) {
628 REGWRITE32(curs, bt_ram, 0);
629 }
630 }
631
632 static int
633 set_cursor(sc, p)
634 struct mfb_softc *sc;
635 struct wsdisplay_cursor *p;
636 {
637 #define cc (&sc->sc_cursor)
638 u_int v, count = 0, icount = 0, index = 0;
639 uint64_t image[CURSOR_MAX_SIZE];
640 uint64_t mask[CURSOR_MAX_SIZE];
641 uint8_t color[6];
642 int error, s;
643
644 v = p->which;
645 if (v & WSDISPLAY_CURSOR_DOCMAP) {
646 index = p->cmap.index;
647 count = p->cmap.count;
648 if (index >= 2 || (index + count) > 2)
649 return (EINVAL);
650 error = copyin(p->cmap.red, &color[index], count);
651 if (error)
652 return error;
653 }
654 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
655 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
656 return (EINVAL);
657 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
658 error = copyin(p->image, image, icount);
659 if (error)
660 return error;
661 error = copyin(p->mask, mask, icount);
662 if (error)
663 return error;
664 }
665
666 s = spltty();
667 if (v & WSDISPLAY_CURSOR_DOCUR)
668 sc->sc_curenb = p->enable;
669 if (v & WSDISPLAY_CURSOR_DOPOS)
670 set_curpos(sc, &p->pos);
671 if (v & WSDISPLAY_CURSOR_DOHOT)
672 cc->cc_hot = p->hot;
673 if (v & WSDISPLAY_CURSOR_DOCMAP)
674 memcpy(&cc->cc_color[index], &color[index], count);
675 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
676 cc->cc_size = p->size;
677 memset(cc->cc_image, 0, sizeof cc->cc_image);
678 memcpy(cc->cc_image, image, icount);
679 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
680 memcpy(cc->cc_mask, mask, icount);
681 }
682 sc->sc_changed |= v;
683 splx(s);
684
685 return (0);
686 #undef cc
687 }
688
689 static int
690 get_cursor(sc, p)
691 struct mfb_softc *sc;
692 struct wsdisplay_cursor *p;
693 {
694 return (EPASSTHROUGH); /* XXX */
695 }
696
697 static void
698 set_curpos(sc, curpos)
699 struct mfb_softc *sc;
700 struct wsdisplay_curpos *curpos;
701 {
702 struct rasops_info *ri = sc->sc_ri;
703 int x = curpos->x, y = curpos->y;
704
705 if (y < 0)
706 y = 0;
707 else if (y > ri->ri_height)
708 y = ri->ri_height;
709 if (x < 0)
710 x = 0;
711 else if (x > ri->ri_width)
712 x = ri->ri_width;
713 sc->sc_cursor.cc_pos.x = x;
714 sc->sc_cursor.cc_pos.y = y;
715 }
Cache object: 06b8be00ee8685bd17bc06cb29cc76d7
|