anymore so this ugly hack is no longer needed. Signed-off-by: Stefan Reinauer <stepan@coresystems.de> Acked-by: Peter Stuge <peter@stuge.se> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5040 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
		
			
				
	
	
		
			676 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			676 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/******************************************************************************
 | 
						|
 * Copyright (c) 2004, 2008 IBM Corporation
 | 
						|
 * Copyright (c) 2008, 2009 Pattrick Hueper <phueper@hueper.net>
 | 
						|
 * 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
 | 
						|
 *****************************************************************************/
 | 
						|
 | 
						|
#include "compat/rtas.h"
 | 
						|
 | 
						|
#include "biosemu.h"
 | 
						|
#include "mem.h"
 | 
						|
#include "device.h"
 | 
						|
#include "debug.h"
 | 
						|
#include "pmm.h"
 | 
						|
 | 
						|
#include <x86emu/x86emu.h>
 | 
						|
#include "../x86emu/prim_ops.h"
 | 
						|
 | 
						|
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | 
						|
#include <device/pci.h>
 | 
						|
#include <device/pci_ops.h>
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
//setup to run the code at the address, that the Interrupt Vector points to...
 | 
						|
void
 | 
						|
setupInt(int intNum)
 | 
						|
{
 | 
						|
	DEBUG_PRINTF_INTR("%s(%x): executing interrupt handler @%08x\n",
 | 
						|
			  __func__, intNum, my_rdl(intNum * 4));
 | 
						|
	// push current R_FLG... will be popped by IRET
 | 
						|
	push_word((u16) M.x86.R_FLG);
 | 
						|
	CLEAR_FLAG(F_IF);
 | 
						|
	CLEAR_FLAG(F_TF);
 | 
						|
	// push current CS:IP to the stack, will be popped by IRET
 | 
						|
	push_word(M.x86.R_CS);
 | 
						|
	push_word(M.x86.R_IP);
 | 
						|
	// set CS:IP to the interrupt handler address... so the next executed instruction will
 | 
						|
	// be the interrupt handler
 | 
						|
	M.x86.R_CS = my_rdw(intNum * 4 + 2);
 | 
						|
	M.x86.R_IP = my_rdw(intNum * 4);
 | 
						|
}
 | 
						|
 | 
						|
// handle int10 (VGA BIOS Interrupt)
 | 
						|
void
 | 
						|
