Annotation of sys/arch/vax/vsa/lcg.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: lcg.c,v 1.10 2006/11/29 12:13:54 miod Exp $ */
2: /*
3: * Copyright (c) 2006 Miodrag Vallat.
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice, this permission notice, and the disclaimer below
8: * appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18: /*
19: * Copyright (c) 2003, 2004 Blaz Antonic
20: * All rights reserved.
21: *
22: * Redistribution and use in source and binary forms, with or without
23: * modification, are permitted provided that the following conditions
24: * are met:
25: * 1. Redistributions of source code must retain the above copyright
26: * notice, this list of conditions and the following disclaimer.
27: * 2. Redistributions in binary form must reproduce the above copyright
28: * notice, this list of conditions and the following disclaimer in the
29: * documentation and/or other materials provided with the distribution.
30: * 3. All advertising materials mentioning features or use of this software
31: * must display the abovementioned copyrights
32: * 4. The name of the author may not be used to endorse or promote products
33: * derived from this software without specific prior written permission
34: *
35: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
36: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
38: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
39: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
40: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
44: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45: */
46:
47: #include <sys/param.h>
48: #include <sys/device.h>
49: #include <sys/systm.h>
50: #include <sys/malloc.h>
51: #include <sys/conf.h>
52: #include <sys/kernel.h>
53:
54: #include <machine/vsbus.h>
55: #include <machine/scb.h>
56: #include <machine/sid.h>
57: #include <machine/cpu.h>
58:
59: #include <uvm/uvm_extern.h>
60:
61: #include <dev/cons.h>
62:
63: #include <dev/wscons/wsconsio.h>
64: #include <dev/wscons/wsdisplayvar.h>
65: #include <dev/rasops/rasops.h>
66:
67: #include <vax/vsa/lcgreg.h>
68:
69: #define LCG_CONFIG_ADDR 0x200f0010 /* configuration register */
70: #define LCG_REG_ADDR 0x20100000 /* registers */
71: #define LCG_REG_SIZE 0x4000
72: #define LCG_LUT_ADDR 0x21800000 /* colormap */
73: #define LCG_LUT_OFFSET 0x0800
74: #define LCG_LUT_SIZE 0x0800
75: #define LCG_FB_ADDR 0x21801000 /* frame buffer */
76:
77: int lcg_match(struct device *, void *, void *);
78: void lcg_attach(struct device *, struct device *, void *);
79:
80: struct lcg_screen {
81: struct rasops_info ss_ri;
82: u_int32_t ss_cfg;
83: u_int ss_width, ss_height, ss_depth;
84: u_int ss_fbsize; /* visible part only */
85: caddr_t ss_addr; /* frame buffer address */
86: vaddr_t ss_reg;
87: volatile u_int8_t *ss_lut;
88: u_int8_t ss_cmap[256 * 3];
89: };
90:
91: /* for console */
92: struct lcg_screen lcg_consscr;
93:
94: struct lcg_softc {
95: struct device sc_dev;
96: struct lcg_screen *sc_scr;
97: int sc_nscreens;
98: };
99:
100: struct cfattach lcg_ca = {
101: sizeof(struct lcg_softc), lcg_match, lcg_attach,
102: };
103:
104: struct cfdriver lcg_cd = {
105: NULL, "lcg", DV_DULL
106: };
107:
108: struct wsscreen_descr lcg_stdscreen = {
109: "std",
110: };
111:
112: const struct wsscreen_descr *_lcg_scrlist[] = {
113: &lcg_stdscreen,
114: };
115:
116: const struct wsscreen_list lcg_screenlist = {
117: sizeof(_lcg_scrlist) / sizeof(struct wsscreen_descr *),
118: _lcg_scrlist,
119: };
120:
121: int lcg_ioctl(void *, u_long, caddr_t, int, struct proc *);
122: paddr_t lcg_mmap(void *, off_t, int);
123: int lcg_alloc_screen(void *, const struct wsscreen_descr *,
124: void **, int *, int *, long *);
125: void lcg_free_screen(void *, void *);
126: int lcg_show_screen(void *, void *, int,
127: void (*) (void *, int, int), void *);
128: void lcg_burner(void *, u_int, u_int);
129:
130: const struct wsdisplay_accessops lcg_accessops = {
131: lcg_ioctl,
132: lcg_mmap,
133: lcg_alloc_screen,
134: lcg_free_screen,
135: lcg_show_screen,
136: NULL, /* load_font */
137: NULL, /* scrollback */
138: NULL, /* getchar */
139: lcg_burner
140: };
141:
142: int lcg_alloc_attr(void *, int, int, int, long *);
143: int lcg_getcmap(struct lcg_screen *, struct wsdisplay_cmap *);
144: void lcg_loadcmap(struct lcg_screen *, int, int);
145: int lcg_probe_screen(u_int32_t, u_int *, u_int *);
146: int lcg_putcmap(struct lcg_screen *, struct wsdisplay_cmap *);
147: void lcg_resetcmap(struct lcg_screen *);
148: int lcg_setup_screen(struct lcg_screen *);
149:
150: #define lcg_read_reg(ss, regno) \
151: *(volatile u_int32_t *)((ss)->ss_reg + (regno))
152: #define lcg_write_reg(ss, regno, val) \
153: *(volatile u_int32_t *)((ss)->ss_reg + (regno)) = (val)
154:
155: int
156: lcg_match(struct device *parent, void *vcf, void *aux)
157: {
158: struct vsbus_softc *sc = (void *)parent;
159: struct vsbus_attach_args *va = aux;
160: vaddr_t cfgreg;
161: int depth, missing;
162: volatile u_int8_t *ch;
163:
164: switch (vax_boardtype) {
165: default:
166: return (0);
167:
168: case VAX_BTYP_46:
169: case VAX_BTYP_48:
170: if (va->va_paddr != LCG_REG_ADDR)
171: return (0);
172:
173: break;
174: }
175:
176: /*
177: * Check the configuration register.
178: * This is done to sort out empty frame buffer slots, since the video
179: * memory test sometimes passes!
180: */
181: cfgreg = vax_map_physmem(LCG_CONFIG_ADDR, 1);
182: depth = lcg_probe_screen(*(volatile u_int32_t *)cfgreg, NULL, NULL);
183: vax_unmap_physmem(cfgreg, 1);
184: if (depth < 0) /* no frame buffer */
185: return (0);
186:
187: /*
188: * Check for video memory.
189: * We can not use badaddr() on these models.
190: */
191: missing = 0;
192: ch = (volatile u_int8_t *)vax_map_physmem(LCG_FB_ADDR, 1);
193: *ch = 0x01;
194: if ((*ch & 0x01) == 0)
195: missing = 1;
196: else {
197: *ch = 0x00;
198: if ((*ch & 0x01) != 0)
199: missing = 1;
200: }
201: vax_unmap_physmem((vaddr_t)ch, 1);
202: if (missing != 0)
203: return (0);
204:
205: sc->sc_mask = 0x04; /* XXX - should be generated */
206: scb_fake(0x120, 0x15);
207: return (20);
208: }
209:
210: void
211: lcg_attach(struct device *parent, struct device *self, void *aux)
212: {
213: struct lcg_softc *sc = (struct lcg_softc *)self;
214: struct lcg_screen *ss;
215: struct wsemuldisplaydev_attach_args aa;
216: vaddr_t tmp;
217: u_int32_t cfg;
218: int console;
219: extern struct consdev wsdisplay_cons;
220:
221: console = (vax_confdata & 0x100) == 0 && cn_tab == &wsdisplay_cons;
222:
223: /*
224: * Check for a recognized configuration register.
225: * If we do not recognize it, print it and do not attach - so that
226: * this gets noticed...
227: */
228: if (!console) {
229: tmp = vax_map_physmem(LCG_CONFIG_ADDR, 1);
230: if (tmp == NULL) {
231: printf("\n%s: can not map configuration register\n",
232: self->dv_xname);
233: return;
234: }
235: cfg = *(volatile u_int32_t *)tmp;
236: vax_unmap_physmem(tmp, 1);
237:
238: if (lcg_probe_screen(cfg, NULL, NULL) <= 0) {
239: printf("\n%s:"
240: " unrecognized configuration register %08x\n",
241: self->dv_xname, cfg);
242: return;
243: }
244: }
245:
246: if (console) {
247: ss = &lcg_consscr;
248: sc->sc_nscreens = 1;
249: } else {
250: ss = malloc(sizeof(struct lcg_screen), M_DEVBUF, M_NOWAIT);
251: if (ss == NULL) {
252: printf(": can not allocate memory\n");
253: return;
254: }
255: bzero(ss, sizeof(struct lcg_screen));
256:
257: ss->ss_cfg = cfg;
258: ss->ss_depth = lcg_probe_screen(ss->ss_cfg,
259: &ss->ss_width, &ss->ss_height);
260: ss->ss_fbsize =
261: roundup(ss->ss_width * ss->ss_height, PAGE_SIZE);
262:
263: ss->ss_addr = (caddr_t)vax_map_physmem(LCG_FB_ADDR,
264: ss->ss_fbsize / VAX_NBPG);
265: if (ss->ss_addr == NULL) {
266: printf(": can not map frame buffer\n");
267: goto fail1;
268: }
269:
270: ss->ss_reg = vax_map_physmem(LCG_REG_ADDR,
271: LCG_REG_SIZE / VAX_NBPG);
272: if (ss->ss_reg == 0L) {
273: printf(": can not map registers\n");
274: goto fail2;
275: }
276:
277: ss->ss_lut = (volatile u_int8_t *)vax_map_physmem(LCG_LUT_ADDR +
278: LCG_LUT_OFFSET, LCG_LUT_SIZE / VAX_NBPG);
279: if (ss->ss_lut == NULL) {
280: printf(": can not map color LUT\n");
281: goto fail3;
282: }
283:
284: if (lcg_setup_screen(ss) != 0) {
285: printf(": initialization failed\n");
286: goto fail4;
287: }
288: }
289: sc->sc_scr = ss;
290:
291: printf(": %dx%dx%d frame buffer\n",
292: ss->ss_width, ss->ss_height, ss->ss_depth);
293:
294: aa.console = console;
295: aa.scrdata = &lcg_screenlist;
296: aa.accessops = &lcg_accessops;
297: aa.accesscookie = sc;
298: aa.defaultscreens = 0;
299:
300: config_found(self, &aa, wsemuldisplaydevprint);
301: return;
302:
303: fail4:
304: vax_unmap_physmem((vaddr_t)ss->ss_lut, LCG_LUT_SIZE / VAX_NBPG);
305: fail3:
306: vax_unmap_physmem(ss->ss_reg, LCG_REG_SIZE / VAX_NBPG);
307: fail2:
308: vax_unmap_physmem((vaddr_t)ss->ss_addr, ss->ss_fbsize / VAX_NBPG);
309: fail1:
310: free(ss, M_DEVBUF);
311: }
312:
313: /*
314: * Determine if we have a recognized frame buffer, its resolution and
315: * color depth.
316: */
317: int
318: lcg_probe_screen(u_int32_t cfg, u_int *width, u_int *height)
319: {
320: u_int w, h, d = 8;
321:
322: switch (vax_boardtype) {
323: case VAX_BTYP_46:
324: switch (cfg & 0xf0) {
325: case 0x00:
326: return (-1); /* no hardware */
327: case 0x20:
328: case 0x60:
329: w = 1024; h = 864;
330: break;
331: case 0x40:
332: w = 1024; h = 768;
333: break;
334: case 0x80:
335: d = 4;
336: /* FALLTHROUGH */
337: case 0x90:
338: case 0xb0:
339: w = 1280; h = 1024;
340: break;
341: default:
342: return (0); /* unknown configuration, please help */
343: }
344: break;
345: case VAX_BTYP_48:
346: switch (cfg & 0x07) {
347: case 0x00:
348: return (-1); /* no hardware */
349: case 0x05:
350: w = 1280; h = 1024;
351: break;
352: case 0x06:
353: if (vax_confdata & 0x80) {
354: w = 1024; h = 768;
355: } else {
356: w = 640; h = 480;
357: }
358: break;
359: case 0x07:
360: if (vax_confdata & 0x80) {
361: w = 1024; h = 864;
362: } else {
363: w = 1024; h = 768;
364: }
365: break;
366: default:
367: return (0); /* unknown configuration, please help */
368: }
369: break;
370: }
371:
372: if (width != NULL)
373: *width = w;
374: if (height != NULL)
375: *height = h;
376:
377: return (d);
378: }
379:
380: /*
381: * Initialize anything necessary for an emulating wsdisplay to work (i.e.
382: * pick a font, initialize a rasops structure, setup the accessops callbacks.)
383: */
384: int
385: lcg_setup_screen(struct lcg_screen *ss)
386: {
387: struct rasops_info *ri = &ss->ss_ri;
388:
389: bzero(ri, sizeof(*ri));
390: /*
391: * Since the frame buffer memory is byte addressed, even in low-bpp
392: * mode, initialize a 8bpp rasops engine. We will report a shorter
393: * colormap if necessary, which will allow X to do TRT.
394: */
395: ri->ri_depth = 8;
396: ri->ri_width = ss->ss_width;
397: ri->ri_height = ss->ss_height;
398: ri->ri_stride = ss->ss_width;
399: ri->ri_flg = RI_CLEAR | RI_CENTER;
400: ri->ri_bits = (void *)ss->ss_addr;
401: ri->ri_hw = ss;
402:
403: /*
404: * Ask for an unholy big display, rasops will trim this to more
405: * reasonable values.
406: */
407: if (rasops_init(ri, 160, 160) != 0)
408: return (-1);
409:
410: if (ss->ss_depth < 8) {
411: ri->ri_ops.alloc_attr = lcg_alloc_attr;
412: ri->ri_caps &= ~WSSCREEN_HILIT;
413: }
414:
415: lcg_stdscreen.ncols = ri->ri_cols;
416: lcg_stdscreen.nrows = ri->ri_rows;
417: lcg_stdscreen.textops = &ri->ri_ops;
418: lcg_stdscreen.fontwidth = ri->ri_font->fontwidth;
419: lcg_stdscreen.fontheight = ri->ri_font->fontheight;
420: lcg_stdscreen.capabilities = ri->ri_caps;
421:
422: lcg_resetcmap(ss);
423:
424: return (0);
425: }
426:
427: int
428: lcg_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
429: {
430: struct lcg_softc *sc = v;
431: struct lcg_screen *ss = sc->sc_scr;
432: struct wsdisplay_fbinfo *wdf;
433: struct wsdisplay_cmap *cm;
434: int error;
435:
436: switch (cmd) {
437: case WSDISPLAYIO_GTYPE:
438: *(u_int *)data = WSDISPLAY_TYPE_LCG;
439: break;
440:
441: case WSDISPLAYIO_GINFO:
442: wdf = (struct wsdisplay_fbinfo *)data;
443: wdf->height = ss->ss_height;
444: wdf->width = ss->ss_width;
445: wdf->depth = 8;
446: wdf->cmsize = 1 << ss->ss_depth;
447: break;
448:
449: case WSDISPLAYIO_LINEBYTES:
450: *(u_int *)data = ss->ss_ri.ri_stride;
451: break;
452:
453: case WSDISPLAYIO_GETCMAP:
454: cm = (struct wsdisplay_cmap *)data;
455: error = lcg_getcmap(ss, cm);
456: if (error != 0)
457: return (error);
458: break;
459: case WSDISPLAYIO_PUTCMAP:
460: cm = (struct wsdisplay_cmap *)data;
461: error = lcg_putcmap(ss, cm);
462: if (error != 0)
463: return (error);
464: lcg_loadcmap(ss, cm->index, cm->count);
465: break;
466:
467: case WSDISPLAYIO_GVIDEO:
468: case WSDISPLAYIO_SVIDEO:
469: break;
470:
471: default:
472: return (-1);
473: }
474:
475: return (0);
476: }
477:
478: paddr_t
479: lcg_mmap(void *v, off_t offset, int prot)
480: {
481: struct lcg_softc *sc = v;
482: struct lcg_screen *ss = sc->sc_scr;
483:
484: if (offset >= ss->ss_fbsize || offset < 0)
485: return (-1);
486:
487: return (LCG_FB_ADDR + offset) >> PGSHIFT;
488: }
489:
490: int
491: lcg_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
492: int *curxp, int *curyp, long *defattrp)
493: {
494: struct lcg_softc *sc = v;
495: struct lcg_screen *ss = sc->sc_scr;
496: struct rasops_info *ri = &ss->ss_ri;
497:
498: if (sc->sc_nscreens > 0)
499: return (ENOMEM);
500:
501: *cookiep = ri;
502: *curxp = *curyp = 0;
503: ri->ri_ops.alloc_attr(ri, 0, 0, 0, defattrp);
504: sc->sc_nscreens++;
505:
506: return (0);
507: }
508:
509: void
510: lcg_free_screen(void *v, void *cookie)
511: {
512: struct lcg_softc *sc = v;
513:
514: sc->sc_nscreens--;
515: }
516:
517: int
518: lcg_show_screen(void *v, void *cookie, int waitok,
519: void (*cb)(void *, int, int), void *cbarg)
520: {
521: return (0);
522: }
523:
524: void
525: lcg_burner(void *v, u_int on, u_int flags)
526: {
527: struct lcg_softc *sc = v;
528: struct lcg_screen *ss = sc->sc_scr;
529: u_int32_t vidcfg;
530:
531: vidcfg = lcg_read_reg(ss, LCG_REG_VIDEO_CONFIG);
532: if (on)
533: vidcfg |= VIDEO_ENABLE_VIDEO | VIDEO_SYNC_ENABLE;
534: else {
535: vidcfg &= ~VIDEO_ENABLE_VIDEO;
536: if (flags & WSDISPLAY_BURN_VBLANK)
537: vidcfg &= ~VIDEO_SYNC_ENABLE;
538: }
539: lcg_write_reg(ss, LCG_REG_VIDEO_CONFIG, vidcfg);
540: }
541:
542: /*
543: * Attribute allocator for 4bpp frame buffers.
544: * In such modes, highlighting is not available.
545: */
546: int
547: lcg_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr)
548: {
549: extern int rasops_alloc_cattr(void *, int, int, int, long *);
550:
551: if ((flg & (WSATTR_BLINK | WSATTR_HILIT)) != 0)
552: return (EINVAL);
553:
554: return (rasops_alloc_cattr(cookie, fg, bg, flg, attr));
555: }
556:
557: /*
558: * Colormap handling routines
559: */
560:
561: int
562: lcg_getcmap(struct lcg_screen *ss, struct wsdisplay_cmap *cm)
563: {
564: u_int index = cm->index, count = cm->count, i;
565: u_int colcount = 1 << ss->ss_depth;
566: int error;
567: u_int8_t ramp[256], *c, *r;
568:
569: if (index >= colcount || count > colcount - index)
570: return (EINVAL);
571:
572: /* extract reds */
573: c = ss->ss_cmap + 0 + index * 3;
574: for (i = count, r = ramp; i != 0; i--)
575: *r++ = *c, c += 3;
576: if ((error = copyout(ramp, cm->red, count)) != 0)
577: return (error);
578:
579: /* extract greens */
580: c = ss->ss_cmap + 1 + index * 3;
581: for (i = count, r = ramp; i != 0; i--)
582: *r++ = *c, c += 3;
583: if ((error = copyout(ramp, cm->green, count)) != 0)
584: return (error);
585:
586: /* extract blues */
587: c = ss->ss_cmap + 2 + index * 3;
588: for (i = count, r = ramp; i != 0; i--)
589: *r++ = *c, c += 3;
590: if ((error = copyout(ramp, cm->blue, count)) != 0)
591: return (error);
592:
593: return (0);
594: }
595:
596: int
597: lcg_putcmap(struct lcg_screen *ss, struct wsdisplay_cmap *cm)
598: {
599: u_int index = cm->index, count = cm->count;
600: u_int colcount = 1 << ss->ss_depth;
601: int i, error;
602: u_int8_t r[256], g[256], b[256], *nr, *ng, *nb, *c;
603:
604: if (index >= colcount || count > colcount - index)
605: return (EINVAL);
606:
607: if ((error = copyin(cm->red, r, count)) != 0)
608: return (error);
609: if ((error = copyin(cm->green, g, count)) != 0)
610: return (error);
611: if ((error = copyin(cm->blue, b, count)) != 0)
612: return (error);
613:
614: nr = r, ng = g, nb = b;
615: c = ss->ss_cmap + index * 3;
616: for (i = count; i != 0; i--) {
617: *c++ = *nr++;
618: *c++ = *ng++;
619: *c++ = *nb++;
620: }
621:
622: return (0);
623: }
624:
625: /* Fill the given colormap (LUT) entry. */
626: #define lcg_set_lut_entry(lutptr, cmap, idx, shift) \
627: do { \
628: *(lutptr)++ = LUT_ADRS_REG; \
629: *(lutptr)++ = (idx); \
630: *(lutptr)++ = LUT_COLOR_AUTOINC; \
631: *(lutptr)++ = (*(cmap)++) >> (shift); \
632: *(lutptr)++ = LUT_COLOR_AUTOINC; \
633: *(lutptr)++ = (*(cmap)++) >> (shift); \
634: *(lutptr)++ = LUT_COLOR_AUTOINC; \
635: *(lutptr)++ = (*(cmap)++) >> (shift); \
636: } while (0)
637:
638: void
639: lcg_loadcmap(struct lcg_screen *ss, int from, int count)
640: {
641: const u_int8_t *cmap;
642: u_int i;
643: volatile u_int8_t *lutptr;
644: u_int32_t vidcfg;
645:
646: /* partial updates ignored for now */
647: cmap = ss->ss_cmap;
648: lutptr = ss->ss_lut;
649: if (ss->ss_depth == 8) {
650: for (i = 0; i < 256; i++) {
651: lcg_set_lut_entry(lutptr, cmap, i, 0);
652: }
653: } else {
654: for (i = 0; i < 16; i++) {
655: lcg_set_lut_entry(lutptr, cmap, i, 4);
656: }
657: }
658:
659: /*
660: * Wait for retrace
661: */
662: while (((vidcfg = lcg_read_reg(ss, LCG_REG_VIDEO_CONFIG)) &
663: VIDEO_VSTATE) != VIDEO_VSYNC)
664: DELAY(1);
665:
666: vidcfg &= ~(VIDEO_SHIFT_SEL | VIDEO_MEM_REFRESH_SEL_MASK |
667: VIDEO_LUT_SHIFT_SEL);
668: /* Do full loads if width is 1024 or 2048, split loads otherwise. */
669: if (ss->ss_width == 1024 || ss->ss_width == 2048)
670: vidcfg |= VIDEO_SHIFT_SEL | (1 << VIDEO_MEM_REFRESH_SEL_SHIFT) |
671: VIDEO_LUT_SHIFT_SEL;
672: else
673: vidcfg |= (2 << VIDEO_MEM_REFRESH_SEL_SHIFT);
674: vidcfg |= VIDEO_LUT_LOAD_SIZE; /* 2KB lut */
675: lcg_write_reg(ss, LCG_REG_VIDEO_CONFIG, vidcfg);
676: lcg_write_reg(ss, LCG_REG_LUT_CONSOLE_SEL, LUT_SEL_COLOR);
677: lcg_write_reg(ss, LCG_REG_LUT_COLOR_BASE_W, LCG_LUT_OFFSET);
678: /* Wait for end of retrace */
679: while (((vidcfg = lcg_read_reg(ss, LCG_REG_VIDEO_CONFIG)) &
680: VIDEO_VSTATE) == VIDEO_VSYNC)
681: DELAY(1);
682: lcg_write_reg(ss, LCG_REG_LUT_CONSOLE_SEL, LUT_SEL_CONSOLE);
683: }
684:
685: void
686: lcg_resetcmap(struct lcg_screen *ss)
687: {
688: if (ss->ss_depth == 8)
689: bcopy(rasops_cmap, ss->ss_cmap, sizeof(ss->ss_cmap));
690: else {
691: bcopy(rasops_cmap, ss->ss_cmap, 8 * 3);
692: bcopy(rasops_cmap + 0xf8 * 3, ss->ss_cmap + 8 * 3, 8 * 3);
693: }
694: lcg_loadcmap(ss, 0, 1 << ss->ss_depth);
695: }
696:
697: /*
698: * Console support code
699: */
700:
701: int lcgcnprobe(void);
702: void lcgcninit(void);
703:
704: int
705: lcgcnprobe()
706: {
707: extern vaddr_t virtual_avail;
708: u_int32_t cfg;
709: vaddr_t tmp;
710: volatile u_int8_t *ch;
711:
712: switch (vax_boardtype) {
713: case VAX_BTYP_46:
714: case VAX_BTYP_48:
715: if ((vax_confdata & 0x100) != 0)
716: break; /* doesn't use graphics console */
717:
718: tmp = virtual_avail;
719: ioaccess(tmp, vax_trunc_page(LCG_CONFIG_ADDR), 1);
720: cfg = *(volatile u_int32_t *)
721: (tmp + (LCG_CONFIG_ADDR & VAX_PGOFSET));
722:
723: if (lcg_probe_screen(cfg, NULL, NULL) <= 0)
724: break; /* unsupported configuration */
725:
726: /*
727: * Check for video memory.
728: * We can not use badaddr() on these models.
729: */
730: ioaccess(tmp, LCG_FB_ADDR, 1);
731: ch = (volatile u_int8_t *)tmp;
732: *ch = 0x01;
733: if ((*ch & 0x01) == 0)
734: break;
735: *ch = 0x00;
736: if ((*ch & 0x01) != 0)
737: break;
738:
739: return (1);
740:
741: default:
742: break;
743: }
744:
745: return (0);
746: }
747:
748: /*
749: * Called very early to setup the glass tty as console.
750: * Because it's called before the VM system is initialized, virtual memory
751: * for the framebuffer can be stolen directly without disturbing anything.
752: */
753: void
754: lcgcninit()
755: {
756: struct lcg_screen *ss = &lcg_consscr;
757: extern vaddr_t virtual_avail;
758: vaddr_t tmp;
759: long defattr;
760: struct rasops_info *ri;
761:
762: tmp = virtual_avail;
763: ioaccess(tmp, vax_trunc_page(LCG_CONFIG_ADDR), 1);
764: ss->ss_cfg = *(volatile u_int32_t *)
765: (tmp + (LCG_CONFIG_ADDR & VAX_PGOFSET));
766:
767: ss->ss_depth = lcg_probe_screen(ss->ss_cfg,
768: &ss->ss_width, &ss->ss_height);
769:
770: ss->ss_fbsize = roundup(ss->ss_width * ss->ss_height, PAGE_SIZE);
771:
772: ss->ss_addr = (caddr_t)virtual_avail;
773: virtual_avail += ss->ss_fbsize;
774: ioaccess((vaddr_t)ss->ss_addr, LCG_FB_ADDR, ss->ss_fbsize / VAX_NBPG);
775:
776: ss->ss_reg = virtual_avail;
777: virtual_avail += LCG_REG_SIZE;
778: ioaccess(ss->ss_reg, LCG_REG_ADDR, LCG_REG_SIZE / VAX_NBPG);
779:
780: ss->ss_lut = (volatile u_int8_t *)virtual_avail;
781: virtual_avail += LCG_LUT_SIZE;
782: ioaccess((vaddr_t)ss->ss_lut, LCG_LUT_ADDR + LCG_LUT_OFFSET,
783: LCG_LUT_SIZE / VAX_NBPG);
784:
785: virtual_avail = round_page(virtual_avail);
786:
787: /* this had better not fail as we can't recover there */
788: if (lcg_setup_screen(ss) != 0)
789: panic(__func__);
790:
791: ri = &ss->ss_ri;
792: ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
793: wsdisplay_cnattach(&lcg_stdscreen, ri, 0, 0, defattr);
794: }
CVSweb