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