mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-23 22:25:41 +00:00
155 lines
4.3 KiB
C++
155 lines
4.3 KiB
C++
/**
|
|
** Supermodel
|
|
** A Sega Model 3 Arcade Emulator.
|
|
** Copyright 2011 Bart Trzynadlowski, Nik Henson
|
|
**
|
|
** This file is part of Supermodel.
|
|
**
|
|
** Supermodel 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, either version 3 of the License, or (at your option)
|
|
** any later version.
|
|
**
|
|
** Supermodel 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 Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
|
**/
|
|
|
|
/*
|
|
* PCI.cpp
|
|
*
|
|
* PCI bus and device emulation. Implementation of the CPCIBus class.
|
|
* IPCIDevice is just a base class from which others are derived. Only the
|
|
* transfer of PCI register data is emulated. Device functionality is
|
|
* handled by device objects (derived from IPCIDevice).
|
|
*
|
|
* TO-DO List:
|
|
* -----------
|
|
* - Exception handling for out-of-memory errors in STL? Right now, we assume
|
|
* the vectors do not run out of memory because so few PCI devices exist.
|
|
*/
|
|
|
|
#include "Supermodel.h"
|
|
|
|
|
|
/******************************************************************************
|
|
Emulation Functions
|
|
******************************************************************************/
|
|
|
|
/*
|
|
* CPCIBus::ReadConfigSpace(device, reg, bits offset):
|
|
*
|
|
* Reads a PCI register belonging to a particular device.
|
|
*/
|
|
UINT32 CPCIBus::ReadConfigSpace(unsigned device, unsigned reg, unsigned bits, unsigned offset)
|
|
{
|
|
unsigned i;
|
|
|
|
// Alignment check
|
|
#ifdef DEBUG
|
|
if (((bits==16)&&(offset&1)) || ((bits==32)&&(offset&3)))
|
|
ErrorLog("Misaligned PCI read request (device=%d,reg=%X,offset=%d)\n", device, reg, offset);
|
|
#endif
|
|
|
|
// Search device vector for a matching device
|
|
for (i = 0; i < DeviceVector.size(); i++)
|
|
{
|
|
if (DeviceVector[i].device == device)
|
|
return DeviceVector[i].DeviceObject->ReadPCIConfigSpace(device, reg, bits, offset);
|
|
}
|
|
|
|
DebugLog("PCI read request for unknown device (device=%d,reg=%X)\n", device, reg);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* CPCIBus::WriteConfigSpace(device, reg, bits, offset, data):
|
|
*
|
|
* Writes to the PCI configuration space register belonging to a particular
|
|
* device.
|
|
*/
|
|
void CPCIBus::WriteConfigSpace(unsigned device, unsigned reg, unsigned bits, unsigned offset, UINT32 data)
|
|
{
|
|
unsigned i;
|
|
|
|
// Search device vector for a matching device
|
|
for (i = 0; i < DeviceVector.size(); i++)
|
|
{
|
|
if (DeviceVector[i].device == device)
|
|
{
|
|
DeviceVector[i].DeviceObject->WritePCIConfigSpace(device, reg, bits, offset, data);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// printf("PCI write request for unknown device (device=%d, reg=%X, data=%X)\n", device, reg, data);
|
|
DebugLog("PCI write request for unknown device (device=%d, reg=%X, data=%X)\n", device, reg, data);
|
|
}
|
|
|
|
/*
|
|
* CPCIBus::Reset():
|
|
*
|
|
* Resets the PCI bus emulation only. The devices attached to the bus are NOT
|
|
* reset or accessed.
|
|
*/
|
|
void CPCIBus::Reset(void)
|
|
{
|
|
// this function really only exists for consistency with other device classes
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
Configuration, Initialization, and Shutdown
|
|
******************************************************************************/
|
|
|
|
/*
|
|
* CPCIBus::AttachDevice(device, DeviceObjectPtr):
|
|
*
|
|
* Attaches a device to the PCI bus. This means it is added to a list of
|
|
* devices to scan when handling PCI configuration space requests.
|
|
*/
|
|
void CPCIBus::AttachDevice(unsigned device, IPCIDevice *DeviceObjectPtr)
|
|
{
|
|
struct DeviceObjectLink D;
|
|
|
|
D.device = device;
|
|
D.DeviceObject = DeviceObjectPtr;
|
|
DeviceVector.push_back(D);
|
|
|
|
DebugLog("Attached device %d to PCI bus\n", device);
|
|
}
|
|
|
|
/*
|
|
* CPCIBus::Init():
|
|
*
|
|
* This must be called first and only once during the lifetime of the class.
|
|
*/
|
|
void CPCIBus::Init(void)
|
|
{
|
|
DeviceVector.clear();
|
|
}
|
|
|
|
/*
|
|
* CPCIBus::CPCIBus(void):
|
|
*
|
|
* Constructor.
|
|
*/
|
|
CPCIBus::CPCIBus(void)
|
|
{
|
|
DebugLog("Built PCI bus\n");
|
|
}
|
|
|
|
/*
|
|
* CPCIBus::~CPCIBus(void):
|
|
*
|
|
* Destructor.
|
|
*/
|
|
CPCIBus::~CPCIBus(void)
|
|
{
|
|
DebugLog("Destroyed PCI bus\n");
|
|
}
|