sfb.c revision 1.43 1 1.43 nisimura /* $NetBSD: sfb.c,v 1.43 2001/01/19 05:43:43 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.43 nisimura __KERNEL_RCSID(0, "$NetBSD: sfb.c,v 1.43 2001/01/19 05:43:43 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.43 nisimura static void sfb_do_cursor __P((struct rasops_info *));
165 1.28 drochner #if 0
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.43 nisimura dc->rinfo.ri_do_cursor = sfb_do_cursor;
336 1.28 drochner
337 1.28 drochner /* XXX shouldn't be global */
338 1.28 drochner sfb_stdscreen.nrows = dc->rinfo.ri_rows;
339 1.28 drochner sfb_stdscreen.ncols = dc->rinfo.ri_cols;
340 1.28 drochner sfb_stdscreen.textops = &dc->rinfo.ri_ops;
341 1.28 drochner sfb_stdscreen.capabilities = dc->rinfo.ri_caps;
342 1.1 nisimura }
343 1.1 nisimura
344 1.27 nisimura static void
345 1.1 nisimura sfbattach(parent, self, aux)
346 1.1 nisimura struct device *parent, *self;
347 1.1 nisimura void *aux;
348 1.1 nisimura {
349 1.1 nisimura struct sfb_softc *sc = (struct sfb_softc *)self;
350 1.1 nisimura struct tc_attach_args *ta = aux;
351 1.1 nisimura struct wsemuldisplaydev_attach_args waa;
352 1.38 nisimura struct hwcmap256 *cm;
353 1.38 nisimura const u_int8_t *p;
354 1.1 nisimura caddr_t sfbasic;
355 1.38 nisimura int console, index;
356 1.1 nisimura
357 1.1 nisimura console = (ta->ta_addr == sfb_consaddr);
358 1.1 nisimura if (console) {
359 1.1 nisimura sc->sc_dc = &sfb_console_dc;
360 1.1 nisimura sc->nscreens = 1;
361 1.1 nisimura }
362 1.1 nisimura else {
363 1.1 nisimura sc->sc_dc = (struct fb_devconfig *)
364 1.1 nisimura malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
365 1.28 drochner memset(sc->sc_dc, 0, sizeof(struct fb_devconfig));
366 1.1 nisimura sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
367 1.1 nisimura }
368 1.1 nisimura printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
369 1.1 nisimura sc->sc_dc->dc_depth);
370 1.1 nisimura
371 1.38 nisimura cm = &sc->sc_cmap;
372 1.38 nisimura p = rasops_cmap;
373 1.38 nisimura for (index = 0; index < CMAP_SIZE; index++, p += 3) {
374 1.38 nisimura cm->r[index] = p[0];
375 1.38 nisimura cm->g[index] = p[1];
376 1.38 nisimura cm->b[index] = p[2];
377 1.38 nisimura }
378 1.15 nisimura
379 1.15 nisimura sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
380 1.15 nisimura sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
381 1.1 nisimura
382 1.27 nisimura tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc);
383 1.1 nisimura
384 1.1 nisimura sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
385 1.1 nisimura *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
386 1.1 nisimura *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
387 1.1 nisimura
388 1.1 nisimura waa.console = console;
389 1.1 nisimura waa.scrdata = &sfb_screenlist;
390 1.1 nisimura waa.accessops = &sfb_accessops;
391 1.1 nisimura waa.accesscookie = sc;
392 1.1 nisimura
393 1.1 nisimura config_found(self, &waa, wsemuldisplaydevprint);
394 1.1 nisimura }
395 1.1 nisimura
396 1.27 nisimura static int
397 1.1 nisimura sfbioctl(v, cmd, data, flag, p)
398 1.1 nisimura void *v;
399 1.1 nisimura u_long cmd;
400 1.1 nisimura caddr_t data;
401 1.1 nisimura int flag;
402 1.1 nisimura struct proc *p;
403 1.1 nisimura {
404 1.1 nisimura struct sfb_softc *sc = v;
405 1.1 nisimura struct fb_devconfig *dc = sc->sc_dc;
406 1.1 nisimura int turnoff;
407 1.1 nisimura
408 1.1 nisimura switch (cmd) {
409 1.1 nisimura case WSDISPLAYIO_GTYPE:
410 1.1 nisimura *(u_int *)data = WSDISPLAY_TYPE_SFB;
411 1.1 nisimura return (0);
412 1.1 nisimura
413 1.1 nisimura case WSDISPLAYIO_GINFO:
414 1.1 nisimura #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
415 1.1 nisimura wsd_fbip->height = sc->sc_dc->dc_ht;
416 1.1 nisimura wsd_fbip->width = sc->sc_dc->dc_wid;
417 1.1 nisimura wsd_fbip->depth = sc->sc_dc->dc_depth;
418 1.1 nisimura wsd_fbip->cmsize = CMAP_SIZE;
419 1.1 nisimura #undef fbt
420 1.1 nisimura return (0);
421 1.1 nisimura
422 1.1 nisimura case WSDISPLAYIO_GETCMAP:
423 1.1 nisimura return get_cmap(sc, (struct wsdisplay_cmap *)data);
424 1.1 nisimura
425 1.1 nisimura case WSDISPLAYIO_PUTCMAP:
426 1.1 nisimura return set_cmap(sc, (struct wsdisplay_cmap *)data);
427 1.1 nisimura
428 1.1 nisimura case WSDISPLAYIO_SVIDEO:
429 1.1 nisimura turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
430 1.1 nisimura if ((dc->dc_blanked == 0) ^ turnoff) {
431 1.1 nisimura dc->dc_blanked = turnoff;
432 1.18 nisimura #if 0 /* XXX later XXX */
433 1.18 nisimura To turn off, assign value 0 in ASIC_VIDEO_VALID register.
434 1.18 nisimura #endif /* XXX XXX XXX */
435 1.1 nisimura }
436 1.1 nisimura return (0);
437 1.1 nisimura
438 1.1 nisimura case WSDISPLAYIO_GVIDEO:
439 1.1 nisimura *(u_int *)data = dc->dc_blanked ?
440 1.1 nisimura WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
441 1.1 nisimura return (0);
442 1.1 nisimura
443 1.1 nisimura case WSDISPLAYIO_GCURPOS:
444 1.1 nisimura *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
445 1.1 nisimura return (0);
446 1.1 nisimura
447 1.1 nisimura case WSDISPLAYIO_SCURPOS:
448 1.1 nisimura set_curpos(sc, (struct wsdisplay_curpos *)data);
449 1.42 nisimura sc->sc_changed = WSDISPLAY_CURSOR_DOPOS;
450 1.1 nisimura return (0);
451 1.1 nisimura
452 1.1 nisimura case WSDISPLAYIO_GCURMAX:
453 1.1 nisimura ((struct wsdisplay_curpos *)data)->x =
454 1.1 nisimura ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
455 1.1 nisimura return (0);
456 1.1 nisimura
457 1.1 nisimura case WSDISPLAYIO_GCURSOR:
458 1.1 nisimura return get_cursor(sc, (struct wsdisplay_cursor *)data);
459 1.1 nisimura
460 1.1 nisimura case WSDISPLAYIO_SCURSOR:
461 1.1 nisimura return set_cursor(sc, (struct wsdisplay_cursor *)data);
462 1.1 nisimura }
463 1.42 nisimura return (ENOTTY);
464 1.1 nisimura }
465 1.1 nisimura
466 1.36 simonb static paddr_t
467 1.1 nisimura sfbmmap(v, offset, prot)
468 1.1 nisimura void *v;
469 1.1 nisimura off_t offset;
470 1.1 nisimura int prot;
471 1.1 nisimura {
472 1.1 nisimura struct sfb_softc *sc = v;
473 1.1 nisimura
474 1.10 nisimura if (offset >= SFB_SIZE || offset < 0)
475 1.1 nisimura return (-1);
476 1.1 nisimura return machine_btop(sc->sc_dc->dc_paddr + offset);
477 1.1 nisimura }
478 1.1 nisimura
479 1.27 nisimura static int
480 1.1 nisimura sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
481 1.1 nisimura void *v;
482 1.1 nisimura const struct wsscreen_descr *type;
483 1.1 nisimura void **cookiep;
484 1.1 nisimura int *curxp, *curyp;
485 1.1 nisimura long *attrp;
486 1.1 nisimura {
487 1.1 nisimura struct sfb_softc *sc = v;
488 1.1 nisimura long defattr;
489 1.1 nisimura
490 1.1 nisimura if (sc->nscreens > 0)
491 1.1 nisimura return (ENOMEM);
492 1.1 nisimura
493 1.28 drochner *cookiep = &sc->sc_dc->rinfo; /* one and only for now */
494 1.1 nisimura *curxp = 0;
495 1.1 nisimura *curyp = 0;
496 1.28 drochner (*sc->sc_dc->rinfo.ri_ops.alloc_attr)(&sc->sc_dc->rinfo, 0, 0, 0, &defattr);
497 1.1 nisimura *attrp = defattr;
498 1.1 nisimura sc->nscreens++;
499 1.1 nisimura return (0);
500 1.1 nisimura }
501 1.1 nisimura
502 1.27 nisimura static void
503 1.1 nisimura sfb_free_screen(v, cookie)
504 1.1 nisimura void *v;
505 1.1 nisimura void *cookie;
506 1.1 nisimura {
507 1.1 nisimura struct sfb_softc *sc = v;
508 1.1 nisimura
509 1.1 nisimura if (sc->sc_dc == &sfb_console_dc)
510 1.1 nisimura panic("sfb_free_screen: console");
511 1.1 nisimura
512 1.1 nisimura sc->nscreens--;
513 1.1 nisimura }
514 1.1 nisimura
515 1.30 drochner static int
516 1.30 drochner sfb_show_screen(v, cookie, waitok, cb, cbarg)
517 1.1 nisimura void *v;
518 1.1 nisimura void *cookie;
519 1.30 drochner int waitok;
520 1.30 drochner void (*cb) __P((void *, int, int));
521 1.30 drochner void *cbarg;
522 1.1 nisimura {
523 1.30 drochner
524 1.30 drochner return (0);
525 1.1 nisimura }
526 1.1 nisimura
527 1.27 nisimura /* EXPORT */ int
528 1.1 nisimura sfb_cnattach(addr)
529 1.42 nisimura tc_addr_t addr;
530 1.1 nisimura {
531 1.42 nisimura struct fb_devconfig *dcp = &sfb_console_dc;
532 1.42 nisimura long defattr;
533 1.1 nisimura
534 1.42 nisimura sfb_getdevconfig(addr, dcp);
535 1.1 nisimura
536 1.42 nisimura (*dcp->rinfo.ri_ops.alloc_attr)(&dcp->rinfo, 0, 0, 0, &defattr);
537 1.1 nisimura
538 1.42 nisimura wsdisplay_cnattach(&sfb_stdscreen, &dcp->rinfo, 0, 0, defattr);
539 1.42 nisimura sfb_consaddr = addr;
540 1.42 nisimura return(0);
541 1.1 nisimura }
542 1.1 nisimura
543 1.27 nisimura static int
544 1.1 nisimura sfbintr(arg)
545 1.1 nisimura void *arg;
546 1.1 nisimura {
547 1.1 nisimura struct sfb_softc *sc = arg;
548 1.42 nisimura caddr_t sfbasic = (caddr_t)sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET;
549 1.16 nisimura caddr_t vdac;
550 1.1 nisimura int v;
551 1.1 nisimura
552 1.1 nisimura *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
553 1.1 nisimura /* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
554 1.1 nisimura
555 1.1 nisimura if (sc->sc_changed == 0)
556 1.42 nisimura goto finish;
557 1.1 nisimura
558 1.42 nisimura vdac = (caddr_t)sc->sc_dc->dc_vaddr + SFB_RAMDAC_OFFSET;
559 1.1 nisimura v = sc->sc_changed;
560 1.42 nisimura if (v & WSDISPLAY_CURSOR_DOCUR) {
561 1.31 ad SELECT(vdac, BT459_IREG_CCR);
562 1.16 nisimura REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
563 1.1 nisimura }
564 1.42 nisimura if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
565 1.42 nisimura int x, y;
566 1.42 nisimura
567 1.42 nisimura x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
568 1.42 nisimura y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
569 1.42 nisimura x += sc->sc_cursor.cc_magic.x;
570 1.42 nisimura y += sc->sc_cursor.cc_magic.y;
571 1.42 nisimura
572 1.42 nisimura SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
573 1.42 nisimura REG(vdac, bt_reg) = x; tc_wmb();
574 1.42 nisimura REG(vdac, bt_reg) = x >> 8; tc_wmb();
575 1.42 nisimura REG(vdac, bt_reg) = y; tc_wmb();
576 1.42 nisimura REG(vdac, bt_reg) = y >> 8; tc_wmb();
577 1.42 nisimura }
578 1.42 nisimura if (v & WSDISPLAY_CURSOR_DOCMAP) {
579 1.1 nisimura u_int8_t *cp = sc->sc_cursor.cc_color;
580 1.1 nisimura
581 1.31 ad SELECT(vdac, BT459_IREG_CCOLOR_2);
582 1.16 nisimura REG(vdac, bt_reg) = cp[1]; tc_wmb();
583 1.16 nisimura REG(vdac, bt_reg) = cp[3]; tc_wmb();
584 1.16 nisimura REG(vdac, bt_reg) = cp[5]; tc_wmb();
585 1.16 nisimura
586 1.16 nisimura REG(vdac, bt_reg) = cp[0]; tc_wmb();
587 1.16 nisimura REG(vdac, bt_reg) = cp[2]; tc_wmb();
588 1.16 nisimura REG(vdac, bt_reg) = cp[4]; tc_wmb();
589 1.1 nisimura }
590 1.42 nisimura if (v & WSDISPLAY_CURSOR_DOSHAPE) {
591 1.3 nisimura u_int8_t *ip, *mp, img, msk;
592 1.3 nisimura u_int8_t u;
593 1.3 nisimura int bcnt;
594 1.3 nisimura
595 1.3 nisimura ip = (u_int8_t *)sc->sc_cursor.cc_image;
596 1.3 nisimura mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
597 1.3 nisimura
598 1.3 nisimura bcnt = 0;
599 1.31 ad SELECT(vdac, BT459_IREG_CRAM_BASE+0);
600 1.3 nisimura /* 64 pixel scan line is consisted with 16 byte cursor ram */
601 1.3 nisimura while (bcnt < sc->sc_cursor.cc_size.y * 16) {
602 1.3 nisimura /* pad right half 32 pixel when smaller than 33 */
603 1.3 nisimura if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
604 1.16 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
605 1.16 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
606 1.3 nisimura }
607 1.3 nisimura else {
608 1.3 nisimura img = *ip++;
609 1.3 nisimura msk = *mp++;
610 1.3 nisimura img &= msk; /* cookie off image */
611 1.3 nisimura u = (msk & 0x0f) << 4 | (img & 0x0f);
612 1.16 nisimura REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
613 1.3 nisimura u = (msk & 0xf0) | (img & 0xf0) >> 4;
614 1.16 nisimura REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
615 1.3 nisimura }
616 1.3 nisimura bcnt += 2;
617 1.3 nisimura }
618 1.3 nisimura /* pad unoccupied scan lines */
619 1.3 nisimura while (bcnt < CURSOR_MAX_SIZE * 16) {
620 1.16 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
621 1.16 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
622 1.3 nisimura bcnt += 2;
623 1.1 nisimura }
624 1.1 nisimura }
625 1.42 nisimura if (v & WSDISPLAY_CMAP_DOLUT) {
626 1.15 nisimura struct hwcmap256 *cm = &sc->sc_cmap;
627 1.1 nisimura int index;
628 1.1 nisimura
629 1.16 nisimura SELECT(vdac, 0);
630 1.1 nisimura for (index = 0; index < CMAP_SIZE; index++) {
631 1.16 nisimura REG(vdac, bt_cmap) = cm->r[index]; tc_wmb();
632 1.16 nisimura REG(vdac, bt_cmap) = cm->g[index]; tc_wmb();
633 1.16 nisimura REG(vdac, bt_cmap) = cm->b[index]; tc_wmb();
634 1.1 nisimura }
635 1.1 nisimura }
636 1.42 nisimura sc->sc_changed = 0;
637 1.42 nisimura finish:
638 1.1 nisimura return (1);
639 1.1 nisimura }
640 1.1 nisimura
641 1.27 nisimura static void
642 1.1 nisimura sfbinit(dc)
643 1.1 nisimura struct fb_devconfig *dc;
644 1.1 nisimura {
645 1.42 nisimura caddr_t vdac = (caddr_t)dc->dc_vaddr + SFB_RAMDAC_OFFSET;
646 1.38 nisimura const u_int8_t *p;
647 1.1 nisimura int i;
648 1.1 nisimura
649 1.31 ad SELECT(vdac, BT459_IREG_COMMAND_0);
650 1.16 nisimura REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb();
651 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb();
652 1.16 nisimura REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb();
653 1.16 nisimura REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb();
654 1.16 nisimura REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb();
655 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb();
656 1.16 nisimura REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb();
657 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb();
658 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb();
659 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb();
660 1.16 nisimura REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb();
661 1.16 nisimura
662 1.31 ad SELECT(vdac, BT459_IREG_CCR);
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.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
675 1.16 nisimura REG(vdac, bt_reg) = 0x0; tc_wmb();
676 1.3 nisimura
677 1.3 nisimura /* build sane colormap */
678 1.16 nisimura SELECT(vdac, 0);
679 1.38 nisimura p = rasops_cmap;
680 1.38 nisimura for (i = 0; i < CMAP_SIZE; i++, p += 3) {
681 1.38 nisimura REG(vdac, bt_cmap) = p[0]; tc_wmb();
682 1.38 nisimura REG(vdac, bt_cmap) = p[1]; tc_wmb();
683 1.38 nisimura REG(vdac, bt_cmap) = p[2]; tc_wmb();
684 1.3 nisimura }
685 1.3 nisimura
686 1.3 nisimura /* clear out cursor image */
687 1.31 ad SELECT(vdac, BT459_IREG_CRAM_BASE);
688 1.3 nisimura for (i = 0; i < 1024; i++)
689 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
690 1.3 nisimura
691 1.3 nisimura /*
692 1.3 nisimura * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
693 1.3 nisimura * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
694 1.3 nisimura * image color. CCOLOR_1 will be never used.
695 1.3 nisimura */
696 1.31 ad SELECT(vdac, BT459_IREG_CCOLOR_1);
697 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
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
701 1.21 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
702 1.21 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
703 1.21 nisimura REG(vdac, bt_reg) = 0; tc_wmb();
704 1.16 nisimura
705 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
706 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
707 1.16 nisimura REG(vdac, bt_reg) = 0xff; tc_wmb();
708 1.1 nisimura }
709 1.1 nisimura
710 1.1 nisimura static int
711 1.1 nisimura get_cmap(sc, p)
712 1.1 nisimura struct sfb_softc *sc;
713 1.1 nisimura struct wsdisplay_cmap *p;
714 1.1 nisimura {
715 1.1 nisimura u_int index = p->index, count = p->count;
716 1.1 nisimura
717 1.1 nisimura if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
718 1.1 nisimura return (EINVAL);
719 1.1 nisimura
720 1.13 mrg if (!uvm_useracc(p->red, count, B_WRITE) ||
721 1.13 mrg !uvm_useracc(p->green, count, B_WRITE) ||
722 1.13 mrg !uvm_useracc(p->blue, count, B_WRITE))
723 1.1 nisimura return (EFAULT);
724 1.1 nisimura
725 1.1 nisimura copyout(&sc->sc_cmap.r[index], p->red, count);
726 1.1 nisimura copyout(&sc->sc_cmap.g[index], p->green, count);
727 1.1 nisimura copyout(&sc->sc_cmap.b[index], p->blue, count);
728 1.1 nisimura
729 1.1 nisimura return (0);
730 1.1 nisimura }
731 1.1 nisimura
732 1.1 nisimura static int
733 1.1 nisimura set_cmap(sc, p)
734 1.1 nisimura struct sfb_softc *sc;
735 1.1 nisimura struct wsdisplay_cmap *p;
736 1.1 nisimura {
737 1.1 nisimura u_int index = p->index, count = p->count;
738 1.1 nisimura
739 1.1 nisimura if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
740 1.1 nisimura return (EINVAL);
741 1.1 nisimura
742 1.13 mrg if (!uvm_useracc(p->red, count, B_READ) ||
743 1.13 mrg !uvm_useracc(p->green, count, B_READ) ||
744 1.13 mrg !uvm_useracc(p->blue, count, B_READ))
745 1.1 nisimura return (EFAULT);
746 1.1 nisimura
747 1.1 nisimura copyin(p->red, &sc->sc_cmap.r[index], count);
748 1.1 nisimura copyin(p->green, &sc->sc_cmap.g[index], count);
749 1.1 nisimura copyin(p->blue, &sc->sc_cmap.b[index], count);
750 1.42 nisimura sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
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
782 1.42 nisimura if (v & WSDISPLAY_CURSOR_DOCUR)
783 1.1 nisimura sc->sc_curenb = p->enable;
784 1.42 nisimura if (v & WSDISPLAY_CURSOR_DOPOS)
785 1.42 nisimura set_curpos(sc, &p->pos);
786 1.42 nisimura if (v & WSDISPLAY_CURSOR_DOHOT)
787 1.42 nisimura cc->cc_hot = p->hot;
788 1.1 nisimura if (v & WSDISPLAY_CURSOR_DOCMAP) {
789 1.1 nisimura copyin(p->cmap.red, &cc->cc_color[index], count);
790 1.1 nisimura copyin(p->cmap.green, &cc->cc_color[index + 2], count);
791 1.1 nisimura copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
792 1.1 nisimura }
793 1.1 nisimura if (v & WSDISPLAY_CURSOR_DOSHAPE) {
794 1.1 nisimura cc->cc_size = p->size;
795 1.1 nisimura memset(cc->cc_image, 0, sizeof cc->cc_image);
796 1.5 nisimura copyin(p->image, cc->cc_image, icount);
797 1.5 nisimura copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
798 1.1 nisimura }
799 1.42 nisimura sc->sc_changed = v;
800 1.1 nisimura
801 1.1 nisimura return (0);
802 1.1 nisimura #undef cc
803 1.1 nisimura }
804 1.1 nisimura
805 1.1 nisimura static int
806 1.1 nisimura get_cursor(sc, p)
807 1.1 nisimura struct sfb_softc *sc;
808 1.1 nisimura struct wsdisplay_cursor *p;
809 1.1 nisimura {
810 1.35 nisimura
811 1.1 nisimura return (ENOTTY); /* XXX */
812 1.1 nisimura }
813 1.1 nisimura
814 1.1 nisimura static void
815 1.1 nisimura set_curpos(sc, curpos)
816 1.1 nisimura struct sfb_softc *sc;
817 1.1 nisimura struct wsdisplay_curpos *curpos;
818 1.1 nisimura {
819 1.1 nisimura struct fb_devconfig *dc = sc->sc_dc;
820 1.1 nisimura int x = curpos->x, y = curpos->y;
821 1.1 nisimura
822 1.1 nisimura if (y < 0)
823 1.1 nisimura y = 0;
824 1.3 nisimura else if (y > dc->dc_ht)
825 1.3 nisimura y = dc->dc_ht;
826 1.1 nisimura if (x < 0)
827 1.1 nisimura x = 0;
828 1.3 nisimura else if (x > dc->dc_wid)
829 1.3 nisimura x = dc->dc_wid;
830 1.1 nisimura sc->sc_cursor.cc_pos.x = x;
831 1.1 nisimura sc->sc_cursor.cc_pos.y = y;
832 1.1 nisimura }
833 1.1 nisimura
834 1.10 nisimura #define MODE_SIMPLE 0
835 1.10 nisimura #define MODE_OPAQUESTIPPLE 1
836 1.10 nisimura #define MODE_OPAQUELINE 2
837 1.10 nisimura #define MODE_TRANSPARENTSTIPPLE 5
838 1.10 nisimura #define MODE_TRANSPARENTLINE 6
839 1.10 nisimura #define MODE_COPY 7
840 1.10 nisimura
841 1.21 nisimura /* parameters for 8bpp configuration */
842 1.10 nisimura #define SFBALIGNMASK 0x7
843 1.10 nisimura #define SFBSTIPPLEALL1 0xffffffff
844 1.10 nisimura #define SFBSTIPPLEBITS 32
845 1.10 nisimura #define SFBSTIPPLEBITMASK 0x1f
846 1.10 nisimura #define SFBSTIPPLEBYTESDONE 32
847 1.21 nisimura #define SFBCOPYALL1 0xffffffff
848 1.21 nisimura #define SFBCOPYBITS 32
849 1.21 nisimura #define SFBCOPYBITMASK 0x1f
850 1.21 nisimura #define SFBCOPYBYTESDONE 32
851 1.21 nisimura
852 1.35 nisimura #if defined(pmax)
853 1.21 nisimura #define WRITE_MB()
854 1.21 nisimura #define BUMP(p) (p)
855 1.21 nisimura #endif
856 1.21 nisimura
857 1.35 nisimura #if defined(alpha)
858 1.21 nisimura #define WRITE_MB() tc_wmb()
859 1.41 nisimura /* SFB registers replicated in 128B stride; cycle after eight iterations */
860 1.40 nisimura #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x80) & ~0x400))
861 1.21 nisimura #endif
862 1.21 nisimura
863 1.21 nisimura #define SFBMODE(p, v) \
864 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
865 1.21 nisimura #define SFBROP(p, v) \
866 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
867 1.21 nisimura #define SFBPLANEMASK(p, v) \
868 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
869 1.21 nisimura #define SFBPIXELMASK(p, v) \
870 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
871 1.21 nisimura #define SFBADDRESS(p, v) \
872 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
873 1.21 nisimura #define SFBSTART(p, v) \
874 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
875 1.21 nisimura #define SFBPIXELSHIFT(p, v) \
876 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
877 1.21 nisimura #define SFBFG(p, v) \
878 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
879 1.21 nisimura #define SFBBG(p, v) \
880 1.21 nisimura (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
881 1.21 nisimura
882 1.10 nisimura /*
883 1.43 nisimura * Paint the cursor.
884 1.10 nisimura */
885 1.27 nisimura static void
886 1.43 nisimura sfb_do_cursor(ri)
887 1.43 nisimura struct rasops_info *ri;
888 1.10 nisimura {
889 1.43 nisimura caddr_t sfb, p;
890 1.43 nisimura int scanspan, height, width, align, x, y;
891 1.43 nisimura u_int32_t lmask, rmask;
892 1.43 nisimura
893 1.43 nisimura x = ri->ri_ccol * ri->ri_font->fontwidth;
894 1.43 nisimura y = ri->ri_crow * ri->ri_font->fontheight;
895 1.43 nisimura scanspan = ri->ri_stride;
896 1.43 nisimura height = ri->ri_font->fontheight;
897 1.43 nisimura
898 1.43 nisimura p = ri->ri_bits + y * scanspan + x;
899 1.43 nisimura align = (long)p & SFBALIGNMASK;
900 1.43 nisimura p -= align;
901 1.43 nisimura width = ri->ri_font->fontwidth + align;
902 1.43 nisimura lmask = SFBSTIPPLEALL1 << align;
903 1.43 nisimura rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
904 1.43 nisimura sfb = ri->ri_hw;
905 1.43 nisimura
906 1.43 nisimura SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
907 1.43 nisimura SFBPLANEMASK(sfb, ~0);
908 1.43 nisimura SFBROP(sfb, 6); /* ROP_XOR */
909 1.43 nisimura SFBFG(sfb, ~0);
910 1.43 nisimura
911 1.43 nisimura lmask = lmask & rmask;
912 1.43 nisimura while (height > 0) {
913 1.43 nisimura SFBADDRESS(sfb, (long)p);
914 1.43 nisimura SFBSTART(sfb, lmask);
915 1.43 nisimura p += scanspan;
916 1.43 nisimura height--;
917 1.43 nisimura }
918 1.43 nisimura SFBMODE(sfb, MODE_SIMPLE);
919 1.43 nisimura SFBROP(sfb, 3); /* ROP_COPY */
920 1.10 nisimura }
921 1.10 nisimura
922 1.10 nisimura /*
923 1.43 nisimura * Paint a character.
924 1.10 nisimura */
925 1.27 nisimura static void
926 1.10 nisimura sfb_putchar(id, row, col, uc, attr)
927 1.10 nisimura void *id;
928 1.10 nisimura int row, col;
929 1.10 nisimura u_int uc;
930 1.10 nisimura long attr;
931 1.10 nisimura {
932 1.28 drochner struct rasops_info *ri = id;
933 1.21 nisimura caddr_t sfb, p;
934 1.21 nisimura int scanspan, height, width, align, x, y;
935 1.21 nisimura u_int32_t lmask, rmask, glyph;
936 1.28 drochner u_int8_t *g;
937 1.10 nisimura
938 1.28 drochner x = col * ri->ri_font->fontwidth;
939 1.28 drochner y = row * ri->ri_font->fontheight;
940 1.28 drochner scanspan = ri->ri_stride;
941 1.28 drochner height = ri->ri_font->fontheight;
942 1.28 drochner uc -= ri->ri_font->firstchar;
943 1.28 drochner g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
944 1.21 nisimura
945 1.28 drochner p = ri->ri_bits + y * scanspan + x;
946 1.21 nisimura align = (long)p & SFBALIGNMASK;
947 1.21 nisimura p -= align;
948 1.28 drochner width = ri->ri_font->fontwidth + align;
949 1.21 nisimura lmask = SFBSTIPPLEALL1 << align;
950 1.21 nisimura rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
951 1.28 drochner sfb = ri->ri_hw;
952 1.10 nisimura
953 1.21 nisimura SFBMODE(sfb, MODE_OPAQUESTIPPLE);
954 1.21 nisimura SFBPLANEMASK(sfb, ~0);
955 1.40 nisimura SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
956 1.40 nisimura SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
957 1.40 nisimura
958 1.40 nisimura /* XXX 2B stride fonts only XXX */
959 1.40 nisimura lmask = lmask & rmask;
960 1.40 nisimura while (height > 0) {
961 1.40 nisimura glyph = *(u_int16_t *)g; /* XXX */
962 1.40 nisimura SFBPIXELMASK(sfb, lmask);
963 1.40 nisimura SFBADDRESS(sfb, (long)p);
964 1.40 nisimura SFBSTART(sfb, glyph << align);
965 1.40 nisimura p += scanspan;
966 1.40 nisimura g += 2; /* XXX */
967 1.40 nisimura height--;
968 1.21 nisimura }
969 1.43 nisimura if (attr & 1 /* UNDERLINE */) {
970 1.43 nisimura p -= scanspan * 2;
971 1.43 nisimura SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
972 1.43 nisimura SFBADDRESS(sfb, (long)p);
973 1.43 nisimura SFBSTART(sfb, lmask);
974 1.43 nisimura }
975 1.43 nisimura
976 1.21 nisimura SFBMODE(sfb, MODE_SIMPLE);
977 1.23 nisimura SFBPIXELMASK(sfb, ~0); /* entire pixel */
978 1.10 nisimura }
979 1.10 nisimura
980 1.28 drochner #if 0
981 1.10 nisimura /*
982 1.16 nisimura * Copy characters in a line.
983 1.10 nisimura */
984 1.27 nisimura static void
985 1.10 nisimura sfb_copycols(id, row, srccol, dstcol, ncols)
986 1.10 nisimura void *id;
987 1.10 nisimura int row, srccol, dstcol, ncols;
988 1.10 nisimura {
989 1.35 nisimura struct rasops_info *ri = id;
990 1.16 nisimura caddr_t sp, dp, basex, sfb;
991 1.25 nisimura int scanspan, height, width, aligns, alignd, shift, w, y;
992 1.39 nisimura u_int32_t lmaskd, rmaskd;
993 1.10 nisimura
994 1.35 nisimura scanspan = ri->ri_stride;
995 1.35 nisimura y = row * ri->ri_font->fontheight;
996 1.39 nisimura basex = ri->ri_bits + y * scanspan;
997 1.35 nisimura height = ri->ri_font->fontheight;
998 1.35 nisimura w = ri->ri_font->fontwidth * ncols;
999 1.16 nisimura
1000 1.35 nisimura sp = basex + ri->ri_font->fontwidth * srccol;
1001 1.25 nisimura aligns = (long)sp & SFBALIGNMASK;
1002 1.35 nisimura dp = basex + ri->ri_font->fontwidth * dstcol;
1003 1.25 nisimura alignd = (long)dp & SFBALIGNMASK;
1004 1.35 nisimura sfb = ri->ri_hw;
1005 1.16 nisimura
1006 1.21 nisimura SFBMODE(sfb, MODE_COPY);
1007 1.21 nisimura SFBPLANEMASK(sfb, ~0);
1008 1.39 nisimura /* small enough to fit in a single 32bit */
1009 1.39 nisimura if ((aligns + w) <= SFBCOPYBITS && (alignd + w) <= SFBCOPYBITS) {
1010 1.39 nisimura SFBPIXELSHIFT(sfb, alignd - aligns);
1011 1.39 nisimura lmaskd = SFBCOPYALL1 << alignd;
1012 1.39 nisimura rmaskd = SFBCOPYALL1 >> (-(alignd + w) & SFBCOPYBITMASK);
1013 1.39 nisimura lmaskd = lmaskd & rmaskd;
1014 1.39 nisimura sp -= aligns;
1015 1.39 nisimura dp -= alignd;
1016 1.39 nisimura while (height > 0) {
1017 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1018 1.39 nisimura *(u_int32_t *)dp = lmaskd; WRITE_MB();
1019 1.39 nisimura sp += scanspan;
1020 1.39 nisimura dp += scanspan;
1021 1.39 nisimura height--;
1022 1.39 nisimura }
1023 1.39 nisimura }
1024 1.26 nisimura /* copy forward (left-to-right) */
1025 1.39 nisimura else if (dstcol < srccol || srccol + ncols < dstcol) {
1026 1.26 nisimura caddr_t sq, dq;
1027 1.26 nisimura
1028 1.26 nisimura shift = alignd - aligns;
1029 1.26 nisimura if (shift < 0) {
1030 1.26 nisimura shift = 8 + shift; /* enforce right rotate */
1031 1.34 nisimura alignd += 8; /* bearing on left edge */
1032 1.16 nisimura }
1033 1.39 nisimura width = alignd + w;
1034 1.39 nisimura lmaskd = SFBCOPYALL1 << alignd;
1035 1.39 nisimura rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1036 1.34 nisimura sp -= aligns;
1037 1.34 nisimura dp -= alignd;
1038 1.16 nisimura
1039 1.26 nisimura SFBPIXELSHIFT(sfb, shift);
1040 1.16 nisimura w = width;
1041 1.26 nisimura sq = sp;
1042 1.26 nisimura dq = dp;
1043 1.16 nisimura while (height > 0) {
1044 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1045 1.39 nisimura *(u_int32_t *)dp = lmaskd; WRITE_MB();
1046 1.21 nisimura width -= 2 * SFBCOPYBITS;
1047 1.16 nisimura while (width > 0) {
1048 1.21 nisimura sp += SFBCOPYBYTESDONE;
1049 1.21 nisimura dp += SFBCOPYBYTESDONE;
1050 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1051 1.39 nisimura *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB();
1052 1.21 nisimura width -= SFBCOPYBITS;
1053 1.16 nisimura }
1054 1.21 nisimura sp += SFBCOPYBYTESDONE;
1055 1.21 nisimura dp += SFBCOPYBYTESDONE;
1056 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1057 1.39 nisimura *(u_int32_t *)dp = rmaskd; WRITE_MB();
1058 1.16 nisimura sp = (sq += scanspan);
1059 1.16 nisimura dp = (dq += scanspan);
1060 1.16 nisimura width = w;
1061 1.16 nisimura height--;
1062 1.16 nisimura }
1063 1.16 nisimura }
1064 1.16 nisimura /* copy backward (right-to-left) */
1065 1.16 nisimura else {
1066 1.26 nisimura caddr_t sq, dq;
1067 1.26 nisimura
1068 1.26 nisimura shift = alignd - aligns;
1069 1.26 nisimura if (shift > 0) {
1070 1.34 nisimura shift = shift - 8; /* force left rotate */
1071 1.39 nisimura alignd += 24;
1072 1.26 nisimura }
1073 1.39 nisimura width = alignd + w;
1074 1.39 nisimura lmaskd = SFBCOPYALL1 << alignd;
1075 1.39 nisimura rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1076 1.34 nisimura sp -= aligns;
1077 1.34 nisimura dp -= alignd;
1078 1.16 nisimura
1079 1.26 nisimura SFBPIXELSHIFT(sfb, shift);
1080 1.16 nisimura w = width;
1081 1.39 nisimura sq = sp += (((aligns + w) - 1) & ~31);
1082 1.39 nisimura dq = dp += (((alignd + w) - 1) & ~31);
1083 1.16 nisimura while (height > 0) {
1084 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1085 1.39 nisimura *(u_int32_t *)dp = rmaskd; WRITE_MB();
1086 1.21 nisimura width -= 2 * SFBCOPYBITS;
1087 1.16 nisimura while (width > 0) {
1088 1.21 nisimura sp -= SFBCOPYBYTESDONE;
1089 1.21 nisimura dp -= SFBCOPYBYTESDONE;
1090 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1091 1.39 nisimura *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB();
1092 1.21 nisimura width -= SFBCOPYBITS;
1093 1.16 nisimura }
1094 1.21 nisimura sp -= SFBCOPYBYTESDONE;
1095 1.21 nisimura dp -= SFBCOPYBYTESDONE;
1096 1.39 nisimura *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1097 1.39 nisimura *(u_int32_t *)dp = lmaskd; WRITE_MB();
1098 1.16 nisimura
1099 1.16 nisimura sp = (sq += scanspan);
1100 1.16 nisimura dp = (dq += scanspan);
1101 1.16 nisimura width = w;
1102 1.16 nisimura height--;
1103 1.16 nisimura }
1104 1.16 nisimura }
1105 1.21 nisimura SFBMODE(sfb, MODE_SIMPLE);
1106 1.26 nisimura SFBPIXELSHIFT(sfb, 0);
1107 1.10 nisimura }
1108 1.28 drochner #endif
1109 1.10 nisimura
1110 1.10 nisimura /*
1111 1.16 nisimura * Clear characters in a line.
1112 1.10 nisimura */
1113 1.27 nisimura static void
1114 1.21 nisimura sfb_erasecols(id, row, startcol, ncols, attr)
1115 1.10 nisimura void *id;
1116 1.10 nisimura int row, startcol, ncols;
1117 1.21 nisimura long attr;
1118 1.10 nisimura {
1119 1.35 nisimura struct rasops_info *ri = id;
1120 1.10 nisimura caddr_t sfb, p;
1121 1.10 nisimura int scanspan, startx, height, width, align, w, y;
1122 1.10 nisimura u_int32_t lmask, rmask;
1123 1.10 nisimura
1124 1.35 nisimura scanspan = ri->ri_stride;
1125 1.35 nisimura y = row * ri->ri_font->fontheight;
1126 1.35 nisimura startx = startcol * ri->ri_font->fontwidth;
1127 1.35 nisimura height = ri->ri_font->fontheight;
1128 1.35 nisimura w = ri->ri_font->fontwidth * ncols;
1129 1.10 nisimura
1130 1.35 nisimura p = ri->ri_bits + y * scanspan + startx;
1131 1.10 nisimura align = (long)p & SFBALIGNMASK;
1132 1.10 nisimura p -= align;
1133 1.10 nisimura width = w + align;
1134 1.10 nisimura lmask = SFBSTIPPLEALL1 << align;
1135 1.10 nisimura rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1136 1.35 nisimura sfb = ri->ri_hw;
1137 1.21 nisimura
1138 1.21 nisimura SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1139 1.21 nisimura SFBPLANEMASK(sfb, ~0);
1140 1.42 nisimura SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1141 1.10 nisimura if (width <= SFBSTIPPLEBITS) {
1142 1.20 nisimura lmask = lmask & rmask;
1143 1.10 nisimura while (height > 0) {
1144 1.21 nisimura SFBADDRESS(sfb, (long)p);
1145 1.21 nisimura SFBSTART(sfb, lmask);
1146 1.10 nisimura p += scanspan;
1147 1.10 nisimura height--;
1148 1.10 nisimura }
1149 1.10 nisimura }
1150 1.10 nisimura else {
1151 1.10 nisimura caddr_t q = p;
1152 1.10 nisimura while (height > 0) {
1153 1.10 nisimura *(u_int32_t *)p = lmask;
1154 1.39 nisimura WRITE_MB();
1155 1.10 nisimura width -= 2 * SFBSTIPPLEBITS;
1156 1.10 nisimura while (width > 0) {
1157 1.10 nisimura p += SFBSTIPPLEBYTESDONE;
1158 1.10 nisimura *(u_int32_t *)p = SFBSTIPPLEALL1;
1159 1.39 nisimura WRITE_MB();
1160 1.10 nisimura width -= SFBSTIPPLEBITS;
1161 1.10 nisimura }
1162 1.10 nisimura p += SFBSTIPPLEBYTESDONE;
1163 1.10 nisimura *(u_int32_t *)p = rmask;
1164 1.39 nisimura WRITE_MB();
1165 1.10 nisimura
1166 1.10 nisimura p = (q += scanspan);
1167 1.10 nisimura width = w + align;
1168 1.10 nisimura height--;
1169 1.10 nisimura }
1170 1.10 nisimura }
1171 1.21 nisimura SFBMODE(sfb, MODE_SIMPLE);
1172 1.10 nisimura }
1173 1.10 nisimura
1174 1.10 nisimura /*
1175 1.16 nisimura * Copy lines.
1176 1.10 nisimura */
1177 1.27 nisimura static void
1178 1.10 nisimura sfb_copyrows(id, srcrow, dstrow, nrows)
1179 1.10 nisimura void *id;
1180 1.10 nisimura int srcrow, dstrow, nrows;
1181 1.10 nisimura {
1182 1.28 drochner struct rasops_info *ri = id;
1183 1.10 nisimura caddr_t sfb, p;
1184 1.10 nisimura int scanspan, offset, srcy, height, width, align, w;
1185 1.10 nisimura u_int32_t lmask, rmask;
1186 1.10 nisimura
1187 1.28 drochner scanspan = ri->ri_stride;
1188 1.28 drochner height = ri->ri_font->fontheight * nrows;
1189 1.28 drochner offset = (dstrow - srcrow) * ri->ri_yscale;
1190 1.28 drochner srcy = ri->ri_font->fontheight * srcrow;
1191 1.10 nisimura if (srcrow < dstrow && srcrow + nrows > dstrow) {
1192 1.10 nisimura scanspan = -scanspan;
1193 1.10 nisimura srcy += height;
1194 1.10 nisimura }
1195 1.10 nisimura
1196 1.35 nisimura p = ri->ri_bits + srcy * ri->ri_stride;
1197 1.10 nisimura align = (long)p & SFBALIGNMASK;
1198 1.10 nisimura p -= align;
1199 1.28 drochner w = ri->ri_emuwidth;
1200 1.10 nisimura width = w + align;
1201 1.21 nisimura lmask = SFBCOPYALL1 << align;
1202 1.21 nisimura rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1203 1.28 drochner sfb = ri->ri_hw;
1204 1.21 nisimura
1205 1.21 nisimura SFBMODE(sfb, MODE_COPY);
1206 1.21 nisimura SFBPLANEMASK(sfb, ~0);
1207 1.21 nisimura SFBPIXELSHIFT(sfb, 0);
1208 1.21 nisimura if (width <= SFBCOPYBITS) {
1209 1.10 nisimura /* never happens */;
1210 1.10 nisimura }
1211 1.10 nisimura else {
1212 1.10 nisimura caddr_t q = p;
1213 1.10 nisimura while (height > 0) {
1214 1.10 nisimura *(u_int32_t *)p = lmask;
1215 1.10 nisimura *(u_int32_t *)(p + offset) = lmask;
1216 1.21 nisimura width -= 2 * SFBCOPYBITS;
1217 1.10 nisimura while (width > 0) {
1218 1.21 nisimura p += SFBCOPYBYTESDONE;
1219 1.21 nisimura *(u_int32_t *)p = SFBCOPYALL1;
1220 1.21 nisimura *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1221 1.21 nisimura width -= SFBCOPYBITS;
1222 1.10 nisimura }
1223 1.21 nisimura p += SFBCOPYBYTESDONE;
1224 1.10 nisimura *(u_int32_t *)p = rmask;
1225 1.10 nisimura *(u_int32_t *)(p + offset) = rmask;
1226 1.10 nisimura
1227 1.10 nisimura p = (q += scanspan);
1228 1.10 nisimura width = w + align;
1229 1.10 nisimura height--;
1230 1.10 nisimura }
1231 1.10 nisimura }
1232 1.21 nisimura SFBMODE(sfb, MODE_SIMPLE);
1233 1.10 nisimura }
1234 1.10 nisimura
1235 1.10 nisimura /*
1236 1.20 nisimura * Erase lines.
1237 1.10 nisimura */
1238 1.10 nisimura void
1239 1.21 nisimura sfb_eraserows(id, startrow, nrows, attr)
1240 1.10 nisimura void *id;
1241 1.10 nisimura int startrow, nrows;
1242 1.21 nisimura long attr;
1243 1.10 nisimura {
1244 1.35 nisimura struct rasops_info *ri = id;
1245 1.10 nisimura caddr_t sfb, p;
1246 1.10 nisimura int scanspan, starty, height, width, align, w;
1247 1.10 nisimura u_int32_t lmask, rmask;
1248 1.10 nisimura
1249 1.35 nisimura scanspan = ri->ri_stride;
1250 1.35 nisimura starty = ri->ri_font->fontheight * startrow;
1251 1.35 nisimura height = ri->ri_font->fontheight * nrows;
1252 1.10 nisimura
1253 1.35 nisimura p = ri->ri_bits + starty * scanspan;
1254 1.10 nisimura align = (long)p & SFBALIGNMASK;
1255 1.10 nisimura p -= align;
1256 1.35 nisimura w = ri->ri_emuwidth;
1257 1.10 nisimura width = w + align;
1258 1.10 nisimura lmask = SFBSTIPPLEALL1 << align;
1259 1.10 nisimura rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1260 1.35 nisimura sfb = ri->ri_hw;
1261 1.21 nisimura
1262 1.21 nisimura SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1263 1.21 nisimura SFBPLANEMASK(sfb, ~0);
1264 1.42 nisimura SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1265 1.10 nisimura if (width <= SFBSTIPPLEBITS) {
1266 1.10 nisimura /* never happens */;
1267 1.10 nisimura }
1268 1.10 nisimura else {
1269 1.10 nisimura caddr_t q = p;
1270 1.10 nisimura while (height > 0) {
1271 1.10 nisimura *(u_int32_t *)p = lmask;
1272 1.39 nisimura WRITE_MB();
1273 1.10 nisimura width -= 2 * SFBSTIPPLEBITS;
1274 1.10 nisimura while (width > 0) {
1275 1.10 nisimura p += SFBSTIPPLEBYTESDONE;
1276 1.10 nisimura *(u_int32_t *)p = SFBSTIPPLEALL1;
1277 1.39 nisimura WRITE_MB();
1278 1.10 nisimura width -= SFBSTIPPLEBITS;
1279 1.10 nisimura }
1280 1.10 nisimura p += SFBSTIPPLEBYTESDONE;
1281 1.10 nisimura *(u_int32_t *)p = rmask;
1282 1.39 nisimura WRITE_MB();
1283 1.10 nisimura
1284 1.10 nisimura p = (q += scanspan);
1285 1.10 nisimura width = w + align;
1286 1.10 nisimura height--;
1287 1.10 nisimura }
1288 1.10 nisimura }
1289 1.21 nisimura SFBMODE(sfb, MODE_SIMPLE);
1290 1.10 nisimura }
1291