1 1.24 thorpej /* $NetBSD: gsfb.c,v 1.24 2021/08/07 16:19:02 thorpej 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.24 thorpej __KERNEL_RCSID(0, "$NetBSD: gsfb.c,v 1.24 2021/08/07 16:19:02 thorpej 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.24 thorpej config_found(self, &wa, wsdisplaydevprint, CFARGS_NONE); 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