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