From 216fa4633a583fcc278186e1f927f32332d1e5c5 Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Wed, 12 Oct 2011 14:25:07 -0700 Subject: [PATCH] Refactor option rom initialization code in coreboot. - move int15 handler out of the generic code into the mainboard directories of those mainboards that actually use it. - move vbe headers to vbe.h - move function prototypes used in native oprom code to x86.h Change-Id: Idfff5e804ea328f7b5feebac72497c97329320ee Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/255 Tested-by: build bot (Jenkins) Reviewed-by: Marc Jones --- src/devices/oprom/include/vbe.h | 112 +++++++++++++++ src/devices/oprom/x86.c | 93 +------------ src/devices/oprom/x86.h | 48 +++++++ src/devices/oprom/x86_interrupts.c | 150 ++++++++++++--------- src/devices/oprom/yabel/vbe.c | 94 +------------ src/mainboard/kontron/986lcd-m/mainboard.c | 50 ++++++- src/mainboard/roda/rk886ex/mainboard.c | 49 ++++++- 7 files changed, 343 insertions(+), 253 deletions(-) create mode 100644 src/devices/oprom/include/vbe.h create mode 100644 src/devices/oprom/x86.h diff --git a/src/devices/oprom/include/vbe.h b/src/devices/oprom/include/vbe.h new file mode 100644 index 0000000000..b87b0d5506 --- /dev/null +++ b/src/devices/oprom/include/vbe.h @@ -0,0 +1,112 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * Copyright (c) 2009 Pattrick Hueper + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +// these structs are for input from and output to OF +typedef struct { + u8 display_type; // 0=NONE, 1= analog, 2=digital + u16 screen_width; + u16 screen_height; + u16 screen_linebytes; // bytes per line in framebuffer, may be more than screen_width + u8 color_depth; // color depth in bpp + u32 framebuffer_address; + u8 edid_block_zero[128]; +} __attribute__ ((__packed__)) screen_info_t; + +typedef struct { + u8 signature[4]; + u16 size_reserved; + u8 monitor_number; + u16 max_screen_width; + u8 color_depth; +} __attribute__ ((__packed__)) screen_info_input_t; + +// these structs only store a subset of the VBE defined fields +// only those needed. +typedef struct { + char signature[4]; + u16 version; + u8 *oem_string_ptr; + u32 capabilities; + u16 video_mode_list[256]; // lets hope we never have more than 256 video modes... + u16 total_memory; +} vbe_info_t; + +typedef struct { + u16 mode_attributes; // 00 + u8 win_a_attributes; // 02 + u8 win_b_attributes; // 03 + u16 win_granularity; // 04 + u16 win_size; // 06 + u16 win_a_segment; // 08 + u16 win_b_segment; // 0a + u32 win_func_ptr; // 0c + u16 bytes_per_scanline; // 10 + u16 x_resolution; // 12 + u16 y_resolution; // 14 + u8 x_charsize; // 16 + u8 y_charsize; // 17 + u8 number_of_planes; // 18 + u8 bits_per_pixel; // 19 + u8 number_of_banks; // 20 + u8 memory_model; // 21 + u8 bank_size; // 22 + u8 number_of_image_pages; // 23 + u8 reserved_page; + u8 red_mask_size; + u8 red_mask_pos; + u8 green_mask_size; + u8 green_mask_pos; + u8 blue_mask_size; + u8 blue_mask_pos; + u8 reserved_mask_size; + u8 reserved_mask_pos; + u8 direct_color_mode_info; + u32 phys_base_ptr; + u32 offscreen_mem_offset; + u16 offscreen_mem_size; + u8 reserved[206]; +} __attribute__ ((__packed__)) vesa_mode_info_t; + +typedef struct { + u16 video_mode; + union { + vesa_mode_info_t vesa; + u8 mode_info_block[256]; + }; + // our crap + //u16 attributes; + //u16 linebytes; + //u16 x_resolution; + //u16 y_resolution; + //u8 x_charsize; + //u8 y_charsize; + //u8 bits_per_pixel; + //u8 memory_model; + //u32 framebuffer_address; +} vbe_mode_info_t; + +typedef struct { + u8 port_number; // i.e. monitor number + u8 edid_transfer_time; + u8 ddc_level; + u8 edid_block_zero[128]; +} vbe_ddc_info_t; + +struct lb_framebuffer; + +void vbe_set_graphics(void); // yabel only + +void fill_lb_framebuffer(struct lb_framebuffer *framebuffer); +void vbe_textmode_console(void); + + diff --git a/src/devices/oprom/x86.c b/src/devices/oprom/x86.c index 37b45e6376..9a6ce41029 100644 --- a/src/devices/oprom/x86.c +++ b/src/devices/oprom/x86.c @@ -26,18 +26,7 @@ #include #include -#define REALMODE_BASE ((void *)0x600) - -struct realmode_idt { - u16 offset, cs; -}; - -void x86_exception(struct eregs *info); - -/* From x86_asm.S */ -extern unsigned char __idt_handler, __idt_handler_size; -extern unsigned char __realmode_code, __realmode_code_size; -extern unsigned char __realmode_call, __realmode_interrupt; +#include "x86.h" void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx, u32 esi, u32 edi) __attribute__((regparm(0))) = (void *)&__realmode_call; @@ -45,10 +34,6 @@ void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx, void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx, u32 esi, u32 edi) __attribute__((regparm(0))) = (void *)&__realmode_interrupt; -#define FAKE_MEMORY_SIZE (1024*1024) // only 1MB -#define INITIAL_EBDA_SEGMENT 0xF600 -#define INITIAL_EBDA_SIZE 0x400 - static void setup_bda(void) { /* clear BIOS DATA AREA */ @@ -104,79 +89,6 @@ void mainboard_interrupt_handlers(int intXX, void *intXX_func) intXX_handler[intXX] = intXX_func; } -static int int10_handler(struct eregs *regs) -{ - int res=-1; - static u8 cursor_row=0, cursor_col=0; - switch((regs->eax & 0xff00)>>8) { - case 0x01: // Set cursor shape - res = 0; - break; - case 0x02: // Set cursor position - if (cursor_row != ((regs->edx >> 8) & 0xff) || - cursor_col >= (regs->edx & 0xff)) { - printk(BIOS_INFO, "\n"); - } - cursor_row = (regs->edx >> 8) & 0xff; - cursor_col = regs->edx & 0xff; - res = 0; - break; - case 0x03: // Get cursor position - regs->eax &= 0x00ff; - regs->ecx = 0x0607; - regs->edx = (cursor_row << 8) | cursor_col; - res = 0; - break; - case 0x06: // Scroll up - printk(BIOS_INFO, "\n"); - res = 0; - break; - case 0x08: // Get Character and Mode at Cursor Position - regs->eax = 0x0f00 | 'A'; // White on black 'A' - res = 0; - break; - case 0x09: // Write Character and attribute - case 0x10: // Write Character - printk(BIOS_INFO, "%c", regs->eax & 0xff); - res = 0; - break; - case 0x0f: // Get video mode - regs->eax = 0x5002; //80x25 - regs->ebx &= 0x00ff; - res = 0; - break; - default: - printk(BIOS_WARNING, "Unknown INT10 function %04x!\n", - regs->eax & 0xffff); - break; - } - return res; -} - -static int int16_handler(struct eregs *regs) -{ - int res=-1; - switch((regs->eax & 0xff00)>>8) { - case 0x00: // Check for Keystroke - regs->eax = 0x6120; // Space Bar, Space - res = 0; - break; - case 0x01: // Check for Keystroke - regs->eflags |= 1<<6; // Zero Flag set (no key available) - res = 0; - break; - default: - printk(BIOS_WARNING, "Unknown INT16 function %04x!\n", - regs->eax & 0xffff); - break; - } - return res; -} - -int int12_handler(struct eregs *regs); -int int15_handler(struct eregs *regs); -int int1a_handler(struct eregs *regs); - static void setup_interrupt_handlers(void) { int i; @@ -206,9 +118,6 @@ static void setup_interrupt_handlers(void) case 0x12: intXX_handler[0x12] = &int12_handler; break; - case 0x15: - intXX_handler[0x15] = &int15_handler; - break; case 0x16: intXX_handler[0x16] = &int16_handler; break; diff --git a/src/devices/oprom/x86.h b/src/devices/oprom/x86.h new file mode 100644 index 0000000000..0bc24122e1 --- /dev/null +++ b/src/devices/oprom/x86.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 Advanced Micro Devices, Inc. + * Copyright (C) 2009-2010 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define REALMODE_BASE ((void *)0x600) + +struct realmode_idt { + u16 offset, cs; +}; + +void x86_exception(struct eregs *info); + +/* From x86_asm.S */ +extern unsigned char __idt_handler, __idt_handler_size; +extern unsigned char __realmode_code, __realmode_code_size; +extern unsigned char __realmode_call, __realmode_interrupt; + +extern void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx, + u32 esi, u32 edi) __attribute__((regparm(0))); + +extern void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx, + u32 esi, u32 edi) __attribute__((regparm(0))); + +#define FAKE_MEMORY_SIZE (1024*1024) // only 1MB +#define INITIAL_EBDA_SEGMENT 0xF600 +#define INITIAL_EBDA_SIZE 0x400 + +int int10_handler(struct eregs *regs); +int int12_handler(struct eregs *regs); +int int16_handler(struct eregs *regs); +int int1a_handler(struct eregs *regs); + diff --git a/src/devices/oprom/x86_interrupts.c b/src/devices/oprom/x86_interrupts.c index 1dd645b421..86d20d7d2e 100644 --- a/src/devices/oprom/x86_interrupts.c +++ b/src/devices/oprom/x86_interrupts.c @@ -26,17 +26,7 @@ #include #include #include - -enum { - PCIBIOS_CHECK = 0xb101, - PCIBIOS_FINDDEV = 0xb102, - PCIBIOS_READCONFBYTE = 0xb108, - PCIBIOS_READCONFWORD = 0xb109, - PCIBIOS_READCONFDWORD = 0xb10a, - PCIBIOS_WRITECONFBYTE = 0xb10b, - PCIBIOS_WRITECONFWORD = 0xb10c, - PCIBIOS_WRITECONFDWORD = 0xb10d -}; +#include "x86.h" // errors go in AH. Just set these up so that word assigns // will work. KISS. @@ -48,9 +38,54 @@ enum { PCIBIOS_BADREG = 0x8700 }; -int int12_handler(struct eregs *regs); -int int1a_handler(struct eregs *regs); -int int15_handler(struct eregs *regs); +int int10_handler(struct eregs *regs) +{ + int res=-1; + static u8 cursor_row=0, cursor_col=0; + switch((regs->eax & 0xff00)>>8) { + case 0x01: // Set cursor shape + res = 0; + break; + case 0x02: // Set cursor position + if (cursor_row != ((regs->edx >> 8) & 0xff) || + cursor_col >= (regs->edx & 0xff)) { + printk(BIOS_INFO, "\n"); + } + cursor_row = (regs->edx >> 8) & 0xff; + cursor_col = regs->edx & 0xff; + res = 0; + break; + case 0x03: // Get cursor position + regs->eax &= 0x00ff; + regs->ecx = 0x0607; + regs->edx = (cursor_row << 8) | cursor_col; + res = 0; + break; + case 0x06: // Scroll up + printk(BIOS_INFO, "\n"); + res = 0; + break; + case 0x08: // Get Character and Mode at Cursor Position + regs->eax = 0x0f00 | 'A'; // White on black 'A' + res = 0; + break; + case 0x09: // Write Character and attribute + case 0x10: // Write Character + printk(BIOS_INFO, "%c", regs->eax & 0xff); + res = 0; + break; + case 0x0f: // Get video mode + regs->eax = 0x5002; //80x25 + regs->ebx &= 0x00ff; + res = 0; + break; + default: + printk(BIOS_WARNING, "Unknown INT10 function %04x!\n", + regs->eax & 0xffff); + break; + } + return res; +} int int12_handler(struct eregs *regs) { @@ -58,6 +93,26 @@ int int12_handler(struct eregs *regs) return 0; } +int int16_handler(struct eregs *regs) +{ + int res=-1; + switch((regs->eax & 0xff00)>>8) { + case 0x00: // Check for Keystroke + regs->eax = 0x6120; // Space Bar, Space + res = 0; + break; + case 0x01: // Check for Keystroke + regs->eflags |= 1<<6; // Zero Flag set (no key available) + res = 0; + break; + default: + printk(BIOS_WARNING, "Unknown INT16 function %04x!\n", + regs->eax & 0xffff); + break; + } + return res; +} + #define PCI_CONFIG_SPACE_TYPE1 (1 << 0) #define PCI_CONFIG_SPACE_TYPE2 (1 << 1) #define PCI_SPECIAL_CYCLE_TYPE1 (1 << 4) @@ -77,7 +132,7 @@ int int1a_handler(struct eregs *regs) u8 byte, reg; switch (func) { - case PCIBIOS_CHECK: + case 0xb101: /* PCIBIOS Check */ regs->edx = 0x20494350; /* ' ICP' */ regs->eax &= 0xffff0000; /* Clear AH / AL */ regs->eax |= PCI_CONFIG_SPACE_TYPE1 | PCI_SPECIAL_CYCLE_TYPE1; @@ -87,7 +142,7 @@ int int1a_handler(struct eregs *regs) regs->edi = 0x00000000; /* protected mode entry */ retval = 0; break; - case PCIBIOS_FINDDEV: + case 0xb102: /* Find Device */ devid = regs->ecx; vendorid = regs->edx; devindex = regs->esi; @@ -114,12 +169,12 @@ int int1a_handler(struct eregs *regs) retval = -1; } break; - case PCIBIOS_READCONFDWORD: - case PCIBIOS_READCONFWORD: - case PCIBIOS_READCONFBYTE: - case PCIBIOS_WRITECONFDWORD: - case PCIBIOS_WRITECONFWORD: - case PCIBIOS_WRITECONFBYTE: + case 0xb10a: /* Read Config Dword */ + case 0xb109: /* Read Config Word */ + case 0xb108: /* Read Config Byte */ + case 0xb10d: /* Write Config Dword */ + case 0xb10c: /* Write Config Word */ + case 0xb10b: /* Write Config Byte */ devfn = regs->ebx & 0xff; bus = regs->ebx >> 8; reg = regs->edi; @@ -133,27 +188,27 @@ int int1a_handler(struct eregs *regs) return retval; } switch (func) { - case PCIBIOS_READCONFBYTE: + case 0xb108: /* Read Config Byte */ byte = pci_read_config8(dev, reg); regs->ecx = byte; break; - case PCIBIOS_READCONFWORD: + case 0xb109: /* Read Config Word */ word = pci_read_config16(dev, reg); regs->ecx = word; break; - case PCIBIOS_READCONFDWORD: + case 0xb10a: /* Read Config Dword */ dword = pci_read_config32(dev, reg); regs->ecx = dword; break; - case PCIBIOS_WRITECONFBYTE: + case 0xb10b: /* Write Config Byte */ byte = regs->ecx; pci_write_config8(dev, reg, byte); break; - case PCIBIOS_WRITECONFWORD: + case 0xb10c: /* Write Config Word */ word = regs->ecx; pci_write_config16(dev, reg, word); break; - case PCIBIOS_WRITECONFDWORD: + case 0xb10d: /* Write Config Dword */ dword = regs->ecx; pci_write_config32(dev, reg, dword); break; @@ -178,42 +233,3 @@ int int1a_handler(struct eregs *regs) return retval; } -int int15_handler(struct eregs *regs) -{ - int res = -1; - - /* This int15 handler is Intel IGD. specific. Other chipsets need other - * handlers. The right way to do this is to move this handler code into - * the mainboard or northbridge code. - * TODO: completely move to mainboards / chipsets. - */ - switch (regs->eax & 0xffff) { - /* And now Intel IGD code */ -#define BOOT_DISPLAY_DEFAULT 0 -#define BOOT_DISPLAY_CRT (1 << 0) -#define BOOT_DISPLAY_TV (1 << 1) -#define BOOT_DISPLAY_EFP (1 << 2) -#define BOOT_DISPLAY_LCD (1 << 3) -#define BOOT_DISPLAY_CRT2 (1 << 4) -#define BOOT_DISPLAY_TV2 (1 << 5) -#define BOOT_DISPLAY_EFP2 (1 << 6) -#define BOOT_DISPLAY_LCD2 (1 << 7) - case 0x5f35: - regs->eax = 0x5f; - regs->ecx = BOOT_DISPLAY_DEFAULT; - res = 0; - break; - case 0x5f40: - regs->eax = 0x5f; - regs->ecx = 3; // This is mainboard specific - printk(BIOS_DEBUG, "DISPLAY=%x\n", regs->ecx); - res = 0; - break; - default: - printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", - regs->eax & 0xffff); - } - - return res; -} - diff --git a/src/devices/oprom/yabel/vbe.c b/src/devices/oprom/yabel/vbe.c index 75e8f3e1c0..27bf5e62b0 100644 --- a/src/devices/oprom/yabel/vbe.c +++ b/src/devices/oprom/yabel/vbe.c @@ -31,13 +31,14 @@ #include "mem.h" #include "interrupt.h" #include "device.h" -#include "vbe.h" #include #include #include "../../src/lib/jpeg.h" +#include + // pointer to VBEInfoBuffer, set by vbe_prepare u8 *vbe_info_buffer = 0; @@ -45,97 +46,6 @@ u8 *vbe_info_buffer = 0; u8 *biosmem; u32 biosmem_size; -// these structs are for input from and output to OF -typedef struct { - u8 display_type; // 0=NONE, 1= analog, 2=digital - u16 screen_width; - u16 screen_height; - u16 screen_linebytes; // bytes per line in framebuffer, may be more than screen_width - u8 color_depth; // color depth in bpp - u32 framebuffer_address; - u8 edid_block_zero[128]; -} __attribute__ ((__packed__)) screen_info_t; - -typedef struct { - u8 signature[4]; - u16 size_reserved; - u8 monitor_number; - u16 max_screen_width; - u8 color_depth; -} __attribute__ ((__packed__)) screen_info_input_t; - -// these structs only store a subset of the VBE defined fields -// only those needed. -typedef struct { - char signature[4]; - u16 version; - u8 *oem_string_ptr; - u32 capabilities; - u16 video_mode_list[256]; // lets hope we never have more than 256 video modes... - u16 total_memory; -} vbe_info_t; - -typedef struct { - u16 mode_attributes; // 00 - u8 win_a_attributes; // 02 - u8 win_b_attributes; // 03 - u16 win_granularity; // 04 - u16 win_size; // 06 - u16 win_a_segment; // 08 - u16 win_b_segment; // 0a - u32 win_func_ptr; // 0c - u16 bytes_per_scanline; // 10 - u16 x_resolution; // 12 - u16 y_resolution; // 14 - u8 x_charsize; // 16 - u8 y_charsize; // 17 - u8 number_of_planes; // 18 - u8 bits_per_pixel; // 19 - u8 number_of_banks; // 20 - u8 memory_model; // 21 - u8 bank_size; // 22 - u8 number_of_image_pages; // 23 - u8 reserved_page; - u8 red_mask_size; - u8 red_mask_pos; - u8 green_mask_size; - u8 green_mask_pos; - u8 blue_mask_size; - u8 blue_mask_pos; - u8 reserved_mask_size; - u8 reserved_mask_pos; - u8 direct_color_mode_info; - u32 phys_base_ptr; - u32 offscreen_mem_offset; - u16 offscreen_mem_size; - u8 reserved[206]; -} __attribute__ ((__packed__)) vesa_mode_info_t; - -typedef struct { - u16 video_mode; - union { - vesa_mode_info_t vesa; - u8 mode_info_block[256]; - }; - // our crap - //u16 attributes; - //u16 linebytes; - //u16 x_resolution; - //u16 y_resolution; - //u8 x_charsize; - //u8 y_charsize; - //u8 bits_per_pixel; - //u8 memory_model; - //u32 framebuffer_address; -} vbe_mode_info_t; - -typedef struct { - u8 port_number; // i.e. monitor number - u8 edid_transfer_time; - u8 ddc_level; - u8 edid_block_zero[128]; -} vbe_ddc_info_t; - static inline u8 vbe_prepare(void) { diff --git a/src/mainboard/kontron/986lcd-m/mainboard.c b/src/mainboard/kontron/986lcd-m/mainboard.c index 1d0c4946b2..d7b1f13cc1 100644 --- a/src/mainboard/kontron/986lcd-m/mainboard.c +++ b/src/mainboard/kontron/986lcd-m/mainboard.c @@ -25,6 +25,7 @@ #endif #include #include +#include #include "chip.h" #if CONFIG_PCI_OPTION_ROM_RUN_YABEL @@ -70,6 +71,53 @@ static void int15_install(void) } #endif +#if defined(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) && CONFIG_PCI_OPTION_ROM_RUN_REALMODE +static int int15_handler(struct eregs *regs) +{ + int res = -1; + + /* This int15 handler is Intel IGD. specific. Other chipsets need other + * handlers. The right way to do this is to move this handler code into + * the mainboard or northbridge code. + * TODO: completely move to mainboards / chipsets. + */ + switch (regs->eax & 0xffff) { + /* And now Intel IGD code */ +#define BOOT_DISPLAY_DEFAULT 0 +#define BOOT_DISPLAY_CRT (1 << 0) +#define BOOT_DISPLAY_TV (1 << 1) +#define BOOT_DISPLAY_EFP (1 << 2) +#define BOOT_DISPLAY_LCD (1 << 3) +#define BOOT_DISPLAY_CRT2 (1 << 4) +#define BOOT_DISPLAY_TV2 (1 << 5) +#define BOOT_DISPLAY_EFP2 (1 << 6) +#define BOOT_DISPLAY_LCD2 (1 << 7) + case 0x5f35: + regs->eax = 0x5f; + regs->ecx = BOOT_DISPLAY_DEFAULT; + res = 0; + break; + case 0x5f40: + regs->eax = 0x5f; + regs->ecx = 3; // This is mainboard specific + printk(BIOS_DEBUG, "DISPLAY=%x\n", regs->ecx); + res = 0; + break; + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", + regs->eax & 0xffff); + } + + return res; +} + +static void int15_install(void) +{ + mainboard_interrupt_handlers(0x15, &int15_handler); +} +#endif + + /* Hardware Monitor */ static u16 hwm_base = 0xa00; @@ -221,7 +269,7 @@ static void verb_setup(void) static void mainboard_enable(device_t dev) { -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE /* Install custom int15 handler for VGA OPROM */ int15_install(); #endif diff --git a/src/mainboard/roda/rk886ex/mainboard.c b/src/mainboard/roda/rk886ex/mainboard.c index 2c5b5e3d71..d87d712259 100644 --- a/src/mainboard/roda/rk886ex/mainboard.c +++ b/src/mainboard/roda/rk886ex/mainboard.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #if CONFIG_PCI_OPTION_ROM_RUN_YABEL @@ -99,6 +100,52 @@ static void int15_install(void) } #endif +#if CONFIG_PCI_OPTION_ROM_RUN_REALMODE +static int int15_handler(struct eregs *regs) +{ + int res = -1; + + /* This int15 handler is Intel IGD. specific. Other chipsets need other + * handlers. The right way to do this is to move this handler code into + * the mainboard or northbridge code. + * TODO: completely move to mainboards / chipsets. + */ + switch (regs->eax & 0xffff) { + /* And now Intel IGD code */ +#define BOOT_DISPLAY_DEFAULT 0 +#define BOOT_DISPLAY_CRT (1 << 0) +#define BOOT_DISPLAY_TV (1 << 1) +#define BOOT_DISPLAY_EFP (1 << 2) +#define BOOT_DISPLAY_LCD (1 << 3) +#define BOOT_DISPLAY_CRT2 (1 << 4) +#define BOOT_DISPLAY_TV2 (1 << 5) +#define BOOT_DISPLAY_EFP2 (1 << 6) +#define BOOT_DISPLAY_LCD2 (1 << 7) + case 0x5f35: + regs->eax = 0x5f; + regs->ecx = BOOT_DISPLAY_DEFAULT; + res = 0; + break; + case 0x5f40: + regs->eax = 0x5f; + regs->ecx = 3; // This is mainboard specific + printk(BIOS_DEBUG, "DISPLAY=%x\n", regs->ecx); + res = 0; + break; + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", + regs->eax & 0xffff); + } + + return res; +} + +static void int15_install(void) +{ + mainboard_interrupt_handlers(0x15, &int15_handler); +} +#endif + #if DUMP_RUNTIME_REGISTERS static void dump_runtime_registers(void) { @@ -125,7 +172,7 @@ static void mainboard_enable(device_t dev) /* Disable Dummy DCC -> GP45 = 1 */ outb(inb(0x60f) | (1 << 5), 0x60f); -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE /* Install custom int15 handler for VGA OPROM */ int15_install(); #endif