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