summaryrefslogtreecommitdiff
path: root/dev
diff options
context:
space:
mode:
authorBenjamin Nash <benash@umich.edu>2005-07-28 13:16:45 -0400
committerBenjamin Nash <benash@umich.edu>2005-07-28 13:16:45 -0400
commita115249eb07f6e3c9666bf408e214fcd38a665fb (patch)
tree21ea53a2698dc89fdc7f26fc81d45db6d69fbe4f /dev
parent648c3beb1d4735e423e77f5189c27c28e5b34493 (diff)
parent74fd4f68c5a7df2efba11497ba1ab5ab62b0b1bf (diff)
downloadgem5-a115249eb07f6e3c9666bf408e214fcd38a665fb.tar.xz
Merge zed.eecs.umich.edu:/.automount/fox/y/mserrano/m5_new/m5
into zed.eecs.umich.edu:/z/benash/bk/m5 SConscript: dev/ide_disk.hh: Formatting. dev/ide_ctrl.cc: Endianness dev/ide_disk.cc: dev/pcidev.cc: dev/tsunami_io.cc: dev/uart8250.cc: Clean up code. --HG-- extra : convert_revision : cb554f0e3a701371d2106cd7e11a4a22f773acc2
Diffstat (limited to 'dev')
-rw-r--r--dev/ide_ctrl.cc154
-rw-r--r--dev/ide_ctrl.hh17
-rw-r--r--dev/ide_disk.cc125
-rw-r--r--dev/ide_disk.hh2
-rw-r--r--dev/pcidev.cc12
-rw-r--r--dev/rtcreg.h14
-rw-r--r--dev/tsunami_io.cc62
-rw-r--r--dev/tsunami_io.hh11
-rw-r--r--dev/uart8250.cc4
-rw-r--r--dev/uart8250.hh3
10 files changed, 223 insertions, 181 deletions
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc
index a2b27d01a..2c86d27c7 100644
--- a/dev/ide_ctrl.cc
+++ b/dev/ide_ctrl.cc
@@ -75,13 +75,13 @@ IdeController::IdeController(Params *p)
bmi_size = BARSize[4];
// zero out all of the registers
- memset(bmi_regs, 0, sizeof(bmi_regs));
+ memset(bmi_regs.data, 0, sizeof(bmi_regs));
memset(pci_config_regs.data, 0, sizeof(pci_config_regs.data));
// setup initial values
pci_config_regs.idetim = htoa((uint32_t)0x80008000); // enable both channels
- *(uint8_t *)&bmi_regs[BMIS0] = 0x60;
- *(uint8_t *)&bmi_regs[BMIS1] = 0x60;
+ bmi_regs.bmis0 = DMA1CAP | DMA0CAP;
+ bmi_regs.bmis1 = DMA1CAP | DMA0CAP;
// reset all internal variables
io_enabled = false;
@@ -218,18 +218,18 @@ IdeController::setDmaComplete(IdeDisk *disk)
if (diskNum < 2) {
// clear the start/stop bit in the command register
- bmi_regs[BMIC0] &= ~SSBM;
+ bmi_regs.bmic0 &= ~SSBM;
// clear the bus master active bit in the status register
- bmi_regs[BMIS0] &= ~BMIDEA;
+ bmi_regs.bmis0 &= ~BMIDEA;
// set the interrupt bit
- bmi_regs[BMIS0] |= IDEINTS;
+ bmi_regs.bmis0 |= IDEINTS;
} else {
// clear the start/stop bit in the command register
- bmi_regs[BMIC1] &= ~SSBM;
+ bmi_regs.bmic1 &= ~SSBM;
// clear the bus master active bit in the status register
- bmi_regs[BMIS1] &= ~BMIDEA;
+ bmi_regs.bmis1 &= ~BMIDEA;
// set the interrupt bit
- bmi_regs[BMIS1] |= IDEINTS;
+ bmi_regs.bmis1 |= IDEINTS;
}
}
@@ -261,7 +261,8 @@ IdeController::ReadConfig(int offset, int size, uint8_t *data)
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::ReadConfig(offset, size, data);
- } else if (offset >= IDE_CTRL_CONFIG_START && (offset + size) <= IDE_CTRL_CONFIG_END) {
+ } else if (offset >= IDE_CTRL_CONFIG_START &&
+ (offset + size) <= IDE_CTRL_CONFIG_END) {
config_offset = offset - IDE_CTRL_CONFIG_START;
dword = 0;
@@ -299,7 +300,8 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::WriteConfig(offset, size, data);
- } else if (offset >= IDE_CTRL_CONFIG_START && (offset + size) <= IDE_CTRL_CONFIG_END) {
+ } else if (offset >= IDE_CTRL_CONFIG_START &&
+ (offset + size) <= IDE_CTRL_CONFIG_END) {
config_offset = offset - IDE_CTRL_CONFIG_START;
@@ -401,7 +403,6 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
RegType_t type;
int disk;
-
/* union
* +-- --+-- --+-- --+-- --+
* | 0 | 1 | 2 | 3 |
@@ -430,15 +431,15 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
case BMI_BLOCK:
switch (req->size) {
case sizeof(uint8_t):
- memcpy(&byte, &bmi_regs[offset], sizeof(uint8_t));
+ memcpy(&byte, &bmi_regs.data[offset], sizeof(uint8_t));
*data = byte;
break;
case sizeof(uint16_t):
- memcpy(&byte, &bmi_regs[offset], sizeof(uint16_t));
+ memcpy(&byte, &bmi_regs.data[offset], sizeof(uint16_t));
*(uint16_t*)data = htoa(word[0]);
break;
case sizeof(uint32_t):
- memcpy(&byte, &bmi_regs[offset], sizeof(uint32_t));
+ memcpy(&byte, &bmi_regs.data[offset], sizeof(uint32_t));
*(uint32_t*)data = htoa(dword);
break;
default:
@@ -479,6 +480,8 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
panic("IDE read of command reg of invalid size: %#x\n", req->size);
}
break;
+ default:
+ panic("IDE controller read of unknown register block type!\n");
}
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
@@ -492,40 +495,29 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
{
Addr offset;
bool primary;
- bool byte;
- bool cmdBlk;
RegType_t type;
int disk;
- parseAddr(req->paddr, offset, primary, type);
- byte = (req->size == sizeof(uint8_t)) ? true : false;
- cmdBlk = (type == COMMAND_BLOCK) ? true : false;
+ union {
+ uint8_t byte;
+ uint16_t word[2];
+ uint32_t dword;
+ };
- DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
- offset, req->size,
- (*(uint32_t *)data) & (0xffffffff >> 8 * (4 - req->size)));
+ dword = 0;
+
+ parseAddr(req->paddr, offset, primary, type);
uint8_t oldVal, newVal;
if (!io_enabled)
return No_Fault;
- if (type == BMI_BLOCK && !bm_enabled)
- return No_Fault;
-
- if (type != BMI_BLOCK) {
- // shadow the dev bit
- if (type == COMMAND_BLOCK && offset == IDE_SELECT_OFFSET) {
- uint8_t *devBit = (primary ? &dev[0] : &dev[1]);
- *devBit = ((*data & IDE_SELECT_DEV_BIT) ? 1 : 0);
- }
-
- assert(req->size != sizeof(uint32_t));
+ switch (type) {
+ case BMI_BLOCK:
+ if (!bm_enabled)
+ return No_Fault;
- disk = getDisk(primary);
- if (disks[disk])
- disks[disk]->write(offset, byte, cmdBlk, data);
- } else {
switch (offset) {
// Bus master IDE command register
case BMIC1:
@@ -536,8 +528,9 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
// select the current disk based on DEV bit
disk = getDisk(primary);
- oldVal = bmi_regs[offset];
- newVal = *data;
+ oldVal = bmi_regs.data[offset];
+ byte = *data;
+ newVal = byte;
// if a DMA transfer is in progress, R/W control cannot change
if (oldVal & SSBM) {
@@ -553,7 +546,7 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
DPRINTF(IdeCtrl, "Stopping DMA transfer\n");
// clear the BMIDEA bit
- bmi_regs[offset + 0x2] &= ~BMIDEA;
+ bmi_regs.data[offset + 0x2] &= ~BMIDEA;
if (disks[disk] == NULL)
panic("DMA stop for disk %d which does not exist\n",
@@ -566,7 +559,7 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
DPRINTF(IdeCtrl, "Starting DMA transfer\n");
// set the BMIDEA bit
- bmi_regs[offset + 0x2] |= BMIDEA;
+ bmi_regs.data[offset + 0x2] |= BMIDEA;
if (disks[disk] == NULL)
panic("DMA start for disk %d which does not exist\n",
@@ -574,14 +567,14 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
// inform the disk of the DMA transfer start
if (primary)
- disks[disk]->startDma(*(uint32_t *)&bmi_regs[BMIDTP0]);
+ disks[disk]->startDma(bmi_regs.bmidtp0);
else
- disks[disk]->startDma(*(uint32_t *)&bmi_regs[BMIDTP1]);
+ disks[disk]->startDma(bmi_regs.bmidtp1);
}
}
// update the register value
- bmi_regs[offset] = newVal;
+ bmi_regs.data[offset] = newVal;
break;
// Bus master IDE status register
@@ -590,8 +583,9 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
if (req->size != sizeof(uint8_t))
panic("Invalid BMIS write size: %x\n", req->size);
- oldVal = bmi_regs[offset];
- newVal = *data;
+ oldVal = bmi_regs.data[offset];
+ byte = *data;
+ newVal = byte;
// the BMIDEA bit is RO
newVal |= (oldVal & BMIDEA);
@@ -607,7 +601,7 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
else
(oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE;
- bmi_regs[offset] = newVal;
+ bmi_regs.data[offset] = newVal;
break;
// Bus master IDE descriptor table pointer register
@@ -616,7 +610,8 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
if (req->size != sizeof(uint32_t))
panic("Invalid BMIDTP write size: %x\n", req->size);
- *(uint32_t *)&bmi_regs[offset] = *(uint32_t *)data & ~0x3;
+ dword = htoa(*(uint32_t *)data & ~0x3);
+ *(uint32_t *)&bmi_regs.data[offset] = dword;
break;
default:
@@ -627,10 +622,53 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
req->size);
// do a default copy of data into the registers
- memcpy((void *)&bmi_regs[offset], data, req->size);
+ memcpy((void *)&bmi_regs.data[offset], data, req->size);
+ }
+ break;
+ case COMMAND_BLOCK:
+ if (offset == IDE_SELECT_OFFSET) {
+ uint8_t *devBit = (primary ? &dev[0] : &dev[1]);
+ *devBit = ((*data & IDE_SELECT_DEV_BIT) ? 1 : 0);
}
+ // fall-through ok!
+ case CONTROL_BLOCK:
+ disk = getDisk(primary);
+
+ if (disks[disk] == NULL)
+ break;
+
+ switch (offset) {
+ case DATA_OFFSET:
+ switch (req->size) {
+ case sizeof(uint16_t):
+ word[0] = htoa(*(uint16_t*)data);
+ disks[disk]->write(offset, type, (uint8_t*)&word[0]);
+ break;
+
+ case sizeof(uint32_t):
+ dword = htoa(*(uint32_t*)data);
+ disks[disk]->write(offset, type, (uint8_t*)&word[0]);
+ disks[disk]->write(offset, type, (uint8_t*)&word[1]);
+ break;
+ default:
+ panic("IDE write of data reg invalid size: %#x\n", req->size);
+ }
+ break;
+ default:
+ if (req->size == sizeof(uint8_t)) {
+ byte = *data;
+ disks[disk]->write(offset, type, &byte);
+ } else
+ panic("IDE write of command reg of invalid size: %#x\n", req->size);
+ }
+ break;
+ default:
+ panic("IDE controller write of unknown register block type!\n");
}
+ DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
+ offset, req->size, dword);
+
return No_Fault;
}
@@ -657,14 +695,14 @@ IdeController::serialize(std::ostream &os)
SERIALIZE_SCALAR(bmi_size);
// Serialize registers
- SERIALIZE_ARRAY(bmi_regs, 16);
- SERIALIZE_ARRAY(dev, 2);
- SERIALIZE_ARRAY(pci_config_regs.data, 22);
+ SERIALIZE_ARRAY(bmi_regs.data, sizeof(bmi_regs));
+ SERIALIZE_ARRAY(dev, sizeof(dev));
+ SERIALIZE_ARRAY(pci_config_regs.data, sizeof(pci_config_regs));
// Serialize internal state
SERIALIZE_SCALAR(io_enabled);
SERIALIZE_SCALAR(bm_enabled);
- SERIALIZE_ARRAY(cmd_in_progress, 4);
+ SERIALIZE_ARRAY(cmd_in_progress, sizeof(cmd_in_progress));
}
void
@@ -686,14 +724,14 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(bmi_size);
// Unserialize registers
- UNSERIALIZE_ARRAY(bmi_regs, 16);
- UNSERIALIZE_ARRAY(dev, 2);
- UNSERIALIZE_ARRAY(pci_config_regs.data, 22);
+ UNSERIALIZE_ARRAY(bmi_regs.data, sizeof(bmi_regs));
+ UNSERIALIZE_ARRAY(dev, sizeof(dev));
+ UNSERIALIZE_ARRAY(pci_config_regs.data, sizeof(pci_config_regs));
// Unserialize internal state
UNSERIALIZE_SCALAR(io_enabled);
UNSERIALIZE_SCALAR(bm_enabled);
- UNSERIALIZE_ARRAY(cmd_in_progress, 4);
+ UNSERIALIZE_ARRAY(cmd_in_progress, sizeof(cmd_in_progress));
if (pioInterface) {
pioInterface->addAddrRange(RangeSize(pri_cmd_addr, pri_cmd_size));
diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh
index 2164f2f4a..51bdd93b1 100644
--- a/dev/ide_ctrl.hh
+++ b/dev/ide_ctrl.hh
@@ -110,7 +110,22 @@ class IdeController : public PciDev
private:
/** Registers used for bus master interface */
- uint8_t bmi_regs[16];
+ union {
+ uint8_t data[16];
+
+ struct {
+ uint8_t bmic0;
+ uint8_t padding_0;
+ uint8_t bmis0;
+ uint8_t padding_1;
+ uint32_t bmidtp0;
+ uint8_t bmic1;
+ uint8_t padding_2;
+ uint8_t bmis1;
+ uint8_t padding_3;
+ uint32_t bmidtp1;
+ };
+ } bmi_regs;
/** Shadows of the device select bit */
uint8_t dev[2];
/** Registers used in device specific PCI configuration */
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index 74d2ae6de..39eb2e698 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -218,18 +218,12 @@ IdeDisk::read(const Addr &offset, RegType_t type, uint8_t *data)
switch (type) {
case COMMAND_BLOCK:
- if (offset == STATUS_OFFSET)
- action = ACT_STAT_READ;
- else if (offset == DATA_OFFSET)
- action = ACT_DATA_READ_SHORT;
-
switch (offset) {
- // Data transfers occur 16 bits at a time
+ // Data transfers occur two bytes at a time
case DATA_OFFSET:
- // use memcpy to preserve IDE's little-endianess
memcpy(data, &cmdReg.data, sizeof(uint16_t));
+ action = ACT_DATA_READ_SHORT;
break;
- // All other transfers are 8-bit
case ERROR_OFFSET:
*data = cmdReg.error;
break;
@@ -250,6 +244,7 @@ IdeDisk::read(const Addr &offset, RegType_t type, uint8_t *data)
break;
case STATUS_OFFSET:
*data = status;
+ action = ACT_STAT_READ;
break;
default:
panic("Invalid IDE command register offset: %#x\n", offset);
@@ -261,7 +256,6 @@ IdeDisk::read(const Addr &offset, RegType_t type, uint8_t *data)
else
panic("Invalid IDE control register offset: %#x\n", offset);
break;
-
default:
panic("Unknown register block!\n");
}
@@ -271,76 +265,59 @@ IdeDisk::read(const Addr &offset, RegType_t type, uint8_t *data)
}
void
-IdeDisk::write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data)
+IdeDisk::write(const Addr &offset, RegType_t type, const uint8_t *data)
{
DevAction_t action = ACT_NONE;
- if (cmdBlk) {
-
- if (!byte && offset != DATA_OFFSET)
- panic("Invalid 16-bit write, only allowed on data reg\n");
-
- if (!byte)
- *((uint16_t *)&cmdReg.data) = *(uint16_t *)data;
- else {
- switch (offset) {
- case DATA_OFFSET:
- memcpy(&cmdReg.data, data, sizeof(uint16_t));
- break;
- case FEATURES_OFFSET:
- //cmdReg.features = *data;
- break;
- case NSECTOR_OFFSET:
- cmdReg.sec_count = *data;
- break;
- case SECTOR_OFFSET:
- cmdReg.sec_num = *data;
- break;
- case LCYL_OFFSET:
- cmdReg.cyl_low = *data;
- break;
- case HCYL_OFFSET:
- cmdReg.cyl_high = *data;
- break;
- case DRIVE_OFFSET:
- cmdReg.drive = *data;
- break;
- case COMMAND_OFFSET:
- cmdReg.command = *data;
- break;
- default:
- panic("Invalid IDE command register offset: %#x\n", offset);
- }
- }
-
- // determine if an action needs to be taken on the state machine
- if (offset == COMMAND_OFFSET) {
- action = ACT_CMD_WRITE;
- } else if (offset == DATA_OFFSET) {
- if (byte)
- action = ACT_DATA_WRITE_BYTE;
- else
- action = ACT_DATA_WRITE_SHORT;
- } else if (offset == DRIVE_OFFSET) {
+ switch (type) {
+ case COMMAND_BLOCK:
+ switch (offset) {
+ case DATA_OFFSET:
+ memcpy(&cmdReg.data, data, sizeof(uint16_t));
+ action = ACT_DATA_WRITE_SHORT;
+ break;
+ case FEATURES_OFFSET:
+ break;
+ case NSECTOR_OFFSET:
+ cmdReg.sec_count = *data;
+ break;
+ case SECTOR_OFFSET:
+ cmdReg.sec_num = *data;
+ break;
+ case LCYL_OFFSET:
+ cmdReg.cyl_low = *data;
+ break;
+ case HCYL_OFFSET:
+ cmdReg.cyl_high = *data;
+ break;
+ case DRIVE_OFFSET:
+ cmdReg.drive = *data;
action = ACT_SELECT_WRITE;
+ break;
+ case COMMAND_OFFSET:
+ cmdReg.command = *data;
+ action = ACT_CMD_WRITE;
+ break;
+ default:
+ panic("Invalid IDE command register offset: %#x\n", offset);
}
-
- } else {
- if (offset != CONTROL_OFFSET)
- panic("Invalid disk control register offset: %#x\n", offset);
-
- if (!byte)
- panic("Invalid 16-bit write to control block\n");
-
- if (*data & CONTROL_RST_BIT) {
- // force the device into the reset state
- devState = Device_Srst;
- action = ACT_SRST_SET;
- } else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT)) {
- action = ACT_SRST_CLEAR;
+ break;
+ case CONTROL_BLOCK:
+ if (offset == CONTROL_OFFSET) {
+ if (*data & CONTROL_RST_BIT) {
+ // force the device into the reset state
+ devState = Device_Srst;
+ action = ACT_SRST_SET;
+ } else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT))
+ action = ACT_SRST_CLEAR;
+
+ nIENBit = (*data & CONTROL_IEN_BIT) ? true : false;
}
-
- nIENBit = (*data & CONTROL_IEN_BIT) ? true : false;
+ else
+ panic("Invalid IDE control register offset: %#x\n", offset);
+ break;
+ default:
+ panic("Unknown register block!\n");
}
if (action != ACT_NONE)
@@ -793,7 +770,7 @@ IdeDisk::intrPost()
// talk to controller to set interrupt
if (ctrl) {
- ctrl->bmi_regs[BMIS0] |= IDEINTS;
+ ctrl->bmi_regs.bmis0 |= IDEINTS;
ctrl->intrPost();
}
}
diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh
index 9799e2d38..ceec11925 100644
--- a/dev/ide_disk.hh
+++ b/dev/ide_disk.hh
@@ -271,7 +271,7 @@ class IdeDisk : public SimObject
// Device register read/write
void read(const Addr &offset, RegType_t type, uint8_t *data);
- void write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data);
+ void write(const Addr &offset, RegType_t type, const uint8_t *data);
// Start/abort functions
void startDma(const uint32_t &prdTableBase);
diff --git a/dev/pcidev.cc b/dev/pcidev.cc
index 31c44bffa..c74fb035c 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -115,10 +115,6 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
uint32_t barnum;
- uint8_t byte_value;
- uint16_t half_value;
- uint32_t word_value;
-
DPRINTF(PCIDEV,
"write device: %#x function: %#x reg: %#x size: %d data: %#x\n",
params()->deviceNum, params()->functionNum, offset, size,
@@ -128,7 +124,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
switch (size) {
case sizeof(uint8_t): // 1-byte access
- byte_value = data;
+ uint8_t byte_value = data;
switch (offset) {
case PCI0_INTERRUPT_LINE:
case PCI_CACHE_LINE_SIZE:
@@ -148,7 +144,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
break;
case sizeof(uint16_t): // 2-byte access
- half_value = data;
+ uint16_t half_value = data;
switch (offset) {
case PCI_COMMAND:
case PCI_STATUS:
@@ -162,7 +158,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
break;
case sizeof(uint32_t): // 4-byte access
- word_value = data;
+ uint32_t word_value = data;
switch (offset) {
case PCI0_BASE_ADDR0:
case PCI0_BASE_ADDR1:
@@ -194,7 +190,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
htoa((word_value & ~0x3) |
(htoa(config.data[offset]) & 0x3));
- if (word_value != 0x1) {
+ if (word_value &= ~0x1) {
Addr base_addr = (word_value & ~0x1) + TSUNAMI_PCI0_IO;
Addr base_size = BARSize[barnum];
diff --git a/dev/rtcreg.h b/dev/rtcreg.h
index 0b33c25b2..032e22ab5 100644
--- a/dev/rtcreg.h
+++ b/dev/rtcreg.h
@@ -36,8 +36,22 @@
#define RTC_DOM 0x07
#define RTC_MON 0x08
#define RTC_YEAR 0x09
+
#define RTC_CNTRL_REGA 0x0A
+#define RTCA_1024HZ 0x06 /* 1024Hz periodic interrupt frequency */
+#define RTCA_32768HZ 0x20 /* 22-stage divider, 32.768KHz timebase */
+#define RTCA_UIP 0x80 /* 1 = date and time update in progress */
+
#define RTC_CNTRL_REGB 0x0B
+#define RTCB_DST 0x01 /* USA Daylight Savings Time enable */
+#define RTCB_24HR 0x02 /* 0 = 12 hours, 1 = 24 hours */
+#define RTCB_BIN 0x04 /* 0 = BCD, 1 = Binary coded time */
+#define RTCB_SQWE 0x08 /* 1 = output sqare wave at SQW pin */
+#define RTCB_UPDT_IE 0x10 /* 1 = enable update-ended interrupt */
+#define RTCB_ALRM_IE 0x20 /* 1 = enable alarm interrupt */
+#define RTCB_PRDC_IE 0x40 /* 1 = enable periodic clock interrupt */
+#define RTCB_NO_UPDT 0x80 /* stop clock updates */
+
#define RTC_CNTRL_REGC 0x0C
#define RTC_CNTRL_REGD 0x0D
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index 82fe40e0a..f9dcbb8e0 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -52,14 +52,11 @@ using namespace std;
#define UNIX_YEAR_OFFSET 52
-struct tm TsunamiIO::tm = { 0 };
-
// Timer Event for Periodic interrupt of RTC
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);
}
@@ -70,11 +67,6 @@ TsunamiIO::RTCEvent::process()
schedule(curTick + interval);
//Actually interrupt the processor here
tsunami->cchip->postRTC();
-
- if (intr_count == 1023)
- tm.tm_sec = (tm.tm_sec + 1) % 60;
-
- intr_count = (intr_count + 1) % 1024;
}
const char *
@@ -98,6 +90,11 @@ TsunamiIO::RTCEvent::unserialize(Checkpoint *cp, const std::string &section)
reschedule(time);
}
+void
+TsunamiIO::RTCEvent::scheduleIntr()
+{
+ schedule(curTick + interval);
+}
// Timer Event for PIT Timers
TsunamiIO::ClockEvent::ClockEvent()
@@ -125,10 +122,8 @@ TsunamiIO::ClockEvent::process()
DPRINTF(Tsunami, "Timer Interrupt\n");
if (mode == 0)
status = 0x20; // set bit that linux is looking for
- else
- schedule(curTick + interval);
-
- current_count--; //decrement count
+ else if (mode == 2)
+ schedule(curTick + current_count*interval);
}
void
@@ -301,12 +296,12 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
case TSDEV_RTC_DATA:
switch(RTCAddress) {
case RTC_CNTRL_REGA:
- *(uint8_t*)data = uip << 7 | 0x26;
+ *(uint8_t*)data = uip << 7 | RTCA_32768HZ | RTCA_1024HZ;
uip = !uip;
return No_Fault;
case RTC_CNTRL_REGB:
// DM and 24/12 and UIE
- *(uint8_t*)data = 0x46;
+ *(uint8_t*)data = RTCB_PRDC_IE | RTCB_BIN | RTCB_24HR;
return No_Fault;
case RTC_CNTRL_REGC:
// If we want to support RTC user access in linux
@@ -331,7 +326,7 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
*(uint8_t *)data = tm.tm_hour;
return No_Fault;
case RTC_DOW:
- *(uint8_t *)data = tm.tm_wday;
+ *(uint8_t *)data = tm.tm_wday + 1;
return No_Fault;
case RTC_DOM:
*(uint8_t *)data = tm.tm_mday;
@@ -340,20 +335,11 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
*(uint8_t *)data = tm.tm_mon + 1;
return No_Fault;
case RTC_YEAR:
- *(uint8_t *)data = tm.tm_year - UNIX_YEAR_OFFSET;
+ *(uint8_t *)data = tm.tm_year;
return No_Fault;
default:
panic("Unknown RTC Address\n");
}
-
- /* Added for keyboard reads */
- case TSDEV_KBD:
- *(uint8_t *)data = 0x00;
- return No_Fault;
- /* Added for ATA PCI DMA */
- case ATA_PCI_DMA:
- *(uint8_t *)data = 0x00;
- return No_Fault;
default:
panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
}
@@ -447,10 +433,10 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
switch(*(uint8_t*)data >> 6) {
case 0:
timer0.LatchCount();
- break;
+ return No_Fault;
case 2:
timer2.LatchCount();
- break;
+ return No_Fault;
default:
panic("Read Back Command not implemented\n");
}
@@ -488,9 +474,10 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
/* two writes before we actually start the Timer
so I set a flag in the timerData */
if(timerData & 0x1000) {
- timerData &= 0x1000;
+ timerData &= ~0x1000;
timerData += *(uint8_t*)data << 8;
timer0.Program(timerData);
+ timerData = 0;
} else {
timerData = *(uint8_t*)data;
timerData |= 0x1000;
@@ -504,12 +491,26 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
case TSDEV_RTC_DATA:
switch(RTCAddress) {
case RTC_CNTRL_REGA:
+ if (*data != (RTCA_32768HZ | RTCA_1024HZ))
+ panic("Unimplemented RTC register A value write!\n");
return No_Fault;
case RTC_CNTRL_REGB:
+ if ((*data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR))
+ panic("Write to RTC reg B bits that are not implemented!\n");
+
+ if (*data & RTCB_PRDC_IE) {
+ if (!rtc.scheduled())
+ rtc.scheduleIntr();
+ } else {
+ if (rtc.scheduled())
+ rtc.deschedule();
+ }
return No_Fault;
case RTC_CNTRL_REGC:
+ panic("Write to RTC reg C not implemented!\n");
return No_Fault;
case RTC_CNTRL_REGD:
+ panic("Write to RTC reg D not implemented!\n");
return No_Fault;
case RTC_SEC:
tm.tm_sec = *(uint8_t *)data;
@@ -527,12 +528,11 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
tm.tm_mday = *(uint8_t *)data;
return No_Fault;
case RTC_MON:
- tm.tm_mon = *(uint8_t *)data - 1;
+ tm.tm_mon = *(uint8_t *)data;
return No_Fault;
case RTC_YEAR:
- tm.tm_year = *(uint8_t *)data + UNIX_YEAR_OFFSET;
+ tm.tm_year = *(uint8_t *)data;
return No_Fault;
- //panic("RTC Write not implmented (rtc.o won't work)\n");
}
default:
panic("I/O Write - va%#x size %d\n", req->vaddr, req->size);
diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh
index 4b28635e8..7054b4ff4 100644
--- a/dev/tsunami_io.hh
+++ b/dev/tsunami_io.hh
@@ -51,7 +51,7 @@ class TsunamiIO : public PioDevice
/** The size of mappad from the above address */
static const Addr size = 0xff;
- static struct tm tm;
+ struct tm tm;
/**
* In Tsunami RTC only has two i/o ports one for data and one for
@@ -154,9 +154,6 @@ 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
@@ -165,7 +162,7 @@ class TsunamiIO : public PioDevice
RTCEvent(Tsunami* t, Tick i);
/**
- * Interrupth the processor and reschedule the event.
+ * Interrupt the processor and reschedule the event.
*/
virtual void process();
@@ -187,6 +184,8 @@ class TsunamiIO : public PioDevice
* @param section The section name of this object
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ void scheduleIntr();
};
/** uip UpdateInProgess says that the rtc is updating, but we just fake it
@@ -243,7 +242,7 @@ class TsunamiIO : public PioDevice
* This variable contains a flag as to how many writes have happened, and
* the time so far.
*/
- uint32_t timerData;
+ uint16_t timerData;
public:
/**
diff --git a/dev/uart8250.cc b/dev/uart8250.cc
index ad3232686..013cbfd00 100644
--- a/dev/uart8250.cc
+++ b/dev/uart8250.cc
@@ -148,9 +148,9 @@ Uart8250::read(MemReqPtr &req, uint8_t *data)
DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status);
status &= ~TX_INT;
if (status & RX_INT)
- *(uint8_t*)data = 0x4;
+ *(uint8_t*)data = IIR_RXID;
else
- *(uint8_t*)data = 0x1;
+ *(uint8_t*)data = IIR_NOPEND;
break;
case 0x3: // Line Control Register (LCR)
*(uint8_t*)data = LCR;
diff --git a/dev/uart8250.hh b/dev/uart8250.hh
index 06a798e26..e85ad72c8 100644
--- a/dev/uart8250.hh
+++ b/dev/uart8250.hh
@@ -38,6 +38,9 @@
#include "dev/io_device.hh"
#include "dev/uart.hh"
+#define IIR_NOPEND 0x1
+#define IIR_RXID 0x4
+
class SimConsole;
class Platform;