diff options
Diffstat (limited to 'sys/arch/amiga/dev/grf_cv.c')
-rw-r--r-- | sys/arch/amiga/dev/grf_cv.c | 636 |
1 files changed, 428 insertions, 208 deletions
diff --git a/sys/arch/amiga/dev/grf_cv.c b/sys/arch/amiga/dev/grf_cv.c index 1dc6fddfc17..034cd957ae7 100644 --- a/sys/arch/amiga/dev/grf_cv.c +++ b/sys/arch/amiga/dev/grf_cv.c @@ -1,5 +1,5 @@ -/* $OpenBSD: grf_cv.c,v 1.14 1997/01/16 09:24:13 niklas Exp $ */ -/* $NetBSD: grf_cv.c,v 1.20 1996/12/23 09:10:05 veego Exp $ */ +/* $OpenBSD: grf_cv.c,v 1.15 1997/09/18 13:39:49 niklas Exp $ */ +/* $NetBSD: grf_cv.c,v 1.24 1997/07/30 11:05:55 veego Exp $ */ /* * Copyright (c) 1995 Michael Teske @@ -16,7 +16,7 @@ * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Ezra Story, by Kari - * Mettinen and by Bernd Ernesti. + * Mettinen, Michael Teske and by Bernd Ernesti. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * @@ -39,18 +39,12 @@ * * Modified for CV64 from * Kari Mettinen's Cirrus driver by Michael Teske 10/95 - * For questions mail me at teske@mail.desy.de * * Thanks to Tekelec Airtronic for providing me with a S3 Trio64 documentation. * Thanks to Bernd 'the fabulous bug-finder' Ernesti for bringing my messy * source to NetBSD style :) - * - * TODO: - * Bugfree Hardware Cursor support. - * The HWC routines provided here are buggy in 16/24 bit - * and may cause a Vertical Bar Crash of the Trio64. - * On the other hand it's better to put the routines in the Xserver, - * so please _don't_ put CV_HARDWARE_CURSOR in your config file. + * Thanks to Harald Koenig for providing information about undocumented + * Trio64 Bugs. */ #include <sys/param.h> @@ -59,10 +53,16 @@ #include <sys/device.h> #include <sys/malloc.h> #include <sys/systm.h> +#include <sys/syslog.h> + #include <machine/cpu.h> +#include <machine/intr.h> + #include <dev/cons.h> + #include <amiga/dev/itevar.h> #include <amiga/amiga/device.h> +#include <amiga/amiga/isr.h> #include <amiga/dev/grfioctl.h> #include <amiga/dev/grfvar.h> #include <amiga/dev/grf_cvreg.h> @@ -72,8 +72,9 @@ int grfcvmatch __P((struct device *, void *, void *)); void grfcvattach __P((struct device *, struct device *, void *)); int grfcvprint __P((void *, const char *)); -static int cv_has_4mb __P((volatile caddr_t)); -static unsigned short cv_compute_clock __P((unsigned long)); +int cvintr __P((void *)); +int cv_has_4mb __P((volatile caddr_t)); +unsigned short cv_compute_clock __P((unsigned long)); void cv_boardinit __P((struct grf_softc *)); int cv_getvmode __P((struct grf_softc *, struct grfvideo_mode *)); int cv_setvmode __P((struct grf_softc *, unsigned int)); @@ -87,20 +88,27 @@ int cv_toggle __P((struct grf_softc *)); int cv_mondefok __P((struct grfvideo_mode *)); int cv_load_mon __P((struct grf_softc *, struct grfcvtext_mode *)); void cv_inittextmode __P((struct grf_softc *)); -static inline void cv_write_port __P((unsigned short, volatile caddr_t)); -static inline void cvscreen __P((int, volatile caddr_t)); -static inline void gfx_on_off __P((int, volatile caddr_t)); +static __inline void cv_write_port __P((unsigned short, volatile caddr_t)); +static __inline void cvscreen __P((int, volatile caddr_t)); +static __inline void gfx_on_off __P((int, volatile caddr_t)); -#ifdef CV_HARDWARE_CURSOR +#ifndef CV_NO_HARDWARE_CURSOR int cv_getspritepos __P((struct grf_softc *, struct grf_position *)); int cv_setspritepos __P((struct grf_softc *, struct grf_position *)); +static __inline short M2I __P((short)); int cv_getspriteinfo __P((struct grf_softc *,struct grf_spriteinfo *)); -void cv_setup_hwc __P((struct grf_softc *, - unsigned char, unsigned char, unsigned char, unsigned char, - const unsigned long *)); +void cv_setup_hwc __P((struct grf_softc *)); int cv_setspriteinfo __P((struct grf_softc *,struct grf_spriteinfo *)); int cv_getspritemax __P((struct grf_softc *,struct grf_position *)); -#endif /* CV_HARDWARE_CURSOR */ +#endif /* !CV_NO_HARDWARE_CURSOR */ + +/* + * Extension to grf_softc for interrupt support + */ +struct grf_cv_softc { + struct grf_softc gcs_sc; + struct isr gcs_isr; +}; /* Graphics display definitions. * These are filled by 'grfconfig' using GRFIOCSETMON. @@ -137,8 +145,8 @@ extern unsigned char S3FONT[]; * (Internally, we still have to use hvalues/8!) */ struct grfcvtext_mode cvconsole_mode = { - {255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8, - 481, 521, 491, 493, 525}, + { 255, "", 25000000, 640, 480, 4, 640/8, 680/8, 768/8, 800/8, + 481, 521, 491, 493, 525 }, 8, S3FONTY, 80, 480 / S3FONTY, S3FONT, 32, 255 }; @@ -250,7 +258,7 @@ long cv_memclk = 50000000; /* standard driver stuff */ struct cfattach grfcv_ca = { - sizeof(struct grf_softc), grfcvmatch, grfcvattach + sizeof(struct grf_cv_softc), grfcvmatch, grfcvattach }; struct cfdriver grfcv_cd = { @@ -258,6 +266,85 @@ struct cfdriver grfcv_cd = { }; static struct cfdata *grfcv_cfdata; +#define CV_INT_NUM 6 /* CV interrupt Level: #2 or #6 */ +#define CV_ULCURSOR 1 /* Underlined Cursor in textmode */ + +#ifndef CV_NO_HARDWARE_CURSOR + +#define HWC_OFF (cv_fbsize - 1024*2) +#define HWC_SIZE 1024 + +static unsigned short cv_cursor_storage[HWC_SIZE/2]; +static short curs_update_flag = 0; +#endif /* !CV_NO_HARDWARE_CURSOR */ + +/* + * Interrupt handler + * This is used for updating the cursor shape (because it _must not_ + * be changed while cursor is displayed) + * and maybe later to avoid busy waiting + * for Vertical Blank and/or gfx engine busy + */ +int +cvintr(arg) + void * arg; +{ +#ifndef CV_NO_HARDWARE_CURSOR + register unsigned long *csrc, *cdest; + int i; +#endif /* !CV_NO_HARDWARE_CURSOR */ + struct grf_softc *gp = arg; + volatile caddr_t ba = gp->g_regkva; + unsigned char test; + unsigned char cridx; /* Save the cr Register index */ + + if (gp == NULL) + return 0; + + test = vgar(ba, GREG_INPUT_STATUS0_R); + + if (test & 0x80) { /* VR int pending */ + /* Save old CR index */ + cridx = vgar (ba, CRT_ADDRESS); + +#if 0 + test = RCrt(ba, CRT_ID_END_VER_RETR); + /* Clear int (bit 4) */ + test &= ~0x10; + WCrt(ba, CRT_ID_END_VER_RETR, test); +#else + vgaw(ba, CRT_ADDRESS, CRT_ID_END_VER_RETR); + asm volatile ("bclr #4,%0@(0x3d5);nop" : : "a" (ba)); +#endif + +#ifndef CV_NO_HARDWARE_CURSOR + /* update the hardware cursor, if necessary */ + if (curs_update_flag) { + csrc = (unsigned long *)cv_cursor_storage; + cdest = (unsigned long *)((volatile char *)gp->g_fbkva + + HWC_OFF); + for (i = 0; i < HWC_SIZE / sizeof(long); i++) + *cdest++ = *csrc++; + curs_update_flag = 0; + } + /* Reenable int */ +#if 0 + test |= 0x10; + WCrt(ba, CRT_ID_END_VER_RETR, test); +#else + /* I don't trust the optimizer here... */ + asm volatile ("bset #4,%0@(0x3d5);nop" : : "a" (ba)); +#endif + cv_setspritepos (gp, NULL); + + /* Restore the old CR index */ + vgaw(ba, CRT_ADDRESS, cridx); + __asm volatile ("nop"); +#endif /* !CV_NO_HARDWARE_CURSOR */ + return (1); + } + return (0); +} /* * Get frambuffer memory size. @@ -265,7 +352,7 @@ static struct cfdata *grfcv_cfdata; * so we have to do it this way. * Return 0 for 2MB, 1 for 4MB */ -static int +int cv_has_4mb(fb) volatile caddr_t fb; { @@ -301,7 +388,7 @@ grfcvmatch(pdp, match, auxp) #ifdef CV64CONSOLE struct cfdata *cfp = match; static int cvcons_unit = -1; -#endif +#endif /* CV64CONSOLE */ struct zbus_args *zap; zap = auxp; @@ -309,7 +396,7 @@ grfcvmatch(pdp, match, auxp) if (amiga_realconfig == 0) #ifdef CV64CONSOLE if (cvcons_unit != -1) -#endif +#endif /* CV64CONSOLE */ return (0); /* Lets be Paranoid: Test man and prod id */ @@ -323,7 +410,7 @@ grfcvmatch(pdp, match, auxp) cvcons_unit = cfp->cf_unit; grfcv_cfdata = cfp; } -#endif +#endif /* CV64CONSOLE */ return (1); } @@ -333,9 +420,10 @@ grfcvattach(pdp, dp, auxp) struct device *pdp, *dp; void *auxp; { - static struct grf_softc congrf; + static struct grf_cv_softc congrf; struct zbus_args *zap; struct grf_softc *gp; + struct grf_cv_softc *gcp; static char attachflag = 0; zap = auxp; @@ -346,28 +434,32 @@ grfcvattach(pdp, dp, auxp) */ if (dp == NULL) /* console init */ - gp = &congrf; + gcp = &congrf; else - gp = (struct grf_softc *)dp; + gcp = (struct grf_cv_softc *)dp; - if (dp != NULL && congrf.g_regkva != 0) { + gp = &gcp->gcs_sc; + + if (dp != NULL && congrf.gcs_sc.g_regkva != 0) { /* * inited earlier, just copy (not device struct) */ printf("\n"); -#ifdef CV64CONSOLE - bcopy(&congrf.g_display, &gp->g_display, - (char *) &gp[1] - (char *) &gp->g_display); -#else - gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000; - gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000; - - gp->g_unit = GRF_CV64_UNIT; - gp->g_mode = cv_mode; - gp->g_conpri = grfcv_cnprobe(); - gp->g_flags = GF_ALIVE; -#endif + bcopy(&congrf.gcs_sc.g_display, &gp->g_display, + (char *) &gcp->gcs_isr - (char *) &gp->g_display); + + /* ... and transfer the isr */ + gcp->gcs_isr.isr_ipl = CV_INT_NUM; +#if CV_INT_NUM == 6 + gcp->gcs_isr.isr_mapped_ipl = IPL_TTY; +#endif /* CV_INT_NUM == 6 */ + gcp->gcs_isr.isr_intr = cvintr; + gcp->gcs_isr.isr_arg = (void *)gp; + + /* First add new isr */ + add_isr(&gcp->gcs_isr); + remove_isr(&congrf.gcs_isr); } else { gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000; gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000; @@ -377,13 +469,22 @@ grfcvattach(pdp, dp, auxp) gp->g_conpri = grfcv_cnprobe(); gp->g_flags = GF_ALIVE; + /* add Interrupt Handler */ + gcp->gcs_isr.isr_ipl = CV_INT_NUM; +#if CV_INT_NUM == 6 + gcp->gcs_isr.isr_mapped_ipl = IPL_TTY; +#endif /* CV_INT_NUM == 6 */ + gcp->gcs_isr.isr_intr = cvintr; + gcp->gcs_isr.isr_arg = (void *)gp; + add_isr(&gcp->gcs_isr); + /* wakeup the board */ cv_boardinit(gp); #ifdef CV64CONSOLE grfcv_iteinit(gp); (void)cv_load_mon(gp, &cvconsole_mode); -#endif +#endif /* CV64CONSOLE */ } /* @@ -391,7 +492,8 @@ grfcvattach(pdp, dp, auxp) */ if (amiga_config_found(grfcv_cfdata, &gp->g_device, gp, grfcvprint)) { if (dp != NULL) - printf("grfcv: CyberVision64 with %dMB being used\n", cv_fbsize/0x100000); + printf("grfcv: CyberVision64 with %dMB being used\n", + cv_fbsize/0x100000); attachflag = 1; } else { if (!attachflag) @@ -421,7 +523,7 @@ grfcvprint(auxp, pnp) * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13 */ -static unsigned short +unsigned short cv_compute_clock(freq) unsigned long freq; { @@ -492,6 +594,17 @@ cv_boardinit(gp) WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48); /* unlock S3 VGA regs */ WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5); /* unlock syscontrol */ + /* + * The default board interrupt is #6. + * Set the roxxler register to use interrupt #2, not #6. + */ +#if CV_INT_NUM == 2 + cv_write_port(0x8080, ba - 0x02000000); +#endif /* CV_INT_NUM == 2 */ + + /* Enable board interrupts */ + cv_write_port(0x8008, ba - 0x02000000); + test = RCrt(ba, CRT_ID_SYSTEM_CONFIG); test = test | 0x01; /* enable enhaced register access */ test = test & 0xEF; /* clear bit 4, 0 wait state */ @@ -504,8 +617,8 @@ cv_boardinit(gp) */ vgaw(ba, ECR_ADV_FUNC_CNTL, 0x31); - /* enable cpu acess, color mode, high 64k page */ - vgaw(ba, GREG_MISC_OUTPUT_W, 0x23); + /* enable color mode (bit0), cpu acess (bit1), high 64k page (bit5) */ + vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); /* Cpu base addr */ WCrt(ba, CRT_ID_EXT_SYS_CNTL_4, 0x00); @@ -752,7 +865,6 @@ cv_getvmode(gp, vm) /* adjust internal values to pixel values */ vm->hblank_start *= 8; - vm->hblank_stop *= 8; vm->hsync_start *= 8; vm->hsync_stop *= 8; vm->htotal *= 8; @@ -812,11 +924,11 @@ cv_mode(gp, cmd, arg, a2, a3) case GM_GRFOFF: #ifndef CV64CONSOLE - cvscreen(1, gp->g_regkva - 0x02000000) -#else + cvscreen(1, gp->g_regkva - 0x02000000); +#else /* !CV64CONSOLE */ cv_load_mon(gp, &cvconsole_mode); ite_reinit(gp->g_itedev); -#endif +#endif /* !CV64CONSOLE */ return (0); case GM_GRFCONFIG: @@ -854,7 +966,7 @@ cv_ioctl (gp, cmd, data) void *data; { switch (cmd) { -#ifdef CV_HARDWARE_CURSOR +#ifndef CV_NO_HARDWARE_CURSOR case GRFIOCGSPRITEPOS: return(cv_getspritepos (gp, (struct grf_position *) data)); @@ -869,14 +981,14 @@ cv_ioctl (gp, cmd, data) case GRFIOCGSPRITEMAX: return(cv_getspritemax (gp, (struct grf_position *) data)); -#else /* CV_HARDWARE_CURSOR */ +#else /* !CV_NO_HARDWARE_CURSOR */ case GRFIOCGSPRITEPOS: case GRFIOCSSPRITEPOS: case GRFIOCSSPRITEINF: case GRFIOCGSPRITEINF: case GRFIOCGSPRITEMAX: break; -#endif /* CV_HARDWARE_CURSOR */ +#endif /* !CV_NO_HARDWARE_CURSOR */ case GRFIOCGETCMAP: return (cv_getcmap (gp, (struct grf_colormap *) data)); @@ -915,7 +1027,6 @@ cv_setmonitor(gp, gv) if (gv->mode_num == 255) { bcopy(gv, &cvconsole_mode.gv, sizeof(struct grfvideo_mode)); cvconsole_mode.gv.hblank_start /= 8; - cvconsole_mode.gv.hblank_stop /= 8; cvconsole_mode.gv.hsync_start /= 8; cvconsole_mode.gv.hsync_stop /= 8; cvconsole_mode.gv.htotal /= 8; @@ -936,7 +1047,7 @@ cv_setmonitor(gp, gv) */ if (gp->g_flags & GF_GRFON) if (md == monitor_current) { - printf("grf_cv: Changing the used mode not allowed!\n"); + printf("grfcv: Changing the used mode not allowed!\n"); return (EINVAL); } @@ -945,7 +1056,6 @@ cv_setmonitor(gp, gv) /* adjust pixel oriented values to internal rep. */ md->hblank_start /= 8; - md->hblank_stop /= 8; md->hsync_start /= 8; md->hsync_stop /= 8; md->htotal /= 8; @@ -1091,13 +1201,13 @@ cv_mondefok(gv) #endif break; default: - printf("grf_cv: Illegal depth in mode %d\n", + printf("grfcv: Illegal depth in mode %d\n", (int) gv->mode_num); return (0); } if (gv->pixel_clock > maxpix) { - printf("grf_cv: Pixelclock too high in mode %d\n", + printf("grfcv: Pixelclock too high in mode %d\n", (int) gv->mode_num); return (0); } @@ -1112,6 +1222,11 @@ cv_mondefok(gv) } } + if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) { + printf("grfcv: sync-on-green is not supported\n"); + return (0); + } + return (1); } @@ -1127,12 +1242,13 @@ cv_load_mon(gp, md) unsigned short mnr; unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT; - char LACE, DBLSCAN, TEXT, CONSOLE; - int uplim, lowlim; int cr50, sr15, sr18, clock_mode, test; int m, n; /* For calc'ing display FIFO */ int tfillm, temptym; /* FIFO fill and empty mclk's */ int hmul; /* Multiplier for hor. Values */ + unsigned char hvsync_pulse; + char TEXT, CONSOLE; + /* identity */ gv = &md->gv; @@ -1140,13 +1256,18 @@ cv_load_mon(gp, md) CONSOLE = (gv->mode_num == 255); if (!cv_mondefok(gv)) { - printf("grfcv: The monitor definition is illegal.\n"); - printf("grfcv: See the manpage of grfconfig for more informations\n"); + printf("grfcv: Monitor definition not ok\n"); return (0); } + ba = gp->g_regkva; fb = gp->g_fbkva; + /* Disable Interrupts */ + test = RCrt(ba, CRT_ID_BACKWAD_COMP_1); + test &= ~0x10; + WCrt(ba, CRT_ID_BACKWAD_COMP_1, test); + /* turn gfx off, don't mess up the display */ gfx_on_off(1, ba); @@ -1171,24 +1292,24 @@ cv_load_mon(gp, md) /* get display mode parameters */ switch (gv->depth) { - case 15: - case 16: - hmul = 2; - break; - default: - hmul = 1; - break; + case 15: + case 16: + hmul = 2; + break; + default: + hmul = 1; + break; } HBS = gv->hblank_start * hmul; - HBE = gv->hblank_stop * hmul; HSS = gv->hsync_start * hmul; HSE = gv->hsync_stop * hmul; - HT = gv->htotal*hmul - 5; + HBE = gv->htotal * hmul - 6; + HT = gv->htotal * hmul - 5; VBS = gv->vblank_start - 1; VSS = gv->vsync_start; VSE = gv->vsync_stop; - VBE = gv->vblank_stop; + VBE = gv->vtotal - 3; VT = gv->vtotal - 2; /* Disable enhanced Mode for text display */ @@ -1201,17 +1322,36 @@ cv_load_mon(gp, md) HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/ VDE = gv->disp_height - 1; - /* figure out whether lace or dblscan is needed */ - - uplim = gv->disp_height + (gv->disp_height / 4); - lowlim = gv->disp_height - (gv->disp_height / 4); - LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0; - DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0; - /* adjustments */ + if (gv->disp_flags & GRF_FLAGS_LACE) { + VDE = VDE / 2; + VBS = VBS / 2; + VSS = VSS / 2; + VSE = VSE / 2; + VBE = VBE / 2; + VT = VT / 2; + } - if (LACE) - VDE /= 2; + /* Horizontal/Vertical Sync Pulse */ + /* + * GREG_MISC_OUTPUT_W Register: + * bit description (0/1) + * 0 Monochrome/Color emulation + * 1 Disable/Enable access of the display memory from the CPU + * 5 Select the low/high 64K page of memory + * 6 Select a positive/negative horizontal retrace sync pulse + * 7 Select a positive/negative vertical retrace sync pulse + */ + hvsync_pulse = vgar(ba, GREG_MISC_OUTPUT_R); + if (gv->disp_flags & GRF_FLAGS_PHSYNC) + hvsync_pulse &= ~0x40; + else + hvsync_pulse |= 0x40; + if (gv->disp_flags & GRF_FLAGS_PVSYNC) + hvsync_pulse &= ~0x80; + else + hvsync_pulse |= 0x80; + vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse); /* GFX hardware cursor off */ WCrt(ba, CRT_ID_HWGC_MODE, 0x00); @@ -1269,7 +1409,7 @@ cv_load_mon(gp, md) WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40 | /* TEXT ? 0x00 ??? */ - (DBLSCAN ? 0x80 : 0x00) | + ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) | ((VBS & 0x200) ? 0x20 : 0x00) | (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); @@ -1278,13 +1418,13 @@ cv_load_mon(gp, md) /* text cursor */ if (TEXT) { -#if 1 +#if CV_ULCURSOR WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2); WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1); -#else +#else /* CV_ULCURSOR */ WCrt(ba, CRT_ID_CURSOR_START, 0x00); WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f); -#endif +#endif /* CV_ULCURSOR */ WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f); WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); @@ -1302,7 +1442,8 @@ cv_load_mon(gp, md) WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2); - WCrt(ba, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00)); + WCrt(ba, CRT_ID_LACE_CONTROL, + ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x20 : 0x00)); WGfx(ba, GCT_ID_GRAPHICS_MODE, ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40)); @@ -1318,9 +1459,9 @@ cv_load_mon(gp, md) WCrt(ba, CRT_ID_BACKWAD_COMP_2, (test | 0x20)); sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); - sr15 &= 0xef; + sr15 &= ~0x10; sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL); - sr18 &= 0x7f; + sr18 &= ~0x80; clock_mode = 0x00; cr50 = 0x00; @@ -1471,12 +1612,28 @@ cv_load_mon(gp, md) } } - /* Some kind of Magic */ + /* Set display enable flag */ WAttr(ba, 0x33, 0); /* turn gfx on again */ gfx_on_off(0, ba); + /* enable interrupts */ + test = RCrt(ba, CRT_ID_BACKWAD_COMP_1); + test |= 0x10; + WCrt(ba, CRT_ID_BACKWAD_COMP_1, test); + + test = RCrt(ba, CRT_ID_END_VER_RETR); + test &= ~0x20; + WCrt(ba, CRT_ID_END_VER_RETR, test); + test &= ~0x10; + WCrt(ba, CRT_ID_END_VER_RETR, test); + test |= 0x10; + WCrt(ba, CRT_ID_END_VER_RETR, test); +#ifndef CV_NO_HARDWARE_CURSOR + cv_setup_hwc(gp); +#endif + /* Pass-through */ cvscreen(0, ba - 0x02000000); @@ -1539,7 +1696,7 @@ cv_inittextmode(gp) } -static inline void +static __inline void cv_write_port(bits, BoardAddr) unsigned short bits; volatile caddr_t BoardAddr; @@ -1566,7 +1723,7 @@ cv_write_port(bits, BoardAddr) * 1 = Amiga Signal, * ba = boardaddr */ -static inline void +static __inline void cvscreen(toggle, ba) int toggle; volatile caddr_t ba; @@ -1581,7 +1738,7 @@ cvscreen(toggle, ba) /* 0 = on, 1= off */ /* ba= registerbase */ -static inline void +static __inline void gfx_on_off(toggle, ba) int toggle; volatile caddr_t ba; @@ -1592,46 +1749,55 @@ gfx_on_off(toggle, ba) toggle = toggle << 5; r = RSeq(ba, SEQ_ID_CLOCKING_MODE); - r &= 0xdf; /* set Bit 5 to 0 */ + r &= ~0x20; /* set Bit 5 to 0 */ WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle); } - -#ifdef CV_HARDWARE_CURSOR +#ifndef CV_NO_HARDWARE_CURSOR static unsigned char cv_hotx = 0, cv_hoty = 0; +static char cv_cursor_on = 0; /* Hardware Cursor handling routines */ int -cv_getspritepos (gp, pos) +cv_getspritepos(gp, pos) struct grf_softc *gp; struct grf_position *pos; { int hi,lo; volatile caddr_t ba = gp->g_regkva; - hi = RCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI); - lo = RCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO); + hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI); + lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO); pos->y = (hi << 8) + lo; - hi = RCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI); - lo = RCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO); + hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI); + lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO); pos->x = (hi << 8) + lo; return (0); } - int -cv_setspritepos (gp, pos) +cv_setspritepos(gp, pos) struct grf_softc *gp; struct grf_position *pos; { volatile caddr_t ba = gp->g_regkva; - short x = pos->x, y = pos->y; + short x, y; + static short savex, savey; short xoff, yoff; + if (pos) { + x = pos->x; + y = pos->y; + savex = x; + savey= y; + } else { /* restore cursor */ + x = savex; + y = savey; + } x -= cv_hotx; y -= cv_hoty; if (x < 0) { @@ -1648,37 +1814,26 @@ cv_setspritepos (gp, pos) yoff = 0; } - WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8)); - WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff)); + WCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8)); + WCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff)); - WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff)); - WCrt (ba, CRT_ID_HWGC_DSTART_X, xoff); - WCrt (ba, CRT_ID_HWGC_DSTART_Y, yoff); - WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8)); + WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff)); + WCrt(ba, CRT_ID_HWGC_DSTART_X, xoff); + WCrt(ba, CRT_ID_HWGC_DSTART_Y, yoff); + WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8)); - return(0); + return (0); } -static inline short -M2I(short val) { - asm volatile (" rorw #8,%0 ; \ - swap %0 ; \ - rorw #8,%0 ; " : "=d" (val) : "0" (val)); - return (val); +static __inline short +M2I(val) + short val; +{ + return (((val & 0xff00) >> 8) | ((val & 0xff) << 8)); } -#define M2INS(val) \ - asm volatile (" rorw #8,%0 ; \ - swap %0 ; \ - rorw #8,%0 ; \ - swap %0 ; " : "=d" (val) : "0" (val)); - -#define HWC_OFF (cv_fbsize - 1024*2) -#define HWC_SIZE 1024 - - int -cv_getspriteinfo (gp, info) +cv_getspriteinfo(gp, info) struct grf_softc *gp; struct grf_spriteinfo *info; { @@ -1728,40 +1883,52 @@ cv_getspriteinfo (gp, info) void -cv_setup_hwc (gp, col1, col2, hsx, hsy, data) +cv_setup_hwc(gp) struct grf_softc *gp; - unsigned char col1; - unsigned char col2; - unsigned char hsx; - unsigned char hsy; - const unsigned long *data; { volatile caddr_t ba = gp->g_regkva; - unsigned long *c = (unsigned long *)(gp->g_fbkva + HWC_OFF); - const unsigned long *s = data; + volatile caddr_t hwc; int test; - short x = (HWC_SIZE / (4*4)) - 1; - /* copy only, if there is a data pointer. */ - if (data) do { - *c++ = *s++; - *c++ = *s++; - *c++ = *s++; - *c++ = *s++; - } while (x-- > 0); + if (gp->g_display.gd_planes <= 4) + cv_cursor_on = 0; /* don't enable hwc in text modes */ + if (cv_cursor_on == 0) + return; /* reset colour stack */ +#if 0 test = RCrt(ba, CRT_ID_HWGC_MODE); - asm volatile("nop"); - WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); - WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); + __asm volatile ("nop"); +#else + /* do it in assembler, the above does't seem to work */ + __asm volatile ("moveb #0x45, %1@(0x3d4); moveb %1@(0x3d5),%0" : + "=r" (test) : "a" (ba)); +#endif + WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); + hwc = ba + CRT_ADDRESS_W; + *hwc = 0; + *hwc = 0; + +#if 0 test = RCrt(ba, CRT_ID_HWGC_MODE); - asm volatile("nop"); - WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1); - WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1); - WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1); + __asm volatile ("nop"); +#else + /* do it in assembler, the above does't seem to work */ + __asm volatile ("moveb #0x45, %1@(0x3d4); moveb %1@(0x3d5),%0" : + "=r" (test) : "a" (ba)); +#endif + switch (gp->g_display.gd_planes) { + case 8: + WCrt(ba, CRT_ID_HWGC_BG_STACK, 0x1); + *hwc = 1; + break; + default: + WCrt(ba, CRT_ID_HWGC_BG_STACK, 0xff); + *hwc = 0xff; + *hwc = 0xff; + } test = HWC_OFF / HWC_SIZE; WCrt (ba, CRT_ID_HWGC_START_AD_HI, (test >> 8)); @@ -1770,14 +1937,21 @@ cv_setup_hwc (gp, col1, col2, hsx, hsy, data) WCrt (ba, CRT_ID_HWGC_DSTART_X , 0); WCrt (ba, CRT_ID_HWGC_DSTART_Y , 0); - WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10); /* Cursor X11 Mode */ + WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10); /* Cursor X11 Mode */ + /* + * Put it into Windoze Mode or you'll see sometimes a white stripe + * on the right side (in double clocking modes with a screen bigger + * > 1023 pixels). + */ + WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x00); /* Cursor Windoze Mode */ WCrt (ba, CRT_ID_HWGC_MODE, 0x01); } - -/* This is the reason why you shouldn't use the HGC in the Kernel:( */ - +/* + * This was the reason why you shouldn't use the HWC in the Kernel:( + * Obsoleted now by use of interrupts :-) + */ #define VerticalRetraceWait(ba) \ { \ while (vgar(ba, GREG_INPUT_STATUS1_R) == 0x00) ; \ @@ -1809,6 +1983,7 @@ cv_setspriteinfo (gp, info) u_char *imp, *mp; unsigned short row; +#ifdef CV_NO_INT /* Cursor off */ WCrt (ba, CRT_ID_HWGC_MODE, 0x00); @@ -1827,6 +2002,10 @@ cv_setspriteinfo (gp, info) * (thanks to Harald Koenig for this tip!) */ + /* + * Remark 06/06/96: Update in interrupt obsoletes this, + * but the warning should stay there! + */ VerticalRetraceWait(ba); WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, 0x7); @@ -1835,6 +2014,7 @@ cv_setspriteinfo (gp, info) WCrt (ba, CRT_ID_HWGC_DSTART_X, 0x3f); WCrt (ba, CRT_ID_HWGC_DSTART_Y, 0x3f); WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, 0x7); +#endif /* CV_NO_INT */ if (info->size.y > 64) info->size.y = 64; @@ -1849,11 +2029,14 @@ cv_setspriteinfo (gp, info) copyin(info->image, image, info->size.y * info->size.x / 8); copyin(info->mask, mask, info->size.y * info->size.x / 8); - hwp = (u_short *)(fb +HWC_OFF); +#ifdef CV_NO_INT + hwp = (u_short *)(fb + HWC_OFF); /* This is necessary in order not to crash the board */ - VerticalRetraceWait(ba); +#else /* CV_NO_INT */ + hwp = (u_short *) cv_cursor_storage; +#endif /* CV_NO_INT */ /* * setting it is slightly more difficult, because we can't @@ -1865,28 +2048,33 @@ cv_setspriteinfo (gp, info) row < info->size.y; row++) { u_short im1, im2, im3, im4, m1, m2, m3, m4; - im1 = *(unsigned short *)imp; - imp += 2; - m1 = *(unsigned short *)mp; + m1 = ~(*(unsigned short *)mp); + im1 = *(unsigned short *)imp & *(unsigned short *)mp; mp += 2; - - im2 = *(unsigned short *)imp; imp += 2; - m2 = *(unsigned short *)mp; + + m2 = ~(*(unsigned short *)mp); + im2 = *(unsigned short *)imp & *(unsigned short *)mp; mp += 2; + imp += 2; if (info->size.x > 32) { - im3 = *(unsigned long *)imp; - imp += 4; - m3 = *(unsigned long *)mp; - mp += 4; - im4 = *(unsigned long *)imp; - imp += 4; - m4 = *(unsigned long *)mp; - mp += 4; + m3 = ~(*(unsigned short *)mp); + im3 = *(unsigned short *)imp & + *(unsigned short *)mp; + mp += 2; + imp += 2; + m4 = ~(*(unsigned short *)mp); + im4 = *(unsigned short *)imp & + *(unsigned short *)mp; + mp += 2; + imp += 2; + } else { + m3 = 0xffff; + im3 = 0; + m4 = 0xffff; + im4 = 0; } - else - im3 = m3 = im4 = m4 = 0; switch (depth) { case 8: @@ -1923,68 +2111,100 @@ cv_setspriteinfo (gp, info) break; } } - for (; row < 64; row++) { - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; + + if (depth < 24) { + for (; row < 64; row++) { + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + } + } else { + for (; row < 64; row++) { + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + } } + free(image, M_TEMP); - cv_setup_hwc(gp, 1, 0, 0, 0, NULL); + /* cv_setup_hwc(gp); */ cv_hotx = info->hot.x; cv_hoty = info->hot.y; +#ifdef CV_NO_INT /* One must not write twice per vertical blank :-( */ - /* VerticalRetraceWait(ba); */ - + VerticalRetraceWait(ba); cv_setspritepos (gp, &info->pos); +#else /* CV_NO_INT */ + cv_setspritepos (gp, &info->pos); + curs_update_flag = 1; +#endif /* CV_NO_INT */ } if (info->set & GRFSPRSET_CMAP) { + volatile caddr_t hwc; int test; - VerticalRetraceWait(ba); - /* reset colour stack */ test = RCrt(ba, CRT_ID_HWGC_MODE); asm volatile("nop"); switch (depth) { - case 32: - case 24: - WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); - case 16: - case 8: - /* info->cmap.green[1] */ + case 8: + case 15: + case 16: WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); + hwc = ba + CRT_ADDRESS_W; + *hwc = 0; + break; + case 32: + case 24: WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); + hwc = ba + CRT_ADDRESS_W; + *hwc = 0; + *hwc = 0; + break; } test = RCrt(ba, CRT_ID_HWGC_MODE); asm volatile("nop"); switch (depth) { - case 8: - WCrt (ba, CRT_ID_HWGC_BG_STACK, 1); + case 8: WCrt (ba, CRT_ID_HWGC_BG_STACK, 1); + hwc = ba + CRT_ADDRESS_W; + *hwc = 1; break; - case 32: case 24: - WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); - case 16: + case 15: + case 16: WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); + hwc = ba + CRT_ADDRESS_W; + *hwc = 0xff; + break; + case 32: + case 24: WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); + hwc = ba + CRT_ADDRESS_W; + *hwc = 0xff; + *hwc = 0xff; + break; } } if (info->set & GRFSPRSET_ENABLE) { -#if 0 - if (info->enable) - control = 0x85; - else - control = 0; - WSeq(ba, SEQ_ID_CURSOR_CONTROL, control); -#endif + if (info->enable) { + cv_cursor_on = 1; + cv_setup_hwc(gp); + /* WCrt(ba, CRT_ID_HWGC_MODE, 0x01); */ + } else + WCrt(ba, CRT_ID_HWGC_MODE, 0x00); } if (info->set & GRFSPRSET_POS) cv_setspritepos(gp, &info->pos); @@ -2009,6 +2229,6 @@ cv_getspritemax (gp, pos) return(0); } -#endif /* CV_HARDWARE_CURSOR */ +#endif /* CV_NO_HARDWARE_CURSOR */ #endif /* NGRFCV */ |