1
0
Fork 0

add PCI framework

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3723
This commit is contained in:
Sebastian Strohhäcker 2011-06-18 13:39:31 +00:00
parent 1828977d5c
commit 6bc4e41458
10 changed files with 682 additions and 4 deletions

View file

@ -24,6 +24,7 @@ mixer.h \
modules.h \
mouse.h \
paging.h \
pci_bus.h \
pic.h \
programs.h \
render.h \

View file

@ -27,6 +27,7 @@ enum LOG_TYPES {
LOG_PIT,LOG_KEYBOARD,LOG_PIC,
LOG_MOUSE,LOG_BIOS,LOG_GUI,LOG_MISC,
LOG_IO,
LOG_PCI,
LOG_MAX
};
@ -65,6 +66,10 @@ struct LOG
void operator()(char const* , double , double , double ) { }
void operator()(char const* , double , double , double , double ) { }
void operator()(char const* , double , double , double , double , double ) { }
void operator()(char const* , double , double , double , double , double , double ) { }
void operator()(char const* , double , double , double , double , double , double , double) { }
void operator()(char const* , char const* ) { }
void operator()(char const* , char const* , double ) { }
@ -73,7 +78,7 @@ struct LOG
void operator()(char const* , double , double, char const* ) { }
void operator()(char const* , char const*, char const*) { }
void operator()(char const* , double , double , double , char const* ) { }
}; //add missing operators to here
//try to avoid anything smaller than bit32...
void GFX_ShowMsg(char const* format,...) GCC_ATTRIBUTE(__format__(__printf__, 1, 2));

85
include/pci_bus.h Normal file
View file

@ -0,0 +1,85 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef DOSBOX_PCI_H
#define DOSBOX_PCI_H
//#define PCI_FUNCTIONALITY_ENABLED 0
#if defined PCI_FUNCTIONALITY_ENABLED
#define PCI_MAX_PCIDEVICES 10
#define PCI_MAX_PCIFUNCTIONS 8
class PCI_Device {
private:
Bits pci_id, pci_subfunction;
Bit16u vendor_id, device_id;
// subdevices declarations, they will respond to pci functions 1 to 7
// (main device is attached to function 0)
Bitu num_subdevices;
PCI_Device* subdevices[PCI_MAX_PCIFUNCTIONS-1];
public:
PCI_Device(Bit16u vendor, Bit16u device);
Bits PCIId(void) {
return pci_id;
}
Bits PCISubfunction(void) {
return pci_subfunction;
}
Bit16u VendorID(void) {
return vendor_id;
}
Bit16u DeviceID(void) {
return device_id;
}
void SetPCIId(Bitu number, Bits subfct);
bool AddSubdevice(PCI_Device* dev);
void RemoveSubdevice(Bits subfct);
PCI_Device* GetSubdevice(Bits subfct);
Bit16u NumSubdevices(void) {
if (num_subdevices>PCI_MAX_PCIFUNCTIONS-1) return PCI_MAX_PCIFUNCTIONS-1;
return num_subdevices;
}
Bits GetNextSubdeviceNumber(void) {
if (num_subdevices>=PCI_MAX_PCIFUNCTIONS-1) return -1;
return num_subdevices+1;
}
virtual Bits ParseReadRegister(Bit8u regnum)=0;
virtual Bits ParseWriteRegister(Bit8u regnum,Bit8u value)=0;
virtual bool InitializeRegisters(Bit8u registers[256])=0;
};
bool PCI_IsInitialized();
RealPt PCI_GetPModeInterface(void);
#endif
#endif

View file

