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