gsfb.c revision 1.22 1 1.22 martin /* $NetBSD: gsfb.c,v 1.22 2014/07/08 13:35:43 martin Exp $ */
2 1.1 uch
3 1.1 uch /*-
4 1.1 uch * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 1.1 uch * All rights reserved.
6 1.1 uch *
7 1.1 uch * This code is derived from software contributed to The NetBSD Foundation
8 1.1 uch * by UCHIYAMA Yasushi.
9 1.1 uch *
10 1.1 uch * Redistribution and use in source and binary forms, with or without
11 1.1 uch * modification, are permitted provided that the following conditions
12 1.1 uch * are met:
13 1.1 uch * 1. Redistributions of source code must retain the above copyright
14 1.1 uch * notice, this list of conditions and the following disclaimer.
15 1.1 uch * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 uch * notice, this list of conditions and the following disclaimer in the
17 1.1 uch * documentation and/or other materials provided with the distribution.
18 1.1 uch *
19 1.1 uch * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 uch * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 uch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 uch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 uch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 uch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 uch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 uch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 uch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 uch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 uch * POSSIBILITY OF SUCH DAMAGE.
30 1.1 uch */
31 1.7 lukem
32 1.7 lukem #include <sys/cdefs.h>
33 1.22 martin __KERNEL_RCSID(0, "$NetBSD: gsfb.c,v 1.22 2014/07/08 13:35:43 martin Exp $");
34 1.1 uch
35 1.1 uch #include "debug_playstation2.h"
36 1.1 uch
37 1.1 uch #include <sys/param.h>
38 1.1 uch #include <sys/systm.h>
39 1.1 uch
40 1.1 uch #include <machine/autoconf.h>
41 1.1 uch
42 1.1 uch #include <dev/cons.h>
43 1.1 uch
44 1.1 uch #include <dev/wscons/wsconsio.h>
45 1.1 uch #include <dev/wscons/wsdisplayvar.h>
46 1.1 uch #include <dev/wscons/wscons_callbacks.h>
47 1.1 uch
48 1.1 uch #include <dev/wsfont/wsfont.h>
49 1.1 uch
50 1.1 uch #include <playstation2/ee/eevar.h>
51 1.1 uch #include <playstation2/ee/gsvar.h>
52 1.1 uch #include <playstation2/ee/gsreg.h>
53 1.1 uch #include <playstation2/ee/dmacvar.h>
54 1.1 uch #include <playstation2/ee/dmacreg.h>
55 1.1 uch
56 1.1 uch #ifdef DEBUG
57 1.1 uch #define STATIC
58 1.1 uch #else
59 1.1 uch #define STATIC static
60 1.1 uch #endif
61 1.1 uch
62 1.22 martin struct gsfb_softc {
63 1.22 martin device_t sc_dev;
64 1.22 martin const struct wsscreen_descr *sc_screen;
65 1.22 martin struct wsdisplay_font *sc_font;
66 1.22 martin bool sc_is_console;
67 1.22 martin };
68 1.22 martin
69 1.22 martin static int gsfb_is_console;
70 1.22 martin static struct gsfb_softc gsfb_console_softc;
71 1.1 uch
72 1.1 uch STATIC void gsfb_dma_kick(paddr_t, size_t);
73 1.1 uch STATIC void gsfb_font_expand_psmct32(const struct wsdisplay_font *, u_int,
74 1.1 uch long, u_int32_t *);
75 1.13 perry STATIC inline void gsfb_set_cursor_pos(u_int32_t *, int, int, int, int);
76 1.1 uch
77 1.1 uch #define ATTR_FG_GET(a) (((a )>> 24) & 0xf)
78 1.1 uch #define ATTR_BG_GET(a) (((a )>> 16) & 0xf)
79 1.1 uch #define ATTR_FG_SET(x) (((x) << 24) & 0x0f000000)
80 1.1 uch #define ATTR_BG_SET(x) (((x) << 16) & 0x000f0000)
81 1.1 uch
82 1.1 uch STATIC const u_int32_t gsfb_ansi_psmct32[] = {
83 1.1 uch 0x80000000, /* black */
84 1.1 uch 0x800000aa, /* red */
85 1.1 uch 0x8000aa00, /* green */
86 1.1 uch 0x8000aaaa, /* brown */
87 1.1 uch 0x80aa0000, /* blue */
88 1.1 uch 0x80aa00aa, /* magenta */
89 1.1 uch 0x80aaaa00, /* cyan */
90 1.1 uch 0x80aaaaaa, /* white */
91 1.1 uch 0x80000000, /* black */
92 1.1 uch 0x800000ff, /* red */
93 1.1 uch 0x8000ff00, /* green */
94 1.1 uch 0x8000ffff, /* brown */
95 1.1 uch 0x80ff0000, /* blue */
96 1.1 uch 0x80ff00ff, /* magenta */
97 1.1 uch 0x80ffff00, /* cyan */
98 1.1 uch 0x80ffffff, /* black */
99 1.1 uch };
100 1.1 uch
101 1.1 uch #define TRXPOS_DXY(f, x, y) \
102 1.1 uch ({ \
103 1.1 uch f[9] = ((x) & 0x000007ff) | (((y) << 16) & 0x07ff0000); \
104 1.1 uch })
105 1.1 uch
106 1.1 uch #define TRXPOS_SY_DY(f, sy, dy) \
107 1.1 uch ({ \
108 1.1 uch f[8] = (((sy) << 16) & 0x07ff0000); \
109 1.1 uch f[9] = (((dy) << 16) & 0x07ff0000); \
110 1.1 uch })
111 1.1 uch
112 1.1 uch #define TRXPOS_DXY_SXY(f, dx, dy, sx, sy) \
113 1.1 uch ({ \
114 1.1 uch f[8] = ((((sy) << 16) & 0x07ff0000) | ((sx) & 0x000007ff)); \
115 1.1 uch f[9] = ((((dy) << 16) & 0x07ff0000) | ((dx) & 0x000007ff)); \
116 1.1 uch })
117 1.1 uch
118 1.1 uch STATIC u_int32_t gsfb_scroll_cmd_640x16[] __attribute__((__aligned__(16))) = {
119 1.1 uch 0x00008004, 0x10000000, 0x0000000e, 0x00000000,
120 1.1 uch 0x000a0000, 0x000a0000, 0x00000050, 0x00000000,
121 1.1 uch 0x07ff0000, 0x07ff0000, 0x00000051, 0x00000000,
122 1.1 uch 0x00000280, 0x00000010, 0x00000052, 0x00000000,
123 1.1 uch 0x00000002, 0x00000000, 0x00000053, 0x00000000,
124 1.1 uch };
125 1.1 uch
126 1.1 uch STATIC u_int32_t gsfb_cursor_cmd[] __attribute__((__aligned__(16))) = {
127 1.1 uch 0x00008007, 0x10000000, 0x0000000e, 0x00000000,
128 1.1 uch 0x00000001, 0x00000000, 0x0000001a, 0x00000000,
129 1.1 uch 0x000000a4, 0x00000080, 0x00000042, 0x00000000,
130 1.1 uch 0x00000046, 0x00000000, 0x00000000, 0x00000000,
131 1.1 uch 0x80ffffff, 0x00000000, 0x00000001, 0x00000000,
132 1.1 uch 0x00000000, 0x00000000, 0x0000000d, 0x00000000,
133 1.1 uch 0x80ffffff, 0x00000000, 0x00000001, 0x00000000,
134 1.1 uch 0x00000000, 0x00000000, 0x00000005, 0x00000000,
135 1.1 uch };
136 1.1 uch
137 1.1 uch STATIC u_int32_t gsfb_copy_cmd_8x16[] __attribute__((__aligned__(16))) = {
138 1.1 uch 0x00008004, 0x10000000, 0x0000000e, 0x00000000,
139 1.1 uch 0x000a0000, 0x000a0000, 0x00000050, 0x00000000,
140 1.1 uch 0x07ff07ff, 0x07ff07ff, 0x00000051, 0x00000000,
141 1.1 uch 0x00000008, 0x00000010, 0x00000052, 0x00000000,
142 1.1 uch 0x00000002, 0x00000000, 0x00000053, 0x00000000,
143 1.1 uch };
144 1.1 uch
145 1.1 uch STATIC u_int32_t gsfb_init_cmd_640x480[] __attribute__((__aligned__(16))) = {
146 1.1 uch 0x00008008, 0x10000000, 0x0000000e, 0x00000000,
147 1.1 uch 0x000a0000, 0x00000000, 0x0000004c, 0x00000000,
148 1.1 uch 0x00000096, 0x00000000, 0x0000004e, 0x00000000,
149 1.1 uch 0x02800000, 0x01e00000, 0x00000040, 0x00000000,
150 1.1 uch 0x00000006, 0x00000000, 0x00000000, 0x00000000,
151 1.1 uch 0x80000000, 0x00000000, 0x00000001, 0x00000000,
152 1.1 uch 0x00000000, 0x00000000, 0x0000000d, 0x00000000,
153 1.1 uch 0x80000000, 0x00000000, 0x00000001, 0x00000000,
154 1.1 uch 0x1e002800, 0x00000000, 0x00000005, 0x00000000,
155 1.1 uch };
156 1.1 uch
157 1.1 uch STATIC u_int32_t gsfb_load_cmd_8x16_psmct32[(6 + 32) * 4]
158 1.1 uch __attribute__((__aligned__(16))) = {
159 1.1 uch /* GIF tag + GS command */
160 1.1 uch 0x00000004, 0x10000000, 0x0000000e, 0x00000000,
161 1.1 uch 0x00000000, 0x000a0000, 0x00000050, 0x00000000,
162 1.1 uch 0x00000000, 0x00000000, 0x00000051, 0x00000000,
163 1.1 uch 0x00000008, 0x00000016, 0x00000052, 0x00000000,
164 1.1 uch 0x00000000, 0x00000000, 0x00000053, 0x00000000,
165 1.1 uch 0x00008020, 0x08000000, 0x00000000, 0x00000000,
166 1.1 uch /* Load area */
167 1.1 uch #define FONT_SCRATCH_BASE (6 * 4)
168 1.1 uch };
169 1.1 uch
170 1.1 uch #ifdef GSFB_DEBUG_MONITOR
171 1.1 uch #include <machine/stdarg.h>
172 1.1 uch STATIC const struct _gsfb_debug_window {
173 1.1 uch int start, nrow, attr;
174 1.1 uch } _gsfb_debug_window[3] = {
175 1.1 uch { 24, 2 , ATTR_BG_SET(WSCOL_BROWN) | ATTR_FG_SET(WSCOL_BLUE) },
176 1.1 uch { 26, 2 , ATTR_BG_SET(WSCOL_CYAN) | ATTR_FG_SET(WSCOL_BLUE) },
177 1.1 uch { 28, 2 , ATTR_BG_SET(WSCOL_WHITE) | ATTR_FG_SET(WSCOL_BLUE) },
178 1.1 uch };
179 1.1 uch STATIC char _gsfb_debug_buf[80 * 2];
180 1.1 uch #endif /* GSFB_DEBUG_MONITOR */
181 1.1 uch
182 1.22 martin STATIC int gsfb_match(device_t, cfdata_t, void *);
183 1.22 martin STATIC void gsfb_attach(device_t, device_t, void *);
184 1.1 uch
185 1.22 martin CFATTACH_DECL_NEW(gsfb, sizeof(struct gsfb_softc),
186 1.6 thorpej gsfb_match, gsfb_attach, NULL, NULL);
187 1.1 uch
188 1.1 uch STATIC void gsfb_hwinit(void);
189 1.22 martin STATIC int gsfb_swinit(struct gsfb_softc*);
190 1.1 uch
191 1.1 uch /* console */
192 1.1 uch void gsfbcnprobe(struct consdev *);
193 1.1 uch void gsfbcninit(struct consdev *);
194 1.1 uch
195 1.1 uch /* emul ops */
196 1.1 uch STATIC void _gsfb_cursor(void *, int, int, int);
197 1.1 uch STATIC int _gsfb_mapchar(void *, int, unsigned int *);
198 1.1 uch STATIC void _gsfb_putchar(void *, int, int, u_int, long);
199 1.1 uch STATIC void _gsfb_copycols(void *, int, int, int, int);
200 1.1 uch STATIC void _gsfb_erasecols(void *, int, int, int, long);
201 1.1 uch STATIC void _gsfb_copyrows(void *, int, int, int);
202 1.1 uch STATIC void _gsfb_eraserows(void *, int, int, long);
203 1.4 junyoung STATIC int _gsfb_allocattr(void *, int, int, int, long *);
204 1.1 uch
205 1.1 uch /* access ops */
206 1.17 christos STATIC int _gsfb_ioctl(void *, void *, u_long, void *, int, struct lwp *);
207 1.16 jmmv STATIC paddr_t _gsfb_mmap(void *, void *, off_t, int);
208 1.1 uch STATIC int _gsfb_alloc_screen(void *, const struct wsscreen_descr *, void **,
209 1.1 uch int *, int *, long *);
210 1.1 uch STATIC void _gsfb_free_screen(void *, void *);
211 1.1 uch STATIC int _gsfb_show_screen(void *, void *, int, void (*)(void *, int, int),
212 1.1 uch void *);
213 1.1 uch STATIC void _gsfb_pollc(void *, int);
214 1.1 uch
215 1.1 uch /*
216 1.1 uch * wsdisplay attach args
217 1.1 uch * std: screen size 640 x 480, font size 8 x 16
218 1.1 uch */
219 1.1 uch #define GSFB_STD_SCREEN_WIDTH 640
220 1.1 uch #define GSFB_STD_SCREEN_HEIGHT 480
221 1.1 uch #define GSFB_STD_FONT_WIDTH 8
222 1.1 uch #define GSFB_STD_FONT_HEIGHT 16
223 1.1 uch const struct wsdisplay_emulops _gsfb_emulops = {
224 1.1 uch .cursor = _gsfb_cursor,
225 1.1 uch .mapchar = _gsfb_mapchar,
226 1.1 uch .putchar = _gsfb_putchar,
227 1.1 uch .copycols = _gsfb_copycols,
228 1.1 uch .erasecols = _gsfb_erasecols,
229 1.1 uch .copyrows = _gsfb_copyrows,
230 1.1 uch .eraserows = _gsfb_eraserows,
231 1.4 junyoung .allocattr = _gsfb_allocattr
232 1.1 uch };
233 1.1 uch
234 1.1 uch const struct wsscreen_descr _gsfb_std_screen = {
235 1.1 uch .name = "std",
236 1.1 uch .ncols = 80,
237 1.1 uch #ifdef GSFB_DEBUG_MONITOR
238 1.1 uch .nrows = 24,
239 1.1 uch #else
240 1.1 uch .nrows = 30,
241 1.1 uch #endif
242 1.1 uch .textops = &_gsfb_emulops,
243 1.1 uch .fontwidth = 8,
244 1.1 uch .fontheight = 16,
245 1.1 uch .capabilities = WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
246 1.1 uch WSSCREEN_WSCOLORS
247 1.1 uch };
248 1.1 uch
249 1.1 uch const struct wsscreen_descr *_gsfb_screen_table[] = {
250 1.1 uch &_gsfb_std_screen,
251 1.1 uch };
252 1.1 uch
253 1.1 uch struct wsscreen_list _gsfb_screen_list = {
254 1.1 uch .nscreens = sizeof(_gsfb_screen_table) /
255 1.1 uch sizeof(_gsfb_screen_table[0]),
256 1.1 uch .screens = _gsfb_screen_table
257 1.1 uch };
258 1.1 uch
259 1.1 uch struct wsdisplay_accessops _gsfb_accessops = {
260 1.1 uch .ioctl = _gsfb_ioctl,
261 1.1 uch .mmap = _gsfb_mmap,
262 1.1 uch .alloc_screen = _gsfb_alloc_screen,
263 1.1 uch .free_screen = _gsfb_free_screen,
264 1.1 uch .show_screen = _gsfb_show_screen,
265 1.1 uch .load_font = 0,
266 1.1 uch .pollc = _gsfb_pollc
267 1.1 uch };
268 1.1 uch
269 1.1 uch int
270 1.22 martin gsfb_match(device_t parent, cfdata_t cf, void *aux)
271 1.1 uch {
272 1.1 uch extern struct cfdriver gsfb_cd;
273 1.1 uch struct mainbus_attach_args *ma = aux;
274 1.1 uch
275 1.1 uch if (strcmp(ma->ma_name, gsfb_cd.cd_name) != 0)
276 1.1 uch return (0);
277 1.1 uch
278 1.22 martin return 1;
279 1.1 uch }
280 1.1 uch
281 1.1 uch void
282 1.22 martin gsfb_attach(device_t parent, device_t self, void *aux)
283 1.1 uch {
284 1.1 uch struct wsemuldisplaydev_attach_args wa;
285 1.22 martin struct gsfb_softc *sc = device_private(self);
286 1.22 martin
287 1.22 martin if (gsfb_is_console) {
288 1.22 martin memcpy(sc, &gsfb_console_softc, sizeof(gsfb_console_softc));
289 1.22 martin sc->sc_is_console = true;
290 1.22 martin }
291 1.22 martin sc->sc_dev = self;
292 1.1 uch
293 1.22 martin if (!sc->sc_is_console && !gsfb_swinit(sc) != 0)
294 1.1 uch return;
295 1.1 uch
296 1.1 uch printf("\n");
297 1.1 uch
298 1.22 martin wa.console = sc->sc_is_console;
299 1.1 uch wa.scrdata = &_gsfb_screen_list;
300 1.1 uch wa.accessops = &_gsfb_accessops;
301 1.22 martin wa.accesscookie = sc;
302 1.1 uch
303 1.1 uch config_found(self, &wa, wsdisplaydevprint);
304 1.1 uch }
305 1.1 uch
306 1.1 uch /*
307 1.1 uch * console
308 1.1 uch */
309 1.1 uch void
310 1.1 uch gsfbcnprobe(struct consdev *cndev)
311 1.1 uch {
312 1.1 uch
313 1.1 uch cndev->cn_pri = CN_INTERNAL;
314 1.1 uch }
315 1.1 uch
316 1.1 uch void
317 1.1 uch gsfbcninit(struct consdev *cndev)
318 1.1 uch {
319 1.1 uch paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_init_cmd_640x480);
320 1.15 christos u_int32_t *buf = (void *)MIPS_PHYS_TO_KSEG1(paddr);
321 1.15 christos long defattr = ATTR_BG_SET(WS_DEFAULT_BG) | ATTR_FG_SET(WS_DEFAULT_FG);
322 1.1 uch
323 1.22 martin gsfb_is_console = 1;
324 1.1 uch
325 1.1 uch gsfb_hwinit();
326 1.22 martin gsfb_swinit(&gsfb_console_softc);
327 1.1 uch
328 1.15 christos /* Set the screen to the default background color at boot */
329 1.15 christos buf[28] = gsfb_ansi_psmct32[ATTR_BG_GET(defattr)];
330 1.1 uch gsfb_dma_kick(paddr, sizeof gsfb_init_cmd_640x480);
331 1.1 uch #ifdef GSFB_DEBUG_MONITOR
332 1.1 uch {
333 1.1 uch const struct _gsfb_debug_window *win;
334 1.1 uch int i;
335 1.1 uch
336 1.1 uch for (i = 0; i < 3; i++) {
337 1.1 uch win = &_gsfb_debug_window[i];
338 1.1 uch _gsfb_eraserows(0, win->start, win->nrow, win->attr);
339 1.1 uch }
340 1.1 uch }
341 1.1 uch #endif /* GSFB_DEBUG_MONITOR */
342 1.1 uch
343 1.22 martin wsdisplay_cnattach(&_gsfb_std_screen, &gsfb_console_softc, 0, 0,
344 1.22 martin defattr);
345 1.1 uch }
346 1.1 uch
347 1.1 uch void
348 1.19 cegger gsfb_hwinit(void)
349 1.1 uch {
350 1.10 uch /*
351 1.10 uch gs_init(VESA_1A) hang up on SCPH-50000.
352 1.10 uch use bootloader's setting.
353 1.10 uch EN1 | CRTMOD | MMOD | AMOD | ALP(all 1.0)
354 1.10 uch */
355 1.10 uch _reg_write_8(GS_S_PMODE_REG, 0xffa5);
356 1.10 uch
357 1.1 uch dmac_init();
358 1.1 uch
359 1.1 uch /* reset GIF channel DMA */
360 1.1 uch _reg_write_4(D2_QWC_REG, 0);
361 1.1 uch _reg_write_4(D2_MADR_REG, 0);
362 1.1 uch _reg_write_4(D2_TADR_REG, 0);
363 1.1 uch _reg_write_4(D2_CHCR_REG, 0);
364 1.1 uch }
365 1.1 uch
366 1.1 uch int
367 1.22 martin gsfb_swinit(struct gsfb_softc *sc)
368 1.1 uch {
369 1.1 uch int font;
370 1.1 uch
371 1.1 uch wsfont_init();
372 1.22 martin font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
373 1.22 martin WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
374 1.1 uch if (font < 0)
375 1.1 uch return (1);
376 1.1 uch
377 1.22 martin if (wsfont_lock(font, &sc->sc_font))
378 1.1 uch return (1);
379 1.1 uch
380 1.22 martin sc->sc_screen = &_gsfb_std_screen;
381 1.1 uch
382 1.1 uch return (0);
383 1.1 uch }
384 1.1 uch
385 1.1 uch /*
386 1.1 uch * wsdisplay
387 1.1 uch */
388 1.1 uch void
389 1.1 uch _gsfb_cursor(void *cookie, int on, int row, int col)
390 1.1 uch {
391 1.22 martin struct gsfb_softc *sc = cookie;
392 1.1 uch paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_cursor_cmd);
393 1.1 uch u_int32_t *buf = (void *)MIPS_PHYS_TO_KSEG1(paddr);
394 1.22 martin struct wsdisplay_font *font = sc->sc_font;
395 1.1 uch
396 1.1 uch gsfb_set_cursor_pos(buf, col, row, font->fontwidth, font->fontheight);
397 1.1 uch
398 1.1 uch gsfb_dma_kick(paddr, sizeof gsfb_cursor_cmd);
399 1.1 uch }
400 1.1 uch
401 1.13 perry inline void
402 1.1 uch gsfb_set_cursor_pos(u_int32_t *p, int x, int y, int w, int h)
403 1.1 uch {
404 1.1 uch
405 1.1 uch x *= w;
406 1.1 uch y *= h;
407 1.1 uch p[20] = ((x << 4) & 0xffff) | ((y << 20) & 0xffff0000);
408 1.14 martin p[28] = (((x + w) << 4) & 0xffff) | (((y + h) << 20) & 0xffff0000);
409 1.1 uch }
410 1.1 uch
411 1.1 uch int
412 1.1 uch _gsfb_mapchar(void *cookie, int c, unsigned int *cp)
413 1.1 uch {
414 1.22 martin struct gsfb_softc *sc = cookie;
415 1.22 martin struct wsdisplay_font *font = sc->sc_font;
416 1.1 uch
417 1.1 uch if (font->encoding != WSDISPLAY_FONTENC_ISO)
418 1.1 uch if ((c = wsfont_map_unichar(font, c)) < 0)
419 1.1 uch goto nomap;
420 1.1 uch
421 1.1 uch if (c < font->firstchar || c >= font->firstchar + font->numchars)
422 1.1 uch goto nomap;
423 1.1 uch
424 1.1 uch *cp = c;
425 1.1 uch return (5);
426 1.1 uch
427 1.1 uch nomap:
428 1.1 uch *cp = ' ';
429 1.1 uch return (0);
430 1.1 uch }
431 1.1 uch
432 1.1 uch void
433 1.1 uch _gsfb_putchar(void *cookie, int row, int col, u_int uc, long attr)
434 1.1 uch {
435 1.22 martin struct gsfb_softc *sc = cookie;
436 1.1 uch paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_load_cmd_8x16_psmct32);
437 1.1 uch u_int32_t *buf = (void *)MIPS_PHYS_TO_KSEG1(paddr);
438 1.22 martin struct wsdisplay_font *font = sc->sc_font;
439 1.1 uch
440 1.1 uch /* copy font data to DMA region */
441 1.1 uch gsfb_font_expand_psmct32(font, uc, attr, &buf[FONT_SCRATCH_BASE]);
442 1.1 uch
443 1.1 uch /* set destination position */
444 1.1 uch TRXPOS_DXY(buf, col * font->fontwidth, row * font->fontheight);
445 1.1 uch
446 1.1 uch /* kick to GIF */
447 1.1 uch gsfb_dma_kick(paddr, sizeof gsfb_load_cmd_8x16_psmct32);
448 1.1 uch }
449 1.1 uch
450 1.1 uch void
451 1.1 uch _gsfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
452 1.1 uch {
453 1.22 martin struct gsfb_softc *sc = cookie;
454 1.1 uch paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_copy_cmd_8x16);
455 1.1 uch u_int32_t *cmd = (void *)MIPS_PHYS_TO_KSEG1(paddr);
456 1.22 martin int y = sc->sc_font->fontheight * row;
457 1.22 martin int w = sc->sc_font->fontwidth;
458 1.1 uch int i;
459 1.1 uch
460 1.1 uch if (dstcol > srccol) {
461 1.1 uch for (i = ncols - 1; i >= 0; i--) {
462 1.1 uch TRXPOS_DXY_SXY(cmd, (dstcol + i) * w, y, (srccol + i) * w, y);
463 1.1 uch gsfb_dma_kick(paddr, sizeof gsfb_copy_cmd_8x16);
464 1.1 uch }
465 1.1 uch } else {
466 1.1 uch for (i = 0; i < ncols; i++) {
467 1.1 uch TRXPOS_DXY_SXY(cmd, (dstcol + i) * w, y, (srccol + i) * w, y);
468 1.1 uch gsfb_dma_kick(paddr, sizeof gsfb_copy_cmd_8x16);
469 1.1 uch }
470 1.1 uch }
471 1.1 uch }
472 1.1 uch
473 1.1 uch void
474 1.1 uch _gsfb_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
475 1.1 uch {
476 1.1 uch int i;
477 1.1 uch
478 1.1 uch for (i = 0; i < ncols; i++)
479 1.1 uch _gsfb_putchar(cookie, row, startcol + i, ' ', attr);
480 1.1 uch }
481 1.1 uch
482 1.1 uch void
483 1.1 uch _gsfb_copyrows(void *cookie, int src, int dst, int num)
484 1.1 uch {
485 1.22 martin struct gsfb_softc *sc = cookie;
486 1.1 uch paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_scroll_cmd_640x16);
487 1.1 uch u_int32_t *cmd = (void *)MIPS_PHYS_TO_KSEG1(paddr);
488 1.1 uch int i;
489 1.22 martin int h = sc->sc_font->fontheight;
490 1.1 uch
491 1.1 uch if (dst > src) {
492 1.1 uch for (i = num - 1; i >= 0; i--) {
493 1.1 uch TRXPOS_SY_DY(cmd, (src + i) * h, (dst + i) * h);
494 1.1 uch gsfb_dma_kick(paddr, sizeof gsfb_scroll_cmd_640x16);
495 1.1 uch }
496 1.1 uch } else {
497 1.1 uch for (i = 0; i < num; i++) {
498 1.1 uch TRXPOS_SY_DY(cmd, (src + i) * h, (dst + i) * h);
499 1.1 uch gsfb_dma_kick(paddr, sizeof gsfb_scroll_cmd_640x16);
500 1.1 uch }
501 1.1 uch }
502 1.1 uch }
503 1.1 uch
504 1.1 uch void
505 1.1 uch _gsfb_eraserows(void *cookie, int row, int nrow, long attr)
506 1.1 uch {
507 1.22 martin struct gsfb_softc *sc = cookie;
508 1.1 uch int i, j;
509 1.1 uch
510 1.1 uch for (j = 0; j < nrow; j++)
511 1.22 martin for (i = 0; i < sc->sc_screen->ncols; i++)
512 1.1 uch _gsfb_putchar(cookie, row + j, i, ' ', attr);
513 1.1 uch }
514 1.1 uch
515 1.1 uch int
516 1.4 junyoung _gsfb_allocattr(void *cookie, int fg, int bg, int flags, long *attr)
517 1.1 uch {
518 1.1 uch
519 1.1 uch if ((flags & WSATTR_BLINK) != 0)
520 1.1 uch return (EINVAL);
521 1.1 uch
522 1.1 uch if ((flags & WSATTR_WSCOLORS) == 0) {
523 1.15 christos fg = WS_DEFAULT_FG;
524 1.15 christos bg = WS_DEFAULT_BG;
525 1.1 uch }
526 1.1 uch
527 1.1 uch if ((flags & WSATTR_HILIT) != 0)
528 1.1 uch fg += 8;
529 1.1 uch
530 1.1 uch flags = (flags & WSATTR_UNDERLINE) ? 1 : 0;
531 1.1 uch
532 1.1 uch
533 1.1 uch *attr = ATTR_BG_SET(bg) | ATTR_FG_SET(fg) | flags;
534 1.1 uch
535 1.1 uch return (0);
536 1.1 uch }
537 1.1 uch
538 1.1 uch int
539 1.17 christos _gsfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
540 1.16 jmmv struct lwp *l)
541 1.1 uch {
542 1.1 uch
543 1.3 atatat return (EPASSTHROUGH); /* Inappropriate ioctl for device */
544 1.1 uch }
545 1.1 uch
546 1.1 uch paddr_t
547 1.16 jmmv _gsfb_mmap(void *v, void *vs, off_t offset, int prot)
548 1.1 uch {
549 1.1 uch
550 1.9 shin return (-1); /* can't mmap */
551 1.1 uch }
552 1.1 uch
553 1.1 uch int
554 1.1 uch _gsfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
555 1.1 uch int *curxp, int *curyp, long *attrp)
556 1.1 uch {
557 1.1 uch
558 1.15 christos *attrp = ATTR_BG_SET(WS_DEFAULT_BG) | ATTR_FG_SET(WS_DEFAULT_FG);
559 1.1 uch
560 1.1 uch return (0);
561 1.1 uch }
562 1.1 uch
563 1.1 uch void
564 1.1 uch _gsfb_free_screen(void *v, void *cookie)
565 1.1 uch {
566 1.1 uch }
567 1.1 uch
568 1.1 uch int
569 1.1 uch _gsfb_show_screen(void *v, void *cookie, int waitok,
570 1.1 uch void (*cb)(void *, int, int), void *cbarg)
571 1.1 uch {
572 1.1 uch
573 1.1 uch return (0);
574 1.1 uch }
575 1.1 uch
576 1.1 uch void
577 1.1 uch _gsfb_pollc(void *v, int on)
578 1.1 uch {
579 1.1 uch
580 1.1 uch }
581 1.1 uch
582 1.1 uch /*
583 1.1 uch * font expansion
584 1.1 uch * PSMCT32 only
585 1.1 uch */
586 1.1 uch void
587 1.1 uch gsfb_font_expand_psmct32(const struct wsdisplay_font *font, u_int c, long attr,
588 1.1 uch u_int32_t *buf)
589 1.1 uch {
590 1.1 uch u_int32_t fg, bg;
591 1.1 uch u_int8_t *bitmap;
592 1.1 uch int i, j;
593 1.1 uch
594 1.1 uch KDASSERT(((u_int32_t)buf & 15) == 0);
595 1.1 uch
596 1.1 uch fg = gsfb_ansi_psmct32[ATTR_FG_GET(attr)];
597 1.1 uch bg = gsfb_ansi_psmct32[ATTR_BG_GET(attr)];
598 1.1 uch
599 1.1 uch bitmap = (u_int8_t *)font->data + (c - font->firstchar) *
600 1.1 uch font->fontheight * font->stride;
601 1.1 uch for (i = 0; i < font->fontheight; i++, bitmap++) {
602 1.1 uch u_int32_t b = *bitmap;
603 1.1 uch for (j = 0; j < font->fontwidth; j++, b <<= 1)
604 1.1 uch *buf++ = (b & 0x80) ? fg : bg;
605 1.1 uch }
606 1.1 uch }
607 1.1 uch
608 1.1 uch void
609 1.1 uch gsfb_dma_kick(paddr_t addr, size_t size)
610 1.1 uch {
611 1.1 uch /* Wait for previous DMA request complete */
612 1.1 uch while (_reg_read_4(D2_QWC_REG))
613 1.1 uch ;
614 1.1 uch
615 1.1 uch /* Wait until GS FIFO empty */
616 1.1 uch while ((_reg_read_8(GS_S_CSR_REG) & (3 << 14)) != (1 << 14))
617 1.1 uch ;
618 1.1 uch
619 1.1 uch /* wait for DMA complete */
620 1.1 uch dmac_bus_poll(D_CH2_GIF);
621 1.1 uch
622 1.1 uch /* transfer addr */
623 1.1 uch _reg_write_4(D2_MADR_REG, addr);
624 1.1 uch /* transfer data size (unit qword) */
625 1.1 uch _reg_write_4(D2_QWC_REG, bytetoqwc(size));
626 1.1 uch
627 1.1 uch /* kick DMA (normal-mode) */
628 1.1 uch dmac_chcr_write(D_CH2_GIF, D_CHCR_STR);
629 1.1 uch }
630 1.1 uch
631 1.1 uch #ifdef GSFB_DEBUG_MONITOR
632 1.1 uch void
633 1.1 uch __gsfb_print(int window, const char *fmt, ...)
634 1.1 uch {
635 1.1 uch const struct _gsfb_debug_window *win;
636 1.1 uch int i, s, x, y, n, a;
637 1.1 uch u_int c;
638 1.1 uch va_list ap;
639 1.1 uch
640 1.1 uch if (!gsfb.initialized)
641 1.1 uch return;
642 1.1 uch
643 1.1 uch s = _intr_suspend();
644 1.1 uch win = &_gsfb_debug_window[window];
645 1.1 uch x = 0;
646 1.1 uch y = win->start;
647 1.1 uch n = win->nrow * 80;
648 1.1 uch a = win->attr;
649 1.1 uch
650 1.1 uch va_start(ap, fmt);
651 1.1 uch vsnprintf(_gsfb_debug_buf, n, fmt, ap);
652 1.1 uch va_end(ap);
653 1.1 uch
654 1.1 uch _gsfb_eraserows(0, y, win->nrow, a);
655 1.1 uch
656 1.1 uch for (i = 0; i < n &&
657 1.1 uch (c = (u_int)_gsfb_debug_buf[i] & 0x7f) != 0; i++) {
658 1.1 uch if (c == '\n')
659 1.1 uch x = 0, y++;
660 1.1 uch else
661 1.1 uch _gsfb_putchar(0, y, x++, c, a);
662 1.1 uch }
663 1.1 uch
664 1.1 uch _intr_resume(s);
665 1.1 uch }
666 1.1 uch
667 1.1 uch void
668 1.1 uch __gsfb_print_hex(int a0, int a1, int a2, int a3)
669 1.1 uch {
670 1.1 uch __gsfb_print(2, "a0=%08x a1=%08x a2=%08x a3=%08x",
671 1.1 uch a0, a1, a2, a3);
672 1.1 uch }
673 1.1 uch #endif /* GSFB_DEBUG_MONITOR */
674