1 1.47 tsutsui /* $NetBSD: ite_cc.c,v 1.47 2023/01/06 10:28:28 tsutsui Exp $ */ 2 1.1 leo 3 1.1 leo /* 4 1.7 leo * Copyright (c) 1996 Leo Weppelman 5 1.1 leo * Copyright (c) 1994 Christian E. Hopps 6 1.1 leo * All rights reserved. 7 1.1 leo * 8 1.1 leo * Redistribution and use in source and binary forms, with or without 9 1.1 leo * modification, are permitted provided that the following conditions 10 1.1 leo * are met: 11 1.1 leo * 1. Redistributions of source code must retain the above copyright 12 1.1 leo * notice, this list of conditions and the following disclaimer. 13 1.1 leo * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 leo * notice, this list of conditions and the following disclaimer in the 15 1.1 leo * documentation and/or other materials provided with the distribution. 16 1.1 leo * 3. All advertising materials mentioning features or use of this software 17 1.1 leo * must display the following acknowledgement: 18 1.1 leo * This product includes software developed by Christian E. Hopps. 19 1.1 leo * 4. The name of the author may not be used to endorse or promote products 20 1.1 leo * derived from this software without specific prior written permission 21 1.1 leo * 22 1.1 leo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 1.1 leo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 1.1 leo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 1.1 leo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 1.1 leo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 1.1 leo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 1.1 leo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 1.1 leo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 1.1 leo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 1.1 leo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 leo */ 33 1.22 lukem 34 1.22 lukem #include <sys/cdefs.h> 35 1.47 tsutsui __KERNEL_RCSID(0, "$NetBSD: ite_cc.c,v 1.47 2023/01/06 10:28:28 tsutsui Exp $"); 36 1.1 leo 37 1.1 leo #include <sys/param.h> 38 1.1 leo #include <sys/conf.h> 39 1.1 leo #include <sys/proc.h> 40 1.1 leo #include <sys/ioctl.h> 41 1.1 leo #include <sys/tty.h> 42 1.1 leo #include <sys/systm.h> 43 1.1 leo #include <sys/queue.h> 44 1.1 leo #include <sys/termios.h> 45 1.1 leo #include <sys/malloc.h> 46 1.7 leo #include <sys/device.h> 47 1.44 riastrad #include <sys/device_impl.h> /* XXX autoconf abuse */ 48 1.1 leo #include <dev/cons.h> 49 1.1 leo #include <machine/cpu.h> 50 1.7 leo #include <atari/atari/device.h> 51 1.1 leo #include <atari/dev/itevar.h> 52 1.1 leo #include <atari/dev/iteioctl.h> 53 1.1 leo #include <atari/dev/grfioctl.h> 54 1.1 leo #include <atari/dev/grfabs_reg.h> 55 1.1 leo #include <atari/dev/grfvar.h> 56 1.1 leo #include <atari/dev/font.h> 57 1.1 leo #include <atari/dev/viewioctl.h> 58 1.1 leo #include <atari/dev/viewvar.h> 59 1.1 leo 60 1.10 leo #include "grfcc.h" 61 1.10 leo 62 1.1 leo /* 63 1.1 leo * This is what ip->priv points to; 64 1.1 leo * it contains local variables for custom-chip ites. 65 1.1 leo */ 66 1.1 leo struct ite_priv { 67 1.1 leo u_char **row_ptr; /* array of pointers into the bitmap */ 68 1.1 leo u_long row_bytes; 69 1.1 leo u_long cursor_opt; 70 1.1 leo u_short *column_offset; /* array of offsets for columns */ 71 1.1 leo u_int row_offset; /* the row offset */ 72 1.1 leo u_short width; /* the bitmap width */ 73 1.1 leo u_short underline; /* where the underline goes */ 74 1.1 leo u_short ft_x; /* the font width */ 75 1.1 leo u_short ft_y; /* the font height */ 76 1.1 leo u_char *font_cell[256];/* the font pointer */ 77 1.1 leo }; 78 1.1 leo typedef struct ite_priv ipriv_t; 79 1.1 leo 80 1.1 leo /* 81 1.1 leo * We need the following space to get an ite-console setup before 82 1.1 leo * the VM-system is brought up. We setup for a 1280x960 monitor with 83 1.1 leo * an 8x8 font. 84 1.1 leo */ 85 1.1 leo #define CONS_MAXROW 120 /* Max. number of rows on console */ 86 1.1 leo #define CONS_MAXCOL 160 /* Max. number of columns on console */ 87 1.1 leo static u_short con_columns[CONS_MAXCOL]; 88 1.1 leo static u_char *con_rows[CONS_MAXROW]; 89 1.1 leo static ipriv_t con_ipriv; 90 1.1 leo 91 1.1 leo extern font_info font_info_8x8; 92 1.1 leo extern font_info font_info_8x16; 93 1.1 leo 94 1.28 dsl static void view_init(struct ite_softc *); 95 1.28 dsl static void view_deinit(struct ite_softc *); 96 1.28 dsl static int itecc_ioctl(struct ite_softc *, u_long, void *, int, 97 1.28 dsl struct lwp *); 98 1.28 dsl static int ite_newsize(struct ite_softc *, struct itewinsize *); 99 1.28 dsl static void cursor32(struct ite_softc *, int); 100 1.28 dsl static void putc8(struct ite_softc *, int, int, int, int); 101 1.28 dsl static void clear8(struct ite_softc *, int, int, int, int); 102 1.28 dsl static void scroll8(struct ite_softc *, int, int, int, int); 103 1.28 dsl static void scrollbmap(bmap_t *, u_short, u_short, u_short, u_short, 104 1.28 dsl short, short); 105 1.1 leo 106 1.1 leo /* 107 1.7 leo * grfcc config stuff 108 1.7 leo */ 109 1.40 tsutsui static void grfccattach(device_t, device_t, void *); 110 1.40 tsutsui static int grfccmatch(device_t, cfdata_t, void *); 111 1.40 tsutsui static int grfccprint(void *, const char *); 112 1.7 leo 113 1.37 tsutsui CFATTACH_DECL_NEW(grfcc, sizeof(struct grf_softc), 114 1.20 thorpej grfccmatch, grfccattach, NULL, NULL); 115 1.7 leo 116 1.7 leo /* 117 1.7 leo * only used in console init. 118 1.7 leo */ 119 1.7 leo static struct cfdata *cfdata_grf = NULL; 120 1.7 leo 121 1.7 leo /* 122 1.7 leo * Probe functions we can use: 123 1.7 leo */ 124 1.7 leo #ifdef TT_VIDEO 125 1.28 dsl void tt_probe_video(MODES *); 126 1.7 leo #endif /* TT_VIDEO */ 127 1.7 leo #ifdef FALCON_VIDEO 128 1.28 dsl void falcon_probe_video(MODES *); 129 1.7 leo #endif /* FALCON_VIDEO */ 130 1.7 leo 131 1.40 tsutsui static int 132 1.37 tsutsui grfccmatch(device_t parent, cfdata_t cf, void *aux) 133 1.7 leo { 134 1.36 tsutsui static int did_consinit = 0; 135 1.36 tsutsui static int must_probe = 1; 136 1.37 tsutsui grf_auxp_t *grf_auxp = aux; 137 1.18 gehenna extern const struct cdevsw view_cdevsw; 138 1.7 leo 139 1.7 leo if (must_probe) { 140 1.7 leo /* 141 1.7 leo * Check if the layers we depend on exist 142 1.7 leo */ 143 1.7 leo if (!(machineid & (ATARI_TT|ATARI_FALCON))) 144 1.36 tsutsui return 0; 145 1.7 leo #ifdef TT_VIDEO 146 1.7 leo if ((machineid & ATARI_TT) && !grfabs_probe(&tt_probe_video)) 147 1.36 tsutsui return 0; 148 1.7 leo #endif /* TT_VIDEO */ 149 1.7 leo #ifdef FALCON_VIDEO 150 1.36 tsutsui if ((machineid & ATARI_FALCON) && 151 1.36 tsutsui !grfabs_probe(&falcon_probe_video)) 152 1.36 tsutsui return 0; 153 1.7 leo #endif /* FALCON_VIDEO */ 154 1.7 leo 155 1.7 leo viewprobe(); 156 1.7 leo must_probe = 0; 157 1.7 leo } 158 1.7 leo 159 1.7 leo if (atari_realconfig == 0) { 160 1.7 leo /* 161 1.16 leo * Early console init. Only match first unit. 162 1.7 leo */ 163 1.16 leo if (did_consinit) 164 1.36 tsutsui return 0; 165 1.37 tsutsui if ((*view_cdevsw.d_open)(cf->cf_unit, 0, 0, NULL)) 166 1.36 tsutsui return 0; 167 1.37 tsutsui cfdata_grf = cf; 168 1.16 leo did_consinit = 1; 169 1.36 tsutsui return 1; 170 1.7 leo } 171 1.7 leo 172 1.7 leo /* 173 1.7 leo * Normal config. When we are called directly from the grfbus, 174 1.16 leo * we only match the first unit. The attach function will call us for 175 1.7 leo * the other configured units. 176 1.7 leo */ 177 1.16 leo if (grf_auxp->from_bus_match && (did_consinit > 1)) 178 1.36 tsutsui return 0; 179 1.7 leo 180 1.37 tsutsui if (!grf_auxp->from_bus_match && (grf_auxp->unit != cf->cf_unit)) 181 1.36 tsutsui return 0; 182 1.7 leo 183 1.7 leo /* 184 1.7 leo * Final constraint: each grf needs a view.... 185 1.7 leo */ 186 1.36 tsutsui if ((cfdata_grf == NULL) || (did_consinit > 1)) { 187 1.37 tsutsui if ((*view_cdevsw.d_open)(cf->cf_unit, 0, 0, NULL)) 188 1.36 tsutsui return 0; 189 1.7 leo } 190 1.16 leo did_consinit = 2; 191 1.36 tsutsui return 1; 192 1.7 leo } 193 1.7 leo 194 1.7 leo /* 195 1.7 leo * attach: initialize the grf-structure and try to attach an ite to us. 196 1.38 chs * note : self is NULL during early console init. 197 1.7 leo */ 198 1.40 tsutsui static void 199 1.37 tsutsui grfccattach(device_t parent, device_t self, void *aux) 200 1.7 leo { 201 1.36 tsutsui static struct grf_softc congrf; 202 1.36 tsutsui static int first_attach = 1; 203 1.37 tsutsui grf_auxp_t *grf_bus_auxp = aux; 204 1.36 tsutsui grf_auxp_t grf_auxp; 205 1.37 tsutsui struct grf_softc *sc; 206 1.36 tsutsui int maj; 207 1.18 gehenna extern const struct cdevsw grf_cdevsw; 208 1.7 leo 209 1.7 leo /* 210 1.47 tsutsui * find our major device number 211 1.7 leo */ 212 1.18 gehenna maj = cdevsw_lookup_major(&grf_cdevsw); 213 1.7 leo 214 1.7 leo /* 215 1.35 wiz * Handle exception case: early console init 216 1.7 leo */ 217 1.37 tsutsui if (self == NULL) { 218 1.37 tsutsui struct device itedev; 219 1.37 tsutsui 220 1.37 tsutsui memset(&itedev, 0, sizeof(itedev)); 221 1.37 tsutsui itedev.dv_private = &congrf; 222 1.37 tsutsui 223 1.16 leo congrf.g_unit = cfdata_grf->cf_unit; 224 1.16 leo congrf.g_grfdev = makedev(maj, congrf.g_unit); 225 1.7 leo congrf.g_itedev = (dev_t)-1; 226 1.7 leo congrf.g_flags = GF_ALIVE; 227 1.7 leo congrf.g_mode = grf_mode; 228 1.7 leo congrf.g_conpri = grfcc_cnprobe(); 229 1.7 leo congrf.g_viewdev = congrf.g_unit; 230 1.7 leo grfcc_iteinit(&congrf); 231 1.7 leo grf_viewsync(&congrf); 232 1.7 leo 233 1.7 leo /* Attach console ite */ 234 1.42 thorpej atari_config_found(cfdata_grf, &itedev, &congrf, grfccprint, 235 1.43 thorpej CFARGS_NONE); 236 1.7 leo return; 237 1.7 leo } 238 1.7 leo 239 1.37 tsutsui sc = device_private(self); 240 1.37 tsutsui sc->g_device = self; 241 1.37 tsutsui sc->g_unit = device_unit(self); 242 1.37 tsutsui grfsp[sc->g_unit] = sc; 243 1.7 leo 244 1.37 tsutsui if ((cfdata_grf != NULL) && (sc->g_unit == congrf.g_unit)) { 245 1.7 leo /* 246 1.7 leo * We inited earlier just copy the info, take care 247 1.7 leo * not to copy the device struct though. 248 1.7 leo */ 249 1.37 tsutsui memcpy(&sc->g_display, &congrf.g_display, 250 1.37 tsutsui (char *)&sc[1] - (char *)&sc->g_display); 251 1.36 tsutsui } else { 252 1.37 tsutsui sc->g_grfdev = makedev(maj, sc->g_unit); 253 1.37 tsutsui sc->g_itedev = (dev_t)-1; 254 1.37 tsutsui sc->g_flags = GF_ALIVE; 255 1.37 tsutsui sc->g_mode = grf_mode; 256 1.37 tsutsui sc->g_conpri = 0; 257 1.37 tsutsui sc->g_viewdev = sc->g_unit; 258 1.37 tsutsui grfcc_iteinit(sc); 259 1.37 tsutsui grf_viewsync(sc); 260 1.7 leo } 261 1.7 leo 262 1.46 tsutsui aprint_normal(": width %d height %d", sc->g_display.gd_dwidth, 263 1.37 tsutsui sc->g_display.gd_dheight); 264 1.37 tsutsui if (sc->g_display.gd_colors == 2) 265 1.46 tsutsui aprint_normal(" monochrome\n"); 266 1.36 tsutsui else 267 1.46 tsutsui aprint_normal(" colors %d\n", sc->g_display.gd_colors); 268 1.47 tsutsui 269 1.7 leo /* 270 1.7 leo * try and attach an ite 271 1.7 leo */ 272 1.43 thorpej config_found(self, sc /* XXX */, grfccprint, CFARGS_NONE); 273 1.7 leo 274 1.7 leo /* 275 1.16 leo * If attaching the first unit, go ahead and 'find' the rest of us 276 1.7 leo */ 277 1.16 leo if (first_attach) { 278 1.16 leo first_attach = 0; 279 1.7 leo grf_auxp.from_bus_match = 0; 280 1.7 leo for (grf_auxp.unit=1; grf_auxp.unit < NGRFCC; grf_auxp.unit++) { 281 1.41 thorpej config_found(parent, &grf_auxp, grf_bus_auxp->busprint, 282 1.43 thorpej CFARGS_NONE); 283 1.7 leo } 284 1.7 leo } 285 1.7 leo } 286 1.7 leo 287 1.40 tsutsui static int 288 1.37 tsutsui grfccprint(void *aux, const char *pnp) 289 1.7 leo { 290 1.36 tsutsui 291 1.36 tsutsui if (pnp) 292 1.21 thorpej aprint_normal("ite at %s", pnp); 293 1.36 tsutsui return UNCONF; 294 1.7 leo } 295 1.7 leo 296 1.7 leo /* 297 1.1 leo * called from grf_cc to return console priority 298 1.1 leo */ 299 1.1 leo int 300 1.31 cegger grfcc_cnprobe(void) 301 1.1 leo { 302 1.36 tsutsui return CN_INTERNAL; 303 1.1 leo } 304 1.1 leo /* 305 1.47 tsutsui * called from grf_cc to init ite portion of 306 1.1 leo * grf_softc struct 307 1.1 leo */ 308 1.1 leo void 309 1.37 tsutsui grfcc_iteinit(struct grf_softc *sc) 310 1.1 leo { 311 1.1 leo 312 1.37 tsutsui sc->g_itecursor = cursor32; 313 1.37 tsutsui sc->g_iteputc = putc8; 314 1.37 tsutsui sc->g_iteclear = clear8; 315 1.37 tsutsui sc->g_itescroll = scroll8; 316 1.37 tsutsui sc->g_iteinit = view_init; 317 1.37 tsutsui sc->g_itedeinit = view_deinit; 318 1.1 leo } 319 1.1 leo 320 1.1 leo static void 321 1.29 dsl view_deinit(struct ite_softc *ip) 322 1.1 leo { 323 1.1 leo ip->flags &= ~ITE_INITED; 324 1.1 leo } 325 1.1 leo 326 1.1 leo static void 327 1.29 dsl view_init(register struct ite_softc *ip) 328 1.1 leo { 329 1.1 leo struct itewinsize wsz; 330 1.1 leo ipriv_t *cci; 331 1.1 leo 332 1.36 tsutsui if ((cci = ip->priv) != NULL) 333 1.1 leo return; 334 1.1 leo 335 1.10 leo ip->itexx_ioctl = itecc_ioctl; 336 1.10 leo 337 1.1 leo #if defined(KFONT_8X8) 338 1.1 leo ip->font = font_info_8x8; 339 1.1 leo #else 340 1.1 leo ip->font = font_info_8x16; 341 1.1 leo #endif 342 1.1 leo 343 1.1 leo /* Find the correct set of rendering routines for this font. */ 344 1.36 tsutsui if (ip->font.width != 8) 345 1.1 leo panic("kernel font size not supported"); 346 1.1 leo 347 1.36 tsutsui if (!atari_realconfig) 348 1.1 leo ip->priv = cci = &con_ipriv; 349 1.36 tsutsui else 350 1.36 tsutsui ip->priv = cci = malloc(sizeof(*cci), M_DEVBUF, M_WAITOK); 351 1.36 tsutsui if (cci == NULL) 352 1.1 leo panic("No memory for ite-view"); 353 1.32 cegger memset(cci, 0, sizeof(*cci)); 354 1.1 leo 355 1.1 leo cci->cursor_opt = 0; 356 1.1 leo cci->row_ptr = NULL; 357 1.1 leo cci->column_offset = NULL; 358 1.1 leo 359 1.1 leo wsz.x = ite_default_x; 360 1.1 leo wsz.y = ite_default_y; 361 1.1 leo wsz.width = ite_default_width; 362 1.1 leo wsz.height = ite_default_height; 363 1.1 leo wsz.depth = ite_default_depth; 364 1.1 leo 365 1.1 leo ite_newsize (ip, &wsz); 366 1.1 leo 367 1.1 leo /* 368 1.1 leo * Only console will be turned on by default.. 369 1.1 leo */ 370 1.36 tsutsui if (ip->flags & ITE_ISCONS) 371 1.1 leo ip->grf->g_mode(ip->grf, GM_GRFON, NULL, 0, 0); 372 1.1 leo } 373 1.1 leo 374 1.1 leo static int 375 1.29 dsl ite_newsize(struct ite_softc *ip, struct itewinsize *winsz) 376 1.1 leo { 377 1.4 leo struct view_size vs; 378 1.47 tsutsui ipriv_t *cci = ip->priv; 379 1.5 leo u_long i, j; 380 1.4 leo int error = 0; 381 1.4 leo view_t *view; 382 1.18 gehenna extern const struct cdevsw view_cdevsw; 383 1.1 leo 384 1.1 leo vs.x = winsz->x; 385 1.1 leo vs.y = winsz->y; 386 1.1 leo vs.width = winsz->width; 387 1.1 leo vs.height = winsz->height; 388 1.1 leo vs.depth = winsz->depth; 389 1.2 leo 390 1.18 gehenna error = (*view_cdevsw.d_ioctl)(ip->grf->g_viewdev, VIOCSSIZE, 391 1.27 christos (void *)&vs, 0, NOLWP); 392 1.4 leo view = viewview(ip->grf->g_viewdev); 393 1.1 leo 394 1.1 leo /* 395 1.1 leo * Reinitialize our structs 396 1.1 leo */ 397 1.47 tsutsui ip->cols = view->display.width / ip->font.width; 398 1.1 leo ip->rows = view->display.height / ip->font.height; 399 1.1 leo 400 1.1 leo /* 401 1.1 leo * save new values so that future opens use them 402 1.1 leo * this may not be correct when we implement Virtual Consoles 403 1.1 leo */ 404 1.1 leo ite_default_height = view->display.height; 405 1.1 leo ite_default_width = view->display.width; 406 1.1 leo ite_default_x = view->display.x; 407 1.1 leo ite_default_y = view->display.y; 408 1.1 leo ite_default_depth = view->bitmap->depth; 409 1.1 leo 410 1.36 tsutsui if (cci->row_ptr && (cci->row_ptr != con_rows)) { 411 1.1 leo free(cci->row_ptr, M_DEVBUF); 412 1.1 leo cci->row_ptr = NULL; 413 1.1 leo } 414 1.36 tsutsui if (cci->column_offset && (cci->column_offset != con_columns)) { 415 1.1 leo free(cci->column_offset, M_DEVBUF); 416 1.1 leo cci->column_offset = NULL; 417 1.1 leo } 418 1.1 leo 419 1.36 tsutsui if (!atari_realconfig) { 420 1.1 leo cci->row_ptr = con_rows; 421 1.1 leo cci->column_offset = con_columns; 422 1.36 tsutsui } else { 423 1.36 tsutsui cci->row_ptr = malloc(sizeof(u_char *) * ip->rows, 424 1.36 tsutsui M_DEVBUF, M_NOWAIT); 425 1.36 tsutsui cci->column_offset = malloc(sizeof(u_int) * ip->cols, 426 1.36 tsutsui M_DEVBUF, M_NOWAIT); 427 1.1 leo } 428 1.1 leo 429 1.36 tsutsui if (!cci->row_ptr || !cci->column_offset) 430 1.1 leo panic("No memory for ite-view"); 431 1.1 leo 432 1.1 leo cci->width = view->bitmap->bytes_per_row << 3; 433 1.1 leo cci->underline = ip->font.baseline + 1; 434 1.1 leo cci->row_offset = view->bitmap->bytes_per_row; 435 1.1 leo cci->ft_x = ip->font.width; 436 1.1 leo cci->ft_y = ip->font.height; 437 1.1 leo cci->row_bytes = cci->row_offset * cci->ft_y; 438 1.1 leo cci->row_ptr[0] = view->bitmap->plane; 439 1.47 tsutsui for (i = 1; i < ip->rows; i++) 440 1.36 tsutsui cci->row_ptr[i] = cci->row_ptr[i - 1] + cci->row_bytes; 441 1.1 leo 442 1.1 leo /* 443 1.1 leo * Initialize the column offsets to point at the correct location 444 1.1 leo * in the first plane. This definitely assumes a font width of 8! 445 1.1 leo */ 446 1.1 leo j = view->bitmap->depth * 2; 447 1.1 leo cci->column_offset[0] = 0; 448 1.47 tsutsui for (i = 1; i < ip->cols; i++) 449 1.1 leo cci->column_offset[i] = ((i >> 1) * j) + (i & 1); 450 1.1 leo 451 1.1 leo /* initialize the font cell pointers */ 452 1.1 leo cci->font_cell[ip->font.font_lo] = ip->font.font_p; 453 1.36 tsutsui for (i = ip->font.font_lo + 1; i <= ip->font.font_hi; i++) 454 1.36 tsutsui cci->font_cell[i] = cci->font_cell[i - 1] + ip->font.height; 455 1.47 tsutsui 456 1.36 tsutsui return error; 457 1.2 leo } 458 1.2 leo 459 1.2 leo int 460 1.36 tsutsui itecc_ioctl(struct ite_softc *ip, u_long cmd, void * addr, int flag, 461 1.36 tsutsui struct lwp *l) 462 1.2 leo { 463 1.2 leo struct winsize ws; 464 1.2 leo struct itewinsize *is; 465 1.2 leo int error = 0; 466 1.4 leo view_t *view = viewview(ip->grf->g_viewdev); 467 1.18 gehenna extern const struct cdevsw ite_cdevsw; 468 1.18 gehenna extern const struct cdevsw view_cdevsw; 469 1.2 leo 470 1.2 leo switch (cmd) { 471 1.2 leo case ITEIOCSWINSZ: 472 1.2 leo is = (struct itewinsize *)addr; 473 1.2 leo 474 1.36 tsutsui if (ite_newsize(ip, is)) 475 1.2 leo error = ENOMEM; 476 1.2 leo else { 477 1.4 leo view = viewview(ip->grf->g_viewdev); 478 1.2 leo ws.ws_row = ip->rows; 479 1.2 leo ws.ws_col = ip->cols; 480 1.2 leo ws.ws_xpixel = view->display.width; 481 1.2 leo ws.ws_ypixel = view->display.height; 482 1.2 leo ite_reset(ip); 483 1.2 leo /* 484 1.47 tsutsui * XXX tell tty about the change 485 1.47 tsutsui * XXX this is messy, but works 486 1.2 leo */ 487 1.18 gehenna (*ite_cdevsw.d_ioctl)(ip->grf->g_itedev, TIOCSWINSZ, 488 1.27 christos (void *)&ws, 0, l); 489 1.2 leo } 490 1.2 leo break; 491 1.2 leo case VIOCSCMAP: 492 1.2 leo case VIOCGCMAP: 493 1.2 leo /* 494 1.23 christos * XXX watchout for that NOLWP. its not really the kernel 495 1.6 leo * XXX talking these two commands don't use the proc pointer 496 1.6 leo * XXX though. 497 1.2 leo */ 498 1.18 gehenna error = (*view_cdevsw.d_ioctl)(ip->grf->g_viewdev, cmd, addr, 499 1.23 christos flag, NOLWP); 500 1.2 leo break; 501 1.2 leo default: 502 1.17 atatat error = EPASSTHROUGH; 503 1.2 leo break; 504 1.2 leo } 505 1.36 tsutsui return error; 506 1.1 leo } 507 1.1 leo 508 1.1 leo static void 509 1.1 leo cursor32(struct ite_softc *ip, int flag) 510 1.1 leo { 511 1.1 leo int cend; 512 1.1 leo u_char *pl; 513 1.1 leo ipriv_t *cci; 514 1.1 leo 515 1.1 leo cci = ip->priv; 516 1.1 leo 517 1.36 tsutsui if (flag == END_CURSOROPT) 518 1.1 leo cci->cursor_opt--; 519 1.36 tsutsui else if (flag == START_CURSOROPT) { 520 1.36 tsutsui if (!cci->cursor_opt) 521 1.36 tsutsui cursor32(ip, ERASE_CURSOR); 522 1.36 tsutsui cci->cursor_opt++; 523 1.36 tsutsui return; /* if we are already opted. */ 524 1.1 leo } 525 1.47 tsutsui 526 1.47 tsutsui if (cci->cursor_opt) 527 1.1 leo return; /* if we are still nested. */ 528 1.1 leo /* else we draw the cursor. */ 529 1.47 tsutsui 530 1.36 tsutsui if (flag != DRAW_CURSOR && flag != END_CURSOROPT) { 531 1.1 leo /* 532 1.1 leo * erase the cursor 533 1.1 leo */ 534 1.47 tsutsui cend = ip->font.height - 1; 535 1.1 leo pl = cci->column_offset[ip->cursorx] 536 1.1 leo + cci->row_ptr[ip->cursory]; 537 1.25 perry __asm volatile 538 1.1 leo ("1: notb %0@ ; addaw %4,%0\n\t" 539 1.1 leo "dbra %1,1b" 540 1.1 leo : "=a" (pl), "=d" (cend) 541 1.1 leo : "0" (pl), "1" (cend), 542 1.1 leo "d" (cci->row_offset) 543 1.1 leo ); 544 1.1 leo } 545 1.1 leo 546 1.36 tsutsui if (flag != DRAW_CURSOR && flag != MOVE_CURSOR && flag != END_CURSOROPT) 547 1.1 leo return; 548 1.47 tsutsui 549 1.47 tsutsui /* 550 1.1 leo * draw the cursor 551 1.1 leo */ 552 1.39 riastrad cend = uimin(ip->curx, ip->cols - 1); 553 1.10 leo if (flag == DRAW_CURSOR 554 1.10 leo && ip->cursorx == cend && ip->cursory == ip->cury) 555 1.8 leo return; 556 1.8 leo ip->cursorx = cend; 557 1.1 leo ip->cursory = ip->cury; 558 1.47 tsutsui cend = ip->font.height - 1; 559 1.1 leo pl = cci->column_offset[ip->cursorx] 560 1.1 leo + cci->row_ptr[ip->cursory]; 561 1.1 leo 562 1.25 perry __asm volatile 563 1.1 leo ("1: notb %0@ ; addaw %4,%0\n\t" 564 1.1 leo "dbra %1,1b" 565 1.1 leo : "=a" (pl), "=d" (cend) 566 1.1 leo : "0" (pl), "1" (cend), 567 1.1 leo "d" (cci->row_offset) 568 1.1 leo ); 569 1.1 leo } 570 1.1 leo 571 1.1 leo static void 572 1.1 leo putc8(struct ite_softc *ip, int c, int dy, int dx, int mode) 573 1.1 leo { 574 1.36 tsutsui ipriv_t *cci = (ipriv_t *)ip->priv; 575 1.36 tsutsui u_char *pl = cci->column_offset[dx] + cci->row_ptr[dy]; 576 1.36 tsutsui u_int fh = cci->ft_y; 577 1.36 tsutsui u_int ro = cci->row_offset; 578 1.36 tsutsui u_char eor_mask; 579 1.36 tsutsui u_char bl, tmp, ul; 580 1.36 tsutsui u_char *ft; 581 1.1 leo 582 1.36 tsutsui if (c < ip->font.font_lo || c > ip->font.font_hi) 583 1.1 leo return; 584 1.1 leo 585 1.45 tsutsui /* 586 1.45 tsutsui * Handle DEC special graphics character by 'ESC ( B' sequence. 587 1.45 tsutsui * Note we assume all font data (fontdata_8x8 and fontdata_8x16) 588 1.45 tsutsui * contain DEC graphics glyph (for 0x5f to 0x7e) at 0x00 to 0x1F. 589 1.45 tsutsui */ 590 1.45 tsutsui if (*ip->GL == CSET_DECGRAPH) { 591 1.45 tsutsui if (ip->font.font_lo == 0 && c >= 0x5f && c <= 0x7e) 592 1.45 tsutsui c -= 0x5f; 593 1.45 tsutsui } 594 1.1 leo ft = cci->font_cell[c]; 595 1.1 leo 596 1.36 tsutsui if (!mode) { 597 1.36 tsutsui while (fh--) { 598 1.1 leo *pl = *ft++; pl += ro; 599 1.1 leo } 600 1.1 leo return; 601 1.1 leo } 602 1.1 leo 603 1.1 leo eor_mask = (mode & ATTR_INV) ? 0xff : 0x00; 604 1.1 leo bl = (mode & ATTR_BOLD) ? 1 : 0; 605 1.3 leo ul = (mode & ATTR_UL) ? fh - cci->underline : fh; 606 1.36 tsutsui for (; fh--; pl += ro) { 607 1.36 tsutsui if (fh != ul) { 608 1.3 leo tmp = *ft++; 609 1.36 tsutsui if (bl) 610 1.3 leo tmp |= (tmp >> 1); 611 1.3 leo *pl = tmp ^ eor_mask; 612 1.36 tsutsui } else { 613 1.3 leo *pl = 0xff ^ eor_mask; 614 1.3 leo ft++; 615 1.3 leo } 616 1.1 leo } 617 1.1 leo } 618 1.1 leo 619 1.1 leo static void 620 1.1 leo clear8(struct ite_softc *ip, int sy, int sx, int h, int w) 621 1.1 leo { 622 1.1 leo ipriv_t *cci = (ipriv_t *) ip->priv; 623 1.4 leo view_t *v = viewview(ip->grf->g_viewdev); 624 1.1 leo bmap_t *bm = v->bitmap; 625 1.1 leo 626 1.36 tsutsui if ((sx == 0) && (w == ip->cols)) { 627 1.1 leo /* common case: clearing whole lines */ 628 1.1 leo while (h--) { 629 1.36 tsutsui int i; 630 1.47 tsutsui u_char *ptr = cci->row_ptr[sy]; 631 1.36 tsutsui for (i = 0; i < ip->font.height; i++) { 632 1.32 cegger memset(ptr, 0, bm->bytes_per_row); 633 1.1 leo ptr += bm->bytes_per_row; 634 1.1 leo } 635 1.1 leo sy++; 636 1.1 leo } 637 1.36 tsutsui } else { 638 1.1 leo /* 639 1.1 leo * clearing only part of a line 640 1.1 leo * XXX could be optimized MUCH better, but is it worth the 641 1.1 leo * trouble? 642 1.1 leo */ 643 1.1 leo 644 1.36 tsutsui int i; 645 1.36 tsutsui u_char *pls, *ple; 646 1.1 leo 647 1.1 leo pls = cci->row_ptr[sy]; 648 1.36 tsutsui ple = pls + cci->column_offset[sx + w - 1]; 649 1.1 leo pls = pls + cci->column_offset[sx]; 650 1.1 leo 651 1.36 tsutsui for (i = ((ip->font.height) * h) - 1; i >= 0; i--) { 652 1.1 leo u_char *p = pls; 653 1.36 tsutsui while (p <= ple) 654 1.1 leo *p++ = 0; 655 1.47 tsutsui pls += bm->bytes_per_row; 656 1.47 tsutsui ple += bm->bytes_per_row; 657 1.1 leo } 658 1.1 leo } 659 1.1 leo } 660 1.1 leo 661 1.1 leo /* Note: sx is only relevant for SCROLL_LEFT or SCROLL_RIGHT. */ 662 1.1 leo static void 663 1.36 tsutsui scroll8(register struct ite_softc *ip, register int sy, int sx, int count, 664 1.36 tsutsui int dir) 665 1.1 leo { 666 1.4 leo bmap_t *bm = viewview(ip->grf->g_viewdev)->bitmap; 667 1.1 leo u_char *pl = ((ipriv_t *)ip->priv)->row_ptr[sy]; 668 1.1 leo 669 1.36 tsutsui if (dir == SCROLL_UP) { 670 1.36 tsutsui int dy = sy - count; 671 1.1 leo 672 1.1 leo cursor32(ip, ERASE_CURSOR); 673 1.36 tsutsui scrollbmap(bm, 0, dy * ip->font.height, bm->bytes_per_row >> 3, 674 1.36 tsutsui (ip->bottom_margin - dy + 1) * ip->font.height, 675 1.36 tsutsui 0, -(count * ip->font.height)); 676 1.36 tsutsui } else if (dir == SCROLL_DOWN) { 677 1.47 tsutsui cursor32(ip, ERASE_CURSOR); 678 1.36 tsutsui scrollbmap(bm, 0, sy * ip->font.height, bm->bytes_per_row >> 3, 679 1.36 tsutsui (ip->bottom_margin - sy + 1) * ip->font.height, 680 1.36 tsutsui 0, count * ip->font.height); 681 1.36 tsutsui } else if (dir == SCROLL_RIGHT) { 682 1.36 tsutsui int sofs = (ip->cols - count) * ip->font.width; 683 1.36 tsutsui int dofs = (ip->cols) * ip->font.width; 684 1.36 tsutsui int i, j; 685 1.1 leo 686 1.1 leo cursor32(ip, ERASE_CURSOR); 687 1.36 tsutsui for (j = ip->font.height - 1; j >= 0; j--) { 688 1.36 tsutsui int sofs2 = sofs, dofs2 = dofs; 689 1.36 tsutsui for (i = (ip->cols - (sx + count)) - 1; i >= 0; i--) { 690 1.36 tsutsui int t; 691 1.36 tsutsui sofs2 -= ip->font.width; 692 1.36 tsutsui dofs2 -= ip->font.width; 693 1.36 tsutsui __asm("bfextu %1@{%2:%3}, %0" : "=d" (t) 694 1.36 tsutsui : "a" (pl), "d" (sofs2), 695 1.36 tsutsui "d" (ip->font.width)); 696 1.36 tsutsui __asm("bfins %3, %0@{%1:%2}" : 697 1.36 tsutsui : "a" (pl), "d" (dofs2), 698 1.36 tsutsui "d" (ip->font.width), "d" (t)); 699 1.36 tsutsui } 700 1.47 tsutsui pl += bm->bytes_per_row; 701 1.1 leo } 702 1.36 tsutsui } else { /* SCROLL_LEFT */ 703 1.1 leo int sofs = (sx) * ip->font.width; 704 1.1 leo int dofs = (sx - count) * ip->font.width; 705 1.1 leo int i, j; 706 1.1 leo 707 1.1 leo cursor32(ip, ERASE_CURSOR); 708 1.36 tsutsui for (j = ip->font.height - 1; j >= 0; j--) { 709 1.36 tsutsui int sofs2 = sofs, dofs2 = dofs; 710 1.36 tsutsui for (i = (ip->cols - sx) - 1; i >= 0; i--) { 711 1.36 tsutsui int t; 712 1.36 tsutsui 713 1.36 tsutsui __asm("bfextu %1@{%2:%3}, %0" : "=d" (t) 714 1.36 tsutsui : "a" (pl), "d" (sofs2), 715 1.36 tsutsui "d" (ip->font.width)); 716 1.36 tsutsui __asm("bfins %3, %0@{%1:%2}" : 717 1.36 tsutsui : "a" (pl), "d" (dofs2), 718 1.36 tsutsui "d" (ip->font.width), "d" (t)); 719 1.36 tsutsui sofs2 += ip->font.width; 720 1.36 tsutsui dofs2 += ip->font.width; 721 1.36 tsutsui } 722 1.47 tsutsui pl += bm->bytes_per_row; 723 1.1 leo } 724 1.47 tsutsui } 725 1.1 leo } 726 1.1 leo 727 1.47 tsutsui static void 728 1.36 tsutsui scrollbmap (bmap_t *bm, u_short x, u_short y, u_short width, u_short height, 729 1.36 tsutsui short dx, short dy) 730 1.1 leo { 731 1.36 tsutsui u_short lwpr = bm->bytes_per_row >> 2; 732 1.1 leo 733 1.36 tsutsui if (dx) { 734 1.36 tsutsui /* FIX: */ 735 1.36 tsutsui panic ("delta x not supported in scroll bitmap yet."); 736 1.47 tsutsui } 737 1.36 tsutsui 738 1.36 tsutsui if (dy == 0) { 739 1.36 tsutsui return; 740 1.47 tsutsui } 741 1.36 tsutsui if (dy > 0) { 742 1.1 leo u_long *pl = (u_long *)bm->plane; 743 1.36 tsutsui u_long *src_y = pl + (lwpr * y); 744 1.36 tsutsui u_long *dest_y = pl + (lwpr * (y + dy)); 745 1.36 tsutsui u_long count = lwpr * (height - dy); 746 1.1 leo u_long *clr_y = src_y; 747 1.1 leo u_long clr_count = dest_y - src_y; 748 1.1 leo u_long bc, cbc; 749 1.47 tsutsui 750 1.1 leo src_y += count - 1; 751 1.1 leo dest_y += count - 1; 752 1.1 leo 753 1.1 leo bc = count >> 4; 754 1.1 leo count &= 0xf; 755 1.47 tsutsui 756 1.1 leo while (bc--) { 757 1.36 tsutsui *dest_y-- = *src_y--; *dest_y-- = *src_y--; 758 1.36 tsutsui *dest_y-- = *src_y--; *dest_y-- = *src_y--; 759 1.36 tsutsui *dest_y-- = *src_y--; *dest_y-- = *src_y--; 760 1.36 tsutsui *dest_y-- = *src_y--; *dest_y-- = *src_y--; 761 1.36 tsutsui *dest_y-- = *src_y--; *dest_y-- = *src_y--; 762 1.36 tsutsui *dest_y-- = *src_y--; *dest_y-- = *src_y--; 763 1.36 tsutsui *dest_y-- = *src_y--; *dest_y-- = *src_y--; 764 1.36 tsutsui *dest_y-- = *src_y--; *dest_y-- = *src_y--; 765 1.1 leo } 766 1.1 leo while (count--) 767 1.36 tsutsui *dest_y-- = *src_y--; 768 1.1 leo 769 1.1 leo cbc = clr_count >> 4; 770 1.1 leo clr_count &= 0xf; 771 1.1 leo 772 1.1 leo while (cbc--) { 773 1.36 tsutsui *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 774 1.36 tsutsui *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 775 1.36 tsutsui *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 776 1.36 tsutsui *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 777 1.36 tsutsui } 778 1.36 tsutsui while (clr_count--) 779 1.36 tsutsui *clr_y++ = 0; 780 1.36 tsutsui } else { 781 1.1 leo u_long *pl = (u_long *)bm->plane; 782 1.36 tsutsui u_long *src_y = pl + (lwpr * (y - dy)); 783 1.47 tsutsui u_long *dest_y = pl + (lwpr * y); 784 1.36 tsutsui long count = lwpr * (height + dy); 785 1.1 leo u_long *clr_y = dest_y + count; 786 1.1 leo u_long clr_count = src_y - dest_y; 787 1.1 leo u_long bc, cbc; 788 1.1 leo 789 1.1 leo bc = count >> 4; 790 1.1 leo count &= 0xf; 791 1.47 tsutsui 792 1.36 tsutsui while (bc--) { 793 1.36 tsutsui *dest_y++ = *src_y++; *dest_y++ = *src_y++; 794 1.36 tsutsui *dest_y++ = *src_y++; *dest_y++ = *src_y++; 795 1.36 tsutsui *dest_y++ = *src_y++; *dest_y++ = *src_y++; 796 1.36 tsutsui *dest_y++ = *src_y++; *dest_y++ = *src_y++; 797 1.36 tsutsui *dest_y++ = *src_y++; *dest_y++ = *src_y++; 798 1.36 tsutsui *dest_y++ = *src_y++; *dest_y++ = *src_y++; 799 1.36 tsutsui *dest_y++ = *src_y++; *dest_y++ = *src_y++; 800 1.36 tsutsui *dest_y++ = *src_y++; *dest_y++ = *src_y++; 801 1.1 leo } 802 1.36 tsutsui while (count--) 803 1.36 tsutsui *dest_y++ = *src_y++; 804 1.1 leo 805 1.1 leo cbc = clr_count >> 4; 806 1.1 leo clr_count &= 0xf; 807 1.1 leo 808 1.1 leo while (cbc--) { 809 1.36 tsutsui *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 810 1.36 tsutsui *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 811 1.36 tsutsui *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 812 1.36 tsutsui *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 813 1.1 leo } 814 1.1 leo while (clr_count--) 815 1.36 tsutsui *clr_y++ = 0; 816 1.36 tsutsui } 817 1.1 leo } 818