/* * execute BIOS E6 call in emulation environment * Copyright 1999 Egbert Eich * Copyright 2004 Venkatesh Pallipadi */ #include #include #include #define _INT10_PRIVATE #include "include/xf86int10.h" #include "include/x86emu.h" #include "include/xf86x86emu.h" #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #define dump_registers(x) #define stack_trace(x) #define __BUILDIO(bwl,bw,type) \ static inline void out##bwl##_local(unsigned long port, unsigned type value) { \ __asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \ }\ static inline unsigned type in##bwl##_local(unsigned long port) { \ unsigned type value; \ __asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \ return value; \ }\ __BUILDIO(b,b,char) __BUILDIO(w,w,short) __BUILDIO(l,,int) int10MemRec genericMem; xf86Int10InfoPtr Int10Current; typedef struct { int shift; int entries; void* base; void* vRam; int highMemory; void* sysMem; char* alloc; } genericInt10Priv; #define INTPriv(x) ((genericInt10Priv*)x->private) int setup_int(xf86Int10InfoPtr pInt) { X86_EAX = (CARD32) pInt->ax; X86_EBX = (CARD32) pInt->bx; X86_ECX = (CARD32) pInt->cx; X86_EDX = (CARD32) pInt->dx; X86_ESI = (CARD32) pInt->si; X86_EDI = (CARD32) pInt->di; X86_EBP = (CARD32) pInt->bp; X86_ESP = 0x1000; X86_SS = pInt->stackseg >> 4; X86_EIP = 0x0600; X86_CS = 0x0; /* address of 'hlt' */ X86_DS = 0x40; /* standard pc ds */ X86_ES = pInt->es; X86_FS = 0; X86_GS = 0; X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK; return 0; } void finish_int(xf86Int10InfoPtr pInt, int sig) { pInt->ax = (CARD32) X86_EAX; pInt->bx = (CARD32) X86_EBX; pInt->cx = (CARD32) X86_ECX; pInt->dx = (CARD32) X86_EDX; pInt->si = (CARD32) X86_ESI; pInt->di = (CARD32) X86_EDI; pInt->es = (CARD16) X86_ES; pInt->bp = (CARD32) X86_EBP; pInt->flags = (CARD32) X86_FLAGS; } xf86Int10InfoPtr xf86ExtendedInitInt10_E6(int entityIndex, int Flags, unsigned int pci_id) { xf86Int10InfoPtr pInt; int bios_location; char *mmap_addr; int fd; pInt = (xf86Int10InfoPtr)calloc(1, sizeof(xf86Int10InfoRec)); pInt->entityIndex = entityIndex; if (!xf86Int10ExecSetup(pInt)) goto error0; pInt->mem = &genericMem; pInt->private = (pointer)calloc(1, sizeof(genericInt10Priv)); fd = open("/dev/mem", O_RDWR); if ( fd < 0 ) { printf("Couldn't open /dev/mem\n"); printf("Cannot emulate video BIOS\n"); exit(3); } mmap_addr = mmap(0, 0x100000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if ( mmap_addr < 0 ) { printf("Couldn't mmap /dev/mem\n"); printf("Cannot emulate video BIOS\n"); exit(4); } INTPriv(pInt)->base = mmap_addr; bios_location = V_BIOS; M.mem_base = (unsigned long)INTPriv(pInt)->base; M.mem_size = 1024*1024; pInt->BIOSseg = V_BIOS >> 4; pInt->entityIndex = pci_id; pInt->ax = pci_id; pInt->num = 0xe6; xf86ExecX86int10(pInt); munmap(mmap_addr, 0x100000); close(fd); return pInt; error0: return NULL; } static CARD8 read_b(xf86Int10InfoPtr pInt, int addr) { return *((char *)INTPriv(pInt)->base + addr); } static CARD16 read_w(xf86Int10InfoPtr pInt, int addr) { return *((char *)INTPriv(pInt)->base + addr); } static CARD32 read_l(xf86Int10InfoPtr pInt, int addr) { return *((char *)INTPriv(pInt)->base + addr); } static void write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val) { *((char *)INTPriv(pInt)->base + addr) = val; return; } static void write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val) { *((char *)INTPriv(pInt)->base + addr) = val; *((char *)INTPriv(pInt)->base + addr + 1) = val >> 8; return; } static void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val) { *((char *)INTPriv(pInt)->base + addr) = val; *((char *)INTPriv(pInt)->base + addr + 1) = val >> 8; *((char *)INTPriv(pInt)->base + addr + 2) = val >> 16; *((char *)INTPriv(pInt)->base + addr + 3) = val >> 24; return; } static void x86emu_do_int(int num) { Int10Current->num = num; if (!int_handler(Int10Current)) { X86EMU_halt_sys(); } } Bool MapCurrentInt10(xf86Int10InfoPtr pInt) { return FALSE; } void xf86FreeInt10(xf86Int10InfoPtr pInt) { return; } void * xf86Int10AllocPages(xf86Int10InfoPtr pInt,int num, int *off) { *off = 0; return NULL; } void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num) { return; } CARD8 x_inb(CARD16 port) { CARD8 val; val = inb_local(port); return val; } CARD16 x_inw(CARD16 port) { CARD16 val; val = inw_local(port); return val; } CARD32 x_inl(CARD16 port) { CARD32 val; val = inl_local(port); return val; } void x_outb(CARD16 port, CARD8 val) { outb_local(port, val); } void x_outw(CARD16 port, CARD16 val) { outw_local(port, val); } void x_outl(CARD16 port, CARD32 val) { outl_local(port, val); } int10MemRec genericMem = { read_b, read_w, read_l, write_b, write_w, write_l }; Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt) { int i; X86EMU_intrFuncs intFuncs[256]; X86EMU_pioFuncs pioFuncs = { (&x_inb), (&x_inw), (&x_inl), (&x_outb), (&x_outw), (&x_outl) }; pInt->cpuRegs = &M; M.mem_base = 0; M.mem_size = 1024*1024; X86EMU_setupPioFuncs(&pioFuncs); for (i=0;i<256;i++) intFuncs[i] = x86emu_do_int; X86EMU_setupIntrFuncs(intFuncs); return TRUE; } void xf86ExecX86int10(xf86Int10InfoPtr pInt) { int sig; sig = setup_int(pInt); Int10Current = pInt; if (sig < 0) return; pushw(pInt, 0 ); pushw(pInt, 0 ); pushw(pInt, 0 ); pushw(pInt, 0 ); pushw(pInt, 0 ); X86_IP = 0; X86_CS = 0; if (int_handler(pInt)) { X86EMU_exec(); } finish_int(pInt, sig); return; } pointer xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr) { return 0; } int find_video_pci_id(void) { int retval; FILE *fp; char *tok; #define READ_SIZE 80 char buf[READ_SIZE]; retval = system("/sbin/lspci -n > /tmp/lspci.out"); if (retval) { /*lspci failed. Use Bus 1, Dev 0, Func 0 as default */ retval = 0x100; return retval; } fp = fopen("/tmp/lspci.out", "r"); if (!fp) { retval = 0x100; goto end; } while (fgets(buf, READ_SIZE, fp)) { if (!strstr(buf, "Class 0300:")) continue; tok = strtok(buf, ":"); if (strlen(tok) > 2 ) tok = strtok(NULL, ":"); retval = strtol(tok, NULL, 16) << 8; tok = strtok(NULL, "."); retval += strtol(tok, NULL, 16) << 3; tok = strtok(NULL, " "); retval += strtol(tok, NULL, 16); break; } end: fclose(fp); unlink("/tmp/lspci.out"); return retval; } int main() { unsigned int pci_id = 0x100; ioperm(0, 0x3ff, 1); iopl(3); pci_id = find_video_pci_id(); xf86ExtendedInitInt10_E6(0, 0, pci_id); return 0; } void printk(const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); printf(fmt, argptr); va_end(argptr); } static int int1A_handler(xf86Int10InfoPtr pInt); static int int42_handler(xf86Int10InfoPtr pInt); static int intE6_handler(xf86Int10InfoPtr pInt); /* general software interrupt handler */ CARD32 getIntVect(xf86Int10InfoPtr pInt,int num) { return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4); } void pushw(xf86Int10InfoPtr pInt, CARD16 val) { X86_ESP -= 2; MEM_WW(pInt, ((CARD32) X86_SS << 4) + X86_SP, val); } int run_bios_int(int num, xf86Int10InfoPtr pInt) { CARD32 eflags; /* check if bios vector is initialized */ if (MEM_RW(pInt, (num << 2) + 2) == (SYS_BIOS >> 4)) { /* SYS_BIOS_SEG ?*/ if (num == 21 && X86_AH == 0x4e) { printk( "Failing Find-Matching-File on non-PC" " (int 21, func 4e)\n"); X86_AX = 2; SET_FLAG(F_CF); return 1; } else { printk( "Ignoring int 0x%02x call\n", num); return 1; } } #ifdef PRINT_INT ErrorF("calling card BIOS at: "); #endif eflags = X86_EFLAGS; eflags = eflags | X86_IF_MASK; X86_EFLAGS = X86_EFLAGS & ~(X86_VIF_MASK | X86_TF_MASK | X86_IF_MASK | X86_NT_MASK); pushw(pInt, eflags); pushw(pInt, X86_CS); pushw(pInt, X86_IP); { short cs, ip; cs = (MEM_RB(pInt, (num << 2) + 3) << 8) + MEM_RB(pInt, (num << 2) + 2); ip = (MEM_RB(pInt, (num << 2) + 1) << 8) + MEM_RB(pInt, (num << 2)); X86_CS = cs; X86_IP = ip; } #ifdef PRINT_INT ErrorF("0x%x:%lx\n", X86_CS, X86_EIP); #endif return 1; } int int_handler(xf86Int10InfoPtr pInt) { int num; int ret = 0; num = pInt->num; dump_registers(pInt); switch (num) { case 0x10: case 0x42: case 0x6D: if (getIntVect(pInt, num) == I_S_DEFAULT_INT_VECT) ret = int42_handler(pInt); break; case 0x1A: ret = int1A_handler(pInt); break; case 0xe6: ret = intE6_handler(pInt); break; default: break; } if (!ret) ret = run_bios_int(num, pInt); if (!ret) { printk( "Halting on int 0x%2.2x!\n", num); dump_registers(pInt); stack_trace(pInt); } return ret; } /* * This is derived from a number of PC system BIOS'es. The intent here is to * provide very primitive video support, before an EGA/VGA BIOS installs its * own interrupt vector. Here, "Ignored" calls should remain so. "Not * Implemented" denotes functionality that can be implemented should the need * arise. What are "Not Implemented" throughout are video memory accesses. * Also, very little input validity checking is done here. */ static int int42_handler(xf86Int10InfoPtr pInt) { switch (X86_AH) { case 0x00: /* Set Video Mode */ /* Enter: AL = video mode number */ /* Leave: Nothing */ /* Implemented (except for clearing the screen) */ { /* Localise */ IOADDRESS ioport; int i; CARD16 int1d, regvals, tmp; CARD8 mode, cgamode, cgacolour; /* * Ignore all mode numbers but 0x00-0x13. Some systems also ignore * 0x0B and 0x0C, but don't do that here. */ if (X86_AL > 0x13) break; /* * You didn't think that was really the mode set, did you? There * are only so many slots in the video parameter table... */ mode = X86_AL; ioport = (IOADDRESS)0x03D4; switch (MEM_RB(pInt, 0x0410) & 0x30) { case 0x30: /* MDA */ mode = 0x07; /* Force mode to 0x07 */ ioport = (IOADDRESS)0x03B4; break; case 0x10: /* CGA 40x25 */ if (mode >= 0x07) mode = 0x01; break; case 0x20: /* CGA 80x25 (MCGA?) */ if (mode >= 0x07) mode = 0x03; break; case 0x00: /* EGA/VGA */ if (mode >= 0x07) /* Don't try MDA timings */ mode = 0x01; /* !?!?! */ break; } /* Locate data in video parameter table */ int1d = MEM_RW(pInt, 0x1d << 2); regvals = ((mode >> 1) << 4) + int1d; cgacolour = 0x30; if (mode == 0x06) { regvals -= 0x10; cgacolour = 0x3F; } /** Update BIOS Data Area **/ /* Video mode */ MEM_WB(pInt, 0x0449, mode); /* Columns */ tmp = MEM_RB(pInt, mode + int1d + 0x48); MEM_WW(pInt, 0x044A, tmp); /* Page length */ tmp = MEM_RW(pInt, (mode & 0x06) + int1d + 0x40); MEM_WW(pInt, 0x044C, tmp); /* Start Address */ MEM_WW(pInt, 0x044E, 0); /* Cursor positions, one for each display page */ for (i = 0x0450; i < 0x0460; i += 2) MEM_WW(pInt, i, 0); /* Cursor start & end scanlines */ tmp = MEM_RB(pInt, regvals + 0x0B); MEM_WB(pInt, 0x0460, tmp); tmp = MEM_RB(pInt, regvals + 0x0A); MEM_WB(pInt, 0x0461, tmp); /* Current display page number */ MEM_WB(pInt, 0x0462, 0); /* CRTC I/O address */ MEM_WW(pInt, 0x0463, (unsigned long)ioport); /* CGA Mode register value */ cgamode = MEM_RB(pInt, mode + int1d + 0x50); MEM_WB(pInt, 0x0465, cgamode); /* CGA Colour register value */ MEM_WB(pInt, 0x0466, cgacolour); /* Rows */ MEM_WB(pInt, 0x0484, (25 - 1)); /* Remap I/O port number into its domain */ ioport = (IOADDRESS)((int) ioport + (int) pInt->ioBase); /* Programme the mode */ outb((unsigned long)ioport + 4, cgamode & 0x37); /* Turn off screen */ for (i = 0; i < 0x10; i++) { tmp = MEM_RB(pInt, regvals + i); outb((unsigned long)ioport, i); outb((unsigned long)ioport + 1, tmp); } outb((unsigned long)ioport + 5, cgacolour); /* Select colour mode */ outb((unsigned long)ioport + 4, cgamode); /* Turn on screen */ } break; case 0x01: /* Set Cursor Type */ /* Enter: CH = starting line for cursor */ /* CL = ending line for cursor */ /* Leave: Nothing */ /* Implemented */ { /* Localise */ IOADDRESS ioport = MEM_RW(pInt, 0x0463) + pInt->ioBase; MEM_WB(pInt, 0x0460, X86_CL); MEM_WB(pInt, 0x0461, X86_CH); outb((unsigned long)ioport, 0x0A); outb((unsigned long)ioport + 1, X86_CH); outb((unsigned long)ioport, 0x0B); outb((unsigned long)ioport + 1, X86_CL); } break; case 0x02: /* Set Cursor Position */ /* Enter: BH = display page number */ /* DH = row */ /* DL = column */ /* Leave: Nothing */ /* Implemented */ { /* Localise */ IOADDRESS ioport; CARD16 offset; MEM_WB(pInt, (X86_BH << 1) + 0x0450, X86_DL); MEM_WB(pInt, (X86_BH << 1) + 0x0451, X86_DH); if (X86_BH != MEM_RB(pInt, 0x0462)) break; offset = (X86_DH * MEM_RW(pInt, 0x044A)) + X86_DL; offset += MEM_RW(pInt, 0x044E) << 1; ioport = MEM_RW(pInt, 0x0463) + pInt->ioBase; outb((unsigned long)ioport, 0x0E); outb((unsigned long)ioport + 1, offset >> 8); outb((unsigned long)ioport, 0x0F); outb((unsigned long)ioport + 1, offset & 0xFF); } break; case 0x03: /* Get Cursor Position */ /* Enter: BH = display page number */ /* Leave: CH = starting line for cursor */ /* CL = ending line for cursor */ /* DH = row */ /* DL = column */ /* Implemented */ { /* Localise */ X86_CL = MEM_RB(pInt, 0x0460); X86_CH = MEM_RB(pInt, 0x0461); X86_DL = MEM_RB(pInt, (X86_BH << 1) + 0x0450); X86_DH = MEM_RB(pInt, (X86_BH << 1) + 0x0451); } break; case 0x04: /* Get Light Pen Position */ /* Enter: Nothing */ /* Leave: AH = 0x01 (down/triggered) or 0x00 (not) */ /* BX = pixel column */ /* CX = pixel row */ /* DH = character row */ /* DL = character column */ /* Not Implemented */ { /* Localise */ printk("int 0x%2.2x(AH=0x04) -- Get Light Pen Position\n", pInt->num); X86_AH = X86_BX = X86_CX = X86_DX = 0; } break; case 0x05: /* Set Display Page */ /* Enter: AL = display page number */ /* Leave: Nothing */ /* Implemented */ { /* Localise */ IOADDRESS ioport = MEM_RW(pInt, 0x0463) + pInt->ioBase; CARD16 start; CARD8 x, y; /* Calculate new start address */ MEM_WB(pInt, 0x0462, X86_AL); start = X86_AL * MEM_RW(pInt, 0x044C); MEM_WW(pInt, 0x044E, start); start <<= 1; /* Update start address */ outb((unsigned long)ioport, 0x0C); outb((unsigned long)ioport + 1, start >> 8); outb((unsigned long)ioport, 0x0D); outb((unsigned long)ioport + 1, start & 0xFF); /* Switch cursor position */ y = MEM_RB(pInt, (X86_AL << 1) + 0x0450); x = MEM_RB(pInt, (X86_AL << 1) + 0x0451); start += (y * MEM_RW(pInt, 0x044A)) + x; /* Update cursor position */ outb((unsigned long)ioport, 0x0E); outb((unsigned long)ioport + 1, start >> 8); outb((unsigned long)ioport, 0x0F); outb((unsigned long)ioport + 1, start & 0xFF); } break; case 0x06: /* Initialise or Scroll Window Up */ /* Enter: AL = lines to scroll up */ /* BH = attribute for blank */ /* CH = upper y of window */ /* CL = left x of window */ /* DH = lower y of window */ /* DL = right x of window */ /* Leave: Nothing */ /* Not Implemented */ { /* Localise */ printk("int 0x%2.2x(AH=0x06) -- Initialise or Scroll Window Up\n", pInt->num); printk(" AL=0x%2.2x, BH=0x%2.2x," " CH=0x%2.2x, CL=0x%2.2x, DH=0x%2.2x, DL=0x%2.2x\n", X86_AL, X86_BH, X86_CH, X86_CL, X86_DH, X86_DL); } break; case 0x07: /* Initialise or Scroll Window Down */ /* Enter: AL = lines to scroll down */ /* BH = attribute for blank */ /* CH = upper y of window */ /* CL = left x of window */ /* DH = lower y of window */ /* DL = right x of window */ /* Leave: Nothing */ /* Not Implemented */ { /* Localise */ printk("int 0x%2.2x(AH=0x07) -- Initialise or Scroll Window Down\n", pInt->num); printk(" AL=0x%2.2x, BH=0x%2.2x," " CH=0x%2.2x, CL=0x%2.2x, DH=0x%2.2x, DL=0x%2.2x\n", X86_AL, X86_BH, X86_CH, X86_CL, X86_DH, X86_DL); } break; case 0x08: /* Read Character and Attribute at Cursor */ /* Enter: BH = display page number */ /* Leave: AH = attribute */ /* AL = character */ /* Not Implemented */ { /* Localise */ printk("int 0x%2.2x(AH=0x08) -- Read Character and Attribute at" " Cursor\n", pInt->num); printk("BH=0x%2.2x\n", X86_BH); X86_AX = 0; } break; case 0x09: /* Write Character and Attribute at Cursor */ /* Enter: AL = character */ /* BH = display page number */ /* BL = attribute (text) or colour (graphics) */ /* CX = replication count */ /* Leave: Nothing */ /* Not Implemented */ { /* Localise */ printk( "int 0x%2.2x(AH=0x09) -- Write Character and Attribute at" " Cursor\n", pInt->num); printk( "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x\n", X86_AL, X86_BH, X86_BL, X86_CX); } break; case 0x0a: /* Write Character at Cursor */ /* Enter: AL = character */ /* BH = display page number */ /* BL = colour */ /* CX = replication count */ /* Leave: Nothing */ /* Not Implemented */ { /* Localise */ printk( "int 0x%2.2x(AH=0x0A) -- Write Character at Cursor\n", pInt->num); printk( "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x\n", X86_AL, X86_BH, X86_BL, X86_CX); } break; case 0x0b: /* Set Palette, Background or Border */ /* Enter: BH = 0x00 or 0x01 */ /* BL = colour or palette (respectively) */ /* Leave: Nothing */ /* Implemented */ { /* Localise */ IOADDRESS ioport = MEM_RW(pInt, 0x0463) + 5 + pInt->ioBase; CARD8 cgacolour = MEM_RB(pInt, 0x0466); if (X86_BH) { cgacolour &= 0xDF; cgacolour |= (X86_BL & 0x01) << 5; } else { cgacolour &= 0xE0; cgacolour |= X86_BL & 0x1F; } MEM_WB(pInt, 0x0466, cgacolour); outb((unsigned long)ioport, cgacolour); } break; case 0x0c: /* Write Graphics Pixel */ /* Enter: AL = pixel value */ /* BH = display page number */ /* CX = column */ /* DX = row */ /* Leave: Nothing */ /* Not Implemented */ { /* Localise */ printk( "int 0x%2.2x(AH=0x0C) -- Write Graphics Pixel\n", pInt->num); printk( "AL=0x%2.2x, BH=0x%2.2x, CX=0x%4.4x, DX=0x%4.4x\n", X86_AL, X86_BH, X86_CX, X86_DX); } break; case 0x0d: /* Read Graphics Pixel */ /* Enter: BH = display page number */ /* CX = column */ /* DX = row */ /* Leave: AL = pixel value */ /* Not Implemented */ { /* Localise */ printk( "int 0x%2.2x(AH=0x0D) -- Read Graphics Pixel\n", pInt->num); printk( "BH=0x%2.2x, CX=0x%4.4x, DX=0x%4.4x\n", X86_BH, X86_CX, X86_DX); X86_AL = 0; } break; case 0x0e: /* Write Character in Teletype Mode */ /* Enter: AL = character */ /* BH = display page number */ /* BL = foreground colour */ /* Leave: Nothing */ /* Not Implemented */ /* WARNING: Emulation of BEL characters will require */ /* emulation of RTC and PC speaker I/O. */ /* Also, this recurses through int 0x10 */ /* which might or might not have been */ /* installed yet. */ { /* Localise */ printk( "int 0x%2.2x(AH=0x0E) -- Write Character in Teletype Mode\n", pInt->num); printk( "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x\n", X86_AL, X86_BH, X86_BL); } break; case 0x0f: /* Get Video Mode */ /* Enter: Nothing */ /* Leave: AH = number of columns */ /* AL = video mode number */ /* BH = display page number */ /* Implemented */ { /* Localise */ X86_AH = MEM_RW(pInt, 0x044A); X86_AL = MEM_RB(pInt, 0x0449); X86_BH = MEM_RB(pInt, 0x0462); } break; case 0x10: /* Colour Control (subfunction in AL) */ /* Enter: Various */ /* Leave: Various */ /* Ignored */ break; case 0x11: /* Font Control (subfunction in AL) */ /* Enter: Various */ /* Leave: Various */ /* Ignored */ break; case 0x12: /* Miscellaneous (subfunction in BL) */ /* Enter: Various */ /* Leave: Various */ /* Ignored. Previous code here optionally allowed */ /* the enabling and disabling of VGA, but no system */ /* BIOS I've come across actually implements it. */ break; case 0x13: /* Write String in Teletype Mode */ /* Enter: AL = write mode */ /* BL = attribute (if (AL & 0x02) == 0) */ /* CX = string length */ /* DH = row */ /* DL = column */ /* ES:BP = string segment:offset */ /* Leave: Nothing */ /* Not Implemented */ /* WARNING: Emulation of BEL characters will require */ /* emulation of RTC and PC speaker I/O. */ /* Also, this recurses through int 0x10 */ /* which might or might not have been */ /* installed yet. */ { /* Localise */ printk( "int 0x%2.2x(AH=0x13) -- Write String in Teletype Mode\n", pInt->num); printk( "AL=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x," " DH=0x%2.2x, DL=0x%2.2x, ES:BP=0x%4.4x:0x%4.4x\n", X86_AL, X86_BL, X86_CX, X86_DH, X86_DL, X86_ES, X86_BP); } break; default: /* Various extensions */ /* Enter: Various */ /* Leave: Various */ /* Ignored */ break; } return 1; } #define SUCCESSFUL 0x00 #define DEVICE_NOT_FOUND 0x86 #define BAD_REGISTER_NUMBER 0x87 static int int1A_handler(xf86Int10InfoPtr pInt) { return 0; /* Unsupported yet */ } /* * handle initialization */ static int intE6_handler(xf86Int10InfoPtr pInt) { X86_AX = pInt->entityIndex; pushw(pInt, X86_CS); pushw(pInt, X86_IP); X86_CS = pInt->BIOSseg; X86_EIP = 0x0003; #if 0 ErrorF("cs=0x%x EIP=0x%x\n", X86_CS, X86_EIP); #endif X86_ES = 0; /* standard pc es */ return 1; }