xref: /illumos-gate/usr/src/cmd/bhyve/vga.c (revision 32640292)
1bf21cd93STycho Nightingale /*-
2*32640292SAndy Fiddaman  * SPDX-License-Identifier: BSD-2-Clause
34c87aefeSPatrick Mooney  *
4bf21cd93STycho Nightingale  * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
5bf21cd93STycho Nightingale  * All rights reserved.
6bf21cd93STycho Nightingale  *
7bf21cd93STycho Nightingale  * Redistribution and use in source and binary forms, with or without
8bf21cd93STycho Nightingale  * modification, are permitted provided that the following conditions
9bf21cd93STycho Nightingale  * are met:
10bf21cd93STycho Nightingale  * 1. Redistributions of source code must retain the above copyright
11bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer.
12bf21cd93STycho Nightingale  * 2. Redistributions in binary form must reproduce the above copyright
13bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer in the
14bf21cd93STycho Nightingale  *    documentation and/or other materials provided with the distribution.
15bf21cd93STycho Nightingale  *
16bf21cd93STycho Nightingale  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
17bf21cd93STycho Nightingale  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18bf21cd93STycho Nightingale  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19bf21cd93STycho Nightingale  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20bf21cd93STycho Nightingale  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21bf21cd93STycho Nightingale  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22bf21cd93STycho Nightingale  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23bf21cd93STycho Nightingale  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24bf21cd93STycho Nightingale  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25bf21cd93STycho Nightingale  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26bf21cd93STycho Nightingale  * SUCH DAMAGE.
27bf21cd93STycho Nightingale  */
28bf21cd93STycho Nightingale 
294c87aefeSPatrick Mooney /*
304c87aefeSPatrick Mooney  * Copyright 2018 Joyent, Inc.
314c87aefeSPatrick Mooney  */
324c87aefeSPatrick Mooney 
33bf21cd93STycho Nightingale #include <sys/cdefs.h>
34bf21cd93STycho Nightingale 
35bf21cd93STycho Nightingale #include <sys/param.h>
36bf21cd93STycho Nightingale 
37bf21cd93STycho Nightingale #include <assert.h>
38bf21cd93STycho Nightingale #include <pthread.h>
39bf21cd93STycho Nightingale #include <stdbool.h>
40bf21cd93STycho Nightingale #include <stdio.h>
41bf21cd93STycho Nightingale #include <stdlib.h>
42bf21cd93STycho Nightingale #include <string.h>
43bf21cd93STycho Nightingale 
44bf21cd93STycho Nightingale #include <machine/vmm.h>
45bf21cd93STycho Nightingale 
46bf21cd93STycho Nightingale #include "bhyvegc.h"
47bf21cd93STycho Nightingale #include "console.h"
48bf21cd93STycho Nightingale #include "inout.h"
49bf21cd93STycho Nightingale #include "mem.h"
50bf21cd93STycho Nightingale #include "vga.h"
51bf21cd93STycho Nightingale 
52bf21cd93STycho Nightingale #define	KB	(1024UL)
53bf21cd93STycho Nightingale #define	MB	(1024 * 1024UL)
54bf21cd93STycho Nightingale 
55bf21cd93STycho Nightingale struct vga_softc {
56bf21cd93STycho Nightingale 	struct mem_range	mr;
57bf21cd93STycho Nightingale 
58bf21cd93STycho Nightingale 	struct bhyvegc		*gc;
59bf21cd93STycho Nightingale 	int			gc_width;
60bf21cd93STycho Nightingale 	int			gc_height;
61bf21cd93STycho Nightingale 	struct bhyvegc_image	*gc_image;
62bf21cd93STycho Nightingale 
63bf21cd93STycho Nightingale 	uint8_t			*vga_ram;
64bf21cd93STycho Nightingale 
65bf21cd93STycho Nightingale 	/*
66bf21cd93STycho Nightingale 	 * General registers
67bf21cd93STycho Nightingale 	 */
68bf21cd93STycho Nightingale 	uint8_t			vga_misc;
69bf21cd93STycho Nightingale 	uint8_t			vga_sts1;
70bf21cd93STycho Nightingale 
71bf21cd93STycho Nightingale 	/*
72bf21cd93STycho Nightingale 	 * Sequencer
73bf21cd93STycho Nightingale 	 */
74bf21cd93STycho Nightingale 	struct {
75bf21cd93STycho Nightingale 		int		seq_index;
76bf21cd93STycho Nightingale 		uint8_t		seq_reset;
77bf21cd93STycho Nightingale 		uint8_t		seq_clock_mode;
78bf21cd93STycho Nightingale 		int		seq_cm_dots;
79bf21cd93STycho Nightingale 		uint8_t		seq_map_mask;
80bf21cd93STycho Nightingale 		uint8_t		seq_cmap_sel;
81bf21cd93STycho Nightingale 		int		seq_cmap_pri_off;
82bf21cd93STycho Nightingale 		int		seq_cmap_sec_off;
83bf21cd93STycho Nightingale 		uint8_t		seq_mm;
84bf21cd93STycho Nightingale 	} vga_seq;
85bf21cd93STycho Nightingale 
86bf21cd93STycho Nightingale 	/*
87bf21cd93STycho Nightingale 	 * CRT Controller
88bf21cd93STycho Nightingale 	 */
89bf21cd93STycho Nightingale 	struct {
90bf21cd93STycho Nightingale 		int		crtc_index;
91bf21cd93STycho Nightingale 		uint8_t		crtc_mode_ctrl;
92bf21cd93STycho Nightingale 		uint8_t		crtc_horiz_total;
93bf21cd93STycho Nightingale 		uint8_t		crtc_horiz_disp_end;
94bf21cd93STycho Nightingale 		uint8_t		crtc_start_horiz_blank;
95bf21cd93STycho Nightingale 		uint8_t		crtc_end_horiz_blank;
96bf21cd93STycho Nightingale 		uint8_t		crtc_start_horiz_retrace;
97bf21cd93STycho Nightingale 		uint8_t		crtc_end_horiz_retrace;
98bf21cd93STycho Nightingale 		uint8_t		crtc_vert_total;
99bf21cd93STycho Nightingale 		uint8_t		crtc_overflow;
100bf21cd93STycho Nightingale 		uint8_t		crtc_present_row_scan;
101bf21cd93STycho Nightingale 		uint8_t		crtc_max_scan_line;
102bf21cd93STycho Nightingale 		uint8_t		crtc_cursor_start;
103bf21cd93STycho Nightingale 		uint8_t		crtc_cursor_on;
104bf21cd93STycho Nightingale 		uint8_t		crtc_cursor_end;
105bf21cd93STycho Nightingale 		uint8_t		crtc_start_addr_high;
106bf21cd93STycho Nightingale 		uint8_t		crtc_start_addr_low;
107bf21cd93STycho Nightingale 		uint16_t	crtc_start_addr;
108bf21cd93STycho Nightingale 		uint8_t		crtc_cursor_loc_low;
109bf21cd93STycho Nightingale 		uint8_t		crtc_cursor_loc_high;
110bf21cd93STycho Nightingale 		uint16_t	crtc_cursor_loc;
111bf21cd93STycho Nightingale 		uint8_t		crtc_vert_retrace_start;
112bf21cd93STycho Nightingale 		uint8_t		crtc_vert_retrace_end;
113bf21cd93STycho Nightingale 		uint8_t		crtc_vert_disp_end;
114bf21cd93STycho Nightingale 		uint8_t		crtc_offset;
115bf21cd93STycho Nightingale 		uint8_t		crtc_underline_loc;
116bf21cd93STycho Nightingale 		uint8_t		crtc_start_vert_blank;
117bf21cd93STycho Nightingale 		uint8_t		crtc_end_vert_blank;
118bf21cd93STycho Nightingale 		uint8_t		crtc_line_compare;
119bf21cd93STycho Nightingale 	} vga_crtc;
120bf21cd93STycho Nightingale 
121bf21cd93STycho Nightingale 	/*
122bf21cd93STycho Nightingale 	 * Graphics Controller
123bf21cd93STycho Nightingale 	 */
124bf21cd93STycho Nightingale 	struct {
125bf21cd93STycho Nightingale 		int		gc_index;
126bf21cd93STycho Nightingale 		uint8_t		gc_set_reset;
127bf21cd93STycho Nightingale 		uint8_t		gc_enb_set_reset;
128bf21cd93STycho Nightingale 		uint8_t		gc_color_compare;
129bf21cd93STycho Nightingale 		uint8_t		gc_rotate;
130bf21cd93STycho Nightingale 		uint8_t		gc_op;
131bf21cd93STycho Nightingale 		uint8_t		gc_read_map_sel;
132bf21cd93STycho Nightingale 		uint8_t		gc_mode;
133bf21cd93STycho Nightingale 		bool		gc_mode_c4;		/* chain 4 */
134bf21cd93STycho Nightingale 		bool		gc_mode_oe;		/* odd/even */
135bf21cd93STycho Nightingale 		uint8_t		gc_mode_rm;		/* read mode */
136bf21cd93STycho Nightingale 		uint8_t		gc_mode_wm;		/* write mode */
137bf21cd93STycho Nightingale 		uint8_t		gc_misc;
138bf21cd93STycho Nightingale 		uint8_t		gc_misc_gm;		/* graphics mode */
139bf21cd93STycho Nightingale 		uint8_t		gc_misc_mm;		/* memory map */
140bf21cd93STycho Nightingale 		uint8_t		gc_color_dont_care;
141bf21cd93STycho Nightingale 		uint8_t		gc_bit_mask;
142bf21cd93STycho Nightingale 		uint8_t		gc_latch0;
143bf21cd93STycho Nightingale 		uint8_t		gc_latch1;
144bf21cd93STycho Nightingale 		uint8_t		gc_latch2;
145bf21cd93STycho Nightingale 		uint8_t		gc_latch3;
146bf21cd93STycho Nightingale 	} vga_gc;
147bf21cd93STycho Nightingale 
148bf21cd93STycho Nightingale 	/*
149bf21cd93STycho Nightingale 	 * Attribute Controller
150bf21cd93STycho Nightingale 	 */
151bf21cd93STycho Nightingale 	struct {
152bf21cd93STycho Nightingale 		int		atc_flipflop;
153bf21cd93STycho Nightingale 		int		atc_index;
154bf21cd93STycho Nightingale 		uint8_t		atc_palette[16];
155bf21cd93STycho Nightingale 		uint8_t		atc_mode;
156bf21cd93STycho Nightingale 		uint8_t		atc_overscan_color;
157bf21cd93STycho Nightingale 		uint8_t		atc_color_plane_enb;
158bf21cd93STycho Nightingale 		uint8_t		atc_horiz_pixel_panning;
159bf21cd93STycho Nightingale 		uint8_t		atc_color_select;
160bf21cd93STycho Nightingale 		uint8_t		atc_color_select_45;
161bf21cd93STycho Nightingale 		uint8_t		atc_color_select_67;
162bf21cd93STycho Nightingale 	} vga_atc;
163bf21cd93STycho Nightingale 
164bf21cd93STycho Nightingale 	/*
165bf21cd93STycho Nightingale 	 * DAC
166bf21cd93STycho Nightingale 	 */
167bf21cd93STycho Nightingale 	struct {
168bf21cd93STycho Nightingale 		uint8_t		dac_state;
1694c87aefeSPatrick Mooney 		uint8_t		dac_rd_index;
1704c87aefeSPatrick Mooney 		uint8_t		dac_rd_subindex;
1714c87aefeSPatrick Mooney 		uint8_t		dac_wr_index;
1724c87aefeSPatrick Mooney 		uint8_t		dac_wr_subindex;
173bf21cd93STycho Nightingale 		uint8_t		dac_palette[3 * 256];
174bf21cd93STycho Nightingale 		uint32_t	dac_palette_rgb[256];
175bf21cd93STycho Nightingale 	} vga_dac;
176bf21cd93STycho Nightingale };
177bf21cd93STycho Nightingale 
178bf21cd93STycho Nightingale static bool
vga_in_reset(struct vga_softc * sc)179bf21cd93STycho Nightingale vga_in_reset(struct vga_softc *sc)
180bf21cd93STycho Nightingale {
181bf21cd93STycho Nightingale 	return (((sc->vga_seq.seq_clock_mode & SEQ_CM_SO) != 0) ||
182bf21cd93STycho Nightingale 	    ((sc->vga_seq.seq_reset & SEQ_RESET_ASYNC) == 0) ||
183bf21cd93STycho Nightingale 	    ((sc->vga_seq.seq_reset & SEQ_RESET_SYNC) == 0) ||
184bf21cd93STycho Nightingale 	    ((sc->vga_crtc.crtc_mode_ctrl & CRTC_MC_TE) == 0));
185bf21cd93STycho Nightingale }
186bf21cd93STycho Nightingale 
187bf21cd93STycho Nightingale static void
vga_check_size(struct bhyvegc * gc,struct vga_softc * sc)188bf21cd93STycho Nightingale vga_check_size(struct bhyvegc *gc, struct vga_softc *sc)
189bf21cd93STycho Nightingale {
190bf21cd93STycho Nightingale 	int old_width, old_height;
191bf21cd93STycho Nightingale 
192bf21cd93STycho Nightingale 	if (vga_in_reset(sc))
193bf21cd93STycho Nightingale 		return;
194bf21cd93STycho Nightingale 
1954c87aefeSPatrick Mooney 	//old_width = sc->gc_width;
1964c87aefeSPatrick Mooney 	//old_height = sc->gc_height;
1974c87aefeSPatrick Mooney 	old_width = sc->gc_image->width;
1984c87aefeSPatrick Mooney 	old_height = sc->gc_image->height;
199bf21cd93STycho Nightingale 
200bf21cd93STycho Nightingale 	/*
201bf21cd93STycho Nightingale 	 * Horizontal Display End: For text modes this is the number
202bf21cd93STycho Nightingale 	 * of characters.  For graphics modes this is the number of
203bf21cd93STycho Nightingale 	 * pixels per scanlines divided by the number of pixels per
204bf21cd93STycho Nightingale 	 * character clock.
205bf21cd93STycho Nightingale 	 */
206bf21cd93STycho Nightingale 	sc->gc_width = (sc->vga_crtc.crtc_horiz_disp_end + 1) *
207bf21cd93STycho Nightingale 	    sc->vga_seq.seq_cm_dots;
208bf21cd93STycho Nightingale 
209bf21cd93STycho Nightingale 	sc->gc_height = (sc->vga_crtc.crtc_vert_disp_end |
210bf21cd93STycho Nightingale 	    (((sc->vga_crtc.crtc_overflow & CRTC_OF_VDE8) >> CRTC_OF_VDE8_SHIFT) << 8) |
211bf21cd93STycho Nightingale 	    (((sc->vga_crtc.crtc_overflow & CRTC_OF_VDE9) >> CRTC_OF_VDE9_SHIFT) << 9)) + 1;
212bf21cd93STycho Nightingale 
213bf21cd93STycho Nightingale 	if (old_width != sc->gc_width || old_height != sc->gc_height)
214bf21cd93STycho Nightingale 		bhyvegc_resize(gc, sc->gc_width, sc->gc_height);
215bf21cd93STycho Nightingale }
216bf21cd93STycho Nightingale 
217bf21cd93STycho Nightingale static uint32_t
vga_get_pixel(struct vga_softc * sc,int x,int y)218bf21cd93STycho Nightingale vga_get_pixel(struct vga_softc *sc, int x, int y)
219bf21cd93STycho Nightingale {
220bf21cd93STycho Nightingale 	int offset;
221bf21cd93STycho Nightingale 	int bit;
222bf21cd93STycho Nightingale 	uint8_t data;
223bf21cd93STycho Nightingale 	uint8_t idx;
224bf21cd93STycho Nightingale 
225bf21cd93STycho Nightingale 	offset = (y * sc->gc_width / 8) + (x / 8);
226bf21cd93STycho Nightingale 	bit = 7 - (x % 8);
227bf21cd93STycho Nightingale 
228bf21cd93STycho Nightingale 	data = (((sc->vga_ram[offset + 0 * 64*KB] >> bit) & 0x1) << 0) |
229bf21cd93STycho Nightingale 		(((sc->vga_ram[offset + 1 * 64*KB] >> bit) & 0x1) << 1) |
230bf21cd93STycho Nightingale 		(((sc->vga_ram[offset + 2 * 64*KB] >> bit) & 0x1) << 2) |
231bf21cd93STycho Nightingale 		(((sc->vga_ram[offset + 3 * 64*KB] >> bit) & 0x1) << 3);
232bf21cd93STycho Nightingale 
233bf21cd93STycho Nightingale 	data &= sc->vga_atc.atc_color_plane_enb;
234bf21cd93STycho Nightingale 
235bf21cd93STycho Nightingale 	if (sc->vga_atc.atc_mode & ATC_MC_IPS) {
236bf21cd93STycho Nightingale 		idx = sc->vga_atc.atc_palette[data] & 0x0f;
237bf21cd93STycho Nightingale 		idx |= sc->vga_atc.atc_color_select_45;
238bf21cd93STycho Nightingale 	} else {
239bf21cd93STycho Nightingale 		idx = sc->vga_atc.atc_palette[data];
240bf21cd93STycho Nightingale 	}
241bf21cd93STycho Nightingale 	idx |= sc->vga_atc.atc_color_select_67;
242bf21cd93STycho Nightingale 
243bf21cd93STycho Nightingale 	return (sc->vga_dac.dac_palette_rgb[idx]);
244bf21cd93STycho Nightingale }
245bf21cd93STycho Nightingale 
246bf21cd93STycho Nightingale static void
vga_render_graphics(struct vga_softc * sc)247bf21cd93STycho Nightingale vga_render_graphics(struct vga_softc *sc)
248bf21cd93STycho Nightingale {
249bf21cd93STycho Nightingale 	int x, y;
250bf21cd93STycho Nightingale 
251bf21cd93STycho Nightingale 	for (y = 0; y < sc->gc_height; y++) {
252bf21cd93STycho Nightingale 		for (x = 0; x < sc->gc_width; x++) {
253bf21cd93STycho Nightingale 			int offset;
254bf21cd93STycho Nightingale 
255bf21cd93STycho Nightingale 			offset = y * sc->gc_width + x;
256bf21cd93STycho Nightingale 			sc->gc_image->data[offset] = vga_get_pixel(sc, x, y);
257bf21cd93STycho Nightingale 		}
258bf21cd93STycho Nightingale 	}
259bf21cd93STycho Nightingale }
260bf21cd93STycho Nightingale 
261bf21cd93STycho Nightingale static uint32_t
vga_get_text_pixel(struct vga_softc * sc,int x,int y)262bf21cd93STycho Nightingale vga_get_text_pixel(struct vga_softc *sc, int x, int y)
263bf21cd93STycho Nightingale {
264bf21cd93STycho Nightingale 	int dots, offset, bit, font_offset;
265bf21cd93STycho Nightingale 	uint8_t ch, attr, font;
266bf21cd93STycho Nightingale 	uint8_t idx;
267bf21cd93STycho Nightingale 
268bf21cd93STycho Nightingale 	dots = sc->vga_seq.seq_cm_dots;
269bf21cd93STycho Nightingale 
270bf21cd93STycho Nightingale 	offset = 2 * sc->vga_crtc.crtc_start_addr;
271bf21cd93STycho Nightingale 	offset += (y / 16 * sc->gc_width / dots) * 2 + (x / dots) * 2;
272bf21cd93STycho Nightingale 
2734c87aefeSPatrick Mooney 	bit = 7 - (x % dots > 7 ? 7 : x % dots);
274bf21cd93STycho Nightingale 
275bf21cd93STycho Nightingale 	ch = sc->vga_ram[offset + 0 * 64*KB];
276bf21cd93STycho Nightingale 	attr = sc->vga_ram[offset + 1 * 64*KB];
277bf21cd93STycho Nightingale 
278bf21cd93STycho Nightingale 	if (sc->vga_crtc.crtc_cursor_on &&
279bf21cd93STycho Nightingale 	    (offset == (sc->vga_crtc.crtc_cursor_loc * 2)) &&
280bf21cd93STycho Nightingale 	    ((y % 16) >= (sc->vga_crtc.crtc_cursor_start & CRTC_CS_CS)) &&
281bf21cd93STycho Nightingale 	    ((y % 16) <= (sc->vga_crtc.crtc_cursor_end & CRTC_CE_CE))) {
282bf21cd93STycho Nightingale 		idx = sc->vga_atc.atc_palette[attr & 0xf];
283bf21cd93STycho Nightingale 		return (sc->vga_dac.dac_palette_rgb[idx]);
284bf21cd93STycho Nightingale 	}
285bf21cd93STycho Nightingale 
286bf21cd93STycho Nightingale 	if ((sc->vga_seq.seq_mm & SEQ_MM_EM) &&
287bf21cd93STycho Nightingale 	    sc->vga_seq.seq_cmap_pri_off != sc->vga_seq.seq_cmap_sec_off) {
288bf21cd93STycho Nightingale 		if (attr & 0x8)
289bf21cd93STycho Nightingale 			font_offset = sc->vga_seq.seq_cmap_pri_off +
290bf21cd93STycho Nightingale 				(ch << 5) + y % 16;
291bf21cd93STycho Nightingale 		else
292bf21cd93STycho Nightingale 			font_offset = sc->vga_seq.seq_cmap_sec_off +
293bf21cd93STycho Nightingale 				(ch << 5) + y % 16;
294bf21cd93STycho Nightingale 		attr &= ~0x8;
295bf21cd93STycho Nightingale 	} else {
296bf21cd93STycho Nightingale 		font_offset = (ch << 5) + y % 16;
297bf21cd93STycho Nightingale 	}
298bf21cd93STycho Nightingale 
299bf21cd93STycho Nightingale 	font = sc->vga_ram[font_offset + 2 * 64*KB];
300bf21cd93STycho Nightingale 
3014c87aefeSPatrick Mooney 	if (font & (1 << bit))
302bf21cd93STycho Nightingale 		idx = sc->vga_atc.atc_palette[attr & 0xf];
303bf21cd93STycho Nightingale 	else
304bf21cd93STycho Nightingale 		idx = sc->vga_atc.atc_palette[attr >> 4];
305bf21cd93STycho Nightingale 
306bf21cd93STycho Nightingale 	return (sc->vga_dac.dac_palette_rgb[idx]);
307bf21cd93STycho Nightingale }
308bf21cd93STycho Nightingale 
309bf21cd93STycho Nightingale static void
vga_render_text(struct vga_softc * sc)310bf21cd93STycho Nightingale vga_render_text(struct vga_softc *sc)
311bf21cd93STycho Nightingale {
312bf21cd93STycho Nightingale 	int x, y;
313bf21cd93STycho Nightingale 
314bf21cd93STycho Nightingale 	for (y = 0; y < sc->gc_height; y++) {
315bf21cd93STycho Nightingale 		for (x = 0; x < sc->gc_width; x++) {
316bf21cd93STycho Nightingale 			int offset;
317bf21cd93STycho Nightingale 
318bf21cd93STycho Nightingale 			offset = y * sc->gc_width + x;
319bf21cd93STycho Nightingale 			sc->gc_image->data[offset] = vga_get_text_pixel(sc, x, y);
320bf21cd93STycho Nightingale 		}
321bf21cd93STycho Nightingale 	}
322bf21cd93STycho Nightingale }
323bf21cd93STycho Nightingale 
3244c87aefeSPatrick Mooney void
vga_render(struct bhyvegc * gc,void * arg)325bf21cd93STycho Nightingale vga_render(struct bhyvegc *gc, void *arg)
326bf21cd93STycho Nightingale {
327bf21cd93STycho Nightingale 	struct vga_softc *sc = arg;
328bf21cd93STycho Nightingale 
329bf21cd93STycho Nightingale 	vga_check_size(gc, sc);
330bf21cd93STycho Nightingale 
331bf21cd93STycho Nightingale 	if (vga_in_reset(sc)) {
332bf21cd93STycho Nightingale 		memset(sc->gc_image->data, 0,
333bf21cd93STycho Nightingale 		    sc->gc_image->width * sc->gc_image->height *
334bf21cd93STycho Nightingale 		     sizeof (uint32_t));
335bf21cd93STycho Nightingale 		return;
336bf21cd93STycho Nightingale 	}
337bf21cd93STycho Nightingale 
338bf21cd93STycho Nightingale 	if (sc->vga_gc.gc_misc_gm && (sc->vga_atc.atc_mode & ATC_MC_GA))
339bf21cd93STycho Nightingale 		vga_render_graphics(sc);
340bf21cd93STycho Nightingale 	else
341bf21cd93STycho Nightingale 		vga_render_text(sc);
342bf21cd93STycho Nightingale }
343bf21cd93STycho Nightingale 
344bf21cd93STycho Nightingale static uint64_t
vga_mem_rd_handler(uint64_t addr,void * arg1)345*32640292SAndy Fiddaman vga_mem_rd_handler(uint64_t addr, void *arg1)
346bf21cd93STycho Nightingale {
347bf21cd93STycho Nightingale 	struct vga_softc *sc = arg1;
348bf21cd93STycho Nightingale 	uint8_t map_sel;
349bf21cd93STycho Nightingale 	int offset;
350bf21cd93STycho Nightingale 
351bf21cd93STycho Nightingale 	offset = addr;
352bf21cd93STycho Nightingale 	switch (sc->vga_gc.gc_misc_mm) {
353bf21cd93STycho Nightingale 	case 0x0:
354bf21cd93STycho Nightingale 		/*
355bf21cd93STycho Nightingale 		 * extended mode: base 0xa0000 size 128k
356bf21cd93STycho Nightingale 		 */
357bf21cd93STycho Nightingale 		offset -=0xa0000;
358bf21cd93STycho Nightingale 		offset &= (128 * KB - 1);
359bf21cd93STycho Nightingale 		break;
360bf21cd93STycho Nightingale 	case 0x1:
361bf21cd93STycho Nightingale 		/*
362bf21cd93STycho Nightingale 		 * EGA/VGA mode: base 0xa0000 size 64k
363bf21cd93STycho Nightingale 		 */
364bf21cd93STycho Nightingale 		offset -=0xa0000;
365bf21cd93STycho Nightingale 		offset &= (64 * KB - 1);
366bf21cd93STycho Nightingale 		break;
367bf21cd93STycho Nightingale 	case 0x2:
368bf21cd93STycho Nightingale 		/*
369bf21cd93STycho Nightingale 		 * monochrome text mode: base 0xb0000 size 32kb
370bf21cd93STycho Nightingale 		 */
3714c87aefeSPatrick Mooney #ifdef __FreeBSD__
372bf21cd93STycho Nightingale 		assert(0);
3734c87aefeSPatrick Mooney #else
3744c87aefeSPatrick Mooney 		abort();
3754c87aefeSPatrick Mooney #endif
376bf21cd93STycho Nightingale 	case 0x3:
377bf21cd93STycho Nightingale 		/*
378bf21cd93STycho Nightingale 		 * color text mode and CGA: base 0xb8000 size 32kb
379bf21cd93STycho Nightingale 		 */
380bf21cd93STycho Nightingale 		offset -=0xb8000;
381bf21cd93STycho Nightingale 		offset &= (32 * KB - 1);
382bf21cd93STycho Nightingale 		break;
383bf21cd93STycho Nightingale 	}
384bf21cd93STycho Nightingale 
385bf21cd93STycho Nightingale 	/* Fill latches. */
386bf21cd93STycho Nightingale 	sc->vga_gc.gc_latch0 = sc->vga_ram[offset + 0*64*KB];
387bf21cd93STycho Nightingale 	sc->vga_gc.gc_latch1 = sc->vga_ram[offset + 1*64*KB];
388bf21cd93STycho Nightingale 	sc->vga_gc.gc_latch2 = sc->vga_ram[offset + 2*64*KB];
389bf21cd93STycho Nightingale 	sc->vga_gc.gc_latch3 = sc->vga_ram[offset + 3*64*KB];
390bf21cd93STycho Nightingale 
391bf21cd93STycho Nightingale 	if (sc->vga_gc.gc_mode_rm) {
392bf21cd93STycho Nightingale 		/* read mode 1 */
393bf21cd93STycho Nightingale 		assert(0);
394bf21cd93STycho Nightingale 	}
395bf21cd93STycho Nightingale 
396bf21cd93STycho Nightingale 	map_sel = sc->vga_gc.gc_read_map_sel;
397bf21cd93STycho Nightingale 	if (sc->vga_gc.gc_mode_oe) {
398bf21cd93STycho Nightingale 		map_sel |= (offset & 1);
399bf21cd93STycho Nightingale 		offset &= ~1;
400bf21cd93STycho Nightingale 	}
401bf21cd93STycho Nightingale 
402bf21cd93STycho Nightingale 	/* read mode 0: return the byte from the selected plane. */
403bf21cd93STycho Nightingale 	offset += map_sel * 64*KB;
404bf21cd93STycho Nightingale 
405bf21cd93STycho Nightingale 	return (sc->vga_ram[offset]);
406bf21cd93STycho Nightingale }
407bf21cd93STycho Nightingale 
408bf21cd93STycho Nightingale static void
vga_mem_wr_handler(uint64_t addr,uint8_t val,void * arg1)409*32640292SAndy Fiddaman vga_mem_wr_handler(uint64_t addr, uint8_t val, void *arg1)
410bf21cd93STycho Nightingale {
411bf21cd93STycho Nightingale 	struct vga_softc *sc = arg1;
412bf21cd93STycho Nightingale 	uint8_t c0, c1, c2, c3;
413bf21cd93STycho Nightingale 	uint8_t m0, m1, m2, m3;
414bf21cd93STycho Nightingale 	uint8_t set_reset;
415bf21cd93STycho Nightingale 	uint8_t enb_set_reset;
416bf21cd93STycho Nightingale 	uint8_t	mask;
417bf21cd93STycho Nightingale 	int offset;
418bf21cd93STycho Nightingale 
419bf21cd93STycho Nightingale 	offset = addr;
420bf21cd93STycho Nightingale 	switch (sc->vga_gc.gc_misc_mm) {
421bf21cd93STycho Nightingale 	case 0x0:
422bf21cd93STycho Nightingale 		/*
423bf21cd93STycho Nightingale 		 * extended mode: base 0xa0000 size 128kb
424bf21cd93STycho Nightingale 		 */
425bf21cd93STycho Nightingale 		offset -=0xa0000;
426bf21cd93STycho Nightingale 		offset &= (128 * KB - 1);
427bf21cd93STycho Nightingale 		break;
428bf21cd93STycho Nightingale 	case 0x1:
429bf21cd93STycho Nightingale 		/*
430bf21cd93STycho Nightingale 		 * EGA/VGA mode: base 0xa0000 size 64kb
431bf21cd93STycho Nightingale 		 */
432bf21cd93STycho Nightingale 		offset -=0xa0000;
433bf21cd93STycho Nightingale 		offset &= (64 * KB - 1);
434bf21cd93STycho Nightingale 		break;
435bf21cd93STycho Nightingale 	case 0x2:
436bf21cd93STycho Nightingale 		/*
437bf21cd93STycho Nightingale 		 * monochrome text mode: base 0xb0000 size 32kb
438bf21cd93STycho Nightingale 		 */
4394c87aefeSPatrick Mooney #ifdef __FreeBSD__
440bf21cd93STycho Nightingale 		assert(0);
4414c87aefeSPatrick Mooney #else
4424c87aefeSPatrick Mooney 		abort();
4434c87aefeSPatrick Mooney #endif
444bf21cd93STycho Nightingale 	case 0x3:
445bf21cd93STycho Nightingale 		/*
446bf21cd93STycho Nightingale 		 * color text mode and CGA: base 0xb8000 size 32kb
447bf21cd93STycho Nightingale 		 */
448bf21cd93STycho Nightingale 		offset -=0xb8000;
449bf21cd93STycho Nightingale 		offset &= (32 * KB - 1);
450bf21cd93STycho Nightingale 		break;
451bf21cd93STycho Nightingale 	}
452bf21cd93STycho Nightingale 
453bf21cd93STycho Nightingale 	set_reset = sc->vga_gc.gc_set_reset;
454bf21cd93STycho Nightingale 	enb_set_reset = sc->vga_gc.gc_enb_set_reset;
455bf21cd93STycho Nightingale 
456bf21cd93STycho Nightingale 	c0 = sc->vga_gc.gc_latch0;
457bf21cd93STycho Nightingale 	c1 = sc->vga_gc.gc_latch1;
458bf21cd93STycho Nightingale 	c2 = sc->vga_gc.gc_latch2;
459bf21cd93STycho Nightingale 	c3 = sc->vga_gc.gc_latch3;
460bf21cd93STycho Nightingale 
461bf21cd93STycho Nightingale 	switch (sc->vga_gc.gc_mode_wm) {
462bf21cd93STycho Nightingale 	case 0:
463bf21cd93STycho Nightingale 		/* write mode 0 */
464bf21cd93STycho Nightingale 		mask = sc->vga_gc.gc_bit_mask;
465bf21cd93STycho Nightingale 
466bf21cd93STycho Nightingale 		val = (val >> sc->vga_gc.gc_rotate) |
467bf21cd93STycho Nightingale 		    (val << (8 - sc->vga_gc.gc_rotate));
468bf21cd93STycho Nightingale 
469bf21cd93STycho Nightingale 		switch (sc->vga_gc.gc_op) {
470bf21cd93STycho Nightingale 		case 0x00:		/* replace */
471bf21cd93STycho Nightingale 			m0 = (set_reset & 1) ? mask : 0x00;
472bf21cd93STycho Nightingale 			m1 = (set_reset & 2) ? mask : 0x00;
473bf21cd93STycho Nightingale 			m2 = (set_reset & 4) ? mask : 0x00;
474bf21cd93STycho Nightingale 			m3 = (set_reset & 8) ? mask : 0x00;
475bf21cd93STycho Nightingale 
476bf21cd93STycho Nightingale 			c0 = (enb_set_reset & 1) ? (c0 & ~mask) : (val & mask);
477bf21cd93STycho Nightingale 			c1 = (enb_set_reset & 2) ? (c1 & ~mask) : (val & mask);
478bf21cd93STycho Nightingale 			c2 = (enb_set_reset & 4) ? (c2 & ~mask) : (val & mask);
479bf21cd93STycho Nightingale 			c3 = (enb_set_reset & 8) ? (c3 & ~mask) : (val & mask);
480bf21cd93STycho Nightingale 
481bf21cd93STycho Nightingale 			c0 |= m0;
482bf21cd93STycho Nightingale 			c1 |= m1;
483bf21cd93STycho Nightingale 			c2 |= m2;
484bf21cd93STycho Nightingale 			c3 |= m3;
485bf21cd93STycho Nightingale 			break;
486bf21cd93STycho Nightingale 		case 0x08:		/* AND */
487bf21cd93STycho Nightingale 			m0 = set_reset & 1 ? 0xff : ~mask;
488bf21cd93STycho Nightingale 			m1 = set_reset & 2 ? 0xff : ~mask;
489bf21cd93STycho Nightingale 			m2 = set_reset & 4 ? 0xff : ~mask;
490bf21cd93STycho Nightingale 			m3 = set_reset & 8 ? 0xff : ~mask;
491bf21cd93STycho Nightingale 
492bf21cd93STycho Nightingale 			c0 = enb_set_reset & 1 ? c0 & m0 : val & m0;
493bf21cd93STycho Nightingale 			c1 = enb_set_reset & 2 ? c1 & m1 : val & m1;
494bf21cd93STycho Nightingale 			c2 = enb_set_reset & 4 ? c2 & m2 : val & m2;
495bf21cd93STycho Nightingale 			c3 = enb_set_reset & 8 ? c3 & m3 : val & m3;
496bf21cd93STycho Nightingale 			break;
497bf21cd93STycho Nightingale 		case 0x10:		/* OR */
498bf21cd93STycho Nightingale 			m0 = set_reset & 1 ? mask : 0x00;
499bf21cd93STycho Nightingale 			m1 = set_reset & 2 ? mask : 0x00;
500bf21cd93STycho Nightingale 			m2 = set_reset & 4 ? mask : 0x00;
501bf21cd93STycho Nightingale 			m3 = set_reset & 8 ? mask : 0x00;
502bf21cd93STycho Nightingale 
503bf21cd93STycho Nightingale 			c0 = enb_set_reset & 1 ? c0 | m0 : val | m0;
504bf21cd93STycho Nightingale 			c1 = enb_set_reset & 2 ? c1 | m1 : val | m1;
505bf21cd93STycho Nightingale 			c2 = enb_set_reset & 4 ? c2 | m2 : val | m2;
506bf21cd93STycho Nightingale 			c3 = enb_set_reset & 8 ? c3 | m3 : val | m3;
507bf21cd93STycho Nightingale 			break;
508bf21cd93STycho Nightingale 		case 0x18:		/* XOR */
509bf21cd93STycho Nightingale 			m0 = set_reset & 1 ? mask : 0x00;
510bf21cd93STycho Nightingale 			m1 = set_reset & 2 ? mask : 0x00;
511bf21cd93STycho Nightingale 			m2 = set_reset & 4 ? mask : 0x00;
512bf21cd93STycho Nightingale 			m3 = set_reset & 8 ? mask : 0x00;
513bf21cd93STycho Nightingale 
514bf21cd93STycho Nightingale 			c0 = enb_set_reset & 1 ? c0 ^ m0 : val ^ m0;
515bf21cd93STycho Nightingale 			c1 = enb_set_reset & 2 ? c1 ^ m1 : val ^ m1;
516bf21cd93STycho Nightingale 			c2 = enb_set_reset & 4 ? c2 ^ m2 : val ^ m2;
517bf21cd93STycho Nightingale 			c3 = enb_set_reset & 8 ? c3 ^ m3 : val ^ m3;
518bf21cd93STycho Nightingale 			break;
519bf21cd93STycho Nightingale 		}
520bf21cd93STycho Nightingale 		break;
521bf21cd93STycho Nightingale 	case 1:
522bf21cd93STycho Nightingale 		/* write mode 1 */
523bf21cd93STycho Nightingale 		break;
524bf21cd93STycho Nightingale 	case 2:
525bf21cd93STycho Nightingale 		/* write mode 2 */
526bf21cd93STycho Nightingale 		mask = sc->vga_gc.gc_bit_mask;
527bf21cd93STycho Nightingale 
528bf21cd93STycho Nightingale 		switch (sc->vga_gc.gc_op) {
529bf21cd93STycho Nightingale 		case 0x00:		/* replace */
530bf21cd93STycho Nightingale 			m0 = (val & 1 ? 0xff : 0x00) & mask;
531bf21cd93STycho Nightingale 			m1 = (val & 2 ? 0xff : 0x00) & mask;
532bf21cd93STycho Nightingale 			m2 = (val & 4 ? 0xff : 0x00) & mask;
533bf21cd93STycho Nightingale 			m3 = (val & 8 ? 0xff : 0x00) & mask;
534bf21cd93STycho Nightingale 
535bf21cd93STycho Nightingale 			c0 &= ~mask;
536bf21cd93STycho Nightingale 			c1 &= ~mask;
537bf21cd93STycho Nightingale 			c2 &= ~mask;
538bf21cd93STycho Nightingale 			c3 &= ~mask;
539bf21cd93STycho Nightingale 
540bf21cd93STycho Nightingale 			c0 |= m0;
541bf21cd93STycho Nightingale 			c1 |= m1;
542bf21cd93STycho Nightingale 			c2 |= m2;
543bf21cd93STycho Nightingale 			c3 |= m3;
544bf21cd93STycho Nightingale 			break;
545bf21cd93STycho Nightingale 		case 0x08:		/* AND */
546bf21cd93STycho Nightingale 			m0 = (val & 1 ? 0xff : 0x00) | ~mask;
547bf21cd93STycho Nightingale 			m1 = (val & 2 ? 0xff : 0x00) | ~mask;
548bf21cd93STycho Nightingale 			m2 = (val & 4 ? 0xff : 0x00) | ~mask;
549bf21cd93STycho Nightingale 			m3 = (val & 8 ? 0xff : 0x00) | ~mask;
550bf21cd93STycho Nightingale 
551bf21cd93STycho Nightingale 			c0 &= m0;
552bf21cd93STycho Nightingale 			c1 &= m1;
553bf21cd93STycho Nightingale 			c2 &= m2;
554bf21cd93STycho Nightingale 			c3 &= m3;
555bf21cd93STycho Nightingale 			break;
556bf21cd93STycho Nightingale 		case 0x10:		/* OR */
557bf21cd93STycho Nightingale 			m0 = (val & 1 ? 0xff : 0x00) & mask;
558bf21cd93STycho Nightingale 			m1 = (val & 2 ? 0xff : 0x00) & mask;
559bf21cd93STycho Nightingale 			m2 = (val & 4 ? 0xff : 0x00) & mask;
560bf21cd93STycho Nightingale 			m3 = (val & 8 ? 0xff : 0x00) & mask;
561bf21cd93STycho Nightingale 
562bf21cd93STycho Nightingale 			c0 |= m0;
563bf21cd93STycho Nightingale 			c1 |= m1;
564bf21cd93STycho Nightingale 			c2 |= m2;
565bf21cd93STycho Nightingale 			c3 |= m3;
566bf21cd93STycho Nightingale 			break;
567bf21cd93STycho Nightingale 		case 0x18:		/* XOR */
568bf21cd93STycho Nightingale 			m0 = (val & 1 ? 0xff : 0x00) & mask;
569bf21cd93STycho Nightingale 			m1 = (val & 2 ? 0xff : 0x00) & mask;
570bf21cd93STycho Nightingale 			m2 = (val & 4 ? 0xff : 0x00) & mask;
571bf21cd93STycho Nightingale 			m3 = (val & 8 ? 0xff : 0x00) & mask;
572bf21cd93STycho Nightingale 
573bf21cd93STycho Nightingale 			c0 ^= m0;
574bf21cd93STycho Nightingale 			c1 ^= m1;
575bf21cd93STycho Nightingale 			c2 ^= m2;
576bf21cd93STycho Nightingale 			c3 ^= m3;
577bf21cd93STycho Nightingale 			break;
578bf21cd93STycho Nightingale 		}
579bf21cd93STycho Nightingale 		break;
580bf21cd93STycho Nightingale 	case 3:
581bf21cd93STycho Nightingale 		/* write mode 3 */
582bf21cd93STycho Nightingale 		mask = sc->vga_gc.gc_bit_mask & val;
583bf21cd93STycho Nightingale 
584bf21cd93STycho Nightingale 		val = (val >> sc->vga_gc.gc_rotate) |
585bf21cd93STycho Nightingale 		    (val << (8 - sc->vga_gc.gc_rotate));
586bf21cd93STycho Nightingale 
587bf21cd93STycho Nightingale 		switch (sc->vga_gc.gc_op) {
588bf21cd93STycho Nightingale 		case 0x00:		/* replace */
589bf21cd93STycho Nightingale 			m0 = (set_reset & 1 ? 0xff : 0x00) & mask;
590bf21cd93STycho Nightingale 			m1 = (set_reset & 2 ? 0xff : 0x00) & mask;
591bf21cd93STycho Nightingale 			m2 = (set_reset & 4 ? 0xff : 0x00) & mask;
592bf21cd93STycho Nightingale 			m3 = (set_reset & 8 ? 0xff : 0x00) & mask;
593bf21cd93STycho Nightingale 
594bf21cd93STycho Nightingale 			c0 &= ~mask;
595bf21cd93STycho Nightingale 			c1 &= ~mask;
596bf21cd93STycho Nightingale 			c2 &= ~mask;
597bf21cd93STycho Nightingale 			c3 &= ~mask;
598bf21cd93STycho Nightingale 
599bf21cd93STycho Nightingale 			c0 |= m0;
600bf21cd93STycho Nightingale 			c1 |= m1;
601bf21cd93STycho Nightingale 			c2 |= m2;
602bf21cd93STycho Nightingale 			c3 |= m3;
603bf21cd93STycho Nightingale 			break;
604bf21cd93STycho Nightingale 		case 0x08:		/* AND */
605bf21cd93STycho Nightingale 			m0 = (set_reset & 1 ? 0xff : 0x00) | ~mask;
606bf21cd93STycho Nightingale 			m1 = (set_reset & 2 ? 0xff : 0x00) | ~mask;
607bf21cd93STycho Nightingale 			m2 = (set_reset & 4 ? 0xff : 0x00) | ~mask;
608bf21cd93STycho Nightingale 			m3 = (set_reset & 8 ? 0xff : 0x00) | ~mask;
609bf21cd93STycho Nightingale 
610bf21cd93STycho Nightingale 			c0 &= m0;
611bf21cd93STycho Nightingale 			c1 &= m1;
612bf21cd93STycho Nightingale 			c2 &= m2;
613bf21cd93STycho Nightingale 			c3 &= m3;
614bf21cd93STycho Nightingale 			break;
615bf21cd93STycho Nightingale 		case 0x10:		/* OR */
616bf21cd93STycho Nightingale 			m0 = (set_reset & 1 ? 0xff : 0x00) & mask;
617bf21cd93STycho Nightingale 			m1 = (set_reset & 2 ? 0xff : 0x00) & mask;
618bf21cd93STycho Nightingale 			m2 = (set_reset & 4 ? 0xff : 0x00) & mask;
619bf21cd93STycho Nightingale 			m3 = (set_reset & 8 ? 0xff : 0x00) & mask;
620bf21cd93STycho Nightingale 
621bf21cd93STycho Nightingale 			c0 |= m0;
622bf21cd93STycho Nightingale 			c1 |= m1;
623bf21cd93STycho Nightingale 			c2 |= m2;
624bf21cd93STycho Nightingale 			c3 |= m3;
625bf21cd93STycho Nightingale 			break;
626bf21cd93STycho Nightingale 		case 0x18:		/* XOR */
627bf21cd93STycho Nightingale 			m0 = (set_reset & 1 ? 0xff : 0x00) & mask;
628bf21cd93STycho Nightingale 			m1 = (set_reset & 2 ? 0xff : 0x00) & mask;
629bf21cd93STycho Nightingale 			m2 = (set_reset & 4 ? 0xff : 0x00) & mask;
630bf21cd93STycho Nightingale 			m3 = (set_reset & 8 ? 0xff : 0x00) & mask;
631bf21cd93STycho Nightingale 
632bf21cd93STycho Nightingale 			c0 ^= m0;
633bf21cd93STycho Nightingale 			c1 ^= m1;
634bf21cd93STycho Nightingale 			c2 ^= m2;
635bf21cd93STycho Nightingale 			c3 ^= m3;
636bf21cd93STycho Nightingale 			break;
637bf21cd93STycho Nightingale 		}
638bf21cd93STycho Nightingale 		break;
639bf21cd93STycho Nightingale 	}
640bf21cd93STycho Nightingale 
641bf21cd93STycho Nightingale 	if (sc->vga_gc.gc_mode_oe) {
642bf21cd93STycho Nightingale 		if (offset & 1) {
643bf21cd93STycho Nightingale 			offset &= ~1;
644bf21cd93STycho Nightingale 			if (sc->vga_seq.seq_map_mask & 2)
645bf21cd93STycho Nightingale 				sc->vga_ram[offset + 1*64*KB] = c1;
646bf21cd93STycho Nightingale 			if (sc->vga_seq.seq_map_mask & 8)
647bf21cd93STycho Nightingale 				sc->vga_ram[offset + 3*64*KB] = c3;
648bf21cd93STycho Nightingale 		} else {
649bf21cd93STycho Nightingale 			if (sc->vga_seq.seq_map_mask & 1)
650bf21cd93STycho Nightingale 				sc->vga_ram[offset + 0*64*KB] = c0;
651bf21cd93STycho Nightingale 			if (sc->vga_seq.seq_map_mask & 4)
652bf21cd93STycho Nightingale 				sc->vga_ram[offset + 2*64*KB] = c2;
653bf21cd93STycho Nightingale 		}
654bf21cd93STycho Nightingale 	} else {
655bf21cd93STycho Nightingale 		if (sc->vga_seq.seq_map_mask & 1)
656bf21cd93STycho Nightingale 			sc->vga_ram[offset + 0*64*KB] = c0;
657bf21cd93STycho Nightingale 		if (sc->vga_seq.seq_map_mask & 2)
658bf21cd93STycho Nightingale 			sc->vga_ram[offset + 1*64*KB] = c1;
659bf21cd93STycho Nightingale 		if (sc->vga_seq.seq_map_mask & 4)
660bf21cd93STycho Nightingale 			sc->vga_ram[offset + 2*64*KB] = c2;
661bf21cd93STycho Nightingale 		if (sc->vga_seq.seq_map_mask & 8)
662bf21cd93STycho Nightingale 			sc->vga_ram[offset + 3*64*KB] = c3;
663bf21cd93STycho Nightingale 	}
664bf21cd93STycho Nightingale }
665bf21cd93STycho Nightingale 
666bf21cd93STycho Nightingale static int
vga_mem_handler(struct vcpu * vcpu __unused,int dir,uint64_t addr,int size,uint64_t * val,void * arg1,long arg2 __unused)667*32640292SAndy Fiddaman vga_mem_handler(struct vcpu *vcpu __unused, int dir, uint64_t addr, int size,
668*32640292SAndy Fiddaman     uint64_t *val, void *arg1, long arg2 __unused)
669bf21cd93STycho Nightingale {
670bf21cd93STycho Nightingale 	if (dir == MEM_F_WRITE) {
671bf21cd93STycho Nightingale 		switch (size) {
672bf21cd93STycho Nightingale 		case 1:
673*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr, *val, arg1);
674bf21cd93STycho Nightingale 			break;
675bf21cd93STycho Nightingale 		case 2:
676*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr, *val, arg1);
677*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr + 1, *val >> 8, arg1);
678bf21cd93STycho Nightingale 			break;
679bf21cd93STycho Nightingale 		case 4:
680*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr, *val, arg1);
681*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr + 1, *val >> 8, arg1);
682*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr + 2, *val >> 16, arg1);
683*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr + 3, *val >> 24, arg1);
684bf21cd93STycho Nightingale 			break;
685bf21cd93STycho Nightingale 		case 8:
686*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr, *val, arg1);
687*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr + 1, *val >> 8, arg1);
688*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr + 2, *val >> 16, arg1);
689*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr + 3, *val >> 24, arg1);
690*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr + 4, *val >> 32, arg1);
691*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr + 5, *val >> 40, arg1);
692*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr + 6, *val >> 48, arg1);
693*32640292SAndy Fiddaman 			vga_mem_wr_handler(addr + 7, *val >> 56, arg1);
694bf21cd93STycho Nightingale 			break;
695bf21cd93STycho Nightingale 		}
696bf21cd93STycho Nightingale 	} else {
697bf21cd93STycho Nightingale 		switch (size) {
698bf21cd93STycho Nightingale 		case 1:
699*32640292SAndy Fiddaman 			*val = vga_mem_rd_handler(addr, arg1);
700bf21cd93STycho Nightingale 			break;
701bf21cd93STycho Nightingale 		case 2:
702*32640292SAndy Fiddaman 			*val = vga_mem_rd_handler(addr, arg1);
703*32640292SAndy Fiddaman 			*val |= vga_mem_rd_handler(addr + 1, arg1) << 8;
704bf21cd93STycho Nightingale 			break;
705bf21cd93STycho Nightingale 		case 4:
706*32640292SAndy Fiddaman 			*val = vga_mem_rd_handler(addr, arg1);
707*32640292SAndy Fiddaman 			*val |= vga_mem_rd_handler(addr + 1, arg1) << 8;
708*32640292SAndy Fiddaman 			*val |= vga_mem_rd_handler(addr + 2, arg1) << 16;
709*32640292SAndy Fiddaman 			*val |= vga_mem_rd_handler(addr + 3, arg1) << 24;
710bf21cd93STycho Nightingale 			break;
711bf21cd93STycho Nightingale 		case 8:
712*32640292SAndy Fiddaman 			*val = vga_mem_rd_handler(addr, arg1);
713*32640292SAndy Fiddaman 			*val |= vga_mem_rd_handler(addr + 1, arg1) << 8;
714*32640292SAndy Fiddaman 			*val |= vga_mem_rd_handler(addr + 2, arg1) << 16;
715*32640292SAndy Fiddaman 			*val |= vga_mem_rd_handler(addr + 3, arg1) << 24;
716*32640292SAndy Fiddaman 			*val |= vga_mem_rd_handler(addr + 4, arg1) << 32;
717*32640292SAndy Fiddaman 			*val |= vga_mem_rd_handler(addr + 5, arg1) << 40;
718*32640292SAndy Fiddaman 			*val |= vga_mem_rd_handler(addr + 6, arg1) << 48;
719*32640292SAndy Fiddaman 			*val |= vga_mem_rd_handler(addr + 7, arg1) << 56;
720bf21cd93STycho Nightingale 			break;
721bf21cd93STycho Nightingale 		}
722bf21cd93STycho Nightingale 	}
723bf21cd93STycho Nightingale 
724bf21cd93STycho Nightingale 	return (0);
725bf21cd93STycho Nightingale }
726bf21cd93STycho Nightingale 
727bf21cd93STycho Nightingale static int
vga_port_in_handler(struct vmctx * ctx,int in,int port,int bytes,uint8_t * val,void * arg)728bf21cd93STycho Nightingale vga_port_in_handler(struct vmctx *ctx, int in, int port, int bytes,
729bf21cd93STycho Nightingale 		    uint8_t *val, void *arg)
730bf21cd93STycho Nightingale {
731bf21cd93STycho Nightingale 	struct vga_softc *sc = arg;
732bf21cd93STycho Nightingale 
733bf21cd93STycho Nightingale 	switch (port) {
734bf21cd93STycho Nightingale 	case CRTC_IDX_MONO_PORT:
735bf21cd93STycho Nightingale 	case CRTC_IDX_COLOR_PORT:
736bf21cd93STycho Nightingale 		*val = sc->vga_crtc.crtc_index;
737bf21cd93STycho Nightingale 		break;
738bf21cd93STycho Nightingale 	case CRTC_DATA_MONO_PORT:
739bf21cd93STycho Nightingale 	case CRTC_DATA_COLOR_PORT:
740bf21cd93STycho Nightingale 		switch (sc->vga_crtc.crtc_index) {
741bf21cd93STycho Nightingale 		case CRTC_HORIZ_TOTAL:
742bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_horiz_total;
743bf21cd93STycho Nightingale 			break;
744bf21cd93STycho Nightingale 		case CRTC_HORIZ_DISP_END:
745bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_horiz_disp_end;
746bf21cd93STycho Nightingale 			break;
747bf21cd93STycho Nightingale 		case CRTC_START_HORIZ_BLANK:
748bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_start_horiz_blank;
749bf21cd93STycho Nightingale 			break;
750bf21cd93STycho Nightingale 		case CRTC_END_HORIZ_BLANK:
751bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_end_horiz_blank;
752bf21cd93STycho Nightingale 			break;
753bf21cd93STycho Nightingale 		case CRTC_START_HORIZ_RETRACE:
754bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_start_horiz_retrace;
755bf21cd93STycho Nightingale 			break;
756bf21cd93STycho Nightingale 		case CRTC_END_HORIZ_RETRACE:
757bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_end_horiz_retrace;
758bf21cd93STycho Nightingale 			break;
759bf21cd93STycho Nightingale 		case CRTC_VERT_TOTAL:
760bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_vert_total;
761bf21cd93STycho Nightingale 			break;
762bf21cd93STycho Nightingale 		case CRTC_OVERFLOW:
763bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_overflow;
764bf21cd93STycho Nightingale 			break;
765bf21cd93STycho Nightingale 		case CRTC_PRESET_ROW_SCAN:
766bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_present_row_scan;
767bf21cd93STycho Nightingale 			break;
768bf21cd93STycho Nightingale 		case CRTC_MAX_SCAN_LINE:
769bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_max_scan_line;
770bf21cd93STycho Nightingale 			break;
771bf21cd93STycho Nightingale 		case CRTC_CURSOR_START:
772bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_cursor_start;
773bf21cd93STycho Nightingale 			break;
774bf21cd93STycho Nightingale 		case CRTC_CURSOR_END:
775bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_cursor_end;
776bf21cd93STycho Nightingale 			break;
777bf21cd93STycho Nightingale 		case CRTC_START_ADDR_HIGH:
778bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_start_addr_high;
779bf21cd93STycho Nightingale 			break;
780bf21cd93STycho Nightingale 		case CRTC_START_ADDR_LOW:
781bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_start_addr_low;
782bf21cd93STycho Nightingale 			break;
783bf21cd93STycho Nightingale 		case CRTC_CURSOR_LOC_HIGH:
784bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_cursor_loc_high;
785bf21cd93STycho Nightingale 			break;
786bf21cd93STycho Nightingale 		case CRTC_CURSOR_LOC_LOW:
787bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_cursor_loc_low;
788bf21cd93STycho Nightingale 			break;
789bf21cd93STycho Nightingale 		case CRTC_VERT_RETRACE_START:
790bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_vert_retrace_start;
791bf21cd93STycho Nightingale 			break;
792bf21cd93STycho Nightingale 		case CRTC_VERT_RETRACE_END:
793bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_vert_retrace_end;
794bf21cd93STycho Nightingale 			break;
795bf21cd93STycho Nightingale 		case CRTC_VERT_DISP_END:
796bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_vert_disp_end;
797bf21cd93STycho Nightingale 			break;
798bf21cd93STycho Nightingale 		case CRTC_OFFSET:
799bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_offset;
800bf21cd93STycho Nightingale 			break;
801bf21cd93STycho Nightingale 		case CRTC_UNDERLINE_LOC:
802bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_underline_loc;
803bf21cd93STycho Nightingale 			break;
804bf21cd93STycho Nightingale 		case CRTC_START_VERT_BLANK:
805bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_start_vert_blank;
806bf21cd93STycho Nightingale 			break;
807bf21cd93STycho Nightingale 		case CRTC_END_VERT_BLANK:
808bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_end_vert_blank;
809bf21cd93STycho Nightingale 			break;
810bf21cd93STycho Nightingale 		case CRTC_MODE_CONTROL:
811bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_mode_ctrl;
812bf21cd93STycho Nightingale 			break;
813bf21cd93STycho Nightingale 		case CRTC_LINE_COMPARE:
814bf21cd93STycho Nightingale 			*val = sc->vga_crtc.crtc_line_compare;
815bf21cd93STycho Nightingale 			break;
816bf21cd93STycho Nightingale 		default:
817bf21cd93STycho Nightingale 			//printf("XXX VGA CRTC: inb 0x%04x at index %d\n", port, sc->vga_crtc.crtc_index);
818bf21cd93STycho Nightingale 			assert(0);
819bf21cd93STycho Nightingale 			break;
820bf21cd93STycho Nightingale 		}
821bf21cd93STycho Nightingale 		break;
822bf21cd93STycho Nightingale 	case ATC_IDX_PORT:
823bf21cd93STycho Nightingale 		*val = sc->vga_atc.atc_index;
824bf21cd93STycho Nightingale 		break;
825bf21cd93STycho Nightingale 	case ATC_DATA_PORT:
826bf21cd93STycho Nightingale 		switch (sc->vga_atc.atc_index) {
827bf21cd93STycho Nightingale 		case ATC_PALETTE0 ... ATC_PALETTE15:
828bf21cd93STycho Nightingale 			*val = sc->vga_atc.atc_palette[sc->vga_atc.atc_index];
829bf21cd93STycho Nightingale 			break;
830bf21cd93STycho Nightingale 		case ATC_MODE_CONTROL:
831bf21cd93STycho Nightingale 			*val = sc->vga_atc.atc_mode;
832bf21cd93STycho Nightingale 			break;
833bf21cd93STycho Nightingale 		case ATC_OVERSCAN_COLOR:
834bf21cd93STycho Nightingale 			*val = sc->vga_atc.atc_overscan_color;
835bf21cd93STycho Nightingale 			break;
836bf21cd93STycho Nightingale 		case ATC_COLOR_PLANE_ENABLE:
837bf21cd93STycho Nightingale 			*val = sc->vga_atc.atc_color_plane_enb;
838bf21cd93STycho Nightingale 			break;
839bf21cd93STycho Nightingale 		case ATC_HORIZ_PIXEL_PANNING:
840bf21cd93STycho Nightingale 			*val = sc->vga_atc.atc_horiz_pixel_panning;
841bf21cd93STycho Nightingale 			break;
842bf21cd93STycho Nightingale 		case ATC_COLOR_SELECT:
843bf21cd93STycho Nightingale 			*val = sc->vga_atc.atc_color_select;
844bf21cd93STycho Nightingale 			break;
845bf21cd93STycho Nightingale 		default:
846bf21cd93STycho Nightingale 			//printf("XXX VGA ATC inb 0x%04x at index %d\n", port , sc->vga_atc.atc_index);
847bf21cd93STycho Nightingale 			assert(0);
848bf21cd93STycho Nightingale 			break;
849bf21cd93STycho Nightingale 		}
850bf21cd93STycho Nightingale 		break;
851bf21cd93STycho Nightingale 	case SEQ_IDX_PORT:
852bf21cd93STycho Nightingale 		*val = sc->vga_seq.seq_index;
853bf21cd93STycho Nightingale 		break;
854bf21cd93STycho Nightingale 	case SEQ_DATA_PORT:
855bf21cd93STycho Nightingale 		switch (sc->vga_seq.seq_index) {
856bf21cd93STycho Nightingale 		case SEQ_RESET:
857bf21cd93STycho Nightingale 			*val = sc->vga_seq.seq_reset;
858bf21cd93STycho Nightingale 			break;
859bf21cd93STycho Nightingale 		case SEQ_CLOCKING_MODE:
860bf21cd93STycho Nightingale 			*val = sc->vga_seq.seq_clock_mode;
861bf21cd93STycho Nightingale 			break;
862bf21cd93STycho Nightingale 		case SEQ_MAP_MASK:
863bf21cd93STycho Nightingale 			*val = sc->vga_seq.seq_map_mask;
864bf21cd93STycho Nightingale 			break;
865bf21cd93STycho Nightingale 		case SEQ_CHAR_MAP_SELECT:
866bf21cd93STycho Nightingale 			*val = sc->vga_seq.seq_cmap_sel;
867bf21cd93STycho Nightingale 			break;
868bf21cd93STycho Nightingale 		case SEQ_MEMORY_MODE:
869bf21cd93STycho Nightingale 			*val = sc->vga_seq.seq_mm;
870bf21cd93STycho Nightingale 			break;
871bf21cd93STycho Nightingale 		default:
872bf21cd93STycho Nightingale 			//printf("XXX VGA SEQ: inb 0x%04x at index %d\n", port, sc->vga_seq.seq_index);
873bf21cd93STycho Nightingale 			assert(0);
874bf21cd93STycho Nightingale 			break;
875bf21cd93STycho Nightingale 		}
8764c87aefeSPatrick Mooney 		break;
877bf21cd93STycho Nightingale 	case DAC_DATA_PORT:
878bf21cd93STycho Nightingale 		*val = sc->vga_dac.dac_palette[3 * sc->vga_dac.dac_rd_index +
879bf21cd93STycho Nightingale 					       sc->vga_dac.dac_rd_subindex];
880bf21cd93STycho Nightingale 		sc->vga_dac.dac_rd_subindex++;
881bf21cd93STycho Nightingale 		if (sc->vga_dac.dac_rd_subindex == 3) {
882bf21cd93STycho Nightingale 			sc->vga_dac.dac_rd_index++;
883bf21cd93STycho Nightingale 			sc->vga_dac.dac_rd_subindex = 0;
884bf21cd93STycho Nightingale 		}
885bf21cd93STycho Nightingale 		break;
886bf21cd93STycho Nightingale 	case GC_IDX_PORT:
887bf21cd93STycho Nightingale 		*val = sc->vga_gc.gc_index;
888bf21cd93STycho Nightingale 		break;
889bf21cd93STycho Nightingale 	case GC_DATA_PORT:
890bf21cd93STycho Nightingale 		switch (sc->vga_gc.gc_index) {
891bf21cd93STycho Nightingale 		case GC_SET_RESET:
892bf21cd93STycho Nightingale 			*val = sc->vga_gc.gc_set_reset;
893bf21cd93STycho Nightingale 			break;
894bf21cd93STycho Nightingale 		case GC_ENABLE_SET_RESET:
895bf21cd93STycho Nightingale 			*val = sc->vga_gc.gc_enb_set_reset;
896bf21cd93STycho Nightingale 			break;
897bf21cd93STycho Nightingale 		case GC_COLOR_COMPARE:
898bf21cd93STycho Nightingale 			*val = sc->vga_gc.gc_color_compare;
899bf21cd93STycho Nightingale 			break;
900bf21cd93STycho Nightingale 		case GC_DATA_ROTATE:
901bf21cd93STycho Nightingale 			*val = sc->vga_gc.gc_rotate;
902bf21cd93STycho Nightingale 			break;
903bf21cd93STycho Nightingale 		case GC_READ_MAP_SELECT:
904bf21cd93STycho Nightingale 			*val = sc->vga_gc.gc_read_map_sel;
905bf21cd93STycho Nightingale 			break;
906bf21cd93STycho Nightingale 		case GC_MODE:
907bf21cd93STycho Nightingale 			*val = sc->vga_gc.gc_mode;
908bf21cd93STycho Nightingale 			break;
909bf21cd93STycho Nightingale 		case GC_MISCELLANEOUS:
910bf21cd93STycho Nightingale 			*val = sc->vga_gc.gc_misc;
911bf21cd93STycho Nightingale 			break;
912bf21cd93STycho Nightingale 		case GC_COLOR_DONT_CARE:
913bf21cd93STycho Nightingale 			*val = sc->vga_gc.gc_color_dont_care;
914bf21cd93STycho Nightingale 			break;
915bf21cd93STycho Nightingale 		case GC_BIT_MASK:
916bf21cd93STycho Nightingale 			*val = sc->vga_gc.gc_bit_mask;
917bf21cd93STycho Nightingale 			break;
918bf21cd93STycho Nightingale 		default:
919bf21cd93STycho Nightingale 			//printf("XXX VGA GC: inb 0x%04x at index %d\n", port, sc->vga_crtc.crtc_index);
920bf21cd93STycho Nightingale 			assert(0);
921bf21cd93STycho Nightingale 			break;
922bf21cd93STycho Nightingale 		}
923bf21cd93STycho Nightingale 		break;
924bf21cd93STycho Nightingale 	case GEN_MISC_OUTPUT_PORT:
925bf21cd93STycho Nightingale 		*val = sc->vga_misc;
926bf21cd93STycho Nightingale 		break;
927bf21cd93STycho Nightingale 	case GEN_INPUT_STS0_PORT:
928bf21cd93STycho Nightingale 		assert(0);
929bf21cd93STycho Nightingale 		break;
930bf21cd93STycho Nightingale 	case GEN_INPUT_STS1_MONO_PORT:
931bf21cd93STycho Nightingale 	case GEN_INPUT_STS1_COLOR_PORT:
932bf21cd93STycho Nightingale 		sc->vga_atc.atc_flipflop = 0;
9334c87aefeSPatrick Mooney #ifdef __FreeBSD__
9344c87aefeSPatrick Mooney 		sc->vga_sts1 = GEN_IS1_VR | GEN_IS1_DE;
9354c87aefeSPatrick Mooney 		//sc->vga_sts1 ^= (GEN_IS1_VR | GEN_IS1_DE);
9364c87aefeSPatrick Mooney #else
9374c87aefeSPatrick Mooney 		/*
9384c87aefeSPatrick Mooney 		 * During the bhyve bring-up process, a guest image was failing
9394c87aefeSPatrick Mooney 		 * to successfully boot.  It appeared to be spinning, waiting
9404c87aefeSPatrick Mooney 		 * for this value to be toggled.  Until it can be ruled out
9414c87aefeSPatrick Mooney 		 * that this is unnecessary (and documentation seems to
9424c87aefeSPatrick Mooney 		 * indicate that it should be present),  the toggle should
9434c87aefeSPatrick Mooney 		 * remain.
9444c87aefeSPatrick Mooney 		 */
945bf21cd93STycho Nightingale 		sc->vga_sts1 ^= (GEN_IS1_VR | GEN_IS1_DE);
9464c87aefeSPatrick Mooney #endif
947bf21cd93STycho Nightingale 		*val = sc->vga_sts1;
948bf21cd93STycho Nightingale 		break;
949bf21cd93STycho Nightingale 	case GEN_FEATURE_CTRL_PORT:
9504c87aefeSPatrick Mooney 		// OpenBSD calls this with bytes = 1
9514c87aefeSPatrick Mooney 		//assert(0);
9524c87aefeSPatrick Mooney 		*val = 0;
9534c87aefeSPatrick Mooney 		break;
9544c87aefeSPatrick Mooney 	case 0x3c3:
9554c87aefeSPatrick Mooney 		*val = 0;
956bf21cd93STycho Nightingale 		break;
957bf21cd93STycho Nightingale 	default:
958bf21cd93STycho Nightingale 		printf("XXX vga_port_in_handler() unhandled port 0x%x\n", port);
9594c87aefeSPatrick Mooney 		//assert(0);
960bf21cd93STycho Nightingale 		return (-1);
961bf21cd93STycho Nightingale 	}
962bf21cd93STycho Nightingale 
963bf21cd93STycho Nightingale 	return (0);
964bf21cd93STycho Nightingale }
965bf21cd93STycho Nightingale 
966bf21cd93STycho Nightingale static int
vga_port_out_handler(struct vmctx * ctx,int in,int port,int bytes,uint8_t val,void * arg)967bf21cd93STycho Nightingale vga_port_out_handler(struct vmctx *ctx, int in, int port, int bytes,
968bf21cd93STycho Nightingale 		     uint8_t val, void *arg)
969bf21cd93STycho Nightingale {
970bf21cd93STycho Nightingale 	struct vga_softc *sc = arg;
971bf21cd93STycho Nightingale 
972bf21cd93STycho Nightingale 	switch (port) {
973bf21cd93STycho Nightingale 	case CRTC_IDX_MONO_PORT:
974bf21cd93STycho Nightingale 	case CRTC_IDX_COLOR_PORT:
975bf21cd93STycho Nightingale 		sc->vga_crtc.crtc_index = val;
976bf21cd93STycho Nightingale 		break;
977bf21cd93STycho Nightingale 	case CRTC_DATA_MONO_PORT:
978bf21cd93STycho Nightingale 	case CRTC_DATA_COLOR_PORT:
979bf21cd93STycho Nightingale 		switch (sc->vga_crtc.crtc_index) {
980bf21cd93STycho Nightingale 		case CRTC_HORIZ_TOTAL:
981bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_horiz_total = val;
982bf21cd93STycho Nightingale 			break;
983bf21cd93STycho Nightingale 		case CRTC_HORIZ_DISP_END:
984bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_horiz_disp_end = val;
985bf21cd93STycho Nightingale 			break;
986bf21cd93STycho Nightingale 		case CRTC_START_HORIZ_BLANK:
987bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_start_horiz_blank = val;
988bf21cd93STycho Nightingale 			break;
989bf21cd93STycho Nightingale 		case CRTC_END_HORIZ_BLANK:
990bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_end_horiz_blank = val;
991bf21cd93STycho Nightingale 			break;
992bf21cd93STycho Nightingale 		case CRTC_START_HORIZ_RETRACE:
993bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_start_horiz_retrace = val;
994bf21cd93STycho Nightingale 			break;
995bf21cd93STycho Nightingale 		case CRTC_END_HORIZ_RETRACE:
996bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_end_horiz_retrace = val;
997bf21cd93STycho Nightingale 			break;
998bf21cd93STycho Nightingale 		case CRTC_VERT_TOTAL:
999bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_vert_total = val;
1000bf21cd93STycho Nightingale 			break;
1001bf21cd93STycho Nightingale 		case CRTC_OVERFLOW:
1002bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_overflow = val;
1003bf21cd93STycho Nightingale 			break;
1004bf21cd93STycho Nightingale 		case CRTC_PRESET_ROW_SCAN:
1005bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_present_row_scan = val;
1006bf21cd93STycho Nightingale 			break;
1007bf21cd93STycho Nightingale 		case CRTC_MAX_SCAN_LINE:
1008bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_max_scan_line = val;
1009bf21cd93STycho Nightingale 			break;
1010bf21cd93STycho Nightingale 		case CRTC_CURSOR_START:
1011bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_cursor_start = val;
1012bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_cursor_on = (val & CRTC_CS_CO) == 0;
1013bf21cd93STycho Nightingale 			break;
1014bf21cd93STycho Nightingale 		case CRTC_CURSOR_END:
1015bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_cursor_end = val;
1016bf21cd93STycho Nightingale 			break;
1017bf21cd93STycho Nightingale 		case CRTC_START_ADDR_HIGH:
1018bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_start_addr_high = val;
1019bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_start_addr &= 0x00ff;
1020bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_start_addr |= (val << 8);
1021bf21cd93STycho Nightingale 			break;
1022bf21cd93STycho Nightingale 		case CRTC_START_ADDR_LOW:
1023bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_start_addr_low = val;
1024bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_start_addr &= 0xff00;
1025bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_start_addr |= (val & 0xff);
1026bf21cd93STycho Nightingale 			break;
1027bf21cd93STycho Nightingale 		case CRTC_CURSOR_LOC_HIGH:
1028bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_cursor_loc_high = val;
1029bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_cursor_loc &= 0x00ff;
1030bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_cursor_loc |= (val << 8);
1031bf21cd93STycho Nightingale 			break;
1032bf21cd93STycho Nightingale 		case CRTC_CURSOR_LOC_LOW:
1033bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_cursor_loc_low = val;
1034bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_cursor_loc &= 0xff00;
1035bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_cursor_loc |= (val & 0xff);
1036bf21cd93STycho Nightingale 			break;
1037bf21cd93STycho Nightingale 		case CRTC_VERT_RETRACE_START:
1038bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_vert_retrace_start = val;
1039bf21cd93STycho Nightingale 			break;
1040bf21cd93STycho Nightingale 		case CRTC_VERT_RETRACE_END:
1041bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_vert_retrace_end = val;
1042bf21cd93STycho Nightingale 			break;
1043bf21cd93STycho Nightingale 		case CRTC_VERT_DISP_END:
1044bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_vert_disp_end = val;
1045bf21cd93STycho Nightingale 			break;
1046bf21cd93STycho Nightingale 		case CRTC_OFFSET:
1047bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_offset = val;
1048bf21cd93STycho Nightingale 			break;
1049bf21cd93STycho Nightingale 		case CRTC_UNDERLINE_LOC:
1050bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_underline_loc = val;
1051bf21cd93STycho Nightingale 			break;
1052bf21cd93STycho Nightingale 		case CRTC_START_VERT_BLANK:
1053bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_start_vert_blank = val;
1054bf21cd93STycho Nightingale 			break;
1055bf21cd93STycho Nightingale 		case CRTC_END_VERT_BLANK:
1056bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_end_vert_blank = val;
1057bf21cd93STycho Nightingale 			break;
1058bf21cd93STycho Nightingale 		case CRTC_MODE_CONTROL:
1059bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_mode_ctrl = val;
1060bf21cd93STycho Nightingale 			break;
1061bf21cd93STycho Nightingale 		case CRTC_LINE_COMPARE:
1062bf21cd93STycho Nightingale 			sc->vga_crtc.crtc_line_compare = val;
1063bf21cd93STycho Nightingale 			break;
1064bf21cd93STycho Nightingale 		default:
1065bf21cd93STycho Nightingale 			//printf("XXX VGA CRTC: outb 0x%04x, 0x%02x at index %d\n", port, val, sc->vga_crtc.crtc_index);
1066bf21cd93STycho Nightingale 			assert(0);
1067bf21cd93STycho Nightingale 			break;
1068bf21cd93STycho Nightingale 		}
1069bf21cd93STycho Nightingale 		break;
1070bf21cd93STycho Nightingale 	case ATC_IDX_PORT:
1071bf21cd93STycho Nightingale 		if (sc->vga_atc.atc_flipflop == 0) {
1072bf21cd93STycho Nightingale 			if (sc->vga_atc.atc_index & 0x20)
1073bf21cd93STycho Nightingale 				assert(0);
1074bf21cd93STycho Nightingale 			sc->vga_atc.atc_index = val & ATC_IDX_MASK;
1075bf21cd93STycho Nightingale 		} else {
1076bf21cd93STycho Nightingale 			switch (sc->vga_atc.atc_index) {
1077bf21cd93STycho Nightingale 			case ATC_PALETTE0 ... ATC_PALETTE15:
1078bf21cd93STycho Nightingale 				sc->vga_atc.atc_palette[sc->vga_atc.atc_index] = val & 0x3f;
1079bf21cd93STycho Nightingale 				break;
1080bf21cd93STycho Nightingale 			case ATC_MODE_CONTROL:
1081bf21cd93STycho Nightingale 				sc->vga_atc.atc_mode = val;
1082bf21cd93STycho Nightingale 				break;
1083bf21cd93STycho Nightingale 			case ATC_OVERSCAN_COLOR:
1084bf21cd93STycho Nightingale 				sc->vga_atc.atc_overscan_color = val;
1085bf21cd93STycho Nightingale 				break;
1086bf21cd93STycho Nightingale 			case ATC_COLOR_PLANE_ENABLE:
1087bf21cd93STycho Nightingale 				sc->vga_atc.atc_color_plane_enb = val;
1088bf21cd93STycho Nightingale 				break;
1089bf21cd93STycho Nightingale 			case ATC_HORIZ_PIXEL_PANNING:
1090bf21cd93STycho Nightingale 				sc->vga_atc.atc_horiz_pixel_panning = val;
1091bf21cd93STycho Nightingale 				break;
1092bf21cd93STycho Nightingale 			case ATC_COLOR_SELECT:
1093bf21cd93STycho Nightingale 				sc->vga_atc.atc_color_select = val;
1094bf21cd93STycho Nightingale 				sc->vga_atc.atc_color_select_45 =
1095bf21cd93STycho Nightingale 					(val & ATC_CS_C45) << 4;
1096bf21cd93STycho Nightingale 				sc->vga_atc.atc_color_select_67 =
10974c87aefeSPatrick Mooney 					((val & ATC_CS_C67) >> 2) << 6;
1098bf21cd93STycho Nightingale 				break;
1099bf21cd93STycho Nightingale 			default:
1100bf21cd93STycho Nightingale 				//printf("XXX VGA ATC: outb 0x%04x, 0x%02x at index %d\n", port, val, sc->vga_atc.atc_index);
1101bf21cd93STycho Nightingale 				assert(0);
1102bf21cd93STycho Nightingale 				break;
1103bf21cd93STycho Nightingale 			}
1104bf21cd93STycho Nightingale 		}
1105bf21cd93STycho Nightingale 		sc->vga_atc.atc_flipflop ^= 1;
1106bf21cd93STycho Nightingale 		break;
1107bf21cd93STycho Nightingale 	case ATC_DATA_PORT:
1108bf21cd93STycho Nightingale 		break;
1109bf21cd93STycho Nightingale 	case SEQ_IDX_PORT:
1110bf21cd93STycho Nightingale 		sc->vga_seq.seq_index = val & 0x1f;
1111bf21cd93STycho Nightingale 		break;
1112bf21cd93STycho Nightingale 	case SEQ_DATA_PORT:
1113bf21cd93STycho Nightingale 		switch (sc->vga_seq.seq_index) {
1114bf21cd93STycho Nightingale 		case SEQ_RESET:
1115bf21cd93STycho Nightingale 			sc->vga_seq.seq_reset = val;
1116bf21cd93STycho Nightingale 			break;
1117bf21cd93STycho Nightingale 		case SEQ_CLOCKING_MODE:
1118bf21cd93STycho Nightingale 			sc->vga_seq.seq_clock_mode = val;
1119bf21cd93STycho Nightingale 			sc->vga_seq.seq_cm_dots = (val & SEQ_CM_89) ? 8 : 9;
1120bf21cd93STycho Nightingale 			break;
1121bf21cd93STycho Nightingale 		case SEQ_MAP_MASK:
1122bf21cd93STycho Nightingale 			sc->vga_seq.seq_map_mask = val;
1123bf21cd93STycho Nightingale 			break;
1124bf21cd93STycho Nightingale 		case SEQ_CHAR_MAP_SELECT:
1125bf21cd93STycho Nightingale 			sc->vga_seq.seq_cmap_sel = val;
1126bf21cd93STycho Nightingale 
1127bf21cd93STycho Nightingale 			sc->vga_seq.seq_cmap_pri_off = ((((val & SEQ_CMS_SA) >> SEQ_CMS_SA_SHIFT) * 2) + ((val & SEQ_CMS_SAH) >> SEQ_CMS_SAH_SHIFT)) * 8 * KB;
1128bf21cd93STycho Nightingale 			sc->vga_seq.seq_cmap_sec_off = ((((val & SEQ_CMS_SB) >> SEQ_CMS_SB_SHIFT) * 2) + ((val & SEQ_CMS_SBH) >> SEQ_CMS_SBH_SHIFT)) * 8 * KB;
1129bf21cd93STycho Nightingale 			break;
1130bf21cd93STycho Nightingale 		case SEQ_MEMORY_MODE:
1131bf21cd93STycho Nightingale 			sc->vga_seq.seq_mm = val;
11324c87aefeSPatrick Mooney 			/* Windows queries Chain4 */
11334c87aefeSPatrick Mooney 			//assert((sc->vga_seq.seq_mm & SEQ_MM_C4) == 0);
1134bf21cd93STycho Nightingale 			break;
1135bf21cd93STycho Nightingale 		default:
1136bf21cd93STycho Nightingale 			//printf("XXX VGA SEQ: outb 0x%04x, 0x%02x at index %d\n", port, val, sc->vga_seq.seq_index);
1137bf21cd93STycho Nightingale 			assert(0);
1138bf21cd93STycho Nightingale 			break;
1139bf21cd93STycho Nightingale 		}
1140bf21cd93STycho Nightingale 		break;
1141bf21cd93STycho Nightingale 	case DAC_MASK:
1142bf21cd93STycho Nightingale 		break;
1143bf21cd93STycho Nightingale 	case DAC_IDX_RD_PORT:
1144bf21cd93STycho Nightingale 		sc->vga_dac.dac_rd_index = val;
1145bf21cd93STycho Nightingale 		sc->vga_dac.dac_rd_subindex = 0;
1146bf21cd93STycho Nightingale 		break;
1147bf21cd93STycho Nightingale 	case DAC_IDX_WR_PORT:
1148bf21cd93STycho Nightingale 		sc->vga_dac.dac_wr_index = val;
1149bf21cd93STycho Nightingale 		sc->vga_dac.dac_wr_subindex = 0;
1150bf21cd93STycho Nightingale 		break;
1151bf21cd93STycho Nightingale 	case DAC_DATA_PORT:
1152bf21cd93STycho Nightingale 		sc->vga_dac.dac_palette[3 * sc->vga_dac.dac_wr_index +
1153bf21cd93STycho Nightingale 					sc->vga_dac.dac_wr_subindex] = val;
1154bf21cd93STycho Nightingale 		sc->vga_dac.dac_wr_subindex++;
1155bf21cd93STycho Nightingale 		if (sc->vga_dac.dac_wr_subindex == 3) {
1156bf21cd93STycho Nightingale 			sc->vga_dac.dac_palette_rgb[sc->vga_dac.dac_wr_index] =
1157bf21cd93STycho Nightingale 				((((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 0] << 2) |
1158bf21cd93STycho Nightingale 				   ((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 0] & 0x1) << 1) |
1159bf21cd93STycho Nightingale 				   (sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 0] & 0x1)) << 16) |
1160bf21cd93STycho Nightingale 				 (((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 1] << 2) |
1161bf21cd93STycho Nightingale 				   ((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 1] & 0x1) << 1) |
1162bf21cd93STycho Nightingale 				   (sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 1] & 0x1)) << 8) |
1163bf21cd93STycho Nightingale 				 (((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 2] << 2) |
1164bf21cd93STycho Nightingale 				   ((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 2] & 0x1) << 1) |
1165bf21cd93STycho Nightingale 				   (sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 2] & 0x1)) << 0));
1166bf21cd93STycho Nightingale 
1167bf21cd93STycho Nightingale 			sc->vga_dac.dac_wr_index++;
1168bf21cd93STycho Nightingale 			sc->vga_dac.dac_wr_subindex = 0;
1169bf21cd93STycho Nightingale 		}
1170bf21cd93STycho Nightingale 		break;
1171bf21cd93STycho Nightingale 	case GC_IDX_PORT:
1172bf21cd93STycho Nightingale 		sc->vga_gc.gc_index = val;
1173bf21cd93STycho Nightingale 		break;
1174bf21cd93STycho Nightingale 	case GC_DATA_PORT:
1175bf21cd93STycho Nightingale 		switch (sc->vga_gc.gc_index) {
1176bf21cd93STycho Nightingale 		case GC_SET_RESET:
1177bf21cd93STycho Nightingale 			sc->vga_gc.gc_set_reset = val;
1178bf21cd93STycho Nightingale 			break;
1179bf21cd93STycho Nightingale 		case GC_ENABLE_SET_RESET:
1180bf21cd93STycho Nightingale 			sc->vga_gc.gc_enb_set_reset = val;
1181bf21cd93STycho Nightingale 			break;
1182bf21cd93STycho Nightingale 		case GC_COLOR_COMPARE:
1183bf21cd93STycho Nightingale 			sc->vga_gc.gc_color_compare = val;
1184bf21cd93STycho Nightingale 			break;
1185bf21cd93STycho Nightingale 		case GC_DATA_ROTATE:
1186bf21cd93STycho Nightingale 			sc->vga_gc.gc_rotate = val;
1187bf21cd93STycho Nightingale 			sc->vga_gc.gc_op = (val >> 3) & 0x3;
1188bf21cd93STycho Nightingale 			break;
1189bf21cd93STycho Nightingale 		case GC_READ_MAP_SELECT:
1190bf21cd93STycho Nightingale 			sc->vga_gc.gc_read_map_sel = val;
1191bf21cd93STycho Nightingale 			break;
1192bf21cd93STycho Nightingale 		case GC_MODE:
1193bf21cd93STycho Nightingale 			sc->vga_gc.gc_mode = val;
1194bf21cd93STycho Nightingale 			sc->vga_gc.gc_mode_c4 = (val & GC_MODE_C4) != 0;
1195bf21cd93STycho Nightingale 			assert(!sc->vga_gc.gc_mode_c4);
1196bf21cd93STycho Nightingale 			sc->vga_gc.gc_mode_oe = (val & GC_MODE_OE) != 0;
1197bf21cd93STycho Nightingale 			sc->vga_gc.gc_mode_rm = (val >> 3) & 0x1;
1198bf21cd93STycho Nightingale 			sc->vga_gc.gc_mode_wm = val & 0x3;
11994c87aefeSPatrick Mooney 
12004c87aefeSPatrick Mooney 			if (sc->gc_image)
12014c87aefeSPatrick Mooney 				sc->gc_image->vgamode = 1;
1202bf21cd93STycho Nightingale 			break;
1203bf21cd93STycho Nightingale 		case GC_MISCELLANEOUS:
1204bf21cd93STycho Nightingale 			sc->vga_gc.gc_misc = val;
1205bf21cd93STycho Nightingale 			sc->vga_gc.gc_misc_gm = val & GC_MISC_GM;
1206bf21cd93STycho Nightingale 			sc->vga_gc.gc_misc_mm = (val & GC_MISC_MM) >>
1207bf21cd93STycho Nightingale 			    GC_MISC_MM_SHIFT;
1208bf21cd93STycho Nightingale 			break;
1209bf21cd93STycho Nightingale 		case GC_COLOR_DONT_CARE:
1210bf21cd93STycho Nightingale 			sc->vga_gc.gc_color_dont_care = val;
1211bf21cd93STycho Nightingale 			break;
1212bf21cd93STycho Nightingale 		case GC_BIT_MASK:
1213bf21cd93STycho Nightingale 			sc->vga_gc.gc_bit_mask = val;
1214bf21cd93STycho Nightingale 			break;
1215bf21cd93STycho Nightingale 		default:
1216bf21cd93STycho Nightingale 			//printf("XXX VGA GC: outb 0x%04x, 0x%02x at index %d\n", port, val, sc->vga_gc.gc_index);
1217bf21cd93STycho Nightingale 			assert(0);
1218bf21cd93STycho Nightingale 			break;
1219bf21cd93STycho Nightingale 		}
1220bf21cd93STycho Nightingale 		break;
1221bf21cd93STycho Nightingale 	case GEN_INPUT_STS0_PORT:
1222bf21cd93STycho Nightingale 		/* write to Miscellaneous Output Register */
1223bf21cd93STycho Nightingale 		sc->vga_misc = val;
1224bf21cd93STycho Nightingale 		break;
1225bf21cd93STycho Nightingale 	case GEN_INPUT_STS1_MONO_PORT:
1226bf21cd93STycho Nightingale 	case GEN_INPUT_STS1_COLOR_PORT:
1227bf21cd93STycho Nightingale 		/* write to Feature Control Register */
1228bf21cd93STycho Nightingale 		break;
12294c87aefeSPatrick Mooney //	case 0x3c3:
12304c87aefeSPatrick Mooney //		break;
1231bf21cd93STycho Nightingale 	default:
12324c87aefeSPatrick Mooney 		printf("XXX vga_port_out_handler() unhandled port 0x%x, val 0x%x\n", port, val);
1233bf21cd93STycho Nightingale 		//assert(0);
1234bf21cd93STycho Nightingale 		return (-1);
1235bf21cd93STycho Nightingale 	}
1236bf21cd93STycho Nightingale 	return (0);
1237bf21cd93STycho Nightingale }
1238bf21cd93STycho Nightingale 
1239bf21cd93STycho Nightingale static int
vga_port_handler(struct vmctx * ctx,int in,int port,int bytes,uint32_t * eax,void * arg)124059d65d31SAndy Fiddaman vga_port_handler(struct vmctx *ctx, int in, int port,
124159d65d31SAndy Fiddaman     int bytes, uint32_t *eax, void *arg)
1242bf21cd93STycho Nightingale {
1243bf21cd93STycho Nightingale 	uint8_t val;
1244bf21cd93STycho Nightingale 	int error;
1245bf21cd93STycho Nightingale 
1246bf21cd93STycho Nightingale 	switch (bytes) {
1247bf21cd93STycho Nightingale 	case 1:
1248bf21cd93STycho Nightingale 		if (in) {
1249bf21cd93STycho Nightingale 			*eax &= ~0xff;
1250bf21cd93STycho Nightingale 			error = vga_port_in_handler(ctx, in, port, 1,
1251bf21cd93STycho Nightingale 						    &val, arg);
1252bf21cd93STycho Nightingale 			if (!error) {
1253bf21cd93STycho Nightingale 				*eax |= val & 0xff;
1254bf21cd93STycho Nightingale 			}
1255bf21cd93STycho Nightingale 		} else {
1256bf21cd93STycho Nightingale 			val = *eax & 0xff;
1257bf21cd93STycho Nightingale 			error = vga_port_out_handler(ctx, in, port, 1,
1258bf21cd93STycho Nightingale 						     val, arg);
1259bf21cd93STycho Nightingale 		}
1260bf21cd93STycho Nightingale 		break;
1261bf21cd93STycho Nightingale 	case 2:
1262bf21cd93STycho Nightingale 		if (in) {
1263bf21cd93STycho Nightingale 			*eax &= ~0xffff;
1264bf21cd93STycho Nightingale 			error = vga_port_in_handler(ctx, in, port, 1,
1265bf21cd93STycho Nightingale 						    &val, arg);
1266bf21cd93STycho Nightingale 			if (!error) {
1267bf21cd93STycho Nightingale 				*eax |= val & 0xff;
1268bf21cd93STycho Nightingale 			}
1269bf21cd93STycho Nightingale 			error = vga_port_in_handler(ctx, in, port + 1, 1,
1270bf21cd93STycho Nightingale 						    &val, arg);
1271bf21cd93STycho Nightingale 			if (!error) {
1272bf21cd93STycho Nightingale 				*eax |= (val & 0xff) << 8;
1273bf21cd93STycho Nightingale 			}
1274bf21cd93STycho Nightingale 		} else {
1275bf21cd93STycho Nightingale 			val = *eax & 0xff;
1276bf21cd93STycho Nightingale 			error = vga_port_out_handler(ctx, in, port, 1,
1277bf21cd93STycho Nightingale 						     val, arg);
1278bf21cd93STycho Nightingale 			val = (*eax >> 8) & 0xff;
1279bf21cd93STycho Nightingale 			error =vga_port_out_handler(ctx, in, port + 1, 1,
1280bf21cd93STycho Nightingale 						    val, arg);
1281bf21cd93STycho Nightingale 		}
1282bf21cd93STycho Nightingale 		break;
1283bf21cd93STycho Nightingale 	default:
1284bf21cd93STycho Nightingale 		assert(0);
1285bf21cd93STycho Nightingale 		return (-1);
1286bf21cd93STycho Nightingale 	}
1287bf21cd93STycho Nightingale 
1288bf21cd93STycho Nightingale 	return (error);
1289bf21cd93STycho Nightingale }
1290bf21cd93STycho Nightingale 
12914c87aefeSPatrick Mooney void *
vga_init(int io_only)12924c87aefeSPatrick Mooney vga_init(int io_only)
1293bf21cd93STycho Nightingale {
1294bf21cd93STycho Nightingale 	struct inout_port iop;
1295bf21cd93STycho Nightingale 	struct vga_softc *sc;
1296bf21cd93STycho Nightingale 	int port, error;
1297bf21cd93STycho Nightingale 
1298bf21cd93STycho Nightingale 	sc = calloc(1, sizeof(struct vga_softc));
1299bf21cd93STycho Nightingale 
1300bf21cd93STycho Nightingale 	bzero(&iop, sizeof(struct inout_port));
1301bf21cd93STycho Nightingale 	iop.name = "VGA";
1302bf21cd93STycho Nightingale 	for (port = VGA_IOPORT_START; port <= VGA_IOPORT_END; port++) {
1303bf21cd93STycho Nightingale 		iop.port = port;
1304bf21cd93STycho Nightingale 		iop.size = 1;
1305bf21cd93STycho Nightingale 		iop.flags = IOPORT_F_INOUT;
1306bf21cd93STycho Nightingale 		iop.handler = vga_port_handler;
1307bf21cd93STycho Nightingale 		iop.arg = sc;
1308bf21cd93STycho Nightingale 
1309bf21cd93STycho Nightingale 		error = register_inout(&iop);
1310bf21cd93STycho Nightingale 		assert(error == 0);
1311bf21cd93STycho Nightingale 	}
1312bf21cd93STycho Nightingale 
13134c87aefeSPatrick Mooney 	sc->gc_image = console_get_image();
13144c87aefeSPatrick Mooney 
13154c87aefeSPatrick Mooney 	/* only handle io ports; vga graphics is disabled */
13164c87aefeSPatrick Mooney 	if (io_only)
13174c87aefeSPatrick Mooney 		return(sc);
13184c87aefeSPatrick Mooney 
1319bf21cd93STycho Nightingale 	sc->mr.name = "VGA memory";
1320bf21cd93STycho Nightingale 	sc->mr.flags = MEM_F_RW;
1321bf21cd93STycho Nightingale 	sc->mr.base = 640 * KB;
1322bf21cd93STycho Nightingale 	sc->mr.size = 128 * KB;
1323bf21cd93STycho Nightingale 	sc->mr.handler = vga_mem_handler;
1324bf21cd93STycho Nightingale 	sc->mr.arg1 = sc;
1325bf21cd93STycho Nightingale 	error = register_mem_fallback(&sc->mr);
1326bf21cd93STycho Nightingale 	assert(error == 0);
1327bf21cd93STycho Nightingale 
1328bf21cd93STycho Nightingale 	sc->vga_ram = malloc(256 * KB);
1329bf21cd93STycho Nightingale 	memset(sc->vga_ram, 0, 256 * KB);
1330bf21cd93STycho Nightingale 
13314c87aefeSPatrick Mooney 	{
13324c87aefeSPatrick Mooney 		static uint8_t palette[] = {
13334c87aefeSPatrick Mooney 			0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
13344c87aefeSPatrick Mooney 			0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a,
13354c87aefeSPatrick Mooney 			0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f,
13364c87aefeSPatrick Mooney 			0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f,
13374c87aefeSPatrick Mooney 		};
13384c87aefeSPatrick Mooney 		int i;
13394c87aefeSPatrick Mooney 
13404c87aefeSPatrick Mooney 		memcpy(sc->vga_dac.dac_palette, palette, 16 * 3 * sizeof (uint8_t));
13414c87aefeSPatrick Mooney 		for (i = 0; i < 16; i++) {
13424c87aefeSPatrick Mooney 			sc->vga_dac.dac_palette_rgb[i] =
13434c87aefeSPatrick Mooney 				((((sc->vga_dac.dac_palette[3*i + 0] << 2) |
13444c87aefeSPatrick Mooney 				   ((sc->vga_dac.dac_palette[3*i + 0] & 0x1) << 1) |
13454c87aefeSPatrick Mooney 				   (sc->vga_dac.dac_palette[3*i + 0] & 0x1)) << 16) |
13464c87aefeSPatrick Mooney 				 (((sc->vga_dac.dac_palette[3*i + 1] << 2) |
13474c87aefeSPatrick Mooney 				   ((sc->vga_dac.dac_palette[3*i + 1] & 0x1) << 1) |
13484c87aefeSPatrick Mooney 				   (sc->vga_dac.dac_palette[3*i + 1] & 0x1)) << 8) |
13494c87aefeSPatrick Mooney 				 (((sc->vga_dac.dac_palette[3*i + 2] << 2) |
13504c87aefeSPatrick Mooney 				   ((sc->vga_dac.dac_palette[3*i + 2] & 0x1) << 1) |
13514c87aefeSPatrick Mooney 				   (sc->vga_dac.dac_palette[3*i + 2] & 0x1)) << 0));
13524c87aefeSPatrick Mooney 		}
13534c87aefeSPatrick Mooney 	}
1354bf21cd93STycho Nightingale 
13554c87aefeSPatrick Mooney 	return (sc);
1356bf21cd93STycho Nightingale }
1357