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