.
--HG-- extra : convert_revision : 1ed206b27498641b64d7f35c74ea1f0623398d4e
This commit is contained in:
parent
8b04218262
commit
16a2357e86
7 changed files with 165 additions and 149 deletions
127
dev/ide_ctrl.cc
127
dev/ide_ctrl.cc
|
@ -76,10 +76,10 @@ IdeController::IdeController(Params *p)
|
|||
|
||||
// zero out all of the registers
|
||||
memset(bmi_regs, 0, sizeof(bmi_regs));
|
||||
memset(pci_regs, 0, sizeof(pci_regs));
|
||||
memset(pci_config_regs.data, 0, sizeof(pci_config_regs.data));
|
||||
|
||||
// setup initial values
|
||||
*(uint32_t *)&pci_regs[IDETIM] = 0x80008000; // enable both channels
|
||||
pci_config_regs.idetim = htoa((uint32_t)0x80008000); // enable both channels
|
||||
*(uint8_t *)&bmi_regs[BMIS0] = 0x60;
|
||||
*(uint8_t *)&bmi_regs[BMIS1] = 0x60;
|
||||
|
||||
|
@ -249,6 +249,7 @@ IdeController::cacheAccess(MemReqPtr &req)
|
|||
void
|
||||
IdeController::ReadConfig(int offset, int size, uint8_t *data)
|
||||
{
|
||||
int config_offset;
|
||||
|
||||
#if TRACING_ON
|
||||
Addr origOffset = offset;
|
||||
|
@ -256,85 +257,66 @@ IdeController::ReadConfig(int offset, int size, uint8_t *data)
|
|||
|
||||
if (offset < PCI_DEVICE_SPECIFIC) {
|
||||
PciDev::ReadConfig(offset, size, data);
|
||||
} else {
|
||||
if (offset >= PCI_IDE_TIMING && offset < (PCI_IDE_TIMING + 4)) {
|
||||
offset -= PCI_IDE_TIMING;
|
||||
offset += IDETIM;
|
||||
} else if (offset >= IDE_CTRL_CONFIG_START && (offset + size) <= IDE_CTRL_CONFIG_END) {
|
||||
|
||||
if ((offset + size) > (IDETIM + 4))
|
||||
panic("PCI read of IDETIM with invalid size\n");
|
||||
} else if (offset == PCI_SLAVE_TIMING) {
|
||||
offset -= PCI_SLAVE_TIMING;
|
||||
offset += SIDETIM;
|
||||
config_offset = offset - IDE_CTRL_CONFIG_START;
|
||||
|
||||
if ((offset + size) > (SIDETIM + 1))
|
||||
panic("PCI read of SIDETIM with invalid size\n");
|
||||
} else if (offset == PCI_UDMA33_CTRL) {
|
||||
offset -= PCI_UDMA33_CTRL;
|
||||
offset += UDMACTL;
|
||||
switch(size) {
|
||||
case sizeof(uint32_t):
|
||||
memcpy(data, &pci_config_regs.data[config_offset], sizeof(uint32_t));
|
||||
*(uint32_t*)data = htoa(*(uint32_t*)data);
|
||||
break;
|
||||
|
||||
if ((offset + size) > (UDMACTL + 1))
|
||||
panic("PCI read of UDMACTL with invalid size\n");
|
||||
} else if (offset >= PCI_UDMA33_TIMING &&
|
||||
offset < (PCI_UDMA33_TIMING + 2)) {
|
||||
offset -= PCI_UDMA33_TIMING;
|
||||
offset += UDMATIM;
|
||||
case sizeof(uint16_t):
|
||||
memcpy(data, &pci_config_regs.data[config_offset], sizeof(uint16_t));
|
||||
*(uint16_t*)data = htoa(*(uint16_t*)data);
|
||||
break;
|
||||
|
||||
if ((offset + size) > (UDMATIM + 2))
|
||||
panic("PCI read of UDMATIM with invalid size\n");
|
||||
} else {
|
||||
panic("PCI read of unimplemented register: %x\n", offset);
|
||||
case sizeof(uint8_t):
|
||||
memcpy(data, &pci_config_regs.data[config_offset], sizeof(uint8_t));
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("Invalid PCI configuration read size!\n");
|
||||
}
|
||||
|
||||
memcpy((void *)data, (void *)&pci_regs[offset], size);
|
||||
} else {
|
||||
panic("Read of unimplemented PCI config. register: %x\n", offset);
|
||||
}
|
||||
|
||||
DPRINTF(IdeCtrl, "PCI read offset: %#x (%#x) size: %#x data: %#x\n",
|
||||
origOffset, offset, size,
|
||||
(*(uint32_t *)data) & (0xffffffff >> 8 * (4 - size)));
|
||||
*(uint32_t *)data & (0xffffffff >> 8 * (4 - size)));
|
||||
}
|
||||
|
||||
void
|
||||
IdeController::WriteConfig(int offset, int size, uint32_t data)
|
||||
{
|
||||
int config_offset;
|
||||
|
||||
if (offset < PCI_DEVICE_SPECIFIC) {
|
||||
PciDev::WriteConfig(offset, size, data);
|
||||
} else if (offset >= IDE_CTRL_CONFIG_START && (offset + size) <= IDE_CTRL_CONFIG_END) {
|
||||
|
||||
config_offset = offset - IDE_CTRL_CONFIG_START;
|
||||
|
||||
switch(size) {
|
||||
case sizeof(uint32_t):
|
||||
case sizeof(uint16_t):
|
||||
case sizeof(uint8_t):
|
||||
memcpy(&pci_config_regs.data[config_offset], &data, size);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("Invalid PCI configuration write size!\n");
|
||||
}
|
||||
|
||||
} else {
|
||||
panic("Write of unimplemented PCI config. register: %x\n", offset);
|
||||
}
|
||||
|
||||
DPRINTF(IdeCtrl, "PCI write offset: %#x size: %#x data: %#x\n",
|
||||
offset, size, data & (0xffffffff >> 8 * (4 - size)));
|
||||
|
||||
// do standard write stuff if in standard PCI space
|
||||
if (offset < PCI_DEVICE_SPECIFIC) {
|
||||
PciDev::WriteConfig(offset, size, data);
|
||||
} else {
|
||||
if (offset >= PCI_IDE_TIMING && offset < (PCI_IDE_TIMING + 4)) {
|
||||
offset -= PCI_IDE_TIMING;
|
||||
offset += IDETIM;
|
||||
|
||||
if ((offset + size) > (IDETIM + 4))
|
||||
panic("PCI write to IDETIM with invalid size\n");
|
||||
} else if (offset == PCI_SLAVE_TIMING) {
|
||||
offset -= PCI_SLAVE_TIMING;
|
||||
offset += SIDETIM;
|
||||
|
||||
if ((offset + size) > (SIDETIM + 1))
|
||||
panic("PCI write to SIDETIM with invalid size\n");
|
||||
} else if (offset == PCI_UDMA33_CTRL) {
|
||||
offset -= PCI_UDMA33_CTRL;
|
||||
offset += UDMACTL;
|
||||
|
||||
if ((offset + size) > (UDMACTL + 1))
|
||||
panic("PCI write to UDMACTL with invalid size\n");
|
||||
} else if (offset >= PCI_UDMA33_TIMING &&
|
||||
offset < (PCI_UDMA33_TIMING + 2)) {
|
||||
offset -= PCI_UDMA33_TIMING;
|
||||
offset += UDMATIM;
|
||||
|
||||
if ((offset + size) > (UDMATIM + 2))
|
||||
panic("PCI write to UDMATIM with invalid size\n");
|
||||
} else {
|
||||
panic("PCI write to unimplemented register: %x\n", offset);
|
||||
}
|
||||
|
||||
memcpy((void *)&pci_regs[offset], (void *)&data, size);
|
||||
}
|
||||
|
||||
// Catch the writes to specific PCI registers that have side affects
|
||||
// (like updating the PIO ranges)
|
||||
|
@ -421,17 +403,22 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
|
|||
return No_Fault;
|
||||
|
||||
// sanity check the size (allows byte, word, or dword access)
|
||||
if (req->size != sizeof(uint8_t) && req->size != sizeof(uint16_t) &&
|
||||
req->size != sizeof(uint32_t))
|
||||
switch (req->size) {
|
||||
case sizeof(uint8_t):
|
||||
case sizeof(uint16_t):
|
||||
case sizeof(uint32_t):
|
||||
break;
|
||||
default:
|
||||
panic("IDE controller read of invalid size: %#x\n", req->size);
|
||||
}
|
||||
|
||||
if (type != BMI_BLOCK) {
|
||||
|
||||
disk = getDisk(primary);
|
||||
if (disks[disk])
|
||||
if (req->size == sizeof(uint32_t) && offset == DATA_OFFSET) {
|
||||
*((uint16_t*)data) = disks[disk]->read(offset, type);
|
||||
*((uint16_t*)data + 1) = disks[disk]->read(offset, type);
|
||||
((uint16_t*)data)[0] = disks[disk]->read(offset, type);
|
||||
((uint16_t*)data)[1] = disks[disk]->read(offset, type);
|
||||
}
|
||||
else if (req->size == sizeof(uint8_t) && offset == DATA_OFFSET) {
|
||||
panic("IDE read of data reg invalid size: %#x\n", req->size);
|
||||
|
@ -622,7 +609,7 @@ IdeController::serialize(std::ostream &os)
|
|||
// Serialize registers
|
||||
SERIALIZE_ARRAY(bmi_regs, 16);
|
||||
SERIALIZE_ARRAY(dev, 2);
|
||||
SERIALIZE_ARRAY(pci_regs, 8);
|
||||
SERIALIZE_ARRAY(pci_config_regs.data, 22);
|
||||
|
||||
// Serialize internal state
|
||||
SERIALIZE_SCALAR(io_enabled);
|
||||
|
@ -651,7 +638,7 @@ IdeController::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
// Unserialize registers
|
||||
UNSERIALIZE_ARRAY(bmi_regs, 16);
|
||||
UNSERIALIZE_ARRAY(dev, 2);
|
||||
UNSERIALIZE_ARRAY(pci_regs, 8);
|
||||
UNSERIALIZE_ARRAY(pci_config_regs.data, 22);
|
||||
|
||||
// Unserialize internal state
|
||||
UNSERIALIZE_SCALAR(io_enabled);
|
||||
|
|
|
@ -64,15 +64,9 @@
|
|||
#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET
|
||||
|
||||
// PCI device specific register byte offsets
|
||||
#define PCI_IDE_TIMING 0x40
|
||||
#define PCI_SLAVE_TIMING 0x44
|
||||
#define PCI_UDMA33_CTRL 0x48
|
||||
#define PCI_UDMA33_TIMING 0x4a
|
||||
#define IDE_CTRL_CONFIG_START 0x40
|
||||
#define IDE_CTRL_CONFIG_END ((IDE_CTRL_CONFIG_START) + sizeof(pci_config_regs))
|
||||
|
||||
#define IDETIM (0)
|
||||
#define SIDETIM (4)
|
||||
#define UDMACTL (5)
|
||||
#define UDMATIM (6)
|
||||
|
||||
typedef enum RegType {
|
||||
COMMAND_BLOCK = 0,
|
||||
|
@ -119,8 +113,30 @@ class IdeController : public PciDev
|
|||
uint8_t bmi_regs[16];
|
||||
/** Shadows of the device select bit */
|
||||
uint8_t dev[2];
|
||||
/** Registers used in PCI configuration */
|
||||
uint8_t pci_regs[8];
|
||||
/** Registers used in device specific PCI configuration */
|
||||
union {
|
||||
uint8_t data[22];
|
||||
|
||||
struct {
|
||||
uint32_t idetim;
|
||||
uint8_t sidetim;
|
||||
uint8_t reserved_45;
|
||||
uint8_t reserved_46;
|
||||
uint8_t reserved_47;
|
||||
uint8_t udmactl;
|
||||
uint8_t reserved_49;
|
||||
uint16_t udmatim;
|
||||
uint8_t reserved_4c;
|
||||
uint8_t reserved_4d;
|
||||
uint8_t reserved_4e;
|
||||
uint8_t reserved_4f;
|
||||
uint8_t reserved_50;
|
||||
uint8_t reserved_51;
|
||||
uint8_t reserved_52;
|
||||
uint8_t reserved_53;
|
||||
uint16_t ideconfig;
|
||||
};
|
||||
} pci_config_regs;
|
||||
|
||||
// Internal management variables
|
||||
bool io_enabled;
|
||||
|
|
|
@ -211,8 +211,7 @@ IdeDisk::bytesInDmaPage(Addr curAddr, uint32_t bytesLeft)
|
|||
uint16_t
|
||||
IdeDisk::read(const Addr &offset, RegType_t type)
|
||||
{
|
||||
|
||||
uint16_t data;
|
||||
uint16_t data = 0;
|
||||
DevAction_t action = ACT_NONE;
|
||||
|
||||
if (type == COMMAND_BLOCK) {
|
||||
|
@ -222,34 +221,34 @@ IdeDisk::read(const Addr &offset, RegType_t type)
|
|||
else if (offset == DATA_OFFSET)
|
||||
action = ACT_DATA_READ_SHORT;
|
||||
|
||||
switch (offset) {
|
||||
case DATA_OFFSET:
|
||||
data = cmdReg.data;
|
||||
break;
|
||||
case ERROR_OFFSET:
|
||||
data = cmdReg.error;
|
||||
break;
|
||||
case NSECTOR_OFFSET:
|
||||
data = cmdReg.sec_count;
|
||||
break;
|
||||
case SECTOR_OFFSET:
|
||||
data = cmdReg.sec_num;
|
||||
break;
|
||||
case LCYL_OFFSET:
|
||||
data = cmdReg.cyl_low;
|
||||
break;
|
||||
case HCYL_OFFSET:
|
||||
data = cmdReg.cyl_high;
|
||||
break;
|
||||
case SELECT_OFFSET:
|
||||
data = cmdReg.drive;
|
||||
break;
|
||||
case STATUS_OFFSET:
|
||||
data = status;
|
||||
break;
|
||||
default:
|
||||
panic("Invalid IDE command register offset: %#x\n", offset);
|
||||
}
|
||||
switch (offset) {
|
||||
case DATA_OFFSET:
|
||||
data = cmdReg.data;
|
||||
break;
|
||||
case ERROR_OFFSET:
|
||||
data = cmdReg.error;
|
||||
break;
|
||||
case NSECTOR_OFFSET:
|
||||
data = cmdReg.sec_count;
|
||||
break;
|
||||
case SECTOR_OFFSET:
|
||||
data = cmdReg.sec_num;
|
||||
break;
|
||||
case LCYL_OFFSET:
|
||||
data = cmdReg.cyl_low;
|
||||
break;
|
||||
case HCYL_OFFSET:
|
||||
data = cmdReg.cyl_high;
|
||||
break;
|
||||
case SELECT_OFFSET:
|
||||
data = cmdReg.drive;
|
||||
break;
|
||||
case STATUS_OFFSET:
|
||||
data = status;
|
||||
break;
|
||||
default:
|
||||
panic("Invalid IDE command register offset: %#x\n", offset);
|
||||
}
|
||||
}
|
||||
else if (type == CONTROL_BLOCK) {
|
||||
if (offset != ALTSTAT_OFFSET)
|
||||
|
@ -262,7 +261,6 @@ IdeDisk::read(const Addr &offset, RegType_t type)
|
|||
updateState(action);
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -78,33 +78,35 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data)
|
|||
|
||||
switch(size) {
|
||||
case sizeof(uint32_t):
|
||||
memcpy((uint8_t*)data, config.data + offset, sizeof(uint32_t));
|
||||
memcpy(data, &config.data[offset], sizeof(uint32_t));
|
||||
*(uint32_t*)data = htoa(*(uint32_t*)data);
|
||||
|
||||
DPRINTF(PCIDEV,
|
||||
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
|
||||
params()->deviceNum, params()->functionNum, offset, size,
|
||||
*(uint32_t*)(config.data + offset));
|
||||
*(uint32_t*)data);
|
||||
break;
|
||||
|
||||
case sizeof(uint16_t):
|
||||
memcpy((uint8_t*)data, config.data + offset, sizeof(uint16_t));
|
||||
memcpy(data, &config.data[offset], sizeof(uint16_t));
|
||||
*(uint16_t*)data = htoa(*(uint16_t*)data);
|
||||
|
||||
DPRINTF(PCIDEV,
|
||||
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
|
||||
params()->deviceNum, params()->functionNum, offset, size,
|
||||
*(uint16_t*)(config.data + offset));
|
||||
*(uint16_t*)data);
|
||||
break;
|
||||
|
||||
case sizeof(uint8_t):
|
||||
memcpy((uint8_t*)data, config.data + offset, sizeof(uint8_t));
|
||||
memcpy(data, &config.data[offset], sizeof(uint8_t));
|
||||
DPRINTF(PCIDEV,
|
||||
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
|
||||
params()->deviceNum, params()->functionNum, offset, size,
|
||||
(uint16_t)(*(uint8_t*)(config.data + offset)));
|
||||
*data);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("Invalid Read Size");
|
||||
panic("Invalid PCI configuration read size!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,17 +59,18 @@ TsunamiIO::RTCEvent::RTCEvent(Tsunami* t, Tick i)
|
|||
: Event(&mainEventQueue), tsunami(t), interval(i)
|
||||
{
|
||||
DPRINTF(MC146818, "RTC Event Initilizing\n");
|
||||
intr_count = 0;
|
||||
schedule(curTick + interval);
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiIO::RTCEvent::process()
|
||||
{
|
||||
static int intr_count = 0;
|
||||
DPRINTF(MC146818, "RTC Timer Interrupt\n");
|
||||
schedule(curTick + interval);
|
||||
//Actually interrupt the processor here
|
||||
tsunami->cchip->postRTC();
|
||||
|
||||
if (intr_count == 1023)
|
||||
tm.tm_sec = (tm.tm_sec + 1) % 60;
|
||||
|
||||
|
@ -113,10 +114,10 @@ TsunamiIO::ClockEvent::ClockEvent()
|
|||
DPRINTF(Tsunami, "Clock Event Initilizing\n");
|
||||
mode = 0;
|
||||
|
||||
current_count.whole = 0;
|
||||
latched_count.whole = 0;
|
||||
current_count = 0;
|
||||
latched_count = 0;
|
||||
latch_on = false;
|
||||
read_msb = false;
|
||||
read_byte = READ_LSB;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -128,7 +129,7 @@ TsunamiIO::ClockEvent::process()
|
|||
else
|
||||
schedule(curTick + interval);
|
||||
|
||||
current_count.whole--; //decrement count
|
||||
current_count--; //decrement count
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -138,7 +139,7 @@ TsunamiIO::ClockEvent::Program(int count)
|
|||
schedule(curTick + count * interval);
|
||||
status = 0;
|
||||
|
||||
current_count.whole = count;
|
||||
current_count = (uint16_t)count;
|
||||
}
|
||||
|
||||
const char *
|
||||
|
@ -162,32 +163,45 @@ TsunamiIO::ClockEvent::Status()
|
|||
void
|
||||
TsunamiIO::ClockEvent::LatchCount()
|
||||
{
|
||||
// behave like a real latch
|
||||
if(!latch_on) {
|
||||
latch_on = true;
|
||||
read_msb = false;
|
||||
latched_count.whole = current_count.whole;
|
||||
read_byte = READ_LSB;
|
||||
latched_count = current_count;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
TsunamiIO::ClockEvent::Read()
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
if(latch_on) {
|
||||
if(!read_msb) {
|
||||
read_msb = true;
|
||||
return latched_count.half.lsb;
|
||||
} else {
|
||||
switch (read_byte) {
|
||||
case READ_LSB:
|
||||
read_byte = READ_MSB;
|
||||
result = (uint8_t)latched_count;
|
||||
break;
|
||||
case READ_MSB:
|
||||
read_byte = READ_LSB;
|
||||
latch_on = false;
|
||||
return latched_count.half.msb;
|
||||
result = latched_count >> 8;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(!read_msb) {
|
||||
read_msb = true;
|
||||
return current_count.half.lsb;
|
||||
} else {
|
||||
return current_count.half.msb;
|
||||
switch (read_byte) {
|
||||
case READ_LSB:
|
||||
read_byte = READ_MSB;
|
||||
result = (uint8_t)current_count;
|
||||
break;
|
||||
case READ_MSB:
|
||||
read_byte = READ_LSB;
|
||||
result = current_count >> 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -75,18 +75,14 @@ class TsunamiIO : public PioDevice
|
|||
uint8_t mode;
|
||||
/** The status of the PIT */
|
||||
uint8_t status;
|
||||
/** The counts (current and latched) of the PIT */
|
||||
union {
|
||||
uint16_t whole;
|
||||
struct {
|
||||
uint8_t msb;
|
||||
uint8_t lsb;
|
||||
} half;
|
||||
} current_count, latched_count;
|
||||
|
||||
/** Thse state of the output latch of the PIT */
|
||||
/** The current count of the PIT */
|
||||
uint16_t current_count;
|
||||
/** The latched count of the PIT */
|
||||
uint16_t latched_count;
|
||||
/** The state of the output latch of the PIT */
|
||||
bool latch_on;
|
||||
bool read_msb;
|
||||
/** The next count half (byte) to read */
|
||||
enum {READ_LSB, READ_MSB} read_byte;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -158,6 +154,9 @@ class TsunamiIO : public PioDevice
|
|||
Tsunami* tsunami;
|
||||
Tick interval;
|
||||
|
||||
/** Count of the number of RTC interrupts that have occured */
|
||||
uint32_t intr_count;
|
||||
|
||||
public:
|
||||
/**
|
||||
* RTC Event initializes the RTC event by scheduling an event
|
||||
|
|
|
@ -93,8 +93,8 @@ FreebsdSystem::doCalibrateClocks(ExecContext *xc)
|
|||
uint8_t *ppc = physmem->dma_addr(ppc_paddr, sizeof(uint32_t));
|
||||
uint8_t *timer = physmem->dma_addr(timer_paddr, sizeof(uint32_t));
|
||||
|
||||
*(uint32_t *)ppc = 2000000000;
|
||||
*(uint32_t *)timer = 1193180;
|
||||
*(uint32_t *)ppc = htoa((uint32_t)2000000000);
|
||||
*(uint32_t *)timer = htoa((uint32_t)1193180);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue