Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Avoid physical/virtual contiguity assumptions using new guest memory access functions
[palacios.git] / bios / seabios / src / vgahooks.c
1 // Hooks for via vgabios calls into main bios.
2 //
3 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "bregs.h" // set_code_invalid
8 #include "biosvar.h" // GET_GLOBAL
9 #include "pci.h" // pci_find_device
10 #include "pci_regs.h" // PCI_VENDOR_ID
11 #include "pci_ids.h" // PCI_VENDOR_ID_VIA
12 #include "util.h" // handle_155f
13 #include "config.h" // CONFIG_*
14
15 #define VH_VIA 1
16 #define VH_INTEL 2
17
18 int VGAHookHandlerType VAR16VISIBLE;
19
20 static void
21 handle_155fXX(struct bregs *regs)
22 {
23     set_code_unimplemented(regs, RET_EUNSUPPORTED);
24 }
25
26
27 /****************************************************************
28  * Via hooks
29  ****************************************************************/
30
31 int ViaFBsize VAR16VISIBLE, ViaRamSpeed VAR16VISIBLE;
32
33 static void
34 via_155f01(struct bregs *regs)
35 {
36     regs->eax = 0x5f;
37     regs->cl = 2; // panel type =  2 = 1024 * 768
38     set_success(regs);
39     dprintf(1, "Warning: VGA panel type is hardcoded\n");
40 }
41
42 static void
43 via_155f02(struct bregs *regs)
44 {
45     regs->eax = 0x5f;
46     regs->bx = 2;
47     regs->cx = 0x401;  // PAL + crt only
48     regs->dx = 0;  // TV Layout - default
49     set_success(regs);
50     dprintf(1, "Warning: VGA TV/CRT output type is hardcoded\n");
51 }
52
53 static void
54 via_155f18(struct bregs *regs)
55 {
56     int fbsize = GET_GLOBAL(ViaFBsize), ramspeed = GET_GLOBAL(ViaRamSpeed);
57     if (fbsize < 0 || ramspeed < 0) {
58         set_code_invalid(regs, RET_EUNSUPPORTED);
59         return;
60     }
61     regs->eax = 0x5f;
62     regs->ebx = 0x500 | (ramspeed << 4) | fbsize;
63     regs->ecx = 0x060;
64     set_success(regs);
65 }
66
67 static void
68 via_155f19(struct bregs *regs)
69 {
70     set_invalid_silent(regs);
71 }
72
73 static void
74 via_155f(struct bregs *regs)
75 {
76     switch (regs->al) {
77     case 0x01: via_155f01(regs); break;
78     case 0x02: via_155f02(regs); break;
79     case 0x18: via_155f18(regs); break;
80     case 0x19: via_155f19(regs); break;
81     default:   handle_155fXX(regs); break;
82     }
83 }
84
85 static int
86 getFBSize(struct pci_device *pci)
87 {
88     /* FB config */
89     u8 reg = pci_config_readb(pci->bdf, 0xa1);
90
91     /* GFX disabled ? */
92     if (!(reg & 0x80))
93         return -1;
94
95     static u8 mem_power[] = {0, 3, 4, 5, 6, 7, 8, 9};
96     return mem_power[(reg >> 4) & 0x7];
97 }
98
99 static int
100 getViaRamSpeed(struct pci_device *pci)
101 {
102     return (pci_config_readb(pci->bdf, 0x90) & 0x07) + 3;
103 }
104
105 static int
106 getAMDRamSpeed(void)
107 {
108     struct pci_device *pci = pci_find_device(PCI_VENDOR_ID_AMD
109                                              , PCI_DEVICE_ID_AMD_K8_NB_MEMCTL);
110     if (!pci)
111         return -1;
112
113     /* mem clk 0 = DDR2 400 */
114     return (pci_config_readb(pci->bdf, 0x94) & 0x7) + 6;
115 }
116
117 /* int 0x15 - 5f18
118
119    ECX = unknown/dont care
120    EBX[3..0] Frame Buffer Size 2^N MiB
121    EBX[7..4] Memory speed:
122        0: SDR  66Mhz
123        1: SDR 100Mhz
124        2: SDR 133Mhz
125        3: DDR 100Mhz (PC1600 or DDR200)
126        4: DDR 133Mhz (PC2100 or DDR266)
127        5: DDR 166Mhz (PC2700 or DDR333)
128        6: DDR 200Mhz (PC3200 or DDR400)
129        7: DDR2 133Mhz (DDR2 533)
130        8: DDR2 166Mhz (DDR2 667)
131        9: DDR2 200Mhz (DDR2 800)
132        A: DDR2 233Mhz (DDR2 1066)
133        B: and above: Unknown
134    EBX[?..8] Total memory size?
135    EAX = 0x5f for success
136 */
137
138 #define PCI_DEVICE_ID_VIA_K8M890CE_3    0x3336
139 #define PCI_DEVICE_ID_VIA_VX855_MEMCTRL 0x3409
140
141 static void
142 via_setup(struct pci_device *pci)
143 {
144     VGAHookHandlerType = VH_VIA;
145
146     struct pci_device *d = pci_find_device(PCI_VENDOR_ID_VIA
147                                            , PCI_DEVICE_ID_VIA_K8M890CE_3);
148     if (d) {
149         ViaFBsize = getFBSize(d);
150         ViaRamSpeed = getAMDRamSpeed();
151         return;
152     }
153     d = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855_MEMCTRL);
154     if (d) {
155         ViaFBsize = getFBSize(d);
156         ViaRamSpeed = getViaRamSpeed(d);
157         return;
158     }
159
160     dprintf(1, "Warning: VGA memory size and speed is hardcoded\n");
161     ViaFBsize = 5; // 32M frame buffer
162     ViaRamSpeed = 4; // MCLK = DDR266
163 }
164
165
166 /****************************************************************
167  * Intel VGA hooks
168  ****************************************************************/
169
170 u8 IntelDisplayType VAR16VISIBLE, IntelDisplayId VAR16VISIBLE;
171
172 static void
173 intel_155f35(struct bregs *regs)
174 {
175     regs->ax = 0x005f;
176     regs->cl = GET_GLOBAL(IntelDisplayType);
177     set_success(regs);
178 }
179
180 static void
181 intel_155f40(struct bregs *regs)
182 {
183     regs->ax = 0x005f;
184     regs->cl = GET_GLOBAL(IntelDisplayId);
185     set_success(regs);
186 }
187
188 static void
189 intel_155f(struct bregs *regs)
190 {
191     switch (regs->al) {
192     case 0x35: intel_155f35(regs); break;
193     case 0x40: intel_155f40(regs); break;
194     default:   handle_155fXX(regs); break;
195     }
196 }
197
198 #define BOOT_DISPLAY_DEFAULT    (0)
199 #define BOOT_DISPLAY_CRT        (1 << 0)
200 #define BOOT_DISPLAY_TV         (1 << 1)
201 #define BOOT_DISPLAY_EFP        (1 << 2)
202 #define BOOT_DISPLAY_LCD        (1 << 3)
203 #define BOOT_DISPLAY_CRT2       (1 << 4)
204 #define BOOT_DISPLAY_TV2        (1 << 5)
205 #define BOOT_DISPLAY_EFP2       (1 << 6)
206 #define BOOT_DISPLAY_LCD2       (1 << 7)
207
208 static void
209 roda_setup(struct pci_device *pci)
210 {
211     VGAHookHandlerType = VH_INTEL;
212     // IntelDisplayType = BOOT_DISPLAY_DEFAULT;
213     IntelDisplayType = BOOT_DISPLAY_LCD;
214     // IntelDisplayId = inb(0x60f) & 0x0f; // Correct according to Crete
215     IntelDisplayId = 3; // Correct according to empirical studies
216 }
217
218 static void
219 kontron_setup(struct pci_device *pci)
220 {
221     VGAHookHandlerType = VH_INTEL;
222     IntelDisplayType = BOOT_DISPLAY_CRT;
223     IntelDisplayId = 3;
224 }
225
226 static void
227 getac_setup(struct pci_device *pci)
228 {
229 }
230
231
232 /****************************************************************
233  * Entry and setup
234  ****************************************************************/
235
236 // Main 16bit entry point
237 void
238 handle_155f(struct bregs *regs)
239 {
240     if (!CONFIG_VGAHOOKS) {
241         handle_155fXX(regs);
242         return;
243     }
244
245     int htype = GET_GLOBAL(VGAHookHandlerType);
246     switch (htype) {
247     case VH_VIA:   via_155f(regs); break;
248     case VH_INTEL: intel_155f(regs); break;
249     default:       handle_155fXX(regs); break;
250     }
251 }
252
253 // Setup
254 void
255 vgahook_setup(struct pci_device *pci)
256 {
257     if (!CONFIG_VGAHOOKS || !CBvendor || !CBpart)
258         return;
259
260     if (strcmp(CBvendor, "KONTRON") == 0 && strcmp(CBpart, "986LCD-M") == 0)
261         kontron_setup(pci);
262     else if (strcmp(CBvendor, "GETAC") == 0 && strcmp(CBpart, "P470") == 0)
263         getac_setup(pci);
264     else if (strcmp(CBvendor, "RODA") == 0 && strcmp(CBpart, "RK886EX") == 0)
265         roda_setup(pci);
266     else if (pci->vendor == PCI_VENDOR_ID_VIA)
267         via_setup(pci);
268 }