handleInt10(void)
 | 
						|
{
 | 
						|
	// the data for INT10 is stored in BDA (0000:0400h) offset 49h-66h
 | 
						|
	// function number in AH
 | 
						|
	//DEBUG_PRINTF_CS_IP("%s:\n", __func__);
 | 
						|
	//x86emu_dump_xregs();
 | 
						|
	//if ((M.x86.R_IP == 0x32c2) && (M.x86.R_SI == 0x1ce2)){
 | 
						|
	//X86EMU_trace_on();
 | 
						|
	//M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
 | 
						|
	//}
 | 
						|
	switch (M.x86.R_AH) {
 | 
						|
	case 0x00:
 | 
						|
		// set video mode
 | 
						|
		// BDA offset 49h is current video mode
 | 
						|
		my_wrb(0x449, M.x86.R_AL);
 | 
						|
		if (M.x86.R_AL > 7)
 | 
						|
			M.x86.R_AL = 0x20;
 | 
						|
		else if (M.x86.R_AL == 6)
 | 
						|
			M.x86.R_AL = 0x3f;
 | 
						|
		else
 | 
						|
			M.x86.R_AL = 0x30;
 | 
						|
		break;
 | 
						|
	case 0x01:
 | 
						|
		// set cursor shape
 | 
						|
		// ignore
 | 
						|
		break;
 | 
						|
	case 0x02:
 | 
						|
		// set cursor position
 | 
						|
		// BH: pagenumber, DX: cursor_pos (DH:row, DL:col)
 | 
						|
		// BDA offset 50h-60h are 8 cursor position words for
 | 
						|
		// eight possible video pages
 | 
						|
		my_wrw(0x450 + (M.x86.R_BH * 2), M.x86.R_DX);
 | 
						|
		break;
 | 
						|
	case 0x03:
 | 
						|
		//get cursor position
 | 
						|
		// BH: pagenumber
 | 
						|
		// BDA offset 50h-60h are 8 cursor position words for
 | 
						|
		// eight possible video pages
 | 
						|
		M.x86.R_AX = 0;
 | 
						|
		M.x86.R_CH = 0;	// start scan line ???
 | 
						|
		M.x86.R_CL = 0;	// end scan line ???
 | 
						|
		M.x86.R_DX = my_rdw(0x450 + (M.x86.R_BH * 2));
 | 
						|
		break;
 | 
						|
	case 0x05:
 | 
						|
		// set active page
 | 
						|
		// BDA offset 62h is current page number
 | 
						|
		my_wrb(0x462, M.x86.R_AL);
 | 
						|
		break;
 | 
						|
	case 0x06:
 | 
						|
		//scroll up windows
 | 
						|
		break;
 | 
						|
	case 0x07:
 | 
						|
		//scroll down windows
 | 
						|
		break;
 | 
						|
	case 0x08:
 | 
						|
		//read character and attribute at position
 | 
						|
		M.x86.R_AH = 0x07;	// white-on-black
 | 
						|
		M.x86.R_AL = 0x20;	// a space...
 | 
						|
		break;
 | 
						|
	case 0x09:
 | 
						|
		// write character and attribute
 | 
						|
		//AL: char, BH: page number, BL: attribute, CX: number of times to write
 | 
						|
		//BDA offset 62h is current page number
 | 
						|
		CHECK_DBG(DEBUG_PRINT_INT10) {
 | 
						|
			u32 i = 0;
 | 
						|
			if (M.x86.R_BH == my_rdb(0x462)) {
 | 
						|
				for (i = 0; i < M.x86.R_CX; i++)
 | 
						|
					printf("%c", M.x86.R_AL);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case 0x0a:
 | 
						|
		// write character
 | 
						|
		//AL: char, BH: page number, BL: attribute, CX: number of times to write
 | 
						|
		//BDA offset 62h is current page number
 | 
						|
		CHECK_DBG(DEBUG_PRINT_INT10) {
 | 
						|
			u32 i = 0;
 | 
						|
			if (M.x86.R_BH == my_rdb(0x462)) {
 | 
						|
				for (i = 0; i < M.x86.R_CX; i++)
 | 
						|
					printf("%c", M.x86.R_AL);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case 0x0e:
 | 
						|
		// teletype output: write character and advance cursor...
 | 
						|
		//AL: char, BH: page number, BL: attribute
 | 
						|
		//BDA offset 62h is current page number
 | 
						|
		CHECK_DBG(DEBUG_PRINT_INT10) {
 | 
						|
			// we ignore the pagenumber on this call...
 | 
						|
			//if (M.x86.R_BH == my_rdb(0x462))
 | 
						|
			{
 | 
						|
				printf("%c", M.x86.R_AL);
 | 
						|
				// for debugging, to read all lines
 | 
						|
				//if (M.x86.R_AL == 0xd) // carriage return
 | 
						|
				//      printf("\n");
 | 
						|
			}
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case 0x0f:
 | 
						|
		// get video mode
 | 
						|
		// BDA offset 49h is current video mode
 | 
						|
		// BDA offset 62h is current page number
 | 
						|
		// BDA offset 4ah is columns on screen
 | 
						|
		M.x86.R_AH = 80;	//number of character columns... we hardcode it to 80
 | 
						|
		M.x86.R_AL = my_rdb(0x449);
 | 
						|
		M.x86.R_BH = my_rdb(0x462);
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		printf("%s(): unknown function (%x) for int10 handler.\n",
 | 
						|
		       __func__, M.x86.R_AH);
 | 
						|
		DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
 | 
						|
				  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
 | 
						|
				  M.x86.R_DX);
 | 
						|
		HALT_SYS();
 | 
						|
		break;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// this table translates ASCII chars into their XT scan codes:
 | 
						|
static u8 keycode_table[256] = {
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 0 - 7
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 8 - 15
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 16 - 23
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 24 - 31
 | 
						|
	0x39, 0x02, 0x28, 0x04, 0x05, 0x06, 0x08, 0x28,	// 32 - 39
 | 
						|
	0x0a, 0x0b, 0x09, 0x2b, 0x33, 0x0d, 0x34, 0x35,	// 40 - 47
 | 
						|
	0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,	// 48 - 55
 | 
						|
	0x09, 0x0a, 0x27, 0x27, 0x33, 0x2b, 0x34, 0x35,	// 56 - 63
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 64 - 71
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 72 - 79
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 80 - 87
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 88 - 95
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 96 - 103
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 104 - 111
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 112 - 119
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// 120 - 127
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// ...
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
}
 | 
						|
 | 
						|
;
 | 
						|
 | 
						|
void
 | 
						|
translate_keycode(u64 * keycode)
 | 
						|
{
 | 
						|
	u8 scan_code = 0;
 | 
						|
	u8 char_code = 0;
 | 
						|
	if (*keycode < 256) {
 | 
						|
		scan_code = keycode_table[*keycode];
 | 
						|
		char_code = (u8) * keycode & 0xff;
 | 
						|
	} else {
 | 
						|
		switch (*keycode) {
 | 
						|
		case 0x1b50:
 | 
						|
			// F1
 | 
						|
			scan_code = 0x3b;
 | 
						|
			char_code = 0x0;
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			printf("%s(): unknown multibyte keycode: %llx\n",
 | 
						|
			       __func__, *keycode);
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	//assemble scan/char code in keycode
 | 
						|
	*keycode = (u64) ((((u16) scan_code) << 8) | char_code);
 | 
						|
}
 | 
						|
 | 
						|
// handle int16 (Keyboard BIOS Interrupt)
 | 
						|
void
 | 
						|
handleInt16(void)
 | 
						|
{
 | 
						|
	// keyboard buffer is in BIOS Memory Area:
 | 
						|
	// offset 0x1a (WORD) pointer to next char in keybuffer
 | 
						|
	// offset 0x1c (WORD) pointer to next insert slot in keybuffer
 | 
						|
	// offset 0x1e-0x3e: 16 WORD Ring Buffer
 | 
						|
	// since we currently always read the char from the FW buffer,
 | 
						|
	// we misuse the ring buffer, we use it as pointer to a u64 that stores
 | 
						|
	// multi-byte keys (e.g. special keys in VT100 terminal)
 | 
						|
	// and as long as a key is available (not 0) we dont read further keys
 | 
						|
	u64 *keycode = (u64 *) (M.mem_base + 0x41e);
 | 
						|
	s8 c;
 | 
						|
	// function number in AH
 | 
						|
	DEBUG_PRINTF_INTR("%s(): Keyboard Interrupt: function: %x.\n",
 | 
						|
			  __func__, M.x86.R_AH);
 | 
						|
	DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n", M.x86.R_AX,
 | 
						|
			  M.x86.R_BX, M.x86.R_CX, M.x86.R_DX);
 | 
						|
	switch (M.x86.R_AH) {
 | 
						|
	case 0x00:
 | 
						|
		// get keystroke
 | 
						|
		if (*keycode) {
 | 
						|
			M.x86.R_AX = (u16) * keycode;
 | 
						|
			// clear keycode
 | 
						|
			*keycode = 0;
 | 
						|
		} else {
 | 
						|
			M.x86.R_AH = 0x61;	// scancode for space key
 | 
						|
			M.x86.R_AL = 0x20;	// a space
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case 0x01:
 | 
						|
		// check keystroke
 | 
						|
		// ZF set = no keystroke
 | 
						|
		// read first byte of key code
 | 
						|
		if (*keycode) {
 | 
						|
			// already read, but not yet taken
 | 
						|
			CLEAR_FLAG(F_ZF);
 | 
						|
			M.x86.R_AX = (u16) * keycode;
 | 
						|
		} else {
 | 
						|
			/* TODO: we need getchar... */
 | 
						|
			c = -1; //getchar();
 | 
						|
			if (c == -1) {
 | 
						|
				// no key available
 | 
						|
				SET_FLAG(F_ZF);
 | 
						|
			} else {
 | 
						|
				*keycode = c;
 | 
						|
 | 
						|
				// since after an ESC it may take a while to receive the next char,
 | 
						|
				// we send something that is not shown on the screen, and then try to get
 | 
						|
				// the next char
 | 
						|
				// TODO: only after ESC?? what about other multibyte keys
 | 
						|
				printf("tt%c%c", 0x08, 0x08);	// 0x08 == Backspace
 | 
						|
 | 
						|
				/* TODO: we need getchar... */
 | 
						|
				while ((c = -1 /*getchar()*/) != -1) {
 | 
						|
					*keycode = (*keycode << 8) | c;
 | 
						|
					DEBUG_PRINTF(" key read: %0llx\n",
 | 
						|
						     *keycode);
 | 
						|
				}
 | 
						|
				translate_keycode(keycode);
 | 
						|
				DEBUG_PRINTF(" translated key: %0llx\n",
 | 
						|
					     *keycode);
 | 
						|
				if (*keycode == 0) {
 | 
						|
					//not found
 | 
						|
					SET_FLAG(F_ZF);
 | 
						|
				} else {
 | 
						|
					CLEAR_FLAG(F_ZF);
 | 
						|
					M.x86.R_AX = (u16) * keycode;
 | 
						|
					//X86EMU_trace_on();
 | 
						|
					//M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		printf("%s(): unknown function (%x) for int16 handler.\n",
 | 
						|
		       __func__, M.x86.R_AH);
 | 
						|
		DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
 | 
						|
				  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
 | 
						|
				  M.x86.R_DX);
 | 
						|
		HALT_SYS();
 | 
						|
		break;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// handle int1a (PCI BIOS Interrupt)
 | 
						|
void
 | 
						|
handleInt1a(void)
 | 
						|
{
 | 
						|
	// function number in AX
 | 
						|
	u8 bus, devfn, offs;
 | 
						|
	struct device* dev;
 | 
						|
	switch (M.x86.R_AX) {
 | 
						|
	case 0xb101:
 | 
						|
		// Installation check
 | 
						|
		CLEAR_FLAG(F_CF);	// clear CF
 | 
						|
		M.x86.R_EDX = 0x20494350;	// " ICP" endian swapped "PCI "
 | 
						|
		M.x86.R_AL = 0x1;	// Config Space Mechanism 1 supported
 | 
						|
		M.x86.R_BX = 0x0210;	// PCI Interface Level Version 2.10
 | 
						|
		M.x86.R_CL = 0xff;	// number of last PCI Bus in system TODO: check!
 | 
						|
		break;
 | 
						|
	case 0xb102:
 | 
						|
		// Find PCI Device
 | 
						|
		// device_id in CX, vendor_id in DX
 | 
						|
		// device index in SI (i.e. if multiple devices with same vendor/device id
 | 
						|
		// are connected). We currently only support device index 0
 | 
						|
		//
 | 
						|
		DEBUG_PRINTF_INTR("%s(): function: %x: PCI Find Device\n",
 | 
						|
				  __func__, M.x86.R_AX);
 | 
						|
		/* FixME: support SI != 0 */
 | 
						|
#if defined(CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES) && CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES==1
 | 
						|
		dev = dev_find_device(M.x86.R_DX, M.x86.R_CX, 0);
 | 
						|
		if (dev != 0) {
 | 
						|
			DEBUG_PRINTF_INTR
 | 
						|
			    ("%s(): function %x: PCI Find Device --> 0x%04x\n",
 | 
						|
			     __func__, M.x86.R_AX, M.x86.R_BX);
 | 
						|
 | 
						|
			M.x86.R_BH = dev->bus->secondary;
 | 
						|
			M.x86.R_BL = dev->path.pci.devfn;
 | 
						|
			M.x86.R_AH = 0x00; // return code: success
 | 
						|
			CLEAR_FLAG(F_CF);
 | 
						|
#else
 | 
						|
		// only allow the device to find itself...
 | 
						|
		if ((M.x86.R_CX == bios_device.pci_device_id)
 | 
						|
		   && (M.x86.R_DX == bios_device.pci_vendor_id)
 | 
						|
		   // device index must be 0
 | 
						|
		   && (M.x86.R_SI == 0)) {
 | 
						|
			CLEAR_FLAG(F_CF);
 | 
						|
			M.x86.R_AH = 0x00;      // return code: success
 | 
						|
			M.x86.R_BH = bios_device.bus;
 | 
						|
			M.x86.R_BL = bios_device.devfn;
 | 
						|
#endif
 | 
						|
		} else {
 | 
						|
			DEBUG_PRINTF_INTR
 | 
						|
			    ("%s(): function %x: invalid device/vendor/device index! (%04x/%04x/%02x expected: %04x/%04x/00) \n",
 | 
						|
			     __func__, M.x86.R_AX, M.x86.R_CX, M.x86.R_DX,
 | 
						|
			     M.x86.R_SI, bios_device.pci_device_id,
 | 
						|
			     bios_device.pci_vendor_id);
 | 
						|
 | 
						|
			SET_FLAG(F_CF);
 | 
						|
			M.x86.R_AH = 0x86;	// return code: device not found
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case 0xb108:		//read configuration byte
 | 
						|
	case 0xb109:		//read configuration word
 | 
						|
	case 0xb10a:		//read configuration dword
 | 
						|
		bus = M.x86.R_BH;
 | 
						|
		devfn = M.x86.R_BL;
 | 
						|
		offs = M.x86.R_DI;
 | 
						|
		DEBUG_PRINTF_INTR("%s(): function: %x: PCI Config Read from device: bus: %02x, devfn: %02x, offset: %02x\n",
 | 
						|
				  __func__, M.x86.R_AX, bus, devfn, offs);
 | 
						|
#if defined(CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES) && CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES==1
 | 
						|
		dev = dev_find_slot(bus, devfn);
 | 
						|
		DEBUG_PRINTF_INTR("%s(): function: %x: dev_find_slot() returned: %s\n",
 | 
						|
				  __func__, M.x86.R_AX, dev_path(dev));
 | 
						|
		if (dev == 0) {
 | 
						|
			// fail accesses to non-existent devices...
 | 
						|
#else
 | 
						|
		dev = bios_device.dev;
 | 
						|
		if ((bus != bios_device.bus)
 | 
						|
		     || (devfn != bios_device.devfn)) {
 | 
						|
			// fail accesses to any device but ours...
 | 
						|
#endif
 | 
						|
			printf
 | 
						|
			    ("%s(): Config read access invalid device! bus: %02x (%02x), devfn: %02x (%02x), offs: %02x\n",
 | 
						|
			     __func__, bus, bios_device.bus, devfn,
 | 
						|
			     bios_device.devfn, offs);
 | 
						|
			SET_FLAG(F_CF);
 | 
						|
			M.x86.R_AH = 0x87;	//return code: bad pci register
 | 
						|
			HALT_SYS();
 | 
						|
			return;
 | 
						|
		} else {
 | 
						|
			switch (M.x86.R_AX) {
 | 
						|
			case 0xb108:
 | 
						|
				M.x86.R_CL =
 | 
						|
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | 
						|
					pci_read_config8(dev, offs);
 | 
						|
#else					
 | 
						|
				    (u8) rtas_pci_config_read(bios_device.
 | 
						|
								   puid, 1,
 | 
						|
								   bus, devfn,
 | 
						|
								   offs);
 | 
						|
#endif
 | 
						|
				DEBUG_PRINTF_INTR
 | 
						|
				    ("%s(): function %x: PCI Config Read @%02x --> 0x%02x\n",
 | 
						|
				     __func__, M.x86.R_AX, offs,
 | 
						|
				     M.x86.R_CL);
 | 
						|
				break;
 | 
						|
			case 0xb109:
 | 
						|
				M.x86.R_CX =
 | 
						|
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | 
						|
					pci_read_config16(dev, offs);
 | 
						|
#else					
 | 
						|
				    (u16) rtas_pci_config_read(bios_device.
 | 
						|
								    puid, 2,
 | 
						|
								    bus, devfn,
 | 
						|
								    offs);
 | 
						|
#endif
 | 
						|
				DEBUG_PRINTF_INTR
 | 
						|
				    ("%s(): function %x: PCI Config Read @%02x --> 0x%04x\n",
 | 
						|
				     __func__, M.x86.R_AX, offs,
 | 
						|
				     M.x86.R_CX);
 | 
						|
				break;
 | 
						|
			case 0xb10a:
 | 
						|
				M.x86.R_ECX =
 | 
						|
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | 
						|
					pci_read_config32(dev, offs);
 | 
						|
#else					
 | 
						|
				    (u32) rtas_pci_config_read(bios_device.
 | 
						|
								    puid, 4,
 | 
						|
								    bus, devfn,
 | 
						|
								    offs);
 | 
						|
#endif
 | 
						|
				DEBUG_PRINTF_INTR
 | 
						|
				    ("%s(): function %x: PCI Config Read @%02x --> 0x%08x\n",
 | 
						|
				     __func__, M.x86.R_AX, offs,
 | 
						|
				     M.x86.R_ECX);
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			CLEAR_FLAG(F_CF);
 | 
						|
			M.x86.R_AH = 0x0;	// return code: success
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case 0xb10b:		//write configuration byte
 | 
						|
	case 0xb10c:		//write configuration word
 | 
						|
	case 0xb10d:		//write configuration dword
 | 
						|
		bus = M.x86.R_BH;
 | 
						|
		devfn = M.x86.R_BL;
 | 
						|
		offs = M.x86.R_DI;
 | 
						|
		if ((bus != bios_device.bus)
 | 
						|
		    || (devfn != bios_device.devfn)) {
 | 
						|
			// fail accesses to any device but ours...
 | 
						|
			printf
 | 
						|
			    ("%s(): Config read access invalid! bus: %x (%x), devfn: %x (%x), offs: %x\n",
 | 
						|
			     __func__, bus, bios_device.bus, devfn,
 | 
						|
			     bios_device.devfn, offs);
 | 
						|
			SET_FLAG(F_CF);
 | 
						|
			M.x86.R_AH = 0x87;	//return code: bad pci register
 | 
						|
			HALT_SYS();
 | 
						|
			return;
 | 
						|
		} else {
 | 
						|
			switch (M.x86.R_AX) {
 | 
						|
			case 0xb10b:
 | 
						|
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | 
						|
					pci_write_config8(bios_device.dev, offs, M.x86.R_CL);
 | 
						|
#else					
 | 
						|
				rtas_pci_config_write(bios_device.puid, 1, bus,
 | 
						|
						      devfn, offs, M.x86.R_CL);
 | 
						|
#endif
 | 
						|
				DEBUG_PRINTF_INTR
 | 
						|
				    ("%s(): function %x: PCI Config Write @%02x <-- 0x%02x\n",
 | 
						|
				     __func__, M.x86.R_AX, offs,
 | 
						|
				     M.x86.R_CL);
 | 
						|
				break;
 | 
						|
			case 0xb10c:
 | 
						|
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | 
						|
					pci_write_config16(bios_device.dev, offs, M.x86.R_CX);
 | 
						|
#else					
 | 
						|
				rtas_pci_config_write(bios_device.puid, 2, bus,
 | 
						|
						      devfn, offs, M.x86.R_CX);
 | 
						|
#endif
 | 
						|
				DEBUG_PRINTF_INTR
 | 
						|
				    ("%s(): function %x: PCI Config Write @%02x <-- 0x%04x\n",
 | 
						|
				     __func__, M.x86.R_AX, offs,
 | 
						|
				     M.x86.R_CX);
 | 
						|
				break;
 | 
						|
			case 0xb10d:
 | 
						|
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | 
						|
					pci_write_config32(bios_device.dev, offs, M.x86.R_ECX);
 | 
						|
#else					
 | 
						|
				rtas_pci_config_write(bios_device.puid, 4, bus,
 | 
						|
						      devfn, offs, M.x86.R_ECX);
 | 
						|
#endif
 | 
						|
				DEBUG_PRINTF_INTR
 | 
						|
				    ("%s(): function %x: PCI Config Write @%02x <-- 0x%08x\n",
 | 
						|
				     __func__, M.x86.R_AX, offs,
 | 
						|
				     M.x86.R_ECX);
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			CLEAR_FLAG(F_CF);
 | 
						|
			M.x86.R_AH = 0x0;	// return code: success
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		printf("%s(): unknown function (%x) for int1a handler.\n",
 | 
						|
		       __func__, M.x86.R_AX);
 | 
						|
		DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
 | 
						|
				  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
 | 
						|
				  M.x86.R_DX);
 | 
						|
		HALT_SYS();
 | 
						|
		break;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// main Interrupt Handler routine, should be registered as x86emu interrupt handler
 | 
						|
void
 | 
						|
handleInterrupt(int intNum)
 | 
						|
{
 | 
						|
	u8 int_handled = 0;
 | 
						|
#ifndef DEBUG_PRINT_INT10
 | 
						|
	// this printf makes output by int 10 unreadable...
 | 
						|
	// so we only enable it, if int10 print is disabled
 | 
						|
	DEBUG_PRINTF_INTR("%s(%x)\n", __func__, intNum);
 | 
						|
#endif
 | 
						|
 | 
						|
	/* check wether this interrupt has a function pointer set in yabel_intFuncArray and run that */
 | 
						|
	if (yabel_intFuncArray[intNum]) {
 | 
						|
		DEBUG_PRINTF_INTR("%s(%x) intHandler overridden, calling it...\n", __func__, intNum);
 | 
						|
		int_handled = (*yabel_intFuncArray[intNum])();
 | 
						|
	} else {
 | 
						|
		switch (intNum) {
 | 
						|
		case 0x10:		//BIOS video interrupt
 | 
						|
		case 0x42:		// INT 10h relocated by EGA/VGA BIOS
 | 
						|
		case 0x6d:		// INT 10h relocated by VGA BIOS
 | 
						|
			// get interrupt vector from IDT (4 bytes per Interrupt starting at address 0
 | 
						|
			if ((my_rdl(intNum * 4) == 0xF000F065) ||	//F000:F065 is default BIOS interrupt handler address
 | 
						|
			    (my_rdl(intNum * 4) == 0xF4F4F4F4))	//invalid
 | 
						|
			{
 | 
						|
#if 0
 | 
						|
				// ignore interrupt...
 | 
						|
				DEBUG_PRINTF_INTR
 | 
						|
				    ("%s(%x): invalid interrupt Vector (%08x) found, interrupt ignored...\n",
 | 
						|
				     __func__, intNum, my_rdl(intNum * 4));
 | 
						|
				DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
 | 
						|
						  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
 | 
						|
						  M.x86.R_DX);
 | 
						|
				//HALT_SYS();
 | 
						|
#endif
 | 
						|
				handleInt10();
 | 
						|
				int_handled = 1;
 | 
						|
			}
 | 
						|
			break;
 | 
						|
		case 0x16:
 | 
						|
			// Keyboard BIOS Interrupt
 | 
						|
			handleInt16();
 | 
						|
			int_handled = 1;
 | 
						|
			break;
 | 
						|
		case 0x1a:
 | 
						|
			// PCI BIOS Interrupt
 | 
						|
			handleInt1a();
 | 
						|
			int_handled = 1;
 | 
						|
			break;
 | 
						|
		case PMM_INT_NUM:
 | 
						|
			/* the selfdefined PMM INT number, this is called by the code in PMM struct, it 
 | 
						|
			 * is handled by pmm_handleInt()
 | 
						|
			 */
 | 
						|
			pmm_handleInt();
 | 
						|
			int_handled = 1;
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			printf("Interrupt %#x (Vector: %x) not implemented\n", intNum,
 | 
						|
			       my_rdl(intNum * 4));
 | 
						|
			DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
 | 
						|
					  M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
 | 
						|
					  M.x86.R_DX);
 | 
						|
			int_handled = 1;
 | 
						|
			HALT_SYS();
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	// if we did not handle the interrupt, jump to the interrupt vector...
 | 
						|
	if (!int_handled) {
 | 
						|
		setupInt(intNum);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// prepare and execute Interrupt 10 (VGA Interrupt)
 | 
						|
void
 | 
						|
runInt10(void)
 | 
						|
{
 | 
						|
	// Initialize stack and data segment
 | 
						|
	M.x86.R_SS = STACK_SEGMENT;
 | 
						|
	M.x86.R_DS = DATA_SEGMENT;
 | 
						|
	M.x86.R_SP = STACK_START_OFFSET;
 | 
						|
 | 
						|
	// push a HLT instruction and a pointer to it onto the stack
 | 
						|
	// any return will pop the pointer and jump to the HLT, thus
 | 
						|
	// exiting (more or less) cleanly
 | 
						|
	push_word(0xf4f4);	//F4=HLT
 | 
						|
	//push_word(M.x86.R_SS);
 | 
						|
	//push_word(M.x86.R_SP + 2);
 | 
						|
 | 
						|
	// setupInt will push the current CS and IP to the stack to return to it,
 | 
						|
	// but we want to halt, so set CS:IP to the HLT instruction we just pushed
 | 
						|
	// to the stack
 | 
						|
	M.x86.R_CS = M.x86.R_SS;
 | 
						|
	M.x86.R_IP = M.x86.R_SP;	// + 4;
 | 
						|
 | 
						|
	CHECK_DBG(DEBUG_TRACE_X86EMU) {
 | 
						|
		X86EMU_trace_on();
 | 
						|
	}
 | 
						|
	CHECK_DBG(DEBUG_JMP) {
 | 
						|
		M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
 | 
						|
		M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
 | 
						|
		M.x86.debug |= DEBUG_TRACECALL_F;
 | 
						|
		M.x86.debug |= DEBUG_TRACECALL_REGS_F;
 | 
						|
	}
 | 
						|
	setupInt(0x10);
 | 
						|
	DEBUG_PRINTF_INTR("%s(): starting execution of INT10...\n",
 | 
						|
			  __func__);
 | 
						|
	X86EMU_exec();
 | 
						|
	DEBUG_PRINTF_INTR("%s(): execution finished\n", __func__);
 | 
						|
}
 | 
						|
 | 
						|
// prepare and execute Interrupt 13 (Disk Interrupt)
 | 
						|
void
 | 
						|
runInt13(void)
 | 
						|
{
 | 
						|
	// Initialize stack and data segment
 | 
						|
	M.x86.R_SS = STACK_SEGMENT;
 | 
						|
	M.x86.R_DS = DATA_SEGMENT;
 | 
						|
	M.x86.R_SP = STACK_START_OFFSET;
 | 
						|
 | 
						|
	// push a HLT instruction and a pointer to it onto the stack
 | 
						|
	// any return will pop the pointer and jump to the HLT, thus
 | 
						|
	// exiting (more or less) cleanly
 | 
						|
	push_word(0xf4f4);	//F4=HLT
 | 
						|
	//push_word(M.x86.R_SS);
 | 
						|
	//push_word(M.x86.R_SP + 2);
 | 
						|
 | 
						|
	// setupInt will push the current CS and IP to the stack to return to it,
 | 
						|
	// but we want to halt, so set CS:IP to the HLT instruction we just pushed
 | 
						|
	// to the stack
 | 
						|
	M.x86.R_CS = M.x86.R_SS;
 | 
						|
	M.x86.R_IP = M.x86.R_SP;
 | 
						|
 | 
						|
	CHECK_DBG(DEBUG_TRACE_X86EMU) {
 | 
						|
		X86EMU_trace_on();
 | 
						|
	}
 | 
						|
	CHECK_DBG(DEBUG_JMP) {
 | 
						|
		M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
 | 
						|
		M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
 | 
						|
		M.x86.debug |= DEBUG_TRACECALL_F;
 | 
						|
		M.x86.debug |= DEBUG_TRACECALL_REGS_F;
 | 
						|
	}
 | 
						|
 | 
						|
	setupInt(0x13);
 | 
						|
	DEBUG_PRINTF_INTR("%s(): starting execution of INT13...\n",
 | 
						|
			  __func__);
 | 
						|
	X86EMU_exec();
 | 
						|
	DEBUG_PRINTF_INTR("%s(): execution finished\n", __func__);
 | 
						|
}
 |