blob: c6c8149083973b9a925ecc838b9cf3cfe702f3ca [file] [log] [blame]
Kevin O'Connordab0a742013-12-03 11:50:49 -05001// Main VGA bios initialization
2//
3// Copyright (C) 2009-2013 Kevin O'Connor <kevin@koconnor.net>
4// Copyright (C) 2001-2008 the LGPL VGABios developers Team
5//
6// This file may be distributed under the terms of the GNU LGPLv3 license.
7
8#include "biosvar.h" // SET_BDA
9#include "bregs.h" // struct bregs
10#include "hw/pci.h" // pci_config_readw
11#include "hw/pci_regs.h" // PCI_VENDOR_ID
Kevin O'Connor940fc1f2014-01-15 13:42:50 -050012#include "hw/serialio.h" // serial_debug_preinit
Kevin O'Connordab0a742013-12-03 11:50:49 -050013#include "output.h" // dprintf
14#include "std/optionrom.h" // struct pci_data
15#include "std/pmm.h" // struct pmmheader
16#include "string.h" // checksum_far
Kevin O'Connor2f2ec112016-08-05 11:14:58 -040017#include "vgabios.h" // SET_VGA
Kevin O'Connordab0a742013-12-03 11:50:49 -050018#include "vgahw.h" // vgahw_setup
Kevin O'Connor2f2ec112016-08-05 11:14:58 -040019#include "vgautil.h" // swcursor_check_event
Kevin O'Connordab0a742013-12-03 11:50:49 -050020
Kevin O'Connorfe2cbf62014-04-14 10:46:34 -040021// Type of emulator platform - for dprintf with certain compile options.
22int PlatformRunningOn VAR16;
23
Kevin O'Connordab0a742013-12-03 11:50:49 -050024
25/****************************************************************
26 * PCI Data
27 ****************************************************************/
28
29struct pci_data rom_pci_data VAR16 VISIBLE16 = {
30 .signature = PCI_ROM_SIGNATURE,
31 .vendor = CONFIG_VGA_VID,
32 .device = CONFIG_VGA_DID,
33 .dlen = 0x18,
34 .class_hi = 0x300,
35 .irevision = 1,
36 .type = PCIROM_CODETYPE_X86,
37 .indicator = 0x80,
38};
39
40
41/****************************************************************
42 * PMM call and extra stack setup
43 ****************************************************************/
44
45u16 ExtraStackSeg VAR16 VISIBLE16;
46
47static void
48allocate_extra_stack(void)
49{
50 if (!CONFIG_VGA_ALLOCATE_EXTRA_STACK)
51 return;
Kevin O'Connor8f82a4f2014-04-06 18:48:39 -040052 u32 pmmscan;
53 for (pmmscan=0; pmmscan < BUILD_BIOS_SIZE; pmmscan+=16) {
54 struct pmmheader *pmm = (void*)pmmscan;
55 if (GET_FARVAR(SEG_BIOS, pmm->signature) != PMM_SIGNATURE)
Kevin O'Connordab0a742013-12-03 11:50:49 -050056 continue;
Kevin O'Connor8f82a4f2014-04-06 18:48:39 -040057 if (checksum_far(SEG_BIOS, pmm, GET_FARVAR(SEG_BIOS, pmm->length)))
Kevin O'Connordab0a742013-12-03 11:50:49 -050058 continue;
Kevin O'Connor8f82a4f2014-04-06 18:48:39 -040059 struct segoff_s entry = GET_FARVAR(SEG_BIOS, pmm->entry);
Kevin O'Connordab0a742013-12-03 11:50:49 -050060 dprintf(1, "Attempting to allocate VGA stack via pmm call to %04x:%04x\n"
61 , entry.seg, entry.offset);
62 u16 res1, res2;
63 asm volatile(
64 "pushl %0\n"
65 "pushw $(8|1)\n" // Permanent low memory request
66 "pushl $0xffffffff\n" // Anonymous handle
Kevin O'Connore8436b52014-02-18 13:48:09 -050067 "pushl $" __stringify(CONFIG_VGA_EXTRA_STACK_SIZE/16) "\n"
Kevin O'Connordab0a742013-12-03 11:50:49 -050068 "pushw $0x00\n" // PMM allocation request
69 "lcallw *12(%%esp)\n"
70 "addl $16, %%esp\n"
71 "cli\n"
72 "cld\n"
73 : "+r" (entry.segoff), "=a" (res1), "=d" (res2) : : "cc", "memory");
74 u32 res = res1 | (res2 << 16);
75 if (!res || res == PMM_FUNCTION_NOT_SUPPORTED)
76 return;
77 dprintf(1, "VGA stack allocated at %x\n", res);
78 SET_VGA(ExtraStackSeg, res >> 4);
79 extern void entry_10_extrastack(void);
80 SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10_extrastack));
81 return;
82 }
83}
84
85
86/****************************************************************
Kevin O'Connorb4eb6fc2014-10-17 22:15:42 -040087 * Timer hook
88 ****************************************************************/
89
90struct segoff_s Timer_Hook_Resume VAR16 VISIBLE16;
91
92void VISIBLE16
93handle_timer_hook(void)
94{
Kevin O'Connor774f5cd2016-08-04 17:02:16 -040095 swcursor_check_event();
Kevin O'Connorb4eb6fc2014-10-17 22:15:42 -040096}
97
98static void
99hook_timer_irq(void)
100{
101 if (!CONFIG_VGA_EMULATE_TEXT)
102 return;
103 extern void entry_timer_hook(void);
104 extern void entry_timer_hook_extrastack(void);
105 struct segoff_s oldirq = GET_IVT(0x08);
106 struct segoff_s newirq = SEGOFF(get_global_seg(), (u32)entry_timer_hook);
107 if (CONFIG_VGA_ALLOCATE_EXTRA_STACK && GET_GLOBAL(ExtraStackSeg))
108 newirq = SEGOFF(get_global_seg(), (u32)entry_timer_hook_extrastack);
109 dprintf(1, "Hooking hardware timer irq (old=%x new=%x)\n"
110 , oldirq.segoff, newirq.segoff);
111 SET_VGA(Timer_Hook_Resume, oldirq);
112 SET_IVT(0x08, newirq);
113}
114
115
116/****************************************************************
Kevin O'Connordab0a742013-12-03 11:50:49 -0500117 * VGA post
118 ****************************************************************/
119
120static void
121init_bios_area(void)
122{
123 // init detected hardware BIOS Area
124 // set 80x25 color (not clear from RBIL but usual)
125 set_equipment_flags(0x30, 0x20);
126
Kevin O'Connordab0a742013-12-03 11:50:49 -0500127 // Set the basic modeset options
128 SET_BDA(modeset_ctl, 0x51);
129
Kevin O'Connorc5acee42014-10-23 15:54:59 -0400130 SET_BDA(dcc_index, CONFIG_VGA_STDVGA_PORTS ? 0x08 : 0xff);
Kevin O'Connor5b89d952014-10-23 13:04:17 -0400131
132 // FIXME
133 SET_BDA(video_msr, 0x00); // Unavailable on vanilla vga, but...
134 SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but...
Kevin O'Connordab0a742013-12-03 11:50:49 -0500135}
136
137int VgaBDF VAR16 = -1;
138int HaveRunInit VAR16;
139
140void VISIBLE16
141vga_post(struct bregs *regs)
142{
Kevin O'Connor940fc1f2014-01-15 13:42:50 -0500143 serial_debug_preinit();
Kevin O'Connordab0a742013-12-03 11:50:49 -0500144 dprintf(1, "Start SeaVGABIOS (version %s)\n", VERSION);
Kevin O'Connorefd70a52015-10-13 15:44:25 -0400145 dprintf(1, "VGABUILD: %s\n", BUILDINFO);
Kevin O'Connordab0a742013-12-03 11:50:49 -0500146 debug_enter(regs, DEBUG_VGA_POST);
147
148 if (CONFIG_VGA_PCI && !GET_GLOBAL(HaveRunInit)) {
149 u16 bdf = regs->ax;
150 if ((pci_config_readw(bdf, PCI_VENDOR_ID)
151 == GET_GLOBAL(rom_pci_data.vendor))
152 && (pci_config_readw(bdf, PCI_DEVICE_ID)
153 == GET_GLOBAL(rom_pci_data.device)))
154 SET_VGA(VgaBDF, bdf);
155 }
156
157 int ret = vgahw_setup();
158 if (ret) {
159 dprintf(1, "Failed to initialize VGA hardware. Exiting.\n");
160 return;
161 }
162
163 if (GET_GLOBAL(HaveRunInit))
164 return;
165
166 init_bios_area();
167
Kevin O'Connorefbf4d62014-02-09 11:50:21 -0500168 if (CONFIG_VGA_STDVGA_PORTS)
169 stdvga_build_video_param();
Kevin O'Connordab0a742013-12-03 11:50:49 -0500170
171 extern void entry_10(void);
172 SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10));
173
174 allocate_extra_stack();
175
Kevin O'Connorb4eb6fc2014-10-17 22:15:42 -0400176 hook_timer_irq();
177
Kevin O'Connordab0a742013-12-03 11:50:49 -0500178 SET_VGA(HaveRunInit, 1);
179
180 // Fixup checksum
181 extern u8 _rom_header_size, _rom_header_checksum;
182 SET_VGA(_rom_header_checksum, 0);
183 u8 sum = -checksum_far(get_global_seg(), 0,
184 GET_GLOBAL(_rom_header_size) * 512);
185 SET_VGA(_rom_header_checksum, sum);
186}