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