sfb.c revision 1.41 1 1.41 nisimura /* $NetBSD: sfb.c,v 1.41 2001/01/15 09:41:57 nisimura Exp $ */
2 1.2 nisimura
3 1.2 nisimura /*
4 1.16 nisimura * Copyright (c) 1998, 1999 Tohru Nishimura. All rights reserved.
5 1.2 nisimura *
6 1.2 nisimura * Redistribution and use in source and binary forms, with or without
7 1.2 nisimura * modification, are permitted provided that the following conditions
8 1.2 nisimura * are met:
9 1.2 nisimura * 1. Redistributions of source code must retain the above copyright
10 1.2 nisimura * notice, this list of conditions and the following disclaimer.
11 1.2 nisimura * 2. Redistributions in binary form must reproduce the above copyright
12 1.2 nisimura * notice, this list of conditions and the following disclaimer in the
13 1.2 nisimura * documentation and/or other materials provided with the distribution.
14 1.2 nisimura * 3. All advertising materials mentioning features or use of this software
15 1.2 nisimura * must display the following acknowledgement:
16 1.2 nisimura * This product includes software developed by Tohru Nishimura
17 1.2 nisimura * for the NetBSD Project.
18 1.2 nisimura * 4. The name of the author may not be used to endorse or promote products
19 1.2 nisimura * derived from this software without specific prior written permission
20 1.2 nisimura *
21 1.2 nisimura * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 1.2 nisimura * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 1.2 nisimura * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 1.2 nisimura * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 1.2 nisimura * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 1.2 nisimura * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 1.2 nisimura * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 1.2 nisimura * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 1.2 nisimura * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 1.2 nisimura * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 1.2 nisimura */
32 1.1 nisimura
33 1.1 nisimura #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
34 1.1 nisimura
35 1.41 nisimura __KERNEL_RCSID(0, "$NetBSD: sfb.c,v 1.41 2001/01/15 09:41:57 nisimura Exp $");
36 1.1 nisimura
37 1.1 nisimura #include <sys/param.h>
38 1.1 nisimura #include <sys/systm.h>
39 1.1 nisimura #include <sys/kernel.h>
40 1.1 nisimura #include <sys/device.h>
41 1.1 nisimura #include <sys/malloc.h>
42 1.1 nisimura #include <sys/buf.h>
43 1.1 nisimura #include <sys/ioctl.h>
44 1.1 nisimura
45 1.1 nisimura #include <machine/bus.h>
46 1.1 nisimura #include <machine/intr.h>
47 1.1 nisimura
48 1.1 nisimura #include <dev/wscons/wsconsio.h>
49 1.1 nisimura #include <dev/wscons/wsdisplayvar.h>
50 1.1 nisimura
51 1.28 drochner #include <dev/rasops/rasops.h>
52 1.28 drochner #include <dev/wsfont/wsfont.h>
53 1.28 drochner
54 1.1 nisimura #include <dev/tc/tcvar.h>
55 1.1 nisimura #include <dev/ic/bt459reg.h>
56 1.4 drochner #include <dev/tc/sfbreg.h>
57 1.1 nisimura
58 1.1 nisimura #include <uvm/uvm_extern.h>
59 1.1 nisimura
60 1.8 thorpej #if defined(pmax)
61 1.1 nisimura #define machine_btop(x) mips_btop(x)
62 1.1 nisimura #define MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x)
63 1.1 nisimura #endif
64 1.1 nisimura
65 1.35 nisimura #if defined(alpha)
66 1.1 nisimura #define machine_btop(x) alpha_btop(x)
67 1.1 nisimura #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
68 1.1 nisimura #endif
69 1.1 nisimura
70 1.1 nisimura /*
71 1.1 nisimura * N.B., Bt459 registers are 8bit width. Some of TC framebuffers have
72 1.3 nisimura * obscure register layout such as 2nd and 3rd Bt459 registers are
73 1.3 nisimura * adjacent each other in a word, i.e.,
74 1.1 nisimura * struct bt459triplet {
75 1.1 nisimura * struct {
76 1.1 nisimura * u_int8_t u0;
77 1.1 nisimura * u_int8_t u1;
78 1.1 nisimura * u_int8_t u2;
79 1.1 nisimura * unsigned :8;
80 1.1 nisimura * } bt_lo;
81 1.17 nisimura * struct {
82 1.17 nisimura *
83 1.1 nisimura * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
84 1.16 nisimura * struct bt459reg {
85 1.16 nisimura * u_int32_t bt_lo;
86 1.16 nisimura * u_int32_t bt_hi;
87 1.16 nisimura * u_int32_t bt_reg;
88 1.16 nisimura * u_int32_t bt_cmap;
89 1.16 nisimura * };
90 1.16 nisimura *
91 1.1 nisimura */
92 1.2 nisimura
93 1.18 nisimura /* Bt459 hardware registers */
94 1.16 nisimura #define bt_lo 0
95 1.16 nisimura #define bt_hi 1
96 1.16 nisimura #define bt_reg 2
97 1.16 nisimura #define bt_cmap 3
98 1.16 nisimura
99 1.16 nisimura #define REG(base, index) *((u_int32_t *)(base) + (index))
100 1.16 nisimura #define SELECT(vdac, regno) do { \
101 1.16 nisimura REG(vdac, bt_lo) = ((regno) & 0x00ff); \
102 1.16 nisimura REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8; \
103 1.16 nisimura tc_wmb(); \
104 1.16 nisimura } while (0)
105 1.1 nisimura
106 1.1 nisimura struct fb_devconfig {
107 1.1 nisimura vaddr_t dc_vaddr; /* memory space virtual base address */
108 1.1 nisimura paddr_t dc_paddr; /* memory space physical base address */
109 1.1 nisimura vsize_t dc_size; /* size of slot memory */
110 1.1 nisimura int dc_wid; /* width of frame buffer */
111 1.1 nisimura int dc_ht; /* height of frame buffer */
112 1.1 nisimura int dc_depth; /* depth, bits per pixel */
113 1.1 nisimura int dc_rowbytes; /* bytes in a FB scan line */
114 1.1 nisimura vaddr_t dc_videobase; /* base of flat frame buffer */
115 1.28 drochner int dc_blanked; /* currently has video disabled */
116 1.28 drochner
117 1.28 drochner struct rasops_info rinfo;
118 1.1 nisimura };
119 1.1 nisimura
120 1.15 nisimura struct hwcmap256 {
121 1.1 nisimura #define CMAP_SIZE 256 /* 256 R/G/B entries */
122 1.1 nisimura u_int8_t r[CMAP_SIZE];
123 1.1 nisimura u_int8_t g[CMAP_SIZE];
124 1.1 nisimura u_int8_t b[CMAP_SIZE];
125 1.1 nisimura };
126 1.1 nisimura
127 1.15 nisimura struct hwcursor64 {
128 1.1 nisimura struct wsdisplay_curpos cc_pos;
129 1.1 nisimura struct wsdisplay_curpos cc_hot;
130 1.1 nisimura struct wsdisplay_curpos cc_size;
131 1.15 nisimura struct wsdisplay_curpos cc_magic;
132 1.1 nisimura #define CURSOR_MAX_SIZE 64
133 1.1 nisimura u_int8_t cc_color[6];
134 1.1 nisimura u_int64_t cc_image[64 + 64];
135 1.1 nisimura };
136 1.1 nisimura
137 1.1 nisimura struct sfb_softc {
138 1.1 nisimura struct device sc_dev;
139 1.1 nisimura struct fb_devconfig *sc_dc; /* device configuration */
140 1.15 nisimura struct hwcmap256 sc_cmap; /* software copy of colormap */
141 1.15 nisimura struct hwcursor64 sc_cursor; /* software copy of cursor */
142 1.1 nisimura int sc_curenb; /* cursor sprite enabled */
143 1.1 nisimura int sc_changed; /* need update of colormap */
144 1.1 nisimura #define DATA_ENB_CHANGED 0x01 /* cursor enable changed */
145 1.1 nisimura #define DATA_CURCMAP_CHANGED 0x02 /* cursor colormap changed */
146 1.1 nisimura #define DATA_CURSHAPE_CHANGED 0x04 /* cursor size, image, mask changed */
147 1.1 nisimura #define DATA_CMAP_CHANGED 0x08 /* colormap changed */
148 1.1 nisimura #define DATA_ALL_CHANGED 0x0f
149 1.1 nisimura int nscreens;
150 1.15 nisimura };
151 1.15 nisimura
152 1.3 nisimura #define HX_MAGIC_X 368
153 1.3 nisimura #define HX_MAGIC_Y 38
154 1.1 nisimura
155 1.27 nisimura static int sfbmatch __P((struct device *, struct cfdata *, void *));
156 1.27 nisimura static void sfbattach __P((struct device *, struct device *, void *));
157 1.1 nisimura
158 1.27 nisimura const struct cfattach sfb_ca = {
159 1.1 nisimura sizeof(struct sfb_softc), sfbmatch, sfbattach,
160 1.1 nisimura };
161 1.1 nisimura
162 1.27 nisimura static void sfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
163 1.27 nisimura static struct fb_devconfig sfb_console_dc;
164 1.27 nisimura static tc_addr_t sfb_consaddr;
165 1.27 nisimura
166 1.35 nisimura static void sfb_putchar __P((void *, int, int, u_int, long));
167 1.35 nisimura static void sfb_erasecols __P((void *, int, int, int, long));
168 1.35 nisimura static void sfb_eraserows __P((void *, int, int, long));
169 1.35 nisimura static void sfb_copyrows __P((void *, int, int, int));
170 1.28 drochner #if 0
171 1.27 nisimura static void sfb_cursor __P((void *, int, int, int));
172 1.27 nisimura static void sfb_copycols __P((void *, int, int, int, int));
173 1.28 drochner #endif
174 1.1 nisimura
175 1.27 nisimura static struct wsscreen_descr sfb_stdscreen = {
176 1.1 nisimura "std", 0, 0,
177 1.28 drochner 0, /* textops */
178 1.1 nisimura 0, 0,
179 1.29 drochner 0 /* capabilities */
180 1.1 nisimura };
181 1.1 nisimura
182 1.27 nisimura static const struct wsscreen_descr *_sfb_scrlist[] = {
183 1.1 nisimura &sfb_stdscreen,
184 1.1 nisimura };
185 1.1 nisimura
186 1.27 nisimura static const struct wsscreen_list sfb_screenlist = {
187 1.1 nisimura sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
188 1.1 nisimura };
189 1.1 nisimura
190 1.36 simonb static int sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
191 1.36 simonb static paddr_t sfbmmap __P((void *, off_t, int));
192 1.1 nisimura
193 1.36 simonb static int sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
194 1.1 nisimura void **, int *, int *, long *));
195 1.36 simonb static void sfb_free_screen __P((void *, void *));
196 1.36 simonb static int sfb_show_screen __P((void *, void *, int,
197 1.36 simonb void (*) (void *, int, int), void *));
198 1.1 nisimura
199 1.27 nisimura static const struct wsdisplay_accessops sfb_accessops = {
200 1.1 nisimura sfbioctl,
201 1.1 nisimura sfbmmap,
202 1.1 nisimura sfb_alloc_screen,
203 1.1 nisimura sfb_free_screen,
204 1.1 nisimura sfb_show_screen,
205 1.7 drochner 0 /* load_font */
206 1.1 nisimura };
207 1.1 nisimura
208 1.1 nisimura int sfb_cnattach __P((tc_addr_t));
209 1.27 nisimura static int sfbintr __P((void *));
210 1.27 nisimura static void sfbinit __P((struct fb_devconfig *));
211 1.1 nisimura
212 1.1 nisimura static int get_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
213 1.1 nisimura static int set_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
214 1.1 nisimura static int set_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
215 1.1 nisimura static int get_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
216 1.1 nisimura static void set_curpos __P((struct sfb_softc *, struct wsdisplay_curpos *));
217 1.1 nisimura static void bt459_set_curpos __P((struct sfb_softc *));
218 1.1 nisimura
219 1.1 nisimura
220 1.3 nisimura /*
221 1.3 nisimura * Compose 2 bit/pixel cursor image. Bit order will be reversed.
222 1.3 nisimura * M M M M I I I I M I M I M I M I
223 1.3 nisimura * [ before ] [ after ]
224 1.3 nisimura * 3 2 1 0 3 2 1 0 0 0 1 1 2 2 3 3
225 1.3 nisimura * 7 6 5 4 7 6 5 4 4 4 5 5 6 6 7 7
226 1.3 nisimura */
227 1.27 nisimura static const u_int8_t shuffle[256] = {
228 1.3 nisimura 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
229 1.3 nisimura 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
230 1.3 nisimura 0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
231 1.3 nisimura 0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
232 1.3 nisimura 0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
233 1.3 nisimura 0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
234 1.3 nisimura 0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
235 1.3 nisimura 0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
236 1.3 nisimura 0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
237 1.3 nisimura 0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
238 1.3 nisimura 0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
239 1.3 nisimura 0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
240 1.3 nisimura 0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
241 1.3 nisimura 0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
242 1.3 nisimura 0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
243 1.3 nisimura 0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
244 1.3 nisimura 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
245 1.3 nisimura 0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
246 1.3 nisimura 0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
247 1.3 nisimura 0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
248 1.3 nisimura 0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
249 1.3 nisimura 0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
250 1.3 nisimura 0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
251 1.3 nisimura 0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
252 1.3 nisimura 0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
253 1.3 nisimura 0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
254 1.3 nisimura 0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
255 1.3 nisimura 0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
256 1.3 nisimura 0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
257 1.3 nisimura 0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
258 1.3 nisimura 0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
259 1.3 nisimura 0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
260 1.3 nisimura };
261 1.3 nisimura
262 1.27 nisimura static int
263 1.1 nisimura sfbmatch(parent, match, aux)
264 1.1 nisimura struct device *parent;
265 1.1 nisimura struct cfdata *match;
266 1.1 nisimura void *aux;
267 1.1 nisimura {
268 1.1 nisimura struct tc_attach_args *ta = aux;
269 1.1 nisimura
270 1.1 nisimura if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0)
271 1.1 nisimura return (0);
272 1.1 nisimura return (1);
273 1.1 nisimura }
274 1.1 nisimura
275 1.27 nisimura static void
276 1.1 nisimura sfb_getdevconfig(dense_addr, dc)
277 1.1 nisimura tc_addr_t dense_addr;
278 1.1 nisimura struct fb_devconfig *dc;
279 1.1 nisimura {
280 1.1 nisimura caddr_t sfbasic;
281 1.28 drochner int i, hsetup, vsetup, vbase, cookie;
282 1.1 nisimura
283 1.1 nisimura dc->dc_vaddr = dense_addr;
284 1.1 nisimura dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr);
285 1.1 nisimura
286 1.1 nisimura sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
287 1.1 nisimura hsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_HSETUP);
288 1.1 nisimura vsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VSETUP);
289 1.19 nisimura *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
290 1.1 nisimura
291 1.1 nisimura dc->dc_wid = (hsetup & 0x1ff) << 2;
292 1.1 nisimura dc->dc_ht = (vsetup & 0x7ff);
293 1.1 nisimura dc->dc_depth = 8;
294 1.1 nisimura dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8);
295 1.1 nisimura dc->dc_videobase = dc->dc_vaddr + SFB_FB_OFFSET + vbase * 4096;
296 1.1 nisimura dc->dc_blanked = 0;
297 1.1 nisimura
298 1.1 nisimura /* initialize colormap and cursor resource */
299 1.1 nisimura sfbinit(dc);
300 1.1 nisimura
301 1.1 nisimura /* clear the screen */
302 1.1 nisimura for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
303 1.1 nisimura *(u_int32_t *)(dc->dc_videobase + i) = 0x0;
304 1.1 nisimura
305 1.35 nisimura dc->rinfo.ri_flg = RI_CENTER;
306 1.28 drochner dc->rinfo.ri_depth = dc->dc_depth;
307 1.28 drochner dc->rinfo.ri_bits = (void *)dc->dc_videobase;
308 1.28 drochner dc->rinfo.ri_width = dc->dc_wid;
309 1.28 drochner dc->rinfo.ri_height = dc->dc_ht;
310 1.28 drochner dc->rinfo.ri_stride = dc->dc_rowbytes;
311 1.28 drochner dc->rinfo.ri_hw = sfbasic;
312 1.1 nisimura
313 1.28 drochner wsfont_init();
314 1.28 drochner /* prefer 8 pixel wide font */
315 1.28 drochner if ((cookie = wsfont_find(NULL, 8, 0, 0)) <= 0)
316 1.28 drochner cookie = wsfont_find(NULL, 0, 0, 0);
317 1.28 drochner if (cookie <= 0) {
318 1.28 drochner printf("sfb: font table is empty\n");
319 1.28 drochner return;
320 1.28 drochner }
321 1.32 ad
322 1.32 ad /* the accelerated sfb_putchar() needs LSbit left */
323 1.28 drochner if (wsfont_lock(cookie, &dc->rinfo.ri_font,
324 1.33 enami WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) {
325 1.28 drochner printf("sfb: couldn't lock font\n");
326 1.28 drochner return;
327 1.28 drochner }
328 1.28 drochner dc->rinfo.ri_wsfcookie = cookie;
329 1.28 drochner
330 1.35 nisimura rasops_init(&dc->rinfo, 34, 80);
331 1.28 drochner
332 1.28 drochner /* add our accelerated functions */
333 1.35 nisimura dc->rinfo.ri_ops.putchar = sfb_putchar;
334 1.35 nisimura dc->rinfo.ri_ops.erasecols = sfb_erasecols;
335 1.28 drochner dc->rinfo.ri_ops.copyrows = sfb_copyrows;
336 1.35 nisimura dc->rinfo.ri_ops.eraserows = sfb_eraserows;
337 1.28 drochner
338 1.28 drochner /* XXX shouldn't be global */
339 1.28 drochner sfb_stdscreen.nrows = dc->rinfo.ri_rows;
340 1.28 drochner sfb_stdscreen.ncols = dc->rinfo.ri_cols;
341 1.28 drochner sfb_stdscreen.textops = &dc->rinfo.ri_ops;
342 1.28 drochner sfb_stdscreen.capabilities = dc->rinfo.ri_caps;
343 1.29 drochner /* our accelerated putchar can't underline */
344 1.29 drochner sfb_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE;
345 1.1 nisimura }
346 1.1 nisimura
347 1.27 nisimura static void
348 1.1 nisimura sfbattach(parent, self, aux)
349 1.1 nisimura struct device *parent, *self;
350 1.1 nisimura void *aux;
351 1.1 nisimura {
352 1.1 nisimura struct sfb_softc *sc = (struct sfb_softc *)self;
353 1.1 nisimura struct tc_attach_args *ta = aux;
354 1.1 nisimura struct wsemuldisplaydev_attach_args waa;
355 1.38 nisimura struct hwcmap256 *cm;
356 1.38 nisimura const u_int8_t *p;
357 1.1 nisimura caddr_t sfbasic;
358 1.38 nisimura int console, index;
359 1.1 nisimura
360 1.1 nisimura console = (ta->ta_addr == sfb_consaddr);
361 1.1 nisimura if (console) {
362 1.1 nisimura sc->sc_dc = &sfb_console_dc;
363 1.1 nisimura sc->nscreens = 1;
364 1.1 nisimura }
365 1.1 nisimura else {
366 1.1 nisimura sc->sc_dc = (struct fb_devconfig *)
367 1.1 nisimura malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
368 1.28 drochner memset(sc->sc_dc, 0, sizeof(struct fb_devconfig));
369 1.1 nisimura sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
370 1.1 nisimura }
371 1.1 nisimura printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
372 1.1 nisimura sc->sc_dc->dc_depth);
373 1.1 nisimura
374 1.38 nisimura cm = &sc->sc_cmap;
375 1.38 nisimura p = rasops_cmap;
376 1.38 nisimura for (index = 0; index < CMAP_SIZE; index++, p += 3) {
377 1.38 nisimura cm->r[index] = p[0];
378 1.38 nisimura cm->g[index] = p[1];
379 1.38 nisimura cm->b[index] = p[2];
380 1.38 nisimura }
381 1.15 nisimura
382 1.15 nisimura sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
383 1.15 nisimura sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
384 1.1 nisimura
385 1.27 nisimura tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc);
386 1.1 nisimura
387 1.1 nisimura sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
388 1.1 nisimura *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
389 1.1 nisimura *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
390 1.1 nisimura
391 1.1 nisimura waa.console = console;
392 1.1 nisimura waa.scrdata = &sfb_screenlist;
393 1.1 nisimura waa.accessops = &sfb_accessops;
394 1.1 nisimura waa.accesscookie = sc;
395 1.1 nisimura
396 1.1 nisimura config_found(self, &waa, wsemuldisplaydevprint);
397 1.1 nisimura }
398 1.1 nisimura
399 1.27 nisimura static int
400 1.1 nisimura sfbioctl(v, cmd, data, flag, p)
401 1.1 nisimura void *v;
402 1.1 nisimura u_long cmd;
403 1.1 nisimura caddr_t data;
404 1.1 nisimura int flag;
405 1.1 nisimura struct proc *p;
406 1.1 nisimura {
407 1.1 nisimura struct sfb_softc *sc = v;
408 1.1 nisimura struct fb_devconfig *dc = sc->sc_dc;
409 1.1 nisimura int turnoff;
410 1.1 nisimura
411 1.1 nisimura switch (cmd) {
412 1.1 nisimura case WSDISPLAYIO_GTYPE:
413 1.1 nisimura *(u_int *)data = WSDISPLAY_TYPE_SFB;
414 1.1 nisimura return (0);
415 1.1 nisimura
416 1.1 nisimura case WSDISPLAYIO_GINFO:
417 1.1 nisimura #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
418 1.1 nisimura wsd_fbip->height = sc->sc_dc->dc_ht;
419 1.1 nisimura wsd_fbip->width = sc->sc_dc->dc_wid;
420 1.1 nisimura wsd_fbip->depth = sc->sc_dc->dc_depth;
421 1.1 nisimura wsd_fbip->cmsize = CMAP_SIZE;
422 1.1 nisimura #undef fbt
423 1.1 nisimura return (0);
424 1.1 nisimura
425 1.1 nisimura case WSDISPLAYIO_GETCMAP:
426 1.1 nisimura return get_cmap(sc, (struct wsdisplay_cmap *)data);
427 1.1 nisimura
428 1.1 nisimura case WSDISPLAYIO_PUTCMAP:
429 1.1 nisimura return set_cmap(sc, (struct wsdisplay_cmap *)data);
430 1.1 nisimura
431 1.1 nisimura case WSDISPLAYIO_SVIDEO:
432 1.1 nisimura turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
433 1.1 nisimura if ((dc->dc_blanked == 0) ^ turnoff) {
434 1.1 nisimura dc->dc_blanked = turnoff;
435 1.18 nisimura #if 0 /* XXX later XXX */
436 1.18 nisimura To turn off, assign value 0 in ASIC_VIDEO_VALID register.
437 1.18 nisimura #endif /* XXX XXX XXX */
438 1.1 nisimura }
439 1.1 nisimura return (0);
440 1.1 nisimura
441 1.1 nisimura case WSDISPLAYIO_GVIDEO:
442 1.1 nisimura *(u_int *)data = dc->dc_blanked ?
443 1.1 nisimura WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
444 1.1 nisimura return (0);
445 1.1 nisimura
446 1.1 nisimura case WSDISPLAYIO_GCURPOS:
447 1.1 nisimura *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
448 1.1 nisimura return (0);
449 1.1 nisimura
450 1.1 nisimura case WSDISPLAYIO_SCURPOS:
451 1.1 nisimura set_curpos(sc, (struct wsdisplay_curpos *)data);
452 1.1 nisimura bt459_set_curpos(sc);
453 1.1 nisimura return (0);
454 1.1 nisimura
455 1.1 nisimura case WSDISPLAYIO_GCURMAX:
456 1.1 nisimura ((struct wsdisplay_curpos *)data)->x =
457 1.1 nisimura ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
458 1.1 nisimura return (0);
459 1.1 nisimura
460 1.1 nisimura case WSDISPLAYIO_GCURSOR:
461 1.1 nisimura return get_cursor(sc, (struct wsdisplay_cursor *)data);
462 1.1 nisimura
463 1.1 nisimura case WSDISPLAYIO_SCURSOR:
464 1.1 nisimura return set_cursor(sc, (struct wsdisplay_cursor *)data);
465 1.1 nisimura }
466 1.1 nisimura return ENOTTY;
467 1.1 nisimura }
468 1.1 nisimura
469 1.36 simonb static paddr_t
470 1.1 nisimura sfbmmap(v, offset, prot)
471 1.1 nisimura void *v;
472 1.1 nisimura off_t offset;
473 1.1 nisimura int prot;
474 1.1 nisimura {
475 1.1 nisimura struct sfb_softc *sc = v;
476 1.1 nisimura
477 1.10 nisimura if (offset >= SFB_SIZE || offset < 0)
478 1.1 nisimura return (-1);
479 1.1 nisimura return machine_btop(sc->sc_dc->dc_paddr + offset);
480 1.1 nisimura }
481 1.1 nisimura
482 1.27 nisimura static int
483 1.1 nisimura sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
484 1.1 nisimura void *v;
485 1.1 nisimura const struct wsscreen_descr *type;
486 1.1 nisimura void **cookiep;
487 1.1 nisimura int *curxp, *curyp;
488 1.1 nisimura long *attrp;
489 1.1 nisimura {
490 1.1 nisimura struct sfb_softc *sc = v;
491 1.1 nisimura long defattr;
492 1.1 nisimura
493 1.1 nisimura if (sc->nscreens > 0)
494 1.1 nisimura return (ENOMEM);
495 1.1 nisimura
496 1.28 drochner *cookiep = &sc->sc_dc->rinfo; /* one and only for now */
497 1.1 nisimura *curxp = 0;
498 1.1 nisimura *curyp = 0;
499 1.28 drochner (*sc->sc_dc->rinfo.ri_ops.alloc_attr)(&sc->sc_dc->rinfo, 0, 0, 0, &defattr);
500 1.1 nisimura *attrp = defattr;
501 1.1 nisimura sc->nscreens++;
502 1.1 nisimura return (0);
503 1.1 nisimura }
504 1.1 nisimura
505 1.27 nisimura static void
506 1.1 nisimura sfb_free_screen(v, cookie)
507 1.1 nisimura void *v;
508 1.1 nisimura void *cookie;
509 1.1 nisimura {
510 1.1 nisimura struct sfb_softc *sc = v;
511 1.1 nisimura
512 1.1 nisimura if (sc->sc_dc == &sfb_console_dc)
513 1.1 nisimura panic("sfb_free_screen: console");
514 1.1 nisimura
515 1.1 nisimura sc->nscreens--;
516 1.1 nisimura }
517 1.1 nisimura
518 1.30 drochner static int
519 1.30 drochner sfb_show_screen(v, cookie, waitok, cb, cbarg)
520 1.1 nisimura void *v;
521 1.1 nisimura void *cookie;
522 1.30 drochner int waitok;
523 1.30 drochner void (*cb) __P((void *, int, int));
524 1.30 drochner void *cbarg;
525 1.1 nisimura {
526 1.30 drochner
527 1.30 drochner return (0);
528 1.1 nisimura }
529 1.1 nisimura
530 1.27 nisimura /* EXPORT */ int
531 1.1 nisimura sfb_cnattach(addr)
532 1.1 nisimura tc_addr_t addr;
533 1.1 nisimura {
534 1.1 nisimura struct fb_devconfig *dcp = &sfb_console_dc;
535 1.1 nisimura long defattr;
536 1.1 nisimura
537 1.1 nisimura sfb_getdevconfig(addr, dcp);
538 1.1 nisimura
539 1.28 drochner (*dcp->rinfo.ri_ops.alloc_attr)(&dcp->rinfo, 0, 0, 0, &defattr);
540 1.1 nisimura
541 1.28 drochner wsdisplay_cnattach(&sfb_stdscreen, &dcp->rinfo, 0, 0, defattr);
542 1.1 nisimura sfb_consaddr = addr;
543 1.1 nisimura return(0);
544 1.1 nisimura }
545 1.1 nisimura
546 1.27 nisimura static int
547 1.1 nisimura sfbintr(arg)
548 1.1 nisimura void *arg;
549 1.1 nisimura {
550 1.1 nisimura struct sfb_softc *sc = arg;
551 1.1 nisimura caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
552 1.1 nisimura caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
553 1.16 nisimura caddr_t vdac;
554 1.1 nisimura int v;
555 1.1 nisimura
556 1.1 nisimura *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
557 1.1 nisimura /* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
558 1.1 nisimura
559 1.1 nisimura if (sc->sc_changed == 0)
560 1.1 nisimura return (1);
561 1.1 nisimura
562 1.1 nisimura vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
563 1.1 nisimura v = sc->sc_changed;
564 1.1 nisimura sc->sc_changed = 0;
565 1.1 nisimura
566 1.1 nisimura if (v & DATA_ENB_CHANGED) {
567 1.31 ad SELECT(vdac, BT459_IREG_CCR);
568 1.16 nisimura REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
569 1.1 nisimura }
570 1.1 nisimura if (v & DATA_CURCMAP_CHANGED) {
571 1.1 nisimura u_int8_t *cp = sc->sc_cursor.cc_color;
572 1.1 nisimura
573 1.31 ad SELECT(vdac, BT459_IREG_CCOLOR_2);
574 1.16 nisimura REG(vdac, bt_reg) = cp[1]; tc_wmb();
575 1.16 nisimura REG(vdac, bt_reg) = cp[3]; tc_wmb();
576 1.16 nisimura REG(vdac, bt_reg) = cp[5]; tc_wmb();
577 1.16 nisimura
578 1.16 nisimura REG(vdac, bt_reg) = cp[0]; tc_wmb();
579 1.16 nisimura REG(vdac, bt_reg) = cp[2]; tc_wmb();
580 1.16 nisimura REG(vdac, bt_reg) = cp[4]; tc_wmb();
581 1.1 nisimura }
582 1.1 nisimura if (v & DATA_CURSHAPE_CHANGED) {
583 1.3 nisimura u_int8_t *ip, *mp, img, msk;
584 1.3 nisimura u_int8_t u;
585 1.3 nisimura int bcnt;
586 1.3 nisimura
587 1.3 nisimura ip = (u_int8_t *)sc->sc_cursor.cc_image;
588 1.3 nisimura mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
589 1.3 nisimura
590 1.3 nisimura bcnt = 0;
591 1.31 ad SELECT(vdac, BT459_IREG_CRAM_BASE+0);
592 1.3 nisimura /* 64 pixel scan line is consisted with 16 byte cursor ram */
593 1.3 nisimura while (bcnt < sc->sc_cursor.cc_size.y * 16) {
594 1.3 nisimura /* pad right half 32 pixel when smaller than 33 */
595 1.3 nisimura if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
596 1.16 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
597 1.16 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
598 1.3 nisimura }
599 1.3 nisimura else {
600 1.3 nisimura img = *ip++;
601 1.3 nisimura msk = *mp++;
602 1.3 nisimura img &= msk; /* cookie off image */
603 1.3 nisimura u = (msk & 0x0f) << 4 | (img & 0x0f);
604 1.16 nisimura REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
605 1.3 nisimura u = (msk & 0xf0) | (img & 0xf0) >> 4;
606 1.16 nisimura REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
607 1.3 nisimura }
608 1.3 nisimura bcnt += 2;
609 1.3 nisimura }
610 1.3 nisimura /* pad unoccupied scan lines */
611 1.3 nisimura while (bcnt < CURSOR_MAX_SIZE * 16) {
612 1.16 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
613 1.16 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
614 1.3 nisimura bcnt += 2;
615 1.1 nisimura }
616 1.1 nisimura }
617 1.1 nisimura if (v & DATA_CMAP_CHANGED) {
618 1.15 nisimura struct hwcmap256 *cm = &sc->sc_cmap;
619 1.1 nisimura int index;
620 1.1 nisimura
621 1.16 nisimura SELECT(vdac, 0);
622 1.1 nisimura for (index = 0; index < CMAP_SIZE; index++) {
623 1.16 nisimura REG(vdac, bt_cmap) = cm->r[index]; tc_wmb();
624 1.16 nisimura REG(vdac, bt_cmap) = cm->g[index]; tc_wmb();
625 1.16 nisimura REG(vdac, bt_cmap) = cm->b[index]; tc_wmb();
626 1.1 nisimura }
627 1.1 nisimura }
628 1.1 nisimura return (1);
629 1.1 nisimura }
630 1.1 nisimura
631 1.27 nisimura static void
632 1.1 nisimura sfbinit(dc)
633 1.1 nisimura struct fb_devconfig *dc;
634 1.1 nisimura {
635 1.1 nisimura caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
636 1.16 nisimura caddr_t vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
637 1.38 nisimura const u_int8_t *p;
638 1.1 nisimura int i;
639 1.1 nisimura
640 1.1 nisimura *(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
641 1.1 nisimura *(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
642 1.21 nisimura *(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */
643 1.21 nisimura *(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3; /* ROP_COPY */
644 1.1 nisimura
645 1.1 nisimura *(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
646 1.1 nisimura
647 1.31 ad SELECT(vdac, BT459_IREG_COMMAND_0);
648 1.16 nisimura REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb();
649 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb();
650 1.16 nisimura REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb();
651 1.16 nisimura REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb();
652 1.16 nisimura REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb();
653 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb();
654 1.16 nisimura REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb();
655 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb();
656 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb();
657 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb();
658 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb();
659 1.16 nisimura
660 1.31 ad SELECT(vdac, BT459_IREG_CCR);
661 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
662 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
663 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
664 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
665 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
666 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
667 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
668 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
669 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
670 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
671 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
672 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
673 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
674 1.3 nisimura
675 1.3 nisimura /* build sane colormap */
676 1.16 nisimura SELECT(vdac, 0);
677 1.38 nisimura p = rasops_cmap;
678 1.38 nisimura for (i = 0; i < CMAP_SIZE; i++, p += 3) {
679 1.38 nisimura REG(vdac, bt_cmap) = p[0]; tc_wmb();
680 1.38 nisimura REG(vdac, bt_cmap) = p[1]; tc_wmb();
681 1.38 nisimura REG(vdac, bt_cmap) = p[2]; tc_wmb();
682 1.3 nisimura }
683 1.3 nisimura
684 1.3 nisimura /* clear out cursor image */
685 1.31 ad SELECT(vdac, BT459_IREG_CRAM_BASE);
686 1.3 nisimura for (i = 0; i < 1024; i++)
687 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
688 1.3 nisimura
689 1.3 nisimura /*
690 1.3 nisimura * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
691 1.3 nisimura * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
692 1.3 nisimura * image color. CCOLOR_1 will be never used.
693 1.3 nisimura */
694 1.31 ad SELECT(vdac, BT459_IREG_CCOLOR_1);
695 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
696 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
697 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
698 1.16 nisimura
699 1.21 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
700 1.21 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
701 1.21 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
702 1.16 nisimura
703 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
704 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
705 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
706 1.1 nisimura }
707 1.1 nisimura
708 1.1 nisimura static int
709 1.1 nisimura get_cmap(sc, p)
710 1.1 nisimura struct sfb_softc *sc;
711 1.1 nisimura struct wsdisplay_cmap *p;
712 1.1 nisimura {
713 1.1 nisimura u_int index = p->index, count = p->count;
714 1.1 nisimura
715 1.1 nisimura if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
716 1.1 nisimura return (EINVAL);
717 1.1 nisimura
718 1.13 mrg if (!uvm_useracc(p->red, count, B_WRITE) ||
719 1.13 mrg !uvm_useracc(p->green, count, B_WRITE) ||
720 1.13 mrg !uvm_useracc(p->blue, count, B_WRITE))
721 1.1 nisimura return (EFAULT);
722 1.1 nisimura
723 1.1 nisimura copyout(&sc->sc_cmap.r[index], p->red, count);
724 1.1 nisimura copyout(&sc->sc_cmap.g[index], p->green, count);
725 1.1 nisimura copyout(&sc->sc_cmap.b[index], p->blue, count);
726 1.1 nisimura
727 1.1 nisimura return (0);
728 1.1 nisimura }
729 1.1 nisimura
730 1.1 nisimura static int
731 1.1 nisimura set_cmap(sc, p)
732 1.1 nisimura struct sfb_softc *sc;
733 1.1 nisimura struct wsdisplay_cmap *p;
734 1.1 nisimura {
735 1.1 nisimura u_int index = p->index, count = p->count;
736 1.1 nisimura
737 1.1 nisimura if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
738 1.1 nisimura return (EINVAL);
739 1.1 nisimura
740 1.13 mrg if (!uvm_useracc(p->red, count, B_READ) ||
741 1.13 mrg !uvm_useracc(p->green, count, B_READ) ||
742 1.13 mrg !uvm_useracc(p->blue, count, B_READ))
743 1.1 nisimura return (EFAULT);
744 1.1 nisimura
745 1.1 nisimura copyin(p->red, &sc->sc_cmap.r[index], count);
746 1.1 nisimura copyin(p->green, &sc->sc_cmap.g[index], count);
747 1.1 nisimura copyin(p->blue, &sc->sc_cmap.b[index], count);
748 1.1 nisimura
749 1.1 nisimura sc->sc_changed |= DATA_CMAP_CHANGED;
750 1.1 nisimura
751 1.1 nisimura return (0);
752 1.1 nisimura }
753 1.1 nisimura
754 1.1 nisimura static int
755 1.1 nisimura set_cursor(sc, p)
756 1.1 nisimura struct sfb_softc *sc;
757 1.1 nisimura struct wsdisplay_cursor *p;
758 1.1 nisimura {
759 1.1 nisimura #define cc (&sc->sc_cursor)
760 1.5 nisimura int v, index, count, icount;
761 1.1 nisimura
762 1.1 nisimura v = p->which;
763 1.1 nisimura if (v & WSDISPLAY_CURSOR_DOCMAP) {
764 1.1 nisimura index = p->cmap.index;
765 1.1 nisimura count = p->cmap.count;
766 1.1 nisimura if (index >= 2 || (index + count) > 2)
767 1.1 nisimura return (EINVAL);
768 1.13 mrg if (!uvm_useracc(p->cmap.red, count, B_READ) ||
769 1.13 mrg !uvm_useracc(p->cmap.green, count, B_READ) ||
770 1.13 mrg !uvm_useracc(p->cmap.blue, count, B_READ))
771 1.1 nisimura return (EFAULT);
772 1.1 nisimura }
773 1.1 nisimura if (v & WSDISPLAY_CURSOR_DOSHAPE) {
774 1.1 nisimura if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
775 1.1 nisimura return (EINVAL);
776 1.5 nisimura icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
777 1.13 mrg if (!uvm_useracc(p->image, icount, B_READ) ||
778 1.13 mrg !uvm_useracc(p->mask, icount, B_READ))
779 1.1 nisimura return (EFAULT);
780 1.1 nisimura }
781 1.1 nisimura if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
782 1.1 nisimura if (v & WSDISPLAY_CURSOR_DOCUR)
783 1.1 nisimura cc->cc_hot = p->hot;
784 1.1 nisimura if (v & WSDISPLAY_CURSOR_DOPOS)
785 1.1 nisimura set_curpos(sc, &p->pos);
786 1.1 nisimura bt459_set_curpos(sc);
787 1.1 nisimura }
788 1.1 nisimura
789 1.1 nisimura sc->sc_changed = 0;
790 1.1 nisimura if (v & WSDISPLAY_CURSOR_DOCUR) {
791 1.1 nisimura sc->sc_curenb = p->enable;
792 1.1 nisimura sc->sc_changed |= DATA_ENB_CHANGED;
793 1.1 nisimura }
794 1.1 nisimura if (v & WSDISPLAY_CURSOR_DOCMAP) {
795 1.1 nisimura copyin(p->cmap.red, &cc->cc_color[index], count);
796 1.1 nisimura copyin(p->cmap.green, &cc->cc_color[index + 2], count);
797 1.1 nisimura copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
798 1.1 nisimura sc->sc_changed |= DATA_CURCMAP_CHANGED;
799 1.1 nisimura }
800 1.1 nisimura if (v & WSDISPLAY_CURSOR_DOSHAPE) {
801 1.1 nisimura cc->cc_size = p->size;
802 1.1 nisimura memset(cc->cc_image, 0, sizeof cc->cc_image);
803 1.5 nisimura copyin(p->image, cc->cc_image, icount);
804 1.5 nisimura copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
805 1.1 nisimura sc->sc_changed |= DATA_CURSHAPE_CHANGED;
806 1.1 nisimura }
807 1.1 nisimura
808 1.1 nisimura return (0);
809 1.1 nisimura #undef cc
810 1.1 nisimura }
811 1.1 nisimura
812 1.1 nisimura static int
813 1.1 nisimura get_cursor(sc, p)
814 1.1 nisimura struct sfb_softc *sc;
815 1.1 nisimura struct wsdisplay_cursor *p;
816 1.1 nisimura {
817 1.35 nisimura
818 1.1 nisimura return (ENOTTY); /* XXX */
819 1.1 nisimura }
820 1.1 nisimura
821 1.1 nisimura static void
822 1.1 nisimura set_curpos(sc, curpos)
823 1.1 nisimura struct sfb_softc *sc;
824 1.1 nisimura struct wsdisplay_curpos *curpos;
825 1.1 nisimura {
826 1.1 nisimura struct fb_devconfig *dc = sc->sc_dc;
827 1.1 nisimura int x = curpos->x, y = curpos->y;
828 1.1 nisimura
829 1.1 nisimura if (y < 0)
830 1.1 nisimura y = 0;
831 1.3 nisimura else if (y > dc->dc_ht)
832 1.3 nisimura y = dc->dc_ht;
833 1.1 nisimura if (x < 0)
834 1.1 nisimura x = 0;
835 1.3 nisimura else if (x > dc->dc_wid)
836 1.3 nisimura x = dc->dc_wid;
837 1.1 nisimura sc->sc_cursor.cc_pos.x = x;
838 1.1 nisimura sc->sc_cursor.cc_pos.y = y;
839 1.1 nisimura }
840 1.1 nisimura
841 1.1 nisimura static void
842 1.1 nisimura bt459_set_curpos(sc)
843 1.1 nisimura struct sfb_softc *sc;
844 1.1 nisimura {
845 1.27 nisimura caddr_t vdac = (caddr_t)sc->sc_dc->dc_vaddr + SFB_RAMDAC_OFFSET;
846 1.3 nisimura int x, y, s;
847 1.1 nisimura
848 1.3 nisimura x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
849 1.3 nisimura y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
850 1.15 nisimura
851 1.15 nisimura x += sc->sc_cursor.cc_magic.x;
852 1.15 nisimura y += sc->sc_cursor.cc_magic.y;
853 1.1 nisimura
854 1.1 nisimura s = spltty();
855 1.1 nisimura
856 1.31 ad SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
857 1.16 nisimura REG(vdac, bt_reg) = x; tc_wmb();
858 1.16 nisimura REG(vdac, bt_reg) = x >> 8; tc_wmb();
859 1.16 nisimura REG(vdac, bt_reg) = y; tc_wmb();
860 1.16 nisimura REG(vdac, bt_reg) = y >> 8; tc_wmb();
861 1.1 nisimura
862 1.1 nisimura splx(s);
863 1.1 nisimura }
864 1.10 nisimura
865 1.10 nisimura #define MODE_SIMPLE 0
866 1.10 nisimura #define MODE_OPAQUESTIPPLE 1
867 1.10 nisimura #define MODE_OPAQUELINE 2
868 1.10 nisimura #define MODE_TRANSPARENTSTIPPLE 5
869 1.10 nisimura #define MODE_TRANSPARENTLINE 6
870 1.10 nisimura #define MODE_COPY 7
871 1.10 nisimura
872 1.21 nisimura /* parameters for 8bpp configuration */
873 1.10 nisimura #define SFBALIGNMASK 0x7
874 1.10 nisimura #define SFBSTIPPLEALL1 0xffffffff
875 1.10 nisimura #define SFBSTIPPLEBITS 32
876 1.10 nisimura #define SFBSTIPPLEBITMASK 0x1f
877 1.10 nisimura #define SFBSTIPPLEBYTESDONE 32
878 1.21 nisimura #define SFBCOPYALL1 0xffffffff
879 1.21 nisimura #define SFBCOPYBITS 32
880 1.21 nisimura #define SFBCOPYBITMASK 0x1f
881 1.21 nisimura #define SFBCOPYBYTESDONE 32
882 1.21 nisimura
883 1.35 nisimura #if defined(pmax)
884 1.21 nisimura #define WRITE_MB()
885 1.21 nisimura #define BUMP(p) (p)
886 1.21 nisimura #endif
887 1.21 nisimura
888 1.35 nisimura #if defined(alpha)
889 1.21 nisimura #define WRITE_MB() tc_wmb()
890 1.41 nisimura /* SFB registers replicated in 128B stride; cycle after eight iterations */
891 1.40 nisimura #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x80) & ~0x400))
892 1.21 nisimura #endif
893 1.21 nisimura
894 1.21 nisimura #define SFBMODE(p, v) \
895 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
896 1.21 nisimura #define SFBROP(p, v) \
897 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
898 1.21 nisimura #define SFBPLANEMASK(p, v) \
899 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
900 1.21 nisimura #define SFBPIXELMASK(p, v) \
901 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
902 1.21 nisimura #define SFBADDRESS(p, v) \
903 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
904 1.21 nisimura #define SFBSTART(p, v) \
905 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
906 1.21 nisimura #define SFBPIXELSHIFT(p, v) \
907 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
908 1.21 nisimura #define SFBFG(p, v) \
909 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
910 1.21 nisimura #define SFBBG(p, v) \
911 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
912 1.21 nisimura
913 1.28 drochner #if 0
914 1.10 nisimura /*
915 1.10 nisimura * Paint (or unpaint) the cursor.
916 1.10 nisimura */
917 1.27 nisimura static void
918 1.10 nisimura sfb_cursor(id, on, row, col)
919 1.10 nisimura void *id;
920 1.10 nisimura int on, row, col;
921 1.10 nisimura {
922 1.40 nisimura /* use Bt459 sprite cursor */
923 1.10 nisimura }
924 1.28 drochner #endif
925 1.10 nisimura
926 1.10 nisimura /*
927 1.10 nisimura * Actually write a string to the frame buffer.
928 1.10 nisimura */
929 1.27 nisimura static void
930 1.10 nisimura sfb_putchar(id, row, col, uc, attr)
931 1.10 nisimura void *id;
932 1.10 nisimura int row, col;
933 1.10 nisimura u_int uc;
934 1.10 nisimura long attr;
935 1.10 nisimura {
936 1.28 drochner struct rasops_info *ri = id;
937 1.21 nisimura caddr_t sfb, p;
938 1.21 nisimura int scanspan, height, width, align, x, y;
939 1.21 nisimura u_int32_t lmask, rmask, glyph;
940 1.28 drochner u_int8_t *g;
941 1.10 nisimura
942 1.28 drochner x = col * ri->ri_font->fontwidth;
943 1.28 drochner y = row * ri->ri_font->fontheight;
944 1.28 drochner scanspan = ri->ri_stride;
945 1.28 drochner height = ri->ri_font->fontheight;
946 1.28 drochner uc -= ri->ri_font->firstchar;
947 1.28 drochner g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
948 1.21 nisimura
949 1.28 drochner p = ri->ri_bits + y * scanspan + x;
950 1.21 nisimura align = (long)p & SFBALIGNMASK;
951 1.21 nisimura p -= align;
952 1.28 drochner width = ri->ri_font->fontwidth + align;
953 1.21 nisimura lmask = SFBSTIPPLEALL1 << align;
954 1.21 nisimura rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
955 1.28 drochner sfb = ri->ri_hw;
956 1.10 nisimura
957 1.21 nisimura SFBMODE(sfb, MODE_OPAQUESTIPPLE);
958 1.21 nisimura SFBPLANEMASK(sfb, ~0);
959 1.40 nisimura SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
960 1.40 nisimura SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
961 1.40 nisimura
962 1.40 nisimura /* XXX 2B stride fonts only XXX */
963 1.40 nisimura lmask = lmask & rmask;
964 1.40 nisimura while (height > 0) {
965 1.40 nisimura glyph = *(u_int16_t *)g; /* XXX */
966 1.40 nisimura SFBPIXELMASK(sfb, lmask);
967 1.40 nisimura SFBADDRESS(sfb, (long)p);
968 1.40 nisimura SFBSTART(sfb, glyph << align);
969 1.40 nisimura p += scanspan;
970 1.40 nisimura g += 2; /* XXX */
971 1.40 nisimura height--;
972 1.21 nisimura }
973 1.21 nisimura SFBMODE(sfb, MODE_SIMPLE);
974 1.23 nisimura SFBPIXELMASK(sfb, ~0); /* entire pixel */
975 1.10 nisimura }
976 1.10 nisimura
977 1.28 drochner #if 0
978 1.10 nisimura /*
979 1.16 nisimura * Copy characters in a line.
980 1.10 nisimura */
981 1.27 nisimura static void
982 1.10 nisimura sfb_copycols(id, row, srccol, dstcol, ncols)
983 1.10 nisimura void *id;
984 1.10 nisimura int row, srccol, dstcol, ncols;
985 1.10 nisimura {
986 1.35 nisimura struct rasops_info *ri = id;
987 1.16 nisimura caddr_t sp, dp, basex, sfb;
988 1.25 nisimura int scanspan, height, width, aligns, alignd, shift, w, y;
989 1.39 nisimura u_int32_t lmaskd, rmaskd;
990 1.10 nisimura
991 1.35 nisimura scanspan = ri->ri_stride;
992 1.35 nisimura y = row * ri->ri_font->fontheight;
993 1.39 nisimura basex = ri->ri_bits + y * scanspan;
994 1.35 nisimura height = ri->ri_font->fontheight;
995 1.35 nisimura w = ri->ri_font->fontwidth * ncols;
996 1.16 nisimura
997 1.35 nisimura sp = basex + ri->ri_font->fontwidth * srccol;
998 1.25 nisimura aligns = (long)sp & SFBALIGNMASK;
999 1.35 nisimura dp = basex + ri->ri_font->fontwidth * dstcol;
1000 1.25 nisimura alignd = (long)dp & SFBALIGNMASK;
1001 1.35 nisimura sfb = ri->ri_hw;
1002 1.16 nisimura
1003 1.21 nisimura SFBMODE(sfb, MODE_COPY);
1004 1.21 nisimura SFBPLANEMASK(sfb, ~0);
1005 1.39 nisimura /* small enough to fit in a single 32bit */
1006 1.39 nisimura if ((aligns + w) <= SFBCOPYBITS && (alignd + w) <= SFBCOPYBITS) {
1007 1.39 nisimura SFBPIXELSHIFT(sfb, alignd - aligns);
1008 1.39 nisimura lmaskd = SFBCOPYALL1 << alignd;
1009 1.39 nisimura rmaskd = SFBCOPYALL1 >> (-(alignd + w) & SFBCOPYBITMASK);
1010 1.39 nisimura lmaskd = lmaskd & rmaskd;
1011 1.39 nisimura sp -= aligns;
1012 1.39 nisimura dp -= alignd;
1013 1.39 nisimura while (height > 0) {
1014 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1015 1.39 nisimura *(u_int32_t *)dp = lmaskd; WRITE_MB();
1016 1.39 nisimura sp += scanspan;
1017 1.39 nisimura dp += scanspan;
1018 1.39 nisimura height--;
1019 1.39 nisimura }
1020 1.39 nisimura }
1021 1.26 nisimura /* copy forward (left-to-right) */
1022 1.39 nisimura else if (dstcol < srccol || srccol + ncols < dstcol) {
1023 1.26 nisimura caddr_t sq, dq;
1024 1.26 nisimura
1025 1.26 nisimura shift = alignd - aligns;
1026 1.26 nisimura if (shift < 0) {
1027 1.26 nisimura shift = 8 + shift; /* enforce right rotate */
1028 1.34 nisimura alignd += 8; /* bearing on left edge */
1029 1.16 nisimura }
1030 1.39 nisimura width = alignd + w;
1031 1.39 nisimura lmaskd = SFBCOPYALL1 << alignd;
1032 1.39 nisimura rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1033 1.34 nisimura sp -= aligns;
1034 1.34 nisimura dp -= alignd;
1035 1.16 nisimura
1036 1.26 nisimura SFBPIXELSHIFT(sfb, shift);
1037 1.16 nisimura w = width;
1038 1.26 nisimura sq = sp;
1039 1.26 nisimura dq = dp;
1040 1.16 nisimura while (height > 0) {
1041 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1042 1.39 nisimura *(u_int32_t *)dp = lmaskd; WRITE_MB();
1043 1.21 nisimura width -= 2 * SFBCOPYBITS;
1044 1.16 nisimura while (width > 0) {
1045 1.21 nisimura sp += SFBCOPYBYTESDONE;
1046 1.21 nisimura dp += SFBCOPYBYTESDONE;
1047 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1048 1.39 nisimura *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB();
1049 1.21 nisimura width -= SFBCOPYBITS;
1050 1.16 nisimura }
1051 1.21 nisimura sp += SFBCOPYBYTESDONE;
1052 1.21 nisimura dp += SFBCOPYBYTESDONE;
1053 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1054 1.39 nisimura *(u_int32_t *)dp = rmaskd; WRITE_MB();
1055 1.16 nisimura sp = (sq += scanspan);
1056 1.16 nisimura dp = (dq += scanspan);
1057 1.16 nisimura width = w;
1058 1.16 nisimura height--;
1059 1.16 nisimura }
1060 1.16 nisimura }
1061 1.16 nisimura /* copy backward (right-to-left) */
1062 1.16 nisimura else {
1063 1.26 nisimura caddr_t sq, dq;
1064 1.26 nisimura
1065 1.26 nisimura shift = alignd - aligns;
1066 1.26 nisimura if (shift > 0) {
1067 1.34 nisimura shift = shift - 8; /* force left rotate */
1068 1.39 nisimura alignd += 24;
1069 1.26 nisimura }
1070 1.39 nisimura width = alignd + w;
1071 1.39 nisimura lmaskd = SFBCOPYALL1 << alignd;
1072 1.39 nisimura rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1073 1.34 nisimura sp -= aligns;
1074 1.34 nisimura dp -= alignd;
1075 1.16 nisimura
1076 1.26 nisimura SFBPIXELSHIFT(sfb, shift);
1077 1.16 nisimura w = width;
1078 1.39 nisimura sq = sp += (((aligns + w) - 1) & ~31);
1079 1.39 nisimura dq = dp += (((alignd + w) - 1) & ~31);
1080 1.16 nisimura while (height > 0) {
1081 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1082 1.39 nisimura *(u_int32_t *)dp = rmaskd; WRITE_MB();
1083 1.21 nisimura width -= 2 * SFBCOPYBITS;
1084 1.16 nisimura while (width > 0) {
1085 1.21 nisimura sp -= SFBCOPYBYTESDONE;
1086 1.21 nisimura dp -= SFBCOPYBYTESDONE;
1087 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1088 1.39 nisimura *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB();
1089 1.21 nisimura width -= SFBCOPYBITS;
1090 1.16 nisimura }
1091 1.21 nisimura sp -= SFBCOPYBYTESDONE;
1092 1.21 nisimura dp -= SFBCOPYBYTESDONE;
1093 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1094 1.39 nisimura *(u_int32_t *)dp = lmaskd; WRITE_MB();
1095 1.16 nisimura
1096 1.16 nisimura sp = (sq += scanspan);
1097 1.16 nisimura dp = (dq += scanspan);
1098 1.16 nisimura width = w;
1099 1.16 nisimura height--;
1100 1.16 nisimura }
1101 1.16 nisimura }
1102 1.21 nisimura SFBMODE(sfb, MODE_SIMPLE);
1103 1.26 nisimura SFBPIXELSHIFT(sfb, 0);
1104 1.10 nisimura }
1105 1.28 drochner #endif
1106 1.10 nisimura
1107 1.10 nisimura /*
1108 1.16 nisimura * Clear characters in a line.
1109 1.10 nisimura */
1110 1.27 nisimura static void
1111 1.21 nisimura sfb_erasecols(id, row, startcol, ncols, attr)
1112 1.10 nisimura void *id;
1113 1.10 nisimura int row, startcol, ncols;
1114 1.21 nisimura long attr;
1115 1.10 nisimura {
1116 1.35 nisimura struct rasops_info *ri = id;
1117 1.10 nisimura caddr_t sfb, p;
1118 1.10 nisimura int scanspan, startx, height, width, align, w, y;
1119 1.10 nisimura u_int32_t lmask, rmask;
1120 1.35 nisimura int fg, bg;
1121 1.10 nisimura
1122 1.35 nisimura scanspan = ri->ri_stride;
1123 1.35 nisimura y = row * ri->ri_font->fontheight;
1124 1.35 nisimura startx = startcol * ri->ri_font->fontwidth;
1125 1.35 nisimura height = ri->ri_font->fontheight;
1126 1.35 nisimura w = ri->ri_font->fontwidth * ncols;
1127 1.10 nisimura
1128 1.35 nisimura p = ri->ri_bits + y * scanspan + startx;
1129 1.10 nisimura align = (long)p & SFBALIGNMASK;
1130 1.10 nisimura p -= align;
1131 1.10 nisimura width = w + align;
1132 1.10 nisimura lmask = SFBSTIPPLEALL1 << align;
1133 1.10 nisimura rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1134 1.35 nisimura sfb = ri->ri_hw;
1135 1.21 nisimura
1136 1.21 nisimura SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1137 1.21 nisimura SFBPLANEMASK(sfb, ~0);
1138 1.35 nisimura rasops_unpack_attr(attr, &fg, &bg, 0);
1139 1.35 nisimura bg |= bg << 8;
1140 1.35 nisimura bg |= bg << 16;
1141 1.35 nisimura SFBFG(sfb, bg); /* fill with bg color */
1142 1.10 nisimura if (width <= SFBSTIPPLEBITS) {
1143 1.20 nisimura lmask = lmask & rmask;
1144 1.10 nisimura while (height > 0) {
1145 1.21 nisimura SFBADDRESS(sfb, (long)p);
1146 1.21 nisimura SFBSTART(sfb, lmask);
1147 1.10 nisimura p += scanspan;
1148 1.10 nisimura height--;
1149 1.10 nisimura }
1150 1.10 nisimura }
1151 1.10 nisimura else {
1152 1.10 nisimura caddr_t q = p;
1153 1.10 nisimura while (height > 0) {
1154 1.10 nisimura *(u_int32_t *)p = lmask;
1155 1.39 nisimura WRITE_MB();
1156 1.10 nisimura width -= 2 * SFBSTIPPLEBITS;
1157 1.10 nisimura while (width > 0) {
1158 1.10 nisimura p += SFBSTIPPLEBYTESDONE;
1159 1.10 nisimura *(u_int32_t *)p = SFBSTIPPLEALL1;
1160 1.39 nisimura WRITE_MB();
1161 1.10 nisimura width -= SFBSTIPPLEBITS;
1162 1.10 nisimura }
1163 1.10 nisimura p += SFBSTIPPLEBYTESDONE;
1164 1.10 nisimura *(u_int32_t *)p = rmask;
1165 1.39 nisimura WRITE_MB();
1166 1.10 nisimura
1167 1.10 nisimura p = (q += scanspan);
1168 1.10 nisimura width = w + align;
1169 1.10 nisimura height--;
1170 1.10 nisimura }
1171 1.10 nisimura }
1172 1.21 nisimura SFBMODE(sfb, MODE_SIMPLE);
1173 1.10 nisimura }
1174 1.10 nisimura
1175 1.10 nisimura /*
1176 1.16 nisimura * Copy lines.
1177 1.10 nisimura */
1178 1.27 nisimura static void
1179 1.10 nisimura sfb_copyrows(id, srcrow, dstrow, nrows)
1180 1.10 nisimura void *id;
1181 1.10 nisimura int srcrow, dstrow, nrows;
1182 1.10 nisimura {
1183 1.28 drochner struct rasops_info *ri = id;
1184 1.10 nisimura caddr_t sfb, p;
1185 1.10 nisimura int scanspan, offset, srcy, height, width, align, w;
1186 1.10 nisimura u_int32_t lmask, rmask;
1187 1.10 nisimura
1188 1.28 drochner scanspan = ri->ri_stride;
1189 1.28 drochner height = ri->ri_font->fontheight * nrows;
1190 1.28 drochner offset = (dstrow - srcrow) * ri->ri_yscale;
1191 1.28 drochner srcy = ri->ri_font->fontheight * srcrow;
1192 1.10 nisimura if (srcrow < dstrow && srcrow + nrows > dstrow) {
1193 1.10 nisimura scanspan = -scanspan;
1194 1.10 nisimura srcy += height;
1195 1.10 nisimura }
1196 1.10 nisimura
1197 1.35 nisimura p = ri->ri_bits + srcy * ri->ri_stride;
1198 1.10 nisimura align = (long)p & SFBALIGNMASK;
1199 1.10 nisimura p -= align;
1200 1.28 drochner w = ri->ri_emuwidth;
1201 1.10 nisimura width = w + align;
1202 1.21 nisimura lmask = SFBCOPYALL1 << align;
1203 1.21 nisimura rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1204 1.28 drochner sfb = ri->ri_hw;
1205 1.21 nisimura
1206 1.21 nisimura SFBMODE(sfb, MODE_COPY);
1207 1.21 nisimura SFBPLANEMASK(sfb, ~0);
1208 1.21 nisimura SFBPIXELSHIFT(sfb, 0);
1209 1.21 nisimura if (width <= SFBCOPYBITS) {
1210 1.10 nisimura /* never happens */;
1211 1.10 nisimura }
1212 1.10 nisimura else {
1213 1.10 nisimura caddr_t q = p;
1214 1.10 nisimura while (height > 0) {
1215 1.10 nisimura *(u_int32_t *)p = lmask;
1216 1.10 nisimura *(u_int32_t *)(p + offset) = lmask;
1217 1.21 nisimura width -= 2 * SFBCOPYBITS;
1218 1.10 nisimura while (width > 0) {
1219 1.21 nisimura p += SFBCOPYBYTESDONE;
1220 1.21 nisimura *(u_int32_t *)p = SFBCOPYALL1;
1221 1.21 nisimura *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1222 1.21 nisimura width -= SFBCOPYBITS;
1223 1.10 nisimura }
1224 1.21 nisimura p += SFBCOPYBYTESDONE;
1225 1.10 nisimura *(u_int32_t *)p = rmask;
1226 1.10 nisimura *(u_int32_t *)(p + offset) = rmask;
1227 1.10 nisimura
1228 1.10 nisimura p = (q += scanspan);
1229 1.10 nisimura width = w + align;
1230 1.10 nisimura height--;
1231 1.10 nisimura }
1232 1.10 nisimura }
1233 1.21 nisimura SFBMODE(sfb, MODE_SIMPLE);
1234 1.10 nisimura }
1235 1.10 nisimura
1236 1.10 nisimura /*
1237 1.20 nisimura * Erase lines.
1238 1.10 nisimura */
1239 1.10 nisimura void
1240 1.21 nisimura sfb_eraserows(id, startrow, nrows, attr)
1241 1.10 nisimura void *id;
1242 1.10 nisimura int startrow, nrows;
1243 1.21 nisimura long attr;
1244 1.10 nisimura {
1245 1.35 nisimura struct rasops_info *ri = id;
1246 1.10 nisimura caddr_t sfb, p;
1247 1.10 nisimura int scanspan, starty, height, width, align, w;
1248 1.10 nisimura u_int32_t lmask, rmask;
1249 1.35 nisimura int fg, bg;
1250 1.10 nisimura
1251 1.35 nisimura scanspan = ri->ri_stride;
1252 1.35 nisimura starty = ri->ri_font->fontheight * startrow;
1253 1.35 nisimura height = ri->ri_font->fontheight * nrows;
1254 1.10 nisimura
1255 1.35 nisimura p = ri->ri_bits + starty * scanspan;
1256 1.10 nisimura align = (long)p & SFBALIGNMASK;
1257 1.10 nisimura p -= align;
1258 1.35 nisimura w = ri->ri_emuwidth;
1259 1.10 nisimura width = w + align;
1260 1.10 nisimura lmask = SFBSTIPPLEALL1 << align;
1261 1.10 nisimura rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1262 1.35 nisimura sfb = ri->ri_hw;
1263 1.21 nisimura
1264 1.21 nisimura SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1265 1.21 nisimura SFBPLANEMASK(sfb, ~0);
1266 1.35 nisimura rasops_unpack_attr(attr, &fg, &bg, 0);
1267 1.35 nisimura bg |= bg << 8;
1268 1.35 nisimura bg |= bg << 16;
1269 1.35 nisimura SFBFG(sfb, bg); /* fill with bg color */
1270 1.10 nisimura if (width <= SFBSTIPPLEBITS) {
1271 1.10 nisimura /* never happens */;
1272 1.10 nisimura }
1273 1.10 nisimura else {
1274 1.10 nisimura caddr_t q = p;
1275 1.10 nisimura while (height > 0) {
1276 1.10 nisimura *(u_int32_t *)p = lmask;
1277 1.39 nisimura WRITE_MB();
1278 1.10 nisimura width -= 2 * SFBSTIPPLEBITS;
1279 1.10 nisimura while (width > 0) {
1280 1.10 nisimura p += SFBSTIPPLEBYTESDONE;
1281 1.10 nisimura *(u_int32_t *)p = SFBSTIPPLEALL1;
1282 1.39 nisimura WRITE_MB();
1283 1.10 nisimura width -= SFBSTIPPLEBITS;
1284 1.10 nisimura }
1285 1.10 nisimura p += SFBSTIPPLEBYTESDONE;
1286 1.10 nisimura *(u_int32_t *)p = rmask;
1287 1.39 nisimura WRITE_MB();
1288 1.10 nisimura
1289 1.10 nisimura p = (q += scanspan);
1290 1.10 nisimura width = w + align;
1291 1.10 nisimura height--;
1292 1.10 nisimura }
1293 1.10 nisimura }
1294 1.21 nisimura SFBMODE(sfb, MODE_SIMPLE);
1295 1.10 nisimura }
1296