10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/* $Id$ */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/** @file
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync * DevLPC - LPC device emulation
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync *
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync * @todo This needs to be _replaced_ by a proper chipset device one day. There
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync * are less than 10 C/C++ statements in this file doing active emulation.
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync */
145f3def013dbea3281a655f726aba48cee34ea9vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync/*
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync * Copyright (C) 2006-2013 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
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/pdmdev.h>
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#include <VBox/log.h>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/stam.h>
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#include <iprt/assert.h>
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync#include <iprt/string.h>
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync#include "VBoxDD2.h"
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync#define RCBA_BASE UINT32_C(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*);
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync Assert(cb == 4); Assert(!(GCPhysAddr & 3));
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync *(uint32_t*)pv = rcba_ram_readl(s, GCPhysAddr);
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 */
6826c1a65f586b47c2abbbabab801950c9a0bb75vboxsyncPDMBOTHCBDECL(int) lpcMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *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 rcba_ram_writel(s, GCPhysAddr, *(uint32_t *)pv);
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync break;
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/**
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]);
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync for (int iLine = 0; iLine < 8; ++iLine)
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync {
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync int iBase = iLine < 4 ? 0x60 : 0x64;
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync uint8_t iMap = PCIDevGetByte(&pThis->dev, iBase + iLine);
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync if ((iMap & 0x80) != 0)
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync pHlp->pfnPrintf(pHlp, "PIRQ%c disabled\n", 'A' + iLine);
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync else
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync pHlp->pfnPrintf(pHlp, "PIRQ%c -> IRQ%d\n", 'A' + iLine, iMap & 0xf);
f862648ac24687a4e6c0327b9f728fa93ad69a62vboxsync }
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);
d35226805940eec624c095ff8232486a46b9232fvboxsync PCIDevSetCommand (&pThis->dev, PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS | PCI_COMMAND_BUSMASTER);
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);
db2645ffc7122bff72559ef7a5cd83950a82f0f5vboxsync PCIDevSetInterruptPin (&pThis->dev, 0x00); /* The LPC device itself generates no interrupts */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync PCIDevSetStatus (&pThis->dev, 0x0200); /* PCI_status_devsel_medium */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync /** @todo rewrite using PCI accessors; Update, rewrite this device from
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync * scratch! Possibly against ICH9 or something else matching our
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync * chipset of choice. (Note that the exteremely partial emulation here
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync * is supposed to be of ICH7 if what's on the top of the file is
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync * anything to go by.) */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* See p. 427 of ICH9 specification for register description */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* 40h - 43h PMBASE 40-43 ACPI Base Address */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync pThis->dev.config[0x40] = 0x01; /* IO space */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync pThis->dev.config[0x41] = 0x80; /* base address / 128, see DevACPI.cpp */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* 44h ACPI_CNTL ACPI Control */
22b1ed1037d8e3cf969d0b82221a22186898cb22vboxsync pThis->dev.config[0x44] = 0x00 | (1<<7); /* SCI is IRQ9, ACPI enabled */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* 48h–4Bh GPIOBASE GPIO Base Address */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* 4C GC GPIO Control */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x4c] = 0x4d;
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* ???? */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x4e] = 0x03;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x4f] = 0x00;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
b1fd9b7aded8eda1a9e12f3c44ef0bb71affce1fvboxsync /* 60h-63h PIRQ[n]_ROUT PIRQ[A-D] Routing Control */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync pThis->dev.config[0x60] = 0x0b; /* PCI A -> IRQ 11 */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync pThis->dev.config[0x61] = 0x09; /* PCI B -> IRQ 9 */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync pThis->dev.config[0x62] = 0x0b; /* PCI C -> IRQ 11 */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync pThis->dev.config[0x63] = 0x09; /* PCI D -> IRQ 9 */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* 64h SIRQ_CNTL Serial IRQ Control 10h R/W, RO */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync pThis->dev.config[0x64] = 0x10;
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync
22b1ed1037d8e3cf969d0b82221a22186898cb22vboxsync /* 68h-6Bh PIRQ[n]_ROUT PIRQ[E-H] Routing Control */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync pThis->dev.config[0x68] = 0x80;
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync pThis->dev.config[0x69] = 0x80;
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync pThis->dev.config[0x6A] = 0x80;
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync pThis->dev.config[0x6B] = 0x80;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
690f529f58cd70ffd9f4271edd7c2540651dccccvboxsync /* 6C-6Dh LPC_IBDF IOxAPIC Bus:Device:Function 00F8h R/W */
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;
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* 80h LPC_I/O_DEC I/O Decode Ranges 0000h R/W */
690f529f58cd70ffd9f4271edd7c2540651dccccvboxsync /* 82h-83h LPC_EN LPC I/F Enables 0000h R/W */
690f529f58cd70ffd9f4271edd7c2540651dccccvboxsync /* 84h-87h GEN1_DEC LPC I/F Generic Decode Range 1 00000000h R/W */
690f529f58cd70ffd9f4271edd7c2540651dccccvboxsync /* 88h-8Bh GEN2_DEC LPC I/F Generic Decode Range 2 00000000h R/W */
690f529f58cd70ffd9f4271edd7c2540651dccccvboxsync /* 8Ch-8Eh GEN3_DEC LPC I/F Generic Decode Range 3 00000000h R/W */
690f529f58cd70ffd9f4271edd7c2540651dccccvboxsync /* 90h-93h GEN4_DEC LPC I/F Generic Decode Range 4 00000000h R/W */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync
690f529f58cd70ffd9f4271edd7c2540651dccccvboxsync /* A0h-CFh Power Management */
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
690f529f58cd70ffd9f4271edd7c2540651dccccvboxsync /* D0h-D3h FWH_SEL1 Firmware Hub Select 1 */
690f529f58cd70ffd9f4271edd7c2540651dccccvboxsync /* D4h-D5h FWH_SEL2 Firmware Hub Select 2 */
690f529f58cd70ffd9f4271edd7c2540651dccccvboxsync /* D8h-D9h FWH_DEC_EN1 Firmware Hub Decode Enable 1 */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* DCh BIOS_CNTL BIOS Control */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* E0h-E1h FDCAP Feature Detection Capability ID */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* E2h FDLEN Feature Detection Capability Length */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* E3h FDVER Feature Detection Version */
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* E4h-EBh FDVCT Feature Vector Description */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
5f0e6ed665965d99bd03b7c2906771b446cff7dbvboxsync /* F0h-F3h RCBA Root Complex Base 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,
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_PASSTHRU,
a96f8709d113c056da40edb8e2591983226a9761vboxsync lpcMMIOWrite, lpcMMIORead, "LPC Memory");
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync if (RT_FAILURE(rc))
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync return rc;
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* No state in the LPC right now */
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,
24ca3d27f14cf8a03b8448f6d0898110e915d46avboxsync /* pfnMemSetup */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnPowerOn */
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync NULL,
10b932b145ceeaa0e8edf111bb0e46dbd0750e14vboxsync /* pfnReset */
0dad7e96164c401fb34d6d667e9abc5e7b9515f6vboxsync NULL,
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 */