1 /* $OpenBSD: omrasops.c,v 1.6 2009/09/05 14:09:35 miod Exp $ */ 2 /* $NetBSD: omrasops.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */ 3 4 /*- 5 * Copyright (c) 2000 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Tohru Nishimura. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Designed speficically for 'm68k bitorder'; 35 * - most significant byte is stored at lower address, 36 * - most significant bit is displayed at left most on screen. 37 * Implementation relies on; 38 * - every memory references is done in aligned 32bit chunk, 39 * - font glyphs are stored in 32bit padded. 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/device.h> 45 46 #include <dev/wscons/wsconsio.h> 47 #include <dev/wscons/wsdisplayvar.h> 48 #include <dev/rasops/rasops.h> 49 50 /* wscons emulator operations */ 51 int om_cursor(void *, int, int, int); 52 int om_putchar(void *, int, int, u_int, long); 53 int om_copycols(void *, int, int, int, int); 54 int om_copyrows(void *, int, int, int num); 55 int om_erasecols(void *, int, int, int, long); 56 int om_eraserows(void *, int, int, long); 57 58 #define ALL1BITS (~0U) 59 #define ALL0BITS (0U) 60 #define BLITWIDTH (32) 61 #define ALIGNMASK (0x1f) 62 #define BYTESDONE (4) 63 64 #define W(p) (*(u_int32_t *)(p)) 65 #define R(p) (*(u_int32_t *)((caddr_t)(p) + 0x40000)) 66 67 /* 68 * Blit a character at the specified co-ordinates. 69 */ 70 int 71 om_putchar(cookie, row, startcol, uc, attr) 72 void *cookie; 73 int row, startcol; 74 u_int uc; 75 long attr; 76 { 77 struct rasops_info *ri = cookie; 78 caddr_t p; 79 int scanspan, startx, height, width, align, y; 80 u_int32_t lmask, rmask, glyph, inverse; 81 int i, fg, bg; 82 u_int8_t *fb; 83 84 scanspan = ri->ri_stride; 85 y = ri->ri_font->fontheight * row; 86 startx = ri->ri_font->fontwidth * startcol; 87 height = ri->ri_font->fontheight; 88 fb = ri->ri_font->data + 89 (uc - ri->ri_font->firstchar) * ri->ri_fontscale; 90 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 91 inverse = (bg != 0) ? ALL1BITS : ALL0BITS; 92 93 p = (caddr_t)ri->ri_bits + y * scanspan + ((startx / 32) * 4); 94 align = startx & ALIGNMASK; 95 width = ri->ri_font->fontwidth + align; 96 lmask = ALL1BITS >> align; 97 rmask = ALL1BITS << (-width & ALIGNMASK); 98 if (width <= BLITWIDTH) { 99 lmask &= rmask; 100 while (height > 0) { 101 glyph = 0; 102 for (i = ri->ri_font->stride; i != 0; i--) 103 glyph = (glyph << 8) | *fb++; 104 glyph <<= (4 - ri->ri_font->stride) * NBBY; 105 glyph = (glyph >> align) ^ inverse; 106 W(p) = (R(p) & ~lmask) | (glyph & lmask); 107 p += scanspan; 108 height--; 109 } 110 } 111 else { 112 caddr_t q = p; 113 u_int32_t lhalf, rhalf; 114 115 while (height > 0) { 116 glyph = 0; 117 for (i = ri->ri_font->stride; i != 0; i--) 118 glyph = (glyph << 8) | *fb++; 119 glyph <<= (4 - ri->ri_font->stride) * NBBY; 120 lhalf = (glyph >> align) ^ inverse; 121 W(p) = (R(p) & ~lmask) | (lhalf & lmask); 122 p += BYTESDONE; 123 rhalf = (glyph << (BLITWIDTH - align)) ^ inverse; 124 W(p) = (rhalf & rmask) | (R(p) & ~rmask); 125 126 p = (q += scanspan); 127 height--; 128 } 129 } 130 131 return 0; 132 } 133 134 int 135 om_erasecols(cookie, row, startcol, ncols, attr) 136 void *cookie; 137 int row, startcol, ncols; 138 long attr; 139 { 140 struct rasops_info *ri = cookie; 141 caddr_t p; 142 int scanspan, startx, height, width, align, w, y; 143 u_int32_t lmask, rmask, fill; 144 145 scanspan = ri->ri_stride; 146 y = ri->ri_font->fontheight * row; 147 startx = ri->ri_font->fontwidth * startcol; 148 height = ri->ri_font->fontheight; 149 w = ri->ri_font->fontwidth * ncols; 150 fill = (attr != 0) ? ALL1BITS : ALL0BITS; 151 152 p = (caddr_t)ri->ri_bits + y * scanspan + ((startx / 32) * 4); 153 align = startx & ALIGNMASK; 154 width = w + align; 155 lmask = ALL1BITS >> align; 156 rmask = ALL1BITS << (-width & ALIGNMASK); 157 if (width <= BLITWIDTH) { 158 lmask &= rmask; 159 fill &= lmask; 160 while (height > 0) { 161 W(p) = (R(p) & ~lmask) | fill; 162 p += scanspan; 163 height--; 164 } 165 } 166 else { 167 caddr_t q = p; 168 while (height > 0) { 169 W(p) = (R(p) & ~lmask) | (fill & lmask); 170 width -= 2 * BLITWIDTH; 171 while (width > 0) { 172 p += BYTESDONE; 173 W(p) = fill; 174 width -= BLITWIDTH; 175 } 176 p += BYTESDONE; 177 W(p) = (fill & rmask) | (R(p) & ~rmask); 178 179 p = (q += scanspan); 180 width = w + align; 181 height--; 182 } 183 } 184 185 return 0; 186 } 187 188 int 189 om_eraserows(cookie, startrow, nrows, attr) 190 void *cookie; 191 int startrow, nrows; 192 long attr; 193 { 194 struct rasops_info *ri = cookie; 195 caddr_t p, q; 196 int scanspan, starty, height, width, w; 197 u_int32_t rmask, fill; 198 199 scanspan = ri->ri_stride; 200 starty = ri->ri_font->fontheight * startrow; 201 height = ri->ri_font->fontheight * nrows; 202 w = ri->ri_emuwidth; 203 fill = (attr == 1) ? ALL1BITS : ALL0BITS; 204 205 p = (caddr_t)ri->ri_bits + starty * scanspan; 206 width = w; 207 rmask = ALL1BITS << (-width & ALIGNMASK); 208 q = p; 209 while (height > 0) { 210 W(p) = fill; /* always aligned */ 211 width -= 2 * BLITWIDTH; 212 while (width > 0) { 213 p += BYTESDONE; 214 W(p) = fill; 215 width -= BLITWIDTH; 216 } 217 p += BYTESDONE; 218 W(p) = (fill & rmask) | (R(p) & ~rmask); 219 p = (q += scanspan); 220 width = w; 221 height--; 222 } 223 224 return 0; 225 } 226 227 int 228 om_copyrows(cookie, srcrow, dstrow, nrows) 229 void *cookie; 230 int srcrow, dstrow, nrows; 231 { 232 struct rasops_info *ri = cookie; 233 caddr_t p, q; 234 int scanspan, offset, srcy, height, width, w; 235 u_int32_t rmask; 236 237 scanspan = ri->ri_stride; 238 height = ri->ri_font->fontheight * nrows; 239 offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight; 240 srcy = ri->ri_font->fontheight * srcrow; 241 if (srcrow < dstrow && srcrow + nrows > dstrow) { 242 scanspan = -scanspan; 243 srcy += height; 244 } 245 246 p = (caddr_t)ri->ri_bits + srcy * ri->ri_stride; 247 w = ri->ri_emuwidth; 248 width = w; 249 rmask = ALL1BITS << (-width & ALIGNMASK); 250 q = p; 251 while (height > 0) { 252 W(p + offset) = R(p); /* always aligned */ 253 width -= 2 * BLITWIDTH; 254 while (width > 0) { 255 p += BYTESDONE; 256 W(p + offset) = R(p); 257 width -= BLITWIDTH; 258 } 259 p += BYTESDONE; 260 W(p + offset) = (R(p) & rmask) | (R(p + offset) & ~rmask); 261 262 p = (q += scanspan); 263 width = w; 264 height--; 265 } 266 267 return 0; 268 } 269 270 int 271 om_copycols(cookie, startrow, srccol, dstcol, ncols) 272 void *cookie; 273 int startrow, srccol, dstcol, ncols; 274 { 275 struct rasops_info *ri = cookie; 276 caddr_t sp, dp, basep; 277 int scanspan, height, width, align, shift, w, y, srcx, dstx; 278 u_int32_t lmask, rmask; 279 280 scanspan = ri->ri_stride; 281 y = ri->ri_font->fontheight * startrow; 282 srcx = ri->ri_font->fontwidth * srccol; 283 dstx = ri->ri_font->fontwidth * dstcol; 284 height = ri->ri_font->fontheight; 285 w = ri->ri_font->fontwidth * ncols; 286 basep = (caddr_t)ri->ri_bits + y * scanspan; 287 288 align = shift = srcx & ALIGNMASK; 289 width = w + align; 290 align = dstx & ALIGNMASK; 291 lmask = ALL1BITS >> align; 292 rmask = ALL1BITS << (-(w + align) & ALIGNMASK); 293 shift = align - shift; 294 sp = basep + (srcx / 32) * 4; 295 dp = basep + (dstx / 32) * 4; 296 297 if (shift != 0) 298 goto hardluckalignment; 299 300 /* alignments comfortably match */ 301 if (width <= BLITWIDTH) { 302 lmask &= rmask; 303 while (height > 0) { 304 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); 305 dp += scanspan; 306 sp += scanspan; 307 height--; 308 } 309 } 310 /* copy forward (left-to-right) */ 311 else if (dstcol < srccol || srccol + ncols < dstcol) { 312 caddr_t sq = sp, dq = dp; 313 314 w = width; 315 while (height > 0) { 316 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); 317 width -= 2 * BLITWIDTH; 318 while (width > 0) { 319 sp += BYTESDONE; 320 dp += BYTESDONE; 321 W(dp) = R(sp); 322 width -= BLITWIDTH; 323 } 324 sp += BYTESDONE; 325 dp += BYTESDONE; 326 W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask); 327 sp = (sq += scanspan); 328 dp = (dq += scanspan); 329 width = w; 330 height--; 331 } 332 } 333 /* copy backward (right-to-left) */ 334 else { 335 caddr_t sq, dq; 336 337 sq = (sp += width / 32 * 4); 338 dq = (dp += width / 32 * 4); 339 w = width; 340 while (height > 0) { 341 W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask); 342 width -= 2 * BLITWIDTH; 343 while (width > 0) { 344 sp -= BYTESDONE; 345 dp -= BYTESDONE; 346 W(dp) = R(sp); 347 width -= BLITWIDTH; 348 } 349 sp -= BYTESDONE; 350 dp -= BYTESDONE; 351 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); 352 353 sp = (sq += scanspan); 354 dp = (dq += scanspan); 355 width = w; 356 height--; 357 } 358 } 359 return 0; 360 361 hardluckalignment: 362 /* alignments painfully disagree */ 363 364 return 0; 365 } 366 367 /* 368 * Position|{enable|disable} the cursor at the specified location. 369 */ 370 int 371 om_cursor(cookie, on, row, col) 372 void *cookie; 373 int on, row, col; 374 { 375 struct rasops_info *ri = cookie; 376 caddr_t p; 377 int scanspan, startx, height, width, align, y; 378 u_int32_t lmask, rmask, image; 379 380 if (!on) { 381 /* make sure it's on */ 382 if ((ri->ri_flg & RI_CURSOR) == 0) 383 return 0; 384 385 row = ri->ri_crow; 386 col = ri->ri_ccol; 387 } else { 388 /* unpaint the old copy. */ 389 ri->ri_crow = row; 390 ri->ri_ccol = col; 391 } 392 393 scanspan = ri->ri_stride; 394 y = ri->ri_font->fontheight * row; 395 startx = ri->ri_font->fontwidth * col; 396 height = ri->ri_font->fontheight; 397 398 p = (caddr_t)ri->ri_bits + y * scanspan + ((startx / 32) * 4); 399 align = startx & ALIGNMASK; 400 width = ri->ri_font->fontwidth + align; 401 lmask = ALL1BITS >> align; 402 rmask = ALL1BITS << (-width & ALIGNMASK); 403 if (width <= BLITWIDTH) { 404 lmask &= rmask; 405 while (height > 0) { 406 image = R(p); 407 W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask); 408 p += scanspan; 409 height--; 410 } 411 } 412 else { 413 caddr_t q = p; 414 415 while (height > 0) { 416 image = R(p); 417 W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask); 418 p += BYTESDONE; 419 image = R(p); 420 W(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask); 421 422 p = (q += scanspan); 423 height--; 424 } 425 } 426 ri->ri_flg ^= RI_CURSOR; 427 428 return 0; 429 } 430