fbbm.c revision 1.1 1 1.1 tsutsui /* $NetBSD: fbbm.c,v 1.1 2026/09/20 10:29:11 tsutsui Exp $ */
2 1.1 tsutsui
3 1.1 tsutsui /*-
4 1.1 tsutsui * Copyright (c) 2026 Izumi Tsutsui. All rights reserved.
5 1.1 tsutsui *
6 1.1 tsutsui * Redistribution and use in source and binary forms, with or without
7 1.1 tsutsui * modification, are permitted provided that the following conditions
8 1.1 tsutsui * are met:
9 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright
10 1.1 tsutsui * notice, this list of conditions and the following disclaimer.
11 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the
13 1.1 tsutsui * documentation and/or other materials provided with the distribution.
14 1.1 tsutsui *
15 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 1.1 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 1.1 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 1.1 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 1.1 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 1.1 tsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 1.1 tsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 1.1 tsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 1.1 tsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 1.1 tsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 1.1 tsutsui */
26 1.1 tsutsui
27 1.1 tsutsui #include <sys/cdefs.h>
28 1.1 tsutsui __KERNEL_RCSID(0, "$NetBSD: fbbm.c,v 1.1 2026/09/20 10:29:11 tsutsui Exp $");
29 1.1 tsutsui
30 1.1 tsutsui #include <sys/param.h>
31 1.1 tsutsui #include <sys/device.h>
32 1.1 tsutsui #include <sys/errno.h>
33 1.1 tsutsui #include <sys/ioctl.h>
34 1.1 tsutsui #include <sys/kmem.h>
35 1.1 tsutsui #include <sys/systm.h>
36 1.1 tsutsui
37 1.1 tsutsui #include <machine/bus.h>
38 1.1 tsutsui
39 1.1 tsutsui #include <news68k/dev/hbvar.h>
40 1.1 tsutsui #include <news68k/dev/nwb225reg.h>
41 1.1 tsutsui
42 1.1 tsutsui #include <dev/wscons/wsconsio.h>
43 1.1 tsutsui #include <dev/wscons/wsdisplayvar.h>
44 1.1 tsutsui
45 1.1 tsutsui struct fbbm_devconfig {
46 1.1 tsutsui bus_space_tag_t dc_bst;
47 1.1 tsutsui bus_space_handle_t dc_rcont_bsh;
48 1.1 tsutsui bus_space_handle_t dc_krom_bsh;
49 1.1 tsutsui
50 1.1 tsutsui int dc_nplanes;
51 1.1 tsutsui uint32_t dc_planemask;
52 1.1 tsutsui int dc_dispver;
53 1.1 tsutsui
54 1.1 tsutsui int dc_fbwidth;
55 1.1 tsutsui int dc_fbheight;
56 1.1 tsutsui int dc_width;
57 1.1 tsutsui int dc_height;
58 1.1 tsutsui
59 1.1 tsutsui int dc_fontwidth;
60 1.1 tsutsui int dc_fontheight;
61 1.1 tsutsui int dc_cellwidth;
62 1.1 tsutsui int dc_cellheight;
63 1.1 tsutsui
64 1.1 tsutsui int dc_ncols;
65 1.1 tsutsui int dc_nrows;
66 1.1 tsutsui int dc_xorigin;
67 1.1 tsutsui int dc_yorigin;
68 1.1 tsutsui
69 1.1 tsutsui int dc_cursoron;
70 1.1 tsutsui int dc_cursorrow;
71 1.1 tsutsui int dc_cursorcol;
72 1.1 tsutsui
73 1.1 tsutsui struct wsscreen_descr dc_wsscrdescr;
74 1.1 tsutsui };
75 1.1 tsutsui
76 1.1 tsutsui struct fbbm_softc {
77 1.1 tsutsui device_t sc_dev;
78 1.1 tsutsui struct fbbm_devconfig *sc_dc;
79 1.1 tsutsui int sc_nscreens;
80 1.1 tsutsui int sc_wsmode;
81 1.1 tsutsui const struct wsscreen_descr *sc_scrdescs[1];
82 1.1 tsutsui struct wsscreen_list sc_scrlist;
83 1.1 tsutsui };
84 1.1 tsutsui
85 1.1 tsutsui /* autoconf functions and helpers */
86 1.1 tsutsui static int fbbm_match(device_t, cfdata_t, void *);
87 1.1 tsutsui static void fbbm_attach(device_t, device_t, void *);
88 1.1 tsutsui
89 1.1 tsutsui static bool fbbm_console_initialized(void);
90 1.1 tsutsui static int fbbm_probe(bus_space_tag_t, bus_addr_t);
91 1.1 tsutsui
92 1.1 tsutsui /* bus_space mappings */
93 1.1 tsutsui static int nwb225_map(struct fbbm_devconfig *, bus_space_tag_t, bus_addr_t);
94 1.1 tsutsui static void nwb225_unmap(struct fbbm_devconfig *);
95 1.1 tsutsui
96 1.1 tsutsui /* ROP helper functions */
97 1.1 tsutsui static void nwb225_rop_reset(struct fbbm_devconfig *);
98 1.1 tsutsui static int nwb225_rop_wait(struct fbbm_devconfig *);
99 1.1 tsutsui static void nwb225_ctl_write(struct fbbm_devconfig *, uint16_t, uint16_t);
100 1.1 tsutsui static void nwb225_rop_set_plane_mask(struct fbbm_devconfig *, uint32_t);
101 1.1 tsutsui static void nwb225_rop_make_funcvec(struct fbbm_devconfig *, u_int,
102 1.1 tsutsui uint32_t, uint32_t, uint8_t *);
103 1.1 tsutsui static void nwb225_rop_funcvec_constant_s(struct fbbm_devconfig *, uint8_t *,
104 1.1 tsutsui u_int);
105 1.1 tsutsui static void nwb225_rop_set_funcvec(struct fbbm_devconfig *, const uint8_t *);
106 1.1 tsutsui
107 1.1 tsutsui /* Hardware primitive ROP functions */
108 1.1 tsutsui static int nwb225_rop_copy_rect(struct fbbm_devconfig *, int, int, int, int,
109 1.1 tsutsui int, int, u_int);
110 1.1 tsutsui static int nwb225_rop_fill_rect(struct fbbm_devconfig *, int, int, int, int,
111 1.1 tsutsui uint32_t);
112 1.1 tsutsui static int nwb225_rop_hwrite(struct fbbm_devconfig *, const uint16_t *, int,
113 1.1 tsutsui int, int, int, int, int, int, uint32_t, uint32_t);
114 1.1 tsutsui
115 1.1 tsutsui /* ROM font functions */
116 1.1 tsutsui static bus_size_t nwb225_krom_ascii_offset(u_int);
117 1.1 tsutsui static void nwb225_krom_load_cell(struct fbbm_devconfig *, u_int,
118 1.1 tsutsui uint16_t *);
119 1.1 tsutsui
120 1.1 tsutsui /* Initialization */
121 1.1 tsutsui static int nwb225_init_hardware(struct fbbm_devconfig *);
122 1.1 tsutsui
123 1.1 tsutsui static void fbbm_init_screen(struct fbbm_devconfig *);
124 1.1 tsutsui static int fbbm_clear_screen(struct fbbm_devconfig *);
125 1.1 tsutsui
126 1.1 tsutsui /* wsdisplay_emulops functions */
127 1.1 tsutsui static void fbbm_cursor(void *, int, int, int);
128 1.1 tsutsui static int fbbm_mapchar(void *, int, u_int *);
129 1.1 tsutsui static void fbbm_putchar(void *, int, int, u_int, long);
130 1.1 tsutsui static void fbbm_copycols(void *, int, int, int, int);
131 1.1 tsutsui static void fbbm_erasecols(void *, int, int, int, long);
132 1.1 tsutsui static void fbbm_copyrows(void *, int, int, int);
133 1.1 tsutsui static void fbbm_eraserows(void *, int, int, long);
134 1.1 tsutsui static int fbbm_allocattr(void *, int, int, int, long *);
135 1.1 tsutsui
136 1.1 tsutsui /* wsdisplay_accessops functions */
137 1.1 tsutsui static int fbbm_ioctl(void *, void *, u_long, void *, int, struct lwp *);
138 1.1 tsutsui static int fbbm_alloc_screen(void *, const struct wsscreen_descr *, void **,
139 1.1 tsutsui int *, int *, long *);
140 1.1 tsutsui static void fbbm_free_screen(void *, void *);
141 1.1 tsutsui static int fbbm_show_screen(void *, void *, int, void (*)(void *, int, int),
142 1.1 tsutsui void *);
143 1.1 tsutsui
144 1.1 tsutsui /* cnattach function for early console */
145 1.1 tsutsui int fbbm_cnattach(void);
146 1.1 tsutsui
147 1.1 tsutsui CFATTACH_DECL_NEW(fbbm, sizeof(struct fbbm_softc),
148 1.1 tsutsui fbbm_match, fbbm_attach, NULL, NULL);
149 1.1 tsutsui
150 1.1 tsutsui static struct fbbm_devconfig fbbm_console_dc;
151 1.1 tsutsui
152 1.1 tsutsui static const struct wsdisplay_emulops fbbm_emulops = {
153 1.1 tsutsui .cursor = fbbm_cursor,
154 1.1 tsutsui .mapchar = fbbm_mapchar,
155 1.1 tsutsui .putchar = fbbm_putchar,
156 1.1 tsutsui .copycols = fbbm_copycols,
157 1.1 tsutsui .erasecols = fbbm_erasecols,
158 1.1 tsutsui .copyrows = fbbm_copyrows,
159 1.1 tsutsui .eraserows = fbbm_eraserows,
160 1.1 tsutsui .allocattr = fbbm_allocattr,
161 1.1 tsutsui .replaceattr = NULL,
162 1.1 tsutsui };
163 1.1 tsutsui
164 1.1 tsutsui static const struct wsdisplay_accessops fbbm_accessops = {
165 1.1 tsutsui .ioctl = fbbm_ioctl,
166 1.1 tsutsui .mmap = NULL,
167 1.1 tsutsui .alloc_screen = fbbm_alloc_screen,
168 1.1 tsutsui .free_screen = fbbm_free_screen,
169 1.1 tsutsui .show_screen = fbbm_show_screen,
170 1.1 tsutsui .load_font = NULL,
171 1.1 tsutsui .pollc = NULL,
172 1.1 tsutsui .scroll = NULL,
173 1.1 tsutsui };
174 1.1 tsutsui
175 1.1 tsutsui /* Timeout count to check ROP op complete */
176 1.1 tsutsui #define NWB225_WAIT_MAX 100000
177 1.1 tsutsui
178 1.1 tsutsui /* Maximum number of planes of NWB-225 (4 or 8) */
179 1.1 tsutsui #define NWB225_MAX_PLANES 8
180 1.1 tsutsui
181 1.1 tsutsui /*
182 1.1 tsutsui * Software logical functions F(S,D).
183 1.1 tsutsui * These values index nwb225_fccnvtab[] and are not hardware function values.
184 1.1 tsutsui */
185 1.1 tsutsui #define NWB225_ROP_LF_0 0x00
186 1.1 tsutsui #define NWB225_ROP_LF_S 0x03
187 1.1 tsutsui #define NWB225_ROP_LF_D 0x05
188 1.1 tsutsui #define NWB225_ROP_LF_DI 0x0a
189 1.1 tsutsui #define NWB225_ROP_LF_1 0x0f
190 1.1 tsutsui
191 1.1 tsutsui /*
192 1.1 tsutsui * Logical FBBM function to 51X hardware function conversion table
193 1.1 tsutsui * taken from NEWS-OS fbbm_51x.o.
194 1.1 tsutsui */
195 1.1 tsutsui static const uint8_t nwb225_fccnvtab[16] = {
196 1.1 tsutsui 0x03, 0x0b, 0x07, 0x0f,
197 1.1 tsutsui 0x02, 0x0a, 0x06, 0x0e,
198 1.1 tsutsui 0x01, 0x09, 0x05, 0x0d,
199 1.1 tsutsui 0x00, 0x08, 0x04, 0x0c,
200 1.1 tsutsui };
201 1.1 tsutsui
202 1.1 tsutsui /*
203 1.1 tsutsui * Fixed initialization values written by the NWS-1750 PROM and NEWS-OS
204 1.1 tsutsui * 51X setup. Their individual timing/control semantics are intentionally
205 1.1 tsutsui * not inferred here.
206 1.1 tsutsui */
207 1.1 tsutsui static const uint16_t nwb225_init_words[] = {
208 1.1 tsutsui 0x0400, 0x0002, 0x0005, 0x00d8,
209 1.1 tsutsui 0x0000, 0x0006, 0x0000,
210 1.1 tsutsui };
211 1.1 tsutsui
212 1.1 tsutsui /*
213 1.1 tsutsui * 4-bit component values taken from the NWS-1750 PROM NWB-225 module.
214 1.1 tsutsui * The PROM repeats this 16-entry table through all 256 palette indices
215 1.1 tsutsui * and writes each component after shifting it left by four bits.
216 1.1 tsutsui */
217 1.1 tsutsui static const uint8_t nwb225_prom_palette[16][3] = {
218 1.1 tsutsui { 0, 0, 0 },
219 1.1 tsutsui { 0, 0, 4 },
220 1.1 tsutsui { 0, 4, 0 },
221 1.1 tsutsui { 0, 4, 4 },
222 1.1 tsutsui { 4, 0, 0 },
223 1.1 tsutsui { 4, 0, 4 },
224 1.1 tsutsui { 4, 4, 0 },
225 1.1 tsutsui { 4, 4, 4 },
226 1.1 tsutsui { 8, 8, 8 },
227 1.1 tsutsui { 0, 0, 15 },
228 1.1 tsutsui { 0, 15, 0 },
229 1.1 tsutsui { 0, 15, 15 },
230 1.1 tsutsui { 15, 0, 0 },
231 1.1 tsutsui { 15, 0, 15 },
232 1.1 tsutsui { 15, 15, 0 },
233 1.1 tsutsui { 15, 15, 15 },
234 1.1 tsutsui };
235 1.1 tsutsui
236 1.1 tsutsui static bool
237 1.1 tsutsui fbbm_console_initialized(void)
238 1.1 tsutsui {
239 1.1 tsutsui
240 1.1 tsutsui /*
241 1.1 tsutsui * This is initialized in fbbm_init_screen() via
242 1.1 tsutsui * fbbm_cnattach() or fbbm_cnattach().
243 1.1 tsutsui */
244 1.1 tsutsui return fbbm_console_dc.dc_wsscrdescr.textops == &fbbm_emulops;
245 1.1 tsutsui }
246 1.1 tsutsui
247 1.1 tsutsui static int
248 1.1 tsutsui fbbm_probe(bus_space_tag_t bst, bus_addr_t rcont_addr)
249 1.1 tsutsui {
250 1.1 tsutsui bus_space_handle_t bsh;
251 1.1 tsutsui int rv;
252 1.1 tsutsui
253 1.1 tsutsui if (bus_space_map(bst, rcont_addr, NWB225_RCONT_SIZE, 0, &bsh) != 0)
254 1.1 tsutsui return 0;
255 1.1 tsutsui
256 1.1 tsutsui /* NEWS-OS fb225_probe() used a byte-sized badaddr() at this base */
257 1.1 tsutsui rv = news68k_bus_space_probe(bst, bsh, 0, 1);
258 1.1 tsutsui bus_space_unmap(bst, bsh, NWB225_RCONT_SIZE);
259 1.1 tsutsui
260 1.1 tsutsui return rv;
261 1.1 tsutsui }
262 1.1 tsutsui
263 1.1 tsutsui static int
264 1.1 tsutsui fbbm_match(device_t parent, cfdata_t cf, void *aux)
265 1.1 tsutsui {
266 1.1 tsutsui struct hb_attach_args *ha = aux;
267 1.1 tsutsui
268 1.1 tsutsui if (strcmp(ha->ha_name, "fbbm") != 0)
269 1.1 tsutsui return 0;
270 1.1 tsutsui if (ha->ha_address != NWB225_RCONT_BASE)
271 1.1 tsutsui return 0;
272 1.1 tsutsui
273 1.1 tsutsui return fbbm_probe(ha->ha_bust, ha->ha_address);
274 1.1 tsutsui }
275 1.1 tsutsui
276 1.1 tsutsui static void
277 1.1 tsutsui fbbm_attach(device_t parent, device_t self, void *aux)
278 1.1 tsutsui {
279 1.1 tsutsui struct fbbm_softc *sc = device_private(self);
280 1.1 tsutsui struct hb_attach_args *ha = aux;
281 1.1 tsutsui struct fbbm_devconfig *dc;
282 1.1 tsutsui struct wsemuldisplaydev_attach_args waa;
283 1.1 tsutsui bool console;
284 1.1 tsutsui
285 1.1 tsutsui sc->sc_dev = self;
286 1.1 tsutsui console = fbbm_console_initialized();
287 1.1 tsutsui
288 1.1 tsutsui if (console) {
289 1.1 tsutsui dc = &fbbm_console_dc;
290 1.1 tsutsui sc->sc_nscreens = 1;
291 1.1 tsutsui } else {
292 1.1 tsutsui dc = kmem_zalloc(sizeof(*dc), KM_SLEEP);
293 1.1 tsutsui if (nwb225_map(dc, ha->ha_bust, ha->ha_address) != 0) {
294 1.1 tsutsui aprint_error(": unable to map device registers");
295 1.1 tsutsui goto out_free;
296 1.1 tsutsui }
297 1.1 tsutsui
298 1.1 tsutsui if (nwb225_init_hardware(dc) != 0) {
299 1.1 tsutsui aprint_error(": controller initialization failed");
300 1.1 tsutsui goto out_unmap;
301 1.1 tsutsui }
302 1.1 tsutsui
303 1.1 tsutsui fbbm_init_screen(dc);
304 1.1 tsutsui if (fbbm_clear_screen(dc) != 0) {
305 1.1 tsutsui aprint_error(": unable to clear text screen");
306 1.1 tsutsui goto out_unmap;
307 1.1 tsutsui }
308 1.1 tsutsui sc->sc_nscreens = 0;
309 1.1 tsutsui }
310 1.1 tsutsui
311 1.1 tsutsui sc->sc_dc = dc;
312 1.1 tsutsui sc->sc_wsmode = WSDISPLAYIO_MODE_EMUL;
313 1.1 tsutsui sc->sc_scrdescs[0] = &dc->dc_wsscrdescr;
314 1.1 tsutsui sc->sc_scrlist.nscreens = __arraycount(sc->sc_scrdescs);
315 1.1 tsutsui sc->sc_scrlist.screens = sc->sc_scrdescs;
316 1.1 tsutsui
317 1.1 tsutsui aprint_normal(": NWB-225, %d x %d, %d planes, display version %d\n",
318 1.1 tsutsui dc->dc_width, dc->dc_height, dc->dc_nplanes, dc->dc_dispver);
319 1.1 tsutsui
320 1.1 tsutsui waa.console = console;
321 1.1 tsutsui waa.scrdata = &sc->sc_scrlist;
322 1.1 tsutsui waa.accessops = &fbbm_accessops;
323 1.1 tsutsui waa.accesscookie = sc;
324 1.1 tsutsui
325 1.1 tsutsui config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE);
326 1.1 tsutsui return;
327 1.1 tsutsui
328 1.1 tsutsui out_unmap:
329 1.1 tsutsui nwb225_unmap(dc);
330 1.1 tsutsui out_free:
331 1.1 tsutsui kmem_free(dc, sizeof(*dc));
332 1.1 tsutsui }
333 1.1 tsutsui
334 1.1 tsutsui static int
335 1.1 tsutsui nwb225_map(struct fbbm_devconfig *dc, bus_space_tag_t bst,
336 1.1 tsutsui bus_addr_t rcont_addr)
337 1.1 tsutsui {
338 1.1 tsutsui int error;
339 1.1 tsutsui
340 1.1 tsutsui dc->dc_bst = bst;
341 1.1 tsutsui
342 1.1 tsutsui error = bus_space_map(bst, rcont_addr, NWB225_RCONT_SIZE, 0,
343 1.1 tsutsui &dc->dc_rcont_bsh);
344 1.1 tsutsui if (error != 0)
345 1.1 tsutsui return error;
346 1.1 tsutsui
347 1.1 tsutsui error = bus_space_map(bst, NWB225_KROM_BASE, NWB225_KROM_SIZE, 0,
348 1.1 tsutsui &dc->dc_krom_bsh);
349 1.1 tsutsui if (error != 0) {
350 1.1 tsutsui bus_space_unmap(bst, dc->dc_rcont_bsh, NWB225_RCONT_SIZE);
351 1.1 tsutsui return error;
352 1.1 tsutsui }
353 1.1 tsutsui
354 1.1 tsutsui return 0;
355 1.1 tsutsui }
356 1.1 tsutsui
357 1.1 tsutsui static void
358 1.1 tsutsui nwb225_unmap(struct fbbm_devconfig *dc)
359 1.1 tsutsui {
360 1.1 tsutsui
361 1.1 tsutsui bus_space_unmap(dc->dc_bst, dc->dc_krom_bsh, NWB225_KROM_SIZE);
362 1.1 tsutsui bus_space_unmap(dc->dc_bst, dc->dc_rcont_bsh, NWB225_RCONT_SIZE);
363 1.1 tsutsui }
364 1.1 tsutsui
365 1.1 tsutsui static void
366 1.1 tsutsui nwb225_rop_reset(struct fbbm_devconfig *dc)
367 1.1 tsutsui {
368 1.1 tsutsui
369 1.1 tsutsui /*
370 1.1 tsutsui * Both NEWS-OS fb51X_rop_reset() and the NWS-1750 PROM perform
371 1.1 tsutsui * this 0 -> 1 sequence.
372 1.1 tsutsui */
373 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh, NWB225_STATUS, 0);
374 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh, NWB225_STATUS, 1);
375 1.1 tsutsui }
376 1.1 tsutsui
377 1.1 tsutsui static int
378 1.1 tsutsui nwb225_rop_wait(struct fbbm_devconfig *dc)
379 1.1 tsutsui {
380 1.1 tsutsui uint16_t status;
381 1.1 tsutsui int i;
382 1.1 tsutsui
383 1.1 tsutsui for (i = 0; i < NWB225_WAIT_MAX; i++) {
384 1.1 tsutsui status = bus_space_read_2(dc->dc_bst, dc->dc_rcont_bsh,
385 1.1 tsutsui NWB225_STATUS);
386 1.1 tsutsui if ((status & NWB225_STATUS_BUSY) == 0)
387 1.1 tsutsui return 0;
388 1.1 tsutsui }
389 1.1 tsutsui
390 1.1 tsutsui /* Reset ROP engine on timeout as NEWS-OS does */
391 1.1 tsutsui nwb225_rop_reset(dc);
392 1.1 tsutsui return ETIMEDOUT;
393 1.1 tsutsui }
394 1.1 tsutsui
395 1.1 tsutsui static void
396 1.1 tsutsui nwb225_ctl_write(struct fbbm_devconfig *dc, uint16_t selector, uint16_t value)
397 1.1 tsutsui {
398 1.1 tsutsui
399 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
400 1.1 tsutsui NWB225_CTL_SELECT, selector);
401 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
402 1.1 tsutsui NWB225_CTL_DATA, value);
403 1.1 tsutsui }
404 1.1 tsutsui
405 1.1 tsutsui static void
406 1.1 tsutsui nwb225_rop_set_plane_mask(struct fbbm_devconfig *dc, uint32_t planemask)
407 1.1 tsutsui {
408 1.1 tsutsui uint8_t disabled_planes;
409 1.1 tsutsui uint16_t hwmask;
410 1.1 tsutsui
411 1.1 tsutsui disabled_planes = (uint8_t)~planemask;
412 1.1 tsutsui hwmask = (uint16_t)disabled_planes << NWB225_PLANE_CTRL_SHIFT;
413 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
414 1.1 tsutsui NWB225_PLANE_CTRL, hwmask);
415 1.1 tsutsui }
416 1.1 tsutsui
417 1.1 tsutsui static void
418 1.1 tsutsui nwb225_rop_make_funcvec(struct fbbm_devconfig *dc, u_int logical_func,
419 1.1 tsutsui uint32_t src1, uint32_t src0, uint8_t *funcvec)
420 1.1 tsutsui {
421 1.1 tsutsui uint8_t f_s0_d, f_s1_d;
422 1.1 tsutsui uint8_t func_by_srcmap[4];
423 1.1 tsutsui uint8_t src1_bit, src0_bit, src_map;
424 1.1 tsutsui int i;
425 1.1 tsutsui
426 1.1 tsutsui KASSERT(logical_func <= 0x0f);
427 1.1 tsutsui KASSERT(dc->dc_nplanes == 4 || dc->dc_nplanes == 8);
428 1.1 tsutsui
429 1.1 tsutsui /* F(0,D) */
430 1.1 tsutsui f_s0_d = (logical_func >> 2) & 0x03;
431 1.1 tsutsui /* F(1,D) */
432 1.1 tsutsui f_s1_d = logical_func & 0x03;
433 1.1 tsutsui
434 1.1 tsutsui func_by_srcmap[0] = (f_s0_d << 2) | f_s0_d;
435 1.1 tsutsui func_by_srcmap[1] = (f_s1_d << 2) | f_s0_d;
436 1.1 tsutsui func_by_srcmap[2] = (f_s0_d << 2) | f_s1_d;
437 1.1 tsutsui func_by_srcmap[3] = (f_s1_d << 2) | f_s1_d;
438 1.1 tsutsui
439 1.1 tsutsui for (i = 0; i < dc->dc_nplanes; i++) {
440 1.1 tsutsui src1_bit = src1 & 0x01;
441 1.1 tsutsui src0_bit = src0 & 0x01;
442 1.1 tsutsui src_map = (src1_bit << 1) | src0_bit;
443 1.1 tsutsui funcvec[i] = func_by_srcmap[src_map];
444 1.1 tsutsui src1 >>= 1;
445 1.1 tsutsui src0 >>= 1;
446 1.1 tsutsui }
447 1.1 tsutsui }
448 1.1 tsutsui
449 1.1 tsutsui static void
450 1.1 tsutsui nwb225_rop_funcvec_constant_s(struct fbbm_devconfig *dc, uint8_t *funcvec,
451 1.1 tsutsui u_int s)
452 1.1 tsutsui {
453 1.1 tsutsui uint8_t logical_func, f_s0_d, f_s1_d, d_func, result;
454 1.1 tsutsui int i;
455 1.1 tsutsui
456 1.1 tsutsui KASSERT(dc->dc_nplanes == 4 || dc->dc_nplanes == 8);
457 1.1 tsutsui KASSERT(s <= 1);
458 1.1 tsutsui
459 1.1 tsutsui for (i = 0; i < dc->dc_nplanes; i++) {
460 1.1 tsutsui logical_func = funcvec[i];
461 1.1 tsutsui KASSERT(logical_func <= 0x0f);
462 1.1 tsutsui
463 1.1 tsutsui /* F(0,D) */
464 1.1 tsutsui f_s0_d = (logical_func >> 2) & 0x03;
465 1.1 tsutsui /* F(1,D) */
466 1.1 tsutsui f_s1_d = logical_func & 0x03;
467 1.1 tsutsui
468 1.1 tsutsui d_func = (s == 0) ? f_s0_d : f_s1_d;
469 1.1 tsutsui switch (d_func) {
470 1.1 tsutsui case 0:
471 1.1 tsutsui result = NWB225_ROP_LF_0;
472 1.1 tsutsui break;
473 1.1 tsutsui case 1:
474 1.1 tsutsui result = NWB225_ROP_LF_D;
475 1.1 tsutsui break;
476 1.1 tsutsui case 2:
477 1.1 tsutsui result = NWB225_ROP_LF_DI;
478 1.1 tsutsui break;
479 1.1 tsutsui case 3:
480 1.1 tsutsui result = NWB225_ROP_LF_1;
481 1.1 tsutsui break;
482 1.1 tsutsui default:
483 1.1 tsutsui KASSERT(false);
484 1.1 tsutsui result = NWB225_ROP_LF_0;
485 1.1 tsutsui break;
486 1.1 tsutsui }
487 1.1 tsutsui funcvec[i] = result;
488 1.1 tsutsui }
489 1.1 tsutsui }
490 1.1 tsutsui
491 1.1 tsutsui static void
492 1.1 tsutsui nwb225_rop_set_funcvec(struct fbbm_devconfig *dc, const uint8_t *funcvec)
493 1.1 tsutsui {
494 1.1 tsutsui uint8_t logical_func, hw_func;
495 1.1 tsutsui int i;
496 1.1 tsutsui
497 1.1 tsutsui for (i = 0; i < dc->dc_nplanes; i++) {
498 1.1 tsutsui KASSERT(funcvec[i] <= 0x0f);
499 1.1 tsutsui logical_func = funcvec[i];
500 1.1 tsutsui hw_func = nwb225_fccnvtab[logical_func];
501 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
502 1.1 tsutsui NWB225_ROP_FUNC(i), hw_func);
503 1.1 tsutsui }
504 1.1 tsutsui }
505 1.1 tsutsui
506 1.1 tsutsui static int
507 1.1 tsutsui nwb225_rect_valid(struct fbbm_devconfig *dc, int x, int y, int width,
508 1.1 tsutsui int height)
509 1.1 tsutsui {
510 1.1 tsutsui
511 1.1 tsutsui if (x < 0 || y < 0 || width <= 0 || height <= 0)
512 1.1 tsutsui return 0;
513 1.1 tsutsui if (x >= dc->dc_fbwidth || y >= dc->dc_fbheight)
514 1.1 tsutsui return 0;
515 1.1 tsutsui if (width > dc->dc_fbwidth - x || height > dc->dc_fbheight - y)
516 1.1 tsutsui return 0;
517 1.1 tsutsui
518 1.1 tsutsui return 1;
519 1.1 tsutsui }
520 1.1 tsutsui
521 1.1 tsutsui static int
522 1.1 tsutsui nwb225_rop_copy_rect(struct fbbm_devconfig *dc, int sx, int sy, int width,
523 1.1 tsutsui int height, int dx, int dy, u_int logical_func)
524 1.1 tsutsui {
525 1.1 tsutsui uint8_t funcvec[NWB225_MAX_PLANES];
526 1.1 tsutsui bus_size_t copy_mode;
527 1.1 tsutsui bool reverse_x, reverse_y;
528 1.1 tsutsui int src_x, src_y, dst_x, dst_y, limit_x;
529 1.1 tsutsui int error;
530 1.1 tsutsui
531 1.1 tsutsui if (logical_func > 0x0f)
532 1.1 tsutsui return EINVAL;
533 1.1 tsutsui
534 1.1 tsutsui if (nwb225_rect_valid(dc, sx, sy, width, height) == 0 ||
535 1.1 tsutsui nwb225_rect_valid(dc, dx, dy, width, height) == 0)
536 1.1 tsutsui return EINVAL;
537 1.1 tsutsui
538 1.1 tsutsui error = nwb225_rop_wait(dc);
539 1.1 tsutsui if (__predict_false(error != 0))
540 1.1 tsutsui return error;
541 1.1 tsutsui
542 1.1 tsutsui nwb225_rop_make_funcvec(dc, logical_func, dc->dc_planemask, 0, funcvec);
543 1.1 tsutsui nwb225_rop_set_funcvec(dc, funcvec);
544 1.1 tsutsui nwb225_rop_set_plane_mask(dc, dc->dc_planemask);
545 1.1 tsutsui
546 1.1 tsutsui /* Wait again as NEWS-OS does */
547 1.1 tsutsui error = nwb225_rop_wait(dc);
548 1.1 tsutsui if (__predict_false(error != 0))
549 1.1 tsutsui return error;
550 1.1 tsutsui
551 1.1 tsutsui reverse_x = (sx < dx);
552 1.1 tsutsui reverse_y = (sy < dy);
553 1.1 tsutsui src_x = sx + (reverse_x ? width : 0);
554 1.1 tsutsui dst_x = dx + (reverse_x ? width : 0);
555 1.1 tsutsui limit_x = dx + (reverse_x ? 0 : width);
556 1.1 tsutsui src_y = sy + (reverse_y ? height - 1 : 0);
557 1.1 tsutsui dst_y = dy + (reverse_y ? height - 1 : 0);
558 1.1 tsutsui
559 1.1 tsutsui if (reverse_x) {
560 1.1 tsutsui if (reverse_y) {
561 1.1 tsutsui copy_mode = NWB225_ROP_COPY_XR_YR;
562 1.1 tsutsui } else {
563 1.1 tsutsui copy_mode = NWB225_ROP_COPY_XR_YF;
564 1.1 tsutsui }
565 1.1 tsutsui } else {
566 1.1 tsutsui if (reverse_y) {
567 1.1 tsutsui copy_mode = NWB225_ROP_COPY_XF_YR;
568 1.1 tsutsui } else {
569 1.1 tsutsui copy_mode = NWB225_ROP_COPY_XF_YF;
570 1.1 tsutsui }
571 1.1 tsutsui }
572 1.1 tsutsui
573 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
574 1.1 tsutsui copy_mode, 0);
575 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
576 1.1 tsutsui NWB225_DST_ADDR(dst_y), dst_x);
577 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
578 1.1 tsutsui NWB225_SRC_ADDR(src_y) | NWB225_ROP_ADDR_FLAG_SET_SHIFT, src_x);
579 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
580 1.1 tsutsui NWB225_ROP_LIMIT(height) | NWB225_ROP_ADDR_FLAG_EXECUTE, limit_x);
581 1.1 tsutsui
582 1.1 tsutsui /* Wait complete for polling ops */
583 1.1 tsutsui error = nwb225_rop_wait(dc);
584 1.1 tsutsui
585 1.1 tsutsui return error;
586 1.1 tsutsui }
587 1.1 tsutsui
588 1.1 tsutsui static int
589 1.1 tsutsui nwb225_rop_fill_rect(struct fbbm_devconfig *dc, int x, int y, int width,
590 1.1 tsutsui int height, uint32_t color)
591 1.1 tsutsui {
592 1.1 tsutsui uint8_t funcvec[NWB225_MAX_PLANES];
593 1.1 tsutsui int error;
594 1.1 tsutsui
595 1.1 tsutsui if (nwb225_rect_valid(dc, x, y, width, height) == 0)
596 1.1 tsutsui return EINVAL;
597 1.1 tsutsui
598 1.1 tsutsui error = nwb225_rop_wait(dc);
599 1.1 tsutsui if (__predict_false(error != 0))
600 1.1 tsutsui return error;
601 1.1 tsutsui
602 1.1 tsutsui color &= dc->dc_planemask;
603 1.1 tsutsui nwb225_rop_make_funcvec(dc, NWB225_ROP_LF_S, color, 0, funcvec);
604 1.1 tsutsui nwb225_rop_funcvec_constant_s(dc, funcvec, 1);
605 1.1 tsutsui nwb225_rop_set_plane_mask(dc, dc->dc_planemask);
606 1.1 tsutsui nwb225_rop_set_funcvec(dc, funcvec);
607 1.1 tsutsui
608 1.1 tsutsui /* Wait again as NEWS-OS does */
609 1.1 tsutsui error = nwb225_rop_wait(dc);
610 1.1 tsutsui if (__predict_false(error != 0))
611 1.1 tsutsui return error;
612 1.1 tsutsui
613 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
614 1.1 tsutsui NWB225_ROP_CONST_FILL, 0);
615 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
616 1.1 tsutsui NWB225_DST_ADDR(0), 0);
617 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
618 1.1 tsutsui NWB225_SRC_ADDR(0) | NWB225_ROP_ADDR_FLAG_SET_SHIFT, 0);
619 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
620 1.1 tsutsui NWB225_DST_ADDR(y), x);
621 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
622 1.1 tsutsui NWB225_ROP_LIMIT(height) | NWB225_ROP_ADDR_FLAG_EXECUTE, x + width);
623 1.1 tsutsui
624 1.1 tsutsui /* Wait complete for polling ops */
625 1.1 tsutsui error = nwb225_rop_wait(dc);
626 1.1 tsutsui
627 1.1 tsutsui return error;
628 1.1 tsutsui }
629 1.1 tsutsui
630 1.1 tsutsui static int
631 1.1 tsutsui nwb225_rop_hwrite(struct fbbm_devconfig *dc, const uint16_t *src_words,
632 1.1 tsutsui int src_stride_words, int srcx, int srcy, int width, int height,
633 1.1 tsutsui int dx, int dy, uint32_t foreground, uint32_t background)
634 1.1 tsutsui {
635 1.1 tsutsui uint8_t funcvec[NWB225_MAX_PLANES];
636 1.1 tsutsui int source_word_offset, source_bit_offset;
637 1.1 tsutsui int row_words, row_skip_words, row, word;
638 1.1 tsutsui const uint16_t *sp;
639 1.1 tsutsui int error;
640 1.1 tsutsui
641 1.1 tsutsui if (src_words == NULL || src_stride_words <= 0 || srcx < 0 || srcy < 0)
642 1.1 tsutsui return EINVAL;
643 1.1 tsutsui
644 1.1 tsutsui if (nwb225_rect_valid(dc, dx, dy, width, height) == 0)
645 1.1 tsutsui return EINVAL;
646 1.1 tsutsui
647 1.1 tsutsui source_word_offset = srcx / NWB225_HWRITE_BITS_PER_WORD;
648 1.1 tsutsui source_bit_offset = srcx % NWB225_HWRITE_BITS_PER_WORD;
649 1.1 tsutsui row_words =
650 1.1 tsutsui howmany(source_bit_offset + width, NWB225_HWRITE_BITS_PER_WORD);
651 1.1 tsutsui if (source_word_offset + row_words > src_stride_words)
652 1.1 tsutsui return EINVAL;
653 1.1 tsutsui
654 1.1 tsutsui error = nwb225_rop_wait(dc);
655 1.1 tsutsui if (__predict_false(error != 0))
656 1.1 tsutsui return error;
657 1.1 tsutsui
658 1.1 tsutsui foreground &= dc->dc_planemask;
659 1.1 tsutsui background &= dc->dc_planemask;
660 1.1 tsutsui nwb225_rop_make_funcvec(dc, NWB225_ROP_LF_S, foreground, background,
661 1.1 tsutsui funcvec);
662 1.1 tsutsui nwb225_rop_set_funcvec(dc, funcvec);
663 1.1 tsutsui nwb225_rop_set_plane_mask(dc, dc->dc_planemask);
664 1.1 tsutsui
665 1.1 tsutsui /* Wait again as NEWS-OS does */
666 1.1 tsutsui error = nwb225_rop_wait(dc);
667 1.1 tsutsui if (__predict_false(error != 0))
668 1.1 tsutsui return error;
669 1.1 tsutsui
670 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
671 1.1 tsutsui NWB225_DST_ADDR(dy), dx);
672 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
673 1.1 tsutsui NWB225_SRC_ADDR(0) | NWB225_ROP_ADDR_FLAG_SET_SHIFT,
674 1.1 tsutsui source_bit_offset);
675 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
676 1.1 tsutsui NWB225_HWRITE_LIMIT(height) | NWB225_ROP_ADDR_FLAG_EXECUTE,
677 1.1 tsutsui dx + width);
678 1.1 tsutsui
679 1.1 tsutsui sp = src_words + (srcy * src_stride_words) + source_word_offset;
680 1.1 tsutsui row_skip_words = src_stride_words - row_words;
681 1.1 tsutsui for (row = 0; row < height; row++) {
682 1.1 tsutsui for (word = 0; word < row_words; word++)
683 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
684 1.1 tsutsui NWB225_HWRITE_DATA, *sp++);
685 1.1 tsutsui sp += row_skip_words;
686 1.1 tsutsui }
687 1.1 tsutsui
688 1.1 tsutsui /* Wait complete for polling ops */
689 1.1 tsutsui error = nwb225_rop_wait(dc);
690 1.1 tsutsui
691 1.1 tsutsui return error;
692 1.1 tsutsui }
693 1.1 tsutsui
694 1.1 tsutsui static bus_size_t
695 1.1 tsutsui nwb225_krom_ascii_offset(u_int c)
696 1.1 tsutsui {
697 1.1 tsutsui u_int index;
698 1.1 tsutsui
699 1.1 tsutsui index = c - NWB225_KROM_ASCII_FIRST;
700 1.1 tsutsui return ((index & 0xe0) << 9) | ((index & 0x1f) << 7);
701 1.1 tsutsui }
702 1.1 tsutsui
703 1.1 tsutsui static void
704 1.1 tsutsui nwb225_krom_load_cell(struct fbbm_devconfig *dc, u_int c, uint16_t *cell)
705 1.1 tsutsui {
706 1.1 tsutsui bus_size_t offset;
707 1.1 tsutsui int row;
708 1.1 tsutsui
709 1.1 tsutsui memset(cell, 0, NWB225_CELL_HEIGHT * sizeof(*cell));
710 1.1 tsutsui offset = nwb225_krom_ascii_offset(c);
711 1.1 tsutsui
712 1.1 tsutsui /*
713 1.1 tsutsui * The PROM renderer reads one 32-bit KROM row, keeps the upper word,
714 1.1 tsutsui * masks its low four bits, and places the 24 glyph rows after four
715 1.1 tsutsui * blank rows in the 16x30 cell.
716 1.1 tsutsui */
717 1.1 tsutsui for (row = 0; row < NWB225_FONT_HEIGHT; row++)
718 1.1 tsutsui cell[NWB225_GLYPH_YOFFSET + row] =
719 1.1 tsutsui bus_space_read_2(dc->dc_bst, dc->dc_krom_bsh,
720 1.1 tsutsui offset + row * NWB225_KROM_ROWBYTES) &
721 1.1 tsutsui NWB225_KROM_ASCII_MASK;
722 1.1 tsutsui }
723 1.1 tsutsui
724 1.1 tsutsui static int
725 1.1 tsutsui nwb225_init_hardware(struct fbbm_devconfig *dc)
726 1.1 tsutsui {
727 1.1 tsutsui uint16_t status, value;
728 1.1 tsutsui int i, component;
729 1.1 tsutsui
730 1.1 tsutsui /*
731 1.1 tsutsui * Use the cold-init sequence used by the NWB-225 routine in the
732 1.1 tsutsui * NWS-1750 PROM. In particular, the second reset is intentional.
733 1.1 tsutsui * The serial console cold-boot experiment required the init block
734 1.1 tsutsui * followed by this reset before stable sync was established by CRTC.
735 1.1 tsutsui */
736 1.1 tsutsui nwb225_rop_reset(dc);
737 1.1 tsutsui
738 1.1 tsutsui for (i = 0; i < __arraycount(nwb225_init_words); i++)
739 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
740 1.1 tsutsui NWB225_INIT_BASE + i * sizeof(uint16_t),
741 1.1 tsutsui nwb225_init_words[i]);
742 1.1 tsutsui
743 1.1 tsutsui status = bus_space_read_2(dc->dc_bst, dc->dc_rcont_bsh, NWB225_STATUS);
744 1.1 tsutsui if ((status & NWB225_STATUS_4PLANE) != 0)
745 1.1 tsutsui dc->dc_nplanes = 4;
746 1.1 tsutsui else
747 1.1 tsutsui dc->dc_nplanes = 8;
748 1.1 tsutsui dc->dc_planemask = (1U << dc->dc_nplanes) - 1;
749 1.1 tsutsui dc->dc_dispver =
750 1.1 tsutsui (status & NWB225_STATUS_DISPVER) >> NWB225_STATUS_DISPVER_SHIFT;
751 1.1 tsutsui
752 1.1 tsutsui nwb225_ctl_write(dc, 4, dc->dc_planemask);
753 1.1 tsutsui nwb225_ctl_write(dc, 5, 0);
754 1.1 tsutsui nwb225_ctl_write(dc, 6, 0x40);
755 1.1 tsutsui nwb225_ctl_write(dc, 7, 0);
756 1.1 tsutsui
757 1.1 tsutsui nwb225_rop_reset(dc);
758 1.1 tsutsui
759 1.1 tsutsui /* Complete the fixed PROM palette/control initialization */
760 1.1 tsutsui for (i = 0; i < 256; i++) {
761 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
762 1.1 tsutsui NWB225_PAL_INDEX, i);
763 1.1 tsutsui for (component = 0; component < 3; component++) {
764 1.1 tsutsui value = nwb225_prom_palette[i & 0x0f][component] << 4;
765 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
766 1.1 tsutsui NWB225_PAL_DATA, value);
767 1.1 tsutsui }
768 1.1 tsutsui }
769 1.1 tsutsui
770 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh, NWB225_PLANE_CTRL, 0);
771 1.1 tsutsui
772 1.1 tsutsui return nwb225_rop_wait(dc);
773 1.1 tsutsui }
774 1.1 tsutsui
775 1.1 tsutsui static void
776 1.1 tsutsui fbbm_init_screen(struct fbbm_devconfig *dc)
777 1.1 tsutsui {
778 1.1 tsutsui
779 1.1 tsutsui dc->dc_fbwidth = NWB225_FB_WIDTH;
780 1.1 tsutsui dc->dc_fbheight = NWB225_FB_HEIGHT;
781 1.1 tsutsui dc->dc_width = NWB225_VIS_WIDTH;
782 1.1 tsutsui dc->dc_height = NWB225_VIS_HEIGHT;
783 1.1 tsutsui
784 1.1 tsutsui dc->dc_fontwidth = NWB225_FONT_WIDTH;
785 1.1 tsutsui dc->dc_fontheight = NWB225_FONT_HEIGHT;
786 1.1 tsutsui dc->dc_cellwidth = NWB225_CELL_WIDTH;
787 1.1 tsutsui dc->dc_cellheight = NWB225_CELL_HEIGHT;
788 1.1 tsutsui
789 1.1 tsutsui dc->dc_ncols = NWB225_TEXT_COLS;
790 1.1 tsutsui dc->dc_nrows = NWB225_TEXT_ROWS;
791 1.1 tsutsui dc->dc_xorigin = NWB225_TEXT_XORIGIN;
792 1.1 tsutsui dc->dc_yorigin = NWB225_TEXT_YORIGIN;
793 1.1 tsutsui
794 1.1 tsutsui dc->dc_wsscrdescr.name = "std";
795 1.1 tsutsui dc->dc_wsscrdescr.ncols = dc->dc_ncols;
796 1.1 tsutsui dc->dc_wsscrdescr.nrows = dc->dc_nrows;
797 1.1 tsutsui dc->dc_wsscrdescr.textops = &fbbm_emulops;
798 1.1 tsutsui dc->dc_wsscrdescr.fontwidth = dc->dc_cellwidth;
799 1.1 tsutsui dc->dc_wsscrdescr.fontheight = dc->dc_cellheight;
800 1.1 tsutsui dc->dc_wsscrdescr.capabilities = WSSCREEN_REVERSE;
801 1.1 tsutsui dc->dc_wsscrdescr.modecookie = NULL;
802 1.1 tsutsui
803 1.1 tsutsui dc->dc_cursoron = 0;
804 1.1 tsutsui dc->dc_cursorrow = 0;
805 1.1 tsutsui dc->dc_cursorcol = 0;
806 1.1 tsutsui }
807 1.1 tsutsui
808 1.1 tsutsui /*
809 1.1 tsutsui * Clear the visible display region.
810 1.1 tsutsui * Called from both normal attach and early cnattach.
811 1.1 tsutsui */
812 1.1 tsutsui static int
813 1.1 tsutsui fbbm_clear_screen(struct fbbm_devconfig *dc)
814 1.1 tsutsui {
815 1.1 tsutsui
816 1.1 tsutsui return nwb225_rop_fill_rect(dc, 0, 0, dc->dc_width, dc->dc_height, 0);
817 1.1 tsutsui }
818 1.1 tsutsui
819 1.1 tsutsui static uint32_t
820 1.1 tsutsui fbbm_attr_background(struct fbbm_devconfig *dc, long attr)
821 1.1 tsutsui {
822 1.1 tsutsui
823 1.1 tsutsui return (attr & WSATTR_REVERSE) != 0 ? dc->dc_planemask : 0;
824 1.1 tsutsui }
825 1.1 tsutsui
826 1.1 tsutsui /*
827 1.1 tsutsui * wsdisplay_emulops functions
828 1.1 tsutsui */
829 1.1 tsutsui static void
830 1.1 tsutsui fbbm_cursor(void *cookie, int on, int row, int col)
831 1.1 tsutsui {
832 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
833 1.1 tsutsui int x, y, error;
834 1.1 tsutsui
835 1.1 tsutsui if (dc->dc_cursoron != 0) {
836 1.1 tsutsui x = dc->dc_xorigin + dc->dc_cursorcol * dc->dc_cellwidth;
837 1.1 tsutsui y = dc->dc_yorigin + dc->dc_cursorrow * dc->dc_cellheight;
838 1.1 tsutsui error = nwb225_rop_copy_rect(dc, x, y, dc->dc_cellwidth,
839 1.1 tsutsui dc->dc_cellheight, x, y, NWB225_ROP_LF_DI);
840 1.1 tsutsui if (error != 0)
841 1.1 tsutsui return;
842 1.1 tsutsui dc->dc_cursoron = 0;
843 1.1 tsutsui }
844 1.1 tsutsui
845 1.1 tsutsui dc->dc_cursorrow = row;
846 1.1 tsutsui dc->dc_cursorcol = col;
847 1.1 tsutsui if (on == 0)
848 1.1 tsutsui return;
849 1.1 tsutsui if (row < 0 || row >= dc->dc_nrows || col < 0 || col >= dc->dc_ncols)
850 1.1 tsutsui return;
851 1.1 tsutsui
852 1.1 tsutsui x = dc->dc_xorigin + col * dc->dc_cellwidth;
853 1.1 tsutsui y = dc->dc_yorigin + row * dc->dc_cellheight;
854 1.1 tsutsui error = nwb225_rop_copy_rect(dc, x, y, dc->dc_cellwidth,
855 1.1 tsutsui dc->dc_cellheight, x, y, NWB225_ROP_LF_DI);
856 1.1 tsutsui if (error == 0)
857 1.1 tsutsui dc->dc_cursoron = 1;
858 1.1 tsutsui }
859 1.1 tsutsui
860 1.1 tsutsui static int
861 1.1 tsutsui fbbm_mapchar(void *cookie, int c, u_int *cp)
862 1.1 tsutsui {
863 1.1 tsutsui
864 1.1 tsutsui if (c < NWB225_KROM_ASCII_FIRST || c > NWB225_KROM_ASCII_LAST) {
865 1.1 tsutsui *cp = ' ';
866 1.1 tsutsui return 0;
867 1.1 tsutsui }
868 1.1 tsutsui
869 1.1 tsutsui *cp = c;
870 1.1 tsutsui return 5;
871 1.1 tsutsui }
872 1.1 tsutsui
873 1.1 tsutsui static void
874 1.1 tsutsui fbbm_putchar(void *cookie, int row, int col, u_int uc, long attr)
875 1.1 tsutsui {
876 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
877 1.1 tsutsui uint16_t cell[NWB225_CELL_HEIGHT];
878 1.1 tsutsui uint32_t foreground, background;
879 1.1 tsutsui int x, y;
880 1.1 tsutsui
881 1.1 tsutsui if (__predict_false(row < 0 || row >= dc->dc_nrows ||
882 1.1 tsutsui col < 0 || col >= dc->dc_ncols))
883 1.1 tsutsui return;
884 1.1 tsutsui if (uc < NWB225_KROM_ASCII_FIRST || uc > NWB225_KROM_ASCII_LAST)
885 1.1 tsutsui uc = ' ';
886 1.1 tsutsui
887 1.1 tsutsui nwb225_krom_load_cell(dc, uc, cell);
888 1.1 tsutsui background = fbbm_attr_background(dc, attr);
889 1.1 tsutsui foreground = (~background) & dc->dc_planemask;
890 1.1 tsutsui x = dc->dc_xorigin + col * dc->dc_cellwidth;
891 1.1 tsutsui y = dc->dc_yorigin + row * dc->dc_cellheight;
892 1.1 tsutsui
893 1.1 tsutsui (void)nwb225_rop_hwrite(dc, cell, 1, 0, 0, dc->dc_cellwidth,
894 1.1 tsutsui dc->dc_cellheight, x, y, foreground, background);
895 1.1 tsutsui }
896 1.1 tsutsui
897 1.1 tsutsui static void
898 1.1 tsutsui fbbm_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
899 1.1 tsutsui {
900 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
901 1.1 tsutsui int sx, dx, y, width;
902 1.1 tsutsui
903 1.1 tsutsui if (ncols <= 0 || row < 0 || row >= dc->dc_nrows)
904 1.1 tsutsui return;
905 1.1 tsutsui if (srccol < 0 || dstcol < 0 || srccol + ncols > dc->dc_ncols ||
906 1.1 tsutsui dstcol + ncols > dc->dc_ncols)
907 1.1 tsutsui return;
908 1.1 tsutsui if (srccol == dstcol)
909 1.1 tsutsui return;
910 1.1 tsutsui
911 1.1 tsutsui sx = dc->dc_xorigin + srccol * dc->dc_cellwidth;
912 1.1 tsutsui dx = dc->dc_xorigin + dstcol * dc->dc_cellwidth;
913 1.1 tsutsui y = dc->dc_yorigin + row * dc->dc_cellheight;
914 1.1 tsutsui width = ncols * dc->dc_cellwidth;
915 1.1 tsutsui (void)nwb225_rop_copy_rect(dc, sx, y, width, dc->dc_cellheight,
916 1.1 tsutsui dx, y, NWB225_ROP_LF_S);
917 1.1 tsutsui }
918 1.1 tsutsui
919 1.1 tsutsui static void
920 1.1 tsutsui fbbm_erasecols(void *cookie, int row, int col, int ncols, long attr)
921 1.1 tsutsui {
922 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
923 1.1 tsutsui uint32_t background;
924 1.1 tsutsui int x, y, width;
925 1.1 tsutsui
926 1.1 tsutsui if (ncols <= 0 || row < 0 || row >= dc->dc_nrows)
927 1.1 tsutsui return;
928 1.1 tsutsui if (col < 0 || col + ncols > dc->dc_ncols)
929 1.1 tsutsui return;
930 1.1 tsutsui
931 1.1 tsutsui x = dc->dc_xorigin + col * dc->dc_cellwidth;
932 1.1 tsutsui y = dc->dc_yorigin + row * dc->dc_cellheight;
933 1.1 tsutsui width = ncols * dc->dc_cellwidth;
934 1.1 tsutsui background = fbbm_attr_background(dc, attr);
935 1.1 tsutsui (void)nwb225_rop_fill_rect(dc, x, y, width, dc->dc_cellheight,
936 1.1 tsutsui background);
937 1.1 tsutsui }
938 1.1 tsutsui
939 1.1 tsutsui static void
940 1.1 tsutsui fbbm_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
941 1.1 tsutsui {
942 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
943 1.1 tsutsui int x, sy, dy, height;
944 1.1 tsutsui
945 1.1 tsutsui if (nrows <= 0 || srcrow < 0 || dstrow < 0 ||
946 1.1 tsutsui srcrow + nrows > dc->dc_nrows || dstrow + nrows > dc->dc_nrows)
947 1.1 tsutsui return;
948 1.1 tsutsui if (srcrow == dstrow)
949 1.1 tsutsui return;
950 1.1 tsutsui
951 1.1 tsutsui x = dc->dc_xorigin;
952 1.1 tsutsui sy = dc->dc_yorigin + srcrow * dc->dc_cellheight;
953 1.1 tsutsui dy = dc->dc_yorigin + dstrow * dc->dc_cellheight;
954 1.1 tsutsui height = nrows * dc->dc_cellheight;
955 1.1 tsutsui (void)nwb225_rop_copy_rect(dc, x, sy,
956 1.1 tsutsui dc->dc_ncols * dc->dc_cellwidth, height, x, dy, NWB225_ROP_LF_S);
957 1.1 tsutsui }
958 1.1 tsutsui
959 1.1 tsutsui static void
960 1.1 tsutsui fbbm_eraserows(void *cookie, int row, int nrows, long attr)
961 1.1 tsutsui {
962 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
963 1.1 tsutsui uint32_t background;
964 1.1 tsutsui int x, y, height;
965 1.1 tsutsui
966 1.1 tsutsui if (nrows <= 0 || row < 0 || row + nrows > dc->dc_nrows)
967 1.1 tsutsui return;
968 1.1 tsutsui
969 1.1 tsutsui x = dc->dc_xorigin;
970 1.1 tsutsui y = dc->dc_yorigin + row * dc->dc_cellheight;
971 1.1 tsutsui height = nrows * dc->dc_cellheight;
972 1.1 tsutsui background = fbbm_attr_background(dc, attr);
973 1.1 tsutsui (void)nwb225_rop_fill_rect(dc, x, y,
974 1.1 tsutsui dc->dc_ncols * dc->dc_cellwidth, height, background);
975 1.1 tsutsui }
976 1.1 tsutsui
977 1.1 tsutsui static int
978 1.1 tsutsui fbbm_allocattr(void *cookie, int fg, int bg, int flags, long *attrp)
979 1.1 tsutsui {
980 1.1 tsutsui
981 1.1 tsutsui if ((flags & ~WSATTR_REVERSE) != 0)
982 1.1 tsutsui return EINVAL;
983 1.1 tsutsui
984 1.1 tsutsui *attrp = flags & WSATTR_REVERSE;
985 1.1 tsutsui return 0;
986 1.1 tsutsui }
987 1.1 tsutsui
988 1.1 tsutsui /*
989 1.1 tsutsui * wsdisplay_accessops functions
990 1.1 tsutsui */
991 1.1 tsutsui static int
992 1.1 tsutsui fbbm_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
993 1.1 tsutsui {
994 1.1 tsutsui struct fbbm_softc *sc = v;
995 1.1 tsutsui struct fbbm_devconfig *dc = sc->sc_dc;
996 1.1 tsutsui struct wsdisplay_fbinfo *fbinfo;
997 1.1 tsutsui
998 1.1 tsutsui switch (cmd) {
999 1.1 tsutsui case WSDISPLAYIO_GTYPE:
1000 1.1 tsutsui *(u_int *)data = WSDISPLAY_TYPE_NWB225;
1001 1.1 tsutsui return 0;
1002 1.1 tsutsui
1003 1.1 tsutsui case WSDISPLAYIO_GINFO:
1004 1.1 tsutsui fbinfo = data;
1005 1.1 tsutsui fbinfo->height = dc->dc_height;
1006 1.1 tsutsui fbinfo->width = dc->dc_width;
1007 1.1 tsutsui fbinfo->depth = dc->dc_nplanes;
1008 1.1 tsutsui fbinfo->cmsize = 0;
1009 1.1 tsutsui return 0;
1010 1.1 tsutsui
1011 1.1 tsutsui case WSDISPLAYIO_SMODE:
1012 1.1 tsutsui sc->sc_wsmode = *(int *)data;
1013 1.1 tsutsui return 0;
1014 1.1 tsutsui
1015 1.1 tsutsui default:
1016 1.1 tsutsui break;
1017 1.1 tsutsui }
1018 1.1 tsutsui
1019 1.1 tsutsui return EPASSTHROUGH;
1020 1.1 tsutsui }
1021 1.1 tsutsui
1022 1.1 tsutsui static int
1023 1.1 tsutsui fbbm_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
1024 1.1 tsutsui int *ccolp, int *crowp, long *attrp)
1025 1.1 tsutsui {
1026 1.1 tsutsui struct fbbm_softc *sc = v;
1027 1.1 tsutsui struct fbbm_devconfig *dc = sc->sc_dc;
1028 1.1 tsutsui long attr;
1029 1.1 tsutsui int error;
1030 1.1 tsutsui
1031 1.1 tsutsui KASSERT(type == &dc->dc_wsscrdescr);
1032 1.1 tsutsui
1033 1.1 tsutsui if (sc->sc_nscreens != 0)
1034 1.1 tsutsui return ENOMEM;
1035 1.1 tsutsui
1036 1.1 tsutsui error = fbbm_allocattr(dc, 0, 0, 0, &attr);
1037 1.1 tsutsui if (error != 0)
1038 1.1 tsutsui return error;
1039 1.1 tsutsui
1040 1.1 tsutsui *cookiep = dc;
1041 1.1 tsutsui *ccolp = 0;
1042 1.1 tsutsui *crowp = 0;
1043 1.1 tsutsui *attrp = attr;
1044 1.1 tsutsui sc->sc_nscreens = 1;
1045 1.1 tsutsui
1046 1.1 tsutsui return 0;
1047 1.1 tsutsui }
1048 1.1 tsutsui
1049 1.1 tsutsui static void
1050 1.1 tsutsui fbbm_free_screen(void *v, void *cookie)
1051 1.1 tsutsui {
1052 1.1 tsutsui struct fbbm_softc *sc = v;
1053 1.1 tsutsui
1054 1.1 tsutsui KASSERT(sc->sc_nscreens == 1);
1055 1.1 tsutsui KASSERT(cookie == sc->sc_dc);
1056 1.1 tsutsui KASSERT(sc->sc_dc != &fbbm_console_dc);
1057 1.1 tsutsui sc->sc_nscreens = 0;
1058 1.1 tsutsui }
1059 1.1 tsutsui
1060 1.1 tsutsui static int
1061 1.1 tsutsui fbbm_show_screen(void *v, void *cookie, int waitok,
1062 1.1 tsutsui void (*cb)(void *, int, int), void *cbarg)
1063 1.1 tsutsui {
1064 1.1 tsutsui
1065 1.1 tsutsui return 0;
1066 1.1 tsutsui }
1067 1.1 tsutsui
1068 1.1 tsutsui int
1069 1.1 tsutsui fbbm_cnattach(void)
1070 1.1 tsutsui {
1071 1.1 tsutsui struct fbbm_devconfig *dc;
1072 1.1 tsutsui long attr;
1073 1.1 tsutsui
1074 1.1 tsutsui if (fbbm_console_initialized())
1075 1.1 tsutsui return 0;
1076 1.1 tsutsui
1077 1.1 tsutsui dc = &fbbm_console_dc;
1078 1.1 tsutsui memset(dc, 0, sizeof(*dc));
1079 1.1 tsutsui if (fbbm_probe(NEWS68K_BUS_SPACE_EIO, NWB225_RCONT_BASE) == 0)
1080 1.1 tsutsui return ENXIO;
1081 1.1 tsutsui
1082 1.1 tsutsui if (nwb225_map(dc, NEWS68K_BUS_SPACE_EIO, NWB225_RCONT_BASE) != 0)
1083 1.1 tsutsui goto out_clear;
1084 1.1 tsutsui
1085 1.1 tsutsui if (nwb225_init_hardware(dc) != 0)
1086 1.1 tsutsui goto out_unmap;
1087 1.1 tsutsui
1088 1.1 tsutsui fbbm_init_screen(dc);
1089 1.1 tsutsui if (fbbm_clear_screen(dc) != 0)
1090 1.1 tsutsui goto out_unmap;
1091 1.1 tsutsui
1092 1.1 tsutsui if (fbbm_allocattr(dc, 0, 0, 0, &attr))
1093 1.1 tsutsui goto out_unmap;
1094 1.1 tsutsui
1095 1.1 tsutsui wsdisplay_cnattach(&dc->dc_wsscrdescr, dc, 0, 0, attr);
1096 1.1 tsutsui return 0;
1097 1.1 tsutsui
1098 1.1 tsutsui out_unmap:
1099 1.1 tsutsui nwb225_unmap(dc);
1100 1.1 tsutsui out_clear:
1101 1.1 tsutsui memset(dc, 0, sizeof(*dc));
1102 1.1 tsutsui return 1;
1103 1.1 tsutsui }
1104 1.1 tsutsui /* $NetBSD: fbbm.c,v 1.1 2026/09/20 10:29:11 tsutsui Exp $ */
1105 1.1 tsutsui
1106 1.1 tsutsui /*-
1107 1.1 tsutsui * Copyright (c) 2026 Izumi Tsutsui. All rights reserved.
1108 1.1 tsutsui *
1109 1.1 tsutsui * Redistribution and use in source and binary forms, with or without
1110 1.1 tsutsui * modification, are permitted provided that the following conditions
1111 1.1 tsutsui * are met:
1112 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright
1113 1.1 tsutsui * notice, this list of conditions and the following disclaimer.
1114 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright
1115 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the
1116 1.1 tsutsui * documentation and/or other materials provided with the distribution.
1117 1.1 tsutsui *
1118 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1119 1.1 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1120 1.1 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1121 1.1 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1122 1.1 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1123 1.1 tsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1124 1.1 tsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1125 1.1 tsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1126 1.1 tsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1127 1.1 tsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1128 1.1 tsutsui */
1129 1.1 tsutsui
1130 1.1 tsutsui #include <sys/cdefs.h>
1131 1.1 tsutsui __KERNEL_RCSID(0, "$NetBSD: fbbm.c,v 1.1 2026/09/20 10:29:11 tsutsui Exp $");
1132 1.1 tsutsui
1133 1.1 tsutsui #include <sys/param.h>
1134 1.1 tsutsui #include <sys/device.h>
1135 1.1 tsutsui #include <sys/errno.h>
1136 1.1 tsutsui #include <sys/ioctl.h>
1137 1.1 tsutsui #include <sys/kmem.h>
1138 1.1 tsutsui #include <sys/systm.h>
1139 1.1 tsutsui
1140 1.1 tsutsui #include <machine/bus.h>
1141 1.1 tsutsui
1142 1.1 tsutsui #include <news68k/dev/hbvar.h>
1143 1.1 tsutsui #include <news68k/dev/nwb225reg.h>
1144 1.1 tsutsui
1145 1.1 tsutsui #include <dev/wscons/wsconsio.h>
1146 1.1 tsutsui #include <dev/wscons/wsdisplayvar.h>
1147 1.1 tsutsui
1148 1.1 tsutsui #define NWB225_WAIT_MAX 100000
1149 1.1 tsutsui
1150 1.1 tsutsui struct fbbm_devconfig {
1151 1.1 tsutsui bus_space_tag_t dc_bst;
1152 1.1 tsutsui bus_space_handle_t dc_rcont_bsh;
1153 1.1 tsutsui bus_space_handle_t dc_krom_bsh;
1154 1.1 tsutsui
1155 1.1 tsutsui int dc_nplanes;
1156 1.1 tsutsui uint32_t dc_planemask;
1157 1.1 tsutsui int dc_dispver;
1158 1.1 tsutsui
1159 1.1 tsutsui int dc_fbwidth;
1160 1.1 tsutsui int dc_fbheight;
1161 1.1 tsutsui int dc_width;
1162 1.1 tsutsui int dc_height;
1163 1.1 tsutsui
1164 1.1 tsutsui int dc_fontwidth;
1165 1.1 tsutsui int dc_fontheight;
1166 1.1 tsutsui int dc_cellwidth;
1167 1.1 tsutsui int dc_cellheight;
1168 1.1 tsutsui
1169 1.1 tsutsui int dc_ncols;
1170 1.1 tsutsui int dc_nrows;
1171 1.1 tsutsui int dc_xorigin;
1172 1.1 tsutsui int dc_yorigin;
1173 1.1 tsutsui
1174 1.1 tsutsui int dc_cursoron;
1175 1.1 tsutsui int dc_cursorrow;
1176 1.1 tsutsui int dc_cursorcol;
1177 1.1 tsutsui
1178 1.1 tsutsui struct wsscreen_descr dc_wsscrdescr;
1179 1.1 tsutsui };
1180 1.1 tsutsui
1181 1.1 tsutsui struct fbbm_softc {
1182 1.1 tsutsui device_t sc_dev;
1183 1.1 tsutsui struct fbbm_devconfig *sc_dc;
1184 1.1 tsutsui int sc_nscreens;
1185 1.1 tsutsui const struct wsscreen_descr *sc_scrdescs[1];
1186 1.1 tsutsui struct wsscreen_list sc_scrlist;
1187 1.1 tsutsui };
1188 1.1 tsutsui
1189 1.1 tsutsui static int fbbm_match(device_t, cfdata_t, void *);
1190 1.1 tsutsui static void fbbm_attach(device_t, device_t, void *);
1191 1.1 tsutsui
1192 1.1 tsutsui static int nwb225_map(struct fbbm_devconfig *, bus_space_tag_t, bus_addr_t);
1193 1.1 tsutsui static void nwb225_unmap(struct fbbm_devconfig *);
1194 1.1 tsutsui static void nwb225_rop_reset(struct fbbm_devconfig *);
1195 1.1 tsutsui static int nwb225_rop_wait(struct fbbm_devconfig *);
1196 1.1 tsutsui static void nwb225_ctl_write(struct fbbm_devconfig *, uint16_t, uint16_t);
1197 1.1 tsutsui static void nwb225_rop_set_plane_mask(struct fbbm_devconfig *, uint32_t);
1198 1.1 tsutsui static void nwb225_rop_make_funcvec(struct fbbm_devconfig *, unsigned int,
1199 1.1 tsutsui uint32_t, uint32_t, uint8_t *);
1200 1.1 tsutsui static void nwb225_rop_setfunc(struct fbbm_devconfig *, const uint8_t *);
1201 1.1 tsutsui static void nwb225_rop_cinit(struct fbbm_devconfig *, const uint8_t *,
1202 1.1 tsutsui uint32_t, unsigned int);
1203 1.1 tsutsui static int nwb225_rop_copy_rect(struct fbbm_devconfig *, int, int, int, int,
1204 1.1 tsutsui int, int, unsigned int);
1205 1.1 tsutsui static int nwb225_rop_fill_rect(struct fbbm_devconfig *, int, int, int, int,
1206 1.1 tsutsui uint32_t);
1207 1.1 tsutsui static int nwb225_rop_hwrite(struct fbbm_devconfig *, const uint16_t *, int,
1208 1.1 tsutsui int, int, int, int, int, int, uint32_t, uint32_t);
1209 1.1 tsutsui static bus_size_t nwb225_krom_ascii_offset(unsigned int);
1210 1.1 tsutsui static void nwb225_krom_load_cell(struct fbbm_devconfig *, unsigned int,
1211 1.1 tsutsui uint16_t *);
1212 1.1 tsutsui static int nwb225_init_hardware(struct fbbm_devconfig *);
1213 1.1 tsutsui
1214 1.1 tsutsui static void fbbm_init_screen(struct fbbm_devconfig *);
1215 1.1 tsutsui static int fbbm_clear_screen(struct fbbm_devconfig *);
1216 1.1 tsutsui static void fbbm_cursor(void *, int, int, int);
1217 1.1 tsutsui static int fbbm_mapchar(void *, int, unsigned int *);
1218 1.1 tsutsui static void fbbm_putchar(void *, int, int, u_int, long);
1219 1.1 tsutsui static void fbbm_copycols(void *, int, int, int, int);
1220 1.1 tsutsui static void fbbm_erasecols(void *, int, int, int, long);
1221 1.1 tsutsui static void fbbm_copyrows(void *, int, int, int);
1222 1.1 tsutsui static void fbbm_eraserows(void *, int, int, long);
1223 1.1 tsutsui static int fbbm_allocattr(void *, int, int, int, long *);
1224 1.1 tsutsui static int fbbm_ioctl(void *, void *, u_long, void *, int, struct lwp *);
1225 1.1 tsutsui static int fbbm_alloc_screen(void *, const struct wsscreen_descr *, void **,
1226 1.1 tsutsui int *, int *, long *);
1227 1.1 tsutsui static void fbbm_free_screen(void *, void *);
1228 1.1 tsutsui static int fbbm_show_screen(void *, void *, int, void (*)(void *, int, int),
1229 1.1 tsutsui void *);
1230 1.1 tsutsui
1231 1.1 tsutsui CFATTACH_DECL_NEW(fbbm, sizeof(struct fbbm_softc),
1232 1.1 tsutsui fbbm_match, fbbm_attach, NULL, NULL);
1233 1.1 tsutsui
1234 1.1 tsutsui static const struct wsdisplay_emulops fbbm_emulops = {
1235 1.1 tsutsui .cursor = fbbm_cursor,
1236 1.1 tsutsui .mapchar = fbbm_mapchar,
1237 1.1 tsutsui .putchar = fbbm_putchar,
1238 1.1 tsutsui .copycols = fbbm_copycols,
1239 1.1 tsutsui .erasecols = fbbm_erasecols,
1240 1.1 tsutsui .copyrows = fbbm_copyrows,
1241 1.1 tsutsui .eraserows = fbbm_eraserows,
1242 1.1 tsutsui .allocattr = fbbm_allocattr,
1243 1.1 tsutsui .replaceattr = NULL,
1244 1.1 tsutsui };
1245 1.1 tsutsui
1246 1.1 tsutsui static const struct wsdisplay_accessops fbbm_accessops = {
1247 1.1 tsutsui .ioctl = fbbm_ioctl,
1248 1.1 tsutsui .mmap = NULL,
1249 1.1 tsutsui .alloc_screen = fbbm_alloc_screen,
1250 1.1 tsutsui .free_screen = fbbm_free_screen,
1251 1.1 tsutsui .show_screen = fbbm_show_screen,
1252 1.1 tsutsui .load_font = NULL,
1253 1.1 tsutsui .pollc = NULL,
1254 1.1 tsutsui .scroll = NULL,
1255 1.1 tsutsui };
1256 1.1 tsutsui
1257 1.1 tsutsui /* Sony FBBM logical Boolean functions used by the initial text backend. */
1258 1.1 tsutsui #define NWB225_BF_0 0x0
1259 1.1 tsutsui #define NWB225_BF_S 0x3
1260 1.1 tsutsui #define NWB225_BF_DI 0xa
1261 1.1 tsutsui #define NWB225_BF_1 0xf
1262 1.1 tsutsui
1263 1.1 tsutsui /*
1264 1.1 tsutsui * Logical FBBM function to 51X hardware function conversion recovered from
1265 1.1 tsutsui * NEWS-OS fbbm_51x.o.
1266 1.1 tsutsui */
1267 1.1 tsutsui static const uint8_t nwb225_fccnvtab[16] = {
1268 1.1 tsutsui 0x03, 0x0b, 0x07, 0x0f, 0x02, 0x0a, 0x06, 0x0e,
1269 1.1 tsutsui 0x01, 0x09, 0x05, 0x0d, 0x00, 0x08, 0x04, 0x0c,
1270 1.1 tsutsui };
1271 1.1 tsutsui
1272 1.1 tsutsui /*
1273 1.1 tsutsui * Function conversion for a constant 0/1 source, indexed by
1274 1.1 tsutsui * [logical_function][source_bit].
1275 1.1 tsutsui */
1276 1.1 tsutsui static const uint8_t nwb225_func01tab[16][2] = {
1277 1.1 tsutsui { 0x03, 0x03 }, { 0x03, 0x0a }, { 0x03, 0x05 }, { 0x03, 0x0c },
1278 1.1 tsutsui { 0x0a, 0x03 }, { 0x0a, 0x0a }, { 0x0a, 0x05 }, { 0x0a, 0x0c },
1279 1.1 tsutsui { 0x05, 0x03 }, { 0x05, 0x0a }, { 0x05, 0x05 }, { 0x05, 0x0c },
1280 1.1 tsutsui { 0x0c, 0x03 }, { 0x0c, 0x0a }, { 0x0c, 0x05 }, { 0x0c, 0x0c },
1281 1.1 tsutsui };
1282 1.1 tsutsui
1283 1.1 tsutsui /*
1284 1.1 tsutsui * Fixed initialization words written by the NWS-1750 PROM and NEWS-OS
1285 1.1 tsutsui * 51X setup. Their individual timing/control semantics are intentionally
1286 1.1 tsutsui * not inferred here.
1287 1.1 tsutsui */
1288 1.1 tsutsui static const uint16_t nwb225_init_words[] = {
1289 1.1 tsutsui 0x0400, 0x0002, 0x0005, 0x00d8,
1290 1.1 tsutsui 0x0000, 0x0006, 0x0000,
1291 1.1 tsutsui };
1292 1.1 tsutsui
1293 1.1 tsutsui /*
1294 1.1 tsutsui * 4-bit component values from the NWS-1750 PROM NWB-225 module. The PROM
1295 1.1 tsutsui * repeats this 16-entry table through all 256 palette indices and writes
1296 1.1 tsutsui * each component after shifting it left by four bits.
1297 1.1 tsutsui */
1298 1.1 tsutsui static const uint8_t nwb225_prom_palette[16][3] = {
1299 1.1 tsutsui { 0, 0, 0 }, { 0, 0, 4 },
1300 1.1 tsutsui { 0, 4, 0 }, { 0, 4, 4 },
1301 1.1 tsutsui { 4, 0, 0 }, { 4, 0, 4 },
1302 1.1 tsutsui { 4, 4, 0 }, { 4, 4, 4 },
1303 1.1 tsutsui { 8, 8, 8 }, { 0, 0, 15 },
1304 1.1 tsutsui { 0, 15, 0 }, { 0, 15, 15 },
1305 1.1 tsutsui { 15, 0, 0 }, { 15, 0, 15 },
1306 1.1 tsutsui { 15, 15, 0 }, { 15, 15, 15 },
1307 1.1 tsutsui };
1308 1.1 tsutsui
1309 1.1 tsutsui static int
1310 1.1 tsutsui fbbm_match(device_t parent, cfdata_t cf, void *aux)
1311 1.1 tsutsui {
1312 1.1 tsutsui struct hb_attach_args *ha = aux;
1313 1.1 tsutsui bus_space_handle_t bsh;
1314 1.1 tsutsui int rv;
1315 1.1 tsutsui
1316 1.1 tsutsui __USE(parent);
1317 1.1 tsutsui __USE(cf);
1318 1.1 tsutsui
1319 1.1 tsutsui if (strcmp(ha->ha_name, "fbbm") != 0)
1320 1.1 tsutsui return 0;
1321 1.1 tsutsui if (ha->ha_address != NWB225_RCONT_BASE)
1322 1.1 tsutsui return 0;
1323 1.1 tsutsui
1324 1.1 tsutsui if (bus_space_map(ha->ha_bust, ha->ha_address, NWB225_RCONT_SIZE,
1325 1.1 tsutsui 0, &bsh) != 0)
1326 1.1 tsutsui return 0;
1327 1.1 tsutsui
1328 1.1 tsutsui /* NEWS-OS fb225_probe() used a byte-sized badaddr() at this base. */
1329 1.1 tsutsui rv = news68k_bus_space_probe(ha->ha_bust, bsh, 0, 1);
1330 1.1 tsutsui bus_space_unmap(ha->ha_bust, bsh, NWB225_RCONT_SIZE);
1331 1.1 tsutsui
1332 1.1 tsutsui return rv;
1333 1.1 tsutsui }
1334 1.1 tsutsui
1335 1.1 tsutsui static void
1336 1.1 tsutsui fbbm_attach(device_t parent, device_t self, void *aux)
1337 1.1 tsutsui {
1338 1.1 tsutsui struct fbbm_softc *sc = device_private(self);
1339 1.1 tsutsui struct hb_attach_args *ha = aux;
1340 1.1 tsutsui struct fbbm_devconfig *dc;
1341 1.1 tsutsui struct wsemuldisplaydev_attach_args waa;
1342 1.1 tsutsui int error;
1343 1.1 tsutsui
1344 1.1 tsutsui __USE(parent);
1345 1.1 tsutsui
1346 1.1 tsutsui sc->sc_dev = self;
1347 1.1 tsutsui
1348 1.1 tsutsui dc = kmem_zalloc(sizeof(*dc), KM_SLEEP);
1349 1.1 tsutsui error = nwb225_map(dc, ha->ha_bust, ha->ha_address);
1350 1.1 tsutsui if (error != 0) {
1351 1.1 tsutsui aprint_error_dev(self, "unable to map device registers: %d\n",
1352 1.1 tsutsui error);
1353 1.1 tsutsui kmem_free(dc, sizeof(*dc));
1354 1.1 tsutsui return;
1355 1.1 tsutsui }
1356 1.1 tsutsui
1357 1.1 tsutsui error = nwb225_init_hardware(dc);
1358 1.1 tsutsui if (error != 0) {
1359 1.1 tsutsui aprint_error_dev(self, "controller initialization failed: %d\n",
1360 1.1 tsutsui error);
1361 1.1 tsutsui nwb225_unmap(dc);
1362 1.1 tsutsui kmem_free(dc, sizeof(*dc));
1363 1.1 tsutsui return;
1364 1.1 tsutsui }
1365 1.1 tsutsui
1366 1.1 tsutsui fbbm_init_screen(dc);
1367 1.1 tsutsui error = fbbm_clear_screen(dc);
1368 1.1 tsutsui if (error != 0) {
1369 1.1 tsutsui aprint_error_dev(self, "unable to clear text screen: %d\n", error);
1370 1.1 tsutsui nwb225_unmap(dc);
1371 1.1 tsutsui kmem_free(dc, sizeof(*dc));
1372 1.1 tsutsui return;
1373 1.1 tsutsui }
1374 1.1 tsutsui
1375 1.1 tsutsui sc->sc_dc = dc;
1376 1.1 tsutsui sc->sc_nscreens = 0;
1377 1.1 tsutsui sc->sc_scrdescs[0] = &dc->dc_wsscrdescr;
1378 1.1 tsutsui sc->sc_scrlist.nscreens = __arraycount(sc->sc_scrdescs);
1379 1.1 tsutsui sc->sc_scrlist.screens = sc->sc_scrdescs;
1380 1.1 tsutsui
1381 1.1 tsutsui aprint_normal(": NWB-225 compatible, %d x %d, %d planes, "
1382 1.1 tsutsui "display version %d\n", dc->dc_width, dc->dc_height,
1383 1.1 tsutsui dc->dc_nplanes, dc->dc_dispver);
1384 1.1 tsutsui
1385 1.1 tsutsui waa.console = 0;
1386 1.1 tsutsui waa.scrdata = &sc->sc_scrlist;
1387 1.1 tsutsui waa.accessops = &fbbm_accessops;
1388 1.1 tsutsui waa.accesscookie = sc;
1389 1.1 tsutsui
1390 1.1 tsutsui config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE);
1391 1.1 tsutsui }
1392 1.1 tsutsui
1393 1.1 tsutsui static int
1394 1.1 tsutsui nwb225_map(struct fbbm_devconfig *dc, bus_space_tag_t bst,
1395 1.1 tsutsui bus_addr_t rcont_addr)
1396 1.1 tsutsui {
1397 1.1 tsutsui int error;
1398 1.1 tsutsui
1399 1.1 tsutsui dc->dc_bst = bst;
1400 1.1 tsutsui
1401 1.1 tsutsui error = bus_space_map(bst, rcont_addr, NWB225_RCONT_SIZE, 0,
1402 1.1 tsutsui &dc->dc_rcont_bsh);
1403 1.1 tsutsui if (error != 0)
1404 1.1 tsutsui return error;
1405 1.1 tsutsui
1406 1.1 tsutsui error = bus_space_map(bst, NWB225_KROM_BASE, NWB225_KROM_SIZE, 0,
1407 1.1 tsutsui &dc->dc_krom_bsh);
1408 1.1 tsutsui if (error != 0) {
1409 1.1 tsutsui bus_space_unmap(bst, dc->dc_rcont_bsh, NWB225_RCONT_SIZE);
1410 1.1 tsutsui return error;
1411 1.1 tsutsui }
1412 1.1 tsutsui
1413 1.1 tsutsui return 0;
1414 1.1 tsutsui }
1415 1.1 tsutsui
1416 1.1 tsutsui static void
1417 1.1 tsutsui nwb225_unmap(struct fbbm_devconfig *dc)
1418 1.1 tsutsui {
1419 1.1 tsutsui
1420 1.1 tsutsui bus_space_unmap(dc->dc_bst, dc->dc_krom_bsh, NWB225_KROM_SIZE);
1421 1.1 tsutsui bus_space_unmap(dc->dc_bst, dc->dc_rcont_bsh, NWB225_RCONT_SIZE);
1422 1.1 tsutsui }
1423 1.1 tsutsui
1424 1.1 tsutsui static void
1425 1.1 tsutsui nwb225_rop_reset(struct fbbm_devconfig *dc)
1426 1.1 tsutsui {
1427 1.1 tsutsui
1428 1.1 tsutsui /* fb51X_rop_reset() and the PROM both perform this 0 -> 1 sequence. */
1429 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh, NWB225_STATUS, 0);
1430 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh, NWB225_STATUS, 1);
1431 1.1 tsutsui }
1432 1.1 tsutsui
1433 1.1 tsutsui static int
1434 1.1 tsutsui nwb225_rop_wait(struct fbbm_devconfig *dc)
1435 1.1 tsutsui {
1436 1.1 tsutsui uint16_t status;
1437 1.1 tsutsui int i;
1438 1.1 tsutsui
1439 1.1 tsutsui for (i = 0; i < NWB225_WAIT_MAX; i++) {
1440 1.1 tsutsui status = bus_space_read_2(dc->dc_bst, dc->dc_rcont_bsh,
1441 1.1 tsutsui NWB225_STATUS);
1442 1.1 tsutsui if ((status & NWB225_STATUS_BUSY) == 0)
1443 1.1 tsutsui return 0;
1444 1.1 tsutsui }
1445 1.1 tsutsui
1446 1.1 tsutsui /* Match the NEWS-OS recovery action, but report failure to K1 attach. */
1447 1.1 tsutsui nwb225_rop_reset(dc);
1448 1.1 tsutsui return ETIMEDOUT;
1449 1.1 tsutsui }
1450 1.1 tsutsui
1451 1.1 tsutsui static void
1452 1.1 tsutsui nwb225_ctl_write(struct fbbm_devconfig *dc, uint16_t selector,
1453 1.1 tsutsui uint16_t value)
1454 1.1 tsutsui {
1455 1.1 tsutsui
1456 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1457 1.1 tsutsui NWB225_CTL_SELECT, selector);
1458 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1459 1.1 tsutsui NWB225_CTL_DATA, value);
1460 1.1 tsutsui }
1461 1.1 tsutsui
1462 1.1 tsutsui static void
1463 1.1 tsutsui nwb225_rop_set_plane_mask(struct fbbm_devconfig *dc, uint32_t planemask)
1464 1.1 tsutsui {
1465 1.1 tsutsui uint16_t hwmask;
1466 1.1 tsutsui
1467 1.1 tsutsui hwmask = (uint16_t)(~(planemask << 8) & 0xff00);
1468 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1469 1.1 tsutsui NWB225_PLANE_CTRL, hwmask);
1470 1.1 tsutsui }
1471 1.1 tsutsui
1472 1.1 tsutsui static void
1473 1.1 tsutsui nwb225_rop_make_funcvec(struct fbbm_devconfig *dc, unsigned int func,
1474 1.1 tsutsui uint32_t fore, uint32_t aux, uint8_t *funcvec)
1475 1.1 tsutsui {
1476 1.1 tsutsui uint8_t tmp[4];
1477 1.1 tsutsui unsigned int i, index;
1478 1.1 tsutsui
1479 1.1 tsutsui func &= 0x0f;
1480 1.1 tsutsui tmp[0] = (func & 0x0c) | (func >> 2);
1481 1.1 tsutsui tmp[1] = (func >> 2) | ((func << 2) & 0x0c);
1482 1.1 tsutsui tmp[2] = func;
1483 1.1 tsutsui tmp[3] = ((func << 2) & 0x0c) | (func & 0x03);
1484 1.1 tsutsui
1485 1.1 tsutsui for (i = 0; i < (unsigned int)dc->dc_nplanes; i++) {
1486 1.1 tsutsui index = ((fore & 1) << 1) | (aux & 1);
1487 1.1 tsutsui funcvec[i] = tmp[index];
1488 1.1 tsutsui fore >>= 1;
1489 1.1 tsutsui aux >>= 1;
1490 1.1 tsutsui }
1491 1.1 tsutsui }
1492 1.1 tsutsui
1493 1.1 tsutsui static void
1494 1.1 tsutsui nwb225_rop_setfunc(struct fbbm_devconfig *dc, const uint8_t *funcvec)
1495 1.1 tsutsui {
1496 1.1 tsutsui unsigned int i;
1497 1.1 tsutsui
1498 1.1 tsutsui for (i = 0; i < (unsigned int)dc->dc_nplanes; i++)
1499 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1500 1.1 tsutsui NWB225_ROP_FUNC + i * sizeof(uint16_t),
1501 1.1 tsutsui nwb225_fccnvtab[funcvec[i] & 0x0f]);
1502 1.1 tsutsui }
1503 1.1 tsutsui
1504 1.1 tsutsui static void
1505 1.1 tsutsui nwb225_rop_cinit(struct fbbm_devconfig *dc, const uint8_t *funcvec,
1506 1.1 tsutsui uint32_t planemask, unsigned int source_bit)
1507 1.1 tsutsui {
1508 1.1 tsutsui unsigned int i;
1509 1.1 tsutsui
1510 1.1 tsutsui nwb225_rop_set_plane_mask(dc, planemask);
1511 1.1 tsutsui source_bit &= 1;
1512 1.1 tsutsui for (i = 0; i < (unsigned int)dc->dc_nplanes; i++)
1513 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1514 1.1 tsutsui NWB225_ROP_FUNC + i * sizeof(uint16_t),
1515 1.1 tsutsui nwb225_func01tab[funcvec[i] & 0x0f][source_bit]);
1516 1.1 tsutsui }
1517 1.1 tsutsui
1518 1.1 tsutsui static int
1519 1.1 tsutsui nwb225_rect_valid(struct fbbm_devconfig *dc, int x, int y, int width,
1520 1.1 tsutsui int height)
1521 1.1 tsutsui {
1522 1.1 tsutsui
1523 1.1 tsutsui if (x < 0 || y < 0 || width <= 0 || height <= 0)
1524 1.1 tsutsui return 0;
1525 1.1 tsutsui if (x >= dc->dc_fbwidth || y >= dc->dc_fbheight)
1526 1.1 tsutsui return 0;
1527 1.1 tsutsui if (width > dc->dc_fbwidth - x || height > dc->dc_fbheight - y)
1528 1.1 tsutsui return 0;
1529 1.1 tsutsui
1530 1.1 tsutsui return 1;
1531 1.1 tsutsui }
1532 1.1 tsutsui
1533 1.1 tsutsui static int
1534 1.1 tsutsui nwb225_rop_copy_rect(struct fbbm_devconfig *dc, int sx, int sy, int width,
1535 1.1 tsutsui int height, int dx, int dy, unsigned int func)
1536 1.1 tsutsui {
1537 1.1 tsutsui uint8_t funcvec[8];
1538 1.1 tsutsui bus_size_t command;
1539 1.1 tsutsui int error;
1540 1.1 tsutsui
1541 1.1 tsutsui if (width <= 0 || height <= 0)
1542 1.1 tsutsui return 0;
1543 1.1 tsutsui if (nwb225_rect_valid(dc, sx, sy, width, height) == 0 ||
1544 1.1 tsutsui nwb225_rect_valid(dc, dx, dy, width, height) == 0)
1545 1.1 tsutsui return EINVAL;
1546 1.1 tsutsui
1547 1.1 tsutsui error = nwb225_rop_wait(dc);
1548 1.1 tsutsui if (error != 0)
1549 1.1 tsutsui return error;
1550 1.1 tsutsui
1551 1.1 tsutsui nwb225_rop_make_funcvec(dc, func, dc->dc_planemask, 0, funcvec);
1552 1.1 tsutsui nwb225_rop_setfunc(dc, funcvec);
1553 1.1 tsutsui nwb225_rop_set_plane_mask(dc, dc->dc_planemask);
1554 1.1 tsutsui
1555 1.1 tsutsui if (sx >= dx) {
1556 1.1 tsutsui if (sy >= dy) {
1557 1.1 tsutsui command = NWB225_ROP_COPY_FF;
1558 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1559 1.1 tsutsui command, 0);
1560 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1561 1.1 tsutsui NWB225_DST_X + dy * sizeof(uint16_t), dx);
1562 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1563 1.1 tsutsui NWB225_SRC_X + sy * sizeof(uint16_t), sx);
1564 1.1 tsutsui } else {
1565 1.1 tsutsui command = NWB225_ROP_COPY_FR;
1566 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1567 1.1 tsutsui command, 0);
1568 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1569 1.1 tsutsui NWB225_DST_X + (dy + height - 1) *
1570 1.1 tsutsui sizeof(uint16_t), dx);
1571 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1572 1.1 tsutsui NWB225_SRC_X + (sy + height - 1) *
1573 1.1 tsutsui sizeof(uint16_t), sx);
1574 1.1 tsutsui }
1575 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1576 1.1 tsutsui NWB225_ROP_EDGE + (height - 1) * sizeof(uint16_t),
1577 1.1 tsutsui dx + width);
1578 1.1 tsutsui } else {
1579 1.1 tsutsui if (sy >= dy) {
1580 1.1 tsutsui command = NWB225_ROP_COPY_RF;
1581 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1582 1.1 tsutsui command, 0);
1583 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1584 1.1 tsutsui NWB225_DST_X + dy * sizeof(uint16_t), dx + width);
1585 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1586 1.1 tsutsui NWB225_SRC_X + sy * sizeof(uint16_t), sx + width);
1587 1.1 tsutsui } else {
1588 1.1 tsutsui command = NWB225_ROP_COPY_RR;
1589 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1590 1.1 tsutsui command, 0);
1591 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1592 1.1 tsutsui NWB225_DST_X + (dy + height - 1) *
1593 1.1 tsutsui sizeof(uint16_t), dx + width);
1594 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1595 1.1 tsutsui NWB225_SRC_X + (sy + height - 1) *
1596 1.1 tsutsui sizeof(uint16_t), sx + width);
1597 1.1 tsutsui }
1598 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1599 1.1 tsutsui NWB225_ROP_EDGE + (height - 1) * sizeof(uint16_t), dx);
1600 1.1 tsutsui }
1601 1.1 tsutsui
1602 1.1 tsutsui return nwb225_rop_wait(dc);
1603 1.1 tsutsui }
1604 1.1 tsutsui
1605 1.1 tsutsui static int
1606 1.1 tsutsui nwb225_rop_fill_rect(struct fbbm_devconfig *dc, int x, int y, int width,
1607 1.1 tsutsui int height, uint32_t color)
1608 1.1 tsutsui {
1609 1.1 tsutsui uint8_t funcvec[8];
1610 1.1 tsutsui int error;
1611 1.1 tsutsui
1612 1.1 tsutsui if (width <= 0 || height <= 0)
1613 1.1 tsutsui return 0;
1614 1.1 tsutsui if (nwb225_rect_valid(dc, x, y, width, height) == 0)
1615 1.1 tsutsui return EINVAL;
1616 1.1 tsutsui
1617 1.1 tsutsui error = nwb225_rop_wait(dc);
1618 1.1 tsutsui if (error != 0)
1619 1.1 tsutsui return error;
1620 1.1 tsutsui
1621 1.1 tsutsui color &= dc->dc_planemask;
1622 1.1 tsutsui nwb225_rop_make_funcvec(dc, NWB225_BF_S, color, 0, funcvec);
1623 1.1 tsutsui nwb225_rop_cinit(dc, funcvec, dc->dc_planemask, 1);
1624 1.1 tsutsui
1625 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1626 1.1 tsutsui NWB225_ROP_CLEAR, 0);
1627 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh, NWB225_DST_X, 0);
1628 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh, NWB225_SRC_X, 0);
1629 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1630 1.1 tsutsui NWB225_DST_X + y * sizeof(uint16_t), x);
1631 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1632 1.1 tsutsui NWB225_ROP_EDGE + (height - 1) * sizeof(uint16_t), x + width);
1633 1.1 tsutsui
1634 1.1 tsutsui return nwb225_rop_wait(dc);
1635 1.1 tsutsui }
1636 1.1 tsutsui
1637 1.1 tsutsui static int
1638 1.1 tsutsui nwb225_rop_hwrite(struct fbbm_devconfig *dc, const uint16_t *src,
1639 1.1 tsutsui int srcwidth, int srcx, int srcy, int width, int height, int dx, int dy,
1640 1.1 tsutsui uint32_t foreground, uint32_t background)
1641 1.1 tsutsui {
1642 1.1 tsutsui uint8_t funcvec[8];
1643 1.1 tsutsui const uint16_t *sp;
1644 1.1 tsutsui int nwords, skip, row, word, error;
1645 1.1 tsutsui
1646 1.1 tsutsui if (src == NULL || srcwidth <= 0 || srcx < 0 || srcy < 0 ||
1647 1.1 tsutsui width <= 0 || height <= 0)
1648 1.1 tsutsui return EINVAL;
1649 1.1 tsutsui if (nwb225_rect_valid(dc, dx, dy, width, height) == 0)
1650 1.1 tsutsui return EINVAL;
1651 1.1 tsutsui
1652 1.1 tsutsui nwords = ((srcx & 15) + width + 15) >> 4;
1653 1.1 tsutsui if ((srcx >> 4) + nwords > srcwidth)
1654 1.1 tsutsui return EINVAL;
1655 1.1 tsutsui
1656 1.1 tsutsui error = nwb225_rop_wait(dc);
1657 1.1 tsutsui if (error != 0)
1658 1.1 tsutsui return error;
1659 1.1 tsutsui
1660 1.1 tsutsui foreground &= dc->dc_planemask;
1661 1.1 tsutsui background &= dc->dc_planemask;
1662 1.1 tsutsui nwb225_rop_make_funcvec(dc, NWB225_BF_S, foreground, background,
1663 1.1 tsutsui funcvec);
1664 1.1 tsutsui nwb225_rop_setfunc(dc, funcvec);
1665 1.1 tsutsui nwb225_rop_set_plane_mask(dc, dc->dc_planemask);
1666 1.1 tsutsui
1667 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1668 1.1 tsutsui NWB225_DST_X + dy * sizeof(uint16_t), dx);
1669 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1670 1.1 tsutsui NWB225_SRC_X, srcx & 15);
1671 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1672 1.1 tsutsui NWB225_HWRITE_EDGE + (height - 1) * sizeof(uint16_t), dx + width);
1673 1.1 tsutsui
1674 1.1 tsutsui sp = src + srcy * srcwidth + (srcx >> 4);
1675 1.1 tsutsui skip = srcwidth - nwords;
1676 1.1 tsutsui for (row = 0; row < height; row++) {
1677 1.1 tsutsui for (word = 0; word < nwords; word++)
1678 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1679 1.1 tsutsui NWB225_HWRITE_DATA, *sp++);
1680 1.1 tsutsui sp += skip;
1681 1.1 tsutsui }
1682 1.1 tsutsui
1683 1.1 tsutsui return nwb225_rop_wait(dc);
1684 1.1 tsutsui }
1685 1.1 tsutsui
1686 1.1 tsutsui static bus_size_t
1687 1.1 tsutsui nwb225_krom_ascii_offset(unsigned int c)
1688 1.1 tsutsui {
1689 1.1 tsutsui unsigned int index;
1690 1.1 tsutsui
1691 1.1 tsutsui index = c - NWB225_KROM_ASCII_FIRST;
1692 1.1 tsutsui return ((index & 0xe0) << 9) | ((index & 0x1f) << 7);
1693 1.1 tsutsui }
1694 1.1 tsutsui
1695 1.1 tsutsui static void
1696 1.1 tsutsui nwb225_krom_load_cell(struct fbbm_devconfig *dc, unsigned int c,
1697 1.1 tsutsui uint16_t *cell)
1698 1.1 tsutsui {
1699 1.1 tsutsui bus_size_t offset;
1700 1.1 tsutsui int row;
1701 1.1 tsutsui
1702 1.1 tsutsui memset(cell, 0, NWB225_CELL_HEIGHT * sizeof(*cell));
1703 1.1 tsutsui offset = nwb225_krom_ascii_offset(c);
1704 1.1 tsutsui
1705 1.1 tsutsui /*
1706 1.1 tsutsui * The PROM renderer reads one 32-bit KROM row, keeps the upper word,
1707 1.1 tsutsui * masks its low four bits, and places the 24 glyph rows after four
1708 1.1 tsutsui * blank rows in the 16x30 cell.
1709 1.1 tsutsui */
1710 1.1 tsutsui for (row = 0; row < NWB225_FONT_HEIGHT; row++)
1711 1.1 tsutsui cell[NWB225_GLYPH_YOFFSET + row] =
1712 1.1 tsutsui bus_space_read_2(dc->dc_bst, dc->dc_krom_bsh,
1713 1.1 tsutsui offset + row * NWB225_KROM_ROWBYTES) &
1714 1.1 tsutsui NWB225_KROM_ASCII_MASK;
1715 1.1 tsutsui }
1716 1.1 tsutsui
1717 1.1 tsutsui static int
1718 1.1 tsutsui nwb225_init_hardware(struct fbbm_devconfig *dc)
1719 1.1 tsutsui {
1720 1.1 tsutsui uint16_t status, value;
1721 1.1 tsutsui unsigned int i, component;
1722 1.1 tsutsui
1723 1.1 tsutsui /*
1724 1.1 tsutsui * Keep the cold-init sequence in the same order as the NWS-1750 PROM
1725 1.1 tsutsui * NWB-225 module. In particular, the second reset is intentional: the
1726 1.1 tsutsui * serial-console cold-boot experiment required the init block followed
1727 1.1 tsutsui * by this reset before stable sync was established.
1728 1.1 tsutsui */
1729 1.1 tsutsui nwb225_rop_reset(dc);
1730 1.1 tsutsui
1731 1.1 tsutsui for (i = 0; i < __arraycount(nwb225_init_words); i++)
1732 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1733 1.1 tsutsui NWB225_INIT_BASE + i * sizeof(uint16_t),
1734 1.1 tsutsui nwb225_init_words[i]);
1735 1.1 tsutsui
1736 1.1 tsutsui status = bus_space_read_2(dc->dc_bst, dc->dc_rcont_bsh,
1737 1.1 tsutsui NWB225_STATUS);
1738 1.1 tsutsui if ((status & NWB225_STATUS_4PLANE) != 0)
1739 1.1 tsutsui dc->dc_nplanes = 4;
1740 1.1 tsutsui else
1741 1.1 tsutsui dc->dc_nplanes = 8;
1742 1.1 tsutsui dc->dc_planemask = (1U << dc->dc_nplanes) - 1;
1743 1.1 tsutsui dc->dc_dispver =
1744 1.1 tsutsui (status & NWB225_STATUS_DISPVER) >> NWB225_STATUS_DISPVER_SHIFT;
1745 1.1 tsutsui
1746 1.1 tsutsui nwb225_ctl_write(dc, 4, dc->dc_planemask);
1747 1.1 tsutsui nwb225_ctl_write(dc, 5, 0);
1748 1.1 tsutsui nwb225_ctl_write(dc, 6, 0x40);
1749 1.1 tsutsui nwb225_ctl_write(dc, 7, 0);
1750 1.1 tsutsui
1751 1.1 tsutsui nwb225_rop_reset(dc);
1752 1.1 tsutsui
1753 1.1 tsutsui /* Complete the fixed PROM palette/control initialization. */
1754 1.1 tsutsui for (i = 0; i < 256; i++) {
1755 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1756 1.1 tsutsui NWB225_PAL_INDEX, i);
1757 1.1 tsutsui for (component = 0; component < 3; component++) {
1758 1.1 tsutsui value = nwb225_prom_palette[i & 0x0f][component] << 4;
1759 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1760 1.1 tsutsui NWB225_PAL_DATA, value);
1761 1.1 tsutsui }
1762 1.1 tsutsui }
1763 1.1 tsutsui
1764 1.1 tsutsui bus_space_write_2(dc->dc_bst, dc->dc_rcont_bsh,
1765 1.1 tsutsui NWB225_PLANE_CTRL, 0);
1766 1.1 tsutsui
1767 1.1 tsutsui return nwb225_rop_wait(dc);
1768 1.1 tsutsui }
1769 1.1 tsutsui
1770 1.1 tsutsui static void
1771 1.1 tsutsui fbbm_init_screen(struct fbbm_devconfig *dc)
1772 1.1 tsutsui {
1773 1.1 tsutsui
1774 1.1 tsutsui dc->dc_fbwidth = NWB225_FB_WIDTH;
1775 1.1 tsutsui dc->dc_fbheight = NWB225_FB_HEIGHT;
1776 1.1 tsutsui dc->dc_width = NWB225_VIS_WIDTH;
1777 1.1 tsutsui dc->dc_height = NWB225_VIS_HEIGHT;
1778 1.1 tsutsui
1779 1.1 tsutsui dc->dc_fontwidth = NWB225_FONT_WIDTH;
1780 1.1 tsutsui dc->dc_fontheight = NWB225_FONT_HEIGHT;
1781 1.1 tsutsui dc->dc_cellwidth = NWB225_CELL_WIDTH;
1782 1.1 tsutsui dc->dc_cellheight = NWB225_CELL_HEIGHT;
1783 1.1 tsutsui
1784 1.1 tsutsui dc->dc_ncols = NWB225_TEXT_COLS;
1785 1.1 tsutsui dc->dc_nrows = NWB225_TEXT_ROWS;
1786 1.1 tsutsui dc->dc_xorigin = NWB225_TEXT_XORIGIN;
1787 1.1 tsutsui dc->dc_yorigin = NWB225_TEXT_YORIGIN;
1788 1.1 tsutsui
1789 1.1 tsutsui dc->dc_wsscrdescr.name = "std";
1790 1.1 tsutsui dc->dc_wsscrdescr.ncols = dc->dc_ncols;
1791 1.1 tsutsui dc->dc_wsscrdescr.nrows = dc->dc_nrows;
1792 1.1 tsutsui dc->dc_wsscrdescr.textops = &fbbm_emulops;
1793 1.1 tsutsui dc->dc_wsscrdescr.fontwidth = dc->dc_cellwidth;
1794 1.1 tsutsui dc->dc_wsscrdescr.fontheight = dc->dc_cellheight;
1795 1.1 tsutsui dc->dc_wsscrdescr.capabilities = WSSCREEN_REVERSE;
1796 1.1 tsutsui dc->dc_wsscrdescr.modecookie = NULL;
1797 1.1 tsutsui
1798 1.1 tsutsui dc->dc_cursoron = 0;
1799 1.1 tsutsui dc->dc_cursorrow = 0;
1800 1.1 tsutsui dc->dc_cursorcol = 0;
1801 1.1 tsutsui }
1802 1.1 tsutsui
1803 1.1 tsutsui /*
1804 1.1 tsutsui * Clear only the visible text display. This is separate from logical screen
1805 1.1 tsutsui * initialization so that the C1 early-console path can perform the clear at
1806 1.1 tsutsui * takeover time before wsdisplay_cnattach(), while the later normal attach
1807 1.1 tsutsui * can reuse the established console state without clearing it again.
1808 1.1 tsutsui */
1809 1.1 tsutsui static int
1810 1.1 tsutsui fbbm_clear_screen(struct fbbm_devconfig *dc)
1811 1.1 tsutsui {
1812 1.1 tsutsui
1813 1.1 tsutsui return nwb225_rop_fill_rect(dc, 0, 0, dc->dc_width, dc->dc_height, 0);
1814 1.1 tsutsui }
1815 1.1 tsutsui
1816 1.1 tsutsui static uint32_t
1817 1.1 tsutsui fbbm_attr_background(struct fbbm_devconfig *dc, long attr)
1818 1.1 tsutsui {
1819 1.1 tsutsui
1820 1.1 tsutsui return (attr & 1) != 0 ? dc->dc_planemask : 0;
1821 1.1 tsutsui }
1822 1.1 tsutsui
1823 1.1 tsutsui static void
1824 1.1 tsutsui fbbm_cursor(void *cookie, int on, int row, int col)
1825 1.1 tsutsui {
1826 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
1827 1.1 tsutsui int x, y, error;
1828 1.1 tsutsui
1829 1.1 tsutsui if (dc->dc_cursoron != 0) {
1830 1.1 tsutsui x = dc->dc_xorigin + dc->dc_cursorcol * dc->dc_cellwidth;
1831 1.1 tsutsui y = dc->dc_yorigin + dc->dc_cursorrow * dc->dc_cellheight;
1832 1.1 tsutsui error = nwb225_rop_copy_rect(dc, x, y, dc->dc_cellwidth,
1833 1.1 tsutsui dc->dc_cellheight, x, y, NWB225_BF_DI);
1834 1.1 tsutsui if (error != 0)
1835 1.1 tsutsui return;
1836 1.1 tsutsui dc->dc_cursoron = 0;
1837 1.1 tsutsui }
1838 1.1 tsutsui
1839 1.1 tsutsui dc->dc_cursorrow = row;
1840 1.1 tsutsui dc->dc_cursorcol = col;
1841 1.1 tsutsui if (on == 0)
1842 1.1 tsutsui return;
1843 1.1 tsutsui if (row < 0 || row >= dc->dc_nrows || col < 0 || col >= dc->dc_ncols)
1844 1.1 tsutsui return;
1845 1.1 tsutsui
1846 1.1 tsutsui x = dc->dc_xorigin + col * dc->dc_cellwidth;
1847 1.1 tsutsui y = dc->dc_yorigin + row * dc->dc_cellheight;
1848 1.1 tsutsui error = nwb225_rop_copy_rect(dc, x, y, dc->dc_cellwidth,
1849 1.1 tsutsui dc->dc_cellheight, x, y, NWB225_BF_DI);
1850 1.1 tsutsui if (error == 0)
1851 1.1 tsutsui dc->dc_cursoron = 1;
1852 1.1 tsutsui }
1853 1.1 tsutsui
1854 1.1 tsutsui static int
1855 1.1 tsutsui fbbm_mapchar(void *cookie, int c, unsigned int *cp)
1856 1.1 tsutsui {
1857 1.1 tsutsui
1858 1.1 tsutsui __USE(cookie);
1859 1.1 tsutsui
1860 1.1 tsutsui if (c < NWB225_KROM_ASCII_FIRST || c > NWB225_KROM_ASCII_LAST) {
1861 1.1 tsutsui *cp = ' ';
1862 1.1 tsutsui return 0;
1863 1.1 tsutsui }
1864 1.1 tsutsui
1865 1.1 tsutsui *cp = c;
1866 1.1 tsutsui return 5;
1867 1.1 tsutsui }
1868 1.1 tsutsui
1869 1.1 tsutsui static void
1870 1.1 tsutsui fbbm_putchar(void *cookie, int row, int col, u_int uc, long attr)
1871 1.1 tsutsui {
1872 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
1873 1.1 tsutsui uint16_t cell[NWB225_CELL_HEIGHT];
1874 1.1 tsutsui uint32_t foreground, background;
1875 1.1 tsutsui int x, y;
1876 1.1 tsutsui
1877 1.1 tsutsui if (row < 0 || row >= dc->dc_nrows || col < 0 || col >= dc->dc_ncols)
1878 1.1 tsutsui return;
1879 1.1 tsutsui if (uc < NWB225_KROM_ASCII_FIRST || uc > NWB225_KROM_ASCII_LAST)
1880 1.1 tsutsui uc = ' ';
1881 1.1 tsutsui
1882 1.1 tsutsui nwb225_krom_load_cell(dc, uc, cell);
1883 1.1 tsutsui background = fbbm_attr_background(dc, attr);
1884 1.1 tsutsui foreground = dc->dc_planemask ^ background;
1885 1.1 tsutsui x = dc->dc_xorigin + col * dc->dc_cellwidth;
1886 1.1 tsutsui y = dc->dc_yorigin + row * dc->dc_cellheight;
1887 1.1 tsutsui
1888 1.1 tsutsui (void)nwb225_rop_hwrite(dc, cell, 1, 0, 0, dc->dc_cellwidth,
1889 1.1 tsutsui dc->dc_cellheight, x, y, foreground, background);
1890 1.1 tsutsui }
1891 1.1 tsutsui
1892 1.1 tsutsui static void
1893 1.1 tsutsui fbbm_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
1894 1.1 tsutsui {
1895 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
1896 1.1 tsutsui int sx, dx, y, width;
1897 1.1 tsutsui
1898 1.1 tsutsui if (ncols <= 0 || row < 0 || row >= dc->dc_nrows)
1899 1.1 tsutsui return;
1900 1.1 tsutsui if (srccol < 0 || dstcol < 0 || srccol + ncols > dc->dc_ncols ||
1901 1.1 tsutsui dstcol + ncols > dc->dc_ncols)
1902 1.1 tsutsui return;
1903 1.1 tsutsui if (srccol == dstcol)
1904 1.1 tsutsui return;
1905 1.1 tsutsui
1906 1.1 tsutsui sx = dc->dc_xorigin + srccol * dc->dc_cellwidth;
1907 1.1 tsutsui dx = dc->dc_xorigin + dstcol * dc->dc_cellwidth;
1908 1.1 tsutsui y = dc->dc_yorigin + row * dc->dc_cellheight;
1909 1.1 tsutsui width = ncols * dc->dc_cellwidth;
1910 1.1 tsutsui (void)nwb225_rop_copy_rect(dc, sx, y, width, dc->dc_cellheight,
1911 1.1 tsutsui dx, y, NWB225_BF_S);
1912 1.1 tsutsui }
1913 1.1 tsutsui
1914 1.1 tsutsui static void
1915 1.1 tsutsui fbbm_erasecols(void *cookie, int row, int col, int ncols, long attr)
1916 1.1 tsutsui {
1917 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
1918 1.1 tsutsui uint32_t background;
1919 1.1 tsutsui int x, y, width;
1920 1.1 tsutsui
1921 1.1 tsutsui if (ncols <= 0 || row < 0 || row >= dc->dc_nrows)
1922 1.1 tsutsui return;
1923 1.1 tsutsui if (col < 0 || col + ncols > dc->dc_ncols)
1924 1.1 tsutsui return;
1925 1.1 tsutsui
1926 1.1 tsutsui x = dc->dc_xorigin + col * dc->dc_cellwidth;
1927 1.1 tsutsui y = dc->dc_yorigin + row * dc->dc_cellheight;
1928 1.1 tsutsui width = ncols * dc->dc_cellwidth;
1929 1.1 tsutsui background = fbbm_attr_background(dc, attr);
1930 1.1 tsutsui (void)nwb225_rop_fill_rect(dc, x, y, width, dc->dc_cellheight,
1931 1.1 tsutsui background);
1932 1.1 tsutsui }
1933 1.1 tsutsui
1934 1.1 tsutsui static void
1935 1.1 tsutsui fbbm_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
1936 1.1 tsutsui {
1937 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
1938 1.1 tsutsui int x, sy, dy, height;
1939 1.1 tsutsui
1940 1.1 tsutsui if (nrows <= 0 || srcrow < 0 || dstrow < 0 ||
1941 1.1 tsutsui srcrow + nrows > dc->dc_nrows || dstrow + nrows > dc->dc_nrows)
1942 1.1 tsutsui return;
1943 1.1 tsutsui if (srcrow == dstrow)
1944 1.1 tsutsui return;
1945 1.1 tsutsui
1946 1.1 tsutsui x = dc->dc_xorigin;
1947 1.1 tsutsui sy = dc->dc_yorigin + srcrow * dc->dc_cellheight;
1948 1.1 tsutsui dy = dc->dc_yorigin + dstrow * dc->dc_cellheight;
1949 1.1 tsutsui height = nrows * dc->dc_cellheight;
1950 1.1 tsutsui (void)nwb225_rop_copy_rect(dc, x, sy,
1951 1.1 tsutsui dc->dc_ncols * dc->dc_cellwidth, height, x, dy, NWB225_BF_S);
1952 1.1 tsutsui }
1953 1.1 tsutsui
1954 1.1 tsutsui static void
1955 1.1 tsutsui fbbm_eraserows(void *cookie, int row, int nrows, long attr)
1956 1.1 tsutsui {
1957 1.1 tsutsui struct fbbm_devconfig *dc = cookie;
1958 1.1 tsutsui uint32_t background;
1959 1.1 tsutsui int x, y, height;
1960 1.1 tsutsui
1961 1.1 tsutsui if (nrows <= 0 || row < 0 || row + nrows > dc->dc_nrows)
1962 1.1 tsutsui return;
1963 1.1 tsutsui
1964 1.1 tsutsui x = dc->dc_xorigin;
1965 1.1 tsutsui y = dc->dc_yorigin + row * dc->dc_cellheight;
1966 1.1 tsutsui height = nrows * dc->dc_cellheight;
1967 1.1 tsutsui background = fbbm_attr_background(dc, attr);
1968 1.1 tsutsui (void)nwb225_rop_fill_rect(dc, x, y,
1969 1.1 tsutsui dc->dc_ncols * dc->dc_cellwidth, height, background);
1970 1.1 tsutsui }
1971 1.1 tsutsui
1972 1.1 tsutsui static int
1973 1.1 tsutsui fbbm_allocattr(void *cookie, int fg, int bg, int flags, long *attrp)
1974 1.1 tsutsui {
1975 1.1 tsutsui
1976 1.1 tsutsui __USE(cookie);
1977 1.1 tsutsui __USE(fg);
1978 1.1 tsutsui __USE(bg);
1979 1.1 tsutsui
1980 1.1 tsutsui if ((flags & ~WSATTR_REVERSE) != 0)
1981 1.1 tsutsui return EINVAL;
1982 1.1 tsutsui
1983 1.1 tsutsui *attrp = (flags & WSATTR_REVERSE) != 0 ? 1 : 0;
1984 1.1 tsutsui return 0;
1985 1.1 tsutsui }
1986 1.1 tsutsui
1987 1.1 tsutsui static int
1988 1.1 tsutsui fbbm_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
1989 1.1 tsutsui struct lwp *l)
1990 1.1 tsutsui {
1991 1.1 tsutsui struct fbbm_softc *sc = v;
1992 1.1 tsutsui struct fbbm_devconfig *dc = sc->sc_dc;
1993 1.1 tsutsui struct wsdisplay_fbinfo *fbinfo;
1994 1.1 tsutsui
1995 1.1 tsutsui __USE(vs);
1996 1.1 tsutsui __USE(flag);
1997 1.1 tsutsui __USE(l);
1998 1.1 tsutsui
1999 1.1 tsutsui switch (cmd) {
2000 1.1 tsutsui case WSDISPLAYIO_GTYPE:
2001 1.1 tsutsui *(u_int *)data = WSDISPLAY_TYPE_NWB225;
2002 1.1 tsutsui return 0;
2003 1.1 tsutsui
2004 1.1 tsutsui case WSDISPLAYIO_GINFO:
2005 1.1 tsutsui fbinfo = data;
2006 1.1 tsutsui fbinfo->height = dc->dc_height;
2007 1.1 tsutsui fbinfo->width = dc->dc_width;
2008 1.1 tsutsui fbinfo->depth = dc->dc_nplanes;
2009 1.1 tsutsui fbinfo->cmsize = 0;
2010 1.1 tsutsui return 0;
2011 1.1 tsutsui
2012 1.1 tsutsui default:
2013 1.1 tsutsui return EPASSTHROUGH;
2014 1.1 tsutsui }
2015 1.1 tsutsui }
2016 1.1 tsutsui
2017 1.1 tsutsui static int
2018 1.1 tsutsui fbbm_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
2019 1.1 tsutsui int *ccolp, int *crowp, long *attrp)
2020 1.1 tsutsui {
2021 1.1 tsutsui struct fbbm_softc *sc = v;
2022 1.1 tsutsui struct fbbm_devconfig *dc = sc->sc_dc;
2023 1.1 tsutsui long attr;
2024 1.1 tsutsui int error;
2025 1.1 tsutsui
2026 1.1 tsutsui KASSERT(type == &dc->dc_wsscrdescr);
2027 1.1 tsutsui
2028 1.1 tsutsui if (sc->sc_nscreens != 0)
2029 1.1 tsutsui return ENOMEM;
2030 1.1 tsutsui
2031 1.1 tsutsui error = fbbm_allocattr(dc, 0, 0, 0, &attr);
2032 1.1 tsutsui if (error != 0)
2033 1.1 tsutsui return error;
2034 1.1 tsutsui
2035 1.1 tsutsui *cookiep = dc;
2036 1.1 tsutsui *ccolp = 0;
2037 1.1 tsutsui *crowp = 0;
2038 1.1 tsutsui *attrp = attr;
2039 1.1 tsutsui sc->sc_nscreens = 1;
2040 1.1 tsutsui
2041 1.1 tsutsui return 0;
2042 1.1 tsutsui }
2043 1.1 tsutsui
2044 1.1 tsutsui static void
2045 1.1 tsutsui fbbm_free_screen(void *v, void *cookie)
2046 1.1 tsutsui {
2047 1.1 tsutsui struct fbbm_softc *sc = v;
2048 1.1 tsutsui
2049 1.1 tsutsui KASSERT(sc->sc_nscreens == 1);
2050 1.1 tsutsui KASSERT(cookie == sc->sc_dc);
2051 1.1 tsutsui sc->sc_nscreens = 0;
2052 1.1 tsutsui }
2053 1.1 tsutsui
2054 1.1 tsutsui static int
2055 1.1 tsutsui fbbm_show_screen(void *v, void *cookie, int waitok,
2056 1.1 tsutsui void (*cb)(void *, int, int), void *cbarg)
2057 1.1 tsutsui {
2058 1.1 tsutsui
2059 1.1 tsutsui __USE(v);
2060 1.1 tsutsui __USE(cookie);
2061 1.1 tsutsui __USE(waitok);
2062 1.1 tsutsui __USE(cb);
2063 1.1 tsutsui __USE(cbarg);
2064 1.1 tsutsui
2065 1.1 tsutsui return 0;
2066 1.1 tsutsui }
2067