1 /* $NetBSD: spx.c,v 1.1 2008/08/12 17:54:47 hans Exp $ */
3 * SPX/LCSPX/SPXg/SPXgt accelerated framebuffer driver for NetBSD/VAX
4 * Copyright (c) 2005 Blaz Antonic
7 * This software contains code written by Michael L. Hitch.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the abovementioned copyrights
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: spx.c,v 1.1 2008/08/12 17:54:47 hans Exp $");
37 #include <sys/param.h>
38 #include <sys/device.h>
39 #include <sys/systm.h>
40 #include <sys/callout.h>
42 #include <sys/malloc.h>
44 #include <sys/kernel.h>
48 #include <machine/vsbus.h>
49 #include <machine/sid.h>
50 #include <machine/cpu.h>
51 #include <machine/ka420.h>
55 #include <dev/dec/dzreg.h>
56 #include <dev/dec/dzvar.h>
57 #include <dev/dec/dzkbdvar.h>
59 #include <dev/wscons/wsdisplayvar.h>
60 #include <dev/wscons/wsconsio.h>
61 #include <dev/wscons/wscons_callbacks.h>
62 #include <dev/wsfont/wsfont.h>
64 #include "machine/scb.h"
68 #define CONF_LCSPX 0x02
69 #define CONF_SPXg 0x10
74 /* Screen hardware defs */
75 #define SPX_FB_ADDR 0x38000000 /* Frame buffer */
76 #define SPXg_FB_ADDR_KA46 0x22200000
77 #define SPXg_FB_ADDR_KA49 0x28200000
78 #define SPXg_FB_ADDR ((vax_boardtype == VAX_BTYP_46) ? \
79 SPXg_FB_ADDR_KA46 : SPXg_FB_ADDR_KA49)
81 #define SPXg_WIN_SIZE 0x00100000 /* Window size */
82 /* # of pixels that fit into single window */
83 #define SPXg_WIN_LINEAR (SPXg_WIN_SIZE / 2)
88 * off-screen font storage space
89 * 32x16 glyphs, 256 regular and underliend chars
91 #define FONT_STORAGE_START (spx_xsize * spx_ysize)
92 #define FONT_STORAGE_SIZE (32 * 16 * 256 * 2)
94 /* register space defines */
95 #define SPX_REG_SIZE 0x00002000
96 #define SPX_REG_ADDR 0x39302000 /* 1st set of SPX registers */
98 #define SPXg_REG_SIZE 0x00004000
99 #define SPXg_REG_ADDR_KA46 0x22004000
100 #define SPXg_REG_ADDR_KA49 0x28004000
101 #define SPXg_REG_ADDR ((vax_boardtype == VAX_BTYP_46) ? \
102 SPXg_REG_ADDR_KA46 : SPXg_REG_ADDR_KA49)
104 #define SPX_REG1_SIZE 0x00001000
105 #define SPX_REG1_ADDR 0x39b00000 /* 2nd set of SPX registers */
107 #define SPXg_REG1_SIZE 0x00001000
108 #define SPXg_REG1_ADDR_KA46 0x22100000
109 #define SPXg_REG1_ADDR_KA49 0x28100000
110 #define SPXg_REG1_ADDR ((vax_boardtype == VAX_BTYP_46) ? \
111 SPXg_REG1_ADDR_KA46 : SPXg_REG1_ADDR_KA49)
112 #define SPX_REG(reg) regaddr[(reg - 0x2000) / 4]
113 #define SPXg_REG(reg) regaddr[(reg - 0x2000) / 2]
115 #define SPX_REG1(reg) regaddr1[(reg) / 4]
116 #define SPXg_REG1(reg) regaddr1[(reg) / 4]
118 /* few SPX register names */
119 #define SPX_COMMAND 0x21ec
120 #define SPX_XSTART 0x21d0
121 #define SPX_YSTART 0x21d4
122 #define SPX_XEND 0x21d8
123 #define SPX_YEND 0x21dc
124 #define SPX_DSTPIX 0x21e0
125 #define SPX_DSTPIX1 0x20e0
126 #define SPX_SRCPIX 0x21e4
127 #define SPX_SRCPIX1 0x20e4
128 #define SPX_MAIN3 0x219c
129 #define SPX_STRIDE 0x21e8 /* SRC | DST */
130 #define SPX_SRCMASK 0x21f0
131 #define SPX_DSTMASK 0x21f4
132 #define SPX_FG 0x2260
133 #define SPX_BG 0x2264
134 #define SPX_DESTLOOP 0x2270
135 #define SPX_MPC 0x21fc
137 /* few SPX opcodes (microcode entry points); rasterop # = opcode ? */
138 #define SPX_OP_FILLRECT 0x19
139 #define SPX_OP_COPYRECT 0x1a
141 /* bt459 locations */
142 #define SPX_BT459_ADDRL 0x39b10000
143 #define SPX_BT459_ADDRH 0x39b14000
144 #define SPX_BT459_REG 0x39b18000
145 #define SPX_BT459_CMAP 0x39b1c000
147 /* bt460 locations */
148 #define SPXg_BT460_BASE_KA46 0x200f0000
149 #define SPXg_BT460_BASE_KA49 0x2a000000
150 #define SPXg_BT460_BASE ((vax_boardtype == VAX_BTYP_46) ? \
151 SPXg_BT460_BASE_KA46 : SPXg_BT460_BASE_KA49)
153 #define SPX_BG_COLOR WS_DEFAULT_BG
154 #define SPX_FG_COLOR WS_DEFAULT_FG
157 * cursor X = 0, Y = 0 on-screen bias
158 * FIXME: BIAS for various HW types
160 #define CUR_XBIAS 360
163 /* few BT459 & BT460 indirect register defines */
164 #define SPXDAC_REG_CCOLOR_1 0x181
165 #define SPXDAC_REG_CCOLOR_2 0x182
166 #define SPXDAC_REG_CCOLOR_3 0x183
167 #define SPXDAC_REG_ID 0x200
168 #define SPXDAC_REG_CMD0 0x201
169 #define SPXDAC_REG_CMD1 0x202
170 #define SPXDAC_REG_CMD2 0x203
171 #define SPXDAC_REG_PRM 0x204
172 #define SPXDAC_REG_CCR 0x300
173 #define SPXDAC_REG_CXLO 0x301
174 #define SPXDAC_REG_CXHI 0x302
175 #define SPXDAC_REG_CYLO 0x303
176 #define SPXDAC_REG_CYHI 0x304
177 #define SPXDAC_REG_WXLO 0x305
178 #define SPXDAC_REG_WXHI 0x306
179 #define SPXDAC_REG_WYLO 0x307
180 #define SPXDAC_REG_WYHI 0x308
181 #define SPXDAC_REG_WWLO 0x309
182 #define SPXDAC_REG_WWHI 0x30a
183 #define SPXDAC_REG_WHLO 0x30b
184 #define SPXDAC_REG_WHHI 0x30c
185 #define SPXDAC_REG_CRAM_BASE 0x400
188 * used to access top/bottom 8 bits of a 16-bit argument for split RAMDAC
191 #define HI(x) (((x) >> 8) & 0xff)
192 #define LO(x) ((x) & 0xff)
194 static int spx_match(device_t
, cfdata_t
, void *);
195 static void spx_attach(device_t
, device_t
, void *);
201 CFATTACH_DECL_NEW(spx
, sizeof(struct spx_softc
),
202 spx_match
, spx_attach
, NULL
, NULL
);
204 static void spx_cursor(void *, int, int, int);
205 static int spx_mapchar(void *, int, unsigned int *);
206 static void spx_putchar(void *, int, int, u_int
, long);
207 static void spx_copycols(void *, int, int, int,int);
208 static void spx_erasecols(void *, int, int, int, long);
209 static void spx_copyrows(void *, int, int, int);
210 static void spx_eraserows(void *, int, int, long);
211 static int spx_allocattr(void *, int, int, int, long *);
212 static int spx_get_cmap(struct wsdisplay_cmap
*);
213 static int spx_set_cmap(struct wsdisplay_cmap
*);
215 static int spx_map_regs(device_t
, u_int
, u_int
, u_int
, u_int
);
216 static void SPX_render_font(void);
217 static void SPXg_render_font(void);
218 static int SPX_map_fb(device_t
, struct vsbus_attach_args
*);
219 static int SPXg_map_fb(device_t
, struct vsbus_attach_args
*);
220 static void spx_init_common(device_t
, struct vsbus_attach_args
*);
222 #define SPX_MAP_FB(self, va, type) if (! type ## _map_fb(self, va)) return
223 #define SPX_MAP_REGS(self, type) if (!spx_map_regs(self, \
226 type ## _REG1_ADDR, \
227 type ## _REG1_SIZE)) \
230 const struct wsdisplay_emulops spx_emulops
= {
241 static char spx_stdscreen_name
[10] = "160x128";
242 struct wsscreen_descr spx_stdscreen
= {
243 spx_stdscreen_name
, 160, 128, /* dynamically set */
245 8, 15, /* dynamically set */
246 WSSCREEN_UNDERLINE
|WSSCREEN_REVERSE
|WSSCREEN_WSCOLORS
,
249 const struct wsscreen_descr
*_spx_scrlist
[] = {
253 const struct wsscreen_list spx_screenlist
= {
254 sizeof(_spx_scrlist
) / sizeof(struct wsscreen_descr
*),
258 static volatile char *spxaddr
;
259 static volatile long *regaddr
;
260 static volatile long *regaddr1
;
262 static volatile char *bt_addrl
;
263 static volatile char *bt_addrh
;
264 static volatile char *bt_reg
;
265 static volatile char *bt_cmap
;
266 static volatile char *bt_wait
; /* SPXg/gt only */
268 static int spx_xsize
;
269 static int spx_ysize
;
270 static int spx_depth
;
273 static long spx_fb_size
;
275 /* Our current hardware colormap */
276 static struct hwcmap256
{
277 #define CMAP_SIZE 256 /* 256 R/G/B entries */
278 u_int8_t r
[CMAP_SIZE
];
279 u_int8_t g
[CMAP_SIZE
];
280 u_int8_t b
[CMAP_SIZE
];
283 /* The default colormap */
288 } spx_default_cmap
= {
289 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff },
290 { 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff },
291 { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff }
294 static char fb_type
= 0;
295 static char spxg_current_page
= 0;
296 #define spxg_switch_page(nr) (SPXg_REG1(0x20) = ((1 << (nr) & 0xff)) << 16)
298 struct wsdisplay_font spx_font
;
302 #define QCHAR_INVALID(c) (((c) < spx_font.firstchar) || \
303 ((c) >= spx_font.firstchar + spx_font.numchars))
304 #define QCHAR(c) (QCHAR_INVALID(c) ? 0 : (c) - spx_font.firstchar)
306 #define QFONT_INDEX(c, line) (QCHAR(c) * spx_font.fontheight + line)
307 #define QFONT_QF(c, line) qf[QFONT_INDEX(c, line)]
308 #define QFONT_QF2(c, line) qf2[QFONT_INDEX(c, line)]
309 #define QFONT(c, line) (spx_font.stride == 2 ? \
310 QFONT_QF2(c, line) : \
313 /* replicate color value */
314 #define COLOR(x) (((x) << 24) | ((x) << 16) | ((x) << 8) | (x))
316 /* convert coordinates into linear offset */
317 #define LINEAR(x, y) ((y * spx_xsize) + x)
319 /* Linear pixel address */
320 #define SPX_POS(row, col, line, dot) \
321 ((col) * spx_font.fontwidth + \
322 (row) * spx_font.fontheight * spx_xsize + \
323 (line) * spx_xsize + dot)
325 #define SPX_ADDR(row, col, line, dot) spxaddr[SPX_POS(row, col, line, dot)]
327 /* Recalculate absolute pixel address from linear address */
328 #define SPXg_ADDR(linear) spxaddr[((((linear) % SPXg_WIN_LINEAR) / 4) * 8) + \
329 (((linear) % SPXg_WIN_LINEAR) % 4)]
332 static int spx_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
333 static paddr_t
spx_mmap(void *, void *, off_t
, int);
334 static int spx_alloc_screen(void *, const struct wsscreen_descr
*,
335 void **, int *, int *, long *);
336 static void spx_free_screen(void *, void *);
337 static int spx_show_screen(void *, void *, int, void (*) (void *, int, int),
340 static void spx_update_cmap(int entry
, char red
, char green
, char blue
);
341 static void set_btreg(u_int addr
, u_char value
);
342 static u_char
get_btreg(u_int addr
);
345 static void spxg_delay(void);
348 * SPX HW accelerated block copy
349 * common code in spx_blkcpy,
350 * HW-specific code accessed through spx_blkcpy_func pointer
352 static void spx_blkcpy(u_int sxpos
, u_int sypos
,
353 u_int dxpos
, u_int dypos
,
354 u_int xdim
, u_int ydim
);
356 static void SPX_blkcpy(u_int sxpos
, u_int sypos
,
357 u_int dxpos
, u_int dypos
,
358 u_int xdim
, u_int ydim
,
360 static void SPXg_blkcpy(u_int sxpos
, u_int sypos
,
361 u_int dxpos
, u_int dypos
,
362 u_int xdim
, u_int ydim
,
364 static void (*spx_blkcpy_func
)(u_int
, u_int
,
369 /* SPX HW accelerated block set, no common code */
370 static void SPX_blkset(u_int xpos
, u_int ypos
,
371 u_int xdim
, u_int ydim
, char color
);
372 static void SPXg_blkset(u_int xpos
, u_int ypos
,
373 u_int xdim
, u_int ydim
, char color
);
374 static void (*spx_blkset_func
)(u_int
, u_int
, u_int
, u_int
, char);
375 #define spx_blkset(x, y, xd, yd, c) spx_blkset_func(x, y, xd, yd, c)
377 /* SPX HW accelerated part of spx_putchar */
378 static void SPX_putchar(int, int, u_int
, char, char);
379 static void SPXg_putchar(int, int, u_int
, char, char);
380 static void (*spx_putchar_func
)(int, int, u_int
, char, char);
382 const struct wsdisplay_accessops spx_accessops
= {
391 /* TODO allocate ss_image dynamically for consoles beyond first one */
398 u_char data
; /* Image character */
399 u_char attr
; /* Attribute: 80/70/08/07 */
400 } ss_image
[160 * 128]; /* allow for maximum possible cell matrix */
403 #define SPX_ATTR_UNDERLINE 0x80
404 #define SPX_BG_MASK 0x70
405 #define SPX_ATTR_REVERSE 0x08
406 #define SPX_FG_MASK 0x07
408 static struct spx_screen spx_conscreen
;
409 static struct spx_screen
*prevscr
, *curscr
;
410 static struct spx_screen
*savescr
;
412 static int cur_fg
, cur_bg
;
413 static int spx_off
= 1;
416 spx_update_cmap(int entry
, char red
, char green
, char blue
)
418 *bt_addrl
= LO(entry
);
419 *bt_addrh
= HI(entry
);
420 if ((entry
>= 0x181) && (entry
<= 0x183)) {
432 set_btreg(u_int addr
, u_char value
)
434 *bt_addrl
= LO(addr
);
435 *bt_addrh
= HI(addr
);
440 get_btreg(u_int addr
)
442 *bt_addrl
= LO(addr
);
443 *bt_addrh
= HI(addr
);
444 return *bt_reg
& 0xff;
452 for (i
= 0; i
<= SPXg_DELAY
; i
++)
453 *bt_wait
= *bt_wait
+ i
;
457 SPX_blkcpy(u_int sxpos
, u_int sypos
,
458 u_int dxpos
, u_int dypos
,
459 u_int xdim
, u_int ydim
,
462 u_int counter
= 0xffffe;
465 SPX_REG(SPX_COMMAND
) = 0x84884648 | direction
; /* 0x848c4648? */
466 SPX_REG(SPX_XSTART
) = dxpos
<< 16;
467 SPX_REG(SPX_YSTART
) = dypos
<< 16;
468 SPX_REG(SPX_XEND
) = (dxpos
+ xdim
) << 16;
469 SPX_REG(SPX_YEND
) = (dypos
+ ydim
) << 16;
471 temp
= ((SPX_REG1(0x10) & 0xc0) << (30 - 6)) | \
472 ((SPX_REG1(0x10) & 0x3f) << 24);
474 SPX_REG(SPX_DSTPIX
) = temp
+ LINEAR(dxpos
, dypos
);
475 SPX_REG(SPX_SRCPIX
) = temp
+ LINEAR(sxpos
, sypos
);
476 SPX_REG(SPX_SRCPIX1
) = 0;
477 SPX_REG(SPX_STRIDE
) = (spx_xsize
<< 16) | spx_xsize
;
478 SPX_REG(SPX_SRCMASK
) = 0xff;
479 SPX_REG(SPX_DSTMASK
) = 0xff;
481 SPX_REG(SPX_DESTLOOP
) = 0x00112003;
482 SPX_REG(SPX_MPC
) = 0x2000 | SPX_OP_COPYRECT
;
484 SPX_REG1(0x18) = 0xffffffff;
485 while ((counter
) && ((SPX_REG1(0x18) & 2) == 0))
490 SPXg_blkcpy(u_int sxpos
, u_int sypos
,
491 u_int dxpos
, u_int dypos
,
492 u_int xdim
, u_int ydim
,
495 u_int counter
= 0xffffe;
498 SPXg_REG(SPX_COMMAND
) = 0x84884648 | direction
; spxg_delay();
499 SPXg_REG(SPX_XSTART
) = dxpos
<< 16; spxg_delay();
500 SPXg_REG(SPX_YSTART
) = dypos
<< 16; spxg_delay();
501 SPXg_REG(SPX_XEND
) = (dxpos
+ xdim
) << 16; spxg_delay();
502 SPXg_REG(SPX_YEND
) = (dypos
+ ydim
) << 16; spxg_delay();
506 SPXg_REG(SPX_DSTPIX
) = temp
+ LINEAR(dxpos
, dypos
); spxg_delay();
507 SPXg_REG(SPX_DSTPIX1
) = 0xff000000; spxg_delay();
508 SPXg_REG(SPX_SRCPIX
) = temp
+ LINEAR(sxpos
, sypos
); spxg_delay();
509 SPXg_REG(SPX_SRCPIX1
) = 0; spxg_delay();
510 SPXg_REG(SPX_STRIDE
) = (spx_xsize
<< 16) | spx_xsize
; spxg_delay();
511 SPXg_REG(SPX_SRCMASK
) = 0xffffffff; spxg_delay();
512 SPXg_REG(SPX_DSTMASK
) = 0xffffffff; spxg_delay();
514 SPXg_REG(SPX_DESTLOOP
) = 0x00112003; spxg_delay();
515 SPXg_REG(SPX_MPC
) = 0x2000 | SPX_OP_COPYRECT
; spxg_delay();
517 while ((counter
) && ((SPXg_REG1(0x0) & 0x8000) == 0))
522 spx_blkcpy(u_int sxpos
, u_int sypos
,
523 u_int dxpos
, u_int dypos
,
524 u_int xdim
, u_int ydim
)
528 /* don't waste time checking whether src and dest actually overlap */
530 direction
|= 0x01; /* X decrement */
536 direction
|= 0x02; /* Y decrement */
542 spx_blkcpy_func(sxpos
, sypos
, dxpos
, dypos
, xdim
, ydim
, direction
);
546 SPX_blkset(u_int xpos
, u_int ypos
, u_int xdim
, u_int ydim
, char color
)
548 u_int counter
= 0xfffe;
551 SPX_REG(SPX_COMMAND
) = 0x84884608;
552 SPX_REG(SPX_XSTART
) = xpos
<< 16;
553 SPX_REG(SPX_YSTART
) = ypos
<< 16;
554 SPX_REG(SPX_XEND
) = (xpos
+ xdim
) << 16;
555 SPX_REG(SPX_YEND
) = (ypos
+ ydim
) << 16;
556 SPX_REG(SPX_STRIDE
) = (spx_xsize
<< 16) | spx_xsize
;
557 SPX_REG(SPX_DESTLOOP
) = 0x20102003;
559 temp
= ((SPX_REG1(0x10) & 0xc0) << (30 - 6)) |
560 ((SPX_REG1(0x10) & 0x3f) << 24);
561 SPX_REG(SPX_DSTPIX
) = temp
+ LINEAR(xpos
, ypos
);
563 SPX_REG(SPX_FG
) = COLOR(color
);
565 SPX_REG(SPX_MPC
) = 0x2000 | SPX_OP_FILLRECT
;
567 SPX_REG1(0x18) = 0xffffffff;
568 while ((counter
) && ((SPX_REG1(0x18) & 2) == 0))
573 SPXg_blkset(u_int xpos
, u_int ypos
, u_int xdim
, u_int ydim
, char color
)
575 u_int counter
= 0xfffe;
578 SPXg_REG(SPX_COMMAND
) = 0x84884608; spxg_delay();
579 SPXg_REG(SPX_XSTART
) = xpos
<< 16; spxg_delay();
580 SPXg_REG(SPX_YSTART
) = ypos
<< 16; spxg_delay();
581 SPXg_REG(SPX_XEND
) = (xpos
+ xdim
) << 16; spxg_delay();
582 SPXg_REG(SPX_YEND
) = (ypos
+ ydim
) << 16; spxg_delay();
583 SPXg_REG(SPX_STRIDE
) = (spx_xsize
<< 16) | spx_xsize
; spxg_delay();
586 SPXg_REG(SPX_DSTPIX
) = temp
+ LINEAR(xpos
, ypos
); spxg_delay();
587 SPXg_REG(SPX_DSTPIX1
) = 0xff000000; spxg_delay();
589 SPXg_REG(SPX_FG
) = COLOR(color
); spxg_delay();
591 SPXg_REG(SPX_DESTLOOP
) = 0x20102003; spxg_delay();
592 SPXg_REG(SPX_MPC
) = 0x2000 | SPX_OP_FILLRECT
; spxg_delay();
594 while ((counter
) && ((SPXg_REG1(0x0) & 0x8000) == 0))
598 int spx_match(device_t parent
, cfdata_t match
, void *aux
)
600 struct vsbus_softc
*sc
= device_private(parent
);
602 struct vsbus_attach_args
*va
= aux
;
603 char *ch
= (char *)va
->va_addr
;
608 * add KA46 when/if ever somebody reports SPXg vax_confdata ID on VS 4000/60
609 * Ditto for SPX ID on KA42 & KA43
611 if (vax_boardtype
!= VAX_BTYP_49
)
614 /* KA49: Identify framebuffer type */
615 switch (vax_confdata
& (CONF_LCSPX
| CONF_SPXg
)) {
618 spx_blkcpy_func
= SPX_blkcpy
;
619 spx_blkset_func
= SPX_blkset
;
620 spx_putchar_func
= SPX_putchar
;
623 fb_type
= FB_IS_SPXg
;
624 spx_blkcpy_func
= SPXg_blkcpy
;
625 spx_blkset_func
= SPXg_blkset
;
626 spx_putchar_func
= SPXg_putchar
;
629 aprint_error("spx_match: no framebuffer found\n");
631 case CONF_LCSPX
| CONF_SPXg
:
632 panic("spx_match: incorrect FB configuration\n");
636 /* FIXME add RAMDAC ID code ??? */
640 * are memory addresses besides va->va_addr off limits at this time ?
641 * RAMDAC ID register test, should read 0x4a for LCSPX, 0x4b for SPXg
643 if (get_btreg(SPXDAC_REG_ID
) != 0x4a)
647 sc
->sc_mask
= 0x04; /* XXX - should be generated */
648 scb_fake(0x14c, 0x15);
654 spx_attach(device_t parent
, device_t self
, void *aux
)
656 struct spx_softc
*sc
= device_private(self
);
657 struct vsbus_attach_args
*va
= aux
;
658 struct wsemuldisplaydev_attach_args aa
;
663 aa
.console
= spxaddr
!= NULL
;
665 spx_init_common(self
, va
);
667 curscr
= &spx_conscreen
;
670 aa
.scrdata
= &spx_screenlist
;
671 aa
.accessops
= &spx_accessops
;
674 set_btreg(SPXDAC_REG_CCR
, 0xc1);
676 config_found(self
, &aa
, wsemuldisplaydevprint
);
682 spx_cursor(void *id
, int on
, int row
, int col
)
684 struct spx_screen
*ss
= id
;
687 attr
= ss
->ss_image
[row
* spx_cols
+ col
].attr
;
688 data
= ss
->ss_image
[row
* spx_cols
+ col
].data
;
690 if (attr
& SPX_ATTR_REVERSE
) {
691 cur_bg
= attr
& SPX_FG_MASK
;
692 cur_fg
= (attr
& SPX_BG_MASK
) >> 4;
694 cur_fg
= attr
& SPX_FG_MASK
;
695 cur_bg
= (attr
& SPX_BG_MASK
) >> 4;
701 spx_putchar_func(row
, col
, data
, cur_bg
, cur_fg
);
703 spx_putchar_func(row
, col
, data
, cur_fg
, cur_bg
);
705 /* change cursor foreground color colormap entry */
706 spx_update_cmap(SPXDAC_REG_CCOLOR_3
,
711 /* update cursor position registers */
712 set_btreg(SPXDAC_REG_CXLO
,
713 LO(col
* spx_font
.fontwidth
+ CUR_XBIAS
));
714 set_btreg(SPXDAC_REG_CXHI
,
715 HI(col
* spx_font
.fontwidth
+ CUR_XBIAS
));
716 set_btreg(SPXDAC_REG_CYLO
,
717 LO(row
* spx_font
.fontheight
+ CUR_YBIAS
));
718 set_btreg(SPXDAC_REG_CYHI
,
719 HI(row
* spx_font
.fontheight
+ CUR_YBIAS
));
723 set_btreg(SPXDAC_REG_CCR
, 0xc1);
726 set_btreg(SPXDAC_REG_CCR
, 0x01);
732 ss
->ss_cur_bg
= cur_bg
;
733 ss
->ss_cur_fg
= cur_fg
;
737 spx_mapchar(void *id
, int uni
, unsigned int *index
)
748 SPX_putchar(int row
, int col
, u_int c
, char dot_fg
, char dot_bg
)
750 u_int counter
= 0xffffe;
753 SPX_REG(SPX_FG
) = COLOR(dot_fg
);
754 SPX_REG(SPX_BG
) = COLOR(dot_bg
);
755 SPX_REG(SPX_MAIN3
) = 0x01010101;
756 SPX_REG(SPX_COMMAND
) = 0x84884648;
757 SPX_REG(SPX_XSTART
) = (col
* spx_font
.fontwidth
) << 16;
758 SPX_REG(SPX_YSTART
) = (row
* spx_font
.fontheight
) << 16;
759 SPX_REG(SPX_XEND
) = ((col
+ 1) * spx_font
.fontwidth
) << 16;
760 SPX_REG(SPX_YEND
) = ((row
+ 1) * spx_font
.fontheight
) << 16;
762 temp
= ((SPX_REG1(0x10) & 0xc0) << (30 - 6)) | \
763 ((SPX_REG1(0x10) & 0x3f) << 24);
765 SPX_REG(SPX_DSTPIX
) = temp
+ LINEAR(col
* spx_font
.fontwidth
,
766 row
* spx_font
.fontheight
);
767 SPX_REG(SPX_SRCPIX
) = temp
+ FONT_STORAGE_START
768 + (c
* spx_font
.fontheight
* spx_font
.fontwidth
);
769 SPX_REG(SPX_SRCPIX1
) = 0;
770 SPX_REG(SPX_STRIDE
) = (spx_font
.fontwidth
<< 16) | spx_xsize
;
771 SPX_REG(SPX_SRCMASK
) = 0xff;
772 SPX_REG(SPX_DSTMASK
) = 0xff;
774 SPX_REG(SPX_DESTLOOP
) = 0x20142003;
775 SPX_REG(SPX_MPC
) = 0x2000 | SPX_OP_COPYRECT
;
777 SPX_REG1(0x18) = 0xffffffff;
779 while ((counter
) && ((SPX_REG1(0x18) & 2) == 0))
784 SPXg_putchar(int row
, int col
, u_int c
, char dot_fg
, char dot_bg
)
786 u_int counter
= 0xffffe;
789 SPXg_REG(SPX_FG
) = COLOR(dot_fg
);
791 SPXg_REG(SPX_BG
) = COLOR(dot_bg
);
793 SPXg_REG(SPX_MAIN3
) = 0x01010101;
795 SPXg_REG(SPX_COMMAND
) = 0x84884648;
797 SPXg_REG(SPX_XSTART
) = (col
* spx_font
.fontwidth
) << 16;
799 SPXg_REG(SPX_YSTART
) = (row
* spx_font
.fontheight
) << 16;
801 SPXg_REG(SPX_XEND
) = ((col
+ 1) * spx_font
.fontwidth
) << 16;
803 SPXg_REG(SPX_YEND
) = ((row
+ 1) * spx_font
.fontheight
) << 16;
808 SPXg_REG(SPX_DSTPIX
) = temp
+ LINEAR(col
* spx_font
.fontwidth
,
809 row
* spx_font
.fontheight
);
811 SPXg_REG(SPX_DSTPIX1
) = 0xff000000;
813 SPXg_REG(SPX_SRCPIX
) = temp
+ FONT_STORAGE_START
+
814 (c
* spx_font
.fontheight
* spx_font
.fontwidth
);
816 SPXg_REG(SPX_SRCPIX1
) = 0;
818 SPXg_REG(SPX_STRIDE
) = (spx_font
.fontwidth
<< 16) | spx_xsize
;
820 SPXg_REG(SPX_SRCMASK
) = 0xffffffff;
822 SPXg_REG(SPX_DSTMASK
) = 0xffffffff;
825 SPXg_REG(SPX_DESTLOOP
) = 0x20142003;
827 SPXg_REG(SPX_MPC
) = 0x2000 | SPX_OP_COPYRECT
;
830 while ((counter
) && ((SPXg_REG1(0x0) & 0x8000) == 0))
835 spx_putchar(void *id
, int row
, int col
, u_int c
, long attr
)
837 struct spx_screen
*ss
= id
;
842 ss
->ss_image
[row
* spx_cols
+ col
].data
= c
;
843 ss
->ss_image
[row
* spx_cols
+ col
].attr
= attr
;
847 dot_fg
= attr
& SPX_FG_MASK
;
848 dot_bg
= (attr
& SPX_BG_MASK
) >> 4;
849 if (attr
& SPX_ATTR_REVERSE
) {
850 dot_fg
= (attr
& SPX_BG_MASK
) >> 4;
851 dot_bg
= attr
& SPX_FG_MASK
;
854 /* adjust glyph index for underlined text */
855 if (attr
& SPX_ATTR_UNDERLINE
)
858 spx_putchar_func(row
, col
, c
, dot_fg
, dot_bg
);
862 * copies columns inside a row.
865 spx_copycols(void *id
, int row
, int srccol
, int dstcol
, int ncols
)
867 struct spx_screen
*ss
= id
;
869 bcopy(&ss
->ss_image
[row
* spx_cols
+ srccol
],
870 &ss
->ss_image
[row
* spx_cols
+ dstcol
],
871 ncols
* sizeof(ss
->ss_image
[0]));
874 spx_blkcpy(srccol
* spx_font
.fontwidth
,
875 row
* spx_font
.fontheight
,
876 dstcol
* spx_font
.fontwidth
,
877 row
* spx_font
.fontheight
,
878 ncols
* spx_font
.fontwidth
,
879 spx_font
.fontheight
);
883 * Erases a bunch of chars inside one row.
886 spx_erasecols(void *id
, int row
, int startcol
, int ncols
, long fillattr
)
888 struct spx_screen
*ss
= id
;
889 int offset
= row
* spx_cols
+ startcol
;
892 memset(&ss
->ss_image
[row
* spx_cols
+ startcol
], 0,
893 ncols
* sizeof(ss
->ss_image
[0]));
895 for (i
= offset
; i
< offset
+ ncols
; ++i
)
896 ss
->ss_image
[i
].attr
= fillattr
;
899 spx_blkset(startcol
* spx_font
.fontwidth
,
900 row
* spx_font
.fontheight
,
901 ncols
* spx_font
.fontwidth
,
903 (fillattr
& SPX_BG_MASK
) >> 4);
907 spx_copyrows(void *id
, int srcrow
, int dstrow
, int nrows
)
909 struct spx_screen
*ss
= id
;
911 bcopy(&ss
->ss_image
[srcrow
* spx_cols
],
912 &ss
->ss_image
[dstrow
* spx_cols
],
913 nrows
* spx_cols
* sizeof(ss
->ss_image
[0]));
916 spx_blkcpy(0, (srcrow
* spx_font
.fontheight
),
917 0, (dstrow
* spx_font
.fontheight
),
918 spx_xsize
, (nrows
* spx_font
.fontheight
));
922 spx_eraserows(void *id
, int startrow
, int nrows
, long fillattr
)
924 struct spx_screen
*ss
= id
;
927 memset(&ss
->ss_image
[startrow
* spx_cols
], 0,
928 nrows
* spx_cols
* sizeof(ss
->ss_image
[0]));
930 for (i
= startrow
* spx_cols
; i
< startrow
+ nrows
* spx_cols
; ++i
)
931 ss
->ss_image
[i
].attr
= fillattr
;
934 spx_blkset(0, (startrow
* spx_font
.fontheight
),
935 spx_xsize
, (nrows
* spx_font
.fontheight
),
936 (fillattr
& SPX_BG_MASK
) >> 4);
940 spx_allocattr(void *id
, int fg
, int bg
, int flags
, long *attrp
)
944 if (flags
& WSATTR_WSCOLORS
)
945 myattr
= (fg
& SPX_FG_MASK
) | ((bg
<< 4) & SPX_BG_MASK
);
947 myattr
= WSCOL_WHITE
<< 4; /* XXXX */
948 if (flags
& WSATTR_REVERSE
)
949 myattr
|= SPX_ATTR_REVERSE
;
950 if (flags
& WSATTR_UNDERLINE
)
951 myattr
|= SPX_ATTR_UNDERLINE
;
957 spx_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
959 struct wsdisplay_fbinfo
*fb
= data
;
963 case WSDISPLAYIO_GTYPE
:
964 *(u_int
*)data
= WSDISPLAY_TYPE_SPX
;
967 case WSDISPLAYIO_GINFO
:
968 fb
->height
= spx_ysize
;
969 fb
->width
= spx_xsize
;
970 fb
->depth
= spx_depth
;
971 fb
->cmsize
= 1 << spx_depth
;
974 case WSDISPLAYIO_GETCMAP
:
975 return spx_get_cmap((struct wsdisplay_cmap
*)data
);
977 case WSDISPLAYIO_PUTCMAP
:
978 return spx_set_cmap((struct wsdisplay_cmap
*)data
);
980 case WSDISPLAYIO_GMODE
:
983 case WSDISPLAYIO_SMODE
:
985 * if setting WSDISPLAYIO_MODE_EMUL, restore console cmap,
988 if (*(u_int
*)data
== WSDISPLAYIO_MODE_EMUL
) {
989 for (i
= 0; i
< 8; i
++) {
990 spx_cmap
.r
[i
] = spx_default_cmap
.r
[i
];
991 spx_cmap
.g
[i
] = spx_default_cmap
.g
[i
];
992 spx_cmap
.b
[i
] = spx_default_cmap
.b
[i
];
993 spx_update_cmap(i
, spx_cmap
.r
[i
], spx_cmap
.g
[i
],
997 spx_show_screen(NULL
, savescr
, 0, NULL
, NULL
);
999 } else { /* WSDISPLAYIO_MODE_MAPPED */
1005 return EPASSTHROUGH
;
1007 case WSDISPLAYIO_SVIDEO
:
1008 if (*(u_int
*)data
== WSDISPLAYIO_VIDEO_ON
&& spx_off
) {
1010 set_btreg(SPXDAC_REG_CMD0
, 0x48);
1013 set_btreg(SPXDAC_REG_CMD2
, 0xc0);
1016 } else if (*(u_int
*)data
== WSDISPLAYIO_VIDEO_OFF
&& !spx_off
) {
1018 set_btreg(SPXDAC_REG_CMD0
, 68);
1021 set_btreg(SPXDAC_REG_CMD2
, 0x40);
1026 case WSDISPLAYIO_GVIDEO
:
1027 *(u_int
*)data
= spx_off
== 0 ?
1028 WSDISPLAYIO_VIDEO_ON
: WSDISPLAYIO_VIDEO_OFF
;
1032 return EPASSTHROUGH
;
1038 * Bad idea on SPXg/gt due to windowed framebuffer access
1041 spx_mmap(void *v
, void *vs
, off_t offset
, int prot
)
1043 if (fb_type
!= FB_IS_SPX
)
1046 if (offset
>= spx_fb_size
|| offset
< 0)
1049 return (SPX_FB_ADDR
+ offset
) >> PGSHIFT
;
1053 spx_alloc_screen(void *v
, const struct wsscreen_descr
*type
, void **cookiep
,
1054 int *curxp
, int *curyp
, long *defattrp
)
1057 struct spx_screen
*ss
;
1059 ss
= malloc(sizeof(struct spx_screen
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
1062 *curxp
= *curyp
= 0;
1063 *defattrp
= (SPX_BG_COLOR
<< 4) | SPX_FG_COLOR
;
1065 for (i
= 0; i
< spx_cols
* spx_rows
; ++i
)
1066 ss
->ss_image
[i
].attr
= *defattrp
;
1072 spx_free_screen(void *v
, void *cookie
)
1074 /* FIXME add something to actually free malloc()ed screen ? */
1078 spx_show_screen(void *v
, void *cookie
, int waitok
,
1079 void (*cb
)(void *, int, int), void *cbarg
)
1081 struct spx_screen
*ss
= cookie
;
1082 u_int row
, col
, attr
;
1091 for (row
= 0; row
< spx_rows
; row
++) {
1092 for (col
= 0; col
< spx_cols
; col
++) {
1093 u_int idx
= row
* spx_cols
+ col
;
1094 attr
= ss
->ss_image
[idx
].attr
;
1095 c
= ss
->ss_image
[idx
].data
;
1097 /* check if cell requires updating */
1098 if ((c
!= prevscr
->ss_image
[idx
].data
) ||
1099 (attr
!= prevscr
->ss_image
[idx
].attr
)) {
1101 spx_putchar(ss
, row
, col
, c
, attr
);
1106 row
= ss
->ss_cury
; col
= ss
->ss_curx
;
1108 spx_cursor(ss
, cur_on
, row
, col
);
1110 cur_fg
= ss
->ss_cur_fg
;
1111 cur_bg
= ss
->ss_cur_bg
;
1117 spx_get_cmap(struct wsdisplay_cmap
*p
)
1119 u_int index
= p
->index
, count
= p
->count
;
1122 if (index
>= (1 << spx_depth
) || count
> (1 << spx_depth
) - index
)
1125 error
= copyout(&spx_cmap
.r
[index
], p
->red
, count
);
1129 error
= copyout(&spx_cmap
.g
[index
], p
->green
, count
);
1133 error
= copyout(&spx_cmap
.b
[index
], p
->blue
, count
);
1138 spx_set_cmap(struct wsdisplay_cmap
*p
)
1140 u_int index
= p
->index
, count
= p
->count
;
1143 if (index
>= (1 << spx_depth
) || count
> (1 << spx_depth
) - index
)
1146 error
= copyin(p
->red
, &spx_cmap
.r
[index
], count
);
1150 error
= copyin(p
->green
, &spx_cmap
.g
[index
], count
);
1154 error
= copyin(p
->blue
, &spx_cmap
.b
[index
], count
);
1160 while (count
-- > 0) {
1161 spx_update_cmap(index
,
1174 spxcninit(struct consdev
*cndev
)
1178 spx_blkset(0, 0, spx_xsize
, spx_ysize
, SPX_BG_COLOR
);
1180 curscr
= &spx_conscreen
;
1182 for (i
= 0; i
< spx_cols
* spx_rows
; i
++)
1183 spx_conscreen
.ss_image
[i
].attr
=
1184 (SPX_BG_COLOR
<< 4) | SPX_FG_COLOR
;
1185 wsdisplay_cnattach(&spx_stdscreen
, &spx_conscreen
, 0, 0,
1186 (SPX_BG_COLOR
<< 4) | SPX_FG_COLOR
);
1187 cn_tab
->cn_pri
= CN_INTERNAL
;
1190 dzkbd_cnattach(0); /* Connect keyboard and screen together */
1195 * Called very early to setup the glass tty as console.
1196 * Because it's called before the VM system is inited, virtual memory
1197 * for the framebuffer can be stolen directly without disturbing anything.
1200 spxcnprobe(struct consdev
*cndev
)
1202 extern const struct cdevsw wsdisplay_cdevsw
;
1204 /* Only for VS 4000/90, 90A and 96 with LCSPX or SPXg/gt*/
1205 if ((vax_boardtype
!= VAX_BTYP_49
) ||
1206 ((vax_confdata
& (CONF_LCSPX
| CONF_SPXg
)) != 0))
1209 if (((vax_confdata
& 8) && (vax_boardtype
== VAX_BTYP_49
)) ||
1210 (((vax_confdata
& KA420_CFG_L3CON
) ||
1211 (vax_confdata
& KA420_CFG_MULTU
)) &&
1212 ((vax_boardtype
== VAX_BTYP_420
) ||
1213 (vax_boardtype
== VAX_BTYP_43
)))) {
1214 aprint_normal("spxcnprobe: Diagnostic console\n");
1215 return; /* Diagnostic console */
1218 /* KA49: Identify framebuffer type */
1219 switch (vax_confdata
& (CONF_LCSPX
| CONF_SPXg
)) {
1221 fb_type
= FB_IS_SPX
;
1222 spx_blkcpy_func
= SPX_blkcpy
;
1223 spx_blkset_func
= SPX_blkset
;
1226 fb_type
= FB_IS_SPXg
;
1227 spx_blkcpy_func
= SPXg_blkcpy
;
1228 spx_blkset_func
= SPXg_blkset
;
1231 aprint_error("spxcnprobe: no framebuffer found\n");
1233 case CONF_LCSPX
| CONF_SPXg
:
1234 panic("spxcnprobe: incorrect FB configuration\n"); break;
1237 spx_init_common(NULL
, NULL
);
1239 cndev
->cn_pri
= CN_INTERNAL
;
1240 cndev
->cn_dev
= makedev(cdevsw_lookup_major(&wsdisplay_cdevsw
), 0);
1244 spx_map_regs(device_t self
,
1245 u_int raddr
, u_int rsize
, u_int r1addr
, u_int r1size
)
1247 extern vaddr_t virtual_avail
;
1250 regaddr
= (long*)virtual_avail
;
1251 virtual_avail
+= rsize
;
1252 ioaccess((vaddr_t
)regaddr
, raddr
, rsize
/VAX_NBPG
);
1254 regaddr1
= (long*)virtual_avail
;
1255 virtual_avail
+= r1size
;
1256 ioaccess((vaddr_t
)regaddr1
, r1addr
, r1size
/VAX_NBPG
);
1261 regaddr
= (long*)vax_map_physmem(raddr
, rsize
/VAX_NBPG
);
1263 aprint_error_dev(self
,
1264 "unable to allocate register memory (1).\n");
1268 regaddr1
= (long*)vax_map_physmem(r1addr
, r1size
/VAX_NBPG
);
1269 if (regaddr1
== 0) {
1270 aprint_error_dev(self
,
1271 "unable to allocate register memory (2).\n");
1279 SPX_map_fb(device_t self
, struct vsbus_attach_args
*va
)
1281 int fbsize
= (spx_fb_size
+ FONT_STORAGE_SIZE
)/VAX_NBPG
;
1282 extern vaddr_t virtual_avail
;
1285 spxaddr
= (char *)virtual_avail
;
1286 virtual_avail
+= (spx_fb_size
+ FONT_STORAGE_SIZE
);
1287 ioaccess((vaddr_t
)spxaddr
, SPX_FB_ADDR
, fbsize
);
1289 bt_addrl
= (char *)virtual_avail
;
1290 virtual_avail
+= VAX_NBPG
;
1291 ioaccess((vaddr_t
)bt_addrl
, SPX_BT459_ADDRL
, 1);
1293 bt_addrh
= (char *)virtual_avail
;
1294 virtual_avail
+= VAX_NBPG
;
1295 ioaccess((vaddr_t
)bt_addrh
, SPX_BT459_ADDRH
, 1);
1297 bt_reg
= (char *)virtual_avail
;
1298 virtual_avail
+= VAX_NBPG
;
1299 ioaccess((vaddr_t
)bt_reg
, SPX_BT459_REG
, 1);
1301 bt_cmap
= (char *)virtual_avail
;
1302 virtual_avail
+= VAX_NBPG
;
1303 ioaccess((vaddr_t
)bt_cmap
, SPX_BT459_CMAP
, 1);
1308 spxaddr
= (char *)vax_map_physmem(va
->va_paddr
, fbsize
);
1310 aprint_error_dev(self
, "unable to map framebuffer memory.\n");
1314 /* map all four RAMDAC registers */
1315 bt_addrl
= (char *)vax_map_physmem(SPX_BT459_ADDRL
, 1);
1316 if (bt_addrl
== 0) {
1317 aprint_error_dev(self
,
1318 "unable to map BT459 Low Address register.\n");
1322 bt_addrh
= (char *)vax_map_physmem(SPX_BT459_ADDRH
, 1);
1323 if (bt_addrh
== 0) {
1324 aprint_error_dev(self
,
1325 "unable to map BT459 High Address register.\n");
1329 bt_reg
= (char *)vax_map_physmem(SPX_BT459_REG
, 1);
1331 aprint_error_dev(self
,
1332 "unable to map BT459 I/O Register.\n");
1336 bt_cmap
= (char *)vax_map_physmem(SPX_BT459_CMAP
, 1);
1338 aprint_error_dev(self
,
1339 "unable to map BT459 Color Map register.\n");
1347 SPXg_map_fb(device_t self
, struct vsbus_attach_args
*va
)
1349 int fbsize
= SPXg_WIN_SIZE
/VAX_NBPG
;
1350 extern vaddr_t virtual_avail
;
1353 spxaddr
= (char *)virtual_avail
;
1354 virtual_avail
+= SPXg_WIN_SIZE
;
1355 ioaccess((vaddr_t
)spxaddr
, SPXg_FB_ADDR
, fbsize
);
1357 bt_addrl
= (char *)virtual_avail
;
1358 virtual_avail
+= VAX_NBPG
;
1359 ioaccess((vaddr_t
)bt_addrl
, SPXg_BT460_BASE
, 1);
1361 bt_addrh
= bt_addrl
+ 0x04;
1362 bt_reg
= bt_addrl
+ 0x08;
1363 bt_cmap
= bt_addrl
+ 0x0c;
1364 bt_wait
= bt_addrl
+ 0x34;
1369 spxaddr
= (char *)vax_map_physmem(va
->va_paddr
, fbsize
);
1371 aprint_error_dev(self
,
1372 "unable to map framebuffer memory window.\n");
1376 bt_addrl
= (char *)vax_map_physmem(SPXg_BT460_BASE
, 1);
1377 if (bt_addrl
== 0) {
1378 aprint_error_dev(self
,
1379 "unable to map BT460 Low Address register.\n");
1382 bt_addrh
= bt_addrl
+ 0x04;
1383 bt_reg
= bt_addrl
+ 0x08;
1384 bt_cmap
= bt_addrl
+ 0x0c;
1385 bt_wait
= bt_addrl
+ 0x34;
1391 SPX_render_font(void)
1393 volatile char *fontaddr
= spxaddr
+ FONT_STORAGE_START
;
1394 int i
, j
, k
, ch
, pixel
;
1396 for (i
= 0; i
< 256; i
++) for (j
= 0; j
< spx_font
.fontheight
; j
++) {
1399 /* regular characters */
1400 pixel
= ((i
* spx_font
.fontheight
)+ j
) * spx_font
.fontwidth
;
1401 for (k
= 0; k
< spx_font
.fontwidth
; k
++)
1403 fontaddr
[pixel
++] = 0xff;
1405 fontaddr
[pixel
++] = 0x00;
1407 /* underlined characters */
1408 pixel
= (((i
+ 256) * spx_font
.fontheight
) + j
)
1409 * spx_font
.fontwidth
;
1410 for (k
= 0; k
< spx_font
.fontwidth
; k
++)
1411 if ((ch
& (1 << k
)) || (j
== (spx_font
.fontheight
- 1)))
1412 fontaddr
[pixel
++] = 0xff;
1414 fontaddr
[pixel
++] = 0x00;
1419 SPXg_render_font(void)
1421 int i
, j
, k
, ch
, pixel
;
1423 for (i
= 0; i
< 256; i
++) for (j
= 0; j
< spx_font
.fontheight
; j
++) {
1425 /* regular characters */
1426 for (k
= 0; k
< spx_font
.fontwidth
; k
++) {
1427 pixel
= FONT_STORAGE_START
1428 + (((i
* spx_font
.fontheight
) + j
)
1429 * spx_font
.fontwidth
) + k
;
1430 if ((pixel
/ SPXg_WIN_LINEAR
) != spxg_current_page
) {
1431 spxg_switch_page(pixel
/ SPXg_WIN_LINEAR
);
1432 spxg_current_page
= (pixel
/ SPXg_WIN_LINEAR
);
1434 SPXg_ADDR(pixel
) = ch
& (1 << k
) ? 0xff : 0x00;
1438 /* underlined characters */
1439 for (k
= 0; k
< spx_font
.fontwidth
; k
++) {
1440 pixel
= FONT_STORAGE_START
1441 + ((((i
+ 256) * spx_font
.fontheight
) + j
)
1442 * spx_font
.fontwidth
) + k
;
1443 if ((pixel
/ SPXg_WIN_LINEAR
) != spxg_current_page
) {
1444 spxg_switch_page(pixel
/ SPXg_WIN_LINEAR
);
1445 spxg_current_page
= (pixel
/ SPXg_WIN_LINEAR
);
1447 if ((ch
& (1 << k
)) || (j
== (spx_font
.fontheight
- 1)))
1448 SPXg_ADDR(pixel
) = 0xff;
1450 SPXg_ADDR(pixel
) = 0x00;
1457 spx_init_common(device_t self
, struct vsbus_attach_args
*va
)
1461 struct wsdisplay_font
*wf
;
1463 /* map SPX registers first */
1464 if (fb_type
== FB_IS_SPX
) {
1465 SPX_MAP_REGS(self
, SPX
);
1466 } else if(fb_type
== FB_IS_SPXg
) {
1467 SPX_MAP_REGS(self
, SPXg
);
1470 if (fb_type
== FB_IS_SPXg
)
1471 spxg_switch_page(0);
1473 /* any KA42/43 SPX resolution detection code should be placed here */
1480 cookie
= wsfont_find(NULL
, 12, 21, 0, WSDISPLAY_FONTORDER_R2L
,
1481 WSDISPLAY_FONTORDER_L2R
);
1483 cookie
= wsfont_find(NULL
, 16, 0, 0, WSDISPLAY_FONTORDER_R2L
, 0);
1485 cookie
= wsfont_find(NULL
, 12, 0, 0, WSDISPLAY_FONTORDER_R2L
, 0);
1487 cookie
= wsfont_find(NULL
, 8, 0, 0, WSDISPLAY_FONTORDER_R2L
, 0);
1489 cookie
= wsfont_find(NULL
, 0, 0, 0, WSDISPLAY_FONTORDER_R2L
,
1490 WSDISPLAY_FONTORDER_L2R
);
1493 aprint_error_dev(self
, "spx_common_init: cookie = -1\n");
1495 if (cookie
== -1 || wsfont_lock(cookie
, &wf
))
1496 panic("spx_common_init: unable to load console font");
1501 aprint_normal_dev(self
, "Using %s %dx%d font\n", wf
->name
,
1502 spx_font
.fontwidth
, spx_font
.fontheight
);
1505 spx_cols
= spx_xsize
/ spx_font
.fontwidth
;
1506 spx_rows
= spx_ysize
/ spx_font
.fontheight
;
1507 spx_fb_size
= spx_xsize
* spx_ysize
;
1508 spx_stdscreen
.ncols
= spx_cols
;
1509 spx_stdscreen
.nrows
= spx_rows
;
1510 spx_stdscreen
.fontwidth
= spx_font
.fontwidth
;
1511 spx_stdscreen
.fontheight
= spx_font
.fontheight
;
1512 sprintf(spx_stdscreen_name
, "%dx%d", spx_cols
, spx_rows
);
1514 /* for SPXg spx_fb_size represents FB window size, not FB length */
1515 if (fb_type
== FB_IS_SPXg
)
1516 spx_fb_size
= SPXg_WIN_SIZE
;
1519 qf2
= (u_short
*)spx_font
.data
;
1521 if (fb_type
== FB_IS_SPX
) {
1522 SPX_MAP_FB(self
, va
, SPX
);
1523 } else if (fb_type
== FB_IS_SPXg
) {
1524 SPX_MAP_FB(self
, va
, SPXg
);
1527 /* display FB type based on RAMDAC ID */
1528 switch (get_btreg(SPXDAC_REG_ID
) & 0xff) {
1531 self
, "RAMDAC ID: 0x%x, Bt459 (SPX/LCSPX) RAMDAC type\n",
1532 get_btreg(SPXDAC_REG_ID
) & 0xff);
1537 self
, "RAMDAC ID: 0x%x, Bt460 (SPXg) RAMDAC type\n",
1538 get_btreg(SPXDAC_REG_ID
) & 0xff);
1541 aprint_error_dev(self
, "unknown RAMDAC type 0x%x\n",
1542 get_btreg(SPXDAC_REG_ID
) & 0xff);
1545 /* render font glyphs to off-screen memory */
1546 if (fb_type
== FB_IS_SPX
)
1548 else if (fb_type
== FB_IS_SPXg
)
1551 /* set up default console color palette */
1552 for (i
= 0; i
< 8; i
++) {
1553 spx_cmap
.r
[i
] = spx_default_cmap
.r
[i
];
1554 spx_cmap
.g
[i
] = spx_default_cmap
.g
[i
];
1555 spx_cmap
.b
[i
] = spx_default_cmap
.b
[i
];
1556 spx_update_cmap(i
, spx_cmap
.r
[i
], spx_cmap
.g
[i
], spx_cmap
.b
[i
]);
1560 * Build 64x64 console cursor bitmap based on font dimensions.
1561 * Palette colors are not used, but 4 pixels 2bpp of cursor sprite,
1562 * fg/bg respectively.
1564 for (i
= 0; i
< 1024; i
++)
1565 set_btreg(SPXDAC_REG_CRAM_BASE
+ i
, 0);
1567 /* build cursor line, 1 to 3 pixels high depending on font height */
1568 if (spx_font
.fontheight
> 26)
1569 i
= spx_font
.fontheight
- 3;
1570 else if (spx_font
.fontheight
> 16)
1571 i
= spx_font
.fontheight
- 2;
1573 i
= spx_font
.fontheight
- 1;
1575 for (; i
<= spx_font
.fontheight
- 1; i
++) {
1576 for (j
= 0; j
< (spx_font
.fontwidth
>> 2); j
++)
1577 set_btreg(SPXDAC_REG_CRAM_BASE
+ i
*16 + j
, 0xff);
1578 k
= (spx_font
.fontwidth
& 3) << 1;
1579 set_btreg(SPXDAC_REG_CRAM_BASE
+ i
*16 + j
, (1 << k
) - 1);
1582 if (fb_type
== FB_IS_SPX
) {
1583 /* set SPX write/read plane masks */
1584 SPX_REG(0x3170) = 0xffffffff;
1585 SPX_REG(0x3174) = 0xffffffff;
1588 /* RAMDAC type-specific configuration */
1589 if (fb_type
== FB_IS_SPX
)
1590 set_btreg(SPXDAC_REG_CMD2
, 0xc0);
1592 /* common configuration */
1593 set_btreg(SPXDAC_REG_CMD0
, 0x48);
1594 set_btreg(SPXDAC_REG_CMD1
, 0x00);
1595 set_btreg(SPXDAC_REG_PRM
, 0xff);
1597 set_btreg(SPXDAC_REG_CXLO
, 0);
1598 set_btreg(SPXDAC_REG_CXHI
, 0);
1599 set_btreg(SPXDAC_REG_CYLO
, 0);
1600 set_btreg(SPXDAC_REG_CYHI
, 0);
1602 set_btreg(SPXDAC_REG_WXLO
, 0);
1603 set_btreg(SPXDAC_REG_WXHI
, 0);
1604 set_btreg(SPXDAC_REG_WYLO
, 0);
1605 set_btreg(SPXDAC_REG_WYHI
, 0);
1607 set_btreg(SPXDAC_REG_WWLO
, 0);
1608 set_btreg(SPXDAC_REG_WWHI
, 0);
1609 set_btreg(SPXDAC_REG_WHLO
, 0);
1610 set_btreg(SPXDAC_REG_WHHI
, 0);