DevLPC.cpp revision b0ef8e9a92e464839d4cb902775788a5fb738451
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/* $Id$ */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/** @file
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * DevLPC - LPC device emulation
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
145f3def013dbea3281a655f726aba48cee34ea9vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/*
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Copyright (C) 2006-2010 Oracle Corporation
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * available from http://www.virtualbox.org. This file is free software;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * you can redistribute it and/or modify it under the terms of the GNU
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * General Public License (GPL) as published by the Free Software
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * --------------------------------------------------------------------
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * This code is based on:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Low Pin Count emulation
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Copyright (c) 2007 Alexander Graf
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * This library is free software; you can redistribute it and/or
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * modify it under the terms of the GNU Lesser General Public
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * License as published by the Free Software Foundation; either
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * version 2 of the License, or (at your option) any later version.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * This library is distributed in the hope that it will be useful,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Lesser General Public License for more details.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * You should have received a copy of the GNU Lesser General Public
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * License along with this library; if not, write to the Free Software
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * *****************************************************************
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * This driver emulates an ICH-7 LPC partially. The LPC is basically the
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * same as the ISA-bridge in the existing PIIX implementation, but
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * more recent and includes support for HPET and Power Management.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/*******************************************************************************
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync* Header Files *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync*******************************************************************************/
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#define LOG_GROUP LOG_GROUP_DEV_LPC
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#include <VBox/pdmdev.h>
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#include <VBox/log.h>
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#include <VBox/stam.h>
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#include <iprt/assert.h>
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#include <iprt/string.h>
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
145f3def013dbea3281a655f726aba48cee34ea9vboxsync#include "../Builtins2.h"
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#define RCBA_BASE 0xFED1C000
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsynctypedef struct
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync{
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /** PCI device structure. */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDEVICE dev;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /** Pointer to the device instance. - R3 ptr. */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PPDMDEVINSR3 pDevIns;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* So far, not much of a state */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync} LPCState;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#ifndef VBOX_DEVICE_STRUCT_TESTCASE
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsyncstatic uint32_t rcba_ram_readl(LPCState* s, RTGCPHYS addr)
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync{
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync Log(("rcba_read at %llx\n", (uint64_t)addr));
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync int32_t iIndex = (addr - RCBA_BASE);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync uint32_t value = 0;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* This is the HPET config pointer, HPAS in DSDT */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync switch (iIndex)
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync {
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync case 0x3404:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync Log(("rcba_read HPET_CONFIG_POINTER\n"));
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync value = 0xf0; /* enabled at 0xfed00000 */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync break;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync case 0x3410:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* This is the HPET config pointer */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync Log(("rcba_read GCS\n"));
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync value = 0;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync break;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync default:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync Log(("Unknown RCBA read\n"));
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync break;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync }
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync return value;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync}
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsyncstatic void rcba_ram_writel(LPCState* s, RTGCPHYS addr, uint32_t value)
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync{
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync Log(("rcba_write %llx = %#x\n", (uint64_t)addr, value));
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync int32_t iIndex = (addr - RCBA_BASE);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync switch (iIndex)
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync {
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync case 0x3410:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync Log(("rcba_write GCS\n"));
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync break;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync default:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync Log(("Unknown RCBA write\n"));
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync break;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync }
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync}
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/**
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * I/O handler for memory-mapped read operations.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @returns VBox status code.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param pDevIns The device instance.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param pvUser User argument.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param GCPhysAddr Physical address (in GC) where the read starts.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param pv Where to store the result.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param cb Number of bytes read.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @thread EMT
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsyncPDMBOTHCBDECL(int) lpcMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync{
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync LPCState *s = PDMINS_2_DATA(pDevIns, LPCState*);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync switch (cb)
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync {
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync case 1:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync case 2:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync break;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync case 4:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync {
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *(uint32_t*)pv = rcba_ram_readl(s, GCPhysAddr);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync break;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync }
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync default:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync return VERR_INTERNAL_ERROR;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync }
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync return VINF_SUCCESS;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync}
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/**
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Memory mapped I/O Handler for write operations.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @returns VBox status code.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param pDevIns The device instance.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param pvUser User argument.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param GCPhysAddr Physical address (in GC) where the read starts.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param pv Where to fetch the value.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param cb Number of bytes to write.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @thread EMT
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsyncPDMBOTHCBDECL(int) lpcMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync{
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync LPCState *s = PDMINS_2_DATA(pDevIns, LPCState*);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync switch (cb)
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync {
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync case 1:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync case 2:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync break;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync case 4:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync {
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /** @todo: locking? */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync rcba_ram_writel(s, GCPhysAddr, *(uint32_t *)pv);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync break;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync }
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync default:
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync return VERR_INTERNAL_ERROR;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync }
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync return VINF_SUCCESS;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync}
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#ifdef IN_RING3
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/**
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Reset notification.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @returns VBox status.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param pDevIns The device instance data.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsyncstatic DECLCALLBACK(void) lpcReset(PPDMDEVINS pDevIns)
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync{
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync LPCState *pThis = PDMINS_2_DATA(pDevIns, LPCState *);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync LogFlow(("lpcReset: \n"));
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync}
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/**
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Info handler, device version.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync *
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param pDevIns Device instance which registered the info.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param pHlp Callback functions for doing output.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @param pszArgs Argument string. Optional and specific to the handler.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsyncstatic DECLCALLBACK(void) lpcInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync{
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync LPCState *pThis = PDMINS_2_DATA(pDevIns, LPCState *);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync LogFlow(("lpcInfo: \n"));
0d9f0399d4356c471af5e68c30b51c73f7909487vboxsync
0d9f0399d4356c471af5e68c30b51c73f7909487vboxsync if (pThis->dev.config[0xde] == 0xbe && pThis->dev.config[0xad] == 0xef)
0d9f0399d4356c471af5e68c30b51c73f7909487vboxsync pHlp->pfnPrintf(pHlp, "APIC backdoor activated\n");
0d9f0399d4356c471af5e68c30b51c73f7909487vboxsync else
0d9f0399d4356c471af5e68c30b51c73f7909487vboxsync pHlp->pfnPrintf(pHlp, "APIC backdoor closed: %02x %02x\n",
0d9f0399d4356c471af5e68c30b51c73f7909487vboxsync pThis->dev.config[0xde], pThis->dev.config[0xad]);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync}
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/**
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @interface_method_impl{PDMDEVREG,pfnConstruct}
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsyncstatic DECLCALLBACK(int) lpcConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync{
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync LPCState *pThis = PDMINS_2_DATA(pDevIns, LPCState *);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync int rc;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync Assert(iInstance == 0);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->pDevIns = pDevIns;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /*
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Register the PCI device.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDevSetVendorId (&pThis->dev, 0x8086); /* Intel */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDevSetDeviceId (&pThis->dev, 0x27b9);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDevSetCommand (&pThis->dev, 0x0007); /* master, memory and I/O */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDevSetRevisionId (&pThis->dev, 0x02);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDevSetClassSub (&pThis->dev, 0x01); /* PCI-to-ISA Bridge */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDevSetClassBase (&pThis->dev, 0x06); /* Bridge */
b0ef8e9a92e464839d4cb902775788a5fb738451vboxsync PCIDevSetHeaderType (&pThis->dev, 0x80); /* normal, multifunction device (so that other devices can be its functions) */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDevSetSubSystemVendorId(&pThis->dev, 0x8086);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDevSetSubSystemId (&pThis->dev, 0x7270);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDevSetInterruptPin (&pThis->dev, 0x03);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDevSetStatus (&pThis->dev, 0x0200); /* PCI_status_devsel_medium */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /** @todo: rewrite using PCI accessors */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x40] = 0x01;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x41] = 0x0b;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x4c] = 0x4d;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x4e] = 0x03;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x4f] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x60] = 0x0a; /* PCI A -> IRQ 10 */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x61] = 0x0a; /* PCI B -> IRQ 10 */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x62] = 0x0b; /* PCI C -> IRQ 11 */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x63] = 0x0b; /* PCI D -> IRQ 11 */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x69] = 0x02;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x70] = 0x80;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x76] = 0x0c;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x77] = 0x0c;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x78] = 0x02;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x79] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x80] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x82] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xa0] = 0x08;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xa2] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xa3] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xa4] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xa5] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xa6] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xa7] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xa8] = 0x0f;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xaa] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xab] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xac] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xae] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* We need to allow direct config reading from this address */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xf0] = (uint8_t)(RCBA_BASE | 1); /* enabled */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xf1] = (uint8_t)(RCBA_BASE >> 8);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xf2] = (uint8_t)(RCBA_BASE >> 16);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0xf3] = (uint8_t)(RCBA_BASE >> 24);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync rc = PDMDevHlpPCIRegister (pDevIns, &pThis->dev);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync if (RT_FAILURE(rc))
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync return rc;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /*
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Register the MMIO regions.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync rc = PDMDevHlpMMIORegister(pDevIns, RCBA_BASE, 0x4000, pThis,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync lpcMMIOWrite, lpcMMIORead, NULL, "LPC Memory");
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync if (RT_FAILURE(rc))
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync return rc;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* No state in the LPC right now */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /*
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * Initialize the device state.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync lpcReset(pDevIns);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /**
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * @todo: Register statistics.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PDMDevHlpDBGFInfoRegister(pDevIns, "lpc", "Display LPC status. (no arguments)", lpcInfo);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync return VINF_SUCCESS;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync}
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/**
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * The device registration structure.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsyncconst PDMDEVREG g_DeviceLPC =
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync{
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* u32Version */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PDM_DEVREG_VERSION,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* szName */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync "lpc",
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* szRCMod */
145f3def013dbea3281a655f726aba48cee34ea9vboxsync "VBoxDD2GC.gc",
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* szR0Mod */
145f3def013dbea3281a655f726aba48cee34ea9vboxsync "VBoxDD2R0.r0",
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pszDescription */
145f3def013dbea3281a655f726aba48cee34ea9vboxsync "Low Pin Count (LPC) Bus",
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* fFlags */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* fClass */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PDM_DEVREG_CLASS_MISC,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* cMaxInstances */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync 1,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* cbInstance */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync sizeof(LPCState),
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnConstruct */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync lpcConstruct,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnDestruct */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnRelocate */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnIOCtl */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnPowerOn */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnReset */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync lpcReset,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnSuspend */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnResume */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnAttach */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnDetach */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnQueryInterface. */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnInitComplete */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnPowerOff */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnSoftReset */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* u32VersionEnd */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PDM_DEVREG_VERSION
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync};
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#endif /* IN_RING3 */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#endif /* VBOX_DEVICE_STRUCT_TESTCASE */