1 1.47 thorpej /* $NetBSD: zx.c,v 1.47 2021/08/07 16:19:15 thorpej Exp $ */ 2 1.1 ad 3 1.1 ad /* 4 1.1 ad * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 1.1 ad * All rights reserved. 6 1.1 ad * 7 1.1 ad * This code is derived from software contributed to The NetBSD Foundation 8 1.1 ad * by Andrew Doran. 9 1.1 ad * 10 1.1 ad * Redistribution and use in source and binary forms, with or without 11 1.1 ad * modification, are permitted provided that the following conditions 12 1.1 ad * are met: 13 1.1 ad * 1. Redistributions of source code must retain the above copyright 14 1.1 ad * notice, this list of conditions and the following disclaimer. 15 1.1 ad * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 ad * notice, this list of conditions and the following disclaimer in the 17 1.1 ad * documentation and/or other materials provided with the distribution. 18 1.1 ad * 19 1.1 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 ad * POSSIBILITY OF SUCH DAMAGE. 30 1.1 ad */ 31 1.1 ad 32 1.1 ad /* 33 1.1 ad * Driver for the Sun ZX display adapter. This would be called 'leo', but 34 1.1 ad * NetBSD/amiga already has a driver by that name. The XFree86 and Linux 35 1.1 ad * drivers were used as "living documentation" when writing this; thanks 36 1.1 ad * to the authors. 37 1.1 ad * 38 1.1 ad * Issues (which can be solved with wscons, happily enough): 39 1.1 ad * 40 1.1 ad * o There is lots of unnecessary mucking about rasops in here, primarily 41 1.1 ad * to appease the sparc fb code. 42 1.1 ad */ 43 1.1 ad 44 1.1 ad #include <sys/cdefs.h> 45 1.47 thorpej __KERNEL_RCSID(0, "$NetBSD: zx.c,v 1.47 2021/08/07 16:19:15 thorpej Exp $"); 46 1.1 ad 47 1.1 ad #include <sys/param.h> 48 1.1 ad #include <sys/systm.h> 49 1.1 ad #include <sys/device.h> 50 1.1 ad #include <sys/ioctl.h> 51 1.1 ad #include <sys/malloc.h> 52 1.1 ad #include <sys/mman.h> 53 1.1 ad #include <sys/tty.h> 54 1.1 ad #include <sys/conf.h> 55 1.1 ad #include <sys/syslog.h> 56 1.1 ad #include <sys/buf.h> 57 1.38 uebayasi #ifdef DEBUG 58 1.38 uebayasi /* for log(9) in zxioctl() */ 59 1.38 uebayasi #include <sys/lwp.h> 60 1.38 uebayasi #include <sys/proc.h> 61 1.38 uebayasi #endif 62 1.1 ad 63 1.20 ad #include <sys/bus.h> 64 1.1 ad #include <machine/autoconf.h> 65 1.1 ad 66 1.1 ad #include <dev/sun/fbio.h> 67 1.1 ad #include <dev/sun/fbvar.h> 68 1.1 ad 69 1.27 macallan #include "wsdisplay.h" 70 1.27 macallan #include <dev/wscons/wsconsio.h> 71 1.27 macallan #include <dev/wsfont/wsfont.h> 72 1.27 macallan #include <dev/rasops/rasops.h> 73 1.27 macallan #include <dev/wscons/wsdisplay_vconsvar.h> 74 1.27 macallan 75 1.27 macallan #include "opt_wsemul.h" 76 1.27 macallan 77 1.1 ad #include <dev/sbus/zxreg.h> 78 1.1 ad #include <dev/sbus/zxvar.h> 79 1.1 ad #include <dev/sbus/sbusvar.h> 80 1.1 ad 81 1.1 ad #include <dev/wscons/wsconsio.h> 82 1.1 ad 83 1.32 tsutsui #include "ioconf.h" 84 1.32 tsutsui 85 1.1 ad #define ZX_STD_ROP (ZX_ROP_NEW | ZX_ATTR_WE_ENABLE | \ 86 1.1 ad ZX_ATTR_OE_ENABLE | ZX_ATTR_FORCE_WID) 87 1.1 ad 88 1.27 macallan static void zx_attach(device_t, device_t, void *); 89 1.29 cegger static int zx_match(device_t, cfdata_t, void *); 90 1.1 ad 91 1.27 macallan static void zx_blank(device_t); 92 1.27 macallan static int zx_cmap_put(struct zx_softc *); 93 1.27 macallan static void zx_copyrect(struct zx_softc *, int, int, int, int, int, int); 94 1.27 macallan static int zx_cross_loadwid(struct zx_softc *, u_int, u_int, u_int); 95 1.27 macallan static int zx_cross_wait(struct zx_softc *); 96 1.27 macallan static void zx_fillrect(struct zx_softc *, int, int, int, int, uint32_t, int); 97 1.27 macallan static int zx_intr(void *); 98 1.27 macallan static void zx_reset(struct zx_softc *); 99 1.27 macallan static void zx_unblank(device_t); 100 1.27 macallan 101 1.27 macallan static void zx_cursor_blank(struct zx_softc *); 102 1.27 macallan static void zx_cursor_color(struct zx_softc *); 103 1.27 macallan static void zx_cursor_move(struct zx_softc *); 104 1.27 macallan static void zx_cursor_set(struct zx_softc *); 105 1.27 macallan static void zx_cursor_unblank(struct zx_softc *); 106 1.27 macallan 107 1.27 macallan static void zx_copycols(void *, int, int, int, int); 108 1.27 macallan static void zx_copyrows(void *, int, int, int); 109 1.27 macallan static void zx_do_cursor(void *, int, int, int); 110 1.27 macallan static void zx_erasecols(void *, int, int, int, long); 111 1.27 macallan static void zx_eraserows(void *, int, int, long); 112 1.27 macallan static void zx_putchar(void *, int, int, u_int, long); 113 1.1 ad 114 1.1 ad struct zx_mmo { 115 1.1 ad off_t mo_va; 116 1.1 ad off_t mo_pa; 117 1.1 ad off_t mo_size; 118 1.1 ad } static const zx_mmo[] = { 119 1.1 ad { ZX_FB0_VOFF, ZX_OFF_SS0, 0x00800000 }, 120 1.1 ad { ZX_LC0_VOFF, ZX_OFF_LC_SS0_USR, 0x00001000 }, 121 1.1 ad { ZX_LD0_VOFF, ZX_OFF_LD_SS0, 0x00001000 }, 122 1.1 ad { ZX_LX0_CURSOR_VOFF, ZX_OFF_LX_CURSOR, 0x00001000 }, 123 1.1 ad { ZX_FB1_VOFF, ZX_OFF_SS1, 0x00800000 }, 124 1.1 ad { ZX_LC1_VOFF, ZX_OFF_LC_SS1_USR, 0x00001000 }, 125 1.1 ad { ZX_LD1_VOFF, ZX_OFF_LD_SS1, 0x00001000 }, 126 1.1 ad { ZX_LX_KRN_VOFF, ZX_OFF_LX_CROSS, 0x00001000 }, 127 1.1 ad { ZX_LC0_KRN_VOFF, ZX_OFF_LC_SS0_KRN, 0x00001000 }, 128 1.1 ad { ZX_LC1_KRN_VOFF, ZX_OFF_LC_SS1_KRN, 0x00001000 }, 129 1.1 ad { ZX_LD_GBL_VOFF, ZX_OFF_LD_GBL, 0x00001000 }, 130 1.14 perry }; 131 1.1 ad 132 1.27 macallan CFATTACH_DECL_NEW(zx, sizeof(struct zx_softc), 133 1.5 thorpej zx_match, zx_attach, NULL, NULL); 134 1.1 ad 135 1.27 macallan static dev_type_open(zxopen); 136 1.27 macallan static dev_type_close(zxclose); 137 1.27 macallan static dev_type_ioctl(zxioctl); 138 1.27 macallan static dev_type_mmap(zxmmap); 139 1.1 ad 140 1.1 ad static struct fbdriver zx_fbdriver = { 141 1.1 ad zx_unblank, zxopen, zxclose, zxioctl, nopoll, zxmmap 142 1.1 ad }; 143 1.1 ad 144 1.27 macallan struct wsscreen_descr zx_defaultscreen = { 145 1.27 macallan "std", 146 1.27 macallan 0, 0, /* will be filled in -- XXX shouldn't, it's global */ 147 1.27 macallan /* doesn't matter - you can't really have more than one leo */ 148 1.27 macallan NULL, /* textops */ 149 1.27 macallan 8, 16, /* font width/height */ 150 1.27 macallan WSSCREEN_WSCOLORS, /* capabilities */ 151 1.27 macallan NULL /* modecookie */ 152 1.27 macallan }; 153 1.27 macallan 154 1.27 macallan static int zx_ioctl(void *, void *, u_long, void *, int, struct lwp *); 155 1.27 macallan static paddr_t zx_mmap(void *, void *, off_t, int); 156 1.27 macallan static void zx_init_screen(void *, struct vcons_screen *, int, long *); 157 1.27 macallan 158 1.27 macallan static int zx_putcmap(struct zx_softc *, struct wsdisplay_cmap *); 159 1.27 macallan static int zx_getcmap(struct zx_softc *, struct wsdisplay_cmap *); 160 1.27 macallan 161 1.27 macallan struct wsdisplay_accessops zx_accessops = { 162 1.27 macallan zx_ioctl, 163 1.27 macallan zx_mmap, 164 1.27 macallan NULL, /* alloc_screen */ 165 1.27 macallan NULL, /* free_screen */ 166 1.27 macallan NULL, /* show_screen */ 167 1.27 macallan NULL, /* load_font */ 168 1.27 macallan NULL, /* pollc */ 169 1.27 macallan NULL /* scroll */ 170 1.27 macallan }; 171 1.27 macallan 172 1.27 macallan const struct wsscreen_descr *_zx_scrlist[] = { 173 1.27 macallan &zx_defaultscreen 174 1.27 macallan }; 175 1.27 macallan 176 1.27 macallan struct wsscreen_list zx_screenlist = { 177 1.27 macallan sizeof(_zx_scrlist) / sizeof(struct wsscreen_descr *), 178 1.27 macallan _zx_scrlist 179 1.27 macallan }; 180 1.27 macallan 181 1.27 macallan 182 1.27 macallan extern const u_char rasops_cmap[768]; 183 1.27 macallan 184 1.27 macallan static struct vcons_screen zx_console_screen; 185 1.27 macallan 186 1.27 macallan static int 187 1.29 cegger zx_match(device_t parent, cfdata_t cf, void *aux) 188 1.1 ad { 189 1.1 ad struct sbus_attach_args *sa; 190 1.14 perry 191 1.1 ad sa = (struct sbus_attach_args *)aux; 192 1.1 ad 193 1.1 ad return (strcmp(sa->sa_name, "SUNW,leo") == 0); 194 1.1 ad } 195 1.1 ad 196 1.27 macallan static void 197 1.27 macallan zx_attach(device_t parent, device_t self, void *args) 198 1.1 ad { 199 1.1 ad struct zx_softc *sc; 200 1.1 ad struct sbus_attach_args *sa; 201 1.1 ad bus_space_handle_t bh; 202 1.1 ad bus_space_tag_t bt; 203 1.1 ad struct fbdevice *fb; 204 1.27 macallan struct wsemuldisplaydev_attach_args aa; 205 1.27 macallan struct rasops_info *ri = &zx_console_screen.scr_ri; 206 1.27 macallan unsigned long defattr; 207 1.28 macallan int isconsole, width, height; 208 1.1 ad 209 1.24 drochner sc = device_private(self); 210 1.27 macallan sc->sc_dv = self; 211 1.27 macallan 212 1.1 ad sa = args; 213 1.1 ad fb = &sc->sc_fb; 214 1.1 ad bt = sa->sa_bustag; 215 1.1 ad sc->sc_bt = bt; 216 1.1 ad sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset); 217 1.1 ad 218 1.30 macallan if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0, 219 1.30 macallan 0x800000, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, &bh) != 0) { 220 1.21 cegger aprint_error_dev(self, "can't map bits\n"); 221 1.1 ad return; 222 1.1 ad } 223 1.19 christos fb->fb_pixels = (void *)bus_space_vaddr(bt, bh); 224 1.33 tsutsui sc->sc_pixels = (uint32_t *)fb->fb_pixels; 225 1.1 ad 226 1.1 ad if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR, 227 1.1 ad PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 228 1.21 cegger aprint_error_dev(self, "can't map zc\n"); 229 1.1 ad return; 230 1.1 ad } 231 1.27 macallan 232 1.25 tsutsui sc->sc_bhzc = bh; 233 1.1 ad 234 1.1 ad if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0, 235 1.1 ad PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 236 1.21 cegger aprint_error_dev(self, "can't map ld/ss0\n"); 237 1.1 ad return; 238 1.1 ad } 239 1.25 tsutsui sc->sc_bhzdss0 = bh; 240 1.1 ad 241 1.1 ad if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1, 242 1.1 ad PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 243 1.21 cegger aprint_error_dev(self, "can't map ld/ss1\n"); 244 1.1 ad return; 245 1.1 ad } 246 1.25 tsutsui sc->sc_bhzdss1 = bh; 247 1.1 ad 248 1.1 ad if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS, 249 1.1 ad PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 250 1.21 cegger aprint_error_dev(self, "can't map zx\n"); 251 1.1 ad return; 252 1.1 ad } 253 1.25 tsutsui sc->sc_bhzx = bh; 254 1.1 ad 255 1.1 ad if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR, 256 1.1 ad PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 257 1.21 cegger aprint_error_dev(self, "can't map zcu\n"); 258 1.1 ad return; 259 1.1 ad } 260 1.25 tsutsui sc->sc_bhzcu = bh; 261 1.1 ad 262 1.1 ad fb->fb_driver = &zx_fbdriver; 263 1.27 macallan fb->fb_device = sc->sc_dv; 264 1.27 macallan fb->fb_flags = device_cfdata(sc->sc_dv)->cf_flags & FB_USERMASK; 265 1.1 ad fb->fb_pfour = NULL; 266 1.26 tsutsui fb->fb_linebytes = prom_getpropint(sa->sa_node, "linebytes", 8192); 267 1.1 ad 268 1.26 tsutsui width = prom_getpropint(sa->sa_node, "width", 1280); 269 1.26 tsutsui height = prom_getpropint(sa->sa_node, "height", 1024); 270 1.26 tsutsui fb_setsize_obp(fb, 32, width, height, sa->sa_node); 271 1.1 ad 272 1.1 ad fb->fb_type.fb_cmsize = 256; 273 1.1 ad fb->fb_type.fb_depth = 32; 274 1.1 ad fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes; 275 1.1 ad fb->fb_type.fb_type = FBTYPE_SUNLEO; 276 1.1 ad 277 1.1 ad printf(": %d x %d", fb->fb_type.fb_width, fb->fb_type.fb_height); 278 1.1 ad isconsole = fb_is_console(sa->sa_node); 279 1.1 ad if (isconsole) 280 1.1 ad printf(" (console)"); 281 1.1 ad printf("\n"); 282 1.1 ad 283 1.1 ad if (sa->sa_nintr != 0) 284 1.6 pk bus_intr_establish(bt, sa->sa_pri, IPL_NONE, zx_intr, sc); 285 1.1 ad 286 1.45 chs sc->sc_cmap = malloc(768, M_DEVBUF, M_WAITOK); 287 1.1 ad zx_reset(sc); 288 1.1 ad 289 1.27 macallan sc->sc_width = fb->fb_type.fb_width; 290 1.27 macallan sc->sc_stride = 8192; /* 32 bit */ 291 1.27 macallan sc->sc_height = fb->fb_type.fb_height; 292 1.27 macallan 293 1.27 macallan /* setup rasops and so on for wsdisplay */ 294 1.27 macallan wsfont_init(); 295 1.27 macallan sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 296 1.27 macallan sc->sc_bg = WS_DEFAULT_BG; 297 1.27 macallan 298 1.27 macallan vcons_init(&sc->vd, sc, &zx_defaultscreen, &zx_accessops); 299 1.27 macallan sc->vd.init_screen = zx_init_screen; 300 1.27 macallan 301 1.27 macallan if (isconsole) { 302 1.27 macallan /* we mess with zx_console_screen only once */ 303 1.27 macallan vcons_init_screen(&sc->vd, &zx_console_screen, 1, 304 1.27 macallan &defattr); 305 1.27 macallan zx_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 306 1.27 macallan 307 1.27 macallan zx_defaultscreen.textops = &ri->ri_ops; 308 1.27 macallan zx_defaultscreen.capabilities = WSSCREEN_WSCOLORS; 309 1.27 macallan zx_defaultscreen.nrows = ri->ri_rows; 310 1.27 macallan zx_defaultscreen.ncols = ri->ri_cols; 311 1.28 macallan zx_fillrect(sc, 0, 0, width, height, 312 1.28 macallan ri->ri_devcmap[defattr >> 16], ZX_STD_ROP); 313 1.34 macallan wsdisplay_cnattach(&zx_defaultscreen, ri, 0, 0, defattr); 314 1.34 macallan vcons_replay_msgbuf(&zx_console_screen); 315 1.27 macallan } else { 316 1.27 macallan /* 317 1.27 macallan * we're not the console so we just clear the screen and don't 318 1.27 macallan * set up any sort of text display 319 1.27 macallan */ 320 1.27 macallan if (zx_defaultscreen.textops == NULL) { 321 1.27 macallan /* 322 1.27 macallan * ugly, but... 323 1.27 macallan * we want the console settings to win, so we only 324 1.27 macallan * touch anything when we find an untouched screen 325 1.27 macallan * definition. In this case we fill it from fb to 326 1.27 macallan * avoid problems in case no zx is the console 327 1.27 macallan */ 328 1.27 macallan zx_defaultscreen.textops = &ri->ri_ops; 329 1.27 macallan zx_defaultscreen.capabilities = ri->ri_caps; 330 1.27 macallan zx_defaultscreen.nrows = ri->ri_rows; 331 1.27 macallan zx_defaultscreen.ncols = ri->ri_cols; 332 1.27 macallan } 333 1.27 macallan } 334 1.1 ad 335 1.27 macallan aa.scrdata = &zx_screenlist; 336 1.27 macallan aa.console = isconsole; 337 1.27 macallan aa.accessops = &zx_accessops; 338 1.27 macallan aa.accesscookie = &sc->vd; 339 1.47 thorpej config_found(sc->sc_dv, &aa, wsemuldisplaydevprint, CFARGS_NONE); 340 1.27 macallan fb_attach(&sc->sc_fb, isconsole); 341 1.1 ad } 342 1.1 ad 343 1.27 macallan static int 344 1.16 christos zxopen(dev_t dev, int flags, int mode, struct lwp *l) 345 1.1 ad { 346 1.1 ad 347 1.1 ad if (device_lookup(&zx_cd, minor(dev)) == NULL) 348 1.1 ad return (ENXIO); 349 1.1 ad return (0); 350 1.1 ad } 351 1.1 ad 352 1.27 macallan static int 353 1.16 christos zxclose(dev_t dev, int flags, int mode, struct lwp *l) 354 1.1 ad { 355 1.1 ad struct zx_softc *sc; 356 1.1 ad 357 1.23 cegger sc = device_lookup_private(&zx_cd, minor(dev)); 358 1.1 ad 359 1.1 ad zx_reset(sc); 360 1.1 ad zx_cursor_blank(sc); 361 1.1 ad return (0); 362 1.1 ad } 363 1.1 ad 364 1.27 macallan static int 365 1.19 christos zxioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 366 1.1 ad { 367 1.1 ad struct zx_softc *sc; 368 1.1 ad struct fbcmap *cm; 369 1.1 ad struct fbcursor *cu; 370 1.13 chs uint32_t curbits[2][32]; 371 1.40 christos int rv, v, count, i, error; 372 1.1 ad 373 1.23 cegger sc = device_lookup_private(&zx_cd, minor(dev)); 374 1.14 perry 375 1.1 ad switch (cmd) { 376 1.1 ad case FBIOGTYPE: 377 1.1 ad *(struct fbtype *)data = sc->sc_fb.fb_type; 378 1.1 ad break; 379 1.1 ad 380 1.1 ad case FBIOGATTR: 381 1.1 ad #define fba ((struct fbgattr *)data) 382 1.1 ad fba->real_type = sc->sc_fb.fb_type.fb_type; 383 1.1 ad fba->owner = 0; /* XXX ??? */ 384 1.1 ad fba->fbtype = sc->sc_fb.fb_type; 385 1.1 ad fba->sattr.flags = 0; 386 1.1 ad fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 387 1.1 ad fba->sattr.dev_specific[0] = -1; 388 1.1 ad fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 389 1.1 ad fba->emu_types[1] = -1; 390 1.1 ad fba->emu_types[2] = -1; 391 1.1 ad #undef fba 392 1.1 ad break; 393 1.1 ad 394 1.1 ad case FBIOGVIDEO: 395 1.1 ad *(int *)data = ((sc->sc_flags & ZX_BLANKED) != 0); 396 1.1 ad break; 397 1.1 ad 398 1.1 ad case FBIOSVIDEO: 399 1.1 ad if (*(int *)data) 400 1.27 macallan zx_unblank(sc->sc_dv); 401 1.1 ad else 402 1.27 macallan zx_blank(sc->sc_dv); 403 1.1 ad break; 404 1.1 ad 405 1.1 ad case FBIOGETCMAP: 406 1.1 ad cm = (struct fbcmap *)data; 407 1.1 ad if (cm->index > 256 || cm->count > 256 - cm->index) 408 1.1 ad return (EINVAL); 409 1.1 ad rv = copyout(sc->sc_cmap + cm->index, cm->red, cm->count); 410 1.2 ad if (rv == 0) 411 1.1 ad rv = copyout(sc->sc_cmap + 256 + cm->index, cm->green, 412 1.1 ad cm->count); 413 1.2 ad if (rv == 0) 414 1.1 ad rv = copyout(sc->sc_cmap + 512 + cm->index, cm->blue, 415 1.1 ad cm->count); 416 1.1 ad return (rv); 417 1.1 ad 418 1.1 ad case FBIOPUTCMAP: 419 1.1 ad cm = (struct fbcmap *)data; 420 1.1 ad if (cm->index > 256 || cm->count > 256 - cm->index) 421 1.1 ad return (EINVAL); 422 1.1 ad rv = copyin(cm->red, sc->sc_cmap + cm->index, cm->count); 423 1.2 ad if (rv == 0) 424 1.1 ad rv = copyin(cm->green, sc->sc_cmap + 256 + cm->index, 425 1.1 ad cm->count); 426 1.2 ad if (rv == 0) 427 1.1 ad rv = copyin(cm->blue, sc->sc_cmap + 512 + cm->index, 428 1.1 ad cm->count); 429 1.1 ad zx_cmap_put(sc); 430 1.1 ad return (rv); 431 1.1 ad 432 1.1 ad case FBIOGCURPOS: 433 1.1 ad *(struct fbcurpos *)data = sc->sc_curpos; 434 1.1 ad break; 435 1.1 ad 436 1.1 ad case FBIOSCURPOS: 437 1.1 ad sc->sc_curpos = *(struct fbcurpos *)data; 438 1.1 ad zx_cursor_move(sc); 439 1.1 ad break; 440 1.1 ad 441 1.1 ad case FBIOGCURMAX: 442 1.1 ad ((struct fbcurpos *)data)->x = 32; 443 1.1 ad ((struct fbcurpos *)data)->y = 32; 444 1.1 ad break; 445 1.1 ad 446 1.1 ad case FBIOSCURSOR: 447 1.1 ad cu = (struct fbcursor *)data; 448 1.1 ad v = cu->set; 449 1.1 ad 450 1.1 ad if ((v & FB_CUR_SETSHAPE) != 0) { 451 1.1 ad if ((u_int)cu->size.x > 32 || (u_int)cu->size.y > 32) 452 1.1 ad return (EINVAL); 453 1.1 ad count = cu->size.y * 4; 454 1.13 chs rv = copyin(cu->mask, curbits[0], count); 455 1.13 chs if (rv) 456 1.13 chs return rv; 457 1.13 chs rv = copyin(cu->image, curbits[1], count); 458 1.13 chs if (rv) 459 1.13 chs return rv; 460 1.1 ad } 461 1.1 ad if ((v & FB_CUR_SETCUR) != 0) { 462 1.1 ad if (cu->enable) 463 1.1 ad zx_cursor_unblank(sc); 464 1.1 ad else 465 1.1 ad zx_cursor_blank(sc); 466 1.1 ad } 467 1.1 ad if ((v & (FB_CUR_SETPOS | FB_CUR_SETHOT)) != 0) { 468 1.1 ad if ((v & FB_CUR_SETPOS) != 0) 469 1.1 ad sc->sc_curpos = cu->pos; 470 1.1 ad if ((v & FB_CUR_SETHOT) != 0) 471 1.1 ad sc->sc_curhot = cu->hot; 472 1.1 ad zx_cursor_move(sc); 473 1.1 ad } 474 1.1 ad if ((v & FB_CUR_SETCMAP) != 0) { 475 1.1 ad if (cu->cmap.index > 2 || 476 1.1 ad cu->cmap.count > 2 - cu->cmap.index) 477 1.1 ad return (EINVAL); 478 1.43 thorpej 479 1.43 thorpej uint8_t red[2], green[2], blue[2]; 480 1.43 thorpej const u_int cnt = cu->cmap.count; 481 1.43 thorpej 482 1.43 thorpej if (cnt && 483 1.43 thorpej ((error = copyin(cu->cmap.red, red, cnt)) || 484 1.43 thorpej (error = copyin(cu->cmap.green, green, cnt)) || 485 1.43 thorpej (error = copyin(cu->cmap.blue, blue, cnt)))) { 486 1.43 thorpej return error; 487 1.43 thorpej } 488 1.43 thorpej 489 1.43 thorpej for (i = 0; i < cnt; i++) { 490 1.43 thorpej sc->sc_curcmap[i + cu->cmap.index + 0] = 491 1.43 thorpej red[i]; 492 1.43 thorpej sc->sc_curcmap[i + cu->cmap.index + 2] = 493 1.43 thorpej green[i]; 494 1.43 thorpej sc->sc_curcmap[i + cu->cmap.index + 4] = 495 1.43 thorpej blue[i]; 496 1.1 ad } 497 1.1 ad zx_cursor_color(sc); 498 1.1 ad } 499 1.1 ad if ((v & FB_CUR_SETSHAPE) != 0) { 500 1.1 ad sc->sc_cursize = cu->size; 501 1.1 ad count = cu->size.y * 4; 502 1.1 ad memset(sc->sc_curbits, 0, sizeof(sc->sc_curbits)); 503 1.13 chs memcpy(sc->sc_curbits[0], curbits[0], count); 504 1.13 chs memcpy(sc->sc_curbits[1], curbits[1], count); 505 1.1 ad zx_cursor_set(sc); 506 1.1 ad } 507 1.1 ad break; 508 1.1 ad 509 1.1 ad case FBIOGCURSOR: 510 1.1 ad cu = (struct fbcursor *)data; 511 1.1 ad 512 1.1 ad cu->set = FB_CUR_SETALL; 513 1.1 ad cu->enable = ((sc->sc_flags & ZX_CURSOR) != 0); 514 1.1 ad cu->pos = sc->sc_curpos; 515 1.1 ad cu->hot = sc->sc_curhot; 516 1.1 ad cu->size = sc->sc_cursize; 517 1.1 ad 518 1.1 ad if (cu->image != NULL) { 519 1.1 ad count = sc->sc_cursize.y * 4; 520 1.13 chs rv = copyout(sc->sc_curbits[1], cu->image, count); 521 1.1 ad if (rv) 522 1.1 ad return (rv); 523 1.13 chs rv = copyout(sc->sc_curbits[0], cu->mask, count); 524 1.1 ad if (rv) 525 1.1 ad return (rv); 526 1.1 ad } 527 1.1 ad if (cu->cmap.red != NULL) { 528 1.40 christos uint8_t red[2], green[2], blue[2]; 529 1.40 christos const uint8_t *ccm = sc->sc_curcmap; 530 1.40 christos cm = &cu->cmap; 531 1.40 christos 532 1.40 christos if (cm->index > 2 || cm->count > 2 - cm->index) 533 1.40 christos return EINVAL; 534 1.40 christos 535 1.40 christos for (i = 0; i < cm->count; i++) { 536 1.40 christos red[i] = ccm[i + cm->index + 0]; 537 1.40 christos green[i] = ccm[i + cm->index + 2]; 538 1.40 christos blue[i] = ccm[i + cm->index + 4]; 539 1.1 ad } 540 1.40 christos 541 1.40 christos if ((error = copyout(red, cm->red, cm->count)) || 542 1.40 christos (error = copyout(green, cm->green, cm->count)) || 543 1.40 christos (error = copyout(blue, cm->blue, cm->count))) 544 1.40 christos return error; 545 1.1 ad } else { 546 1.1 ad cu->cmap.index = 0; 547 1.1 ad cu->cmap.count = 2; 548 1.1 ad } 549 1.1 ad break; 550 1.1 ad 551 1.1 ad default: 552 1.1 ad #ifdef DEBUG 553 1.1 ad log(LOG_NOTICE, "zxioctl(0x%lx) (%s[%d])\n", cmd, 554 1.18 jdc l->l_proc->p_comm, l->l_proc->p_pid); 555 1.1 ad #endif 556 1.1 ad return (ENOTTY); 557 1.1 ad } 558 1.1 ad 559 1.1 ad return (0); 560 1.1 ad } 561 1.1 ad 562 1.27 macallan static int 563 1.1 ad zx_intr(void *cookie) 564 1.1 ad { 565 1.1 ad 566 1.1 ad return (1); 567 1.1 ad } 568 1.1 ad 569 1.27 macallan static void 570 1.1 ad zx_reset(struct zx_softc *sc) 571 1.1 ad { 572 1.1 ad struct fbtype *fbt; 573 1.1 ad u_int i; 574 1.1 ad 575 1.1 ad fbt = &sc->sc_fb.fb_type; 576 1.1 ad 577 1.1 ad zx_cross_loadwid(sc, ZX_WID_DBL_8, 0, 0x2c0); 578 1.1 ad zx_cross_loadwid(sc, ZX_WID_DBL_8, 1, 0x30); 579 1.1 ad zx_cross_loadwid(sc, ZX_WID_DBL_8, 2, 0x20); 580 1.1 ad zx_cross_loadwid(sc, ZX_WID_DBL_24, 1, 0x30); 581 1.1 ad 582 1.25 tsutsui i = bus_space_read_4(sc->sc_bt, sc->sc_bhzdss1, zd_misc); 583 1.1 ad i |= ZX_SS1_MISC_ENABLE; 584 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss1, zd_misc, i); 585 1.1 ad 586 1.27 macallan bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_wid, 1); 587 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_widclip, 0); 588 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_wmask, 0xffff); 589 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_vclipmin, 0); 590 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_vclipmax, 591 1.1 ad (fbt->fb_width - 1) | ((fbt->fb_height - 1) << 16)); 592 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_fg, 0); 593 1.27 macallan bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_planemask, 0xffffffff); 594 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, ZX_STD_ROP); 595 1.1 ad 596 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_extent, 597 1.1 ad (fbt->fb_width - 1) | ((fbt->fb_height - 1) << 11)); 598 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_addrspace, 599 1.25 tsutsui ZX_ADDRSPC_FONT_OBGR); 600 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_fontt, 0); 601 1.1 ad 602 1.1 ad for (i = 0; i < 256; i++) { 603 1.1 ad sc->sc_cmap[i] = rasops_cmap[i * 3]; 604 1.1 ad sc->sc_cmap[i + 256] = rasops_cmap[i * 3 + 1]; 605 1.1 ad sc->sc_cmap[i + 512] = rasops_cmap[i * 3 + 2]; 606 1.1 ad } 607 1.1 ad 608 1.1 ad zx_cmap_put(sc); 609 1.1 ad } 610 1.1 ad 611 1.27 macallan static int 612 1.1 ad zx_cross_wait(struct zx_softc *sc) 613 1.1 ad { 614 1.1 ad int i; 615 1.1 ad 616 1.1 ad for (i = 300000; i != 0; i--) { 617 1.25 tsutsui if ((bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr) & 618 1.25 tsutsui ZX_CROSS_CSR_PROGRESS) == 0) 619 1.1 ad break; 620 1.1 ad DELAY(1); 621 1.1 ad } 622 1.1 ad 623 1.1 ad if (i == 0) 624 1.1 ad printf("zx_cross_wait: timed out\n"); 625 1.1 ad 626 1.1 ad return (i); 627 1.1 ad } 628 1.1 ad 629 1.27 macallan static int 630 1.1 ad zx_cross_loadwid(struct zx_softc *sc, u_int type, u_int index, u_int value) 631 1.1 ad { 632 1.12 chs u_int tmp = 0; 633 1.1 ad 634 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_WID); 635 1.1 ad 636 1.1 ad if (zx_cross_wait(sc)) 637 1.1 ad return (1); 638 1.1 ad 639 1.1 ad if (type == ZX_WID_DBL_8) 640 1.1 ad tmp = (index & 0x0f) + 0x40; 641 1.1 ad else if (type == ZX_WID_DBL_24) 642 1.1 ad tmp = index & 0x3f; 643 1.1 ad 644 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, 0x5800 + tmp); 645 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_value, value); 646 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_WID); 647 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr, 648 1.25 tsutsui ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2); 649 1.1 ad 650 1.1 ad return (0); 651 1.1 ad } 652 1.1 ad 653 1.27 macallan static int 654 1.1 ad zx_cmap_put(struct zx_softc *sc) 655 1.1 ad { 656 1.1 ad const u_char *b; 657 1.1 ad u_int i, t; 658 1.1 ad 659 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_CLUT0); 660 1.27 macallan 661 1.27 macallan zx_cross_wait(sc); 662 1.1 ad 663 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, 664 1.25 tsutsui ZX_CROSS_TYPE_CLUTDATA); 665 1.1 ad 666 1.1 ad for (i = 0, b = sc->sc_cmap; i < 256; i++) { 667 1.1 ad t = b[i]; 668 1.1 ad t |= b[i + 256] << 8; 669 1.1 ad t |= b[i + 512] << 16; 670 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_value, t); 671 1.1 ad } 672 1.1 ad 673 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_CLUT0); 674 1.25 tsutsui i = bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr); 675 1.1 ad i = i | ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2; 676 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr, i); 677 1.1 ad return (0); 678 1.1 ad } 679 1.1 ad 680 1.27 macallan static void 681 1.1 ad zx_cursor_move(struct zx_softc *sc) 682 1.1 ad { 683 1.1 ad int sx, sy, x, y; 684 1.1 ad 685 1.1 ad x = sc->sc_curpos.x - sc->sc_curhot.x; 686 1.1 ad y = sc->sc_curpos.y - sc->sc_curhot.y; 687 1.1 ad 688 1.1 ad if (x < 0) { 689 1.42 riastrad sx = uimin(-x, 32); 690 1.1 ad x = 0; 691 1.1 ad } else 692 1.1 ad sx = 0; 693 1.1 ad 694 1.1 ad if (y < 0) { 695 1.42 riastrad sy = uimin(-y, 32); 696 1.1 ad y = 0; 697 1.1 ad } else 698 1.1 ad sy = 0; 699 1.1 ad 700 1.1 ad if (sx != sc->sc_shiftx || sy != sc->sc_shifty) { 701 1.1 ad sc->sc_shiftx = sx; 702 1.1 ad sc->sc_shifty = sy; 703 1.1 ad zx_cursor_set(sc); 704 1.1 ad } 705 1.1 ad 706 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_sxy, 707 1.25 tsutsui ((y & 0x7ff) << 11) | (x & 0x7ff)); 708 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 709 1.25 tsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x30); 710 1.1 ad 711 1.1 ad /* XXX Necessary? */ 712 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 713 1.25 tsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x80); 714 1.1 ad } 715 1.1 ad 716 1.27 macallan static void 717 1.1 ad zx_cursor_set(struct zx_softc *sc) 718 1.1 ad { 719 1.1 ad int i, j, data; 720 1.1 ad 721 1.2 ad if ((sc->sc_flags & ZX_CURSOR) != 0) 722 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 723 1.25 tsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) & 724 1.25 tsutsui ~0x80); 725 1.1 ad 726 1.1 ad for (j = 0; j < 2; j++) { 727 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_type, 0x20 << j); 728 1.2 ad 729 1.1 ad for (i = sc->sc_shifty; i < 32; i++) { 730 1.1 ad data = sc->sc_curbits[j][i]; 731 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data, 732 1.25 tsutsui data >> sc->sc_shiftx); 733 1.1 ad } 734 1.1 ad for (i = sc->sc_shifty; i != 0; i--) 735 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data, 0); 736 1.1 ad } 737 1.2 ad 738 1.2 ad if ((sc->sc_flags & ZX_CURSOR) != 0) 739 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 740 1.25 tsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x80); 741 1.1 ad } 742 1.1 ad 743 1.27 macallan static void 744 1.1 ad zx_cursor_blank(struct zx_softc *sc) 745 1.1 ad { 746 1.1 ad 747 1.1 ad sc->sc_flags &= ~ZX_CURSOR; 748 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 749 1.25 tsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) & ~0x80); 750 1.1 ad } 751 1.1 ad 752 1.27 macallan static void 753 1.1 ad zx_cursor_unblank(struct zx_softc *sc) 754 1.1 ad { 755 1.1 ad 756 1.1 ad sc->sc_flags |= ZX_CURSOR; 757 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 758 1.25 tsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x80); 759 1.1 ad } 760 1.1 ad 761 1.27 macallan static void 762 1.1 ad zx_cursor_color(struct zx_softc *sc) 763 1.1 ad { 764 1.33 tsutsui uint8_t tmp; 765 1.1 ad 766 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_type, 0x50); 767 1.1 ad 768 1.1 ad tmp = sc->sc_curcmap[0] | (sc->sc_curcmap[2] << 8) | 769 1.1 ad (sc->sc_curcmap[4] << 16); 770 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data, tmp); 771 1.1 ad 772 1.1 ad tmp = sc->sc_curcmap[1] | (sc->sc_curcmap[3] << 8) | 773 1.1 ad (sc->sc_curcmap[5] << 16); 774 1.44 thorpej bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data, tmp); 775 1.1 ad 776 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 777 1.25 tsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x03); 778 1.1 ad } 779 1.1 ad 780 1.27 macallan static void 781 1.27 macallan zx_blank(device_t dv) 782 1.1 ad { 783 1.1 ad struct zx_softc *sc; 784 1.1 ad 785 1.24 drochner sc = device_private(dv); 786 1.1 ad 787 1.1 ad if ((sc->sc_flags & ZX_BLANKED) != 0) 788 1.1 ad return; 789 1.1 ad sc->sc_flags |= ZX_BLANKED; 790 1.1 ad 791 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_VIDEO); 792 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr, 793 1.25 tsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr) & 794 1.25 tsutsui ~ZX_CROSS_CSR_ENABLE); 795 1.1 ad } 796 1.1 ad 797 1.27 macallan static void 798 1.27 macallan zx_unblank(device_t dv) 799 1.1 ad { 800 1.1 ad struct zx_softc *sc; 801 1.1 ad 802 1.24 drochner sc = device_private(dv); 803 1.1 ad 804 1.1 ad if ((sc->sc_flags & ZX_BLANKED) == 0) 805 1.1 ad return; 806 1.1 ad sc->sc_flags &= ~ZX_BLANKED; 807 1.1 ad 808 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_VIDEO); 809 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr, 810 1.25 tsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr) | 811 1.25 tsutsui ZX_CROSS_CSR_ENABLE); 812 1.1 ad } 813 1.1 ad 814 1.27 macallan static paddr_t 815 1.1 ad zxmmap(dev_t dev, off_t off, int prot) 816 1.1 ad { 817 1.1 ad struct zx_softc *sc; 818 1.15 tsutsui const struct zx_mmo *mm, *mmmax; 819 1.2 ad 820 1.23 cegger sc = device_lookup_private(&zx_cd, minor(dev)); 821 1.2 ad off = trunc_page(off); 822 1.1 ad mm = zx_mmo; 823 1.15 tsutsui mmmax = mm + sizeof(zx_mmo) / sizeof(zx_mmo[0]); 824 1.1 ad 825 1.15 tsutsui for (; mm < mmmax; mm++) 826 1.1 ad if (off >= mm->mo_va && off < mm->mo_va + mm->mo_size) { 827 1.1 ad off = off - mm->mo_va + mm->mo_pa; 828 1.1 ad return (bus_space_mmap(sc->sc_bt, sc->sc_paddr, 829 1.1 ad off, prot, BUS_SPACE_MAP_LINEAR)); 830 1.1 ad } 831 1.1 ad 832 1.1 ad return (-1); 833 1.1 ad } 834 1.1 ad 835 1.27 macallan static void 836 1.27 macallan zx_fillrect(struct zx_softc *sc, int x, int y, int w, int h, uint32_t bg, 837 1.1 ad int rop) 838 1.1 ad { 839 1.1 ad 840 1.1 ad 841 1.25 tsutsui while ((bus_space_read_4(sc->sc_bt, sc->sc_bhzc, zc_csr) & 842 1.25 tsutsui ZX_CSR_BLT_BUSY) != 0) 843 1.1 ad ; 844 1.1 ad 845 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, rop); 846 1.27 macallan bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_fg, bg); 847 1.34 macallan bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_extent, 848 1.34 macallan (w - 1) | ((h - 1) << 11)); 849 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_fill, 850 1.25 tsutsui x | (y << 11) | 0x80000000); 851 1.1 ad } 852 1.1 ad 853 1.27 macallan static void 854 1.27 macallan zx_copyrect(struct zx_softc *sc, int sx, int sy, int dx, int dy, int w, 855 1.1 ad int h) 856 1.1 ad { 857 1.27 macallan uint32_t dir; 858 1.1 ad 859 1.35 macallan w -= 1; 860 1.35 macallan h -= 1; 861 1.35 macallan 862 1.1 ad if (sy < dy || sx < dx) { 863 1.1 ad dir = 0x80000000; 864 1.1 ad sx += w; 865 1.1 ad sy += h; 866 1.1 ad dx += w; 867 1.1 ad dy += h; 868 1.1 ad } else 869 1.1 ad dir = 0; 870 1.1 ad 871 1.25 tsutsui while ((bus_space_read_4(sc->sc_bt, sc->sc_bhzc, zc_csr) & 872 1.25 tsutsui ZX_CSR_BLT_BUSY) != 0) 873 1.1 ad ; 874 1.1 ad 875 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, ZX_STD_ROP); 876 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_extent, 877 1.25 tsutsui w | (h << 11) | dir); 878 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_src, sx | (sy << 11)); 879 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_copy, dx | (dy << 11)); 880 1.1 ad } 881 1.1 ad 882 1.27 macallan static void 883 1.27 macallan zx_do_cursor(void *cookie, int on, int row, int col) 884 1.1 ad { 885 1.27 macallan struct rasops_info *ri = cookie; 886 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 887 1.27 macallan struct zx_softc *sc = scr->scr_cookie; 888 1.27 macallan int x, y, wi, he; 889 1.27 macallan 890 1.27 macallan wi = ri->ri_font->fontwidth; 891 1.27 macallan he = ri->ri_font->fontheight; 892 1.27 macallan 893 1.27 macallan if (ri->ri_flg & RI_CURSOR) { 894 1.27 macallan x = ri->ri_ccol * wi + ri->ri_xorigin; 895 1.27 macallan y = ri->ri_crow * he + ri->ri_yorigin; 896 1.27 macallan zx_fillrect(sc, x, y, wi, he, 0xff000000, 897 1.27 macallan ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE | 898 1.27 macallan ZX_ATTR_FORCE_WID); 899 1.27 macallan ri->ri_flg &= ~RI_CURSOR; 900 1.27 macallan } 901 1.1 ad 902 1.27 macallan ri->ri_crow = row; 903 1.27 macallan ri->ri_ccol = col; 904 1.1 ad 905 1.27 macallan if (on) 906 1.27 macallan { 907 1.27 macallan x = ri->ri_ccol * wi + ri->ri_xorigin; 908 1.27 macallan y = ri->ri_crow * he + ri->ri_yorigin; 909 1.27 macallan zx_fillrect(sc, x, y, wi, he, 0xff000000, 910 1.27 macallan ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE | 911 1.27 macallan ZX_ATTR_FORCE_WID); 912 1.27 macallan ri->ri_flg |= RI_CURSOR; 913 1.27 macallan } 914 1.1 ad } 915 1.1 ad 916 1.27 macallan static void 917 1.27 macallan zx_erasecols(void *cookie, int row, int startcol, int ncols, long attr) 918 1.1 ad { 919 1.27 macallan struct rasops_info *ri = cookie; 920 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 921 1.27 macallan struct zx_softc *sc = scr->scr_cookie; 922 1.27 macallan int32_t x, y, width, height, bg; 923 1.27 macallan 924 1.27 macallan x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 925 1.27 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 926 1.27 macallan width = ri->ri_font->fontwidth * ncols; 927 1.27 macallan height = ri->ri_font->fontheight; 928 1.27 macallan bg = ((uint32_t)ri->ri_devcmap[(attr >> 16) & 0xff]) << 24; 929 1.27 macallan zx_fillrect(sc, x, y, width, height, bg, ZX_STD_ROP); 930 1.27 macallan } 931 1.27 macallan 932 1.27 macallan static void 933 1.27 macallan zx_eraserows(void *cookie, int row, int nrows, long attr) 934 1.27 macallan { 935 1.27 macallan struct rasops_info *ri = cookie; 936 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 937 1.27 macallan struct zx_softc *sc = scr->scr_cookie; 938 1.27 macallan int32_t x, y, width, height, bg; 939 1.27 macallan 940 1.27 macallan if ((row == 0) && (nrows == ri->ri_rows)) { 941 1.27 macallan x = y = 0; 942 1.27 macallan width = ri->ri_width; 943 1.27 macallan height = ri->ri_height; 944 1.27 macallan } else { 945 1.27 macallan x = ri->ri_xorigin; 946 1.27 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 947 1.27 macallan width = ri->ri_emuwidth; 948 1.27 macallan height = ri->ri_font->fontheight * nrows; 949 1.27 macallan } 950 1.27 macallan bg = ((uint32_t)ri->ri_devcmap[(attr >> 16) & 0xff]) << 24; 951 1.27 macallan zx_fillrect(sc, x, y, width, height, bg, ZX_STD_ROP); 952 1.1 ad } 953 1.1 ad 954 1.27 macallan static void 955 1.27 macallan zx_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 956 1.1 ad { 957 1.27 macallan struct rasops_info *ri = cookie; 958 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 959 1.27 macallan struct zx_softc *sc = scr->scr_cookie; 960 1.27 macallan int32_t x, ys, yd, width, height; 961 1.1 ad 962 1.27 macallan x = ri->ri_xorigin; 963 1.27 macallan ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 964 1.27 macallan yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 965 1.27 macallan width = ri->ri_emuwidth; 966 1.27 macallan height = ri->ri_font->fontheight * nrows; 967 1.27 macallan zx_copyrect(sc, x, ys, x, yd, width, height); 968 1.1 ad } 969 1.1 ad 970 1.27 macallan static void 971 1.27 macallan zx_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 972 1.1 ad { 973 1.27 macallan struct rasops_info *ri = cookie; 974 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 975 1.27 macallan struct zx_softc *sc = scr->scr_cookie; 976 1.27 macallan int32_t xs, xd, y, width, height; 977 1.1 ad 978 1.27 macallan xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 979 1.27 macallan xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 980 1.27 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 981 1.27 macallan width = ri->ri_font->fontwidth * ncols; 982 1.27 macallan height = ri->ri_font->fontheight; 983 1.27 macallan zx_copyrect(sc, xs, y, xd, y, width, height); 984 1.1 ad } 985 1.1 ad 986 1.27 macallan static void 987 1.1 ad zx_putchar(void *cookie, int row, int col, u_int uc, long attr) 988 1.1 ad { 989 1.27 macallan struct rasops_info *ri = cookie; 990 1.36 macallan struct wsdisplay_font *font = PICK_FONT(ri, uc); 991 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 992 1.27 macallan struct zx_softc *sc = scr->scr_cookie; 993 1.33 tsutsui volatile uint32_t *dp; 994 1.33 tsutsui uint8_t *fb; 995 1.27 macallan int fs, i, ul; 996 1.27 macallan uint32_t fg, bg; 997 1.27 macallan 998 1.27 macallan rasops_unpack_attr(attr, &fg, &bg, &ul); 999 1.27 macallan bg = ((uint32_t)ri->ri_devcmap[bg]) << 24; 1000 1.27 macallan fg = ((uint32_t)ri->ri_devcmap[fg]) << 24; 1001 1.27 macallan if (uc == ' ') { 1002 1.27 macallan int x, y; 1003 1.1 ad 1004 1.36 macallan x = ri->ri_xorigin + font->fontwidth * col; 1005 1.36 macallan y = ri->ri_yorigin + font->fontheight * row; 1006 1.36 macallan zx_fillrect(sc, x, y, font->fontwidth, 1007 1.36 macallan font->fontheight, bg, ZX_STD_ROP); 1008 1.1 ad return; 1009 1.1 ad } 1010 1.1 ad 1011 1.33 tsutsui dp = (volatile uint32_t *)sc->sc_pixels + 1012 1.27 macallan ((row * font->fontheight + ri->ri_yorigin) << 11) + 1013 1.27 macallan (col * font->fontwidth + ri->ri_xorigin); 1014 1.33 tsutsui fb = (uint8_t *)font->data + (uc - font->firstchar) * 1015 1.1 ad ri->ri_fontscale; 1016 1.1 ad fs = font->stride; 1017 1.1 ad 1018 1.25 tsutsui while ((bus_space_read_4(sc->sc_bt, sc->sc_bhzc, zc_csr) & 1019 1.25 tsutsui ZX_CSR_BLT_BUSY) != 0) 1020 1.1 ad ; 1021 1.1 ad 1022 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, ZX_STD_ROP); 1023 1.27 macallan bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_fg, fg); 1024 1.27 macallan bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_bg, bg); 1025 1.25 tsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_fontmsk, 1026 1.27 macallan 0xffffffff << (32 - font->fontwidth)); 1027 1.1 ad 1028 1.27 macallan if (font->fontwidth <= 8) { 1029 1.27 macallan for (i = font->fontheight; i != 0; i--, dp += 2048) { 1030 1.1 ad *dp = *fb << 24; 1031 1.1 ad fb += fs; 1032 1.1 ad } 1033 1.1 ad } else { 1034 1.27 macallan for (i = font->fontheight; i != 0; i--, dp += 2048) { 1035 1.33 tsutsui *dp = *((uint16_t *)fb) << 16; 1036 1.1 ad fb += fs; 1037 1.1 ad } 1038 1.1 ad } 1039 1.1 ad 1040 1.1 ad if (ul) { 1041 1.1 ad dp -= 4096; 1042 1.1 ad *dp = 0xffffffff; 1043 1.1 ad } 1044 1.1 ad } 1045 1.27 macallan 1046 1.27 macallan static int 1047 1.27 macallan zx_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 1048 1.27 macallan struct lwp *l) 1049 1.27 macallan { 1050 1.27 macallan /* we'll probably need to add more stuff here */ 1051 1.27 macallan struct vcons_data *vd = v; 1052 1.27 macallan struct zx_softc *sc = vd->cookie; 1053 1.27 macallan struct wsdisplay_fbinfo *wdf; 1054 1.27 macallan struct vcons_screen *ms = sc->vd.active; 1055 1.41 macallan struct rasops_info *ri = &ms->scr_ri; 1056 1.27 macallan switch (cmd) { 1057 1.27 macallan case WSDISPLAYIO_GTYPE: 1058 1.27 macallan *(u_int *)data = WSDISPLAY_TYPE_SUNTCX; 1059 1.27 macallan return 0; 1060 1.27 macallan case WSDISPLAYIO_GINFO: 1061 1.27 macallan wdf = (void *)data; 1062 1.27 macallan wdf->height = ri->ri_height; 1063 1.27 macallan wdf->width = ri->ri_width; 1064 1.27 macallan wdf->depth = ri->ri_depth; 1065 1.27 macallan wdf->cmsize = 256; 1066 1.27 macallan return 0; 1067 1.27 macallan 1068 1.27 macallan case WSDISPLAYIO_GETCMAP: 1069 1.27 macallan return zx_getcmap(sc, 1070 1.27 macallan (struct wsdisplay_cmap *)data); 1071 1.27 macallan case WSDISPLAYIO_PUTCMAP: 1072 1.27 macallan return zx_putcmap(sc, 1073 1.27 macallan (struct wsdisplay_cmap *)data); 1074 1.27 macallan 1075 1.27 macallan case WSDISPLAYIO_SMODE: 1076 1.27 macallan { 1077 1.27 macallan int new_mode = *(int*)data; 1078 1.27 macallan if (new_mode != sc->sc_mode) 1079 1.27 macallan { 1080 1.27 macallan sc->sc_mode = new_mode; 1081 1.27 macallan if(new_mode == WSDISPLAYIO_MODE_EMUL) 1082 1.27 macallan { 1083 1.34 macallan zx_reset(sc); 1084 1.27 macallan vcons_redraw_screen(ms); 1085 1.27 macallan } 1086 1.27 macallan } 1087 1.27 macallan } 1088 1.41 macallan return 0; 1089 1.27 macallan } 1090 1.27 macallan return EPASSTHROUGH; 1091 1.27 macallan } 1092 1.27 macallan 1093 1.27 macallan static paddr_t 1094 1.27 macallan zx_mmap(void *v, void *vs, off_t offset, int prot) 1095 1.27 macallan { 1096 1.27 macallan /* I'm not at all sure this is the right thing to do */ 1097 1.27 macallan return zxmmap(0, offset, prot); /* assume minor dev 0 for now */ 1098 1.27 macallan } 1099 1.27 macallan 1100 1.27 macallan static int 1101 1.27 macallan zx_putcmap(struct zx_softc *sc, struct wsdisplay_cmap *cm) 1102 1.27 macallan { 1103 1.27 macallan u_int index = cm->index; 1104 1.27 macallan u_int count = cm->count; 1105 1.27 macallan int error,i; 1106 1.27 macallan if (index >= 256 || count > 256 || index + count > 256) 1107 1.27 macallan return EINVAL; 1108 1.27 macallan 1109 1.27 macallan for (i = 0; i < count; i++) 1110 1.27 macallan { 1111 1.27 macallan error = copyin(&cm->red[i], 1112 1.27 macallan &sc->sc_cmap[index + i], 1); 1113 1.27 macallan if (error) 1114 1.27 macallan return error; 1115 1.27 macallan error = copyin(&cm->green[i], 1116 1.27 macallan &sc->sc_cmap[index + i + 256], 1); 1117 1.27 macallan if (error) 1118 1.27 macallan return error; 1119 1.27 macallan error = copyin(&cm->blue[i], 1120 1.27 macallan &sc->sc_cmap[index + i + 512], 1); 1121 1.27 macallan if (error) 1122 1.27 macallan return error; 1123 1.27 macallan } 1124 1.27 macallan zx_cmap_put(sc); 1125 1.27 macallan 1126 1.27 macallan return 0; 1127 1.27 macallan } 1128 1.27 macallan 1129 1.27 macallan static int 1130 1.27 macallan zx_getcmap(struct zx_softc *sc, struct wsdisplay_cmap *cm) 1131 1.27 macallan { 1132 1.27 macallan u_int index = cm->index; 1133 1.27 macallan u_int count = cm->count; 1134 1.27 macallan int error,i; 1135 1.27 macallan 1136 1.27 macallan if (index >= 256 || count > 256 || index + count > 256) 1137 1.27 macallan return EINVAL; 1138 1.27 macallan 1139 1.27 macallan for (i = 0; i < count; i++) 1140 1.27 macallan { 1141 1.27 macallan error = copyout(&sc->sc_cmap[index + i], 1142 1.27 macallan &cm->red[i], 1); 1143 1.27 macallan if (error) 1144 1.27 macallan return error; 1145 1.27 macallan error = copyout(&sc->sc_cmap[index + i + 256], 1146 1.27 macallan &cm->green[i], 1); 1147 1.27 macallan if (error) 1148 1.27 macallan return error; 1149 1.27 macallan error = copyout(&sc->sc_cmap[index + i + 256], 1150 1.27 macallan &cm->blue[i], 1); 1151 1.27 macallan if (error) 1152 1.27 macallan return error; 1153 1.27 macallan } 1154 1.27 macallan 1155 1.27 macallan return 0; 1156 1.27 macallan } 1157 1.27 macallan 1158 1.27 macallan static void 1159 1.27 macallan zx_init_screen(void *cookie, struct vcons_screen *scr, 1160 1.27 macallan int existing, long *defattr) 1161 1.27 macallan { 1162 1.27 macallan struct zx_softc *sc = cookie; 1163 1.27 macallan struct rasops_info *ri = &scr->scr_ri; 1164 1.27 macallan 1165 1.27 macallan ri->ri_depth = 8; /*sc->sc_fb.fb_type.fb_depth = 32;*/ 1166 1.27 macallan ri->ri_width = sc->sc_width; 1167 1.27 macallan ri->ri_height = sc->sc_height; 1168 1.27 macallan ri->ri_stride = sc->sc_stride; 1169 1.27 macallan ri->ri_flg = RI_CENTER; 1170 1.27 macallan 1171 1.27 macallan ri->ri_bits = (void *)sc->sc_pixels; 1172 1.27 macallan 1173 1.39 macallan rasops_init(ri, 0, 0); 1174 1.27 macallan ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_REVERSE; 1175 1.27 macallan rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 1176 1.27 macallan sc->sc_width / ri->ri_font->fontwidth); 1177 1.27 macallan 1178 1.27 macallan ri->ri_hw = scr; 1179 1.27 macallan 1180 1.27 macallan ri->ri_ops.cursor = zx_do_cursor; 1181 1.27 macallan ri->ri_ops.copycols = zx_copycols; 1182 1.27 macallan ri->ri_ops.copyrows = zx_copyrows; 1183 1.27 macallan ri->ri_ops.erasecols = zx_erasecols; 1184 1.27 macallan ri->ri_ops.eraserows = zx_eraserows; 1185 1.27 macallan ri->ri_ops.putchar = zx_putchar; 1186 1.27 macallan } 1187