1 /* $NetBSD: grf_cv.c,v 1.55 2012/11/08 18:04:56 rkujawa Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Michael Teske 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Ezra Story, by Kari 18 * Mettinen, Michael Teske and by Bernd Ernesti. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 #include "opt_amigacons.h" 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: grf_cv.c,v 1.55 2012/11/08 18:04:56 rkujawa Exp $"); 37 38 #include "grfcv.h" 39 #include "ite.h" 40 #include "wsdisplay.h" 41 #if NGRFCV > 0 42 43 /* 44 * Graphics routines for the CyberVision 64 board, using the S3 Trio64. 45 * 46 * Modified for CV64 from 47 * Kari Mettinen's Cirrus driver by Michael Teske 10/95 48 * 49 * Thanks to Tekelec Airtronic for providing me with a S3 Trio64 documentation. 50 * Thanks to Bernd 'the fabulous bug-finder' Ernesti for bringing my messy 51 * source to NetBSD style :) 52 * Thanks to Harald Koenig for providing information about undocumented 53 * Trio64 Bugs. 54 */ 55 56 #include <sys/param.h> 57 #include <sys/errno.h> 58 #include <sys/ioctl.h> 59 #include <sys/device.h> 60 #include <sys/malloc.h> 61 #include <sys/systm.h> 62 #include <sys/syslog.h> 63 64 #include <machine/cpu.h> 65 66 #include <dev/cons.h> 67 #if NWSDISPLAY > 0 68 #include <dev/wscons/wsconsio.h> 69 #include <dev/wscons/wsdisplayvar.h> 70 #include <dev/rasops/rasops.h> 71 #include <dev/wscons/wsdisplay_vconsvar.h> 72 #endif 73 74 #include <amiga/dev/itevar.h> 75 #include <amiga/amiga/device.h> 76 #include <amiga/amiga/isr.h> 77 #include <amiga/dev/grfioctl.h> 78 #include <amiga/dev/grfws.h> 79 #include <amiga/dev/grfvar.h> 80 #include <amiga/dev/grf_cvreg.h> 81 #include <amiga/dev/zbusvar.h> 82 83 int grfcvmatch(device_t, cfdata_t, void *); 84 void grfcvattach(device_t, device_t, void *); 85 int grfcvprint(void *, const char *); 86 87 int cvintr(void *); 88 static int cv_has_4mb(volatile void *); 89 static unsigned short cv_compute_clock(unsigned long); 90 void cv_boardinit(struct grf_softc *); 91 int cv_getvmode(struct grf_softc *, struct grfvideo_mode *); 92 int cv_setvmode(struct grf_softc *, unsigned int); 93 int cv_blank(struct grf_softc *, int *); 94 int cv_mode(register struct grf_softc *, u_long, void *, u_long, int); 95 int cv_ioctl(register struct grf_softc *gp, u_long cmd, void *data); 96 int cv_setmonitor(struct grf_softc *, struct grfvideo_mode *); 97 int cv_getcmap(struct grf_softc *, struct grf_colormap *); 98 int cv_putcmap(struct grf_softc *, struct grf_colormap *); 99 int cv_toggle(struct grf_softc *); 100 int cv_mondefok(struct grfvideo_mode *); 101 int cv_load_mon(struct grf_softc *, struct grfcvtext_mode *); 102 void cv_inittextmode(struct grf_softc *); 103 static inline void cv_write_port(unsigned short, volatile void *); 104 static inline void cvscreen(int, volatile void *); 105 static inline void gfx_on_off(int, volatile void *); 106 107 #ifndef CV_NO_HARDWARE_CURSOR 108 int cv_getspritepos(struct grf_softc *, struct grf_position *); 109 int cv_setspritepos(struct grf_softc *, struct grf_position *); 110 int cv_getspriteinfo(struct grf_softc *,struct grf_spriteinfo *); 111 void cv_setup_hwc(struct grf_softc *); 112 int cv_setspriteinfo(struct grf_softc *,struct grf_spriteinfo *); 113 int cv_getspritemax(struct grf_softc *,struct grf_position *); 114 #endif /* !CV_NO_HARDWARE_CURSOR */ 115 116 /* 117 * Extension to grf_softc for interrupt support 118 */ 119 120 struct grf_cv_softc { 121 struct grf_softc gcs_sc; 122 struct isr gcs_isr; 123 }; 124 125 /* Graphics display definitions. 126 * These are filled by 'grfconfig' using GRFIOCSETMON. 127 */ 128 #define monitor_def_max 24 129 static struct grfvideo_mode monitor_def[24] = { 130 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, 131 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, 132 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} 133 }; 134 static struct grfvideo_mode *monitor_current = &monitor_def[0]; 135 #define MAXPIXELCLOCK 135000000 /* safety */ 136 137 unsigned char cv_pass_toggle; /* passthru status tracker */ 138 139 /* Console display definition. 140 * Default hardcoded text mode. This grf_cv is set up to 141 * use one text mode only, and this is it. You may use 142 * grfconfig to change the mode after boot. 143 */ 144 145 /* Console font */ 146 #ifdef KFONT_8X11 147 #define S3FONT kernel_font_8x11 148 #define S3FONTY 11 149 #else 150 #define S3FONT kernel_font_8x8 151 #define S3FONTY 8 152 #endif 153 extern unsigned char S3FONT[]; 154 155 /* 156 * Define default console mode 157 * (Internally, we still have to use hvalues/8!) 158 */ 159 struct grfcvtext_mode cvconsole_mode = { 160 {255, "", 25000000, 640, 480, 4, 640/8, 680/8, 768/8, 800/8, 161 481, 491, 493, 525, 0}, 162 8, S3FONTY, 80, 480 / S3FONTY, S3FONT, 32, 255 163 }; 164 165 /* Console colors */ 166 unsigned char cvconscolors[16][3] = { /* background, foreground, hilite */ 167 /* R G B */ 168 {0x30, 0x30, 0x30}, 169 {0x00, 0x00, 0x00}, 170 {0x80, 0x00, 0x00}, 171 {0x00, 0x80, 0x00}, 172 {0x00, 0x00, 0x80}, 173 {0x80, 0x80, 0x00}, 174 {0x00, 0x80, 0x80}, 175 {0x80, 0x00, 0x80}, 176 {0xff, 0xff, 0xff}, 177 {0x40, 0x40, 0x40}, 178 {0xff, 0x00, 0x00}, 179 {0x00, 0xff, 0x00}, 180 {0x00, 0x00, 0xff}, 181 {0xff, 0xff, 0x00}, 182 {0x00, 0xff, 0xff}, 183 {0x00, 0x00, 0xff} 184 }; 185 186 static unsigned char clocks[]={ 187 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69, 188 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c, 189 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a, 190 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69, 191 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65, 192 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63, 193 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d, 194 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49, 195 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42, 196 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43, 197 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49, 198 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a, 199 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49, 200 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41, 201 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43, 202 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45, 203 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45, 204 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45, 205 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44, 206 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46, 207 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f, 208 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22, 209 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46, 210 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b, 211 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44, 212 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26, 213 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b, 214 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25, 215 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25, 216 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21, 217 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29, 218 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29, 219 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29, 220 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28, 221 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26, 222 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21, 223 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28, 224 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27, 225 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22, 226 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27, 227 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27, 228 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21, 229 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26, 230 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27, 231 0x13, 0x1, 0x13, 0x1, 0x7d, 0x27, 0x4c, 0x9, 232 0x37, 0x22, 0x5b, 0xb, 0x71, 0x26, 0x5c, 0xb, 233 0x6b, 0xd, 0x47, 0x23, 0x14, 0x1, 0x4f, 0x9, 234 0x23, 0x3, 0x75, 0x26, 0x7d, 0xf, 0x1c, 0x2, 235 0x51, 0x9, 0x59, 0x24, 0x61, 0xb, 0x69, 0x25, 236 0x79, 0x26, 0x34, 0x5, 0x1d, 0x2, 0x6b, 0x25, 237 0x54, 0x9, 0x35, 0x5, 0x45, 0x7, 0x6d, 0x25, 238 0x7d, 0x26, 0x16, 0x1, 0x7f, 0x26, 0x77, 0xd, 239 0x4f, 0x23, 0x78, 0xd, 0x2f, 0x21, 0x27, 0x3, 240 0x1f, 0x2, 0x59, 0x9, 0x6a, 0xb, 0x73, 0x25, 241 0x6b, 0xb, 0x63, 0x24, 0x5b, 0x9, 0x20, 0x2, 242 0x7e, 0xd, 0x4b, 0x7, 0x65, 0x24, 0x43, 0x22, 243 0x18, 0x1, 0x6f, 0xb, 0x5e, 0x9, 0x70, 0xb, 244 0x2a, 0x3, 0x33, 0x4, 0x45, 0x6, 0x60, 0x9, 245 0x7b, 0xc, 0x19, 0x1, 0x19, 0x1, 0x7d, 0xc, 246 0x74, 0xb, 0x50, 0x7, 0x75, 0xb, 0x63, 0x9, 247 0x51, 0x7, 0x23, 0x2, 0x3f, 0x5, 0x1a, 0x1, 248 0x65, 0x9, 0x2d, 0x3, 0x40, 0x5, 0x0, 0x0, 249 }; 250 251 252 /* Board Address of CV64 */ 253 static volatile void *cv_boardaddr; 254 static int cv_fbsize; 255 256 /* 257 * Memory clock (binpatchable). 258 * Let's be defensive: 50 MHz runs on all boards I know of. 259 * 55 MHz runs on most boards. But you should know what you're doing 260 * if you set this flag. Again: This flag may destroy your CV Board. 261 * Use it at your own risk!!! 262 * Anyway, this doesn't imply that I'm responsible if your board breaks 263 * without setting this flag :-). 264 */ 265 #ifdef CV_AGGRESSIVE_TIMING 266 long cv_memclk = 55000000; 267 #else 268 long cv_memclk = 50000000; 269 #endif 270 271 #if NWSDISPLAY > 0 272 /* wsdisplay acessops, emulops */ 273 static void cv_wscursor(void *, int, int, int); 274 static void cv_wsputchar(void *, int, int, u_int, long); 275 static void cv_wscopycols(void *, int, int, int, int); 276 static void cv_wserasecols(void *, int, int, int, long); 277 static void cv_wscopyrows(void *, int, int, int); 278 static void cv_wseraserows(void *, int, int, long); 279 static int cv_wsallocattr(void *, int, int, int, long *); 280 static int cv_wsmapchar(void *, int, unsigned int *); 281 282 static struct wsdisplay_accessops cv_accessops = { 283 .ioctl = grf_wsioctl, 284 .mmap = grf_wsmmap 285 }; 286 287 static struct wsdisplay_emulops cv_textops = { 288 .cursor = cv_wscursor, 289 .mapchar = cv_wsmapchar, 290 .putchar = cv_wsputchar, 291 .copycols = cv_wscopycols, 292 .erasecols = cv_wserasecols, 293 .copyrows = cv_wscopyrows, 294 .eraserows = cv_wseraserows, 295 .allocattr = cv_wsallocattr 296 }; 297 298 static struct ws_ao_ioctl cv_wsioctl = { 299 grf_wsaoginfo, 300 grf_wsaogetcmap, 301 grf_wsaoputcmap, 302 grf_wsaogvideo, 303 grf_wsaosvideo, 304 grf_wsaogmode, 305 grf_wsaosmode, 306 grf_wsaogtype 307 }; 308 309 static struct wsscreen_descr cv_screen = { 310 .name = "default", 311 .textops = &cv_textops, 312 .fontwidth = 8, 313 .fontheight = S3FONTY, 314 .capabilities = WSSCREEN_HILIT | WSSCREEN_BLINK | 315 WSSCREEN_REVERSE | WSSCREEN_UNDERLINE 316 }; 317 #endif /* NWSDISPLAY > 0 */ 318 319 /* standard driver stuff */ 320 CFATTACH_DECL_NEW(grfcv, sizeof(struct grf_cv_softc), 321 grfcvmatch, grfcvattach, NULL, NULL); 322 323 static struct cfdata *cfdata; 324 325 #define CV_INT_NUM 6 /* CV interrupt Level: #2 or #6 */ 326 #define CV_ULCURSOR 1 /* Underlined Cursor in textmode */ 327 328 #ifndef CV_NO_HARDWARE_CURSOR 329 330 #define HWC_OFF (cv_fbsize - 1024*2) 331 #define HWC_SIZE 1024 332 333 static unsigned short cv_cursor_storage[HWC_SIZE/2]; 334 static short curs_update_flag = 0; 335 336 #endif /* !CV_NO_HARDWARE_CURSOR */ 337 338 /* 339 * Interrupt handler 340 * This is used for updating the cursor shape (because it _must not_ 341 * be changed while cursor is displayed) 342 * and maybe later to avoid busy waiting 343 * for Vertical Blank and/or gfx engine busy 344 */ 345 346 int 347 cvintr(void *arg) 348 { 349 #ifndef CV_NO_HARDWARE_CURSOR 350 volatile unsigned long *csrc, *cdest; 351 int i; 352 #endif 353 struct grf_softc *gp = arg; 354 volatile void *ba = gp->g_regkva; 355 unsigned char test; 356 unsigned char cridx; /* Save the cr Register index */ 357 358 if (gp == NULL) 359 return 0; 360 361 test = vgar(ba, GREG_INPUT_STATUS0_R); 362 363 if (test & 0x80) { /* VR int pending */ 364 /* Save old CR index */ 365 cridx = vgar (ba, CRT_ADDRESS); 366 367 #if !defined(__m68k__) 368 test = RCrt(ba, CRT_ID_END_VER_RETR); 369 /* Clear int (bit 4) */ 370 test &= ~0x10; 371 WCrt(ba, CRT_ID_END_VER_RETR, test); 372 #else 373 vgaw(ba, CRT_ADDRESS, CRT_ID_END_VER_RETR); 374 __asm volatile("bclr #4,%0@(0x3d5);nop" : : "a" (ba)); 375 #endif 376 377 #ifndef CV_NO_HARDWARE_CURSOR 378 /* update the hardware cursor, if necessary */ 379 if (curs_update_flag) { 380 csrc = (unsigned long *)cv_cursor_storage; 381 cdest = (volatile unsigned long *) 382 ((volatile char*)gp->g_fbkva + HWC_OFF); 383 for (i = 0; i < HWC_SIZE / sizeof(long); i++) 384 *cdest++ = *csrc++; 385 curs_update_flag = 0; 386 } 387 /* Reenable int */ 388 #if !defined(__m68k__) 389 test |= 0x10; 390 WCrt(ba, CRT_ID_END_VER_RETR, test); 391 #else 392 /* I don't trust the optimizer here... */ 393 __asm volatile("bset #4,%0@(0x3d5);nop" : : "a" (ba)); 394 #endif 395 cv_setspritepos (gp, NULL); 396 397 /* Restore the old CR index */ 398 vgaw(ba, CRT_ADDRESS, cridx); 399 amiga_cpu_sync(); 400 #endif /* !CV_NO_HARDWARE_CURSOR */ 401 return (1); 402 } 403 return (0); 404 } 405 406 /* 407 * Get frambuffer memory size. 408 * phase5 didn't provide the bit in CR36, 409 * so we have to do it this way. 410 * Return 0 for 2MB, 1 for 4MB 411 */ 412 static int 413 cv_has_4mb(volatile void *fb) 414 { 415 volatile unsigned long *testfbw, *testfbr; 416 417 /* write patterns in memory and test if they can be read */ 418 testfbw = (volatile unsigned long *)fb; 419 testfbr = (volatile unsigned long *)((volatile char*)fb + 0x02000000); 420 *testfbw = 0x87654321; 421 amiga_cpu_sync(); 422 if (*testfbr != 0x87654321) 423 return (0); 424 425 /* upper memory region */ 426 testfbw = (volatile unsigned long *)((volatile char*)fb + 0x00200000); 427 testfbr = (volatile unsigned long *)((volatile char*)fb + 0x02200000); 428 *testfbw = 0x87654321; 429 amiga_cpu_sync(); 430 if (*testfbr != 0x87654321) 431 return (0); 432 *testfbw = 0xAAAAAAAA; 433 amiga_cpu_sync(); 434 if (*testfbr != 0xAAAAAAAA) 435 return (0); 436 *testfbw = 0x55555555; 437 amiga_cpu_sync(); 438 if (*testfbr != 0x55555555) 439 return (0); 440 return (1); 441 } 442 443 int 444 grfcvmatch(device_t paren, cfdata_t cf, void *aux) 445 { 446 #ifdef CV64CONSOLE 447 static int cvcons_unit = -1; 448 #endif 449 struct zbus_args *zap; 450 451 zap = aux; 452 453 if (amiga_realconfig == 0) 454 #ifdef CV64CONSOLE 455 if (cvcons_unit != -1) 456 #endif 457 return (0); 458 459 /* Lets be Paranoid: Test man and prod id */ 460 if (zap->manid != 8512 || zap->prodid != 34) 461 return (0); 462 463 cv_boardaddr = zap->va; 464 465 #ifdef CV64CONSOLE 466 if (amiga_realconfig == 0) { 467 cvcons_unit = cf->cf_unit; 468 cfdata = cf; 469 } 470 #endif 471 472 return (1); 473 } 474 475 void 476 grfcvattach(device_t parent, device_t self, void *aux) 477 { 478 static struct grf_cv_softc congrf; 479 static char attachflag = 0; 480 struct device temp; 481 struct zbus_args *zap; 482 struct grf_softc *gp; 483 struct grf_cv_softc *gcp; 484 485 zap = aux; 486 487 /* 488 * This function is called twice, once on console init (self == NULL) 489 * and once on "normal" grf5 init. 490 */ 491 492 if (self == NULL) { 493 gcp = &congrf; 494 gp = &gcp->gcs_sc; 495 gp->g_device = &temp; 496 temp.dv_private = gp; 497 } else { 498 gcp = device_private(self); 499 gp = &gcp->gcs_sc; 500 gp->g_device = self; 501 } 502 503 504 if (self != NULL && congrf.gcs_sc.g_regkva != 0) { 505 /* 506 * inited earlier, just copy (not device struct) 507 */ 508 509 printf("\n"); 510 memcpy(&gp->g_display, &congrf.gcs_sc.g_display, 511 (char *) &gcp->gcs_isr - (char *) &gp->g_display); 512 513 /* ... and transfer the isr */ 514 gcp->gcs_isr.isr_ipl = CV_INT_NUM; 515 gcp->gcs_isr.isr_intr = cvintr; 516 gcp->gcs_isr.isr_arg = (void *)gp; 517 518 /* First add new isr */ 519 add_isr(&gcp->gcs_isr); 520 remove_isr(&congrf.gcs_isr); 521 } else { 522 gp->g_regkva = (volatile char *)cv_boardaddr + 0x02000000; 523 gp->g_fbkva = (volatile char *)cv_boardaddr + 0x01400000; 524 525 gp->g_unit = GRF_CV64_UNIT; 526 gp->g_mode = cv_mode; 527 #if NITE > 0 528 gp->g_conpri = grfcv_cnprobe(); 529 #endif 530 gp->g_flags = GF_ALIVE; 531 532 /* add Interrupt Handler */ 533 gcp->gcs_isr.isr_ipl = CV_INT_NUM; 534 gcp->gcs_isr.isr_intr = cvintr; 535 gcp->gcs_isr.isr_arg = (void *)gp; 536 add_isr(&gcp->gcs_isr); 537 538 /* wakeup the board */ 539 cv_boardinit(gp); 540 541 #ifdef CV64CONSOLE 542 #if NWSDISPLAY > 0 543 gp->g_accessops = &cv_accessops; 544 gp->g_emulops = &cv_textops; 545 gp->g_defaultscreen = cv_screen; 546 gp->g_screens[0] = &gp->g_defaultscreen; 547 gp->g_wsioctl = &cv_wsioctl; 548 #else 549 grfcv_iteinit(gp); 550 #endif 551 (void)cv_load_mon(gp, &cvconsole_mode); 552 #endif 553 } 554 555 /* 556 * attach grf 557 */ 558 if (amiga_config_found(cfdata, gp->g_device, gp, grfcvprint)) { 559 if (self != NULL) 560 printf("grfcv: CyberVision64 with %dMB being used\n", 561 cv_fbsize/0x100000); 562 attachflag = 1; 563 } else { 564 if (!attachflag) 565 /*printf("grfcv unattached!!\n")*/; 566 } 567 } 568 569 int 570 grfcvprint(void *aux, const char *pnp) 571 { 572 if (pnp) 573 aprint_normal("ite at %s: ", pnp); 574 return (UNCONF); 575 } 576 577 578 /* 579 * Computes M, N, and R values from 580 * given input frequency. It uses a table of 581 * precomputed values, to keep CPU time low. 582 * 583 * The return value consist of: 584 * lower byte: Bits 4-0: N Divider Value 585 * Bits 5-6: R Value for e.g. SR10 or SR12 586 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13 587 */ 588 589 static unsigned short 590 cv_compute_clock(unsigned long freq) 591 { 592 static unsigned char *mnr, *save; /* M, N + R vals */ 593 unsigned long work_freq, r; 594 unsigned short erg; 595 long diff, d2; 596 597 if (freq < 12500000 || freq > MAXPIXELCLOCK) { 598 printf("grfcv: Illegal clock frequency: %ldMHz\n", freq/1000000); 599 printf("grfcv: Using default frequency: 25MHz\n"); 600 printf("grfcv: See the manpage of grfconfig for more informations.\n"); 601 freq = 25000000; 602 } 603 604 mnr = clocks; /* there the vals are stored */ 605 d2 = 0x7fffffff; 606 607 while (*mnr) { /* mnr vals are 0-terminated */ 608 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2); 609 610 r = (mnr[1] >> 5) & 0x03; 611 if (r != 0) 612 work_freq=work_freq >> r; /* r is the freq divider */ 613 614 work_freq *= 0x3E8; /* 2nd part of OSC */ 615 616 diff = abs(freq - work_freq); 617 618 if (d2 >= diff) { 619 d2 = diff; 620 /* In save are the vals for minimal diff */ 621 save = mnr; 622 } 623 mnr += 2; 624 } 625 erg = *((unsigned short *)save); 626 627 return (erg); 628 } 629 630 631 void 632 cv_boardinit(struct grf_softc *gp) 633 { 634 volatile void *ba; 635 unsigned char test; 636 unsigned int clockpar; 637 int i; 638 struct grfinfo *gi; 639 640 ba = gp->g_regkva; 641 /* Reset board */ 642 for (i = 0; i < 6; i++) 643 /* Clear all bits */ 644 cv_write_port (0xff, (volatile char*)ba - 0x02000000); 645 646 /* Return to operational Mode */ 647 cv_write_port(0x8004, (volatile char*)ba - 0x02000000); 648 649 /* Wakeup Chip */ 650 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x10); 651 vgaw(ba, SREG_OPTION_SELECT, 0x01); 652 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x08); 653 654 vgaw(ba, GREG_MISC_OUTPUT_W, 0x03); 655 656 WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48); /* unlock S3 VGA regs */ 657 WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5); /* unlock syscontrol */ 658 659 /* 660 * The default board interrupt is #6. 661 * Set the roxxler register to use interrupt #2, not #6. 662 */ 663 #if CV_INT_NUM == 2 664 cv_write_port(0x8080, (volatile char*)ba - 0x02000000); 665 #endif 666 667 /* Enable board interrupts */ 668 cv_write_port(0x8008, (volatile char*)ba - 0x02000000); 669 670 test = RCrt(ba, CRT_ID_SYSTEM_CONFIG); 671 test = test | 0x01; /* enable enhanced register access */ 672 test = test & 0xEF; /* clear bit 4, 0 wait state */ 673 WCrt(ba, CRT_ID_SYSTEM_CONFIG, test); 674 675 /* 676 * bit 1=1: enable enhanced mode functions 677 * bit 4=1: enable linear addressing 678 * bit 5=1: enable MMIO 679 */ 680 vgaw(ba, ECR_ADV_FUNC_CNTL, 0x31); 681 682 /* enable color mode (bit0), CPU access (bit1), high 64k page (bit5) */ 683 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); 684 685 /* CPU base addr */ 686 WCrt(ba, CRT_ID_EXT_SYS_CNTL_4, 0x00); 687 688 /* Reset. This does nothing, but everyone does it:) */ 689 WSeq(ba, SEQ_ID_RESET, 0x03); 690 691 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01); /* 8 Dot Clock */ 692 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f); /* Enable write planes */ 693 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); /* Character Font */ 694 695 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x02); /* Complete mem access */ 696 697 WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x06); /* Unlock extensions */ 698 test = RSeq(ba, SEQ_ID_BUS_REQ_CNTL); /* Bus Request */ 699 700 /* enable 4MB fast Page Mode */ 701 test = test | 1 << 6; 702 WSeq(ba, SEQ_ID_BUS_REQ_CNTL, test); 703 /* faster LUT write */ 704 WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0xC0); 705 706 test = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); /* Clksyn2 read */ 707 708 /* immediately Clkload bit clear */ 709 test = test & 0xDF; 710 711 /* 2 MCLK Memory Write.... */ 712 if (cv_memclk >= 55000000) 713 test |= 0x80; 714 715 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test); 716 717 /* Memory CLK */ 718 clockpar = cv_compute_clock(cv_memclk); 719 test = (clockpar & 0xFF00) >> 8; 720 WSeq(ba, SEQ_ID_MCLK_HI, test); /* PLL N-Divider Value */ 721 722 test = clockpar & 0xFF; 723 WSeq(ba, SEQ_ID_MCLK_LO, test); /* PLL M-Divider Value */ 724 725 if (RCrt(ba, CRT_ID_REVISION) == 0x10) /* bugfix for new S3 chips */ 726 WSeq(ba, SEQ_ID_MORE_MAGIC, test); 727 728 /* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */ 729 /* DCLK */ 730 WSeq(ba, SEQ_ID_DCLK_HI, 0x13); 731 WSeq(ba, SEQ_ID_DCLK_LO, 0x41); 732 733 test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2); 734 test = test | 0x22; 735 736 /* DCLK + MCLK Clock immediate load! */ 737 WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test); 738 739 /* DCLK load */ 740 test = vgar(ba, 0x3cc); 741 test = test | 0x0c; 742 vgaw(ba, 0x3c2, test); 743 744 /* Clear bit 5 again, prevent further loading. */ 745 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x02); 746 747 WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F); 748 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F); 749 WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50); 750 WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82); 751 WCrt(ba, CRT_ID_START_HOR_RETR, 0x54); 752 WCrt(ba, CRT_ID_END_HOR_RETR, 0x80); 753 WCrt(ba, CRT_ID_VER_TOTAL, 0xBF); 754 755 WCrt(ba, CRT_ID_OVERFLOW, 0x1F); /* overflow reg */ 756 757 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); /* no panning */ 758 759 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40); /* vscan */ 760 761 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 762 WCrt(ba, CRT_ID_CURSOR_END, 0x00); 763 764 /* Display start address */ 765 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 766 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 767 768 /* Cursor location */ 769 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 770 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 771 772 /* Vertical retrace */ 773 WCrt(ba, CRT_ID_START_VER_RETR, 0x9C); 774 WCrt(ba, CRT_ID_END_VER_RETR, 0x0E); 775 776 WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F); 777 WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50); 778 779 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00); 780 781 WCrt(ba, CRT_ID_START_VER_BLANK, 0x96); 782 WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9); 783 784 WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3); 785 786 WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF); 787 788 WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */ 789 790 /* Refresh count 1, High speed text font, enhanced color mode */ 791 WCrt(ba, CRT_ID_MISC_1, 0x35); 792 793 /* start fifo position */ 794 WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5a); 795 796 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x70); 797 798 /* address window position */ 799 WCrt(ba, CRT_ID_LAW_POS_LO, 0x40); 800 801 /* N Parameter for Display FIFO */ 802 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, 0xFF); 803 804 WGfx(ba, GCT_ID_SET_RESET, 0x00); 805 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00); 806 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00); 807 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00); 808 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 809 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40); 810 WGfx(ba, GCT_ID_MISC, 0x01); 811 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F); 812 WGfx(ba, GCT_ID_BITMASK, 0xFF); 813 814 /* colors for text mode */ 815 for (i = 0; i <= 0xf; i++) 816 WAttr (ba, i, i); 817 818 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x41); 819 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x01); 820 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0F); 821 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00); 822 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00); 823 824 vgaw(ba, VDAC_MASK, 0xFF); /* DAC Mask */ 825 826 *((volatile unsigned long *)((volatile char*)ba + ECR_FRGD_COLOR)) = 0xFF; 827 *((volatile unsigned long *)((volatile char*)ba + ECR_BKGD_COLOR)) = 0; 828 829 /* colors initially set to greyscale */ 830 831 vgaw(ba, VDAC_ADDRESS_W, 0); 832 for (i = 255; i >= 0 ; i--) { 833 vgaw(ba, VDAC_DATA, i); 834 vgaw(ba, VDAC_DATA, i); 835 vgaw(ba, VDAC_DATA, i); 836 } 837 838 /* GFx hardware cursor off */ 839 WCrt(ba, CRT_ID_HWGC_MODE, 0x00); 840 841 /* Set first to 4 MB, so test will work */ 842 WCrt(ba, CRT_ID_LAW_CNTL, 0x13); 843 844 /* find *correct* fbsize of z3 board */ 845 if (cv_has_4mb((volatile char *)cv_boardaddr + 0x01400000)) { 846 cv_fbsize = 1024 * 1024 * 4; 847 WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */ 848 } else { 849 cv_fbsize = 1024 * 1024 * 2; 850 WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */ 851 } 852 853 /* Initialize graphics engine */ 854 GfxBusyWait(ba); 855 vgaw16(ba, ECR_FRGD_MIX, 0x27); 856 vgaw16(ba, ECR_BKGD_MIX, 0x07); 857 858 vgaw16(ba, ECR_READ_REG_DATA, 0x1000); 859 delay(200000); 860 vgaw16(ba, ECR_READ_REG_DATA, 0x2000); 861 GfxBusyWait(ba); 862 vgaw16(ba, ECR_READ_REG_DATA, 0x3fff); 863 GfxBusyWait(ba); 864 delay(200000); 865 vgaw16(ba, ECR_READ_REG_DATA, 0x4fff); 866 GfxBusyWait(ba); 867 868 vgaw16(ba, ECR_BITPLANE_WRITE_MASK, ~0); 869 870 GfxBusyWait (ba); 871 vgaw16(ba, ECR_READ_REG_DATA, 0xe000); 872 vgaw16(ba, ECR_CURRENT_Y_POS2, 0x00); 873 vgaw16(ba, ECR_CURRENT_X_POS2, 0x00); 874 vgaw16(ba, ECR_READ_REG_DATA, 0xa000); 875 vgaw16(ba, ECR_DEST_Y__AX_STEP, 0x00); 876 vgaw16(ba, ECR_DEST_Y2__AX_STEP2, 0x00); 877 vgaw16(ba, ECR_DEST_X__DIA_STEP, 0x00); 878 vgaw16(ba, ECR_DEST_X2__DIA_STEP2, 0x00); 879 vgaw16(ba, ECR_SHORT_STROKE, 0x00); 880 vgaw16(ba, ECR_DRAW_CMD, 0x01); 881 GfxBusyWait (ba); 882 883 /* It ain't easy to write here, so let's do it again */ 884 vgaw16(ba, ECR_READ_REG_DATA, 0x4fff); 885 886 vgaw16(ba, ECR_BKGD_COLOR, 0x01); 887 vgaw16(ba, ECR_FRGD_COLOR, 0x00); 888 889 /* Enable Video Display (Set Bit 5) */ 890 WAttr(ba, 0x33, 0); 891 892 gi = &gp->g_display; 893 gi->gd_regaddr = (void *) kvtop (__UNVOLATILE(ba)); 894 gi->gd_regsize = 64 * 1024; 895 gi->gd_fbaddr = (void *) kvtop (__UNVOLATILE(gp->g_fbkva)); 896 gi->gd_fbsize = cv_fbsize; 897 } 898 899 900 int 901 cv_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm) 902 { 903 struct grfvideo_mode *gv; 904 905 #ifdef CV64CONSOLE 906 /* Handle grabbing console mode */ 907 if (vm->mode_num == 255) { 908 memcpy(vm, &cvconsole_mode, sizeof(struct grfvideo_mode)); 909 /* XXX so grfconfig can tell us the correct text dimensions. */ 910 vm->depth = cvconsole_mode.fy; 911 } else 912 #endif 913 { 914 if (vm->mode_num == 0) 915 vm->mode_num = (monitor_current - monitor_def) + 1; 916 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max) 917 return (EINVAL); 918 gv = monitor_def + (vm->mode_num - 1); 919 if (gv->mode_num == 0) 920 return (EINVAL); 921 922 memcpy(vm, gv, sizeof(struct grfvideo_mode)); 923 } 924 925 /* adjust internal values to pixel values */ 926 927 vm->hblank_start *= 8; 928 vm->hsync_start *= 8; 929 vm->hsync_stop *= 8; 930 vm->htotal *= 8; 931 932 return (0); 933 } 934 935 936 int 937 cv_setvmode(struct grf_softc *gp, unsigned mode) 938 { 939 940 if (!mode || (mode > monitor_def_max) || 941 monitor_def[mode - 1].mode_num == 0) 942 return (EINVAL); 943 944 monitor_current = monitor_def + (mode - 1); 945 946 return (0); 947 } 948 949 950 int 951 cv_blank(struct grf_softc *gp, int *on) 952 { 953 volatile void *ba; 954 955 ba = gp->g_regkva; 956 gfx_on_off(*on > 0 ? 0 : 1, ba); 957 return (0); 958 } 959 960 961 /* 962 * Change the mode of the display. 963 * Return a UNIX error number or 0 for success. 964 */ 965 int 966 cv_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2, 967 int a3) 968 { 969 int error; 970 971 switch (cmd) { 972 case GM_GRFON: 973 error = cv_load_mon (gp, 974 (struct grfcvtext_mode *) monitor_current) ? 0 : EINVAL; 975 return (error); 976 977 case GM_GRFOFF: 978 #ifndef CV64CONSOLE 979 cvscreen(1, (volatile char *)gp->g_regkva - 0x02000000); 980 #else 981 cv_load_mon(gp, &cvconsole_mode); 982 #if NITE > 0 983 ite_reinit(gp->g_itedev); 984 #endif 985 #endif /* CV64CONSOLE */ 986 return (0); 987 988 case GM_GRFCONFIG: 989 return (0); 990 991 case GM_GRFGETVMODE: 992 return (cv_getvmode (gp, (struct grfvideo_mode *) arg)); 993 994 case GM_GRFSETVMODE: 995 error = cv_setvmode (gp, *(unsigned *) arg); 996 if (!error && (gp->g_flags & GF_GRFON)) 997 cv_load_mon(gp, 998 (struct grfcvtext_mode *) monitor_current); 999 return (error); 1000 1001 case GM_GRFGETNUMVM: 1002 *(int *)arg = monitor_def_max; 1003 return (0); 1004 1005 case GM_GRFIOCTL: 1006 return (cv_ioctl (gp, a2, arg)); 1007 1008 default: 1009 break; 1010 } 1011 1012 return (EPASSTHROUGH); 1013 } 1014 1015 1016 int 1017 cv_ioctl(register struct grf_softc *gp, u_long cmd, void *data) 1018 { 1019 switch (cmd) { 1020 #ifndef CV_NO_HARDWARE_CURSOR 1021 case GRFIOCGSPRITEPOS: 1022 return(cv_getspritepos (gp, (struct grf_position *) data)); 1023 1024 case GRFIOCSSPRITEPOS: 1025 return(cv_setspritepos (gp, (struct grf_position *) data)); 1026 1027 case GRFIOCSSPRITEINF: 1028 return(cv_setspriteinfo (gp, (struct grf_spriteinfo *) data)); 1029 1030 case GRFIOCGSPRITEINF: 1031 return(cv_getspriteinfo (gp, (struct grf_spriteinfo *) data)); 1032 1033 case GRFIOCGSPRITEMAX: 1034 return(cv_getspritemax (gp, (struct grf_position *) data)); 1035 #else /* !CV_NO_HARDWARE_CURSOR */ 1036 case GRFIOCGSPRITEPOS: 1037 case GRFIOCSSPRITEPOS: 1038 case GRFIOCSSPRITEINF: 1039 case GRFIOCGSPRITEINF: 1040 case GRFIOCGSPRITEMAX: 1041 break; 1042 #endif /* !CV_NO_HARDWARE_CURSOR */ 1043 1044 case GRFIOCGETCMAP: 1045 return (cv_getcmap (gp, (struct grf_colormap *) data)); 1046 1047 case GRFIOCPUTCMAP: 1048 return (cv_putcmap (gp, (struct grf_colormap *) data)); 1049 1050 case GRFIOCBITBLT: 1051 break; 1052 1053 case GRFTOGGLE: 1054 return (cv_toggle (gp)); 1055 1056 case GRFIOCSETMON: 1057 return (cv_setmonitor (gp, (struct grfvideo_mode *)data)); 1058 1059 case GRFIOCBLANK: 1060 return (cv_blank (gp, (int *)data)); 1061 } 1062 return (EPASSTHROUGH); 1063 } 1064 1065 1066 int 1067 cv_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv) 1068 { 1069 struct grfvideo_mode *md; 1070 1071 if (!cv_mondefok(gv)) 1072 return (EINVAL); 1073 1074 #ifdef CV64CONSOLE 1075 /* handle interactive setting of console mode */ 1076 if (gv->mode_num == 255) { 1077 memcpy(&cvconsole_mode.gv, gv, sizeof(struct grfvideo_mode)); 1078 cvconsole_mode.gv.hblank_start /= 8; 1079 cvconsole_mode.gv.hsync_start /= 8; 1080 cvconsole_mode.gv.hsync_stop /= 8; 1081 cvconsole_mode.gv.htotal /= 8; 1082 cvconsole_mode.rows = gv->disp_height / cvconsole_mode.fy; 1083 cvconsole_mode.cols = gv->disp_width / cvconsole_mode.fx; 1084 if (!(gp->g_flags & GF_GRFON)) 1085 cv_load_mon(gp, &cvconsole_mode); 1086 #if NITE > 0 1087 ite_reinit(gp->g_itedev); 1088 #endif 1089 return (0); 1090 } 1091 #endif 1092 1093 md = monitor_def + (gv->mode_num - 1); 1094 1095 /* 1096 * Prevent user from crashing the system by using 1097 * grfconfig while in X 1098 */ 1099 if (gp->g_flags & GF_GRFON) 1100 if (md == monitor_current) { 1101 printf("grfcv: Changing the used mode not allowed!\n"); 1102 return (EINVAL); 1103 } 1104 1105 memcpy(md, gv, sizeof(struct grfvideo_mode)); 1106 1107 /* adjust pixel oriented values to internal rep. */ 1108 1109 md->hblank_start /= 8; 1110 md->hsync_start /= 8; 1111 md->hsync_stop /= 8; 1112 md->htotal /= 8; 1113 1114 return (0); 1115 } 1116 1117 1118 int 1119 cv_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap) 1120 { 1121 volatile void *ba; 1122 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1123 short x; 1124 int error; 1125 1126 ba = gfp->g_regkva; 1127 if (cmap->count == 0 || cmap->index >= 256) 1128 return (0); 1129 1130 if (cmap->count > 256 - cmap->index) 1131 cmap->count = 256 - cmap->index; 1132 1133 /* first read colors out of the chip, then copyout to userspace */ 1134 vgaw (ba, VDAC_ADDRESS_W, cmap->index); 1135 x = cmap->count - 1; 1136 1137 rp = red + cmap->index; 1138 gp = green + cmap->index; 1139 bp = blue + cmap->index; 1140 1141 do { 1142 *rp++ = vgar (ba, VDAC_DATA) << 2; 1143 *gp++ = vgar (ba, VDAC_DATA) << 2; 1144 *bp++ = vgar (ba, VDAC_DATA) << 2; 1145 } while (x-- > 0); 1146 1147 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count)) 1148 && !(error = copyout (green + cmap->index, cmap->green, cmap->count)) 1149 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count))) 1150 return (0); 1151 1152 return (error); 1153 } 1154 1155 1156 int 1157 cv_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap) 1158 { 1159 volatile void *ba; 1160 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1161 short x; 1162 int error; 1163 1164 ba = gfp->g_regkva; 1165 if (cmap->count == 0 || cmap->index >= 256) 1166 return (0); 1167 1168 if (cmap->count > 256 - cmap->index) 1169 cmap->count = 256 - cmap->index; 1170 1171 /* first copy the colors into kernelspace */ 1172 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count)) 1173 && !(error = copyin (cmap->green, green + cmap->index, cmap->count)) 1174 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) { 1175 vgaw (ba, VDAC_ADDRESS_W, cmap->index); 1176 x = cmap->count - 1; 1177 1178 rp = red + cmap->index; 1179 gp = green + cmap->index; 1180 bp = blue + cmap->index; 1181 1182 do { 1183 vgaw (ba, VDAC_DATA, *rp++ >> 2); 1184 vgaw (ba, VDAC_DATA, *gp++ >> 2); 1185 vgaw (ba, VDAC_DATA, *bp++ >> 2); 1186 } while (x-- > 0); 1187 return (0); 1188 } else 1189 return (error); 1190 } 1191 1192 1193 int 1194 cv_toggle(struct grf_softc *gp) 1195 { 1196 volatile void *ba; 1197 1198 ba = gp->g_regkva; 1199 #ifndef CV64CONSOLE 1200 cv_pass_toggle = 1; 1201 #endif /* !CV64CONSOLE */ 1202 1203 if (cv_pass_toggle) { 1204 cvscreen(0, (volatile char*)ba - 0x02000000); 1205 cv_pass_toggle = 0; 1206 } else { 1207 cvscreen(1, (volatile char*)ba - 0x02000000); 1208 cv_pass_toggle = 1; 1209 } 1210 1211 return (0); 1212 } 1213 1214 1215 int 1216 cv_mondefok(struct grfvideo_mode *gv) 1217 { 1218 unsigned long maxpix; 1219 1220 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) { 1221 if (gv->mode_num != 255 || gv->depth != 4) 1222 return (0); 1223 } 1224 1225 switch(gv->depth) { 1226 case 4: 1227 maxpix = MAXPIXELCLOCK - 55000000; 1228 break; 1229 case 8: 1230 maxpix = MAXPIXELCLOCK; 1231 break; 1232 case 15: 1233 case 16: 1234 #ifdef CV_AGGRESSIVE_TIMING 1235 maxpix = MAXPIXELCLOCK - 35000000; 1236 #else 1237 maxpix = MAXPIXELCLOCK - 55000000; 1238 #endif 1239 break; 1240 case 24: 1241 case 32: 1242 #ifdef CV_AGGRESSIVE_TIMING 1243 maxpix = MAXPIXELCLOCK - 75000000; 1244 #else 1245 maxpix = MAXPIXELCLOCK - 85000000; 1246 #endif 1247 break; 1248 default: 1249 printf("grfcv: Illegal depth in mode %d\n", 1250 (int) gv->mode_num); 1251 return (0); 1252 } 1253 1254 if (gv->pixel_clock > maxpix) { 1255 printf("grfcv: Pixelclock too high in mode %d\n", 1256 (int) gv->mode_num); 1257 return (0); 1258 } 1259 1260 if (gv->mode_num == 255) { /* console mode */ 1261 if ((gv->disp_width / 8) > MAXCOLS) { 1262 printf ("grfcv: Too many columns for console\n"); 1263 return (0); 1264 } else if ((gv->disp_height / S3FONTY) > MAXROWS) { 1265 printf ("grfcv: Too many rows for console\n"); 1266 return (0); 1267 } 1268 } 1269 1270 if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) { 1271 printf("grfcv: sync-on-green is not supported\n"); 1272 return (0); 1273 } 1274 1275 return (1); 1276 } 1277 1278 1279 int 1280 cv_load_mon(struct grf_softc *gp, struct grfcvtext_mode *md) 1281 { 1282 struct grfvideo_mode *gv; 1283 struct grfinfo *gi; 1284 volatile void *ba, *fb; 1285 unsigned short mnr; 1286 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, 1287 VSE, VT; 1288 int cr50, sr15, sr18, clock_mode, test; 1289 int m, n; /* For calc'ing display FIFO */ 1290 int tfillm, temptym; /* FIFO fill and empty mclk's */ 1291 int hmul; /* Multiplier for hor. Values */ 1292 unsigned char hvsync_pulse; 1293 char TEXT, CONSOLE; 1294 1295 /* identity */ 1296 gv = &md->gv; 1297 1298 TEXT = (gv->depth == 4); 1299 CONSOLE = (gv->mode_num == 255); 1300 1301 if (!cv_mondefok(gv)) { 1302 printf("grfcv: Monitor definition not ok\n"); 1303 return (0); 1304 } 1305 1306 ba = gp->g_regkva; 1307 fb = gp->g_fbkva; 1308 1309 /* Disable Interrupts */ 1310 test = RCrt(ba, CRT_ID_BACKWAD_COMP_1); 1311 test &= ~0x10; 1312 WCrt(ba, CRT_ID_BACKWAD_COMP_1, test); 1313 1314 /* turn gfx off, don't mess up the display */ 1315 gfx_on_off(1, ba); 1316 1317 /* provide all needed information in grf device-independent locations */ 1318 gp->g_data = (void *) gv; 1319 gi = &gp->g_display; 1320 gi->gd_colors = 1 << gv->depth; 1321 gi->gd_planes = gv->depth; 1322 gi->gd_fbwidth = gv->disp_width; 1323 gi->gd_fbheight = gv->disp_height; 1324 gi->gd_fbx = 0; 1325 gi->gd_fby = 0; 1326 if (CONSOLE) { 1327 gi->gd_dwidth = md->fx * md->cols; 1328 gi->gd_dheight = md->fy * md->rows; 1329 } else { 1330 gi->gd_dwidth = gv->disp_width; 1331 gi->gd_dheight = gv->disp_height; 1332 } 1333 gi->gd_dx = 0; 1334 gi->gd_dy = 0; 1335 1336 /* get display mode parameters */ 1337 switch (gv->depth) { 1338 case 15: 1339 case 16: 1340 hmul = 2; 1341 break; 1342 default: 1343 hmul = 1; 1344 break; 1345 } 1346 1347 HBS = gv->hblank_start * hmul; 1348 HSS = gv->hsync_start * hmul; 1349 HSE = gv->hsync_stop * hmul; 1350 HBE = gv->htotal * hmul - 6; 1351 HT = gv->htotal * hmul - 5; 1352 VBS = gv->vblank_start - 1; 1353 VSS = gv->vsync_start; 1354 VSE = gv->vsync_stop; 1355 VBE = gv->vtotal - 3; 1356 VT = gv->vtotal - 2; 1357 1358 /* Disable enhanced Mode for text display */ 1359 1360 vgaw(ba, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31)); 1361 1362 if (TEXT) 1363 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1; 1364 else 1365 HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/ 1366 VDE = gv->disp_height - 1; 1367 1368 /* adjustments */ 1369 1370 if (gv->disp_flags & GRF_FLAGS_LACE) { 1371 VDE = VDE / 2; 1372 VBS = VBS / 2; 1373 VSS = VSS / 2; 1374 VSE = VSE / 2; 1375 VBE = VBE / 2; 1376 VT = VT / 2; 1377 } 1378 1379 /* Horizontal/Vertical Sync Pulse */ 1380 /* 1381 * GREG_MISC_OUTPUT_W Register: 1382 * bit description (0/1) 1383 * 0 Monochrome/Color emulation 1384 * 1 Disable/Enable access of the display memory from the CPU 1385 * 5 Select the low/high 64K page of memory 1386 * 6 Select a positive/negative horizontal retrace sync pulse 1387 * 7 Select a positive/negative vertical retrace sync pulse 1388 */ 1389 hvsync_pulse = vgar(ba, GREG_MISC_OUTPUT_R); 1390 if (gv->disp_flags & GRF_FLAGS_PHSYNC) 1391 hvsync_pulse &= ~0x40; 1392 else 1393 hvsync_pulse |= 0x40; 1394 if (gv->disp_flags & GRF_FLAGS_PVSYNC) 1395 hvsync_pulse &= ~0x80; 1396 else 1397 hvsync_pulse |= 0x80; 1398 vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse); 1399 1400 /* GFX hardware cursor off */ 1401 WCrt(ba, CRT_ID_HWGC_MODE, 0x00); 1402 WCrt(ba, CRT_ID_EXT_DAC_CNTL, 0x00); 1403 1404 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e); 1405 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 1406 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff); 1407 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 1408 1409 /* Set clock */ 1410 1411 mnr = cv_compute_clock(gv->pixel_clock); 1412 WSeq(ba, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8)); 1413 WSeq(ba, SEQ_ID_DCLK_LO, (mnr & 0xFF)); 1414 1415 /* load display parameters into board */ 1416 1417 WCrt(ba, CRT_ID_EXT_HOR_OVF, 1418 ((HT & 0x100) ? 0x01 : 0x00) | 1419 ((HDE & 0x100) ? 0x02 : 0x00) | 1420 ((HBS & 0x100) ? 0x04 : 0x00) | 1421 /* ((HBE & 0x40) ? 0x08 : 0x00) | */ /* Later... */ 1422 ((HSS & 0x100) ? 0x10 : 0x00) | 1423 /* ((HSE & 0x20) ? 0x20 : 0x00) | */ 1424 (((HT-5) & 0x100) ? 0x40 : 0x00) ); 1425 1426 WCrt(ba, CRT_ID_EXT_VER_OVF, 1427 0x40 | /* Line compare */ 1428 ((VT & 0x400) ? 0x01 : 0x00) | 1429 ((VDE & 0x400) ? 0x02 : 0x00) | 1430 ((VBS & 0x400) ? 0x04 : 0x00) | 1431 ((VSS & 0x400) ? 0x10 : 0x00) ); 1432 1433 WCrt(ba, CRT_ID_HOR_TOTAL, HT); 1434 WCrt(ba, CRT_ID_DISPLAY_FIFO, HT - 5); 1435 1436 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE)); 1437 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS); 1438 WCrt(ba, CRT_ID_END_HOR_BLANK, ((HBE & 0x1f) | 0x80)); 1439 WCrt(ba, CRT_ID_START_HOR_RETR, HSS); 1440 WCrt(ba, CRT_ID_END_HOR_RETR, 1441 (HSE & 0x1f) | 1442 ((HBE & 0x20) ? 0x80 : 0x00) ); 1443 WCrt(ba, CRT_ID_VER_TOTAL, VT); 1444 WCrt(ba, CRT_ID_OVERFLOW, 1445 0x10 | 1446 ((VT & 0x100) ? 0x01 : 0x00) | 1447 ((VDE & 0x100) ? 0x02 : 0x00) | 1448 ((VSS & 0x100) ? 0x04 : 0x00) | 1449 ((VBS & 0x100) ? 0x08 : 0x00) | 1450 ((VT & 0x200) ? 0x20 : 0x00) | 1451 ((VDE & 0x200) ? 0x40 : 0x00) | 1452 ((VSS & 0x200) ? 0x80 : 0x00) ); 1453 1454 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 1455 0x40 | /* TEXT ? 0x00 ??? */ 1456 ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) | 1457 ((VBS & 0x200) ? 0x20 : 0x00) | 1458 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); 1459 1460 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3); 1461 1462 /* text cursor */ 1463 1464 if (TEXT) { 1465 #if CV_ULCURSOR 1466 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2); 1467 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1); 1468 #else 1469 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 1470 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f); 1471 #endif 1472 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f); 1473 1474 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 1475 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 1476 } 1477 1478 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 1479 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 1480 1481 WCrt(ba, CRT_ID_START_VER_RETR, VSS); 1482 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f)); 1483 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE); 1484 WCrt(ba, CRT_ID_START_VER_BLANK, VBS); 1485 WCrt(ba, CRT_ID_END_VER_BLANK, VBE); 1486 1487 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); 1488 WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2); 1489 WCrt(ba, CRT_ID_LACE_CONTROL, 1490 ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x20 : 0x00)); 1491 1492 WGfx(ba, GCT_ID_GRAPHICS_MODE, 1493 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40)); 1494 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01)); 1495 1496 WSeq (ba, SEQ_ID_MEMORY_MODE, 1497 ((TEXT || (gv->depth == 1)) ? 0x06 : 0x02)); 1498 1499 vgaw(ba, VDAC_MASK, 0xff); 1500 1501 /* Blank border */ 1502 test = RCrt(ba, CRT_ID_BACKWAD_COMP_2); 1503 WCrt(ba, CRT_ID_BACKWAD_COMP_2, (test | 0x20)); 1504 1505 sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); 1506 sr15 &= ~0x10; 1507 sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL); 1508 sr18 &= ~0x80; 1509 clock_mode = 0x00; 1510 cr50 = 0x00; 1511 1512 test = RCrt(ba, CRT_ID_EXT_MISC_CNTL_2); 1513 test &= 0xd; 1514 1515 /* clear roxxler byte-swapping... */ 1516 cv_write_port(0x0040, cv_boardaddr); 1517 cv_write_port(0x0020, cv_boardaddr); 1518 1519 switch (gv->depth) { 1520 case 1: 1521 case 4: /* text */ 1522 HDE = gv->disp_width / 16; 1523 break; 1524 case 8: 1525 if (gv->pixel_clock > 80000000) { 1526 clock_mode = 0x10 | 0x02; 1527 sr15 |= 0x10; 1528 sr18 |= 0x80; 1529 } 1530 HDE = gv->disp_width / 8; 1531 cr50 |= 0x00; 1532 break; 1533 case 15: 1534 cv_write_port (0x8020, cv_boardaddr); 1535 clock_mode = 0x30; 1536 HDE = gv->disp_width / 4; 1537 cr50 |= 0x10; 1538 break; 1539 case 16: 1540 cv_write_port (0x8020, cv_boardaddr); 1541 clock_mode = 0x50; 1542 HDE = gv->disp_width / 4; 1543 cr50 |= 0x10; 1544 break; 1545 case 24: /* this is really 32 Bit on CV64 */ 1546 case 32: 1547 cv_write_port(0x8040, cv_boardaddr); 1548 clock_mode = 0xd0; 1549 HDE = (gv->disp_width / 2); 1550 cr50 |= 0x30; 1551 break; 1552 } 1553 1554 WCrt(ba, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test); 1555 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, sr15); 1556 WSeq(ba, SEQ_ID_RAMDAC_CNTL, sr18); 1557 WCrt(ba, CRT_ID_SCREEN_OFFSET, HDE); 1558 1559 WCrt(ba, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35)); 1560 1561 test = RCrt(ba, CRT_ID_EXT_SYS_CNTL_2); 1562 test &= ~0x30; 1563 /* HDE Overflow in bits 4-5 */ 1564 test |= (HDE >> 4) & 0x30; 1565 WCrt(ba, CRT_ID_EXT_SYS_CNTL_2, test); 1566 1567 /* Set up graphics engine */ 1568 switch (gv->disp_width) { 1569 case 1024: 1570 cr50 |= 0x00; 1571 break; 1572 case 640: 1573 cr50 |= 0x40; 1574 break; 1575 case 800: 1576 cr50 |= 0x80; 1577 break; 1578 case 1280: 1579 cr50 |= 0xc0; 1580 break; 1581 case 1152: 1582 cr50 |= 0x01; 1583 break; 1584 case 1600: 1585 cr50 |= 0x81; 1586 break; 1587 default: /* XXX The Xserver has to handle this */ 1588 break; 1589 } 1590 1591 WCrt(ba, CRT_ID_EXT_SYS_CNTL_1, cr50); 1592 1593 delay(100000); 1594 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41)); 1595 delay(100000); 1596 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 1597 (gv->depth == 1) ? 0x01 : 0x0f); 1598 delay(100000); 1599 1600 /* 1601 * M-Parameter of Display FIFO 1602 * This is dependent on the pixel clock and the memory clock. 1603 * The FIFO filling bandwidth is 240 MHz and the FIFO is 96 Byte wide. 1604 * Then the time to fill the FIFO is tfill = (96/240000000) sec, the time 1605 * to empty the FIFO is tempty = (96/pixelclock) sec. 1606 * Then the M parameter maximum is ((tempty-tfill)*cv_memclk-9)/2. 1607 * This seems to be logical, ain't it? 1608 * Remember: We have to use integer arithmetics :( 1609 * Divide by 1000 to prevent overflows. 1610 */ 1611 1612 tfillm = (96 * (cv_memclk/1000))/240000; 1613 1614 switch(gv->depth) { 1615 case 32: 1616 case 24: 1617 temptym = (24 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1618 break; 1619 case 15: 1620 case 16: 1621 temptym = (48 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1622 break; 1623 case 4: 1624 temptym = (192 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1625 break; 1626 default: 1627 temptym = (96 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1628 break; 1629 } 1630 1631 m = (temptym - tfillm - 9) / 2; 1632 if (m < 0) 1633 m = 0; /* prevent underflow */ 1634 m = (m & 0x1f) << 3; 1635 if (m < 0x18) 1636 m = 0x18; 1637 n = 0xff; 1638 1639 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, m); 1640 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, n); 1641 delay(10000); 1642 1643 /* text initialization */ 1644 1645 if (TEXT) { 1646 cv_inittextmode(gp); 1647 } 1648 1649 if (CONSOLE) { 1650 int i; 1651 vgaw(ba, VDAC_ADDRESS_W, 0); 1652 for (i = 0; i < 16; i++) { 1653 vgaw(ba, VDAC_DATA, cvconscolors[i][0]); 1654 vgaw(ba, VDAC_DATA, cvconscolors[i][1]); 1655 vgaw(ba, VDAC_DATA, cvconscolors[i][2]); 1656 } 1657 } 1658 1659 /* Set display enable flag */ 1660 WAttr(ba, 0x33, 0); 1661 1662 /* turn gfx on again */ 1663 gfx_on_off(0, ba); 1664 1665 /* enable interrupts */ 1666 test = RCrt(ba, CRT_ID_BACKWAD_COMP_1); 1667 test |= 0x10; 1668 WCrt(ba, CRT_ID_BACKWAD_COMP_1, test); 1669 1670 test = RCrt(ba, CRT_ID_END_VER_RETR); 1671 test &= ~0x20; 1672 WCrt(ba, CRT_ID_END_VER_RETR, test); 1673 test &= ~0x10; 1674 WCrt(ba, CRT_ID_END_VER_RETR, test); 1675 test |= 0x10; 1676 WCrt(ba, CRT_ID_END_VER_RETR, test); 1677 #ifndef CV_NO_HARDWARE_CURSOR 1678 cv_setup_hwc(gp); 1679 #endif 1680 1681 /* Pass-through */ 1682 cvscreen(0, (volatile char*)ba - 0x02000000); 1683 1684 return (1); 1685 } 1686 1687 1688 void 1689 cv_inittextmode(struct grf_softc *gp) 1690 { 1691 struct grfcvtext_mode *tm = (struct grfcvtext_mode *)gp->g_data; 1692 volatile void *ba, *fb; 1693 volatile unsigned char *c; 1694 unsigned char *f, y; 1695 unsigned short z; 1696 1697 ba = gp->g_regkva; 1698 fb = gp->g_fbkva; 1699 1700 /* load text font into beginning of display memory. 1701 * Each character cell is 32 bytes long (enough for 4 planes) 1702 * In linear addressing text mode, the memory is organized 1703 * so, that the Bytes of all 4 planes are interleaved. 1704 * 1st byte plane 0, 1st byte plane 1, 1st byte plane 2, 1705 * 1st byte plane 3, 2nd byte plane 0, 2nd byte plane 1,... 1706 * The font is loaded in plane 2. 1707 */ 1708 1709 c = (volatile unsigned char *) fb; 1710 1711 /* clear screen */ 1712 for (z = 0; z < tm->cols * tm->rows * 3; z++) { 1713 *c++ = 0x20; 1714 *c++ = 0x07; 1715 *c++ = 0; 1716 *c++ = 0; 1717 } 1718 1719 c = (volatile unsigned char *)fb + (32 * tm->fdstart * 4 + 2); 1720 f = tm->fdata; 1721 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy) * 4) 1722 for (y = 0; y < tm->fy; y++) { 1723 *c = *f++; 1724 c += 4; 1725 } 1726 1727 /* print out a little init msg */ 1728 c = (volatile unsigned char *)fb + (tm->cols - 6) * 4; 1729 *c++ = 'C'; 1730 *c++ = 0x0a; 1731 c +=2; 1732 *c++ = 'V'; 1733 *c++ = 0x0b; 1734 c +=2; 1735 *c++ = '6'; 1736 *c++ = 0x0c; 1737 c +=2; 1738 *c++ = '4'; 1739 *c++ = 0x0d; 1740 } 1741 1742 1743 static inline void 1744 cv_write_port(unsigned short bits, volatile void *BoardAddr) 1745 { 1746 volatile char *addr; 1747 static unsigned char CVPortBits = 0; /* mirror port bits here */ 1748 1749 addr = (volatile char*)BoardAddr + 0x40001; 1750 if (bits & 0x8000) 1751 CVPortBits |= bits & 0xFF; /* Set bits */ 1752 else { 1753 bits = bits & 0xFF; 1754 bits = (~bits) & 0xFF ; 1755 CVPortBits &= bits; /* Clear bits */ 1756 } 1757 1758 *addr = CVPortBits; 1759 } 1760 1761 1762 /* 1763 * Monitor Switch 1764 * 0 = CyberVision Signal 1765 * 1 = Amiga Signal, 1766 * ba = boardaddr 1767 */ 1768 static inline void 1769 cvscreen(int toggle, volatile void *ba) 1770 { 1771 1772 if (toggle == 1) 1773 cv_write_port (0x10, ba); 1774 else 1775 cv_write_port (0x8010, ba); 1776 } 1777 1778 1779 /* 0 = on, 1= off */ 1780 /* ba= registerbase */ 1781 static inline void 1782 gfx_on_off(int toggle, volatile void *ba) 1783 { 1784 int r; 1785 1786 toggle &= 0x1; 1787 toggle = toggle << 5; 1788 1789 r = RSeq(ba, SEQ_ID_CLOCKING_MODE); 1790 r &= ~0x20; /* set Bit 5 to 0 */ 1791 1792 WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle); 1793 } 1794 1795 1796 #ifndef CV_NO_HARDWARE_CURSOR 1797 1798 static unsigned char cv_hotx = 0, cv_hoty = 0; 1799 static char cv_cursor_on = 0; 1800 1801 /* Hardware Cursor handling routines */ 1802 1803 int 1804 cv_getspritepos(struct grf_softc *gp, struct grf_position *pos) 1805 { 1806 int hi,lo; 1807 volatile void *ba = gp->g_regkva; 1808 1809 hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI); 1810 lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO); 1811 1812 pos->y = (hi << 8) + lo; 1813 hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI); 1814 lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO); 1815 pos->x = (hi << 8) + lo; 1816 return (0); 1817 } 1818 1819 1820 int 1821 cv_setspritepos(struct grf_softc *gp, struct grf_position *pos) 1822 { 1823 volatile void *ba = gp->g_regkva; 1824 short x, y; 1825 static short savex, savey; 1826 short xoff, yoff; 1827 1828 if (pos) { 1829 x = pos->x; 1830 y = pos->y; 1831 savex = x; 1832 savey= y; 1833 } else { /* restore cursor */ 1834 x = savex; 1835 y = savey; 1836 } 1837 x -= cv_hotx; 1838 y -= cv_hoty; 1839 if (x < 0) { 1840 xoff = ((-x) & 0xFE); 1841 x = 0; 1842 } else { 1843 xoff = 0; 1844 } 1845 1846 if (y < 0) { 1847 yoff = ((-y) & 0xFE); 1848 y = 0; 1849 } else { 1850 yoff = 0; 1851 } 1852 1853 WCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8)); 1854 WCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff)); 1855 1856 WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff)); 1857 WCrt(ba, CRT_ID_HWGC_DSTART_X, xoff); 1858 WCrt(ba, CRT_ID_HWGC_DSTART_Y, yoff); 1859 WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8)); 1860 1861 return(0); 1862 } 1863 1864 static inline short 1865 M2I(short val) 1866 { 1867 return ( ((val & 0xff00) >> 8) | ((val & 0xff) << 8)); 1868 } 1869 1870 int 1871 cv_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info) 1872 { 1873 volatile void *ba, *fb; 1874 1875 ba = gp->g_regkva; 1876 fb = gp->g_fbkva; 1877 1878 if (info->set & GRFSPRSET_ENABLE) 1879 info->enable = RCrt(ba, CRT_ID_HWGC_MODE) & 0x01; 1880 1881 if (info->set & GRFSPRSET_POS) 1882 cv_getspritepos (gp, &info->pos); 1883 1884 #if 0 /* XXX */ 1885 if (info->set & GRFSPRSET_SHAPE) { 1886 u_char image[512], mask[512]; 1887 volatile u_long *hwp; 1888 u_char *imp, *mp; 1889 short row; 1890 info->size.x = 64; 1891 info->size.y = 64; 1892 for (row = 0, hwp = (u_long *)(fb + HWC_OFF), 1893 mp = mask, imp = image; 1894 row < 64; 1895 row++) { 1896 u_long bp10, bp20, bp11, bp21; 1897 bp10 = *hwp++; 1898 bp20 = *hwp++; 1899 bp11 = *hwp++; 1900 bp21 = *hwp++; 1901 M2I (bp10); 1902 M2I (bp20); 1903 M2I (bp11); 1904 M2I (bp21); 1905 *imp++ = (~bp10) & bp11; 1906 *imp++ = (~bp20) & bp21; 1907 *mp++ = (~bp10) | (bp10 & ~bp11); 1908 *mp++ = (~bp20) & (bp20 & ~bp21); 1909 } 1910 copyout (image, info->image, sizeof (image)); 1911 copyout (mask, info->mask, sizeof (mask)); 1912 } 1913 #endif 1914 return(0); 1915 } 1916 1917 1918 void 1919 cv_setup_hwc(struct grf_softc *gp) 1920 { 1921 volatile void *ba = gp->g_regkva; 1922 volatile char *hwc; 1923 int test; 1924 1925 if (gp->g_display.gd_planes <= 4) 1926 cv_cursor_on = 0; /* don't enable hwc in text modes */ 1927 if (cv_cursor_on == 0) 1928 return; 1929 1930 /* reset colour stack */ 1931 #if !defined(__m68k__) 1932 test = RCrt(ba, CRT_ID_HWGC_MODE); 1933 amiga_cpu_sync(); 1934 #else 1935 /* do it in assembler, the above does't seem to work */ 1936 __asm volatile ("moveb #0x45, %1@(0x3d4); \ 1937 moveb %1@(0x3d5),%0" : "=d" (test) : "a" (ba)); 1938 #endif 1939 1940 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 1941 1942 hwc = (volatile char*)ba + CRT_ADDRESS_W; 1943 *hwc = 0; 1944 *hwc = 0; 1945 1946 #if !defined(__m68k__) 1947 test = RCrt(ba, CRT_ID_HWGC_MODE); 1948 amiga_cpu_sync(); 1949 #else 1950 /* do it in assembler, the above does't seem to work */ 1951 __asm volatile ("moveb #0x45, %1@(0x3d4); \ 1952 moveb %1@(0x3d5),%0" : "=d" (test) : "a" (ba)); 1953 #endif 1954 switch (gp->g_display.gd_planes) { 1955 case 8: 1956 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1); 1957 *hwc = 1; 1958 break; 1959 default: 1960 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); 1961 *hwc = 0xff; 1962 *hwc = 0xff; 1963 } 1964 1965 test = HWC_OFF / HWC_SIZE; 1966 WCrt (ba, CRT_ID_HWGC_START_AD_HI, (test >> 8)); 1967 WCrt (ba, CRT_ID_HWGC_START_AD_LO, (test & 0xff)); 1968 1969 WCrt (ba, CRT_ID_HWGC_DSTART_X , 0); 1970 WCrt (ba, CRT_ID_HWGC_DSTART_Y , 0); 1971 1972 WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10); /* Cursor X11 Mode */ 1973 /* 1974 * Put it into Windoze Mode or you'll see sometimes a white stripe 1975 * on the right side (in double clocking modes with a screen bigger 1976 * > 1023 pixels). 1977 */ 1978 WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x00); /* Cursor Windoze Mode */ 1979 1980 WCrt (ba, CRT_ID_HWGC_MODE, 0x01); 1981 } 1982 1983 1984 /* 1985 * This was the reason why you shouldn't use the HWC in the Kernel:( 1986 * Obsoleted now by use of interrupts :-) 1987 */ 1988 1989 #define VerticalRetraceWait(ba) \ 1990 { \ 1991 while (vgar(ba, GREG_INPUT_STATUS1_R) == 0x00) ; \ 1992 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x08) ; \ 1993 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x00) ; \ 1994 } 1995 1996 1997 int 1998 cv_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info) 1999 { 2000 volatile void *ba, *fb; 2001 int depth = gp->g_display.gd_planes; 2002 2003 ba = gp->g_regkva; 2004 fb = gp->g_fbkva; 2005 2006 if (info->set & GRFSPRSET_SHAPE) { 2007 /* 2008 * For an explanation of these weird actions here, see above 2009 * when reading the shape. We set the shape directly into 2010 * the video memory, there's no reason to keep 1k on the 2011 * kernel stack just as template 2012 */ 2013 u_char *image, *mask; 2014 volatile u_short *hwp; 2015 u_char *imp, *mp; 2016 unsigned short row; 2017 2018 #ifdef CV_NO_INT 2019 /* Cursor off */ 2020 WCrt (ba, CRT_ID_HWGC_MODE, 0x00); 2021 2022 /* 2023 * The Trio64 crashes if the cursor data is written 2024 * while the cursor is displayed. 2025 * Sadly, turning the cursor off is not enough. 2026 * What we have to do is: 2027 * 1. Wait for vertical retrace, to make sure no-one 2028 * has moved the cursor in this sync period (because 2029 * another write then would have no effect, argh!). 2030 * 2. Move the cursor off-screen 2031 * 3. Another wait for v. retrace to make sure the cursor 2032 * is really off. 2033 * 4. Write the data, finally. 2034 * (thanks to Harald Koenig for this tip!) 2035 */ 2036 2037 /* 2038 * Remark 06/06/96: Update in interrupt obsoletes this, 2039 * but the warning should stay there! 2040 */ 2041 2042 VerticalRetraceWait(ba); 2043 2044 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, 0x7); 2045 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO, 0xff); 2046 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, 0xff); 2047 WCrt (ba, CRT_ID_HWGC_DSTART_X, 0x3f); 2048 WCrt (ba, CRT_ID_HWGC_DSTART_Y, 0x3f); 2049 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, 0x7); 2050 #endif /* CV_NO_INT */ 2051 2052 if (info->size.y > 64) 2053 info->size.y = 64; 2054 if (info->size.x > 64) 2055 info->size.x = 64; 2056 if (info->size.x < 32) 2057 info->size.x = 32; 2058 2059 image = malloc(HWC_SIZE, M_TEMP, M_WAITOK); 2060 mask = image + HWC_SIZE/2; 2061 2062 copyin(info->image, image, info->size.y * info->size.x / 8); 2063 copyin(info->mask, mask, info->size.y * info->size.x / 8); 2064 2065 #ifdef CV_NO_INT 2066 hwp = (u_short *)(fb +HWC_OFF); 2067 2068 /* This is necessary in order not to crash the board */ 2069 VerticalRetraceWait(ba); 2070 #else /* CV_NO_INT */ 2071 hwp = (u_short *) cv_cursor_storage; 2072 #endif /* CV_NO_INT */ 2073 2074 /* 2075 * setting it is slightly more difficult, because we can't 2076 * force the application to not pass a *smaller* than 2077 * supported bitmap 2078 */ 2079 2080 for (row = 0, mp = mask, imp = image; 2081 row < info->size.y; row++) { 2082 u_short im1, im2, im3, im4, m1, m2, m3, m4; 2083 2084 m1 = ~(*(unsigned short *)mp); 2085 im1 = *(unsigned short *)imp & *(unsigned short *)mp; 2086 mp += 2; 2087 imp += 2; 2088 2089 m2 = ~(*(unsigned short *)mp); 2090 im2 = *(unsigned short *)imp & *(unsigned short *)mp; 2091 mp += 2; 2092 imp += 2; 2093 2094 if (info->size.x > 32) { 2095 m3 = ~(*(unsigned short *)mp); 2096 im3 = *(unsigned short *)imp & *(unsigned short *)mp; 2097 mp += 2; 2098 imp += 2; 2099 m4 = ~(*(unsigned short *)mp); 2100 im4 = *(unsigned short *)imp & *(unsigned short *)mp; 2101 mp += 2; 2102 imp += 2; 2103 } else { 2104 m3 = 0xffff; 2105 im3 = 0; 2106 m4 = 0xffff; 2107 im4 = 0; 2108 } 2109 2110 switch (depth) { 2111 case 8: 2112 *hwp++ = m1; 2113 *hwp++ = im1; 2114 *hwp++ = m2; 2115 *hwp++ = im2; 2116 *hwp++ = m3; 2117 *hwp++ = im3; 2118 *hwp++ = m4; 2119 *hwp++ = im4; 2120 break; 2121 case 15: 2122 case 16: 2123 *hwp++ = M2I(m1); 2124 *hwp++ = M2I(im1); 2125 *hwp++ = M2I(m2); 2126 *hwp++ = M2I(im2); 2127 *hwp++ = M2I(m3); 2128 *hwp++ = M2I(im3); 2129 *hwp++ = M2I(m4); 2130 *hwp++ = M2I(im4); 2131 break; 2132 case 24: 2133 case 32: 2134 *hwp++ = M2I(im1); 2135 *hwp++ = M2I(m1); 2136 *hwp++ = M2I(im2); 2137 *hwp++ = M2I(m2); 2138 *hwp++ = M2I(im3); 2139 *hwp++ = M2I(m3); 2140 *hwp++ = M2I(im4); 2141 *hwp++ = M2I(m4); 2142 break; 2143 } 2144 } 2145 2146 if (depth < 24) { 2147 for (; row < 64; row++) { 2148 *hwp++ = 0xffff; 2149 *hwp++ = 0x0000; 2150 *hwp++ = 0xffff; 2151 *hwp++ = 0x0000; 2152 *hwp++ = 0xffff; 2153 *hwp++ = 0x0000; 2154 *hwp++ = 0xffff; 2155 *hwp++ = 0x0000; 2156 } 2157 } else { 2158 for (; row < 64; row++) { 2159 *hwp++ = 0x0000; 2160 *hwp++ = 0xffff; 2161 *hwp++ = 0x0000; 2162 *hwp++ = 0xffff; 2163 *hwp++ = 0x0000; 2164 *hwp++ = 0xffff; 2165 *hwp++ = 0x0000; 2166 *hwp++ = 0xffff; 2167 } 2168 } 2169 2170 free(image, M_TEMP); 2171 /* cv_setup_hwc(gp); */ 2172 cv_hotx = info->hot.x; 2173 cv_hoty = info->hot.y; 2174 2175 #ifdef CV_NO_INT 2176 /* One must not write twice per vertical blank :-( */ 2177 VerticalRetraceWait(ba); 2178 cv_setspritepos (gp, &info->pos); 2179 #else /* CV_NO_INT */ 2180 cv_setspritepos (gp, &info->pos); 2181 curs_update_flag = 1; 2182 #endif /* CV_NO_INT */ 2183 } 2184 if (info->set & GRFSPRSET_CMAP) { 2185 volatile char *hwc; 2186 int test; 2187 2188 /* reset colour stack */ 2189 test = RCrt(ba, CRT_ID_HWGC_MODE); 2190 amiga_cpu_sync(); 2191 switch (depth) { 2192 case 8: 2193 case 15: 2194 case 16: 2195 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 2196 hwc = (volatile char*)ba + CRT_ADDRESS_W; 2197 *hwc = 0; 2198 break; 2199 case 32: 2200 case 24: 2201 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 2202 hwc = (volatile char*)ba + CRT_ADDRESS_W; 2203 *hwc = 0; 2204 *hwc = 0; 2205 break; 2206 } 2207 2208 test = RCrt(ba, CRT_ID_HWGC_MODE); 2209 amiga_cpu_sync(); 2210 switch (depth) { 2211 case 8: 2212 WCrt (ba, CRT_ID_HWGC_BG_STACK, 1); 2213 hwc = (volatile char*)ba + CRT_ADDRESS_W; 2214 *hwc = 1; 2215 break; 2216 case 15: 2217 case 16: 2218 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); 2219 hwc = (volatile char*)ba + CRT_ADDRESS_W; 2220 *hwc = 0xff; 2221 break; 2222 case 32: 2223 case 24: 2224 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); 2225 hwc = (volatile char*)ba + CRT_ADDRESS_W; 2226 *hwc = 0xff; 2227 *hwc = 0xff; 2228 break; 2229 } 2230 } 2231 2232 if (info->set & GRFSPRSET_ENABLE) { 2233 if (info->enable) { 2234 cv_cursor_on = 1; 2235 cv_setup_hwc(gp); 2236 /* WCrt(ba, CRT_ID_HWGC_MODE, 0x01); */ 2237 } else 2238 WCrt(ba, CRT_ID_HWGC_MODE, 0x00); 2239 } 2240 if (info->set & GRFSPRSET_POS) 2241 cv_setspritepos(gp, &info->pos); 2242 if (info->set & GRFSPRSET_HOT) { 2243 2244 cv_hotx = info->hot.x; 2245 cv_hoty = info->hot.y; 2246 cv_setspritepos (gp, &info->pos); 2247 } 2248 return(0); 2249 } 2250 2251 2252 int 2253 cv_getspritemax (struct grf_softc *gp, struct grf_position *pos) 2254 { 2255 2256 pos->x = 64; 2257 pos->y = 64; 2258 return(0); 2259 } 2260 2261 #endif /* !CV_NO_HARDWARE_CURSOR */ 2262 2263 #if NWSDISPLAY > 0 2264 2265 static void 2266 cv_wscursor(void *c, int on, int row, int col) 2267 { 2268 struct rasops_info *ri; 2269 struct vcons_screen *scr; 2270 struct grf_softc *gp; 2271 volatile void *ba; 2272 int offs; 2273 2274 ri = c; 2275 scr = ri->ri_hw; 2276 gp = scr->scr_cookie; 2277 ba = gp->g_regkva; 2278 2279 if ((ri->ri_flg & RI_CURSOR) && !on) { 2280 /* cursor was visible, but we want to remove it */ 2281 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/ 2282 ri->ri_flg &= ~RI_CURSOR; 2283 } 2284 2285 ri->ri_crow = row; 2286 ri->ri_ccol = col; 2287 2288 if (on) { 2289 /* move cursor to new location */ 2290 if (!(ri->ri_flg & RI_CURSOR)) { 2291 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/ 2292 ri->ri_flg |= RI_CURSOR; 2293 } 2294 offs = gp->g_rowoffset[row] + col; 2295 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, offs & 0xff); 2296 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, offs >> 8); 2297 } 2298 } 2299 2300 static void cv_wsputchar(void *c, int row, int col, u_int ch, long attr) 2301 { 2302 struct rasops_info *ri; 2303 struct vcons_screen *scr; 2304 struct grf_softc *gp; 2305 volatile unsigned char *cp; 2306 2307 ri = c; 2308 scr = ri->ri_hw; 2309 gp = scr->scr_cookie; 2310 cp = gp->g_fbkva; 2311 cp += (gp->g_rowoffset[row] + col) << 2; 2312 *cp++ = ch; 2313 *cp = attr; 2314 } 2315 2316 static void 2317 cv_wscopycols(void *c, int row, int srccol, int dstcol, int ncols) 2318 { 2319 struct rasops_info *ri; 2320 struct vcons_screen *scr; 2321 struct grf_softc *gp; 2322 volatile uint16_t *src, *dst; 2323 2324 KASSERT(ncols > 0); 2325 ri = c; 2326 scr = ri->ri_hw; 2327 gp = scr->scr_cookie; 2328 src = dst = gp->g_fbkva; 2329 src += (gp->g_rowoffset[row] + srccol) << 1; 2330 dst += (gp->g_rowoffset[row] + dstcol) << 1; 2331 if (src < dst) { 2332 /* need to copy backwards */ 2333 src += (ncols - 1) << 1; 2334 dst += (ncols - 1) << 1; 2335 while (ncols--) { 2336 *dst = *src; 2337 src -= 2; 2338 dst -= 2; 2339 } 2340 } else 2341 while (ncols--) { 2342 *dst = *src; 2343 src += 2; 2344 dst += 2; 2345 } 2346 } 2347 2348 static void 2349 cv_wserasecols(void *c, int row, int startcol, int ncols, long fillattr) 2350 { 2351 struct rasops_info *ri; 2352 struct vcons_screen *scr; 2353 struct grf_softc *gp; 2354 volatile uint16_t *cp; 2355 uint16_t val; 2356 2357 ri = c; 2358 scr = ri->ri_hw; 2359 gp = scr->scr_cookie; 2360 cp = gp->g_fbkva; 2361 val = 0x2000 | fillattr; 2362 cp += (gp->g_rowoffset[row] + startcol) << 1; 2363 while (ncols--) { 2364 *cp = val; 2365 cp += 2; 2366 } 2367 } 2368 2369 static void 2370 cv_wscopyrows(void *c, int srcrow, int dstrow, int nrows) 2371 { 2372 struct rasops_info *ri; 2373 struct vcons_screen *scr; 2374 struct grf_softc *gp; 2375 volatile uint16_t *src, *dst; 2376 int n; 2377 2378 KASSERT(nrows > 0); 2379 ri = c; 2380 scr = ri->ri_hw; 2381 gp = scr->scr_cookie; 2382 src = dst = gp->g_fbkva; 2383 n = ri->ri_cols * nrows; 2384 if (src < dst) { 2385 /* need to copy backwards */ 2386 src += gp->g_rowoffset[srcrow + nrows] << 1; 2387 dst += gp->g_rowoffset[dstrow + nrows] << 1; 2388 while (n--) { 2389 src -= 2; 2390 dst -= 2; 2391 *dst = *src; 2392 } 2393 } else { 2394 src += gp->g_rowoffset[srcrow] << 1; 2395 dst += gp->g_rowoffset[dstrow] << 1; 2396 while (n--) { 2397 *dst = *src; 2398 src += 2; 2399 dst += 2; 2400 } 2401 } 2402 } 2403 2404 static void 2405 cv_wseraserows(void *c, int row, int nrows, long fillattr) 2406 { 2407 struct rasops_info *ri; 2408 struct vcons_screen *scr; 2409 struct grf_softc *gp; 2410 volatile uint16_t *cp; 2411 int n; 2412 uint16_t val; 2413 2414 ri = c; 2415 scr = ri->ri_hw; 2416 gp = scr->scr_cookie; 2417 cp = gp->g_fbkva; 2418 val = 0x2000 | fillattr; 2419 cp += gp->g_rowoffset[row] << 1; 2420 n = ri->ri_cols * nrows; 2421 while (n--) { 2422 *cp = val; 2423 cp += 2; 2424 } 2425 } 2426 2427 static int 2428 cv_wsallocattr(void *c, int fg, int bg, int flg, long *attr) 2429 { 2430 2431 /* XXX color support? */ 2432 *attr = (flg & WSATTR_REVERSE) ? 0x70 : 0x07; 2433 if (flg & WSATTR_UNDERLINE) *attr = 0x01; 2434 if (flg & WSATTR_HILIT) *attr |= 0x08; 2435 if (flg & WSATTR_BLINK) *attr |= 0x80; 2436 return 0; 2437 } 2438 2439 /* our font does not support unicode extensions */ 2440 static int 2441 cv_wsmapchar(void *c, int ch, unsigned int *cp) 2442 { 2443 2444 if (ch > 0 && ch < 256) { 2445 *cp = ch; 2446 return 5; 2447 } 2448 *cp = ' '; 2449 return 0; 2450 } 2451 2452 #endif /* NWSDISPLAY > 0 */ 2453 2454 #endif /* NGRFCV */ 2455