/* * XFree86 int10 module * execute BIOS int 10h calls in x86 real mode environment * Copyright 1999 Egbert Eich */ #ifdef HAVE_XORG_CONFIG_H #include <xorg-config.h> #endif #include "xf86.h" #include "compiler.h" #define _INT10_PRIVATE #include "xf86int10.h" #include "int10Defines.h" #include "Pci.h" #define REG pInt xf86Int10InfoPtr Int10Current = NULL; static int int1A_handler(xf86Int10InfoPtr pInt); #ifndef _PC static int int42_handler(xf86Int10InfoPtr pInt); #endif static int intE6_handler(xf86Int10InfoPtr pInt); static struct pci_device *findPci(xf86Int10InfoPtr pInt, unsigned short bx); static CARD32 pciSlotBX( const struct pci_device * pvp ); int int_handler(xf86Int10InfoPtr pInt) { int num = pInt->num; int ret = 0; switch (num) { #ifndef _PC case 0x10: case 0x42: case 0x6D: if (getIntVect(pInt, num) == I_S_DEFAULT_INT_VECT) ret = int42_handler(pInt); break; #endif 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) { xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Halting on int 0x%2.2x!\n", num); dump_registers(pInt); stack_trace(pInt); } return ret; } #ifndef _PC /* * 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 = 0x03D4; switch (MEM_RB(pInt, 0x0410) & 0x30) { case 0x30: /* MDA */ mode = 0x07; /* Force mode to 0x07 */ ioport = 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, 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 += pInt->ioBase; /* Programme the mode */ outb(ioport + 4, cgamode & 0x37); /* Turn off screen */ for (i = 0; i < 0x10; i++) { tmp = MEM_RB(pInt, regvals + i); outb(ioport, i); outb(ioport + 1, tmp); } outb(ioport + 5, cgacolour); /* Select colour mode */ outb(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(ioport, 0x0A); outb(ioport + 1, X86_CH); outb(ioport, 0x0B); outb(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(ioport, 0x0E); outb(ioport + 1, offset >> 8); outb(ioport, 0x0F); outb(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 */ xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, "int 0x%2.2x(AH=0x04) -- Get Light Pen Position\n", pInt->num); if (xf86GetVerbosity() > 3) { dump_registers(pInt); stack_trace(pInt); } 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(ioport, 0x0C); outb(ioport + 1, start >> 8); outb(ioport, 0x0D); outb(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(ioport, 0x0E); outb(ioport + 1, start >> 8); outb(ioport, 0x0F); outb(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 */ xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, "int 0x%2.2x(AH=0x06) -- Initialise or Scroll Window Up\n", pInt->num); xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, " 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); if (xf86GetVerbosity() > 3) { dump_registers(pInt); stack_trace(pInt); } } 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 */ xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, "int 0x%2.2x(AH=0x07) -- Initialise or Scroll Window Down\n", pInt->num); xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, " 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); if (xf86GetVerbosity() > 3) { dump_registers(pInt); stack_trace(pInt); } } break; case 0x08: /* Read Character and Attribute at Cursor */ /* Enter: BH = display page number */ /* Leave: AH = attribute */ /* AL = character */ /* Not Implemented */ { /* Localise */ xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, "int 0x%2.2x(AH=0x08) -- Read Character and Attribute at" " Cursor\n", pInt->num); xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, "BH=0x%2.2x\n", X86_BH); if (xf86GetVerbosity() > 3) { dump_registers(pInt); stack_trace(pInt); } 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 */ xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, "int 0x%2.2x(AH=0x09) -- Write Character and Attribute at" " Cursor\n", pInt->num); xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, "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); if (xf86GetVerbosity() > 3) { dump_registers(pInt); stack_trace(pInt); } } break; case 0x0a: /* Write Character at Cursor */ /* Enter: AL = character */ /* BH = display page number */ /* BL = colour */ /* CX = replication count */ /* Leave: Nothing */ /* Not Implemented */ { /* Localise */ xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, "int 0x%2.2x(AH=0x0A) -- Write Character at Cursor\n", pInt->num); xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, "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); if (xf86GetVerbosity() > 3) { dump_registers(pInt); stack_trace(pInt); } } 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(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 */ xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, "int 0x%2.2x(AH=0x0C) -- Write Graphics Pixel\n", pInt->num); xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, "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); if (xf86GetVerbosity() > 3) { dump_registers(pInt); stack_trace(pInt); } } break; case 0x0d: /* Read Graphics Pixel */ /* Enter: BH = display page number */ /* CX = column */ /* DX = row */ /* Leave: AL = pixel value */ /* Not Implemented */ { /* Localise */ xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, "int 0x%2.2x(AH=0x0D) -- Read Graphics Pixel\n", pInt->num); xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, "BH=0x%2.2x, CX=0x%4.4x, DX=0x%4.4x\n", X86_BH, X86_CX, X86_DX); if (xf86GetVerbosity() > 3) { dump_registers(pInt); stack_trace(pInt); } 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 */ xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, "int 0x%2.2x(AH=0x0E) -- Write Character in Teletype Mode\n", pInt->num); xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x\n", X86_AL, X86_BH, X86_BL); if (xf86GetVerbosity() > 3) { dump_registers(pInt); stack_trace(pInt); } } 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 */ xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, "int 0x%2.2x(AH=0x13) -- Write String in Teletype Mode\n", pInt->num); xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 3, "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); if (xf86GetVerbosity() > 3) { dump_registers(pInt); stack_trace(pInt); } } break; default: /* Various extensions */ /* Enter: Various */ /* Leave: Various */ /* Ignored */ break; } return 1; } #endif #define SUCCESSFUL 0x00 #define DEVICE_NOT_FOUND 0x86 #define BAD_REGISTER_NUMBER 0x87 #ifdef SHOW_ALL_DEVICES /** * These functions are meant to be used by the PCI BIOS emulation. Some * BIOSes need to see if there are \b other chips of the same type around so * by setting \c exclude one PCI device can be explicitely excluded, if * required. */ static struct pci_device * do_find(const struct pci_id_match *m, char n, const struct pci_device * exclude) { struct pci_device *dev; struct pci_device_iterator *iter; n++; iter = pci_id_match_iterator_create(m); while ((dev = pci_device_next(iter)) != NULL) { if ((dev != exclude) && !(--n)) { break; } } pci_iterator_destroy(iter); return dev; } static struct pci_device * find_pci_device_vendor(CARD16 vendorID, CARD16 deviceID, char n, const struct pci_device * exclude) { struct pci_id_match m; m.vendor_id = vendorID; m.device_id = deviceID; m.subvendor_id = PCI_MATCH_ANY; m.subdevice_id = PCI_MATCH_ANY; m.device_class = 0; m.device_class_mask = 0; return do_find(& m, n, exclude); } static struct pci_device * find_pci_class(CARD8 intf, CARD8 subClass, CARD16 _class, char n, const struct pci_device * exclude) { struct pci_id_match m; m.vendor_id = PCI_MATCH_ANY; m.device_id = PCI_MATCH_ANY; m.subvendor_id = PCI_MATCH_ANY; m.subdevice_id = PCI_MATCH_ANY; m.device_class = (((uint32_t)_class) << 16) | (((uint32_t)subClass) << 8) | intf; m.device_class_mask = 0x00ffffff; return do_find(& m, n, exclude); } #endif /* * Return the last bus number in the same domain as dev. Only look at the * one domain since this is going into %cl, and VGA I/O is per-domain anyway. */ static int int1A_last_bus_number(struct pci_device *dev) { struct pci_device *d; struct pci_slot_match m = { dev->domain, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY }; struct pci_device_iterator *iter; int i = 0; iter = pci_slot_match_iterator_create(&m); while ((d = pci_device_next(iter))) if (d->bus > i) i = d->bus; pci_iterator_destroy(iter); return i; } static int int1A_handler(xf86Int10InfoPtr pInt) { struct pci_device * const pvp = xf86GetPciInfoForEntity(pInt->entityIndex); struct pci_device * dev; if (pvp == NULL) return 0; /* oops */ #ifdef PRINT_INT ErrorF("int 0x1a: ax=0x%x bx=0x%x cx=0x%x dx=0x%x di=0x%x es=0x%x\n", X86_EAX, X86_EBX, X86_ECX, X86_EDX, X86_EDI, X86_ESI); #endif switch (X86_AX) { case 0xb101: X86_EAX &= 0xFF00; /* no config space/special cycle support */ X86_EDX = 0x20494350; /* " ICP" */ X86_EBX = 0x0210; /* Version 2.10 */ X86_ECX &= 0xFF00; X86_ECX |= int1A_last_bus_number(pvp); X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ #ifdef PRINT_INT ErrorF("ax=0x%x dx=0x%x bx=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_EDX, X86_EBX, X86_ECX, X86_EFLAGS); #endif return 1; case 0xb102: if ( (X86_DX == pvp->vendor_id) && (X86_CX == pvp->device_id) && (X86_ESI == 0) ) { X86_EAX = X86_AL | (SUCCESSFUL << 8); X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ X86_EBX = pciSlotBX(pvp); } #ifdef SHOW_ALL_DEVICES else if ((dev = find_pci_device_vendor(X86_EDX, X86_ECX, X86_ESI, pvp))) { X86_EAX = X86_AL | (SUCCESSFUL << 8); X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ X86_EBX = pciSlotBX(dev); } #endif else { X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8); X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ } #ifdef PRINT_INT ErrorF("ax=0x%x bx=0x%x flags=0x%x\n", X86_EAX, X86_EBX, X86_EFLAGS); #endif return 1; case 0xb103: if ( (X86_ECX & 0x00FFFFFF) == pvp->device_class ) { X86_EAX = X86_AL | (SUCCESSFUL << 8); X86_EBX = pciSlotBX(pvp); X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ } #ifdef SHOW_ALL_DEVICES else if ((dev = find_pci_class(X86_CL, X86_CH, (X86_ECX & 0xffff0000) >> 16, X86_ESI, pvp))) { X86_EAX = X86_AL | (SUCCESSFUL << 8); X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ X86_EBX = pciSlotBX(dev); } #endif else { X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8); X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ } #ifdef PRINT_INT ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); #endif return 1; case 0xb108: if ((dev = findPci(pInt, X86_EBX)) != NULL) { pci_device_cfg_read_u8(dev, & X86_CL, X86_DI); X86_EAX = X86_AL | (SUCCESSFUL << 8); X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ } else { X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ } #ifdef PRINT_INT ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS); #endif return 1; case 0xb109: if ((dev = findPci(pInt, X86_EBX)) != NULL) { pci_device_cfg_read_u16(dev, & X86_CX, X86_DI); X86_EAX = X86_AL | (SUCCESSFUL << 8); X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ } else { X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ } #ifdef PRINT_INT ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS); #endif return 1; case 0xb10a: if ((dev = findPci(pInt, X86_EBX)) != NULL) { pci_device_cfg_read_u32(dev, & X86_ECX, X86_DI); X86_EAX = X86_AL | (SUCCESSFUL << 8); X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ } else { X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ } #ifdef PRINT_INT ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS); #endif return 1; case 0xb10b: if ((dev = findPci(pInt, X86_EBX)) != NULL) { pci_device_cfg_write_u8(dev, X86_CL, X86_DI); X86_EAX = X86_AL | (SUCCESSFUL << 8); X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ } else { X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ } #ifdef PRINT_INT ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); #endif return 1; case 0xb10c: if ((dev = findPci(pInt, X86_EBX)) != NULL) { pci_device_cfg_write_u16(dev, X86_CX, X86_DI); X86_EAX = X86_AL | (SUCCESSFUL << 8); X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ } else { X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ } #ifdef PRINT_INT ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); #endif return 1; case 0xb10d: if ((dev = findPci(pInt, X86_EBX)) != NULL) { pci_device_cfg_write_u32(dev, X86_ECX, X86_DI); X86_EAX = X86_AL | (SUCCESSFUL << 8); X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */ } else { X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8); X86_EFLAGS |= ((unsigned long)0x01); /* set carry flag */ } #ifdef PRINT_INT ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS); #endif return 1; default: xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, "int 0x1a subfunction\n"); dump_registers(pInt); if (xf86GetVerbosity() > 3) stack_trace(pInt); return 0; } } static struct pci_device * findPci(xf86Int10InfoPtr pInt, unsigned short bx) { const unsigned bus = (bx >> 8) & 0x00FF; const unsigned dev = (bx >> 3) & 0x001F; const unsigned func = (bx ) & 0x0007; return pci_device_find_by_slot(pInt->dev->domain, bus, dev, func); } static CARD32 pciSlotBX(const struct pci_device * pvp) { return ((pvp->bus << 8) & 0x00FF00) | (pvp->dev << 3) | (pvp->func); } /* * handle initialization */ static int intE6_handler(xf86Int10InfoPtr pInt) { struct pci_device * pvp; if ((pvp = xf86GetPciInfoForEntity(pInt->entityIndex))) X86_AX = (pvp->bus << 8) | (pvp->dev << 3) | (pvp->func & 0x7); pushw(pInt, X86_CS); pushw(pInt, X86_IP); X86_CS = pInt->BIOSseg; X86_EIP = 0x0003; X86_ES = 0; /* standard pc es */ return 1; }