File indexing completed on 2025-05-11 08:23:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <sys/types.h>
0027 #include "pci.h"
0028 #include <libcpu/byteorder.h>
0029 #ifdef __BOOT__
0030 #include "bootldr.h"
0031 #include <limits.h>
0032 #include <rtems/bspIo.h>
0033 #endif
0034
0035
0036
0037
0038
0039 typedef union _reg_type1 {
0040 unsigned e;
0041 unsigned short x;
0042 struct {
0043 unsigned char l, h;
0044 } lh;
0045 } reg_type1;
0046
0047 typedef union _reg_type2 {
0048 uint32_t e;
0049 uint16_t x;
0050 } reg_type2;
0051
0052 typedef struct _x86 {
0053 reg_type1
0054 _eax, _ecx, _edx, _ebx;
0055 reg_type2
0056 _esp, _ebp, _esi, _edi;
0057 unsigned
0058 es, cs, ss, ds, fs, gs, eip, eflags;
0059 unsigned char
0060 *esbase, *csbase, *ssbase, *dsbase, *fsbase, *gsbase;
0061 volatile unsigned char *iobase;
0062 unsigned char *ioperm;
0063 unsigned
0064 reason, nexteip, parm1, parm2, opcode, base;
0065 unsigned *optable, opreg;
0066 unsigned char* vbase;
0067 unsigned instructions;
0068 #ifdef __BOOT__
0069 u_char * ram;
0070 u_char * rom;
0071 struct pci_dev * dev;
0072 #else
0073 unsigned filler[14];
0074 unsigned eipstats[32768][2];
0075 #endif
0076 } x86;
0077
0078 x86 v86_private __attribute__((aligned(32)));
0079
0080
0081 extern
0082 void em86_enter(x86 * p);
0083
0084 #define EAX (p->_eax.e)
0085 #define ECX (p->_ecx.e)
0086 #define EDX (p->_edx.e)
0087 #define EBX (p->_ebx.e)
0088 #define ESP (p->_esp.e)
0089 #define EBP (p->_ebp.e)
0090 #define ESI (p->_esi.e)
0091 #define EDI (p->_edi.e)
0092 #define AX (p->_eax.x)
0093 #define CX (p->_ecx.x)
0094 #define DX (p->_edx.x)
0095 #define BX (p->_ebx.x)
0096 #define SP (p->_esp.x)
0097 #define BP (p->_ebp.x)
0098 #define SI (p->_esi.x)
0099 #define DI (p->_edi.x)
0100 #define AL (p->_eax.lh.l)
0101 #define CL (p->_ecx.lh.l)
0102 #define DL (p->_edx.lh.l)
0103 #define BL (p->_ebx.lh.l)
0104 #define AH (p->_eax.lh.h)
0105 #define CH (p->_ecx.lh.h)
0106 #define DH (p->_edx.lh.h)
0107 #define BH (p->_ebx.lh.h)
0108
0109
0110 #ifdef __BOOT__
0111 #define printf printk
0112 #endif
0113 #ifdef DEBUG
0114 static void dump86(x86 * p){
0115 unsigned char *s = p->csbase + p->eip;
0116 printf("cs:eip=%04x:%08x, eax=%08x, ecx=%08x, edx=%08x, ebx=%08x\n",
0117 p->cs, p->eip, ld_le32(&EAX),
0118 ld_le32(&ECX), ld_le32(&EDX), ld_le32(&EBX));
0119 printf("ss:esp=%04x:%08x, ebp=%08x, esi=%08x, edi=%08x, efl=%08x\n",
0120 p->ss, ld_le32(&ESP), ld_le32(&EBP),
0121 ld_le32(&ESI), ld_le32(&EDI), p->eflags);
0122 printf("nip=%08x, ds=%04x, es=%04x, fs=%04x, gs=%04x, total=%d\n",
0123 p->nexteip, p->ds, p->es, p->fs, p->gs, p->instructions);
0124 printf("code: %02x %02x %02x %02x %02x %02x "
0125 "%02x %02x %02x %02x %02x %02x\n",
0126 s[0], s[1], s[2], s[3], s[4], s[5],
0127 s[6], s[7], s[8], s[9], s[10], s[11]);
0128 #ifndef __BOOT__
0129 printf("op1=%08x, op2=%08x, result=%08x, flags=%08x\n",
0130 p->filler[11], p->filler[12], p->filler[13], p->filler[14]);
0131 #endif
0132 }
0133 #else
0134 #define dump86(x)
0135 #endif
0136
0137 static int bios86pci(x86 * p) {
0138 unsigned reg=ld_le16(&DI);
0139 reg_type2 tmp;
0140
0141 if (AL>=8 && AL<=13 && reg>0xff) {
0142 AH = PCIBIOS_BAD_REGISTER_NUMBER;
0143 } else {
0144 switch(AL) {
0145 case 2:
0146
0147
0148
0149
0150
0151 if (SI) {
0152 AH=PCIBIOS_DEVICE_NOT_FOUND;
0153 } else {
0154 BH = p->dev->bus->number;
0155 BL = p->dev->devfn;
0156 AH = 0;
0157 }
0158 break;
0159
0160
0161
0162 case 8:
0163 AH=pcibios_read_config_byte(BH, BL, reg, &CL);
0164 break;
0165 case 9:
0166 AH=pcibios_read_config_word(BH, BL, reg, &tmp.x);
0167 CX=ld_le16(&tmp.x);
0168 break;
0169 case 10:
0170 AH=pcibios_read_config_dword(BH, BL, reg, &tmp.e);
0171 ECX=ld_le32(&tmp.e);
0172 break;
0173 case 11:
0174 AH=pcibios_write_config_byte(BH, BL, reg, CL);
0175 break;
0176 case 12:
0177 AH=pcibios_write_config_word(BH, BL, reg, ld_le16(&CX));
0178 break;
0179 case 13:
0180 AH=pcibios_write_config_dword(
0181 BH, BL, reg, ld_le32((uint32_t *)&ECX));
0182 break;
0183 default:
0184 printf("Unimplemented or illegal PCI service call #%d!\n",
0185 AL);
0186 return 1;
0187 }
0188 }
0189 p->eip = p->nexteip;
0190
0191 if (AH) p->eflags |= 1; else p->eflags &=~1;
0192 return 0;
0193 }
0194
0195 static void push2(x86 *p, unsigned value) {
0196 unsigned char * sbase= p->ssbase;
0197 unsigned newsp = (ld_le16(&SP)-2)&0xffff;
0198 st_le16(&SP,newsp);
0199 st_le16((unsigned short *)(sbase+newsp), value);
0200 }
0201
0202 static unsigned pop2(x86 *p) {
0203 unsigned char * sbase=p->ssbase;
0204 unsigned oldsp = ld_le16(&SP);
0205 st_le16(&SP,oldsp+2);
0206 return ld_le16((unsigned short *)(sbase+oldsp));
0207 }
0208
0209 static int int10h(x86 * p) {
0210 unsigned vector;
0211 vector=ld_le32((uint32_t *)p->vbase+0x10);
0212 if (((vector&0xffff0000)>>16)==0xc000) {
0213 push2(p, p->eflags);
0214 push2(p, p->cs);
0215 push2(p, p->nexteip);
0216 p->cs=vector>>16;
0217 p->csbase=p->vbase + (p->cs<<4);
0218 p->eip=vector&0xffff;
0219 #if 1
0220 p->eflags&=0xfcff;
0221 #else
0222 p->eflags = (p->eflags&0xfcff)|0x100;
0223 #endif
0224
0225 return(0);
0226 } else {
0227 switch(AH) {
0228 case 0x12:
0229 switch(BL){
0230 case 0x32:
0231 p->eip=p->nexteip;
0232 return(0);
0233 break;
0234 default:
0235 break;
0236 }
0237 default:
0238 break;
0239 }
0240 printf("unhandled soft interrupt 0x10: vector=%x\n", vector);
0241 return(1);
0242 }
0243 }
0244
0245 static int process_softint(x86 * p) {
0246 #if 0
0247 if (p->parm1!=0x10 || AH!=0x0e) {
0248 printf("Soft interrupt\n");
0249 dump86(p);
0250 }
0251 #endif
0252 switch(p->parm1) {
0253 case 0x10:
0254 return int10h(p);
0255 case 0x1a:
0256 if(AH==0xb1) return bios86pci(p);
0257 break;
0258 default:
0259 break;
0260 }
0261 dump86(p);
0262 printf("Unhandled soft interrupt number 0x%04x, AX=0x%04x\n",
0263 p->parm1, ld_le16(&AX));
0264 return(1);
0265 }
0266
0267
0268
0269
0270 #define code_zerdiv 0
0271 #define code_trap 1
0272 #define code_int3 3
0273 #define code_into 4
0274 #define code_bound 5
0275 #define code_ud 6
0276 #define code_dna 7
0277
0278 #define code_iretw 256
0279 #define code_iretl 257
0280 #define code_lcallw 258
0281 #define code_lcalll 259
0282 #define code_ljmpw 260
0283 #define code_ljmpl 261
0284 #define code_lretw 262
0285 #define code_lretl 263
0286 #define code_softint 264
0287 #define code_lock 265
0288
0289
0290
0291
0292
0293
0294
0295 #define code_inb 1024+1
0296 #define code_inw 1024+2
0297 #define code_inl 1024+4
0298 #define code_outb 1024+512+1
0299 #define code_outw 1024+512+2
0300 #define code_outl 1024+512+4
0301 #define code_insb_a16 1024+256+1
0302 #define code_insw_a16 1024+256+2
0303 #define code_insl_a16 1024+256+4
0304 #define code_outsb_a16 1024+512+256+1
0305 #define code_outsw_a16 1024+512+256+2
0306 #define code_outsl_a16 1024+512+256+4
0307 #define code_insb_a32 1024+256+128+1
0308 #define code_insw_a32 1024+256+128+2
0309 #define code_insl_a32 1024+256+128+4
0310 #define code_outsb_a32 1024+512+256+128+1
0311 #define code_outsw_a32 1024+512+256+128+2
0312 #define code_outsl_a32 1024+512+256+128+4
0313
0314 int em86_trap(x86 *p) {
0315 #ifndef __BOOT__
0316 int i;
0317 unsigned char command[80];
0318 unsigned char *verb, *t;
0319 unsigned short *fp;
0320 static unsigned char def=0;
0321 static unsigned char * bptaddr=NULL;
0322 static unsigned char bptopc;
0323 unsigned char cmd;
0324 unsigned tmp;
0325 #endif
0326 switch(p->reason) {
0327 case code_int3:
0328 #ifndef __BOOT__
0329 if(p->csbase+p->eip == bptaddr) {
0330 *bptaddr=bptopc;
0331 bptaddr=NULL;
0332 }
0333 else printf("Unexpected ");
0334 #endif
0335 printf("Breakpoint Interrupt !\n");
0336
0337 #ifdef __BOOT__
0338 return 0;
0339 #else
0340 case code_trap:
0341 dump86(p);
0342 for(;;) {
0343 printf("b(reakpoint, g(o, q(uit, s(tack, t(race ? [%c] ", def);
0344 fgets(command,sizeof(command),stdin);
0345 verb = strtok(command," \n");
0346 if(verb) cmd=*verb; else cmd=def;
0347 def=0;
0348 switch(cmd) {
0349 case 'b':
0350 case 'B':
0351 if(bptaddr) *bptaddr=bptopc;
0352 t=strtok(0," \n");
0353 i=sscanf(t,"%x",&tmp);
0354 if(i==1) {
0355 bptaddr=p->vbase + tmp;
0356 bptopc=*bptaddr;
0357 *bptaddr=0xcc;
0358 } else bptaddr=NULL;
0359 break;
0360 case 'q':
0361 case 'Q':
0362 return 1;
0363 break;
0364
0365 case 'g':
0366 case 'G':
0367 p->eflags &= ~0x100;
0368 return 0;
0369 break;
0370
0371 case 's':
0372 case 'S':
0373 fp = (unsigned short *)(p->ssbase+ld_le16(&SP));
0374 printf("Stack [%04x:%04x]: %04x %04x %04x %04x %04x %04x %04x %04x\n",
0375 p->ss, ld_le16(&SP),
0376 ld_le16(fp+0), ld_le16(fp+1), ld_le16(fp+2), ld_le16(fp+3),
0377 ld_le16(fp+4), ld_le16(fp+5), ld_le16(fp+6), ld_le16(fp+7));
0378 break;
0379 case 't':
0380 case 'T':
0381 p->eflags |= 0x10100;
0382 def='t';
0383 return 0;
0384 break;
0385
0386 }
0387 }
0388 #endif
0389 break;
0390 case code_ud:
0391 printf("Attempt to execute an unimplemented"
0392 "or undefined opcode!\n");
0393 dump86(p);
0394 return(1);
0395 break;
0396 case code_dna:
0397 printf("Attempt to execute a floating point instruction!\n");
0398 dump86(p);
0399 return(1);
0400 break;
0401 case code_softint:
0402 return process_softint(p);
0403 break;
0404 case code_iretw:
0405 p->eip=pop2(p);
0406 p->cs=pop2(p);
0407 p->csbase=p->vbase + (p->cs<<4);
0408 p->eflags= (p->eflags&0xfffe0000)|pop2(p);
0409
0410 return(0);
0411 break;
0412 #ifndef __BOOT__
0413 case code_inb:
0414 case code_inw:
0415 case code_inl:
0416 case code_insb_a16:
0417 case code_insw_a16:
0418 case code_insl_a16:
0419 case code_insb_a32:
0420 case code_insw_a32:
0421 case code_insl_a32:
0422 case code_outb:
0423 case code_outw:
0424 case code_outl:
0425 case code_outsb_a16:
0426 case code_outsw_a16:
0427 case code_outsl_a16:
0428 case code_outsb_a32:
0429 case code_outsw_a32:
0430 case code_outsl_a32:
0431
0432 for(i=p->parm1; i<p->parm1+(p->reason&7); i++) {
0433 p->ioperm[i/8] &= ~(1<<i%8);
0434 }
0435 printf("Access to ports %04x-%04x enabled.\n",
0436 p->parm1, p->parm1+(p->reason&7)-1);
0437 return(0);
0438 #endif
0439 case code_lretw:
0440
0441 if ( *(u_int *)(p->ssbase+ld_le16(&SP)) == UINT_MAX) return 1;
0442
0443 default:
0444 dump86(p);
0445 printf("em86_trap called with unhandled reason code !\n");
0446 return(1);
0447
0448 }
0449 }
0450
0451 void cleanup_v86_mess(void) {
0452 x86 *p = (x86 *) bd->v86_private;
0453
0454
0455 vfree(p->vbase);
0456 p->vbase = 0;
0457 pfree(p->ram);
0458 p->ram = 0;
0459 sfree(p->ioperm);
0460 p->ioperm=0;
0461 }
0462
0463 int init_v86(void) {
0464 x86 *p = (x86 *) bd->v86_private;
0465
0466
0467 if (p->vbase) return 0;
0468
0469
0470 memset(p, 0, sizeof(*p));
0471 p->ioperm = salloc(65536/8+1);
0472 p->ram = palloc(0xa0000);
0473 p->iobase = ptr_mem_map->io_base;
0474
0475 if (!p->ram || !p->ioperm) return 1;
0476
0477
0478 p->ioperm[65536/8] = 0xff;
0479
0480 p->vbase = valloc(0x110000);
0481 if (!p->vbase) return 1;
0482
0483
0484 vmap(p->vbase, (u_long)p->ram|PTE_RAM, 0xa0000);
0485 vmap(p->vbase+0x100000, (u_long)p->ram|PTE_RAM, 0x10000);
0486 vmap(p->vbase+0xa0000,
0487 ((u_long)ptr_mem_map->isa_mem_base+0xa0000)|PTE_IO, 0x20000);
0488 return 0;
0489 }
0490
0491 void em86_main(struct pci_dev *dev){
0492 x86 *p = (x86 *) bd->v86_private;
0493 u_short signature;
0494 u_char length;
0495 volatile u_int *src;
0496 u_int *dst, left;
0497 uint32_t saved_rom;
0498 #if defined(MONITOR_IO) && !defined(__BOOT__)
0499 #define IOMASK 0xff
0500 #else
0501 #define IOMASK 0
0502 #endif
0503
0504 #ifndef __BOOT__
0505 int i;
0506
0507 for(i=0; i<65536/8; i++) p->ioperm[i]=IOMASK;
0508 p->ioperm[i] = 0xff;
0509 #endif
0510 p->dev = dev;
0511 memset(p->vbase, 0, 0xa0000);
0512
0513 p->cs = 0xc000; p->csbase = p->vbase + 0xc0000;
0514 p->ss = 0x1000; p->ssbase = p->vbase + 0x10000;
0515 p->eflags=0x200;
0516 st_le16(&SP,0xfffc); p->eip=3;
0517
0518 p->dsbase = p->esbase = p->fsbase = p->gsbase = p->vbase;
0519
0520
0521 AH=dev->bus->number;
0522 AL=dev->devfn;
0523
0524
0525
0526
0527
0528
0529 *(u_int *)(p->ssbase+ld_le16(&SP)) = UINT_MAX;
0530
0531
0532 st_le32((uint32_t *)p->vbase + 0x10, 0xf000f065);
0533
0534
0535 pci_bootloader_read_config_dword(dev, PCI_ROM_ADDRESS, &saved_rom);
0536 pci_bootloader_write_config_dword(dev, PCI_ROM_ADDRESS, 0x000c0001);
0537
0538
0539
0540
0541 signature = *(u_short *)(ptr_mem_map->isa_mem_base+0xc0000);
0542 if (signature!=0x55aa) {
0543 printf("bad signature: %04x.\n", signature);
0544 return;
0545 }
0546
0547 length = ptr_mem_map->isa_mem_base[0xc0002];
0548 p->rom = palloc(length*512);
0549 if (!p->rom) return;
0550
0551 for(dst=(u_int *) p->rom,
0552 src=(volatile u_int *)(ptr_mem_map->isa_mem_base+0xc0000),
0553 left = length*512/sizeof(u_int);
0554 left--;
0555 *dst++=*src++);
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565 pci_bootloader_write_config_dword(dev, PCI_ROM_ADDRESS, saved_rom);
0566 vmap(p->vbase+0xc0000, (u_long)p->rom|PTE_RAM, length*512);
0567
0568
0569 em86_enter(p);
0570
0571
0572 vunmap(p->vbase+0xc0000);
0573 pfree(p->rom);
0574 }