#include "grf.h" #if NGRF > 0 /* Graphics routines for the Retina board, using the NCR 77C22E+ VGA controller. */ #include "sys/param.h" #include "sys/errno.h" #include "grfioctl.h" #include "grfvar.h" #include "grf_rtreg.h" #include "../include/cpu.h" #include "device.h" extern caddr_t ZORRO2ADDR; /* NOTE: this driver for the MacroSystem Retina board was only possible, because MacroSystem provided information about the pecularities of the board. THANKS! Competition in Europe among gfx board manufacturers is rather tough, so Lutz Vieweg, who wrote the initial driver, has made an agreement with MS not to document the driver source (see also his Copyright disclaimer below). -> ALL comments after -> "/* -------------- START OF CODE -------------- * /" -> have been added by myself (mw) from studying the publically -> available "NCR 77C22E+" Data Manual Lutz' original driver source (without any of my comments) is available on request. */ /* This code offers low-level routines to access the Retina graphics-board manufactured by MS MacroSystem GmbH from within NetBSD for the Amiga. No warranties for any kind of function at all - this code may crash your hardware and scratch your harddisk. Use at your own risk. Freely distributable. Written by Lutz Vieweg 07/93 Thanks to MacroSystem for providing me with the neccessary information to create theese routines. The sparse documentation of this code results from the agreements between MS and me. */ extern unsigned char kernel_font_width, kernel_font_height; extern unsigned char kernel_font_lo, kernel_font_hi; extern unsigned char kernel_font[]; #define MDF_DBL 1 #define MDF_LACE 2 #define MDF_CLKDIV2 4 /* standard-palette definition */ unsigned char NCRStdPalette[16*3] = { /* R G B */ 0, 0, 0, 192,192,192, 128, 0, 0, 0,128, 0, 0, 0,128, 128,128, 0, 0,128,128, 128, 0,128, 64, 64, 64, /* the higher 8 colors have more intensity for */ 255,255,255, /* compatibility with standard attributes */ 255, 0, 0, 0,255, 0, 0, 0,255, 255,255, 0, 0,255,255, 255, 0,255 }; /* The following structures are examples for monitor-definitions. To make one of your own, first use "DefineMonitor" and create the 8-bit monitor-mode of your dreams. Then save it, and make a structure from the values provided in the file DefineMonitor stored - the labels in the comment above the structure definition show where to put what value. Then you'll need to adapt your monitor-definition to the font you want to use. Be FX the width of the font, then the following modifications have to be applied to your values: HBS = (HBS * 4) / FX HSS = (HSS * 4) / FX HSE = (HSE * 4) / FX HBE = (HBE * 4) / FX HT = (HT * 4) / FX Make sure your maximum width (MW) and height (MH) are even multiples of the fonts' width and height. */ #if 0 /* horizontal 31.5 kHz */ /* FQ FLG MW MH HBS HSS HSE HBE HT VBS VSS VSE VBE VT */ struct MonDef MON_640_512_60 = { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535, /* Depth, PAL, TX, TY, XY,FontX, FontY, FontData, FLo, Fhi */ 4, NCRStdPalette, 80, 64, 5120, 8, 8, kernel_font, 32, 255}; /* horizontal 38kHz */ struct MonDef MON_768_600_60 = { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638, 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255}; /* horizontal 64kHz */ struct MonDef MON_768_600_80 = { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628, 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255}; #if 0 struct MonDef MON_1024_768_80 = { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}; #else struct MonDef MON_1024_768_80 = { 90000000, 0, 1024, 768, 257,258,278,321,320, 769, 770, 783, 804, 804, 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}; #endif struct MonDef MON_1024_1024_59= { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087, 4, NCRStdPalette,128, 128, 16384, 8, 8, kernel_font, 32, 255}; /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */ struct MonDef MON_1280_1024_60= {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073, 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}; /* horizontal 75kHz */ struct MonDef MON_1280_1024_69= {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073, 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}; #else struct MonDef monitor_defs[] = { /* horizontal 31.5 kHz */ { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535, 4, NCRStdPalette, 80, 64, 5120, 8, 8, kernel_font, 32, 255}, /* horizontal 38kHz */ { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638, 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255}, /* horizontal 64kHz */ { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628, 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255}, { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, { 100000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, { 110000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, { 120000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, { 13000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, { 72000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, { 75000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804, 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, { 90000000, 24, 1024, 768, 129,130,139,161,160, 769, 770, 783, 804, 804, 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255}, { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087, 4, NCRStdPalette,128, 128, 16384, 8, 8, kernel_font, 32, 255}, /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */ {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073, 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}, /* horizontal 75kHz */ {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073, 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255}, }; static const char *monitor_descr[] = { "80x64 (640x512) 31.5kHz", "96x75 (768x600) 38kHz", "96x75 (768x600) 64kHz", "128x96 (1024x768) 64kHz", "128x128 (1024x1024) 64kHz", "160x128 (1280x1024) 64kHz ***EXCEEDS CHIP LIMIT!!!***", "160x128 (1280x1024) 75kHz ***EXCEEDS CHIP LIMIT!!!***", }; int retina_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]); /* patchable */ int retina_default_mon = 2; #endif static struct MonDef *current_mon; /* -------------- START OF CODE -------------- */ static const long FQTab[16] = { 25175000, 28322000, 36000000, 65000000, 44900000, 50000000, 80000000, 75000000, 56644000, 63000000, 72000000, 130000000, 90000000, 100000000, 110000000, 120000000 }; /*--------------------------------------------------*/ /*--------------------------------------------------*/ #if 0 static struct MonDef *default_monitor = &DEFAULT_MONDEF; #endif static int rt_load_mon (struct grf_softc *gp, struct MonDef *md) { struct grfinfo *gi = &gp->g_display; volatile unsigned char *ba; volatile unsigned char *fb; short FW, clksel, HDE, VDE; for (clksel = 15; clksel; clksel--) { if (FQTab[clksel] == md->FQ) break; } if (clksel < 0) return 0; ba = gp->g_regkva;; fb = gp->g_fbkva; switch (md->FX) { case 4: FW = 0; break; case 7: FW = 1; break; case 8: FW = 2; break; case 9: FW = 3; break; case 10: FW = 4; break; case 11: FW = 5; break; case 12: FW = 6; break; case 13: FW = 7; break; case 14: FW = 8; break; case 15: FW = 9; break; case 16: FW = 11; break; default: return 0; break; }; HDE = (md->MW+md->FX-1)/md->FX; VDE = md->MH-1; /* hmm... */ fb[0x8000] = 0; /* enable extension registers */ WSeq (ba, SEQ_ID_EXTENDED_ENABLE, 0x05); #if 0 /* program the clock oscillator */ vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04)); vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00); /* XXXX according to the NCR specs, this register should be set to 1 XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE XXXX setting. */ WSeq (ba, SEQ_ID_RESET, 0x03); WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8)); WSeq (ba, SEQ_ID_MAP_MASK, 0x0f); WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); /* odd/even write select + extended memory */ WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06); /* XXXX I think this order of setting RESET is wrong... */ WSeq (ba, SEQ_ID_RESET, 0x01); WSeq (ba, SEQ_ID_RESET, 0x03); #else WSeq (ba, SEQ_ID_RESET, 0x01); /* set font width + rest of clocks */ WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) ); /* another clock bit, plus hw stuff */ WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) ); /* program the clock oscillator */ vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04)); vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00); WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8)); WSeq (ba, SEQ_ID_MAP_MASK, 0x0f); WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); /* odd/even write select + extended memory */ WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06); WSeq (ba, SEQ_ID_RESET, 0x03); #endif /* monochrome cursor */ WSeq (ba, SEQ_ID_CURSOR_CONTROL, 0x00); /* bank0 */ WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00); WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, 0x00); WSeq (ba, 0x1a , 0x00); /* these are reserved, really set them to 0 ??? */ WSeq (ba, 0x1b , 0x00); /* these are reserved, really set them to 0 ??? */ /* bank0 */ WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00); WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00); /* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */ WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40); #if 0 /* set font width + rest of clocks */ WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) ); #endif /* no ext-chain4 + no host-addr-bit-16 */ WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, 0x00); /* no packed/nibble + no 256bit gfx format */ WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00); /* AT-interface */ WSeq (ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x06); /* see fg/bg color expansion */ WSeq (ba, SEQ_ID_COLOR_EXP_WFG, 0x01); WSeq (ba, SEQ_ID_COLOR_EXP_WBG, 0x00); WSeq (ba, SEQ_ID_EXT_RW_CONTROL, 0x00); #if 0 /* another clock bit, plus hw stuff */ WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) ); #endif /* don't tristate PCLK and PIX */ WSeq (ba, SEQ_ID_COLOR_KEY_CNTL, 0x40 ); /* reset CRC circuit */ WSeq (ba, SEQ_ID_CRC_CONTROL, 0x00 ); /* set RAS/CAS swap */ WSeq (ba, SEQ_ID_PERF_SELECT, 0x20); WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf ) | 0x20); WCrt (ba, CRT_ID_HOR_TOTAL, md->HT & 0xff); WCrt (ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1) & 0xff); WCrt (ba, CRT_ID_START_HOR_BLANK, md->HBS & 0xff); WCrt (ba, CRT_ID_END_HOR_BLANK, (md->HBE & 0x1f) | 0x80); WCrt (ba, CRT_ID_START_HOR_RETR, md->HSS & 0xff); WCrt (ba, CRT_ID_END_HOR_RETR, (md->HSE & 0x1f) | ((md->HBE & 0x20)/ 0x20 * 0x80)); WCrt (ba, CRT_ID_VER_TOTAL, (md->VT & 0xff)); WCrt (ba, CRT_ID_OVERFLOW, (( (md->VSS & 0x200) / 0x200 * 0x80) | ((VDE & 0x200) / 0x200 * 0x40) | ((md->VT & 0x200) / 0x200 * 0x20) | 0x10 | ((md->VBS & 0x100) / 0x100 * 8 ) | ((md->VSS & 0x100) / 0x100 * 4 ) | ((VDE & 0x100) / 0x100 * 2 ) | ((md->VT & 0x100) / 0x100 ))); WCrt (ba, CRT_ID_PRESET_ROW_SCAN, 0x00); WCrt (ba, CRT_ID_MAX_SCAN_LINE, (( (md->FLG & MDF_DBL)/ MDF_DBL * 0x80) | 0x40 | ((md->VBS & 0x200)/0x200 * 0x20) | ((md->FY-1) & 0x1f))); WCrt (ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2); WCrt (ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1); WCrt (ba, CRT_ID_START_ADDR_HIGH, 0x00); WCrt (ba, CRT_ID_START_ADDR_LOW, 0x00); WCrt (ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); WCrt (ba, CRT_ID_CURSOR_LOC_LOW, 0x00); WCrt (ba, CRT_ID_START_VER_RETR, md->VSS & 0xff); WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0x0f) | 0x80 | 0x20); WCrt (ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff); WCrt (ba, CRT_ID_OFFSET, (HDE / 2) & 0xff); WCrt (ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f); WCrt (ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff); WCrt (ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff); /* byte mode + wrap + select row scan counter + cms */ WCrt (ba, CRT_ID_MODE_CONTROL, 0xe3); WCrt (ba, CRT_ID_LINE_COMPARE, 0xff); /* enable extended end bits + those bits */ WCrt (ba, CRT_ID_EXT_HOR_TIMING1, ( 0x20 | ((md->FLG & MDF_LACE) / MDF_LACE * 0x10) | ((md->HT & 0x100) / 0x100 * 0x01) | (((HDE-1) & 0x100) / 0x100 * 0x02) | ((md->HBS & 0x100) / 0x100 * 0x04) | ((md->HSS & 0x100) / 0x100 * 0x08))); WCrt (ba, CRT_ID_EXT_START_ADDR, (((HDE / 2) & 0x100)/0x100 * 16)); WCrt (ba, CRT_ID_EXT_HOR_TIMING2, ( ((md->HT & 0x200)/ 0x200 * 0x01) | (((HDE-1) & 0x200)/ 0x200 * 0x02) | ((md->HBS & 0x200)/ 0x200 * 0x04) | ((md->HSS & 0x200)/ 0x200 * 0x08) | ((md->HBE & 0xc0) / 0x40 * 0x10) | ((md->HSE & 0x60) / 0x20 * 0x40))); WCrt (ba, CRT_ID_EXT_VER_TIMING, ( ((md->VSE & 0x10) / 0x10 * 0x80) | ((md->VBE & 0x300)/ 0x100 * 0x20) | 0x10 | ((md->VSS & 0x400)/ 0x400 * 0x08) | ((md->VBS & 0x400)/ 0x400 * 0x04) | ((VDE & 0x400)/ 0x400 * 0x02) | ((md->VT & 0x400)/ 0x400 * 0x01))); WGfx (ba, GCT_ID_SET_RESET, 0x00); WGfx (ba, GCT_ID_ENABLE_SET_RESET, 0x00); WGfx (ba, GCT_ID_COLOR_COMPARE, 0x00); WGfx (ba, GCT_ID_DATA_ROTATE, 0x00); WGfx (ba, GCT_ID_READ_MAP_SELECT, 0x00); WGfx (ba, GCT_ID_GRAPHICS_MODE, 0x00); WGfx (ba, GCT_ID_MISC, 0x04); WGfx (ba, GCT_ID_COLOR_XCARE, 0xff); WGfx (ba, GCT_ID_BITMASK, 0xff); /* reset the Attribute Controller flipflop */ vgar (ba, GREG_STATUS1_R); WAttr (ba, ACT_ID_PALETTE0, 0x00); WAttr (ba, ACT_ID_PALETTE1, 0x01); WAttr (ba, ACT_ID_PALETTE2, 0x02); WAttr (ba, ACT_ID_PALETTE3, 0x03); WAttr (ba, ACT_ID_PALETTE4, 0x04); WAttr (ba, ACT_ID_PALETTE5, 0x05); WAttr (ba, ACT_ID_PALETTE6, 0x06); WAttr (ba, ACT_ID_PALETTE7, 0x07); WAttr (ba, ACT_ID_PALETTE8, 0x08); WAttr (ba, ACT_ID_PALETTE9, 0x09); WAttr (ba, ACT_ID_PALETTE10, 0x0a); WAttr (ba, ACT_ID_PALETTE11, 0x0b); WAttr (ba, ACT_ID_PALETTE12, 0x0c); WAttr (ba, ACT_ID_PALETTE13, 0x0d); WAttr (ba, ACT_ID_PALETTE14, 0x0e); WAttr (ba, ACT_ID_PALETTE15, 0x0f); vgar (ba, GREG_STATUS1_R); WAttr (ba, ACT_ID_ATTR_MODE_CNTL, 0x08); WAttr (ba, ACT_ID_OVERSCAN_COLOR, 0x00); WAttr (ba, ACT_ID_COLOR_PLANE_ENA, 0x0f); WAttr (ba, ACT_ID_HOR_PEL_PANNING, 0x00); WAttr (ba, ACT_ID_COLOR_SELECT, 0x00); vgar (ba, GREG_STATUS1_R); /* I have *NO* idea what strobing reg-0x20 might do... */ vgaw (ba, ACT_ADDRESS_W, 0x20); WCrt (ba, CRT_ID_MAX_SCAN_LINE, ( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) | 0x40 | ((md->VBS & 0x200)/0x200 * 0x20) | ((md->FY-1) & 0x1f))); /* not it's time for guessing... */ vgaw (ba, VDAC_REG_D, 0x02); /* if this does what I think it does, it selects DAC register 0, and writes the palette in subsequent registers, thus it works similar to the WD33C93 select/data mechanism */ vgaw (ba, VDAC_REG_SELECT, 0x00); { short x = 15; const unsigned char * col = md->PAL; do { vgaw (ba, VDAC_REG_DATA, *col++); vgaw (ba, VDAC_REG_DATA, *col++); vgaw (ba, VDAC_REG_DATA, *col++); } while (x--); } /* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */ { /* first set the whole font memory to a test-pattern, so we can see if something that shouldn't be drawn IS drawn.. */ { unsigned char * c = fb; long x; Map(2); for (x = 0; x < 65536; x++) { *c++ = (x & 1)? 0xaa : 0x55; } } { unsigned char * c = fb; long x; Map(3); for (x = 0; x < 65536; x++) { *c++ = (x & 1)? 0xaa : 0x55; } } { /* ok, now position at first defined character, and copy over the images */ unsigned char * c = fb + md->FLo * 32; const unsigned char * f = md->FData; unsigned short z; Map(2); for (z = md->FLo; z <= md->FHi; z++) { short y = md->FY-1; if (md->FX > 8){ do { *c++ = *f; f += 2; } while (y--); } else { do { *c++ = *f++; } while (y--); } c += 32-md->FY; } if (md->FX > 8) { unsigned short z; Map(3); c = fb + md->FLo*32; f = md->FData+1; for (z = md->FLo; z <= md->FHi; z++) { short y = md->FY-1; do { *c++ = *f; f += 2; } while (y--); c += 32-md->FY; } } } } /* select map 0 */ WGfx (ba, GCT_ID_READ_MAP_SELECT, 0); /* allow writes into maps 0 and 1 */ WSeq (ba, SEQ_ID_MAP_MASK, 3); /* select extended chain4 addressing: !A0/!A1 map 0 character to be displayed !A1/ A1 map 1 attribute of that character A0/!A1 map 2 not used (masked out, ignored) A0/ A1 map 3 not used (masked out, ignored) */ WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02); { /* position in display memory */ unsigned short * c = (unsigned short *) fb; /* fill with blank, white on black */ const unsigned short fill_val = 0x2010; short x = md->XY; do { *c = fill_val; c += 2; } while (x--); /* I won't comment this :-)) */ c = (unsigned short *) fb; c += (md->TX-6)*2; { unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f}; unsigned short * f = init_msg; x = 5; do { *c = *f++; c += 2; } while (x--); } } gp->g_data = (caddr_t) md; gi->gd_regaddr = (long)ba - (long)ZORRO2ADDR + (long)ZORRO2BASE;; gi->gd_regsize = 64*1024; gi->gd_fbaddr = (long)fb - (long)ZORRO2ADDR + (long)ZORRO2BASE; gi->gd_fbsize = 64*1024; /* larger, but that's whats mappable */ gi->gd_colors = 1 << md->DEP; gi->gd_planes = md->DEP; gi->gd_fbwidth = md->MW; gi->gd_fbheight = md->MH; gi->gd_fbx = 0; gi->gd_fby = 0; gi->gd_dwidth = md->TX * md->FX; gi->gd_dheight = md->TY * md->FY; gi->gd_dx = 0; gi->gd_dy = 0; /* initialized, works, return 1 */ return 1; } int rt_init (struct grf_softc *gp, struct amiga_device *ad, struct amiga_hw *ahw) { /* if already initialized, fail */ if (gp->g_regkva) return 0; gp->g_regkva = ahw->hw_kva; gp->g_fbkva = ahw->hw_kva + 64*1024; /* don't let them patch it out of bounds */ if ((unsigned)retina_default_mon >= retina_mon_max) retina_default_mon = 0; current_mon = monitor_defs + retina_default_mon; return rt_load_mon (gp, current_mon); } static int rt_getvmode (gp, vm) struct grf_softc *gp; struct grfvideo_mode *vm; { struct MonDef *md; if (vm->mode_num && vm->mode_num > retina_mon_max) return EINVAL; if (! vm->mode_num) vm->mode_num = (current_mon - monitor_defs) + 1; md = monitor_defs + (vm->mode_num - 1); strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1), sizeof (vm->mode_descr)); vm->pixel_clock = md->FQ; vm->disp_width = md->MW; vm->disp_height = md->MH; vm->depth = md->DEP; vm->hblank_start = md->HBS; vm->hblank_stop = md->HBE; vm->hsync_start = md->HSS; vm->hsync_stop = md->HSE; vm->htotal = md->HT; vm->vblank_start = md->VBS; vm->vblank_stop = md->VBE; vm->vsync_start = md->VSS; vm->vsync_stop = md->VSE; vm->vtotal = md->VT; return 0; } static int rt_setvmode (gp, mode) struct grf_softc *gp; unsigned mode; { struct MonDef *md; if (!mode || mode > retina_mon_max) return EINVAL; current_mon = monitor_defs + (mode - 1); return rt_load_mon (gp, current_mon) ? 0 : EINVAL; } /* * Change the mode of the display. * Right now all we can do is grfon/grfoff. * Return a UNIX error number or 0 for success. */ rt_mode(gp, cmd, arg) register struct grf_softc *gp; int cmd; void *arg; { /* implement these later... */ switch (cmd) { case GM_GRFON: return 0; case GM_GRFOFF: return 0; case GM_GRFCONFIG: return 0; case GM_GRFGETVMODE: return rt_getvmode (gp, (struct grfvideo_mode *) arg); case GM_GRFSETVMODE: return rt_setvmode (gp, *(unsigned *) arg); case GM_GRFGETNUMVM: *(int *)arg = retina_mon_max; return 0; default: break; } return EINVAL; } #endif /* NGRF */