1 /* $NetBSD: grf_cv.c,v 1.56 2014/01/22 00:25:16 christos 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.56 2014/01/22 00:25:16 christos 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 grf_softc *gp; 482 struct grf_cv_softc *gcp; 483 484 485 /* 486 * This function is called twice, once on console init (self == NULL) 487 * and once on "normal" grf5 init. 488 */ 489 490 if (self == NULL) { 491 gcp = &congrf; 492 gp = &gcp->gcs_sc; 493 gp->g_device = &temp; 494 temp.dv_private = gp; 495 } else { 496 gcp = device_private(self); 497 gp = &gcp->gcs_sc; 498 gp->g_device = self; 499 } 500 501 502 if (self != NULL && congrf.gcs_sc.g_regkva != 0) { 503 /* 504 * inited earlier, just copy (not device struct) 505 */ 506 507 printf("\n"); 508 memcpy(&gp->g_display, &congrf.gcs_sc.g_display, 509 (char *) &gcp->gcs_isr - (char *) &gp->g_display); 510 511 /* ... and transfer the isr */ 512 gcp->gcs_isr.isr_ipl = CV_INT_NUM; 513 gcp->gcs_isr.isr_intr = cvintr; 514 gcp->gcs_isr.isr_arg = (void *)gp; 515 516 /* First add new isr */ 517 add_isr(&gcp->gcs_isr); 518 remove_isr(&congrf.gcs_isr); 519 } else { 520 gp->g_regkva = (volatile char *)cv_boardaddr + 0x02000000; 521 gp->g_fbkva = (volatile char *)cv_boardaddr + 0x01400000; 522 523 gp->g_unit = GRF_CV64_UNIT; 524 gp->g_mode = cv_mode; 525 #if NITE > 0 526 gp->g_conpri = grfcv_cnprobe(); 527 #endif 528 gp->g_flags = GF_ALIVE; 529 530 /* add Interrupt Handler */ 531 gcp->gcs_isr.isr_ipl = CV_INT_NUM; 532 gcp->gcs_isr.isr_intr = cvintr; 533 gcp->gcs_isr.isr_arg = (void *)gp; 534 add_isr(&gcp->gcs_isr); 535 536 /* wakeup the board */ 537 cv_boardinit(gp); 538 539 #ifdef CV64CONSOLE 540 #if NWSDISPLAY > 0 541 gp->g_accessops = &cv_accessops; 542 gp->g_emulops = &cv_textops; 543 gp->g_defaultscreen = cv_screen; 544 gp->g_screens[0] = &gp->g_defaultscreen; 545 gp->g_wsioctl = &cv_wsioctl; 546 #else 547 grfcv_iteinit(gp); 548 #endif 549 (void)cv_load_mon(gp, &cvconsole_mode); 550 #endif 551 } 552 553 /* 554 * attach grf 555 */ 556 if (amiga_config_found(cfdata, gp->g_device, gp, grfcvprint)) { 557 if (self != NULL) 558 printf("grfcv: CyberVision64 with %dMB being used\n", 559 cv_fbsize/0x100000); 560 attachflag = 1; 561 } else { 562 if (!attachflag) 563 /*printf("grfcv unattached!!\n")*/; 564 } 565 } 566 567 int 568 grfcvprint(void *aux, const char *pnp) 569 { 570 if (pnp) 571 aprint_normal("ite at %s: ", pnp); 572 return (UNCONF); 573 } 574 575 576 /* 577 * Computes M, N, and R values from 578 * given input frequency. It uses a table of 579 * precomputed values, to keep CPU time low. 580 * 581 * The return value consist of: 582 * lower byte: Bits 4-0: N Divider Value 583 * Bits 5-6: R Value for e.g. SR10 or SR12 584 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13 585 */ 586 587 static unsigned short 588 cv_compute_clock(unsigned long freq) 589 { 590 static unsigned char *mnr, *save; /* M, N + R vals */ 591 unsigned long work_freq, r; 592 unsigned short erg; 593 long diff, d2; 594 595 if (freq < 12500000 || freq > MAXPIXELCLOCK) { 596 printf("grfcv: Illegal clock frequency: %ldMHz\n", freq/1000000); 597 printf("grfcv: Using default frequency: 25MHz\n"); 598 printf("grfcv: See the manpage of grfconfig for more informations.\n"); 599 freq = 25000000; 600 } 601 602 mnr = clocks; /* there the vals are stored */ 603 d2 = 0x7fffffff; 604 605 while (*mnr) { /* mnr vals are 0-terminated */ 606 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2); 607 608 r = (mnr[1] >> 5) & 0x03; 609 if (r != 0) 610 work_freq=work_freq >> r; /* r is the freq divider */ 611 612 work_freq *= 0x3E8; /* 2nd part of OSC */ 613 614 diff = abs(freq - work_freq); 615 616 if (d2 >= diff) { 617 d2 = diff; 618 /* In save are the vals for minimal diff */ 619 save = mnr; 620 } 621 mnr += 2; 622 } 623 erg = *((unsigned short *)save); 624 625 return (erg); 626 } 627 628 629 void 630 cv_boardinit(struct grf_softc *gp) 631 { 632 volatile void *ba; 633 unsigned char test; 634 unsigned int clockpar; 635 int i; 636 struct grfinfo *gi; 637 638 ba = gp->g_regkva; 639 /* Reset board */ 640 for (i = 0; i < 6; i++) 641 /* Clear all bits */ 642 cv_write_port (0xff, (volatile char*)ba - 0x02000000); 643 644 /* Return to operational Mode */ 645 cv_write_port(0x8004, (volatile char*)ba - 0x02000000); 646 647 /* Wakeup Chip */ 648 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x10); 649 vgaw(ba, SREG_OPTION_SELECT, 0x01); 650 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x08); 651 652 vgaw(ba, GREG_MISC_OUTPUT_W, 0x03); 653 654 WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48); /* unlock S3 VGA regs */ 655 WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5); /* unlock syscontrol */ 656 657 /* 658 * The default board interrupt is #6. 659 * Set the roxxler register to use interrupt #2, not #6. 660 */ 661 #if CV_INT_NUM == 2 662 cv_write_port(0x8080, (volatile char*)ba - 0x02000000); 663 #endif 664 665 /* Enable board interrupts */ 666 cv_write_port(0x8008, (volatile char*)ba - 0x02000000); 667 668 test = RCrt(ba, CRT_ID_SYSTEM_CONFIG); 669 test = test | 0x01; /* enable enhanced register access */ 670 test = test & 0xEF; /* clear bit 4, 0 wait state */ 671 WCrt(ba, CRT_ID_SYSTEM_CONFIG, test); 672 673 /* 674 * bit 1=1: enable enhanced mode functions 675 * bit 4=1: enable linear addressing 676 * bit 5=1: enable MMIO 677 */ 678 vgaw(ba, ECR_ADV_FUNC_CNTL, 0x31); 679 680 /* enable color mode (bit0), CPU access (bit1), high 64k page (bit5) */ 681 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); 682 683 /* CPU base addr */ 684 WCrt(ba, CRT_ID_EXT_SYS_CNTL_4, 0x00); 685 686 /* Reset. This does nothing, but everyone does it:) */ 687 WSeq(ba, SEQ_ID_RESET, 0x03); 688 689 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01); /* 8 Dot Clock */ 690 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f); /* Enable write planes */ 691 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); /* Character Font */ 692 693 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x02); /* Complete mem access */ 694 695 WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x06); /* Unlock extensions */ 696 test = RSeq(ba, SEQ_ID_BUS_REQ_CNTL); /* Bus Request */ 697 698 /* enable 4MB fast Page Mode */ 699 test = test | 1 << 6; 700 WSeq(ba, SEQ_ID_BUS_REQ_CNTL, test); 701 /* faster LUT write */ 702 WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0xC0); 703 704 test = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); /* Clksyn2 read */ 705 706 /* immediately Clkload bit clear */ 707 test = test & 0xDF; 708 709 /* 2 MCLK Memory Write.... */ 710 if (cv_memclk >= 55000000) 711 test |= 0x80; 712 713 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test); 714 715 /* Memory CLK */ 716 clockpar = cv_compute_clock(cv_memclk); 717 test = (clockpar & 0xFF00) >> 8; 718 WSeq(ba, SEQ_ID_MCLK_HI, test); /* PLL N-Divider Value */ 719 720 test = clockpar & 0xFF; 721 WSeq(ba, SEQ_ID_MCLK_LO, test); /* PLL M-Divider Value */ 722 723 if (RCrt(ba, CRT_ID_REVISION) == 0x10) /* bugfix for new S3 chips */ 724 WSeq(ba, SEQ_ID_MORE_MAGIC, test); 725 726 /* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */ 727 /* DCLK */ 728 WSeq(ba, SEQ_ID_DCLK_HI, 0x13); 729 WSeq(ba, SEQ_ID_DCLK_LO, 0x41); 730 731 test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2); 732 test = test | 0x22; 733 734 /* DCLK + MCLK Clock immediate load! */ 735 WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test); 736 737 /* DCLK load */ 738 test = vgar(ba, 0x3cc); 739 test = test | 0x0c; 740 vgaw(ba, 0x3c2, test); 741 742 /* Clear bit 5 again, prevent further loading. */ 743 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x02); 744 745 WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F); 746 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F); 747 WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50); 748 WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82); 749 WCrt(ba, CRT_ID_START_HOR_RETR, 0x54); 750 WCrt(ba, CRT_ID_END_HOR_RETR, 0x80); 751 WCrt(ba, CRT_ID_VER_TOTAL, 0xBF); 752 753 WCrt(ba, CRT_ID_OVERFLOW, 0x1F); /* overflow reg */ 754 755 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); /* no panning */ 756 757 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40); /* vscan */ 758 759 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 760 WCrt(ba, CRT_ID_CURSOR_END, 0x00); 761 762 /* Display start address */ 763 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 764 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 765 766 /* Cursor location */ 767 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 768 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 769 770 /* Vertical retrace */ 771 WCrt(ba, CRT_ID_START_VER_RETR, 0x9C); 772 WCrt(ba, CRT_ID_END_VER_RETR, 0x0E); 773 774 WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F); 775 WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50); 776 777 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00); 778 779 WCrt(ba, CRT_ID_START_VER_BLANK, 0x96); 780 WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9); 781 782 WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3); 783 784 WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF); 785 786 WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */ 787 788 /* Refresh count 1, High speed text font, enhanced color mode */ 789 WCrt(ba, CRT_ID_MISC_1, 0x35); 790 791 /* start fifo position */ 792 WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5a); 793 794 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x70); 795 796 /* address window position */ 797 WCrt(ba, CRT_ID_LAW_POS_LO, 0x40); 798 799 /* N Parameter for Display FIFO */ 800 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, 0xFF); 801 802 WGfx(ba, GCT_ID_SET_RESET, 0x00); 803 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00); 804 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00); 805 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00); 806 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 807 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40); 808 WGfx(ba, GCT_ID_MISC, 0x01); 809 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F); 810 WGfx(ba, GCT_ID_BITMASK, 0xFF); 811 812 /* colors for text mode */ 813 for (i = 0; i <= 0xf; i++) 814 WAttr (ba, i, i); 815 816 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x41); 817 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x01); 818 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0F); 819 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00); 820 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00); 821 822 vgaw(ba, VDAC_MASK, 0xFF); /* DAC Mask */ 823 824 *((volatile unsigned long *)((volatile char*)ba + ECR_FRGD_COLOR)) = 0xFF; 825 *((volatile unsigned long *)((volatile char*)ba + ECR_BKGD_COLOR)) = 0; 826 827 /* colors initially set to greyscale */ 828 829 vgaw(ba, VDAC_ADDRESS_W, 0); 830 for (i = 255; i >= 0 ; i--) { 831 vgaw(ba, VDAC_DATA, i); 832 vgaw(ba, VDAC_DATA, i); 833 vgaw(ba, VDAC_DATA, i); 834 } 835 836 /* GFx hardware cursor off */ 837 WCrt(ba, CRT_ID_HWGC_MODE, 0x00); 838 839 /* Set first to 4 MB, so test will work */ 840 WCrt(ba, CRT_ID_LAW_CNTL, 0x13); 841 842 /* find *correct* fbsize of z3 board */ 843 if (cv_has_4mb((volatile char *)cv_boardaddr + 0x01400000)) { 844 cv_fbsize = 1024 * 1024 * 4; 845 WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */ 846 } else { 847 cv_fbsize = 1024 * 1024 * 2; 848 WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */ 849 } 850 851 /* Initialize graphics engine */ 852 GfxBusyWait(ba); 853 vgaw16(ba, ECR_FRGD_MIX, 0x27); 854 vgaw16(ba, ECR_BKGD_MIX, 0x07); 855 856 vgaw16(ba, ECR_READ_REG_DATA, 0x1000); 857 delay(200000); 858 vgaw16(ba, ECR_READ_REG_DATA, 0x2000); 859 GfxBusyWait(ba); 860 vgaw16(ba, ECR_READ_REG_DATA, 0x3fff); 861 GfxBusyWait(ba); 862 delay(200000); 863 vgaw16(ba, ECR_READ_REG_DATA, 0x4fff); 864 GfxBusyWait(ba); 865 866 vgaw16(ba, ECR_BITPLANE_WRITE_MASK, ~0); 867 868 GfxBusyWait (ba); 869 vgaw16(ba, ECR_READ_REG_DATA, 0xe000); 870 vgaw16(ba, ECR_CURRENT_Y_POS2, 0x00); 871 vgaw16(ba, ECR_CURRENT_X_POS2, 0x00); 872 vgaw16(ba, ECR_READ_REG_DATA, 0xa000); 873 vgaw16(ba, ECR_DEST_Y__AX_STEP, 0x00); 874 vgaw16(ba, ECR_DEST_Y2__AX_STEP2, 0x00); 875 vgaw16(ba, ECR_DEST_X__DIA_STEP, 0x00); 876 vgaw16(ba, ECR_DEST_X2__DIA_STEP2, 0x00); 877 vgaw16(ba, ECR_SHORT_STROKE, 0x00); 878 vgaw16(ba, ECR_DRAW_CMD, 0x01); 879 GfxBusyWait (ba); 880 881 /* It ain't easy to write here, so let's do it again */ 882 vgaw16(ba, ECR_READ_REG_DATA, 0x4fff); 883 884 vgaw16(ba, ECR_BKGD_COLOR, 0x01); 885 vgaw16(ba, ECR_FRGD_COLOR, 0x00); 886 887 /* Enable Video Display (Set Bit 5) */ 888 WAttr(ba, 0x33, 0); 889 890 gi = &gp->g_display; 891 gi->gd_regaddr = (void *) kvtop (__UNVOLATILE(ba)); 892 gi->gd_regsize = 64 * 1024; 893 gi->gd_fbaddr = (void *) kvtop (__UNVOLATILE(gp->g_fbkva)); 894 gi->gd_fbsize = cv_fbsize; 895 } 896 897 898 int 899 cv_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm) 900 { 901 struct grfvideo_mode *gv; 902 903 #ifdef CV64CONSOLE 904 /* Handle grabbing console mode */ 905 if (vm->mode_num == 255) { 906 memcpy(vm, &cvconsole_mode, sizeof(struct grfvideo_mode)); 907 /* XXX so grfconfig can tell us the correct text dimensions. */ 908 vm->depth = cvconsole_mode.fy; 909 } else 910 #endif 911 { 912 if (vm->mode_num == 0) 913 vm->mode_num = (monitor_current - monitor_def) + 1; 914 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max) 915 return (EINVAL); 916 gv = monitor_def + (vm->mode_num - 1); 917 if (gv->mode_num == 0) 918 return (EINVAL); 919 920 memcpy(vm, gv, sizeof(struct grfvideo_mode)); 921 } 922 923 /* adjust internal values to pixel values */ 924 925 vm->hblank_start *= 8; 926 vm->hsync_start *= 8; 927 vm->hsync_stop *= 8; 928 vm->htotal *= 8; 929 930 return (0); 931 } 932 933 934 int 935 cv_setvmode(struct grf_softc *gp, unsigned mode) 936 { 937 938 if (!mode || (mode > monitor_def_max) || 939 monitor_def[mode - 1].mode_num == 0) 940 return (EINVAL); 941 942 monitor_current = monitor_def + (mode - 1); 943 944 return (0); 945 } 946 947 948 int 949 cv_blank(struct grf_softc *gp, int *on) 950 { 951 volatile void *ba; 952 953 ba = gp->g_regkva; 954 gfx_on_off(*on > 0 ? 0 : 1, ba); 955 return (0); 956 } 957 958 959 /* 960 * Change the mode of the display. 961 * Return a UNIX error number or 0 for success. 962 */ 963 int 964 cv_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2, 965 int a3) 966 { 967 int error; 968 969 switch (cmd) { 970 case GM_GRFON: 971 error = cv_load_mon (gp, 972 (struct grfcvtext_mode *) monitor_current) ? 0 : EINVAL; 973 return (error); 974 975 case GM_GRFOFF: 976 #ifndef CV64CONSOLE 977 cvscreen(1, (volatile char *)gp->g_regkva - 0x02000000); 978 #else 979 cv_load_mon(gp, &cvconsole_mode); 980 #if NITE > 0 981 ite_reinit(gp->g_itedev); 982 #endif 983 #endif /* CV64CONSOLE */ 984 return (0); 985 986 case GM_GRFCONFIG: 987 return (0); 988 989 case GM_GRFGETVMODE: 990 return (cv_getvmode (gp, (struct grfvideo_mode *) arg)); 991 992 case GM_GRFSETVMODE: 993 error = cv_setvmode (gp, *(unsigned *) arg); 994 if (!error && (gp->g_flags & GF_GRFON)) 995 cv_load_mon(gp, 996 (struct grfcvtext_mode *) monitor_current); 997 return (error); 998 999 case GM_GRFGETNUMVM: 1000 *(int *)arg = monitor_def_max; 1001 return (0); 1002 1003 case GM_GRFIOCTL: 1004 return (cv_ioctl (gp, a2, arg)); 1005 1006 default: 1007 break; 1008 } 1009 1010 return (EPASSTHROUGH); 1011 } 1012 1013 1014 int 1015 cv_ioctl(register struct grf_softc *gp, u_long cmd, void *data) 1016 { 1017 switch (cmd) { 1018 #ifndef CV_NO_HARDWARE_CURSOR 1019 case GRFIOCGSPRITEPOS: 1020 return(cv_getspritepos (gp, (struct grf_position *) data)); 1021 1022 case GRFIOCSSPRITEPOS: 1023 return(cv_setspritepos (gp, (struct grf_position *) data)); 1024 1025 case GRFIOCSSPRITEINF: 1026 return(cv_setspriteinfo (gp, (struct grf_spriteinfo *) data)); 1027 1028 case GRFIOCGSPRITEINF: 1029 return(cv_getspriteinfo (gp, (struct grf_spriteinfo *) data)); 1030 1031 case GRFIOCGSPRITEMAX: 1032 return(cv_getspritemax (gp, (struct grf_position *) data)); 1033 #else /* !CV_NO_HARDWARE_CURSOR */ 1034 case GRFIOCGSPRITEPOS: 1035 case GRFIOCSSPRITEPOS: 1036 case GRFIOCSSPRITEINF: 1037 case GRFIOCGSPRITEINF: 1038 case GRFIOCGSPRITEMAX: 1039 break; 1040 #endif /* !CV_NO_HARDWARE_CURSOR */ 1041 1042 case GRFIOCGETCMAP: 1043 return (cv_getcmap (gp, (struct grf_colormap *) data)); 1044 1045 case GRFIOCPUTCMAP: 1046 return (cv_putcmap (gp, (struct grf_colormap *) data)); 1047 1048 case GRFIOCBITBLT: 1049 break; 1050 1051 case GRFTOGGLE: 1052 return (cv_toggle (gp)); 1053 1054 case GRFIOCSETMON: 1055 return (cv_setmonitor (gp, (struct grfvideo_mode *)data)); 1056 1057 case GRFIOCBLANK: 1058 return (cv_blank (gp, (int *)data)); 1059 } 1060 return (EPASSTHROUGH); 1061 } 1062 1063 1064 int 1065 cv_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv) 1066 { 1067 struct grfvideo_mode *md; 1068 1069 if (!cv_mondefok(gv)) 1070 return (EINVAL); 1071 1072 #ifdef CV64CONSOLE 1073 /* handle interactive setting of console mode */ 1074 if (gv->mode_num == 255) { 1075 memcpy(&cvconsole_mode.gv, gv, sizeof(struct grfvideo_mode)); 1076 cvconsole_mode.gv.hblank_start /= 8; 1077 cvconsole_mode.gv.hsync_start /= 8; 1078 cvconsole_mode.gv.hsync_stop /= 8; 1079 cvconsole_mode.gv.htotal /= 8; 1080 cvconsole_mode.rows = gv->disp_height / cvconsole_mode.fy; 1081 cvconsole_mode.cols = gv->disp_width / cvconsole_mode.fx; 1082 if (!(gp->g_flags & GF_GRFON)) 1083 cv_load_mon(gp, &cvconsole_mode); 1084 #if NITE > 0 1085 ite_reinit(gp->g_itedev); 1086 #endif 1087 return (0); 1088 } 1089 #endif 1090 1091 md = monitor_def + (gv->mode_num - 1); 1092 1093 /* 1094 * Prevent user from crashing the system by using 1095 * grfconfig while in X 1096 */ 1097 if (gp->g_flags & GF_GRFON) 1098 if (md == monitor_current) { 1099 printf("grfcv: Changing the used mode not allowed!\n"); 1100 return (EINVAL); 1101 } 1102 1103 memcpy(md, gv, sizeof(struct grfvideo_mode)); 1104 1105 /* adjust pixel oriented values to internal rep. */ 1106 1107 md->hblank_start /= 8; 1108 md->hsync_start /= 8; 1109 md->hsync_stop /= 8; 1110 md->htotal /= 8; 1111 1112 return (0); 1113 } 1114 1115 1116 int 1117 cv_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap) 1118 { 1119 volatile void *ba; 1120 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1121 short x; 1122 int error; 1123 1124 ba = gfp->g_regkva; 1125 if (cmap->count == 0 || cmap->index >= 256) 1126 return (0); 1127 1128 if (cmap->count > 256 - cmap->index) 1129 cmap->count = 256 - cmap->index; 1130 1131 /* first read colors out of the chip, then copyout to userspace */ 1132 vgaw (ba, VDAC_ADDRESS_W, cmap->index); 1133 x = cmap->count - 1; 1134 1135 rp = red + cmap->index; 1136 gp = green + cmap->index; 1137 bp = blue + cmap->index; 1138 1139 do { 1140 *rp++ = vgar (ba, VDAC_DATA) << 2; 1141 *gp++ = vgar (ba, VDAC_DATA) << 2; 1142 *bp++ = vgar (ba, VDAC_DATA) << 2; 1143 } while (x-- > 0); 1144 1145 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count)) 1146 && !(error = copyout (green + cmap->index, cmap->green, cmap->count)) 1147 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count))) 1148 return (0); 1149 1150 return (error); 1151 } 1152 1153 1154 int 1155 cv_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap) 1156 { 1157 volatile void *ba; 1158 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1159 short x; 1160 int error; 1161 1162 ba = gfp->g_regkva; 1163 if (cmap->count == 0 || cmap->index >= 256) 1164 return (0); 1165 1166 if (cmap->count > 256 - cmap->index) 1167 cmap->count = 256 - cmap->index; 1168 1169 /* first copy the colors into kernelspace */ 1170 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count)) 1171 && !(error = copyin (cmap->green, green + cmap->index, cmap->count)) 1172 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) { 1173 vgaw (ba, VDAC_ADDRESS_W, cmap->index); 1174 x = cmap->count - 1; 1175 1176 rp = red + cmap->index; 1177 gp = green + cmap->index; 1178 bp = blue + cmap->index; 1179 1180 do { 1181 vgaw (ba, VDAC_DATA, *rp++ >> 2); 1182 vgaw (ba, VDAC_DATA, *gp++ >> 2); 1183 vgaw (ba, VDAC_DATA, *bp++ >> 2); 1184 } while (x-- > 0); 1185 return (0); 1186 } else 1187 return (error); 1188 } 1189 1190 1191 int 1192 cv_toggle(struct grf_softc *gp) 1193 { 1194 volatile void *ba; 1195 1196 ba = gp->g_regkva; 1197 #ifndef CV64CONSOLE 1198 cv_pass_toggle = 1; 1199 #endif /* !CV64CONSOLE */ 1200 1201 if (cv_pass_toggle) { 1202 cvscreen(0, (volatile char*)ba - 0x02000000); 1203 cv_pass_toggle = 0; 1204 } else { 1205 cvscreen(1, (volatile char*)ba - 0x02000000); 1206 cv_pass_toggle = 1; 1207 } 1208 1209 return (0); 1210 } 1211 1212 1213 int 1214 cv_mondefok(struct grfvideo_mode *gv) 1215 { 1216 unsigned long maxpix; 1217 1218 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) { 1219 if (gv->mode_num != 255 || gv->depth != 4) 1220 return (0); 1221 } 1222 1223 switch(gv->depth) { 1224 case 4: 1225 maxpix = MAXPIXELCLOCK - 55000000; 1226 break; 1227 case 8: 1228 maxpix = MAXPIXELCLOCK; 1229 break; 1230 case 15: 1231 case 16: 1232 #ifdef CV_AGGRESSIVE_TIMING 1233 maxpix = MAXPIXELCLOCK - 35000000; 1234 #else 1235 maxpix = MAXPIXELCLOCK - 55000000; 1236 #endif 1237 break; 1238 case 24: 1239 case 32: 1240 #ifdef CV_AGGRESSIVE_TIMING 1241 maxpix = MAXPIXELCLOCK - 75000000; 1242 #else 1243 maxpix = MAXPIXELCLOCK - 85000000; 1244 #endif 1245 break; 1246 default: 1247 printf("grfcv: Illegal depth in mode %d\n", 1248 (int) gv->mode_num); 1249 return (0); 1250 } 1251 1252 if (gv->pixel_clock > maxpix) { 1253 printf("grfcv: Pixelclock too high in mode %d\n", 1254 (int) gv->mode_num); 1255 return (0); 1256 } 1257 1258 if (gv->mode_num == 255) { /* console mode */ 1259 if ((gv->disp_width / 8) > MAXCOLS) { 1260 printf ("grfcv: Too many columns for console\n"); 1261 return (0); 1262 } else if ((gv->disp_height / S3FONTY) > MAXROWS) { 1263 printf ("grfcv: Too many rows for console\n"); 1264 return (0); 1265 } 1266 } 1267 1268 if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) { 1269 printf("grfcv: sync-on-green is not supported\n"); 1270 return (0); 1271 } 1272 1273 return (1); 1274 } 1275 1276 1277 int 1278 cv_load_mon(struct grf_softc *gp, struct grfcvtext_mode *md) 1279 { 1280 struct grfvideo_mode *gv; 1281 struct grfinfo *gi; 1282 volatile void *ba; 1283 unsigned short mnr; 1284 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, 1285 VSE, VT; 1286 int cr50, sr15, sr18, clock_mode, test; 1287 int m, n; /* For calc'ing display FIFO */ 1288 int tfillm, temptym; /* FIFO fill and empty mclk's */ 1289 int hmul; /* Multiplier for hor. Values */ 1290 unsigned char hvsync_pulse; 1291 char TEXT, CONSOLE; 1292 1293 /* identity */ 1294 gv = &md->gv; 1295 1296 TEXT = (gv->depth == 4); 1297 CONSOLE = (gv->mode_num == 255); 1298 1299 if (!cv_mondefok(gv)) { 1300 printf("grfcv: Monitor definition not ok\n"); 1301 return (0); 1302 } 1303 1304 ba = gp->g_regkva; 1305 1306 /* Disable Interrupts */ 1307 test = RCrt(ba, CRT_ID_BACKWAD_COMP_1); 1308 test &= ~0x10; 1309 WCrt(ba, CRT_ID_BACKWAD_COMP_1, test); 1310 1311 /* turn gfx off, don't mess up the display */ 1312 gfx_on_off(1, ba); 1313 1314 /* provide all needed information in grf device-independent locations */ 1315 gp->g_data = (void *) gv; 1316 gi = &gp->g_display; 1317 gi->gd_colors = 1 << gv->depth; 1318 gi->gd_planes = gv->depth; 1319 gi->gd_fbwidth = gv->disp_width; 1320 gi->gd_fbheight = gv->disp_height; 1321 gi->gd_fbx = 0; 1322 gi->gd_fby = 0; 1323 if (CONSOLE) { 1324 gi->gd_dwidth = md->fx * md->cols; 1325 gi->gd_dheight = md->fy * md->rows; 1326 } else { 1327 gi->gd_dwidth = gv->disp_width; 1328 gi->gd_dheight = gv->disp_height; 1329 } 1330 gi->gd_dx = 0; 1331 gi->gd_dy = 0; 1332 1333 /* get display mode parameters */ 1334 switch (gv->depth) { 1335 case 15: 1336 case 16: 1337 hmul = 2; 1338 break; 1339 default: 1340 hmul = 1; 1341 break; 1342 } 1343 1344 HBS = gv->hblank_start * hmul; 1345 HSS = gv->hsync_start * hmul; 1346 HSE = gv->hsync_stop * hmul; 1347 HBE = gv->htotal * hmul - 6; 1348 HT = gv->htotal * hmul - 5; 1349 VBS = gv->vblank_start - 1; 1350 VSS = gv->vsync_start; 1351 VSE = gv->vsync_stop; 1352 VBE = gv->vtotal - 3; 1353 VT = gv->vtotal - 2; 1354 1355 /* Disable enhanced Mode for text display */ 1356 1357 vgaw(ba, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31)); 1358 1359 if (TEXT) 1360 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1; 1361 else 1362 HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/ 1363 VDE = gv->disp_height - 1; 1364 1365 /* adjustments */ 1366 1367 if (gv->disp_flags & GRF_FLAGS_LACE) { 1368 VDE = VDE / 2; 1369 VBS = VBS / 2; 1370 VSS = VSS / 2; 1371 VSE = VSE / 2; 1372 VBE = VBE / 2; 1373 VT = VT / 2; 1374 } 1375 1376 /* Horizontal/Vertical Sync Pulse */ 1377 /* 1378 * GREG_MISC_OUTPUT_W Register: 1379 * bit description (0/1) 1380 * 0 Monochrome/Color emulation 1381 * 1 Disable/Enable access of the display memory from the CPU 1382 * 5 Select the low/high 64K page of memory 1383 * 6 Select a positive/negative horizontal retrace sync pulse 1384 * 7 Select a positive/negative vertical retrace sync pulse 1385 */ 1386 hvsync_pulse = vgar(ba, GREG_MISC_OUTPUT_R); 1387 if (gv->disp_flags & GRF_FLAGS_PHSYNC) 1388 hvsync_pulse &= ~0x40; 1389 else 1390 hvsync_pulse |= 0x40; 1391 if (gv->disp_flags & GRF_FLAGS_PVSYNC) 1392 hvsync_pulse &= ~0x80; 1393 else 1394 hvsync_pulse |= 0x80; 1395 vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse); 1396 1397 /* GFX hardware cursor off */ 1398 WCrt(ba, CRT_ID_HWGC_MODE, 0x00); 1399 WCrt(ba, CRT_ID_EXT_DAC_CNTL, 0x00); 1400 1401 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e); 1402 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 1403 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff); 1404 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 1405 1406 /* Set clock */ 1407 1408 mnr = cv_compute_clock(gv->pixel_clock); 1409 WSeq(ba, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8)); 1410 WSeq(ba, SEQ_ID_DCLK_LO, (mnr & 0xFF)); 1411 1412 /* load display parameters into board */ 1413 1414 WCrt(ba, CRT_ID_EXT_HOR_OVF, 1415 ((HT & 0x100) ? 0x01 : 0x00) | 1416 ((HDE & 0x100) ? 0x02 : 0x00) | 1417 ((HBS & 0x100) ? 0x04 : 0x00) | 1418 /* ((HBE & 0x40) ? 0x08 : 0x00) | */ /* Later... */ 1419 ((HSS & 0x100) ? 0x10 : 0x00) | 1420 /* ((HSE & 0x20) ? 0x20 : 0x00) | */ 1421 (((HT-5) & 0x100) ? 0x40 : 0x00) ); 1422 1423 WCrt(ba, CRT_ID_EXT_VER_OVF, 1424 0x40 | /* Line compare */ 1425 ((VT & 0x400) ? 0x01 : 0x00) | 1426 ((VDE & 0x400) ? 0x02 : 0x00) | 1427 ((VBS & 0x400) ? 0x04 : 0x00) | 1428 ((VSS & 0x400) ? 0x10 : 0x00) ); 1429 1430 WCrt(ba, CRT_ID_HOR_TOTAL, HT); 1431 WCrt(ba, CRT_ID_DISPLAY_FIFO, HT - 5); 1432 1433 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE)); 1434 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS); 1435 WCrt(ba, CRT_ID_END_HOR_BLANK, ((HBE & 0x1f) | 0x80)); 1436 WCrt(ba, CRT_ID_START_HOR_RETR, HSS); 1437 WCrt(ba, CRT_ID_END_HOR_RETR, 1438 (HSE & 0x1f) | 1439 ((HBE & 0x20) ? 0x80 : 0x00) ); 1440 WCrt(ba, CRT_ID_VER_TOTAL, VT); 1441 WCrt(ba, CRT_ID_OVERFLOW, 1442 0x10 | 1443 ((VT & 0x100) ? 0x01 : 0x00) | 1444 ((VDE & 0x100) ? 0x02 : 0x00) | 1445 ((VSS & 0x100) ? 0x04 : 0x00) | 1446 ((VBS & 0x100) ? 0x08 : 0x00) | 1447 ((VT & 0x200) ? 0x20 : 0x00) | 1448 ((VDE & 0x200) ? 0x40 : 0x00) | 1449 ((VSS & 0x200) ? 0x80 : 0x00) ); 1450 1451 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 1452 0x40 | /* TEXT ? 0x00 ??? */ 1453 ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) | 1454 ((VBS & 0x200) ? 0x20 : 0x00) | 1455 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); 1456 1457 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3); 1458 1459 /* text cursor */ 1460 1461 if (TEXT) { 1462 #if CV_ULCURSOR 1463 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2); 1464 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1); 1465 #else 1466 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 1467 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f); 1468 #endif 1469 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f); 1470 1471 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 1472 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 1473 } 1474 1475 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 1476 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 1477 1478 WCrt(ba, CRT_ID_START_VER_RETR, VSS); 1479 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f)); 1480 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE); 1481 WCrt(ba, CRT_ID_START_VER_BLANK, VBS); 1482 WCrt(ba, CRT_ID_END_VER_BLANK, VBE); 1483 1484 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); 1485 WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2); 1486 WCrt(ba, CRT_ID_LACE_CONTROL, 1487 ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x20 : 0x00)); 1488 1489 WGfx(ba, GCT_ID_GRAPHICS_MODE, 1490 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40)); 1491 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01)); 1492 1493 WSeq (ba, SEQ_ID_MEMORY_MODE, 1494 ((TEXT || (gv->depth == 1)) ? 0x06 : 0x02)); 1495 1496 vgaw(ba, VDAC_MASK, 0xff); 1497 1498 /* Blank border */ 1499 test = RCrt(ba, CRT_ID_BACKWAD_COMP_2); 1500 WCrt(ba, CRT_ID_BACKWAD_COMP_2, (test | 0x20)); 1501 1502 sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); 1503 sr15 &= ~0x10; 1504 sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL); 1505 sr18 &= ~0x80; 1506 clock_mode = 0x00; 1507 cr50 = 0x00; 1508 1509 test = RCrt(ba, CRT_ID_EXT_MISC_CNTL_2); 1510 test &= 0xd; 1511 1512 /* clear roxxler byte-swapping... */ 1513 cv_write_port(0x0040, cv_boardaddr); 1514 cv_write_port(0x0020, cv_boardaddr); 1515 1516 switch (gv->depth) { 1517 case 1: 1518 case 4: /* text */ 1519 HDE = gv->disp_width / 16; 1520 break; 1521 case 8: 1522 if (gv->pixel_clock > 80000000) { 1523 clock_mode = 0x10 | 0x02; 1524 sr15 |= 0x10; 1525 sr18 |= 0x80; 1526 } 1527 HDE = gv->disp_width / 8; 1528 cr50 |= 0x00; 1529 break; 1530 case 15: 1531 cv_write_port (0x8020, cv_boardaddr); 1532 clock_mode = 0x30; 1533 HDE = gv->disp_width / 4; 1534 cr50 |= 0x10; 1535 break; 1536 case 16: 1537 cv_write_port (0x8020, cv_boardaddr); 1538 clock_mode = 0x50; 1539 HDE = gv->disp_width / 4; 1540 cr50 |= 0x10; 1541 break; 1542 case 24: /* this is really 32 Bit on CV64 */ 1543 case 32: 1544 cv_write_port(0x8040, cv_boardaddr); 1545 clock_mode = 0xd0; 1546 HDE = (gv->disp_width / 2); 1547 cr50 |= 0x30; 1548 break; 1549 } 1550 1551 WCrt(ba, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test); 1552 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, sr15); 1553 WSeq(ba, SEQ_ID_RAMDAC_CNTL, sr18); 1554 WCrt(ba, CRT_ID_SCREEN_OFFSET, HDE); 1555 1556 WCrt(ba, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35)); 1557 1558 test = RCrt(ba, CRT_ID_EXT_SYS_CNTL_2); 1559 test &= ~0x30; 1560 /* HDE Overflow in bits 4-5 */ 1561 test |= (HDE >> 4) & 0x30; 1562 WCrt(ba, CRT_ID_EXT_SYS_CNTL_2, test); 1563 1564 /* Set up graphics engine */ 1565 switch (gv->disp_width) { 1566 case 1024: 1567 cr50 |= 0x00; 1568 break; 1569 case 640: 1570 cr50 |= 0x40; 1571 break; 1572 case 800: 1573 cr50 |= 0x80; 1574 break; 1575 case 1280: 1576 cr50 |= 0xc0; 1577 break; 1578 case 1152: 1579 cr50 |= 0x01; 1580 break; 1581 case 1600: 1582 cr50 |= 0x81; 1583 break; 1584 default: /* XXX The Xserver has to handle this */ 1585 break; 1586 } 1587 1588 WCrt(ba, CRT_ID_EXT_SYS_CNTL_1, cr50); 1589 1590 delay(100000); 1591 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41)); 1592 delay(100000); 1593 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 1594 (gv->depth == 1) ? 0x01 : 0x0f); 1595 delay(100000); 1596 1597 /* 1598 * M-Parameter of Display FIFO 1599 * This is dependent on the pixel clock and the memory clock. 1600 * The FIFO filling bandwidth is 240 MHz and the FIFO is 96 Byte wide. 1601 * Then the time to fill the FIFO is tfill = (96/240000000) sec, the time 1602 * to empty the FIFO is tempty = (96/pixelclock) sec. 1603 * Then the M parameter maximum is ((tempty-tfill)*cv_memclk-9)/2. 1604 * This seems to be logical, ain't it? 1605 * Remember: We have to use integer arithmetics :( 1606 * Divide by 1000 to prevent overflows. 1607 */ 1608 1609 tfillm = (96 * (cv_memclk/1000))/240000; 1610 1611 switch(gv->depth) { 1612 case 32: 1613 case 24: 1614 temptym = (24 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1615 break; 1616 case 15: 1617 case 16: 1618 temptym = (48 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1619 break; 1620 case 4: 1621 temptym = (192 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1622 break; 1623 default: 1624 temptym = (96 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1625 break; 1626 } 1627 1628 m = (temptym - tfillm - 9) / 2; 1629 if (m < 0) 1630 m = 0; /* prevent underflow */ 1631 m = (m & 0x1f) << 3; 1632 if (m < 0x18) 1633 m = 0x18; 1634 n = 0xff; 1635 1636 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, m); 1637 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, n); 1638 delay(10000); 1639 1640 /* text initialization */ 1641 1642 if (TEXT) { 1643 cv_inittextmode(gp); 1644 } 1645 1646 if (CONSOLE) { 1647 int i; 1648 vgaw(ba, VDAC_ADDRESS_W, 0); 1649 for (i = 0; i < 16; i++) { 1650 vgaw(ba, VDAC_DATA, cvconscolors[i][0]); 1651 vgaw(ba, VDAC_DATA, cvconscolors[i][1]); 1652 vgaw(ba, VDAC_DATA, cvconscolors[i][2]); 1653 } 1654 } 1655 1656 /* Set display enable flag */ 1657 WAttr(ba, 0x33, 0); 1658 1659 /* turn gfx on again */ 1660 gfx_on_off(0, ba); 1661 1662 /* enable interrupts */ 1663 test = RCrt(ba, CRT_ID_BACKWAD_COMP_1); 1664 test |= 0x10; 1665 WCrt(ba, CRT_ID_BACKWAD_COMP_1, test); 1666 1667 test = RCrt(ba, CRT_ID_END_VER_RETR); 1668 test &= ~0x20; 1669 WCrt(ba, CRT_ID_END_VER_RETR, test); 1670 test &= ~0x10; 1671 WCrt(ba, CRT_ID_END_VER_RETR, test); 1672 test |= 0x10; 1673 WCrt(ba, CRT_ID_END_VER_RETR, test); 1674 #ifndef CV_NO_HARDWARE_CURSOR 1675 cv_setup_hwc(gp); 1676 #endif 1677 1678 /* Pass-through */ 1679 cvscreen(0, (volatile char*)ba - 0x02000000); 1680 1681 return (1); 1682 } 1683 1684 1685 void 1686 cv_inittextmode(struct grf_softc *gp) 1687 { 1688 struct grfcvtext_mode *tm = (struct grfcvtext_mode *)gp->g_data; 1689 volatile void *fb; 1690 volatile unsigned char *c; 1691 unsigned char *f, y; 1692 unsigned short z; 1693 1694 fb = gp->g_fbkva; 1695 1696 /* load text font into beginning of display memory. 1697 * Each character cell is 32 bytes long (enough for 4 planes) 1698 * In linear addressing text mode, the memory is organized 1699 * so, that the Bytes of all 4 planes are interleaved. 1700 * 1st byte plane 0, 1st byte plane 1, 1st byte plane 2, 1701 * 1st byte plane 3, 2nd byte plane 0, 2nd byte plane 1,... 1702 * The font is loaded in plane 2. 1703 */ 1704 1705 c = (volatile unsigned char *) fb; 1706 1707 /* clear screen */ 1708 for (z = 0; z < tm->cols * tm->rows * 3; z++) { 1709 *c++ = 0x20; 1710 *c++ = 0x07; 1711 *c++ = 0; 1712 *c++ = 0; 1713 } 1714 1715 c = (volatile unsigned char *)fb + (32 * tm->fdstart * 4 + 2); 1716 f = tm->fdata; 1717 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy) * 4) 1718 for (y = 0; y < tm->fy; y++) { 1719 *c = *f++; 1720 c += 4; 1721 } 1722 1723 /* print out a little init msg */ 1724 c = (volatile unsigned char *)fb + (tm->cols - 6) * 4; 1725 *c++ = 'C'; 1726 *c++ = 0x0a; 1727 c +=2; 1728 *c++ = 'V'; 1729 *c++ = 0x0b; 1730 c +=2; 1731 *c++ = '6'; 1732 *c++ = 0x0c; 1733 c +=2; 1734 *c++ = '4'; 1735 *c++ = 0x0d; 1736 } 1737 1738 1739 static inline void 1740 cv_write_port(unsigned short bits, volatile void *BoardAddr) 1741 { 1742 volatile char *addr; 1743 static unsigned char CVPortBits = 0; /* mirror port bits here */ 1744 1745 addr = (volatile char*)BoardAddr + 0x40001; 1746 if (bits & 0x8000) 1747 CVPortBits |= bits & 0xFF; /* Set bits */ 1748 else { 1749 bits = bits & 0xFF; 1750 bits = (~bits) & 0xFF ; 1751 CVPortBits &= bits; /* Clear bits */ 1752 } 1753 1754 *addr = CVPortBits; 1755 } 1756 1757 1758 /* 1759 * Monitor Switch 1760 * 0 = CyberVision Signal 1761 * 1 = Amiga Signal, 1762 * ba = boardaddr 1763 */ 1764 static inline void 1765 cvscreen(int toggle, volatile void *ba) 1766 { 1767 1768 if (toggle == 1) 1769 cv_write_port (0x10, ba); 1770 else 1771 cv_write_port (0x8010, ba); 1772 } 1773 1774 1775 /* 0 = on, 1= off */ 1776 /* ba= registerbase */ 1777 static inline void 1778 gfx_on_off(int toggle, volatile void *ba) 1779 { 1780 int r; 1781 1782 toggle &= 0x1; 1783 toggle = toggle << 5; 1784 1785 r = RSeq(ba, SEQ_ID_CLOCKING_MODE); 1786 r &= ~0x20; /* set Bit 5 to 0 */ 1787 1788 WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle); 1789 } 1790 1791 1792 #ifndef CV_NO_HARDWARE_CURSOR 1793 1794 static unsigned char cv_hotx = 0, cv_hoty = 0; 1795 static char cv_cursor_on = 0; 1796 1797 /* Hardware Cursor handling routines */ 1798 1799 int 1800 cv_getspritepos(struct grf_softc *gp, struct grf_position *pos) 1801 { 1802 int hi,lo; 1803 volatile void *ba = gp->g_regkva; 1804 1805 hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI); 1806 lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO); 1807 1808 pos->y = (hi << 8) + lo; 1809 hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI); 1810 lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO); 1811 pos->x = (hi << 8) + lo; 1812 return (0); 1813 } 1814 1815 1816 int 1817 cv_setspritepos(struct grf_softc *gp, struct grf_position *pos) 1818 { 1819 volatile void *ba = gp->g_regkva; 1820 short x, y; 1821 static short savex, savey; 1822 short xoff, yoff; 1823 1824 if (pos) { 1825 x = pos->x; 1826 y = pos->y; 1827 savex = x; 1828 savey= y; 1829 } else { /* restore cursor */ 1830 x = savex; 1831 y = savey; 1832 } 1833 x -= cv_hotx; 1834 y -= cv_hoty; 1835 if (x < 0) { 1836 xoff = ((-x) & 0xFE); 1837 x = 0; 1838 } else { 1839 xoff = 0; 1840 } 1841 1842 if (y < 0) { 1843 yoff = ((-y) & 0xFE); 1844 y = 0; 1845 } else { 1846 yoff = 0; 1847 } 1848 1849 WCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8)); 1850 WCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff)); 1851 1852 WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff)); 1853 WCrt(ba, CRT_ID_HWGC_DSTART_X, xoff); 1854 WCrt(ba, CRT_ID_HWGC_DSTART_Y, yoff); 1855 WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8)); 1856 1857 return(0); 1858 } 1859 1860 static inline short 1861 M2I(short val) 1862 { 1863 return ( ((val & 0xff00) >> 8) | ((val & 0xff) << 8)); 1864 } 1865 1866 int 1867 cv_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info) 1868 { 1869 volatile void *ba; 1870 1871 ba = gp->g_regkva; 1872 1873 if (info->set & GRFSPRSET_ENABLE) 1874 info->enable = RCrt(ba, CRT_ID_HWGC_MODE) & 0x01; 1875 1876 if (info->set & GRFSPRSET_POS) 1877 cv_getspritepos (gp, &info->pos); 1878 1879 #if 0 /* XXX */ 1880 volatile void *fb = gp->g_fbkva; 1881 if (info->set & GRFSPRSET_SHAPE) { 1882 u_char image[512], mask[512]; 1883 volatile u_long *hwp; 1884 volative void *fb = gp->g_fbkva; 1885 u_char *imp, *mp; 1886 short row; 1887 info->size.x = 64; 1888 info->size.y = 64; 1889 for (row = 0, hwp = (u_long *)(fb + HWC_OFF), 1890 mp = mask, imp = image; 1891 row < 64; 1892 row++) { 1893 u_long bp10, bp20, bp11, bp21; 1894 bp10 = *hwp++; 1895 bp20 = *hwp++; 1896 bp11 = *hwp++; 1897 bp21 = *hwp++; 1898 M2I (bp10); 1899 M2I (bp20); 1900 M2I (bp11); 1901 M2I (bp21); 1902 *imp++ = (~bp10) & bp11; 1903 *imp++ = (~bp20) & bp21; 1904 *mp++ = (~bp10) | (bp10 & ~bp11); 1905 *mp++ = (~bp20) & (bp20 & ~bp21); 1906 } 1907 copyout (image, info->image, sizeof (image)); 1908 copyout (mask, info->mask, sizeof (mask)); 1909 } 1910 #endif 1911 return(0); 1912 } 1913 1914 1915 void 1916 cv_setup_hwc(struct grf_softc *gp) 1917 { 1918 volatile void *ba = gp->g_regkva; 1919 volatile char *hwc; 1920 int test; 1921 1922 if (gp->g_display.gd_planes <= 4) 1923 cv_cursor_on = 0; /* don't enable hwc in text modes */ 1924 if (cv_cursor_on == 0) 1925 return; 1926 1927 /* reset colour stack */ 1928 #if !defined(__m68k__) 1929 test = RCrt(ba, CRT_ID_HWGC_MODE); 1930 amiga_cpu_sync(); 1931 #else 1932 /* do it in assembler, the above does't seem to work */ 1933 __asm volatile ("moveb #0x45, %1@(0x3d4); \ 1934 moveb %1@(0x3d5),%0" : "=d" (test) : "a" (ba)); 1935 #endif 1936 1937 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 1938 1939 hwc = (volatile char*)ba + CRT_ADDRESS_W; 1940 *hwc = 0; 1941 *hwc = 0; 1942 1943 #if !defined(__m68k__) 1944 test = RCrt(ba, CRT_ID_HWGC_MODE); 1945 amiga_cpu_sync(); 1946 #else 1947 /* do it in assembler, the above does't seem to work */ 1948 __asm volatile ("moveb #0x45, %1@(0x3d4); \ 1949 moveb %1@(0x3d5),%0" : "=d" (test) : "a" (ba)); 1950 #endif 1951 switch (gp->g_display.gd_planes) { 1952 case 8: 1953 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1); 1954 *hwc = 1; 1955 break; 1956 default: 1957 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); 1958 *hwc = 0xff; 1959 *hwc = 0xff; 1960 } 1961 1962 test = HWC_OFF / HWC_SIZE; 1963 WCrt (ba, CRT_ID_HWGC_START_AD_HI, (test >> 8)); 1964 WCrt (ba, CRT_ID_HWGC_START_AD_LO, (test & 0xff)); 1965 1966 WCrt (ba, CRT_ID_HWGC_DSTART_X , 0); 1967 WCrt (ba, CRT_ID_HWGC_DSTART_Y , 0); 1968 1969 WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10); /* Cursor X11 Mode */ 1970 /* 1971 * Put it into Windoze Mode or you'll see sometimes a white stripe 1972 * on the right side (in double clocking modes with a screen bigger 1973 * > 1023 pixels). 1974 */ 1975 WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x00); /* Cursor Windoze Mode */ 1976 1977 WCrt (ba, CRT_ID_HWGC_MODE, 0x01); 1978 } 1979 1980 1981 /* 1982 * This was the reason why you shouldn't use the HWC in the Kernel:( 1983 * Obsoleted now by use of interrupts :-) 1984 */ 1985 1986 #define VerticalRetraceWait(ba) \ 1987 { \ 1988 while (vgar(ba, GREG_INPUT_STATUS1_R) == 0x00) ; \ 1989 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x08) ; \ 1990 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x00) ; \ 1991 } 1992 1993 1994 int 1995 cv_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info) 1996 { 1997 volatile void *ba; 1998 int depth = gp->g_display.gd_planes; 1999 2000 ba = gp->g_regkva; 2001 2002 if (info->set & GRFSPRSET_SHAPE) { 2003 /* 2004 * For an explanation of these weird actions here, see above 2005 * when reading the shape. We set the shape directly into 2006 * the video memory, there's no reason to keep 1k on the 2007 * kernel stack just as template 2008 */ 2009 u_char *image, *mask; 2010 volatile u_short *hwp; 2011 u_char *imp, *mp; 2012 unsigned short row; 2013 2014 #ifdef CV_NO_INT 2015 /* Cursor off */ 2016 WCrt (ba, CRT_ID_HWGC_MODE, 0x00); 2017 2018 /* 2019 * The Trio64 crashes if the cursor data is written 2020 * while the cursor is displayed. 2021 * Sadly, turning the cursor off is not enough. 2022 * What we have to do is: 2023 * 1. Wait for vertical retrace, to make sure no-one 2024 * has moved the cursor in this sync period (because 2025 * another write then would have no effect, argh!). 2026 * 2. Move the cursor off-screen 2027 * 3. Another wait for v. retrace to make sure the cursor 2028 * is really off. 2029 * 4. Write the data, finally. 2030 * (thanks to Harald Koenig for this tip!) 2031 */ 2032 2033 /* 2034 * Remark 06/06/96: Update in interrupt obsoletes this, 2035 * but the warning should stay there! 2036 */ 2037 2038 VerticalRetraceWait(ba); 2039 2040 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, 0x7); 2041 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO, 0xff); 2042 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, 0xff); 2043 WCrt (ba, CRT_ID_HWGC_DSTART_X, 0x3f); 2044 WCrt (ba, CRT_ID_HWGC_DSTART_Y, 0x3f); 2045 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, 0x7); 2046 #endif /* CV_NO_INT */ 2047 2048 if (info->size.y > 64) 2049 info->size.y = 64; 2050 if (info->size.x > 64) 2051 info->size.x = 64; 2052 if (info->size.x < 32) 2053 info->size.x = 32; 2054 2055 image = malloc(HWC_SIZE, M_TEMP, M_WAITOK); 2056 mask = image + HWC_SIZE/2; 2057 2058 copyin(info->image, image, info->size.y * info->size.x / 8); 2059 copyin(info->mask, mask, info->size.y * info->size.x / 8); 2060 2061 #ifdef CV_NO_INT 2062 hwp = (u_short *)(fb +HWC_OFF); 2063 2064 /* This is necessary in order not to crash the board */ 2065 VerticalRetraceWait(ba); 2066 #else /* CV_NO_INT */ 2067 hwp = (u_short *) cv_cursor_storage; 2068 #endif /* CV_NO_INT */ 2069 2070 /* 2071 * setting it is slightly more difficult, because we can't 2072 * force the application to not pass a *smaller* than 2073 * supported bitmap 2074 */ 2075 2076 for (row = 0, mp = mask, imp = image; 2077 row < info->size.y; row++) { 2078 u_short im1, im2, im3, im4, m1, m2, m3, m4; 2079 2080 m1 = ~(*(unsigned short *)mp); 2081 im1 = *(unsigned short *)imp & *(unsigned short *)mp; 2082 mp += 2; 2083 imp += 2; 2084 2085 m2 = ~(*(unsigned short *)mp); 2086 im2 = *(unsigned short *)imp & *(unsigned short *)mp; 2087 mp += 2; 2088 imp += 2; 2089 2090 if (info->size.x > 32) { 2091 m3 = ~(*(unsigned short *)mp); 2092 im3 = *(unsigned short *)imp & *(unsigned short *)mp; 2093 mp += 2; 2094 imp += 2; 2095 m4 = ~(*(unsigned short *)mp); 2096 im4 = *(unsigned short *)imp & *(unsigned short *)mp; 2097 mp += 2; 2098 imp += 2; 2099 } else { 2100 m3 = 0xffff; 2101 im3 = 0; 2102 m4 = 0xffff; 2103 im4 = 0; 2104 } 2105 2106 switch (depth) { 2107 case 8: 2108 *hwp++ = m1; 2109 *hwp++ = im1; 2110 *hwp++ = m2; 2111 *hwp++ = im2; 2112 *hwp++ = m3; 2113 *hwp++ = im3; 2114 *hwp++ = m4; 2115 *hwp++ = im4; 2116 break; 2117 case 15: 2118 case 16: 2119 *hwp++ = M2I(m1); 2120 *hwp++ = M2I(im1); 2121 *hwp++ = M2I(m2); 2122 *hwp++ = M2I(im2); 2123 *hwp++ = M2I(m3); 2124 *hwp++ = M2I(im3); 2125 *hwp++ = M2I(m4); 2126 *hwp++ = M2I(im4); 2127 break; 2128 case 24: 2129 case 32: 2130 *hwp++ = M2I(im1); 2131 *hwp++ = M2I(m1); 2132 *hwp++ = M2I(im2); 2133 *hwp++ = M2I(m2); 2134 *hwp++ = M2I(im3); 2135 *hwp++ = M2I(m3); 2136 *hwp++ = M2I(im4); 2137 *hwp++ = M2I(m4); 2138 break; 2139 } 2140 } 2141 2142 if (depth < 24) { 2143 for (; row < 64; row++) { 2144 *hwp++ = 0xffff; 2145 *hwp++ = 0x0000; 2146 *hwp++ = 0xffff; 2147 *hwp++ = 0x0000; 2148 *hwp++ = 0xffff; 2149 *hwp++ = 0x0000; 2150 *hwp++ = 0xffff; 2151 *hwp++ = 0x0000; 2152 } 2153 } else { 2154 for (; row < 64; row++) { 2155 *hwp++ = 0x0000; 2156 *hwp++ = 0xffff; 2157 *hwp++ = 0x0000; 2158 *hwp++ = 0xffff; 2159 *hwp++ = 0x0000; 2160 *hwp++ = 0xffff; 2161 *hwp++ = 0x0000; 2162 *hwp++ = 0xffff; 2163 } 2164 } 2165 2166 free(image, M_TEMP); 2167 /* cv_setup_hwc(gp); */ 2168 cv_hotx = info->hot.x; 2169 cv_hoty = info->hot.y; 2170 2171 #ifdef CV_NO_INT 2172 /* One must not write twice per vertical blank :-( */ 2173 VerticalRetraceWait(ba); 2174 cv_setspritepos (gp, &info->pos); 2175 #else /* CV_NO_INT */ 2176 cv_setspritepos (gp, &info->pos); 2177 curs_update_flag = 1; 2178 #endif /* CV_NO_INT */ 2179 } 2180 if (info->set & GRFSPRSET_CMAP) { 2181 volatile char *hwc; 2182 2183 /* reset colour stack */ 2184 (void)RCrt(ba, CRT_ID_HWGC_MODE); 2185 amiga_cpu_sync(); 2186 switch (depth) { 2187 case 8: 2188 case 15: 2189 case 16: 2190 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 2191 hwc = (volatile char*)ba + CRT_ADDRESS_W; 2192 *hwc = 0; 2193 break; 2194 case 32: 2195 case 24: 2196 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 2197 hwc = (volatile char*)ba + CRT_ADDRESS_W; 2198 *hwc = 0; 2199 *hwc = 0; 2200 break; 2201 } 2202 2203 (void)RCrt(ba, CRT_ID_HWGC_MODE); 2204 amiga_cpu_sync(); 2205 switch (depth) { 2206 case 8: 2207 WCrt (ba, CRT_ID_HWGC_BG_STACK, 1); 2208 hwc = (volatile char*)ba + CRT_ADDRESS_W; 2209 *hwc = 1; 2210 break; 2211 case 15: 2212 case 16: 2213 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); 2214 hwc = (volatile char*)ba + CRT_ADDRESS_W; 2215 *hwc = 0xff; 2216 break; 2217 case 32: 2218 case 24: 2219 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); 2220 hwc = (volatile char*)ba + CRT_ADDRESS_W; 2221 *hwc = 0xff; 2222 *hwc = 0xff; 2223 break; 2224 } 2225 } 2226 2227 if (info->set & GRFSPRSET_ENABLE) { 2228 if (info->enable) { 2229 cv_cursor_on = 1; 2230 cv_setup_hwc(gp); 2231 /* WCrt(ba, CRT_ID_HWGC_MODE, 0x01); */ 2232 } else 2233 WCrt(ba, CRT_ID_HWGC_MODE, 0x00); 2234 } 2235 if (info->set & GRFSPRSET_POS) 2236 cv_setspritepos(gp, &info->pos); 2237 if (info->set & GRFSPRSET_HOT) { 2238 2239 cv_hotx = info->hot.x; 2240 cv_hoty = info->hot.y; 2241 cv_setspritepos (gp, &info->pos); 2242 } 2243 return(0); 2244 } 2245 2246 2247 int 2248 cv_getspritemax (struct grf_softc *gp, struct grf_position *pos) 2249 { 2250 2251 pos->x = 64; 2252 pos->y = 64; 2253 return(0); 2254 } 2255 2256 #endif /* !CV_NO_HARDWARE_CURSOR */ 2257 2258 #if NWSDISPLAY > 0 2259 2260 static void 2261 cv_wscursor(void *c, int on, int row, int col) 2262 { 2263 struct rasops_info *ri; 2264 struct vcons_screen *scr; 2265 struct grf_softc *gp; 2266 volatile void *ba; 2267 int offs; 2268 2269 ri = c; 2270 scr = ri->ri_hw; 2271 gp = scr->scr_cookie; 2272 ba = gp->g_regkva; 2273 2274 if ((ri->ri_flg & RI_CURSOR) && !on) { 2275 /* cursor was visible, but we want to remove it */ 2276 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/ 2277 ri->ri_flg &= ~RI_CURSOR; 2278 } 2279 2280 ri->ri_crow = row; 2281 ri->ri_ccol = col; 2282 2283 if (on) { 2284 /* move cursor to new location */ 2285 if (!(ri->ri_flg & RI_CURSOR)) { 2286 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/ 2287 ri->ri_flg |= RI_CURSOR; 2288 } 2289 offs = gp->g_rowoffset[row] + col; 2290 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, offs & 0xff); 2291 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, offs >> 8); 2292 } 2293 } 2294 2295 static void cv_wsputchar(void *c, int row, int col, u_int ch, long attr) 2296 { 2297 struct rasops_info *ri; 2298 struct vcons_screen *scr; 2299 struct grf_softc *gp; 2300 volatile unsigned char *cp; 2301 2302 ri = c; 2303 scr = ri->ri_hw; 2304 gp = scr->scr_cookie; 2305 cp = gp->g_fbkva; 2306 cp += (gp->g_rowoffset[row] + col) << 2; 2307 *cp++ = ch; 2308 *cp = attr; 2309 } 2310 2311 static void 2312 cv_wscopycols(void *c, int row, int srccol, int dstcol, int ncols) 2313 { 2314 struct rasops_info *ri; 2315 struct vcons_screen *scr; 2316 struct grf_softc *gp; 2317 volatile uint16_t *src, *dst; 2318 2319 KASSERT(ncols > 0); 2320 ri = c; 2321 scr = ri->ri_hw; 2322 gp = scr->scr_cookie; 2323 src = dst = gp->g_fbkva; 2324 src += (gp->g_rowoffset[row] + srccol) << 1; 2325 dst += (gp->g_rowoffset[row] + dstcol) << 1; 2326 if (src < dst) { 2327 /* need to copy backwards */ 2328 src += (ncols - 1) << 1; 2329 dst += (ncols - 1) << 1; 2330 while (ncols--) { 2331 *dst = *src; 2332 src -= 2; 2333 dst -= 2; 2334 } 2335 } else 2336 while (ncols--) { 2337 *dst = *src; 2338 src += 2; 2339 dst += 2; 2340 } 2341 } 2342 2343 static void 2344 cv_wserasecols(void *c, int row, int startcol, int ncols, long fillattr) 2345 { 2346 struct rasops_info *ri; 2347 struct vcons_screen *scr; 2348 struct grf_softc *gp; 2349 volatile uint16_t *cp; 2350 uint16_t val; 2351 2352 ri = c; 2353 scr = ri->ri_hw; 2354 gp = scr->scr_cookie; 2355 cp = gp->g_fbkva; 2356 val = 0x2000 | fillattr; 2357 cp += (gp->g_rowoffset[row] + startcol) << 1; 2358 while (ncols--) { 2359 *cp = val; 2360 cp += 2; 2361 } 2362 } 2363 2364 static void 2365 cv_wscopyrows(void *c, int srcrow, int dstrow, int nrows) 2366 { 2367 struct rasops_info *ri; 2368 struct vcons_screen *scr; 2369 struct grf_softc *gp; 2370 volatile uint16_t *src, *dst; 2371 int n; 2372 2373 KASSERT(nrows > 0); 2374 ri = c; 2375 scr = ri->ri_hw; 2376 gp = scr->scr_cookie; 2377 src = dst = gp->g_fbkva; 2378 n = ri->ri_cols * nrows; 2379 if (src < dst) { 2380 /* need to copy backwards */ 2381 src += gp->g_rowoffset[srcrow + nrows] << 1; 2382 dst += gp->g_rowoffset[dstrow + nrows] << 1; 2383 while (n--) { 2384 src -= 2; 2385 dst -= 2; 2386 *dst = *src; 2387 } 2388 } else { 2389 src += gp->g_rowoffset[srcrow] << 1; 2390 dst += gp->g_rowoffset[dstrow] << 1; 2391 while (n--) { 2392 *dst = *src; 2393 src += 2; 2394 dst += 2; 2395 } 2396 } 2397 } 2398 2399 static void 2400 cv_wseraserows(void *c, int row, int nrows, long fillattr) 2401 { 2402 struct rasops_info *ri; 2403 struct vcons_screen *scr; 2404 struct grf_softc *gp; 2405 volatile uint16_t *cp; 2406 int n; 2407 uint16_t val; 2408 2409 ri = c; 2410 scr = ri->ri_hw; 2411 gp = scr->scr_cookie; 2412 cp = gp->g_fbkva; 2413 val = 0x2000 | fillattr; 2414 cp += gp->g_rowoffset[row] << 1; 2415 n = ri->ri_cols * nrows; 2416 while (n--) { 2417 *cp = val; 2418 cp += 2; 2419 } 2420 } 2421 2422 static int 2423 cv_wsallocattr(void *c, int fg, int bg, int flg, long *attr) 2424 { 2425 2426 /* XXX color support? */ 2427 *attr = (flg & WSATTR_REVERSE) ? 0x70 : 0x07; 2428 if (flg & WSATTR_UNDERLINE) *attr = 0x01; 2429 if (flg & WSATTR_HILIT) *attr |= 0x08; 2430 if (flg & WSATTR_BLINK) *attr |= 0x80; 2431 return 0; 2432 } 2433 2434 /* our font does not support unicode extensions */ 2435 static int 2436 cv_wsmapchar(void *c, int ch, unsigned int *cp) 2437 { 2438 2439 if (ch > 0 && ch < 256) { 2440 *cp = ch; 2441 return 5; 2442 } 2443 *cp = ' '; 2444 return 0; 2445 } 2446 2447 #endif /* NWSDISPLAY > 0 */ 2448 2449 #endif /* NGRFCV */ 2450