@ -245,6 +245,7 @@ void LOG_StartUp(void) {
loggrp[LOG_MISC].front="MISC";
loggrp[LOG_IO].front="IO";
loggrp[LOG_PCI].front="PCI";
/* Register the log section */
Section_prop * sect=control->AddSection_prop("log",LOG_Init);

View file

@ -41,6 +41,7 @@
#include "mapper.h"
#include "ints/int10.h"
#include "render.h"
#include "pci_bus.h"
Config * control;
MachineType machine;
@ -73,6 +74,10 @@ void MIXER_Init(Section*);
void MIDI_Init(Section*);
void HARDWARE_Init(Section*);
#if defined(PCI_FUNCTIONALITY_ENABLED)
void PCI_Init(Section*);
#endif
void KEYBOARD_Init(Section*); //TODO This should setup INT 16 too but ok ;)
void JOYSTICK_Init(Section*);
@ -446,6 +451,12 @@ void DOSBOX_Init(void) {
secprop->AddInitFunction(&VGA_Init);
secprop->AddInitFunction(&KEYBOARD_Init);
#if defined(PCI_FUNCTIONALITY_ENABLED)
secprop=control->AddSection_prop("pci",&PCI_Init,false); //PCI bus
#endif
secprop=control->AddSection_prop("mixer",&MIXER_Init);
Pbool = secprop->Add_bool("nosound",Property::Changeable::OnlyAtStart,false);
Pbool->Set_help("Enable silent mode, sound is still emulated though.");

View file

@ -2,12 +2,12 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
SUBDIRS = serialport
EXTRA_DIST = opl.cpp opl.h adlib.h dbopl.h
EXTRA_DIST = opl.cpp opl.h adlib.h dbopl.h pci_devices.h
noinst_LIBRARIES = libhardware.a
libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler.cpp joystick.cpp keyboard.cpp \
memory.cpp mixer.cpp pcspeaker.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \
memory.cpp mixer.cpp pcspeaker.cpp pci_bus.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \
vga.cpp vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp vga_other.cpp \
vga_memory.cpp vga_misc.cpp vga_seq.cpp vga_xga.cpp vga_s3.cpp vga_tseng.cpp vga_paradise.cpp \
cmos.cpp disney.cpp gus.cpp mpu401.cpp ipx.cpp ipxserver.cpp dbopl.cpp

438
src/hardware/pci_bus.cpp Normal file
View file

@ -0,0 +1,438 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "dosbox.h"
#include "inout.h"
#include "mem.h"
#include "pci_bus.h"
#include "setup.h"
#include "debug.h"
#include "callback.h"
#include "regs.h"
#if defined(PCI_FUNCTIONALITY_ENABLED)
static Bit32u pci_caddress=0; // current PCI addressing
static Bitu pci_devices_installed=0; // number of registered PCI devices
static Bit8u pci_cfg_data[PCI_MAX_PCIDEVICES][PCI_MAX_PCIFUNCTIONS][256]; // PCI configuration data
static PCI_Device* pci_devices[PCI_MAX_PCIDEVICES]; // registered PCI devices
// PCI address
// 31 - set for a PCI access
// 30-24 - 0
// 23-16 - bus number (0x00ff0000)
// 15-11 - device number (slot) (0x0000f800)
// 10- 8 - subfunction number (0x00000700)
// 7- 2 - config register # (0x000000fc)
static void write_pci_addr(Bitu port,Bitu val,Bitu iolen) {
LOG(LOG_PCI,LOG_NORMAL)("Write PCI address :=%x",val);
pci_caddress=val;
}
static void write_pci_register(PCI_Device* dev,Bit8u regnum,Bit8u value) {
// vendor/device/class IDs/header type/etc. are read-only
if ((regnum<0x04) || ((regnum>=0x06) && (regnum<0x0c)) || (regnum==0x0e)) return;
if (dev==NULL) return;
switch (pci_cfg_data[dev->PCIId()][dev->PCISubfunction()][0x0e]&0x7f) { // header-type specific handling
case 0x00:
if ((regnum>=0x28) && (regnum<0x30)) return; // subsystem information is read-only
break;
case 0x01:
case 0x02:
default:
break;
}
// call device routine for special actions and the
// possibility to discard/replace the value that is to be written
Bits parsed_register=dev->ParseWriteRegister(regnum,value);
if (parsed_register>=0)
pci_cfg_data[dev->PCIId()][dev->PCISubfunction()][regnum]=(Bit8u)(parsed_register&0xff);
}
static void write_pci(Bitu port,Bitu val,Bitu iolen) {
LOG(LOG_PCI,LOG_NORMAL)("Write PCI data :=%x (len %d)",port,val,iolen);
// check for enabled/bus 0
if ((pci_caddress & 0x80ff0000) == 0x80000000) {
Bit8u devnum = (Bit8u)((pci_caddress >> 11) & 0x1f);
Bit8u fctnum = (Bit8u)((pci_caddress >> 8) & 0x7);
Bit8u regnum = (Bit8u)((pci_caddress & 0xfc) + (port & 0x03));
LOG(LOG_PCI,LOG_NORMAL)(" Write to device %x register %x (function %x) (:=%x)",devnum,regnum,fctnum,val);
if (devnum>=pci_devices_installed) return;
PCI_Device* masterdev=pci_devices[devnum];
if (masterdev==NULL) return;
if (fctnum>masterdev->NumSubdevices()) return;
PCI_Device* dev=masterdev->GetSubdevice(fctnum);
if (dev==NULL) return;
// write data to PCI device/configuration
switch (iolen) {
case 1: write_pci_register(dev,regnum+0,(Bit8u)(val&0xff)); break;
case 2: write_pci_register(dev,regnum+0,(Bit8u)(val&0xff));
write_pci_register(dev,regnum+1,(Bit8u)((val>>8)&0xff)); break;
case 4: write_pci_register(dev,regnum+0,(Bit8u)(val&0xff));
write_pci_register(dev,regnum+1,(Bit8u)((val>>8)&0xff));
write_pci_register(dev,regnum+2,(Bit8u)((val>>16)&0xff));
write_pci_register(dev,regnum+3,(Bit8u)((val>>24)&0xff)); break;
}
}
}
static Bitu read_pci_addr(Bitu port,Bitu iolen) {
LOG(LOG_PCI,LOG_NORMAL)("Read PCI address -> %x",pci_caddress);
return pci_caddress;
}
// read single 8bit value from register file (special register treatment included)
static Bit8u read_pci_register(PCI_Device* dev,Bit8u regnum) {
switch (regnum) {
case 0x00:
return (Bit8u)(dev->VendorID()&0xff);
case 0x01:
return (Bit8u)((dev->VendorID()>>8)&0xff);
case 0x02:
return (Bit8u)(dev->DeviceID()&0xff);
case 0x03:
return (Bit8u)((dev->DeviceID()>>8)&0xff);
case 0x0e:
return (pci_cfg_data[dev->PCIId()][dev->PCISubfunction()][regnum]&0x7f) |
((dev->NumSubdevices()>0)?0x80:0x00);
default:
break;
}
// call device routine for special actions and possibility to discard/remap register
Bits parsed_regnum=dev->ParseReadRegister(regnum);
if ((parsed_regnum>=0) && (parsed_regnum<256))
return pci_cfg_data[dev->PCIId()][dev->PCISubfunction()][parsed_regnum];
return 0xff;
}
static Bitu read_pci(Bitu port,Bitu iolen) {
LOG(LOG_PCI,LOG_NORMAL)("Read PCI data -> %x",pci_caddress);
if ((pci_caddress & 0x80ff0000) == 0x80000000) {
Bit8u devnum = (Bit8u)((pci_caddress >> 11) & 0x1f);
Bit8u fctnum = (Bit8u)((pci_caddress >> 8) & 0x7);
Bit8u regnum = (Bit8u)((pci_caddress & 0xfc) + (port & 0x03));
if (devnum>=pci_devices_installed) return 0xffffffff;
LOG(LOG_PCI,LOG_NORMAL)(" Read from device %x register %x (function %x); addr %x",
devnum,regnum,fctnum,pci_caddress);
PCI_Device* masterdev=pci_devices[devnum];
if (masterdev==NULL) return 0xffffffff;
if (fctnum>masterdev->NumSubdevices()) return 0xffffffff;
PCI_Device* dev=masterdev->GetSubdevice(fctnum);
if (dev!=NULL) {
switch (iolen) {
case 1:
{
Bit8u val8=read_pci_register(dev,regnum);
return val8;
}
case 2:
{
Bit16u val16=read_pci_register(dev,regnum);
val16|=(read_pci_register(dev,regnum+1)<<8);
return val16;
}
case 4:
{
Bit32u val32=read_pci_register(dev,regnum);
val32|=(read_pci_register(dev,regnum+1)<<8);
val32|=(read_pci_register(dev,regnum+2)<<16);
val32|=(read_pci_register(dev,regnum+3)<<24);
return val32;
}
default:
break;
}
}
}
return 0xffffffff;
}
static Bitu PCI_PM_Handler() {
LOG_MSG("PCI PMode handler, function %x",reg_ax);
return CBRET_NONE;
}
PCI_Device::PCI_Device(Bit16u vendor, Bit16u device) {
pci_id=-1;
pci_subfunction=-1;
vendor_id=vendor;
device_id=device;
num_subdevices=0;
for (Bitu dct=0;dct<PCI_MAX_PCIFUNCTIONS-1;dct++) subdevices[dct]=0;
}
void PCI_Device::SetPCIId(Bitu number, Bits subfct) {
if ((number>=0) && (number<PCI_MAX_PCIDEVICES)) {
pci_id=number;
if ((subfct>=0) && (subfct<PCI_MAX_PCIFUNCTIONS-1))
pci_subfunction=subfct;
else
pci_subfunction=-1;
}
}
bool PCI_Device::AddSubdevice(PCI_Device* dev) {
if (num_subdevices<PCI_MAX_PCIFUNCTIONS-1) {
if (subdevices[num_subdevices]!=NULL) E_Exit("PCI subdevice slot already in use!");
subdevices[num_subdevices]=dev;
num_subdevices++;
return true;
}
return false;
}
void PCI_Device::RemoveSubdevice(Bits subfct) {
if ((subfct>0) && (subfct<PCI_MAX_PCIFUNCTIONS)) {
if (subfct<=this->NumSubdevices()) {
delete subdevices[subfct-1];
subdevices[subfct-1]=NULL;
// should adjust things like num_subdevices as well...
}
}
}
PCI_Device* PCI_Device::GetSubdevice(Bits subfct) {
if (subfct>=PCI_MAX_PCIFUNCTIONS) return NULL;
if (subfct>0) {
if (subfct<=this->NumSubdevices()) return subdevices[subfct-1];
} else if (subfct==0) {
return this;
}
return NULL;
}
// queued devices (PCI device registering requested before the PCI framework was initialized)
static const Bitu max_rqueued_devices=16;
static Bitu num_rqueued_devices=0;
static PCI_Device* rqueued_devices[max_rqueued_devices];
#include "pci_devices.h"
class PCI:public Module_base{
private:
bool initialized;
protected:
IO_WriteHandleObject PCI_WriteHandler[5];
IO_ReadHandleObject PCI_ReadHandler[5];
CALLBACK_HandlerObject callback_pci;
public:
PhysPt GetPModeCallbackPointer(void) {
return Real2Phys(callback_pci.Get_RealPointer());
}
bool IsInitialized(void) {
return initialized;
}
// set up port handlers and configuration data
void InitializePCI(void) {
// install PCI-addressing ports
PCI_WriteHandler[0].Install(0xcf8,write_pci_addr,IO_MD);
PCI_ReadHandler[0].Install(0xcf8,read_pci_addr,IO_MD);
// install PCI-register read/write handlers
for (Bitu ct=0;ct<4;ct++) {
PCI_WriteHandler[1+ct].Install(0xcfc+ct,write_pci,IO_MB);
PCI_ReadHandler[1+ct].Install(0xcfc+ct,read_pci,IO_MB);
}
for (Bitu dev=0; dev<PCI_MAX_PCIDEVICES; dev++)
for (Bitu fct=0; fct<PCI_MAX_PCIFUNCTIONS-1; fct++)
for (Bitu reg=0; reg<256; reg++)
pci_cfg_data[dev][fct][reg] = 0;
callback_pci.Install(&PCI_PM_Handler,CB_IRETD,"PCI PM");
initialized=true;
}
// register PCI device to bus and setup data
Bits RegisterPCIDevice(PCI_Device* device, Bits slot=-1) {
if (device==NULL) return -1;
if (slot>=0) {
// specific slot specified, basic check for validity
if (slot>=PCI_MAX_PCIDEVICES) return -1;
} else {
// auto-add to new slot, check if one is still free
if (pci_devices_installed>=PCI_MAX_PCIDEVICES) return -1;
}
if (!initialized) InitializePCI();
if (slot<0) slot=pci_devices_installed; // use next slot
Bits subfunction=0; // main device unless specific already-occupied slot is requested
if (pci_devices[slot]!=NULL) {
subfunction=pci_devices[slot]->GetNextSubdeviceNumber();
if (subfunction<0) E_Exit("Too many PCI subdevices!");
}
if (device->InitializeRegisters(pci_cfg_data[slot][subfunction])) {
device->SetPCIId(slot, subfunction);
if (pci_devices[slot]==NULL) {
pci_devices[slot]=device;
pci_devices_installed++;
} else {
pci_devices[slot]->AddSubdevice(device);
}
return slot;
}
return -1;
}
void Deinitialize(void) {
initialized=false;
pci_devices_installed=0;
num_rqueued_devices=0;
pci_caddress=0;
for (Bitu dev=0; dev<PCI_MAX_PCIDEVICES; dev++)
for (Bitu fct=0; fct<PCI_MAX_PCIFUNCTIONS-1; fct++)
for (Bitu reg=0; reg<256; reg++)
pci_cfg_data[dev][fct][reg] = 0;
// install PCI-addressing ports
PCI_WriteHandler[0].Uninstall();
PCI_ReadHandler[0].Uninstall();
// install PCI-register read/write handlers
for (Bitu ct=0;ct<4;ct++) {
PCI_WriteHandler[1+ct].Uninstall();
PCI_ReadHandler[1+ct].Uninstall();
}
callback_pci.Uninstall();
}
void RemoveDevice(Bit16u vendor_id, Bit16u device_id) {
for (Bitu dct=0;dct<pci_devices_installed;dct++) {
if (pci_devices[dct]!=NULL) {
if (pci_devices[dct]->NumSubdevices()>0) {
for (Bitu sct=1;sct<PCI_MAX_PCIFUNCTIONS;sct++) {
PCI_Device* sdev=pci_devices[dct]->GetSubdevice(sct);
if (sdev!=NULL) {
if ((sdev->VendorID()==vendor_id) && (sdev->DeviceID()==device_id)) {
pci_devices[dct]->RemoveSubdevice(sct);
}
}
}
}
if ((pci_devices[dct]->VendorID()==vendor_id) && (pci_devices[dct]->DeviceID()==device_id)) {
delete pci_devices[dct];
pci_devices[dct]=NULL;
}
}
}
// check if all devices have been removed
bool any_device_left=false;
for (Bitu dct=0;dct<PCI_MAX_PCIDEVICES;dct++) {
if (dct>=pci_devices_installed) break;
if (pci_devices[dct]!=NULL) {
any_device_left=true;
break;
}
}
if (!any_device_left) Deinitialize();
Bitu last_active_device=PCI_MAX_PCIDEVICES;
for (Bitu dct=0;dct<PCI_MAX_PCIDEVICES;dct++) {
if (pci_devices[dct]!=NULL) last_active_device=dct;
}
if (last_active_device<pci_devices_installed)
pci_devices_installed=last_active_device+1;
}
PCI(Section* configuration):Module_base(configuration) {
initialized=false;
pci_devices_installed=0;
for (Bitu devct=0;devct<PCI_MAX_PCIDEVICES;devct++)
pci_devices[devct]=NULL;
if (num_rqueued_devices>0) {
// register all devices that have been added before the PCI bus was instantiated
for (Bitu dct=0;dct<num_rqueued_devices;dct++) {
this->RegisterPCIDevice(rqueued_devices[dct]);
}
num_rqueued_devices=0;
}
}
~PCI(){
initialized=false;
pci_devices_installed=0;
num_rqueued_devices=0;
}
};
static PCI* pci_interface=NULL;
PhysPt PCI_GetPModeInterface(void) {
if (pci_interface) {
return pci_interface->GetPModeCallbackPointer();
}
return 0;
}
bool PCI_IsInitialized() {
if (pci_interface) return pci_interface->IsInitialized();
return false;
}
void PCI_ShutDown(Section* sec){
delete pci_interface;
pci_interface=NULL;
}
void PCI_Init(Section* sec) {
pci_interface = new PCI(sec);
sec->AddDestroyFunction(&PCI_ShutDown,false);
}
#endif

View file

@ -0,0 +1,18 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

View file

@ -26,6 +26,7 @@
#include "inout.h"
#include "pic.h"
#include "hardware.h"
#include "pci_bus.h"
#include "joystick.h"
#include "mouse.h"
#include "setup.h"
@ -354,8 +355,120 @@ static Bitu INT1A_Handler(void) {
TandyDAC_Handler(reg_ah);
break;
case 0xb1: /* PCI Bios Calls */
LOG(LOG_BIOS,LOG_ERROR)("INT1A:PCI bios call %2X",reg_al);
LOG(LOG_BIOS,LOG_WARN)("INT1A:PCI bios call %2X",reg_al);
#if defined(PCI_FUNCTIONALITY_ENABLED)
switch (reg_al) {
case 0x01: // installation check
if (PCI_IsInitialized()) {
reg_ah=0x00;
reg_al=0x01; // cfg space mechanism 1 supported
reg_bx=0x0210; // ver 2.10
reg_cx=0x0000; // only one PCI bus
reg_edx=0x20494350;
reg_edi=PCI_GetPModeInterface();
CALLBACK_SCF(false);
} else {
CALLBACK_SCF(true);
}
break;
case 0x02: { // find device
Bitu devnr=0;
Bitu count=0x100;
Bit32u devicetag=(reg_cx<<16)|reg_dx;
Bits found=-1;
for (Bitu i=0; i<=count; i++) {
IO_WriteD(0xcf8,0x80000000|(i<<8)); // query unique device/subdevice entries
if (IO_ReadD(0xcfc)==devicetag) {
if (devnr==reg_si) {
found=i;
break;
} else {
// device found, but not the SIth device
devnr++;
}
}
}
if (found>=0) {
reg_ah=0x00;
reg_bh=0x00; // bus 0
reg_bl=(Bit8u)(found&0xff);
CALLBACK_SCF(false);
} else {
reg_ah=0x86; // device not found
CALLBACK_SCF(true);
}
}
break;
case 0x03: { // find device by class code
Bitu devnr=0;
Bitu count=0x100;
Bit32u classtag=reg_ecx&0xffffff;
Bits found=-1;
for (Bitu i=0; i<=count; i++) {
IO_WriteD(0xcf8,0x80000000|(i<<8)); // query unique device/subdevice entries
if (IO_ReadD(0xcfc)!=0xffffffff) {
IO_WriteD(0xcf8,0x80000000|(i<<8)|0x08);
if ((IO_ReadD(0xcfc)>>8)==classtag) {
if (devnr==reg_si) {
found=i;
break;
} else {
// device found, but not the SIth device
devnr++;
}
}
}
}
if (found>=0) {
reg_ah=0x00;
reg_bh=0x00; // bus 0
reg_bl=(Bit8u)(found&0xff);
CALLBACK_SCF(false);
} else {
reg_ah=0x86; // device not found
CALLBACK_SCF(true);
}
}
break;
case 0x08: // read configuration byte
IO_WriteD(0xcf8,0x80000000|(reg_bx<<8)|(reg_di&0xfc));
reg_cl=IO_ReadB(0xcfc+(reg_di&3));
CALLBACK_SCF(false);
break;
case 0x09: // read configuration word
IO_WriteD(0xcf8,0x80000000|(reg_bx<<8)|(reg_di&0xfc));
reg_cx=IO_ReadW(0xcfc+(reg_di&2));
CALLBACK_SCF(false);
break;
case 0x0a: // read configuration dword
IO_WriteD(0xcf8,0x80000000|(reg_bx<<8)|(reg_di&0xfc));
reg_ecx=IO_ReadD(0xcfc+(reg_di&3));
CALLBACK_SCF(false);
break;
case 0x0b: // write configuration byte
IO_WriteD(0xcf8,0x80000000|(reg_bx<<8)|(reg_di&0xfc));
IO_WriteB(0xcfc+(reg_di&3),reg_cl);
CALLBACK_SCF(false);
break;
case 0x0c: // write configuration word
IO_WriteD(0xcf8,0x80000000|(reg_bx<<8)|(reg_di&0xfc));
IO_WriteW(0xcfc+(reg_di&2),reg_cx);
CALLBACK_SCF(false);
break;
case 0x0d: // write configuration dword
IO_WriteD(0xcf8,0x80000000|(reg_bx<<8)|(reg_di&0xfc));
IO_WriteD(0xcfc+(reg_di&3),reg_ecx);
CALLBACK_SCF(false);
break;
default:
LOG(LOG_BIOS,LOG_ERROR)("INT1A:PCI BIOS: unknown function %x (%x %x %x)",
reg_ax,reg_bx,reg_cx,reg_dx);
CALLBACK_SCF(true);
break;
}
#else
CALLBACK_SCF(true);
#endif
break;
default:
LOG(LOG_BIOS,LOG_ERROR)("INT1A:Undefined call %2X",reg_ah);

View file

@ -480,6 +480,9 @@
<File
RelativePath="..\src\hardware\mixer.cpp">
</File>
<File
RelativePath="..\src\hardware\pci_bus.cpp">
</File>
<File
RelativePath="..\src\hardware\pic.cpp">
</File>
@ -831,6 +834,9 @@
<File
RelativePath="..\include\paging.h">
</File>
<File
RelativePath="..\include\pci_bus.h">
</File>
<File
RelativePath="..\include\pic.h">
</File>