blob: 13221fddfbb599504920076fe26fd0d40eab8483 [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
18#include "vgabios.h" // struct VideoSavePointer_s
19#include "vgahw.h" // vgahw_setup
20
21// Standard Video Save Pointer Table
22struct VideoSavePointer_s {
23 struct segoff_s videoparam;
24 struct segoff_s paramdynamicsave;
25 struct segoff_s textcharset;
26 struct segoff_s graphcharset;
27 struct segoff_s secsavepointer;
28 u8 reserved[8];
29} PACKED;
30
31struct VideoSavePointer_s video_save_pointer_table VAR16;
32
33struct VideoParam_s video_param_table[29] VAR16;
34
35
36/****************************************************************
37 * PCI Data
38 ****************************************************************/
39
40struct pci_data rom_pci_data VAR16 VISIBLE16 = {
41 .signature = PCI_ROM_SIGNATURE,
42 .vendor = CONFIG_VGA_VID,
43 .device = CONFIG_VGA_DID,
44 .dlen = 0x18,
45 .class_hi = 0x300,
46 .irevision = 1,
47 .type = PCIROM_CODETYPE_X86,
48 .indicator = 0x80,
49};
50
51
52/****************************************************************
53 * PMM call and extra stack setup
54 ****************************************************************/
55
56u16 ExtraStackSeg VAR16 VISIBLE16;
57
58static void
59allocate_extra_stack(void)
60{
61 if (!CONFIG_VGA_ALLOCATE_EXTRA_STACK)
62 return;
63 void *pmmscan = (void*)BUILD_BIOS_ADDR;
64 for (; pmmscan < (void*)BUILD_BIOS_ADDR+BUILD_BIOS_SIZE; pmmscan+=16) {
65 struct pmmheader *pmm = pmmscan;
66 if (pmm->signature != PMM_SIGNATURE)
67 continue;
68 if (checksum_far(0, pmm, pmm->length))
69 continue;
70 struct segoff_s entry = pmm->entry;
71 dprintf(1, "Attempting to allocate VGA stack via pmm call to %04x:%04x\n"
72 , entry.seg, entry.offset);
73 u16 res1, res2;
74 asm volatile(
75 "pushl %0\n"
76 "pushw $(8|1)\n" // Permanent low memory request
77 "pushl $0xffffffff\n" // Anonymous handle
78 "pushl $" __stringify(CONFIG_VGA_EXTRA_STACK_SIZE) "\n"
79 "pushw $0x00\n" // PMM allocation request
80 "lcallw *12(%%esp)\n"
81 "addl $16, %%esp\n"
82 "cli\n"
83 "cld\n"
84 : "+r" (entry.segoff), "=a" (res1), "=d" (res2) : : "cc", "memory");
85 u32 res = res1 | (res2 << 16);
86 if (!res || res == PMM_FUNCTION_NOT_SUPPORTED)
87 return;
88 dprintf(1, "VGA stack allocated at %x\n", res);
89 SET_VGA(ExtraStackSeg, res >> 4);
90 extern void entry_10_extrastack(void);
91 SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10_extrastack));
92 return;
93 }
94}
95
96
97/****************************************************************
98 * VGA post
99 ****************************************************************/
100
101static void
102init_bios_area(void)
103{
104 // init detected hardware BIOS Area
105 // set 80x25 color (not clear from RBIL but usual)
106 set_equipment_flags(0x30, 0x20);
107
108 // the default char height
109 SET_BDA(char_height, 0x10);
110
111 // Clear the screen
112 SET_BDA(video_ctl, 0x60);
113
114 // Set the basic screen we have
115 SET_BDA(video_switches, 0xf9);
116
117 // Set the basic modeset options
118 SET_BDA(modeset_ctl, 0x51);
119
120 // Set the default MSR
121 SET_BDA(video_msr, 0x09);
122}
123
124int VgaBDF VAR16 = -1;
125int HaveRunInit VAR16;
126
127void VISIBLE16
128vga_post(struct bregs *regs)
129{
Kevin O'Connor940fc1f2014-01-15 13:42:50 -0500130 serial_debug_preinit();
Kevin O'Connordab0a742013-12-03 11:50:49 -0500131 dprintf(1, "Start SeaVGABIOS (version %s)\n", VERSION);
132 debug_enter(regs, DEBUG_VGA_POST);
133
134 if (CONFIG_VGA_PCI && !GET_GLOBAL(HaveRunInit)) {
135 u16 bdf = regs->ax;
136 if ((pci_config_readw(bdf, PCI_VENDOR_ID)
137 == GET_GLOBAL(rom_pci_data.vendor))
138 && (pci_config_readw(bdf, PCI_DEVICE_ID)
139 == GET_GLOBAL(rom_pci_data.device)))
140 SET_VGA(VgaBDF, bdf);
141 }
142
143 int ret = vgahw_setup();
144 if (ret) {
145 dprintf(1, "Failed to initialize VGA hardware. Exiting.\n");
146 return;
147 }
148
149 if (GET_GLOBAL(HaveRunInit))
150 return;
151
152 init_bios_area();
153
154 SET_VGA(video_save_pointer_table.videoparam
155 , SEGOFF(get_global_seg(), (u32)video_param_table));
156 stdvga_build_video_param();
157
158 extern void entry_10(void);
159 SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10));
160
161 allocate_extra_stack();
162
163 SET_VGA(HaveRunInit, 1);
164
165 // Fixup checksum
166 extern u8 _rom_header_size, _rom_header_checksum;
167 SET_VGA(_rom_header_checksum, 0);
168 u8 sum = -checksum_far(get_global_seg(), 0,
169 GET_GLOBAL(_rom_header_size) * 512);
170 SET_VGA(_rom_header_checksum, sum);
171}