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