1 1.36 uwe /* $NetBSD: pcdisplay_subr.c,v 1.36 2022/03/25 12:24:44 uwe Exp $ */ 2 1.1 drochner 3 1.1 drochner /* 4 1.1 drochner * Copyright (c) 1995, 1996 Carnegie-Mellon University. 5 1.1 drochner * All rights reserved. 6 1.1 drochner * 7 1.1 drochner * Author: Chris G. Demetriou 8 1.28 perry * 9 1.1 drochner * Permission to use, copy, modify and distribute this software and 10 1.1 drochner * its documentation is hereby granted, provided that both the copyright 11 1.1 drochner * notice and this permission notice appear in all copies of the 12 1.1 drochner * software, derivative works or modified versions, and any portions 13 1.1 drochner * thereof, and that both notices appear in supporting documentation. 14 1.28 perry * 15 1.28 perry * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 1.28 perry * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 1.1 drochner * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 1.28 perry * 19 1.1 drochner * Carnegie Mellon requests users of this software to return to 20 1.1 drochner * 21 1.1 drochner * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 22 1.1 drochner * School of Computer Science 23 1.1 drochner * Carnegie Mellon University 24 1.1 drochner * Pittsburgh PA 15213-3890 25 1.1 drochner * 26 1.1 drochner * any improvements or extensions that they make and grant Carnegie the 27 1.1 drochner * rights to redistribute these changes. 28 1.1 drochner */ 29 1.20 lukem 30 1.20 lukem #include <sys/cdefs.h> 31 1.36 uwe __KERNEL_RCSID(0, "$NetBSD: pcdisplay_subr.c,v 1.36 2022/03/25 12:24:44 uwe Exp $"); 32 1.27 jmmv 33 1.27 jmmv #include "opt_wsmsgattrs.h" /* for WSDISPLAY_CUSTOM_OUTPUT */ 34 1.1 drochner 35 1.1 drochner #include <sys/param.h> 36 1.1 drochner #include <sys/systm.h> 37 1.1 drochner #include <sys/device.h> 38 1.34 ad #include <sys/bus.h> 39 1.1 drochner 40 1.1 drochner #include <dev/ic/mc6845reg.h> 41 1.1 drochner #include <dev/ic/pcdisplayvar.h> 42 1.21 christos #include <dev/wscons/wsconsio.h> 43 1.1 drochner 44 1.1 drochner #include <dev/wscons/wsdisplayvar.h> 45 1.12 ad 46 1.12 ad void 47 1.30 jmmv pcdisplay_cursor_init(struct pcdisplayscreen *scr, int existing) 48 1.12 ad { 49 1.14 ad #ifdef PCDISPLAY_SOFTCURSOR 50 1.14 ad bus_space_tag_t memt; 51 1.14 ad bus_space_handle_t memh; 52 1.14 ad int off; 53 1.12 ad 54 1.35 jmcneill /* Disable the hardware cursor */ 55 1.35 jmcneill pcdisplay_6845_write(scr->hdl, curstart, 0x20); 56 1.35 jmcneill pcdisplay_6845_write(scr->hdl, curend, 0x00); 57 1.28 perry 58 1.14 ad if (existing) { 59 1.14 ad /* 60 1.19 drochner * This is the first screen. At this point, scr->mem is NULL 61 1.19 drochner * (no backing store), so we can't use pcdisplay_cursor() to 62 1.19 drochner * do this. 63 1.14 ad */ 64 1.14 ad memt = scr->hdl->ph_memt; 65 1.14 ad memh = scr->hdl->ph_memh; 66 1.23 junyoung off = (scr->cursorrow * scr->type->ncols + scr->cursorcol) * 2 67 1.23 junyoung + scr->dispoffset; 68 1.14 ad 69 1.14 ad scr->cursortmp = bus_space_read_2(memt, memh, off); 70 1.14 ad bus_space_write_2(memt, memh, off, scr->cursortmp ^ 0x7700); 71 1.15 ad } else 72 1.15 ad scr->cursortmp = 0; 73 1.17 thorpej #else 74 1.17 thorpej /* 75 1.17 thorpej * Firmware might not have initialized the cursor shape. Make 76 1.17 thorpej * sure there's something we can see. 77 1.19 drochner * Don't touch the hardware if this is not the first screen. 78 1.17 thorpej */ 79 1.19 drochner if (existing) { 80 1.19 drochner pcdisplay_6845_write(scr->hdl, curstart, 81 1.19 drochner scr->type->fontheight - 2); 82 1.19 drochner pcdisplay_6845_write(scr->hdl, curend, 83 1.19 drochner scr->type->fontheight - 1); 84 1.19 drochner } 85 1.12 ad #endif 86 1.14 ad scr->cursoron = 1; 87 1.12 ad } 88 1.1 drochner 89 1.1 drochner void 90 1.30 jmmv pcdisplay_cursor(void *id, int on, int row, int col) 91 1.1 drochner { 92 1.7 ad #ifdef PCDISPLAY_SOFTCURSOR 93 1.7 ad struct pcdisplayscreen *scr = id; 94 1.7 ad bus_space_tag_t memt = scr->hdl->ph_memt; 95 1.7 ad bus_space_handle_t memh = scr->hdl->ph_memh; 96 1.7 ad int off; 97 1.7 ad 98 1.7 ad /* Remove old cursor image */ 99 1.7 ad if (scr->cursoron) { 100 1.23 junyoung off = scr->cursorrow * scr->type->ncols + scr->cursorcol; 101 1.7 ad if (scr->active) 102 1.7 ad bus_space_write_2(memt, memh, scr->dispoffset + off * 2, 103 1.7 ad scr->cursortmp); 104 1.7 ad else 105 1.7 ad scr->mem[off] = scr->cursortmp; 106 1.7 ad } 107 1.28 perry 108 1.23 junyoung scr->cursorrow = row; 109 1.23 junyoung scr->cursorcol = col; 110 1.7 ad 111 1.7 ad if ((scr->cursoron = on) == 0) 112 1.7 ad return; 113 1.7 ad 114 1.23 junyoung off = (scr->cursorrow * scr->type->ncols + scr->cursorcol); 115 1.8 ad if (scr->active) { 116 1.14 ad off = off * 2 + scr->dispoffset; 117 1.14 ad scr->cursortmp = bus_space_read_2(memt, memh, off); 118 1.14 ad bus_space_write_2(memt, memh, off, scr->cursortmp ^ 0x7700); 119 1.8 ad } else { 120 1.8 ad scr->cursortmp = scr->mem[off]; 121 1.9 ad scr->mem[off] = scr->cursortmp ^ 0x7700; 122 1.8 ad } 123 1.7 ad #else /* PCDISPLAY_SOFTCURSOR */ 124 1.1 drochner struct pcdisplayscreen *scr = id; 125 1.1 drochner int pos; 126 1.1 drochner 127 1.23 junyoung scr->cursorrow = row; 128 1.24 tron scr->cursorcol = col; 129 1.1 drochner scr->cursoron = on; 130 1.1 drochner 131 1.1 drochner if (scr->active) { 132 1.7 ad if (!on) 133 1.19 drochner pos = 0x3fff; 134 1.7 ad else 135 1.6 drochner pos = scr->dispoffset / 2 136 1.6 drochner + row * scr->type->ncols + col; 137 1.1 drochner 138 1.1 drochner pcdisplay_6845_write(scr->hdl, cursorh, pos >> 8); 139 1.1 drochner pcdisplay_6845_write(scr->hdl, cursorl, pos); 140 1.1 drochner } 141 1.7 ad #endif /* PCDISPLAY_SOFTCURSOR */ 142 1.1 drochner } 143 1.1 drochner 144 1.5 drochner #if 0 145 1.5 drochner unsigned int 146 1.30 jmmv pcdisplay_mapchar_simple(void *id, int uni) 147 1.4 drochner { 148 1.5 drochner if (uni < 128) 149 1.5 drochner return (uni); 150 1.5 drochner 151 1.5 drochner return (1); /* XXX ??? smiley */ 152 1.5 drochner } 153 1.5 drochner #endif 154 1.4 drochner 155 1.1 drochner void 156 1.30 jmmv pcdisplay_putchar(void *id, int row, int col, unsigned int c, long attr) 157 1.1 drochner { 158 1.1 drochner struct pcdisplayscreen *scr = id; 159 1.1 drochner bus_space_tag_t memt = scr->hdl->ph_memt; 160 1.1 drochner bus_space_handle_t memh = scr->hdl->ph_memh; 161 1.33 mjf size_t off; 162 1.1 drochner 163 1.1 drochner off = row * scr->type->ncols + col; 164 1.1 drochner 165 1.33 mjf /* check for bogus row and column sizes */ 166 1.33 mjf if (__predict_false(off >= (scr->type->ncols * scr->type->nrows))) 167 1.33 mjf return; 168 1.33 mjf 169 1.4 drochner if (scr->active) 170 1.6 drochner bus_space_write_2(memt, memh, scr->dispoffset + off * 2, 171 1.5 drochner c | (attr << 8)); 172 1.4 drochner else 173 1.5 drochner scr->mem[off] = c | (attr << 8); 174 1.26 christos 175 1.26 christos scr->visibleoffset = scr->dispoffset; 176 1.1 drochner } 177 1.1 drochner 178 1.1 drochner void 179 1.30 jmmv pcdisplay_copycols(void *id, int row, int srccol, int dstcol, int ncols) 180 1.1 drochner { 181 1.1 drochner struct pcdisplayscreen *scr = id; 182 1.1 drochner bus_space_tag_t memt = scr->hdl->ph_memt; 183 1.1 drochner bus_space_handle_t memh = scr->hdl->ph_memh; 184 1.1 drochner bus_size_t srcoff, dstoff; 185 1.1 drochner 186 1.1 drochner srcoff = dstoff = row * scr->type->ncols; 187 1.1 drochner srcoff += srccol; 188 1.1 drochner dstoff += dstcol; 189 1.1 drochner 190 1.1 drochner if (scr->active) 191 1.6 drochner bus_space_copy_region_2(memt, memh, 192 1.6 drochner scr->dispoffset + srcoff * 2, 193 1.6 drochner memh, scr->dispoffset + dstoff * 2, 194 1.6 drochner ncols); 195 1.1 drochner else 196 1.18 thorpej memcpy(&scr->mem[dstoff], &scr->mem[srcoff], ncols * 2); 197 1.1 drochner } 198 1.1 drochner 199 1.1 drochner void 200 1.30 jmmv pcdisplay_erasecols(void *id, int row, int startcol, int ncols, long fillattr) 201 1.1 drochner { 202 1.1 drochner struct pcdisplayscreen *scr = id; 203 1.1 drochner bus_space_tag_t memt = scr->hdl->ph_memt; 204 1.1 drochner bus_space_handle_t memh = scr->hdl->ph_memh; 205 1.1 drochner bus_size_t off; 206 1.1 drochner u_int16_t val; 207 1.1 drochner int i; 208 1.1 drochner 209 1.1 drochner off = row * scr->type->ncols + startcol; 210 1.1 drochner 211 1.1 drochner val = (fillattr << 8) | ' '; 212 1.1 drochner 213 1.1 drochner if (scr->active) 214 1.6 drochner bus_space_set_region_2(memt, memh, scr->dispoffset + off * 2, 215 1.6 drochner val, ncols); 216 1.1 drochner else 217 1.1 drochner for (i = 0; i < ncols; i++) 218 1.1 drochner scr->mem[off + i] = val; 219 1.1 drochner } 220 1.1 drochner 221 1.1 drochner void 222 1.30 jmmv pcdisplay_copyrows(void *id, int srcrow, int dstrow, int nrows) 223 1.1 drochner { 224 1.1 drochner struct pcdisplayscreen *scr = id; 225 1.1 drochner bus_space_tag_t memt = scr->hdl->ph_memt; 226 1.1 drochner bus_space_handle_t memh = scr->hdl->ph_memh; 227 1.1 drochner int ncols = scr->type->ncols; 228 1.1 drochner bus_size_t srcoff, dstoff; 229 1.1 drochner 230 1.1 drochner srcoff = srcrow * ncols + 0; 231 1.1 drochner dstoff = dstrow * ncols + 0; 232 1.1 drochner 233 1.1 drochner if (scr->active) 234 1.6 drochner bus_space_copy_region_2(memt, memh, 235 1.6 drochner scr->dispoffset + srcoff * 2, 236 1.6 drochner memh, scr->dispoffset + dstoff * 2, 237 1.6 drochner nrows * ncols); 238 1.1 drochner else 239 1.18 thorpej memcpy(&scr->mem[dstoff], &scr->mem[srcoff], 240 1.1 drochner nrows * ncols * 2); 241 1.1 drochner } 242 1.1 drochner 243 1.1 drochner void 244 1.30 jmmv pcdisplay_eraserows(void *id, int startrow, int nrows, long fillattr) 245 1.1 drochner { 246 1.1 drochner struct pcdisplayscreen *scr = id; 247 1.1 drochner bus_space_tag_t memt = scr->hdl->ph_memt; 248 1.1 drochner bus_space_handle_t memh = scr->hdl->ph_memh; 249 1.1 drochner bus_size_t off, count; 250 1.1 drochner u_int16_t val; 251 1.25 thorpej u_int i; 252 1.1 drochner 253 1.1 drochner off = startrow * scr->type->ncols; 254 1.1 drochner count = nrows * scr->type->ncols; 255 1.1 drochner 256 1.1 drochner val = (fillattr << 8) | ' '; 257 1.1 drochner 258 1.1 drochner if (scr->active) 259 1.6 drochner bus_space_set_region_2(memt, memh, scr->dispoffset + off * 2, 260 1.6 drochner val, count); 261 1.1 drochner else 262 1.1 drochner for (i = 0; i < count; i++) 263 1.1 drochner scr->mem[off + i] = val; 264 1.21 christos } 265 1.21 christos 266 1.27 jmmv #ifdef WSDISPLAY_CUSTOM_OUTPUT 267 1.27 jmmv void 268 1.30 jmmv pcdisplay_replaceattr(void *id, long oldattr, long newattr) 269 1.27 jmmv { 270 1.27 jmmv struct pcdisplayscreen *scr = id; 271 1.27 jmmv bus_space_tag_t memt = scr->hdl->ph_memt; 272 1.27 jmmv bus_space_handle_t memh = scr->hdl->ph_memh; 273 1.27 jmmv int off; 274 1.27 jmmv uint16_t chardata; 275 1.27 jmmv 276 1.27 jmmv if (scr->active) 277 1.27 jmmv for (off = 0; off < scr->type->nrows * scr->type->ncols; 278 1.27 jmmv off++) { 279 1.27 jmmv chardata = bus_space_read_2(memt, memh, 280 1.27 jmmv scr->dispoffset + off * 2); 281 1.27 jmmv if ((long)(chardata >> 8) == oldattr) 282 1.27 jmmv bus_space_write_2(memt, memh, 283 1.27 jmmv scr->dispoffset + off * 2, 284 1.27 jmmv ((u_int16_t)(newattr << 8)) | 285 1.27 jmmv (chardata & 0x00FF)); 286 1.27 jmmv } 287 1.27 jmmv else 288 1.27 jmmv for (off = 0; off < scr->type->nrows * scr->type->ncols; 289 1.27 jmmv off++) { 290 1.27 jmmv chardata = scr->mem[off]; 291 1.27 jmmv if ((long)(chardata >> 8) == oldattr) 292 1.27 jmmv scr->mem[off] = ((u_int16_t)(newattr << 8)) | 293 1.27 jmmv (chardata & 0x00FF); 294 1.27 jmmv } 295 1.27 jmmv } 296 1.27 jmmv #endif /* WSDISPLAY_CUSTOM_OUTPUT */ 297 1.27 jmmv 298 1.21 christos int 299 1.32 jmmv pcdisplay_getwschar(struct pcdisplayscreen *scr, struct wsdisplay_char *wschar) 300 1.21 christos { 301 1.33 mjf size_t off; 302 1.21 christos uint16_t chardata; 303 1.21 christos uint8_t attrbyte; 304 1.21 christos 305 1.32 jmmv KASSERT(scr != NULL && wschar != NULL); 306 1.32 jmmv 307 1.21 christos off = wschar->row * scr->type->ncols + wschar->col; 308 1.21 christos if (off >= scr->type->ncols * scr->type->nrows) 309 1.36 uwe return EINVAL; 310 1.21 christos 311 1.21 christos if (scr->active) 312 1.31 jmmv chardata = bus_space_read_2(scr->hdl->ph_memt, 313 1.31 jmmv scr->hdl->ph_memh, scr->dispoffset + off * 2); 314 1.21 christos else 315 1.21 christos chardata = scr->mem[off]; 316 1.21 christos 317 1.21 christos wschar->letter = (chardata & 0x00FF); 318 1.21 christos wschar->flags = 0; 319 1.21 christos attrbyte = (chardata & 0xFF00) >> 8; 320 1.21 christos if ((attrbyte & 0x08)) wschar->flags |= WSDISPLAY_CHAR_BRIGHT; 321 1.21 christos if ((attrbyte & 0x80)) wschar->flags |= WSDISPLAY_CHAR_BLINK; 322 1.21 christos wschar->foreground = attrbyte & 0x07; 323 1.21 christos wschar->background = (attrbyte >> 4) & 0x07; 324 1.21 christos 325 1.21 christos return 0; 326 1.21 christos } 327 1.21 christos 328 1.21 christos int 329 1.32 jmmv pcdisplay_putwschar(struct pcdisplayscreen *scr, struct wsdisplay_char *wschar) 330 1.21 christos { 331 1.33 mjf size_t off; 332 1.21 christos uint16_t chardata; 333 1.21 christos uint8_t attrbyte; 334 1.21 christos 335 1.32 jmmv KASSERT(scr != NULL && wschar != NULL); 336 1.32 jmmv 337 1.21 christos off = wschar->row * scr->type->ncols + wschar->col; 338 1.21 christos if (off >= (scr->type->ncols * scr->type->nrows)) 339 1.36 uwe return EINVAL; 340 1.21 christos 341 1.21 christos attrbyte = wschar->background & 0x07; 342 1.21 christos if (wschar->flags & WSDISPLAY_CHAR_BLINK) attrbyte |= 0x08; 343 1.21 christos attrbyte <<= 4; 344 1.21 christos attrbyte |= wschar->foreground & 0x07; 345 1.21 christos if (wschar->flags & WSDISPLAY_CHAR_BRIGHT) attrbyte |= 0x08; 346 1.21 christos chardata = (attrbyte << 8) | wschar->letter; 347 1.21 christos 348 1.21 christos if (scr->active) 349 1.31 jmmv bus_space_write_2(scr->hdl->ph_memt, scr->hdl->ph_memh, 350 1.31 jmmv scr->dispoffset + off * 2, chardata); 351 1.21 christos else 352 1.21 christos scr->mem[off] = chardata; 353 1.21 christos 354 1.21 christos return 0; 355 1.1 drochner } 356