2 #include <console/console.h>
3 #include <device/device.h>
4 #include <device/pci.h>
5 #include <device/pci_ids.h>
6 #include <device/pci_ops.h>
8 #include <x86emu/x86emu.h>
10 #define MEM_WB(where, what) wrb(where, what)
11 #define MEM_WW(where, what) wrw(where, what)
12 #define MEM_WL(where, what) wrl(where, what)
14 #define MEM_RB(where) rdb(where)
15 #define MEM_RW(where) rdw(where)
16 #define MEM_RL(where) rdl(where)
20 void x_outb(u16 port, u8 val);
21 void x_outw(u16 port, u16 val);
23 void x_outl(u16 port, u32 val);
25 /* general software interrupt handler */
26 u32 getIntVect(int num)
28 return MEM_RW(num << 2) + (MEM_RW((num << 2) + 2) << 4);
31 /* FixME: There is already a push_word() in the emulator */
35 MEM_WW(((u32) X86_SS << 4) + X86_SP, val);
38 int run_bios_int(int num)
46 X86_CS = MEM_RW((num << 2) + 2);
47 X86_IP = MEM_RW(num << 2);
59 // printk_debug("inb(0x%04x) = 0x%02x\n", port, val);
70 //printk_debug("inw(0x%04x) = 0x%04x\n", port, val);
80 //printk_debug("inl(0x%04x) = 0x%08x\n", port, val);
84 void x_outb(u16 port, u8 val)
87 // printk_debug("outb(0x%02x, 0x%04x)\n", val, port);
91 void x_outw(u16 port, u16 val)
93 //printk_debug("outw(0x%04x, 0x%04x)\n", val, port);
97 void x_outl(u16 port, u32 val)
99 //printk_debug("outl(0x%08x, 0x%04x)\n", val, port);
103 X86EMU_pioFuncs myfuncs = {
105 x_outb, x_outw, x_outl
110 /* Interrupt multiplexer */
116 // printk_debug("int%x vector at %x\n", num, getIntVect(num));
123 if (getIntVect(num) == 0x0000) {
124 printk_debug("un-inited int vector\n");
127 if (getIntVect(num) == 0xFF065) {
128 //ret = int42_handler();
134 //ret = int15_handler();
138 //ret = int16_handler();
142 ret = pcibios_handler();
146 //ret = intE6_handler();
154 ret = run_bios_int(num);
158 #define SYS_BIOS 0xf0000
160 * here we are really paranoid about faking a "real"
161 * BIOS. Most of this information was pulled from
164 void setup_int_vect(void)
168 /* let the int vects point to the SYS_BIOS seg */
169 for (i = 0; i < 0x80; i++) {
171 MEM_WW((i << 2) + 2, SYS_BIOS >> 4);
176 /* font tables default location (int 1F) */
177 MEM_WW(0x1f << 2, 0xfa6e);
178 /* int 11 default location (Get Equipment Configuration) */
179 MEM_WW(0x11 << 2, 0xf84d);
180 /* int 12 default location (Get Conventional Memory Size) */
181 MEM_WW(0x12 << 2, 0xf841);
182 /* int 15 default location (I/O System Extensions) */
183 MEM_WW(0x15 << 2, 0xf859);
184 /* int 1A default location (RTC, PCI and others) */
185 MEM_WW(0x1a << 2, 0xff6e);
186 /* int 05 default location (Bound Exceeded) */
187 MEM_WW(0x05 << 2, 0xff54);
188 /* int 08 default location (Double Fault) */
189 MEM_WW(0x08 << 2, 0xfea5);
190 /* int 13 default location (Disk) */
191 MEM_WW(0x13 << 2, 0xec59);
192 /* int 0E default location (Page Fault) */
193 MEM_WW(0x0e << 2, 0xef57);
194 /* int 17 default location (Parallel Port) */
195 MEM_WW(0x17 << 2, 0xefd2);
196 /* fdd table default location (int 1e) */
197 MEM_WW(0x1e << 2, 0xefc7);
199 /* Set Equipment flag to VGA */
200 i = MEM_RB(0x0410) & 0xCF;
202 /* XXX Perhaps setup more of the BDA here. See also int42(0x00). */
205 int setup_system_bios(void *base_addr)
207 char *base = (char *) base_addr;
210 * we trap the "industry standard entry points" to the BIOS
211 * and all other locations by filling them with "hlt"
212 * TODO: implement hlt-handler for these
214 memset(base, 0xf4, 0x10000);
217 //strcpy(base + 0x0FFF5, "06/11/99");
218 /* set up eisa ident string */
219 //strcpy(base + 0x0FFD9, "PCI_ISA");
220 /* write system model id for IBM-AT */
221 //*((unsigned char *) (base + 0x0FFFE)) = 0xfc;
226 void reset_int_vect(void)
229 * This table is normally located at 0xF000:0xF0A4. However, int 0x42,
230 * function 0 (Mode Set) expects it (or a copy) somewhere in the bottom
231 * 64kB. Note that because this data doesn't survive POST, int 0x42 should
232 * only be used during EGA/VGA BIOS initialisation.
234 static const u8 VideoParms[] = {
235 /* Timing for modes 0x00 & 0x01 */
236 0x38, 0x28, 0x2d, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
237 0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
238 /* Timing for modes 0x02 & 0x03 */
239 0x71, 0x50, 0x5a, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
240 0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
241 /* Timing for modes 0x04, 0x05 & 0x06 */
242 0x38, 0x28, 0x2d, 0x0a, 0x7f, 0x06, 0x64, 0x70,
243 0x02, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
244 /* Timing for mode 0x07 */
245 0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19,
246 0x02, 0x0d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
247 /* Display page lengths in little endian order */
248 0x00, 0x08, /* Modes 0x00 and 0x01 */
249 0x00, 0x10, /* Modes 0x02 and 0x03 */
250 0x00, 0x40, /* Modes 0x04 and 0x05 */
251 0x00, 0x40, /* Modes 0x06 and 0x07 */
252 /* Number of columns for each mode */
253 40, 40, 80, 80, 40, 40, 80, 80,
254 /* CGA Mode register value for each mode */
255 0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29,
257 0x00, 0x00, 0x00, 0x00
261 for (i = 0; i < sizeof(VideoParms); i++)
262 MEM_WB(i + (0x1000 - sizeof(VideoParms)), VideoParms[i]);
263 MEM_WW(0x1d << 2, 0x1000 - sizeof(VideoParms));
264 MEM_WW((0x1d << 2) + 2, 0);
266 printk_debug("SETUP INT\n");
267 MEM_WW(0x10 << 2, 0xf065);
268 MEM_WW((0x10 << 2) + 2, SYS_BIOS >> 4);
269 MEM_WW(0x42 << 2, 0xf065);
270 MEM_WW((0x42 << 2) + 2, SYS_BIOS >> 4);
271 MEM_WW(0x6D << 2, 0xf065);
272 MEM_WW((0x6D << 2) + 2, SYS_BIOS >> 4);
275 void run_bios(struct device * dev, unsigned long addr)
279 unsigned short initialcs = (addr & 0xF0000) >> 4;
280 unsigned short initialip = (addr + 3) & 0xFFFF;
281 unsigned short devfn = dev->bus->secondary << 8 | dev->path.u.pci.devfn;
282 X86EMU_intrFuncs intFuncs[256];
284 X86EMU_setMemBase(0, 0x100000);
285 X86EMU_setupPioFuncs(&myfuncs);
286 for (i = 0; i < 256; i++)
287 intFuncs[i] = do_int;
288 X86EMU_setupIntrFuncs(intFuncs);
291 char *date = "01/01/99";
292 for (i = 0; date[i]; i++)
293 wrb(0xffff5 + i, date[i]);
299 /* FixME: move PIT init to its own file */
307 X86_AX = devfn ? devfn : 0xff;
312 /* Initialize stack and data segment */
318 /* We need a sane way to return from bios
319 * execution. A hlt instruction and a pointer
320 * to it, both kept on the stack, will do.
322 pushw(0xf4f4); /* hlt; hlt */
326 // X86EMU_trace_on();