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