1 1.26 andvar /* $NetBSD: vga_subr.c,v 1.26 2023/05/06 21:34:40 andvar Exp $ */ 2 1.1 drochner 3 1.1 drochner /* 4 1.1 drochner * Copyright (c) 1998 5 1.1 drochner * Matthias Drochner. All rights reserved. 6 1.1 drochner * 7 1.1 drochner * Redistribution and use in source and binary forms, with or without 8 1.1 drochner * modification, are permitted provided that the following conditions 9 1.1 drochner * are met: 10 1.1 drochner * 1. Redistributions of source code must retain the above copyright 11 1.1 drochner * notice, this list of conditions and the following disclaimer. 12 1.1 drochner * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 drochner * notice, this list of conditions and the following disclaimer in the 14 1.1 drochner * documentation and/or other materials provided with the distribution. 15 1.1 drochner * 16 1.1 drochner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 drochner * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 drochner * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 drochner * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 drochner * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.1 drochner * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.1 drochner * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.1 drochner * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.1 drochner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.1 drochner * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.1 drochner * 27 1.1 drochner */ 28 1.7 lukem 29 1.21 dsl #include <sys/cdefs.h> 30 1.26 andvar __KERNEL_RCSID(0, "$NetBSD: vga_subr.c,v 1.26 2023/05/06 21:34:40 andvar Exp $"); 31 1.21 dsl 32 1.18 jmmv /* for WSDISPLAY_BORDER_COLOR */ 33 1.18 jmmv #include "opt_wsdisplay_border.h" 34 1.18 jmmv 35 1.1 drochner #include <sys/param.h> 36 1.1 drochner #include <sys/systm.h> 37 1.1 drochner #include <sys/device.h> 38 1.1 drochner #include <sys/queue.h> 39 1.22 ad #include <sys/bus.h> 40 1.1 drochner 41 1.2 drochner #include <dev/ic/mc6845reg.h> 42 1.14 tsutsui #include <dev/ic/pcdisplay.h> 43 1.2 drochner #include <dev/ic/pcdisplayvar.h> 44 1.1 drochner #include <dev/ic/vgareg.h> 45 1.1 drochner #include <dev/ic/vgavar.h> 46 1.1 drochner 47 1.1 drochner #include <dev/wscons/wsdisplayvar.h> 48 1.1 drochner 49 1.8 junyoung static void fontram(struct vga_handle *); 50 1.8 junyoung static void textram(struct vga_handle *); 51 1.1 drochner 52 1.1 drochner static void 53 1.8 junyoung fontram(struct vga_handle *vh) 54 1.1 drochner { 55 1.12 tsutsui 56 1.1 drochner /* program sequencer to access character generator */ 57 1.1 drochner 58 1.1 drochner vga_ts_write(vh, syncreset, 0x01); /* synchronous reset */ 59 1.1 drochner vga_ts_write(vh, wrplmask, 0x04); /* write to map 2 */ 60 1.1 drochner vga_ts_write(vh, memmode, 0x07); /* sequential addressing */ 61 1.1 drochner vga_ts_write(vh, syncreset, 0x03); /* clear synchronous reset */ 62 1.1 drochner 63 1.1 drochner /* program graphics controller to access character generator */ 64 1.1 drochner 65 1.16 wiz vga_gdc_write(vh, rdplanesel, 0x02); /* select map 2 for CPU reads */ 66 1.1 drochner vga_gdc_write(vh, mode, 0x00); /* disable odd-even addressing */ 67 1.1 drochner vga_gdc_write(vh, misc, 0x04); /* map starts at 0xA000 */ 68 1.1 drochner } 69 1.1 drochner 70 1.1 drochner static void 71 1.8 junyoung textram(struct vga_handle *vh) 72 1.1 drochner { 73 1.12 tsutsui 74 1.1 drochner /* program sequencer to access video ram */ 75 1.1 drochner 76 1.1 drochner vga_ts_write(vh, syncreset, 0x01); /* synchronous reset */ 77 1.1 drochner vga_ts_write(vh, wrplmask, 0x03); /* write to map 0 & 1 */ 78 1.1 drochner vga_ts_write(vh, memmode, 0x03); /* odd-even addressing */ 79 1.1 drochner vga_ts_write(vh, syncreset, 0x03); /* clear synchronous reset */ 80 1.1 drochner 81 1.1 drochner /* program graphics controller for text mode */ 82 1.1 drochner 83 1.16 wiz vga_gdc_write(vh, rdplanesel, 0x00); /* select map 0 for CPU reads */ 84 1.1 drochner vga_gdc_write(vh, mode, 0x10); /* enable odd-even addressing */ 85 1.1 drochner /* map starts at 0xb800 or 0xb000 (mono) */ 86 1.2 drochner vga_gdc_write(vh, misc, (vh->vh_mono ? 0x0a : 0x0e)); 87 1.1 drochner } 88 1.1 drochner 89 1.11 junyoung #ifndef VGA_RASTERCONSOLE 90 1.1 drochner void 91 1.10 drochner vga_loadchars(struct vga_handle *vh, int fontset, int first, int num, int lpc, 92 1.15 jdolecek const char *data) 93 1.1 drochner { 94 1.1 drochner int offset, i, j, s; 95 1.1 drochner 96 1.1 drochner /* fontset number swizzle done in vga_setfontset() */ 97 1.1 drochner offset = (fontset << 13) | (first << 5); 98 1.1 drochner 99 1.1 drochner s = splhigh(); 100 1.1 drochner fontram(vh); 101 1.1 drochner 102 1.10 drochner for (i = 0; i < num; i++) 103 1.10 drochner for (j = 0; j < lpc; j++) 104 1.10 drochner bus_space_write_1(vh->vh_memt, vh->vh_allmemh, 105 1.12 tsutsui offset + (i << 5) + j, data[i * lpc + j]); 106 1.1 drochner 107 1.1 drochner textram(vh); 108 1.1 drochner splx(s); 109 1.1 drochner } 110 1.1 drochner 111 1.1 drochner void 112 1.12 tsutsui vga_readoutchars(struct vga_handle *vh, int fontset, int first, int num, 113 1.12 tsutsui int lpc, char *data) 114 1.1 drochner { 115 1.10 drochner int offset, i, j, s; 116 1.10 drochner 117 1.10 drochner /* fontset number swizzle done in vga_setfontset() */ 118 1.10 drochner offset = (fontset << 13) | (first << 5); 119 1.10 drochner 120 1.10 drochner s = splhigh(); 121 1.10 drochner fontram(vh); 122 1.10 drochner 123 1.10 drochner for (i = 0; i < num; i++) 124 1.10 drochner for (j = 0; j < lpc; j++) 125 1.12 tsutsui data[i * lpc + j] = bus_space_read_1(vh->vh_memt, 126 1.12 tsutsui vh->vh_allmemh, offset + (i << 5) + j); 127 1.10 drochner 128 1.10 drochner textram(vh); 129 1.10 drochner splx(s); 130 1.10 drochner } 131 1.10 drochner 132 1.9 junyoung #ifdef VGA_CONSOLE_ATI_BROKEN_FONTSEL 133 1.10 drochner void 134 1.10 drochner vga_copyfont01(struct vga_handle *vh) 135 1.10 drochner { 136 1.9 junyoung int s; 137 1.9 junyoung 138 1.9 junyoung s = splhigh(); 139 1.9 junyoung fontram(vh); 140 1.10 drochner 141 1.12 tsutsui bus_space_copy_region_1(vh->vh_memt, vh->vh_allmemh, 0, 142 1.12 tsutsui vh->vh_allmemh, 1 << 13, 1 << 13); 143 1.10 drochner 144 1.9 junyoung textram(vh); 145 1.9 junyoung splx(s); 146 1.10 drochner } 147 1.10 drochner #endif 148 1.10 drochner 149 1.10 drochner void 150 1.10 drochner vga_setfontset(struct vga_handle *vh, int fontset1, int fontset2) 151 1.10 drochner { 152 1.24 tsutsui uint8_t cmap; 153 1.24 tsutsui static const uint8_t cmaptaba[] = { 154 1.3 drochner 0x00, 0x10, 0x01, 0x11, 155 1.3 drochner 0x02, 0x12, 0x03, 0x13 156 1.1 drochner }; 157 1.24 tsutsui static const uint8_t cmaptabb[] = { 158 1.3 drochner 0x00, 0x20, 0x04, 0x24, 159 1.3 drochner 0x08, 0x28, 0x0c, 0x2c 160 1.1 drochner }; 161 1.1 drochner 162 1.4 drochner /* extended font if fontset1 != fontset2 */ 163 1.3 drochner cmap = cmaptaba[fontset1] | cmaptabb[fontset2]; 164 1.1 drochner 165 1.1 drochner vga_ts_write(vh, fontsel, cmap); 166 1.1 drochner } 167 1.1 drochner 168 1.1 drochner void 169 1.8 junyoung vga_setscreentype(struct vga_handle *vh, const struct wsscreen_descr *type) 170 1.1 drochner { 171 1.12 tsutsui 172 1.1 drochner vga_6845_write(vh, maxrow, type->fontheight - 1); 173 1.1 drochner 174 1.1 drochner /* lo byte */ 175 1.1 drochner vga_6845_write(vh, vde, type->fontheight * type->nrows - 1); 176 1.1 drochner 177 1.6 ad #ifndef PCDISPLAY_SOFTCURSOR 178 1.1 drochner /* set cursor to last 2 lines */ 179 1.1 drochner vga_6845_write(vh, curstart, type->fontheight - 2); 180 1.1 drochner vga_6845_write(vh, curend, type->fontheight - 1); 181 1.5 ad #endif 182 1.3 drochner /* 183 1.3 drochner * disable colour plane 3 if needed for font selection 184 1.3 drochner */ 185 1.3 drochner if (type->capabilities & WSSCREEN_HILIT) { 186 1.3 drochner /* 187 1.3 drochner * these are the screens which don't support 188 1.3 drochner * 512-character fonts 189 1.3 drochner */ 190 1.3 drochner vga_attr_write(vh, colplen, 0x0f); 191 1.3 drochner } else 192 1.3 drochner vga_attr_write(vh, colplen, 0x07); 193 1.1 drochner } 194 1.11 junyoung 195 1.11 junyoung #else /* !VGA_RASTERCONSOLE */ 196 1.11 junyoung void 197 1.24 tsutsui vga_load_builtinfont(struct vga_handle *vh, uint8_t *font, int firstchar, 198 1.11 junyoung int numchars) 199 1.11 junyoung { 200 1.11 junyoung int i, s; 201 1.12 tsutsui 202 1.11 junyoung s = splhigh(); 203 1.11 junyoung fontram(vh); 204 1.11 junyoung 205 1.11 junyoung for (i = firstchar; i < firstchar + numchars; i++) 206 1.11 junyoung bus_space_read_region_1(vh->vh_memt, vh->vh_allmemh, i * 32, 207 1.12 tsutsui font + i * 16, 16); 208 1.12 tsutsui 209 1.11 junyoung textram(vh); 210 1.11 junyoung splx(s); 211 1.11 junyoung } 212 1.11 junyoung #endif /* !VGA_RASTERCONSOLE */ 213 1.14 tsutsui 214 1.14 tsutsui /* 215 1.14 tsutsui * vga_reset(): 216 1.14 tsutsui * Reset VGA registers to put it into 80x25 text mode. (mode 3) 217 1.14 tsutsui * This function should be called from MD consinit() on ports 218 1.14 tsutsui * whose firmware does not use text mode at boot time. 219 1.14 tsutsui */ 220 1.14 tsutsui void 221 1.24 tsutsui vga_reset(struct vga_handle *vh, void (*md_initfunc)(struct vga_handle *)) 222 1.14 tsutsui { 223 1.24 tsutsui uint8_t reg; 224 1.14 tsutsui 225 1.14 tsutsui if (bus_space_map(vh->vh_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga)) 226 1.14 tsutsui return; 227 1.14 tsutsui 228 1.25 uwe reg = vga_raw_read(vh, VGA_MISC_DATAR); 229 1.14 tsutsui vh->vh_mono = !(reg & 0x01); 230 1.14 tsutsui 231 1.14 tsutsui if (bus_space_map(vh->vh_iot, vh->vh_mono ? 0x3b0 : 0x3d0, 0x10, 232 1.14 tsutsui 0, &vh->vh_ioh_6845)) 233 1.14 tsutsui goto out1; 234 1.14 tsutsui 235 1.14 tsutsui if (bus_space_map(vh->vh_memt, 0xa0000, 0x20000, 0, &vh->vh_allmemh)) 236 1.14 tsutsui goto out2; 237 1.14 tsutsui 238 1.14 tsutsui if (bus_space_subregion(vh->vh_memt, vh->vh_allmemh, 239 1.14 tsutsui vh->vh_mono ? 0x10000 : 0x18000, 0x8000, &vh->vh_memh)) 240 1.14 tsutsui goto out3; 241 1.14 tsutsui 242 1.14 tsutsui /* check if VGA already in text mode. */ 243 1.14 tsutsui if ((vga_gdc_read(vh, misc) & 0x01) == 0) 244 1.14 tsutsui goto out3; 245 1.14 tsutsui 246 1.14 tsutsui /* initialize common VGA registers */ 247 1.14 tsutsui vga_initregs(vh); 248 1.14 tsutsui 249 1.14 tsutsui /* initialize chipset specific registers */ 250 1.14 tsutsui if (md_initfunc != NULL) 251 1.14 tsutsui (*md_initfunc)(vh); 252 1.14 tsutsui 253 1.14 tsutsui delay(10000); 254 1.14 tsutsui 255 1.14 tsutsui /* clear text buffer RAM */ 256 1.14 tsutsui bus_space_set_region_2(vh->vh_memt, vh->vh_memh, 0, 257 1.14 tsutsui ((BG_BLACK | FG_LIGHTGREY) << 8) | ' ', 80 * 25 /*XXX*/); 258 1.14 tsutsui 259 1.14 tsutsui out3: 260 1.14 tsutsui bus_space_unmap(vh->vh_memt, vh->vh_allmemh, 0x20000); 261 1.14 tsutsui out2: 262 1.14 tsutsui bus_space_unmap(vh->vh_iot, vh->vh_ioh_6845, 0x10); 263 1.14 tsutsui out1: 264 1.14 tsutsui bus_space_unmap(vh->vh_iot, vh->vh_ioh_vga, 0x10); 265 1.14 tsutsui } 266 1.14 tsutsui 267 1.14 tsutsui /* 268 1.14 tsutsui * values to initialize registers. 269 1.14 tsutsui */ 270 1.14 tsutsui 271 1.14 tsutsui /* miscellaneous output register */ 272 1.14 tsutsui #define VGA_MISCOUT 0x66 273 1.14 tsutsui 274 1.14 tsutsui /* sequencer registers */ 275 1.24 tsutsui static const uint8_t vga_ts[] = { 276 1.14 tsutsui 0x03, /* 00: reset */ 277 1.14 tsutsui 0x00, /* 01: clocking mode */ 278 1.14 tsutsui 0x03, /* 02: map mask */ 279 1.14 tsutsui 0x00, /* 03: character map select */ 280 1.14 tsutsui 0x02 /* 04: memory mode */ 281 1.14 tsutsui }; 282 1.14 tsutsui 283 1.14 tsutsui /* CRT controller registers */ 284 1.24 tsutsui static const uint8_t vga_crtc[] = { 285 1.14 tsutsui 0x5f, /* 00: horizontal total */ 286 1.14 tsutsui 0x4f, /* 01: horizontal display-enable end */ 287 1.14 tsutsui 0x50, /* 02: start horizontal blanking */ 288 1.14 tsutsui 0x82, /* 03: display skew control / end horizontal blanking */ 289 1.14 tsutsui 0x55, /* 04: start horizontal retrace pulse */ 290 1.14 tsutsui 0x81, /* 05: horizontal retrace delay / end horizontal retrace */ 291 1.19 tsutsui 0xbf, /* 06: vertical total */ 292 1.14 tsutsui 0x1f, /* 07: overflow register */ 293 1.14 tsutsui 0x00, /* 08: preset row scan */ 294 1.14 tsutsui 0x4f, /* 09: overflow / maximum scan line */ 295 1.14 tsutsui 0x0d, /* 0A: cursor off / cursor start */ 296 1.14 tsutsui 0x0e, /* 0B: cursor skew / cursor end */ 297 1.14 tsutsui 0x00, /* 0C: start regenerative buffer address high */ 298 1.14 tsutsui 0x00, /* 0D: start regenerative buffer address low */ 299 1.14 tsutsui 0x00, /* 0E: cursor location high */ 300 1.14 tsutsui 0x00, /* 0F: cursor location low */ 301 1.14 tsutsui 0x9c, /* 10: vertical retrace start */ 302 1.14 tsutsui 0x8e, /* 11: vertical interrupt / vertical retrace end */ 303 1.14 tsutsui 0x8f, /* 12: vertical display enable end */ 304 1.14 tsutsui 0x28, /* 13: logical line width */ 305 1.14 tsutsui 0x00, /* 14: underline location */ 306 1.14 tsutsui 0x96, /* 15: start vertical blanking */ 307 1.14 tsutsui 0xb9, /* 16: end vertical blanking */ 308 1.14 tsutsui 0xa3, /* 17: CRT mode control */ 309 1.14 tsutsui 0xff /* 18: line compare */ 310 1.14 tsutsui }; 311 1.14 tsutsui 312 1.14 tsutsui /* graphics controller registers */ 313 1.24 tsutsui static const uint8_t vga_gdc[] = { 314 1.14 tsutsui 0x00, /* 00: set/reset map */ 315 1.14 tsutsui 0x00, /* 01: enable set/reset */ 316 1.14 tsutsui 0x00, /* 02: color compare */ 317 1.14 tsutsui 0x00, /* 03: data rotate */ 318 1.14 tsutsui 0x00, /* 04: read map select */ 319 1.14 tsutsui 0x10, /* 05: graphics mode */ 320 1.14 tsutsui 0x0e, /* 06: miscellaneous */ 321 1.14 tsutsui 0x00, /* 07: color don't care */ 322 1.14 tsutsui 0xff /* 08: bit mask */ 323 1.14 tsutsui }; 324 1.14 tsutsui 325 1.14 tsutsui /* attribute controller registers */ 326 1.24 tsutsui static const uint8_t vga_atc[] = { 327 1.14 tsutsui 0x00, /* 00: internal palette 0 */ 328 1.14 tsutsui 0x01, /* 01: internal palette 1 */ 329 1.14 tsutsui 0x02, /* 02: internal palette 2 */ 330 1.14 tsutsui 0x03, /* 03: internal palette 3 */ 331 1.14 tsutsui 0x04, /* 04: internal palette 4 */ 332 1.14 tsutsui 0x05, /* 05: internal palette 5 */ 333 1.14 tsutsui 0x14, /* 06: internal palette 6 */ 334 1.14 tsutsui 0x07, /* 07: internal palette 7 */ 335 1.14 tsutsui 0x38, /* 08: internal palette 8 */ 336 1.14 tsutsui 0x39, /* 09: internal palette 9 */ 337 1.14 tsutsui 0x3a, /* 0A: internal palette 10 */ 338 1.14 tsutsui 0x3b, /* 0B: internal palette 11 */ 339 1.14 tsutsui 0x3c, /* 0C: internal palette 12 */ 340 1.14 tsutsui 0x3d, /* 0D: internal palette 13 */ 341 1.14 tsutsui 0x3e, /* 0E: internal palette 14 */ 342 1.14 tsutsui 0x3f, /* 0F: internal palette 15 */ 343 1.14 tsutsui 0x0c, /* 10: attribute mode control */ 344 1.18 jmmv WSDISPLAY_BORDER_COLOR, /* 11: overscan color */ 345 1.14 tsutsui 0x0f, /* 12: color plane enable */ 346 1.14 tsutsui 0x08, /* 13: horizontal PEL panning */ 347 1.14 tsutsui 0x00 /* 14: color select */ 348 1.14 tsutsui }; 349 1.14 tsutsui 350 1.14 tsutsui /* video DAC palette registers */ 351 1.26 andvar /* XXX only set up 16 colors used by internal palette in ATC registers */ 352 1.24 tsutsui static const uint8_t vga_dacpal[] = { 353 1.14 tsutsui /* R G B */ 354 1.14 tsutsui 0x00, 0x00, 0x00, /* BLACK */ 355 1.14 tsutsui 0x00, 0x00, 0x2a, /* BLUE */ 356 1.14 tsutsui 0x00, 0x2a, 0x00, /* GREEN */ 357 1.14 tsutsui 0x00, 0x2a, 0x2a, /* CYAN */ 358 1.14 tsutsui 0x2a, 0x00, 0x00, /* RED */ 359 1.14 tsutsui 0x2a, 0x00, 0x2a, /* MAGENTA */ 360 1.14 tsutsui 0x2a, 0x15, 0x00, /* BROWN */ 361 1.14 tsutsui 0x2a, 0x2a, 0x2a, /* LIGHTGREY */ 362 1.14 tsutsui 0x15, 0x15, 0x15, /* DARKGREY */ 363 1.14 tsutsui 0x15, 0x15, 0x3f, /* LIGHTBLUE */ 364 1.14 tsutsui 0x15, 0x3f, 0x15, /* LIGHTGREEN */ 365 1.14 tsutsui 0x15, 0x3f, 0x3f, /* LIGHTCYAN */ 366 1.14 tsutsui 0x3f, 0x15, 0x15, /* LIGHTRED */ 367 1.14 tsutsui 0x3f, 0x15, 0x3f, /* LIGHTMAGENTA */ 368 1.14 tsutsui 0x3f, 0x3f, 0x15, /* YELLOW */ 369 1.14 tsutsui 0x3f, 0x3f, 0x3f /* WHITE */ 370 1.14 tsutsui }; 371 1.14 tsutsui 372 1.23 jmcneill void 373 1.24 tsutsui vga_initregs(struct vga_handle *vh) 374 1.14 tsutsui { 375 1.14 tsutsui int i; 376 1.14 tsutsui 377 1.14 tsutsui /* disable video */ 378 1.14 tsutsui vga_ts_write(vh, mode, vga_ts[1] | VGA_TS_MODE_BLANK); 379 1.14 tsutsui 380 1.14 tsutsui /* synchronous reset */ 381 1.14 tsutsui vga_ts_write(vh, syncreset, 0x01); 382 1.26 andvar /* set TS registers */ 383 1.14 tsutsui for (i = 2; i < VGA_TS_NREGS; i++) 384 1.14 tsutsui _vga_ts_write(vh, i, vga_ts[i]); 385 1.14 tsutsui /* clear synchronous reset */ 386 1.14 tsutsui vga_ts_write(vh, syncreset, 0x03); 387 1.14 tsutsui 388 1.26 andvar /* unprotect CRTC registers */ 389 1.14 tsutsui vga_6845_write(vh, vsynce, vga_6845_read(vh, vsynce) & ~0x80); 390 1.26 andvar /* set CRTC registers */ 391 1.14 tsutsui for (i = 0; i < MC6845_NREGS; i++) 392 1.14 tsutsui _vga_6845_write(vh, i, vga_crtc[i]); 393 1.14 tsutsui 394 1.26 andvar /* set GDC registers */ 395 1.14 tsutsui for (i = 0; i < VGA_GDC_NREGS; i++) 396 1.14 tsutsui _vga_gdc_write(vh, i, vga_gdc[i]); 397 1.14 tsutsui 398 1.26 andvar /* set ATC registers */ 399 1.14 tsutsui for (i = 0; i < VGA_ATC_NREGS; i++) 400 1.14 tsutsui _vga_attr_write(vh, i, vga_atc[i]); 401 1.14 tsutsui 402 1.14 tsutsui /* set DAC palette */ 403 1.14 tsutsui if (!vh->vh_mono) { 404 1.14 tsutsui for (i = 0; i < 16; i++) { 405 1.25 uwe vga_raw_write(vh, 406 1.14 tsutsui VGA_DAC_ADDRW, vga_atc[i]); 407 1.25 uwe vga_raw_write(vh, 408 1.14 tsutsui VGA_DAC_PALETTE, vga_dacpal[i * 3 + 0]); 409 1.25 uwe vga_raw_write(vh, 410 1.14 tsutsui VGA_DAC_PALETTE, vga_dacpal[i * 3 + 1]); 411 1.25 uwe vga_raw_write(vh, 412 1.14 tsutsui VGA_DAC_PALETTE, vga_dacpal[i * 3 + 2]); 413 1.14 tsutsui } 414 1.14 tsutsui } 415 1.14 tsutsui 416 1.14 tsutsui /* set misc output register */ 417 1.25 uwe vga_raw_write(vh, 418 1.14 tsutsui VGA_MISC_DATAW, VGA_MISCOUT | (vh->vh_mono ? 0 : 0x01)); 419 1.14 tsutsui 420 1.14 tsutsui /* reenable video */ 421 1.14 tsutsui vga_ts_write(vh, mode, vga_ts[1] & ~VGA_TS_MODE_BLANK); 422 1.14 tsutsui } 423