]>
Commit | Line | Data |
---|---|---|
c7de829c WD |
1 | /**************************************************************************** |
2 | * | |
3 | * BIOS emulator and interface | |
4 | * to Realmode X86 Emulator Library | |
5 | * | |
6 | * Copyright (C) 1996-1999 SciTech Software, Inc. | |
7 | * | |
8 | * ======================================================================== | |
9 | * | |
10 | * Permission to use, copy, modify, distribute, and sell this software and | |
11 | * its documentation for any purpose is hereby granted without fee, | |
12 | * provided that the above copyright notice appear in all copies and that | |
13 | * both that copyright notice and this permission notice appear in | |
14 | * supporting documentation, and that the name of the authors not be used | |
15 | * in advertising or publicity pertaining to distribution of the software | |
16 | * without specific, written prior permission. The authors makes no | |
17 | * representations about the suitability of this software for any purpose. | |
18 | * It is provided "as is" without express or implied warranty. | |
19 | * | |
20 | * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |
21 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |
22 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |
23 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |
24 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | |
25 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
26 | * PERFORMANCE OF THIS SOFTWARE. | |
27 | * | |
28 | * ======================================================================== | |
29 | * | |
30 | * Language: ANSI C | |
31 | * Environment: Any | |
32 | * Developer: Kendall Bennett | |
33 | * | |
34 | * Description: Module implementing the BIOS specific functions. | |
35 | * | |
36 | ****************************************************************************/ | |
37 | ||
38 | #include "biosemui.h" | |
39 | ||
40 | /*----------------------------- Implementation ----------------------------*/ | |
41 | ||
42 | /**************************************************************************** | |
43 | PARAMETERS: | |
44 | intno - Interrupt number being serviced | |
45 | ||
46 | REMARKS: | |
47 | Handler for undefined interrupts. | |
48 | ****************************************************************************/ | |
49 | static void X86API undefined_intr( | |
50 | int intno) | |
51 | { | |
52 | if (BE_rdw(intno * 4 + 2) == BIOS_SEG) | |
8bde7f77 | 53 | printk("biosEmu: undefined interrupt %xh called!\n",intno); |
c7de829c | 54 | else |
8bde7f77 | 55 | X86EMU_prepareForInt(intno); |
c7de829c WD |
56 | } |
57 | ||
58 | /**************************************************************************** | |
59 | PARAMETERS: | |
60 | intno - Interrupt number being serviced | |
61 | ||
62 | REMARKS: | |
63 | This function handles the default system BIOS Int 10h (the default is stored | |
64 | in the Int 42h vector by the system BIOS at bootup). We only need to handle | |
65 | a small number of special functions used by the BIOS during POST time. | |
66 | ****************************************************************************/ | |
67 | static void X86API int42( | |
68 | int intno) | |
69 | { | |
70 | if (M.x86.R_AH == 0x12 && M.x86.R_BL == 0x32) { | |
8bde7f77 WD |
71 | if (M.x86.R_AL == 0) { |
72 | /* Enable CPU accesses to video memory */ | |
73 | PM_outpb(0x3c2, PM_inpb(0x3cc) | (u8)0x02); | |
74 | return; | |
75 | } | |
76 | else if (M.x86.R_AL == 1) { | |
77 | /* Disable CPU accesses to video memory */ | |
78 | PM_outpb(0x3c2, PM_inpb(0x3cc) & (u8)~0x02); | |
79 | return; | |
80 | } | |
c7de829c | 81 | #ifdef DEBUG |
8bde7f77 WD |
82 | else { |
83 | printk("biosEmu/bios.int42: unknown function AH=0x12, BL=0x32, AL=%#02x\n",M.x86.R_AL); | |
84 | } | |
c7de829c | 85 | #endif |
8bde7f77 | 86 | } |
c7de829c WD |
87 | #ifdef DEBUG |
88 | else { | |
8bde7f77 WD |
89 | printk("biosEmu/bios.int42: unknown function AH=%#02x, AL=%#02x, BL=%#02x\n",M.x86.R_AH, M.x86.R_AL, M.x86.R_BL); |
90 | } | |
c7de829c WD |
91 | #endif |
92 | } | |
93 | ||
94 | /**************************************************************************** | |
95 | PARAMETERS: | |
96 | intno - Interrupt number being serviced | |
97 | ||
98 | REMARKS: | |
99 | This function handles the default system BIOS Int 10h. If the POST code | |
100 | has not yet re-vectored the Int 10h BIOS interrupt vector, we handle this | |
101 | by simply calling the int42 interrupt handler above. Very early in the | |
102 | BIOS POST process, the vector gets replaced and we simply let the real | |
103 | mode interrupt handler process the interrupt. | |
104 | ****************************************************************************/ | |
105 | static void X86API int10( | |
106 | int intno) | |
107 | { | |
108 | if (BE_rdw(intno * 4 + 2) == BIOS_SEG) | |
8bde7f77 | 109 | int42(intno); |
c7de829c | 110 | else |
8bde7f77 | 111 | X86EMU_prepareForInt(intno); |
c7de829c WD |
112 | } |
113 | ||
114 | /* Result codes returned by the PCI BIOS */ | |
115 | ||
116 | #define SUCCESSFUL 0x00 | |
117 | #define FUNC_NOT_SUPPORT 0x81 | |
118 | #define BAD_VENDOR_ID 0x83 | |
119 | #define DEVICE_NOT_FOUND 0x86 | |
120 | #define BAD_REGISTER_NUMBER 0x87 | |
121 | #define SET_FAILED 0x88 | |
122 | #define BUFFER_TOO_SMALL 0x89 | |
123 | ||
124 | /**************************************************************************** | |
125 | PARAMETERS: | |
126 | intno - Interrupt number being serviced | |
127 | ||
128 | REMARKS: | |
129 | This function handles the default Int 1Ah interrupt handler for the real | |
130 | mode code, which provides support for the PCI BIOS functions. Since we only | |
131 | want to allow the real mode BIOS code *only* see the PCI config space for | |
132 | its own device, we only return information for the specific PCI config | |
133 | space that we have passed in to the init function. This solves problems | |
134 | when using the BIOS to warm boot a secondary adapter when there is an | |
135 | identical adapter before it on the bus (some BIOS'es get confused in this | |
136 | case). | |
137 | ****************************************************************************/ | |
138 | static void X86API int1A( | |
139 | unused) | |
140 | { | |
141 | u16 pciSlot; | |
142 | ||
143 | /* Fail if no PCI device information has been registered */ | |
144 | if (!_BE_env.vgaInfo.pciInfo) | |
8bde7f77 | 145 | return; |
c7de829c WD |
146 | pciSlot = (u16)(_BE_env.vgaInfo.pciInfo->slot.i >> 8); |
147 | switch (M.x86.R_AX) { | |
8bde7f77 WD |
148 | case 0xB101: /* PCI bios present? */ |
149 | M.x86.R_AL = 0x00; /* no config space/special cycle generation support */ | |
150 | M.x86.R_EDX = 0x20494350; /* " ICP" */ | |
151 | M.x86.R_BX = 0x0210; /* Version 2.10 */ | |
152 | M.x86.R_CL = 0; /* Max bus number in system */ | |
153 | CLEAR_FLAG(F_CF); | |
154 | break; | |
155 | case 0xB102: /* Find PCI device */ | |
156 | M.x86.R_AH = DEVICE_NOT_FOUND; | |
157 | if (M.x86.R_DX == _BE_env.vgaInfo.pciInfo->VendorID && | |
158 | M.x86.R_CX == _BE_env.vgaInfo.pciInfo->DeviceID && | |
159 | M.x86.R_SI == 0) { | |
160 | M.x86.R_AH = SUCCESSFUL; | |
161 | M.x86.R_BX = pciSlot; | |
162 | } | |
163 | CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); | |
164 | break; | |
165 | case 0xB103: /* Find PCI class code */ | |
166 | M.x86.R_AH = DEVICE_NOT_FOUND; | |
167 | if (M.x86.R_CL == _BE_env.vgaInfo.pciInfo->Interface && | |
168 | M.x86.R_CH == _BE_env.vgaInfo.pciInfo->SubClass && | |
169 | (u8)(M.x86.R_ECX >> 16) == _BE_env.vgaInfo.pciInfo->BaseClass) { | |
170 | M.x86.R_AH = SUCCESSFUL; | |
171 | M.x86.R_BX = pciSlot; | |
172 | } | |
173 | CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); | |
174 | break; | |
175 | case 0xB108: /* Read configuration byte */ | |
176 | M.x86.R_AH = BAD_REGISTER_NUMBER; | |
177 | if (M.x86.R_BX == pciSlot) { | |
178 | M.x86.R_AH = SUCCESSFUL; | |
179 | M.x86.R_CL = (u8)PCI_accessReg(M.x86.R_DI,0,PCI_READ_BYTE,_BE_env.vgaInfo.pciInfo); | |
180 | } | |
181 | CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); | |
182 | break; | |
183 | case 0xB109: /* Read configuration word */ | |
184 | M.x86.R_AH = BAD_REGISTER_NUMBER; | |
185 | if (M.x86.R_BX == pciSlot) { | |
186 | M.x86.R_AH = SUCCESSFUL; | |
187 | M.x86.R_CX = (u16)PCI_accessReg(M.x86.R_DI,0,PCI_READ_WORD,_BE_env.vgaInfo.pciInfo); | |
188 | } | |
189 | CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); | |
190 | break; | |
191 | case 0xB10A: /* Read configuration dword */ | |
192 | M.x86.R_AH = BAD_REGISTER_NUMBER; | |
193 | if (M.x86.R_BX == pciSlot) { | |
194 | M.x86.R_AH = SUCCESSFUL; | |
195 | M.x86.R_ECX = (u32)PCI_accessReg(M.x86.R_DI,0,PCI_READ_DWORD,_BE_env.vgaInfo.pciInfo); | |
196 | } | |
197 | CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); | |
198 | break; | |
199 | case 0xB10B: /* Write configuration byte */ | |
200 | M.x86.R_AH = BAD_REGISTER_NUMBER; | |
201 | if (M.x86.R_BX == pciSlot) { | |
202 | M.x86.R_AH = SUCCESSFUL; | |
203 | PCI_accessReg(M.x86.R_DI,M.x86.R_CL,PCI_WRITE_BYTE,_BE_env.vgaInfo.pciInfo); | |
204 | } | |
205 | CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); | |
206 | break; | |
207 | case 0xB10C: /* Write configuration word */ | |
208 | M.x86.R_AH = BAD_REGISTER_NUMBER; | |
209 | if (M.x86.R_BX == pciSlot) { | |
210 | M.x86.R_AH = SUCCESSFUL; | |
211 | PCI_accessReg(M.x86.R_DI,M.x86.R_CX,PCI_WRITE_WORD,_BE_env.vgaInfo.pciInfo); | |
212 | } | |
213 | CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); | |
214 | break; | |
215 | case 0xB10D: /* Write configuration dword */ | |
216 | M.x86.R_AH = BAD_REGISTER_NUMBER; | |
217 | if (M.x86.R_BX == pciSlot) { | |
218 | M.x86.R_AH = SUCCESSFUL; | |
219 | PCI_accessReg(M.x86.R_DI,M.x86.R_ECX,PCI_WRITE_DWORD,_BE_env.vgaInfo.pciInfo); | |
220 | } | |
221 | CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF); | |
222 | break; | |
223 | default: | |
224 | printk("biosEmu/bios.int1a: unknown function AX=%#04x\n", M.x86.R_AX); | |
225 | } | |
c7de829c WD |
226 | } |
227 | ||
228 | /**************************************************************************** | |
229 | REMARKS: | |
230 | This function initialises the BIOS emulation functions for the specific | |
231 | PCI display device. We insulate the real mode BIOS from any other devices | |
232 | on the bus, so that it will work correctly thinking that it is the only | |
233 | device present on the bus (ie: avoiding any adapters present in from of | |
234 | the device we are trying to control). | |
235 | ****************************************************************************/ | |
236 | void _BE_bios_init( | |
237 | u32 *intrTab) | |
238 | { | |
239 | int i; | |
240 | X86EMU_intrFuncs bios_intr_tab[256]; | |
241 | ||
242 | for (i = 0; i < 256; ++i) { | |
8bde7f77 WD |
243 | intrTab[i] = BIOS_SEG << 16; |
244 | bios_intr_tab[i] = undefined_intr; | |
245 | } | |
c7de829c WD |
246 | bios_intr_tab[0x10] = int10; |
247 | bios_intr_tab[0x1A] = int1A; | |
248 | bios_intr_tab[0x42] = int42; | |
249 | X86EMU_setupIntrFuncs(bios_intr_tab); | |
250 | } |