Home | History | Annotate | Line # | Download | only in dev
grf_rt.c revision 1.3
      1 #include "grf.h"
      2 #if NGRF > 0
      3 
      4 /* Graphics routines for the Retina board,
      5    using the NCR 77C22E+ VGA controller. */
      6 
      7 #include "sys/param.h"
      8 #include "sys/errno.h"
      9 #include "grfioctl.h"
     10 #include "grfvar.h"
     11 #include "grf_rtreg.h"
     12 #include "../include/cpu.h"
     13 #include "device.h"
     14 
     15 extern caddr_t ZORRO2ADDR;
     16 
     17 /* NOTE: this driver for the MacroSystem Retina board was only possible,
     18          because MacroSystem provided information about the pecularities
     19          of the board. THANKS! Competition in Europe among gfx board
     20          manufacturers is rather tough, so Lutz Vieweg, who wrote the
     21          initial driver, has made an agreement with MS not to document
     22          the driver source (see also his Copyright disclaimer below).
     23          -> ALL comments after
     24 	 -> "/* -------------- START OF CODE -------------- * /"
     25 	 -> have been added by myself (mw) from studying the publically
     26 	 -> available "NCR 77C22E+" Data Manual
     27 
     28 	 Lutz' original driver source (without any of my comments) is
     29 	 available on request. */
     30 
     31 
     32 /* This code offers low-level routines to access the Retina graphics-board
     33    manufactured by MS MacroSystem GmbH from within NetBSD for the Amiga.
     34    No warranties for any kind of function at all - this code may crash
     35    your hardware and scratch your harddisk.
     36    Use at your own risk.
     37    Freely distributable.
     38 
     39    Written by Lutz Vieweg 07/93
     40 
     41    Thanks to MacroSystem for providing me with the neccessary information
     42    to create theese routines. The sparse documentation of this code
     43    results from the agreements between MS and me.
     44 */
     45 
     46 extern unsigned char kernel_font_width, kernel_font_height;
     47 extern unsigned char kernel_font_lo, kernel_font_hi;
     48 extern unsigned char kernel_font[];
     49 
     50 
     51 #define MDF_DBL 1
     52 #define MDF_LACE 2
     53 #define MDF_CLKDIV2 4
     54 
     55 
     56 /* standard-palette definition */
     57 
     58 unsigned char NCRStdPalette[16*3] = {
     59 /*   R   G   B  */
     60 	  0,  0,  0,
     61 	192,192,192,
     62 	128,  0,  0,
     63 	  0,128,  0,
     64 	  0,  0,128,
     65 	128,128,  0,
     66 	  0,128,128,
     67 	128,  0,128,
     68 	 64, 64, 64, /* the higher 8 colors have more intensity for  */
     69 	255,255,255, /* compatibility with standard attributes       */
     70 	255,  0,  0,
     71 	  0,255,  0,
     72 	  0,  0,255,
     73 	255,255,  0,
     74 	  0,255,255,
     75 	255,  0,255
     76 };
     77 
     78 
     79 /* The following structures are examples for monitor-definitions. To make one
     80    of your own, first use "DefineMonitor" and create the 8-bit monitor-mode of
     81    your dreams. Then save it, and make a structure from the values provided in
     82    the file DefineMonitor stored - the labels in the comment above the
     83    structure definition show where to put what value.
     84 
     85    Then you'll need to adapt your monitor-definition to the font you want to
     86    use. Be FX the width of the font, then the following modifications have to
     87    be applied to your values:
     88 
     89    HBS = (HBS * 4) / FX
     90    HSS = (HSS * 4) / FX
     91    HSE = (HSE * 4) / FX
     92    HBE = (HBE * 4) / FX
     93    HT  = (HT  * 4) / FX
     94 
     95    Make sure your maximum width (MW) and height (MH) are even multiples of
     96    the fonts' width and height.
     97 */
     98 
     99 #if 0
    100 /* horizontal 31.5 kHz */
    101 
    102 /*                                      FQ     FLG    MW   MH   HBS HSS HSE HBE  HT  VBS  VSS  VSE  VBE   VT  */
    103    struct MonDef MON_640_512_60  = { 50000000,  28,  640, 512,   81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
    104    /* Depth,           PAL, TX,  TY,    XY,FontX, FontY,    FontData,  FLo,  Fhi */
    105           4, NCRStdPalette, 80,  64,  5120,    8,     8, kernel_font,   32,  255};
    106 
    107 /* horizontal 38kHz */
    108 
    109    struct MonDef MON_768_600_60  = { 75000000,  28,  768, 600,   97, 99,107,120,117, 601, 615, 625, 638, 638,
    110           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font,   32,  255};
    111 
    112 /* horizontal 64kHz */
    113 
    114    struct MonDef MON_768_600_80  = { 50000000, 24,  768, 600,   97,104,112,122,119, 601, 606, 616, 628, 628,
    115           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font,   32,  255};
    116 
    117 #if 0
    118    struct MonDef MON_1024_768_80 = { 90000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
    119           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255};
    120 #else
    121    struct MonDef MON_1024_768_80 = { 90000000, 0, 1024, 768,  257,258,278,321,320, 769, 770, 783, 804, 804,
    122           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255};
    123 #endif
    124 
    125    struct MonDef MON_1024_1024_59= { 90000000, 24, 1024,1024,  129,130,141,173,170,1025,1059,1076,1087,1087,
    126           4, NCRStdPalette,128, 128, 16384,    8,     8, kernel_font,   32,  255};
    127 
    128 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR
    129             HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
    130             MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!     */
    131 
    132    struct MonDef MON_1280_1024_60= {110000000,  24, 1280,1024,  161,162,176,211,208,1025,1026,1043,1073,1073,
    133           4, NCRStdPalette,160, 128, 20480,    8,     8, kernel_font,   32,  255};
    134 
    135 /* horizontal 75kHz */
    136 
    137    struct MonDef MON_1280_1024_69= {120000000,  24, 1280,1024,  161,162,175,200,197,1025,1026,1043,1073,1073,
    138           4, NCRStdPalette,160, 128, 20480,    8,     8, kernel_font,   32,  255};
    139 
    140 #else
    141 
    142 struct MonDef monitor_defs[] = {
    143 /* horizontal 31.5 kHz */
    144 
    145    { 50000000,  28,  640, 512,   81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
    146           4, NCRStdPalette, 80,  64,  5120,    8,     8, kernel_font,   32,  255},
    147 
    148 /* horizontal 38kHz */
    149 
    150    { 75000000,  28,  768, 600,   97, 99,107,120,117, 601, 615, 625, 638, 638,
    151           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font,   32,  255},
    152 
    153 /* horizontal 64kHz */
    154 
    155    { 50000000, 24,  768, 600,   97,104,112,122,119, 601, 606, 616, 628, 628,
    156           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font,   32,  255},
    157 
    158 
    159 
    160    { 90000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
    161           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
    162 
    163    { 100000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
    164           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
    165 
    166    { 110000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
    167           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
    168 
    169    { 120000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
    170           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
    171 
    172    { 13000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
    173           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
    174 
    175    { 72000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
    176           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
    177 
    178    { 75000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
    179           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
    180 
    181 
    182 
    183 
    184    { 90000000, 24, 1024, 768,  129,130,139,161,160, 769, 770, 783, 804, 804,
    185           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
    186 
    187    { 90000000, 24, 1024,1024,  129,130,141,173,170,1025,1059,1076,1087,1087,
    188           4, NCRStdPalette,128, 128, 16384,    8,     8, kernel_font,   32,  255},
    189 
    190 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR
    191             HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
    192             MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!     */
    193 
    194    {110000000,  24, 1280,1024,  161,162,176,211,208,1025,1026,1043,1073,1073,
    195           4, NCRStdPalette,160, 128, 20480,    8,     8, kernel_font,   32,  255},
    196 
    197 /* horizontal 75kHz */
    198 
    199    {120000000,  24, 1280,1024,  161,162,175,200,197,1025,1026,1043,1073,1073,
    200           4, NCRStdPalette,160, 128, 20480,    8,     8, kernel_font,   32,  255},
    201 
    202 };
    203 
    204 static const char *monitor_descr[] = {
    205   "80x64 (640x512) 31.5kHz",
    206   "96x75 (768x600) 38kHz",
    207   "96x75 (768x600) 64kHz",
    208   "128x96 (1024x768) 64kHz",
    209   "128x128 (1024x1024) 64kHz",
    210   "160x128 (1280x1024) 64kHz ***EXCEEDS CHIP LIMIT!!!***",
    211   "160x128 (1280x1024) 75kHz ***EXCEEDS CHIP LIMIT!!!***",
    212 };
    213 
    214 int retina_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]);
    215 
    216 /* patchable */
    217 int retina_default_mon = 2;
    218 
    219 #endif
    220 
    221 
    222 static struct MonDef *current_mon;
    223 
    224 /* -------------- START OF CODE -------------- */
    225 
    226 
    227 static const long FQTab[16] =
    228 { 25175000,  28322000,  36000000,  65000000,
    229   44900000,  50000000,  80000000,  75000000,
    230   56644000,  63000000,  72000000, 130000000,
    231   90000000, 100000000, 110000000, 120000000 };
    232 
    233 
    234 /*--------------------------------------------------*/
    235 /*--------------------------------------------------*/
    236 
    237 #if 0
    238 static struct MonDef *default_monitor = &DEFAULT_MONDEF;
    239 #endif
    240 
    241 
    242 static int rt_load_mon (struct grf_softc *gp, struct MonDef *md)
    243 {
    244 	struct grfinfo *gi = &gp->g_display;
    245 	volatile unsigned char *ba;
    246 	volatile unsigned char *fb;
    247 	short FW, clksel, HDE, VDE;
    248 
    249 	for (clksel = 15; clksel; clksel--) {
    250 		if (FQTab[clksel] == md->FQ) break;
    251 	}
    252 	if (clksel < 0) return 0;
    253 
    254 	ba = gp->g_regkva;;
    255 	fb = gp->g_fbkva;
    256 
    257 	switch (md->FX) {
    258 	case 4:
    259 		FW = 0;
    260 		break;
    261 	case 7:
    262 		FW = 1;
    263 		break;
    264 	case 8:
    265 		FW = 2;
    266 		break;
    267 	case 9:
    268 		FW = 3;
    269 		break;
    270 	case 10:
    271 		FW = 4;
    272 		break;
    273 	case 11:
    274 		FW = 5;
    275 		break;
    276 	case 12:
    277 		FW = 6;
    278 		break;
    279 	case 13:
    280 		FW = 7;
    281 		break;
    282 	case 14:
    283 		FW = 8;
    284 		break;
    285 	case 15:
    286 		FW = 9;
    287 		break;
    288 	case 16:
    289 		FW = 11;
    290 		break;
    291 	default:
    292 		return 0;
    293 		break;
    294 	};
    295 
    296 	HDE = (md->MW+md->FX-1)/md->FX;
    297 	VDE = md->MH-1;
    298 
    299 	/* hmm... */
    300 	fb[0x8000] = 0;
    301 
    302 		/* enable extension registers */
    303 	WSeq (ba, SEQ_ID_EXTENDED_ENABLE,	0x05);
    304 
    305 #if 0
    306 	/* program the clock oscillator */
    307 	vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
    308 	vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00);
    309 
    310 	/* XXXX according to the NCR specs, this register should be set to 1
    311 	   XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE
    312 	   XXXX setting. */
    313 	WSeq (ba, SEQ_ID_RESET, 		0x03);
    314 
    315 	WSeq (ba, SEQ_ID_CLOCKING_MODE, 	0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
    316 	WSeq (ba, SEQ_ID_MAP_MASK, 		0x0f);
    317 	WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 	0x00);
    318 		/* odd/even write select + extended memory */
    319 	WSeq (ba, SEQ_ID_MEMORY_MODE, 	0x06);
    320 	/* XXXX I think this order of setting RESET is wrong... */
    321 	WSeq (ba, SEQ_ID_RESET, 		0x01);
    322 	WSeq (ba, SEQ_ID_RESET, 		0x03);
    323 #else
    324 	WSeq (ba, SEQ_ID_RESET, 		0x01);
    325 
    326 		/* set font width + rest of clocks */
    327 	WSeq (ba, SEQ_ID_EXT_CLOCK_MODE,	0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
    328 		/* another clock bit, plus hw stuff */
    329 	WSeq (ba, SEQ_ID_MISC_FEATURE_SEL,	0xf4 | (clksel & 8) );
    330 
    331 	/* program the clock oscillator */
    332 	vgaw (ba, GREG_MISC_OUTPUT_W, 		0xe3 | ((clksel & 3) * 0x04));
    333 	vgaw (ba, GREG_FEATURE_CONTROL_W, 	0x00);
    334 
    335 	WSeq (ba, SEQ_ID_CLOCKING_MODE, 	0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
    336 	WSeq (ba, SEQ_ID_MAP_MASK, 		0x0f);
    337 	WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 	0x00);
    338 		/* odd/even write select + extended memory */
    339 	WSeq (ba, SEQ_ID_MEMORY_MODE, 		0x06);
    340 	WSeq (ba, SEQ_ID_RESET, 		0x03);
    341 #endif
    342 
    343 		/* monochrome cursor */
    344 	WSeq (ba, SEQ_ID_CURSOR_CONTROL,	0x00);
    345 		/* bank0 */
    346 	WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI,	0x00);
    347 	WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO,	0x00);
    348 	WSeq (ba, 0x1a , 0x00);  /* these are reserved, really set them to 0 ??? */
    349 	WSeq (ba, 0x1b , 0x00);  /* these are reserved, really set them to 0 ??? */
    350 		/* bank0 */
    351 	WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI,	0x00);
    352 	WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO,	0x00);
    353 		/* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */
    354 	WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA,	0x3 | 0x4 | 0x10 | 0x40);
    355 #if 0
    356 		/* set font width + rest of clocks */
    357 	WSeq (ba, SEQ_ID_EXT_CLOCK_MODE,	0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
    358 #endif
    359 		/* no ext-chain4 + no host-addr-bit-16 */
    360 	WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR,	0x00);
    361 		/* no packed/nibble + no 256bit gfx format */
    362 	WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL,	0x00);
    363 		/* AT-interface */
    364 	WSeq (ba, SEQ_ID_BUS_WIDTH_FEEDB,	0x06);
    365 		/* see fg/bg color expansion */
    366 	WSeq (ba, SEQ_ID_COLOR_EXP_WFG,		0x01);
    367 	WSeq (ba, SEQ_ID_COLOR_EXP_WBG,		0x00);
    368 	WSeq (ba, SEQ_ID_EXT_RW_CONTROL,	0x00);
    369 #if 0
    370 		/* another clock bit, plus hw stuff */
    371 	WSeq (ba, SEQ_ID_MISC_FEATURE_SEL,	0xf4 | (clksel & 8) );
    372 #endif
    373 		/* don't tristate PCLK and PIX */
    374 	WSeq (ba, SEQ_ID_COLOR_KEY_CNTL,	0x40 );
    375 		/* reset CRC circuit */
    376 	WSeq (ba, SEQ_ID_CRC_CONTROL,		0x00 );
    377 		/* set RAS/CAS swap */
    378 	WSeq (ba, SEQ_ID_PERF_SELECT,		0x20);
    379 
    380 	WCrt (ba, CRT_ID_END_VER_RETR,		(md->VSE & 0xf ) | 0x20);
    381 	WCrt (ba, CRT_ID_HOR_TOTAL,		md->HT   & 0xff);
    382 	WCrt (ba, CRT_ID_HOR_DISP_ENA_END,	(HDE-1)  & 0xff);
    383 	WCrt (ba, CRT_ID_START_HOR_BLANK,	md->HBS  & 0xff);
    384 	WCrt (ba, CRT_ID_END_HOR_BLANK,		(md->HBE & 0x1f) | 0x80);
    385 
    386 	WCrt (ba, CRT_ID_START_HOR_RETR,	md->HSS  & 0xff);
    387 	WCrt (ba, CRT_ID_END_HOR_RETR,		(md->HSE & 0x1f) | ((md->HBE & 0x20)/ 0x20 * 0x80));
    388 	WCrt (ba, CRT_ID_VER_TOTAL,		(md->VT  & 0xff));
    389 	WCrt (ba, CRT_ID_OVERFLOW,		(( (md->VSS  & 0x200) / 0x200 * 0x80)
    390 						 | ((VDE     & 0x200) / 0x200 * 0x40)
    391 						 | ((md->VT  & 0x200) / 0x200 * 0x20)
    392 						 | 				0x10
    393 						 | ((md->VBS & 0x100) / 0x100 * 8   )
    394 						 | ((md->VSS & 0x100) / 0x100 * 4   )
    395 						 | ((VDE     & 0x100) / 0x100 * 2   )
    396 						 | ((md->VT  & 0x100) / 0x100       )));
    397 	WCrt (ba, CRT_ID_PRESET_ROW_SCAN,	0x00);
    398 
    399 	WCrt (ba, CRT_ID_MAX_SCAN_LINE, 	((  (md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
    400 						 | 				   0x40
    401 						 | ((md->VBS & 0x200)/0x200	 * 0x20)
    402 						 | ((md->FY-1) 			 & 0x1f)));
    403 
    404 	WCrt (ba, CRT_ID_CURSOR_START,		(md->FY & 0x1f) - 2);
    405 	WCrt (ba, CRT_ID_CURSOR_END,		(md->FY & 0x1f) - 1);
    406 
    407 	WCrt (ba, CRT_ID_START_ADDR_HIGH,	0x00);
    408 	WCrt (ba, CRT_ID_START_ADDR_LOW,	0x00);
    409 
    410 	WCrt (ba, CRT_ID_CURSOR_LOC_HIGH,	0x00);
    411 	WCrt (ba, CRT_ID_CURSOR_LOC_LOW,	0x00);
    412 
    413 	WCrt (ba, CRT_ID_START_VER_RETR,	md->VSS    & 0xff);
    414 	WCrt (ba, CRT_ID_END_VER_RETR,		(md->VSE   & 0x0f) | 0x80 | 0x20);
    415 	WCrt (ba, CRT_ID_VER_DISP_ENA_END,	VDE        & 0xff);
    416 	WCrt (ba, CRT_ID_OFFSET,		(HDE / 2)  & 0xff);
    417 	WCrt (ba, CRT_ID_UNDERLINE_LOC,		(md->FY-1) & 0x1f);
    418 	WCrt (ba, CRT_ID_START_VER_BLANK,	md->VBS    & 0xff);
    419 	WCrt (ba, CRT_ID_END_VER_BLANK,		md->VBE    & 0xff);
    420 		/* byte mode + wrap + select row scan counter + cms */
    421 	WCrt (ba, CRT_ID_MODE_CONTROL,		0xe3);
    422 	WCrt (ba, CRT_ID_LINE_COMPARE,		0xff);
    423 
    424 		/* enable extended end bits + those bits */
    425 	WCrt (ba, CRT_ID_EXT_HOR_TIMING1,	(           				 0x20
    426 						 | ((md->FLG & MDF_LACE)  / MDF_LACE   * 0x10)
    427 						 | ((md->HT  & 0x100) / 0x100          * 0x01)
    428 						 | (((HDE-1) & 0x100) / 0x100 	       * 0x02)
    429 						 | ((md->HBS & 0x100) / 0x100 	       * 0x04)
    430 						 | ((md->HSS & 0x100) / 0x100 	       * 0x08)));
    431 
    432 	WCrt (ba, CRT_ID_EXT_START_ADDR,	(((HDE / 2) & 0x100)/0x100 * 16));
    433 
    434 	WCrt (ba, CRT_ID_EXT_HOR_TIMING2, 	(  ((md->HT  & 0x200)/ 0x200  	       * 0x01)
    435 						 | (((HDE-1) & 0x200)/ 0x200 	       * 0x02)
    436 						 | ((md->HBS & 0x200)/ 0x200 	       * 0x04)
    437 						 | ((md->HSS & 0x200)/ 0x200 	       * 0x08)
    438 						 | ((md->HBE & 0xc0) / 0x40  	       * 0x10)
    439 						 | ((md->HSE & 0x60) / 0x20  	       * 0x40)));
    440 
    441 	WCrt (ba, CRT_ID_EXT_VER_TIMING,	(  ((md->VSE & 0x10) / 0x10  	       * 0x80)
    442 						 | ((md->VBE & 0x300)/ 0x100 	       * 0x20)
    443 						 |				         0x10
    444 						 | ((md->VSS & 0x400)/ 0x400 	       * 0x08)
    445 						 | ((md->VBS & 0x400)/ 0x400 	       * 0x04)
    446 						 | ((VDE     & 0x400)/ 0x400 	       * 0x02)
    447 						 | ((md->VT  & 0x400)/ 0x400           * 0x01)));
    448 
    449 	WGfx (ba, GCT_ID_SET_RESET,		0x00);
    450 	WGfx (ba, GCT_ID_ENABLE_SET_RESET,	0x00);
    451 	WGfx (ba, GCT_ID_COLOR_COMPARE,		0x00);
    452 	WGfx (ba, GCT_ID_DATA_ROTATE,		0x00);
    453 	WGfx (ba, GCT_ID_READ_MAP_SELECT,	0x00);
    454 	WGfx (ba, GCT_ID_GRAPHICS_MODE,		0x00);
    455 	WGfx (ba, GCT_ID_MISC,			0x04);
    456 	WGfx (ba, GCT_ID_COLOR_XCARE,		0xff);
    457 	WGfx (ba, GCT_ID_BITMASK,		0xff);
    458 
    459 	/* reset the Attribute Controller flipflop */
    460 	vgar (ba, GREG_STATUS1_R);
    461 	WAttr (ba, ACT_ID_PALETTE0,		0x00);
    462 	WAttr (ba, ACT_ID_PALETTE1,		0x01);
    463 	WAttr (ba, ACT_ID_PALETTE2,		0x02);
    464 	WAttr (ba, ACT_ID_PALETTE3,		0x03);
    465 	WAttr (ba, ACT_ID_PALETTE4,		0x04);
    466 	WAttr (ba, ACT_ID_PALETTE5,		0x05);
    467 	WAttr (ba, ACT_ID_PALETTE6,		0x06);
    468 	WAttr (ba, ACT_ID_PALETTE7,		0x07);
    469 	WAttr (ba, ACT_ID_PALETTE8,		0x08);
    470 	WAttr (ba, ACT_ID_PALETTE9,		0x09);
    471 	WAttr (ba, ACT_ID_PALETTE10,		0x0a);
    472 	WAttr (ba, ACT_ID_PALETTE11,		0x0b);
    473 	WAttr (ba, ACT_ID_PALETTE12,		0x0c);
    474 	WAttr (ba, ACT_ID_PALETTE13,		0x0d);
    475 	WAttr (ba, ACT_ID_PALETTE14,		0x0e);
    476 	WAttr (ba, ACT_ID_PALETTE15,		0x0f);
    477 
    478 	vgar (ba, GREG_STATUS1_R);
    479 	WAttr (ba, ACT_ID_ATTR_MODE_CNTL,	0x08);
    480 
    481 	WAttr (ba, ACT_ID_OVERSCAN_COLOR,	0x00);
    482 	WAttr (ba, ACT_ID_COLOR_PLANE_ENA,	0x0f);
    483 	WAttr (ba, ACT_ID_HOR_PEL_PANNING,	0x00);
    484 	WAttr (ba, ACT_ID_COLOR_SELECT,	0x00);
    485 
    486 	vgar (ba, GREG_STATUS1_R);
    487 		/* I have *NO* idea what strobing reg-0x20 might do... */
    488 	vgaw (ba, ACT_ADDRESS_W, 0x20);
    489 
    490 	WCrt (ba, CRT_ID_MAX_SCAN_LINE,		( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
    491 						|	                          0x40
    492 						| ((md->VBS & 0x200)/0x200	* 0x20)
    493 						| ((md->FY-1) 			& 0x1f)));
    494 
    495 
    496 	/* not it's time for guessing... */
    497 
    498 	vgaw (ba, VDAC_REG_D, 	   0x02);
    499 
    500 		/* if this does what I think it does, it selects DAC
    501 		   register 0, and writes the palette in subsequent
    502 		   registers, thus it works similar to the WD33C93
    503 		   select/data mechanism */
    504 	vgaw (ba, VDAC_REG_SELECT, 0x00);
    505 
    506 	{
    507 
    508 		short x = 15;
    509 		const unsigned char * col = md->PAL;
    510 		do {
    511 
    512 			vgaw (ba, VDAC_REG_DATA, *col++);
    513 			vgaw (ba, VDAC_REG_DATA, *col++);
    514 			vgaw (ba, VDAC_REG_DATA, *col++);
    515 
    516 
    517 		} while (x--);
    518 
    519 	}
    520 
    521 
    522 	/* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */
    523 	{
    524 
    525 		/* first set the whole font memory to a test-pattern, so we
    526 		   can see if something that shouldn't be drawn IS drawn.. */
    527 		{
    528 			unsigned char * c = fb;
    529 			long x;
    530 			Map(2);
    531 
    532 			for (x = 0; x < 65536; x++) {
    533 				*c++ = (x & 1)? 0xaa : 0x55;
    534 			}
    535 		}
    536 
    537 		{
    538 			unsigned char * c = fb;
    539 			long x;
    540 			Map(3);
    541 
    542 			for (x = 0; x < 65536; x++) {
    543 				*c++ = (x & 1)? 0xaa : 0x55;
    544 			}
    545 		}
    546 
    547 		{
    548 		  /* ok, now position at first defined character, and
    549 		     copy over the images */
    550 		  unsigned char * c = fb + md->FLo * 32;
    551 		  const unsigned char * f = md->FData;
    552 		  unsigned short z;
    553 
    554 		  Map(2);
    555 		  for (z = md->FLo; z <= md->FHi; z++) {
    556 
    557 			short y = md->FY-1;
    558 			if (md->FX > 8){
    559 				do {
    560 					*c++ = *f;
    561 					f += 2;
    562 				} while (y--);
    563 			}
    564 			else {
    565 				do {
    566 					*c++ = *f++;
    567 				} while (y--);
    568 			}
    569 
    570 			c += 32-md->FY;
    571 
    572 		  }
    573 
    574 		  if (md->FX > 8) {
    575 			unsigned short z;
    576 
    577 			Map(3);
    578 			c = fb + md->FLo*32;
    579 			f = md->FData+1;
    580 			for (z = md->FLo; z <= md->FHi; z++) {
    581 
    582 				short y = md->FY-1;
    583 				do {
    584 					*c++ = *f;
    585 					f += 2;
    586 				} while (y--);
    587 
    588 				c += 32-md->FY;
    589 
    590 			}
    591 		  }
    592 		}
    593 
    594 	}
    595 
    596 		/* select map 0 */
    597 	WGfx (ba, GCT_ID_READ_MAP_SELECT,	0);
    598 		/* allow writes into maps 0 and 1 */
    599 	WSeq (ba, SEQ_ID_MAP_MASK,		3);
    600 		/* select extended chain4 addressing:
    601 		    !A0/!A1	map 0	character to be displayed
    602 		    !A1/ A1	map 1	attribute of that character
    603 		     A0/!A1	map 2	not used (masked out, ignored)
    604 		     A0/ A1 	map 3	not used (masked out, ignored) */
    605 	WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR,	RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
    606 
    607 	{
    608 		/* position in display memory */
    609 		unsigned short * c = (unsigned short *) fb;
    610 
    611 		/* fill with blank, white on black */
    612 		const unsigned short fill_val = 0x2010;
    613 		short x = md->XY;
    614 		do {
    615 			*c = fill_val;
    616 			c += 2;
    617 		} while (x--);
    618 
    619 		/* I won't comment this :-)) */
    620 		c = (unsigned short *) fb;
    621 		c += (md->TX-6)*2;
    622 		{
    623 		  unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f};
    624 		  unsigned short * f = init_msg;
    625 		  x = 5;
    626 		  do {
    627 			*c = *f++;
    628 			c += 2;
    629 	 	  } while (x--);
    630 	 	}
    631 
    632 
    633 	}
    634 
    635 
    636 	gp->g_data	= (caddr_t) md;
    637 	gi->gd_regaddr  = (long)ba - (long)ZORRO2ADDR + (long)ZORRO2BASE;;
    638 	gi->gd_regsize  = 64*1024;
    639 
    640 	gi->gd_fbaddr   = (long)fb - (long)ZORRO2ADDR + (long)ZORRO2BASE;
    641 	gi->gd_fbsize   = 64*1024;	/* larger, but that's whats mappable */
    642 
    643 	gi->gd_colors   = 1 << md->DEP;
    644 	gi->gd_planes   = md->DEP;
    645 
    646 	gi->gd_fbwidth  = md->MW;
    647 	gi->gd_fbheight = md->MH;
    648 	gi->gd_fbx	= 0;
    649 	gi->gd_fby	= 0;
    650 	gi->gd_dwidth   = md->TX * md->FX;
    651 	gi->gd_dheight  = md->TY * md->FY;
    652 	gi->gd_dx	= 0;
    653 	gi->gd_dy	= 0;
    654 
    655 	/* initialized, works, return 1 */
    656 	return 1;
    657 }
    658 
    659 int rt_init (struct grf_softc *gp, struct amiga_device *ad, struct amiga_hw *ahw)
    660 {
    661   /* if already initialized, fail */
    662   if (gp->g_regkva)
    663     return 0;
    664 
    665   gp->g_regkva = ahw->hw_kva;
    666   gp->g_fbkva  = ahw->hw_kva + 64*1024;
    667 
    668   /* don't let them patch it out of bounds */
    669   if ((unsigned)retina_default_mon >= retina_mon_max)
    670     retina_default_mon = 0;
    671 
    672   current_mon = monitor_defs + retina_default_mon;
    673 
    674   return rt_load_mon (gp, current_mon);
    675 }
    676 
    677 static int
    678 rt_getvmode (gp, vm)
    679      struct grf_softc *gp;
    680      struct grfvideo_mode *vm;
    681 {
    682   struct MonDef *md;
    683 
    684   if (vm->mode_num && vm->mode_num > retina_mon_max)
    685     return EINVAL;
    686 
    687   if (! vm->mode_num)
    688     vm->mode_num = (current_mon - monitor_defs) + 1;
    689 
    690   md = monitor_defs + (vm->mode_num - 1);
    691   strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
    692 	   sizeof (vm->mode_descr));
    693   vm->pixel_clock  = md->FQ;
    694   vm->disp_width   = md->MW;
    695   vm->disp_height  = md->MH;
    696   vm->depth        = md->DEP;
    697   vm->hblank_start = md->HBS;
    698   vm->hblank_stop  = md->HBE;
    699   vm->hsync_start  = md->HSS;
    700   vm->hsync_stop   = md->HSE;
    701   vm->htotal       = md->HT;
    702   vm->vblank_start = md->VBS;
    703   vm->vblank_stop  = md->VBE;
    704   vm->vsync_start  = md->VSS;
    705   vm->vsync_stop   = md->VSE;
    706   vm->vtotal       = md->VT;
    707 
    708   return 0;
    709 }
    710 
    711 
    712 static int
    713 rt_setvmode (gp, mode)
    714      struct grf_softc *gp;
    715      unsigned mode;
    716 {
    717   struct MonDef *md;
    718 
    719   if (!mode || mode > retina_mon_max)
    720     return EINVAL;
    721 
    722   current_mon = monitor_defs + (mode - 1);
    723   return rt_load_mon (gp, current_mon) ? 0 : EINVAL;
    724 }
    725 
    726 
    727 /*
    728  * Change the mode of the display.
    729  * Right now all we can do is grfon/grfoff.
    730  * Return a UNIX error number or 0 for success.
    731  */
    732 rt_mode(gp, cmd, arg)
    733 	register struct grf_softc *gp;
    734 	int cmd;
    735 	void *arg;
    736 {
    737   /* implement these later... */
    738 
    739   switch (cmd)
    740     {
    741     case GM_GRFON:
    742       return 0;
    743 
    744     case GM_GRFOFF:
    745       return 0;
    746 
    747     case GM_GRFCONFIG:
    748       return 0;
    749 
    750     case GM_GRFGETVMODE:
    751       return rt_getvmode (gp, (struct grfvideo_mode *) arg);
    752 
    753     case GM_GRFSETVMODE:
    754       return rt_setvmode (gp, *(unsigned *) arg);
    755 
    756     case GM_GRFGETNUMVM:
    757       *(int *)arg = retina_mon_max;
    758       return 0;
    759 
    760     default:
    761       break;
    762     }
    763 
    764   return EINVAL;
    765 }
    766 
    767 #endif	/* NGRF */
    768