blob: 8d12261829f663f4fed98a99faa9346f9d0b5d21 [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
17#include "util.h" // VERSION
Kevin O'Connor63977902014-10-23 16:24:36 -040018#include "vgabios.h" // video_save_pointer_table
Kevin O'Connordab0a742013-12-03 11:50:49 -050019#include "vgahw.h" // vgahw_setup
20
Kevin O'Connor63977902014-10-23 16:24:36 -040021struct video_save_pointer_s video_save_pointer_table VAR16;
Kevin O'Connordab0a742013-12-03 11:50:49 -050022
Kevin O'Connor63977902014-10-23 16:24:36 -040023struct video_param_s video_param_table[29] VAR16;
Kevin O'Connordab0a742013-12-03 11:50:49 -050024
Kevin O'Connorfe2cbf62014-04-14 10:46:34 -040025// Type of emulator platform - for dprintf with certain compile options.
26int PlatformRunningOn VAR16;
27
Kevin O'Connordab0a742013-12-03 11:50:49 -050028
29/****************************************************************
30 * PCI Data
31 ****************************************************************/
32
33struct pci_data rom_pci_data VAR16 VISIBLE16 = {
34 .signature = PCI_ROM_SIGNATURE,
35 .vendor = CONFIG_VGA_VID,
36 .device = CONFIG_VGA_DID,
37 .dlen = 0x18,
38 .class_hi = 0x300,
39 .irevision = 1,
40 .type = PCIROM_CODETYPE_X86,
41 .indicator = 0x80,
42};
43
44
45/****************************************************************
46 * PMM call and extra stack setup
47 ****************************************************************/
48
49u16 ExtraStackSeg VAR16 VISIBLE16;
50
51static void
52allocate_extra_stack(void)
53{
54 if (!CONFIG_VGA_ALLOCATE_EXTRA_STACK)
55 return;
Kevin O'Connor8f82a4f2014-04-06 18:48:39 -040056 u32 pmmscan;
57 for (pmmscan=0; pmmscan < BUILD_BIOS_SIZE; pmmscan+=16) {
58 struct pmmheader *pmm = (void*)pmmscan;
59 if (GET_FARVAR(SEG_BIOS, pmm->signature) != PMM_SIGNATURE)
Kevin O'Connordab0a742013-12-03 11:50:49 -050060 continue;
Kevin O'Connor8f82a4f2014-04-06 18:48:39 -040061 if (checksum_far(SEG_BIOS, pmm, GET_FARVAR(SEG_BIOS, pmm->length)))
Kevin O'Connordab0a742013-12-03 11:50:49 -050062 continue;
Kevin O'Connor8f82a4f2014-04-06 18:48:39 -040063 struct segoff_s entry = GET_FARVAR(SEG_BIOS, pmm->entry);
Kevin O'Connordab0a742013-12-03 11:50:49 -050064 dprintf(1, "Attempting to allocate VGA stack via pmm call to %04x:%04x\n"
65 , entry.seg, entry.offset);
66 u16 res1, res2;
67 asm volatile(
68 "pushl %0\n"
69 "pushw $(8|1)\n" // Permanent low memory request
70 "pushl $0xffffffff\n" // Anonymous handle
Kevin O'Connore8436b52014-02-18 13:48:09 -050071 "pushl $" __stringify(CONFIG_VGA_EXTRA_STACK_SIZE/16) "\n"
Kevin O'Connordab0a742013-12-03 11:50:49 -050072 "pushw $0x00\n" // PMM allocation request
73 "lcallw *12(%%esp)\n"
74 "addl $16, %%esp\n"
75 "cli\n"
76 "cld\n"
77 : "+r" (entry.segoff), "=a" (res1), "=d" (res2) : : "cc", "memory");
78 u32 res = res1 | (res2 << 16);
79 if (!res || res == PMM_FUNCTION_NOT_SUPPORTED)
80 return;
81 dprintf(1, "VGA stack allocated at %x\n", res);
82 SET_VGA(ExtraStackSeg, res >> 4);
83 extern void entry_10_extrastack(void);
84 SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10_extrastack));
85 return;
86 }
87}
88
89
90/****************************************************************
Kevin O'Connorb4eb6fc2014-10-17 22:15:42 -040091 * Timer hook
92 ****************************************************************/
93
94struct segoff_s Timer_Hook_Resume VAR16 VISIBLE16;
95
96void VISIBLE16
97handle_timer_hook(void)
98{
99 if (!vga_emulate_text())
100 return;
101 vgafb_set_swcursor(GET_BDA(timer_counter) % 18 < 9);
102}
103
104static void
105hook_timer_irq(void)
106{
107 if (!CONFIG_VGA_EMULATE_TEXT)
108 return;
109 extern void entry_timer_hook(void);
110 extern void entry_timer_hook_extrastack(void);
111 struct segoff_s oldirq = GET_IVT(0x08);
112 struct segoff_s newirq = SEGOFF(get_global_seg(), (u32)entry_timer_hook);
113 if (CONFIG_VGA_ALLOCATE_EXTRA_STACK && GET_GLOBAL(ExtraStackSeg))
114 newirq = SEGOFF(get_global_seg(), (u32)entry_timer_hook_extrastack);
115 dprintf(1, "Hooking hardware timer irq (old=%x new=%x)\n"
116 , oldirq.segoff, newirq.segoff);
117 SET_VGA(Timer_Hook_Resume, oldirq);
118 SET_IVT(0x08, newirq);
119}
120
121
122/****************************************************************
Kevin O'Connordab0a742013-12-03 11:50:49 -0500123 * VGA post
124 ****************************************************************/
125
126static void
127init_bios_area(void)
128{
129 // init detected hardware BIOS Area
130 // set 80x25 color (not clear from RBIL but usual)
131 set_equipment_flags(0x30, 0x20);
132
Kevin O'Connordab0a742013-12-03 11:50:49 -0500133 // Set the basic modeset options
134 SET_BDA(modeset_ctl, 0x51);
135
Kevin O'Connorc5acee42014-10-23 15:54:59 -0400136 SET_BDA(dcc_index, CONFIG_VGA_STDVGA_PORTS ? 0x08 : 0xff);
Kevin O'Connor5b89d952014-10-23 13:04:17 -0400137 SET_BDA(video_savetable
138 , SEGOFF(get_global_seg(), (u32)&video_save_pointer_table));
139
140 // FIXME
141 SET_BDA(video_msr, 0x00); // Unavailable on vanilla vga, but...
142 SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but...
Kevin O'Connordab0a742013-12-03 11:50:49 -0500143}
144
145int VgaBDF VAR16 = -1;
146int HaveRunInit VAR16;
147
148void VISIBLE16
149vga_post(struct bregs *regs)
150{
Kevin O'Connor940fc1f2014-01-15 13:42:50 -0500151 serial_debug_preinit();
Kevin O'Connordab0a742013-12-03 11:50:49 -0500152 dprintf(1, "Start SeaVGABIOS (version %s)\n", VERSION);
153 debug_enter(regs, DEBUG_VGA_POST);
154
155 if (CONFIG_VGA_PCI && !GET_GLOBAL(HaveRunInit)) {
156 u16 bdf = regs->ax;
157 if ((pci_config_readw(bdf, PCI_VENDOR_ID)
158 == GET_GLOBAL(rom_pci_data.vendor))
159 && (pci_config_readw(bdf, PCI_DEVICE_ID)
160 == GET_GLOBAL(rom_pci_data.device)))
161 SET_VGA(VgaBDF, bdf);
162 }
163
164 int ret = vgahw_setup();
165 if (ret) {
166 dprintf(1, "Failed to initialize VGA hardware. Exiting.\n");
167 return;
168 }
169
170 if (GET_GLOBAL(HaveRunInit))
171 return;
172
173 init_bios_area();
174
175 SET_VGA(video_save_pointer_table.videoparam
176 , SEGOFF(get_global_seg(), (u32)video_param_table));
Kevin O'Connorefbf4d62014-02-09 11:50:21 -0500177 if (CONFIG_VGA_STDVGA_PORTS)
178 stdvga_build_video_param();
Kevin O'Connordab0a742013-12-03 11:50:49 -0500179
180 extern void entry_10(void);
181 SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10));
182
183 allocate_extra_stack();
184
Kevin O'Connorb4eb6fc2014-10-17 22:15:42 -0400185 hook_timer_irq();
186
Kevin O'Connordab0a742013-12-03 11:50:49 -0500187 SET_VGA(HaveRunInit, 1);
188
189 // Fixup checksum
190 extern u8 _rom_header_size, _rom_header_checksum;
191 SET_VGA(_rom_header_checksum, 0);
192 u8 sum = -checksum_far(get_global_seg(), 0,
193 GET_GLOBAL(_rom_header_size) * 512);
194 SET_VGA(_rom_header_checksum, sum);
195}