]>
git.ipfire.org Git - people/dweismueller/ipfire-2.x.git/blob - src/hwinfo/src/int10/i10_v86.c
8fcdef160cacff676246ea60ba4c4681b7c98256
2 * Copyright 1999 Egbert Eich
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the authors not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. The authors makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
14 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
25 #include <asm/unistd.h>
31 #include "vm86_struct.h"
35 #include "AsmMacros.h"
37 extern int emu_vm86(struct vm86_struct
*vm
, unsigned debug
);
39 #define INT2PTR(a) ((a) + (unsigned char *) 0)
41 void log_err(char *format
, ...) __attribute__ ((format (printf
, 1, 2)));
43 struct vm86_struct vm86s
;
45 static int vm86_GP_fault(void);
46 static int vm86_do_int(int num
);
48 static int vm86_rep(struct vm86_struct
*ptr
);
50 void log_registers(void);
52 #define CPU_REG(x) (vm86s.regs.x)
53 #define CPU_REG_LW(reg) (*((CARD16 *)&CPU_REG(reg)))
54 #define CPU_REG_HW(reg) (*((CARD16 *)&CPU_REG(reg) + 1))
55 #define CPU_REG_LB(reg) (*(CARD8 *)&CPU_REG(e##reg))
56 #define SEG_ADR(type, seg, reg) type((CPU_REG_LW(seg) << 4) + CPU_REG_LW(e##reg) + (unsigned char *) 0)
64 P
.inb
= (CARD8(*)(CARD16
))inb
;
65 P
.inw
= (CARD16(*)(CARD16
))inw
;
66 P
.inl
= (CARD32(*)(CARD16
))inl
;
67 P
.outb
= (void(*)(CARD16
,CARD8
))outb
;
68 P
.outw
= (void(*)(CARD16
,CARD16
))outw
;
69 P
.outl
= (void(*)(CARD16
,CARD32
))outl
;
74 setup_vm86(unsigned long bios_start
, i86biosRegsPtr regs
)
79 vm86s
.flags
= VM86_SCREEN_BITMAP
;
81 vm86s
.screen_bitmap
= 0;
82 vm86s
.cpu_type
= CPU_586
;
83 memset(&vm86s
.int_revectored
, 0xff,sizeof(vm86s
.int_revectored
)) ;
84 memset(&vm86s
.int21_revectored
, 0xff,sizeof(vm86s
.int21_revectored
)) ;
86 eip
= bios_start
& 0xFFFF;
87 cs
= (bios_start
& 0xFF0000) >> 4;
89 CPU_REG(eax
) = regs
->ax
;
90 CPU_REG(ebx
) = regs
->bx
;
91 CPU_REG(ecx
) = regs
->cx
;
92 CPU_REG(edx
) = regs
->dx
;
94 CPU_REG(edi
) = regs
->di
;
99 CPU_REG(ss
) = 0x30; /* This is the standard pc bios stack */
100 CPU_REG(es
) = regs
->es
;
101 CPU_REG(ds
) = 0x40; /* standard pc ds */
104 CPU_REG(eflags
) |= (VIF_MASK
| VIP_MASK
);
108 collect_bios_regs(i86biosRegsPtr regs
)
110 regs
->ax
= CPU_REG(eax
);
111 regs
->bx
= CPU_REG(ebx
);
112 regs
->cx
= CPU_REG(ecx
);
113 regs
->dx
= CPU_REG(edx
);
114 regs
->es
= CPU_REG(es
);
115 regs
->ds
= CPU_REG(ds
);
116 regs
->di
= CPU_REG(edi
);
117 regs
->si
= CPU_REG(esi
);
120 static int do_vm86(int cpuemu
)
130 retval
= emu_vm86(&vm86s
, cpuemu
& 2);
133 retval
= vm86_rep(&vm86s
);
136 retval
= emu_vm86(&vm86s
, cpuemu
& 2);
139 switch (VM86_TYPE(retval
)) {
141 if (!vm86_GP_fault())
145 log_err("vm86_sti :-((\n");
149 if (!vm86_do_int(VM86_ARG(retval
))) {
150 log_err("Unknown vm86_int: %X\n",VM86_ARG(retval
));
154 /* I'm not sure yet what to do if we can handle ints */
157 log_err("VBE: received a signal!\n");
161 log_err("unknown type(0x%x)=0x%x\n",
162 VM86_ARG(retval
),VM86_TYPE(retval
));
171 do_x86(unsigned long bios_start
, i86biosRegsPtr regs
, int cpuemu
)
173 setup_vm86(bios_start
, regs
);
174 while(do_vm86(cpuemu
)) {};
175 collect_bios_regs(regs
);
178 /* get the linear address */
179 #define LIN_PREF_SI ((pref_seg << 4) + CPU_REG_LW(esi))
181 #define LWECX (prefix66 ^ prefix67 ? CPU_REG(ecx) : CPU_REG_LW(ecx))
186 unsigned char *csp
, *lina
;
189 int done
,is_rep
,prefix66
,prefix67
;
192 csp
= lina
= SEG_ADR((unsigned char *), cs
, ip
);
194 printf("exception: \n");
199 prefix66
= prefix67
= 0;
202 /* eat up prefixes */
206 case 0x66: /* operand prefix */ prefix66
=1; break;
207 case 0x67: /* address prefix */ prefix67
=1; break;
208 case 0x2e: /* CS */ pref_seg
=CPU_REG(cs
); break;
209 case 0x3e: /* DS */ pref_seg
=CPU_REG(ds
); break;
210 case 0x26: /* ES */ pref_seg
=CPU_REG(es
); break;
211 case 0x36: /* SS */ pref_seg
=CPU_REG(ss
); break;
212 case 0x65: /* GS */ pref_seg
=CPU_REG(gs
); break;
213 case 0x64: /* FS */ pref_seg
=CPU_REG(fs
); break;
214 case 0xf2: /* repnz */
215 case 0xf3: /* rep */ is_rep
=1; break;
219 csp
--; /* oops one too many */
220 org_eip
= CPU_REG(eip
);
221 CPU_REG_LW(eip
) += (csp
- lina
);
225 case 0x6c: /* insb */
226 /* NOTE: ES can't be overwritten; prefixes 66,67 should use esi,edi,ecx
227 * but is anyone using extended regs in real mode? */
228 /* WARNING: no test for DI wrapping! */
229 CPU_REG_LW(edi
) += port_rep_inb(CPU_REG_LW(edx
),
230 SEG_ADR((CARD8
*),es
,di
),
231 CPU_REG_LW(eflags
)&DF
,
233 if (is_rep
) LWECX
= 0;
237 case 0x6d: /* (rep) insw / insd */
238 /* NOTE: ES can't be overwritten */
239 /* WARNING: no test for _DI wrapping! */
241 CPU_REG_LW(edi
) += port_rep_inl(CPU_REG_LW(edx
),
242 SEG_ADR((CARD32
*),es
,di
),
243 CPU_REG_LW(eflags
)&DF
,
247 CPU_REG_LW(edi
) += port_rep_inw(CPU_REG_LW(edx
),
248 SEG_ADR((CARD16
*),es
,di
),
249 CPU_REG_LW(eflags
)&DF
,
252 if (is_rep
) LWECX
= 0;
256 case 0x6e: /* (rep) outsb */
257 if (pref_seg
< 0) pref_seg
= CPU_REG_LW(ds
);
258 /* WARNING: no test for _SI wrapping! */
259 CPU_REG_LW(esi
) += port_rep_outb(CPU_REG_LW(edx
),(CARD8
*)INT2PTR(LIN_PREF_SI
),
260 CPU_REG_LW(eflags
)&DF
,
262 if (is_rep
) LWECX
= 0;
266 case 0x6f: /* (rep) outsw / outsd */
267 if (pref_seg
< 0) pref_seg
= CPU_REG_LW(ds
);
268 /* WARNING: no test for _SI wrapping! */
270 CPU_REG_LW(esi
) += port_rep_outl(CPU_REG_LW(edx
),
271 (CARD32
*)INT2PTR(LIN_PREF_SI
),
272 CPU_REG_LW(eflags
)&DF
,
276 CPU_REG_LW(esi
) += port_rep_outw(CPU_REG_LW(edx
),
277 (CARD16
*)INT2PTR(LIN_PREF_SI
),
278 CPU_REG_LW(eflags
)&DF
,
281 if (is_rep
) LWECX
= 0;
285 case 0xe5: /* inw xx, inl xx */
286 if (prefix66
) CPU_REG(eax
) = P
.inl((int) csp
[1]);
287 else CPU_REG_LW(eax
) = P
.inw((int) csp
[1]);
288 CPU_REG_LW(eip
) += 2;
290 case 0xe4: /* inb xx */
291 CPU_REG_LW(eax
) &= ~(CARD32
)0xff;
292 CPU_REG_LB(ax
) |= P
.inb((int) csp
[1]);
293 CPU_REG_LW(eip
) += 2;
295 case 0xed: /* inw dx, inl dx */
296 if (prefix66
) CPU_REG(eax
) = P
.inl(CPU_REG_LW(edx
));
297 else CPU_REG_LW(eax
) = P
.inw(CPU_REG_LW(edx
));
298 CPU_REG_LW(eip
) += 1;
300 case 0xec: /* inb dx */
301 CPU_REG_LW(eax
) &= ~(CARD32
)0xff;
302 CPU_REG_LB(ax
) |= P
.inb(CPU_REG_LW(edx
));
303 CPU_REG_LW(eip
) += 1;
306 case 0xe7: /* outw xx */
307 if (prefix66
) P
.outl((int)csp
[1], CPU_REG(eax
));
308 else P
.outw((int)csp
[1], CPU_REG_LW(eax
));
309 CPU_REG_LW(eip
) += 2;
311 case 0xe6: /* outb xx */
312 P
.outb((int) csp
[1], CPU_REG_LB(ax
));
313 CPU_REG_LW(eip
) += 2;
315 case 0xef: /* outw dx */
316 if (prefix66
) P
.outl(CPU_REG_LW(edx
), CPU_REG(eax
));
317 else P
.outw(CPU_REG_LW(edx
), CPU_REG_LW(eax
));
318 CPU_REG_LW(eip
) += 1;
320 case 0xee: /* outb dx */
321 P
.outb(CPU_REG_LW(edx
), CPU_REG_LB(ax
));
322 CPU_REG_LW(eip
) += 1;
327 printf("hlt at %p\n", lina
);
332 log_err("CPU 0x0f Trap at eip=0x%lx\n",CPU_REG(eip
));
336 case 0xf0: /* lock */
338 log_err("unknown reason for exception\n");
341 log_err("cannot continue\n");
343 } /* end of switch() */
353 /* try to run bios interrupt */
355 /* if not installed fall back */
356 #define COPY(x) regs.x = CPU_REG(x)
357 #define COPY_R(x) CPU_REG(x) = regs.x
376 if (!(val
= int_handler(num
,®s
)))
377 if (!(val
= run_bios_int(num
,®s
)))
405 vm86_rep(struct vm86_struct
*ptr
)
410 /* stay away from %ebx */
411 __asm__
__volatile__("push %%ebx\n\tmov %%ecx,%%ebx\n\tpush %%gs\n\tint $0x80\n\tpop %%gs\n\tpop %%ebx\n"
412 :"=a" (__res
):"a" ((int)113),
413 "c" ((struct vm86_struct
*)ptr
));
427 #define pushw(base, ptr, val) \
428 __asm__ __volatile__( \
430 "movb %h2,(%1,%0)\n\t" \
434 : "r" (base), "q" (val), "0" (ptr))
438 #define pushw(base, ptr, val) { \
439 ptr = ((ptr) - 1) & 0xffff; \
440 *((unsigned char *)(base) + (ptr)) = (val) >> 8; \
441 ptr = ((ptr) - 1) & 0xffff; \
442 *((unsigned char *)(base) + (ptr)) = (val); \
448 run_bios_int(int num
, struct regs86
*regs
)
455 static int firsttime
= 1;
457 /* check if bios vector is initialized */
458 if (((CARD16
*)0)[(num
<<1)+1] == 0x0000) { /* SYS_BIOS_SEG ?*/
469 ssp
= (CARD16
*)INT2PTR(CPU_REG(ss
)<<4);
470 sp
= (CARD32
) CPU_REG_LW(esp
);
472 eflags
= regs
->eflags
;
473 eflags
= ((eflags
& VIF_MASK
) != 0)
474 ? (eflags
| IF_MASK
) : (eflags
& ~(CARD32
) IF_MASK
);
475 pushw(ssp
, sp
, eflags
);
476 pushw(ssp
, sp
, regs
->cs
);
477 pushw(ssp
, sp
, (CARD16
)regs
->eip
);
479 regs
->cs
= ((CARD16
*) 0)[(num
<< 1) + 1];
480 regs
->eip
= (regs
->eip
& 0xFFFF0000) | ((CARD16
*) 0)[num
<< 1];
484 regs
->eflags
= regs
->eflags
485 & ~(VIF_MASK
| TF_MASK
| IF_MASK
| NT_MASK
);
492 return ((CARD32
*)0)[num
];
498 return (CPU_REG(cs
) << 4) + CPU_REG(eip
);
504 " eax %08x, ebx %08x, ecx %08x, edx %08x\n"
505 " esi %08x, edi %08x, ebp %08x, esp %08x\n"
506 " ds %04x, es %04x, fs %04x, gs %04x, ss %04x\n"
507 " cs:eip %04x:%08x\n",
508 (unsigned) CPU_REG(eax
), (unsigned) CPU_REG(ebx
), (unsigned) CPU_REG(ecx
), (unsigned) CPU_REG(edx
),
509 (unsigned) CPU_REG(esi
), (unsigned) CPU_REG(edi
), (unsigned) CPU_REG(ebp
), (unsigned) CPU_REG(esp
),
510 (unsigned) CPU_REG(ds
), (unsigned) CPU_REG(es
),
511 (unsigned) CPU_REG(fs
), (unsigned) CPU_REG(gs
), (unsigned) CPU_REG(ss
),
512 (unsigned) CPU_REG(cs
), (unsigned) CPU_REG(eip
)