summaryrefslogtreecommitdiff
path: root/dev
diff options
context:
space:
mode:
Diffstat (limited to 'dev')
-rw-r--r--dev/ide_ctrl.cc16
-rw-r--r--dev/ide_disk.cc125
-rw-r--r--dev/ide_disk.hh6
-rw-r--r--dev/ns_gige.cc2
-rw-r--r--dev/ns_gige.hh2
-rw-r--r--dev/pcidev.cc10
-rw-r--r--dev/tsunami_io.cc127
-rw-r--r--dev/tsunami_io.hh25
-rw-r--r--dev/tsunamireg.h12
9 files changed, 266 insertions, 59 deletions
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc
index 0037e06e0..964bd01c2 100644
--- a/dev/ide_ctrl.cc
+++ b/dev/ide_ctrl.cc
@@ -412,14 +412,10 @@ IdeController::read(MemReqPtr &req, 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;
if (!io_enabled)
return No_Fault;
@@ -430,11 +426,19 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
panic("IDE controller read of invalid size: %#x\n", req->size);
if (type != BMI_BLOCK) {
- assert(req->size != sizeof(uint32_t));
disk = getDisk(primary);
if (disks[disk])
- disks[disk]->read(offset, byte, cmdBlk, data);
+ 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);
+ }
+ else if (req->size == sizeof(uint8_t) && offset == DATA_OFFSET) {
+ panic("IDE read of data reg invalid size: %#x\n", req->size);
+ }
+ else {
+ *data = disks[disk]->read(offset, type);
+ }
} else {
memcpy((void *)data, &bmi_regs[offset], req->size);
}
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index 23d04bb5e..555eb023e 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -134,6 +134,8 @@ IdeDisk::reset(int id)
memset(&cmdReg, 0, sizeof(CommandReg_t));
memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
+ cmdReg.error = 1;
+
dmaInterfaceBytes = 0;
curPrdAddr = 0;
curSector = 0;
@@ -206,46 +208,61 @@ IdeDisk::bytesInDmaPage(Addr curAddr, uint32_t bytesLeft)
// Device registers read/write
////
-void
-IdeDisk::read(const Addr &offset, bool byte, bool cmdBlk, uint8_t *data)
+uint16_t
+IdeDisk::read(const Addr &offset, RegType_t type)
{
- DevAction_t action = ACT_NONE;
-
- if (cmdBlk) {
- if (offset < 0 || offset > sizeof(CommandReg_t))
- panic("Invalid disk command register offset: %#x\n", offset);
- if (!byte && offset != DATA_OFFSET)
- panic("Invalid 16-bit read, only allowed on data reg\n");
+ uint16_t data;
+ DevAction_t action = ACT_NONE;
- if (!byte)
- *(uint16_t *)data = *(uint16_t *)&cmdReg.data0;
- else
- *data = ((uint8_t *)&cmdReg)[offset];
+ if (type == COMMAND_BLOCK) {
- // determine if an action needs to be taken on the state machine
- if (offset == STATUS_OFFSET) {
+ if (offset == STATUS_OFFSET)
action = ACT_STAT_READ;
- *data = status; // status is in a shadow, explicity copy
- } else if (offset == DATA_OFFSET) {
- if (byte)
- action = ACT_DATA_READ_BYTE;
- else
- action = ACT_DATA_READ_SHORT;
- }
-
- } else {
+ 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);
+ }
+ }
+ else if (type == CONTROL_BLOCK) {
if (offset != ALTSTAT_OFFSET)
- panic("Invalid disk control register offset: %#x\n", offset);
-
- if (!byte)
- panic("Invalid 16-bit read from control block\n");
+ panic("Invalid IDE control register offset: %#x\n", offset);
- *data = status;
+ data = status;
}
if (action != ACT_NONE)
updateState(action);
+
+ return data;
+
}
void
@@ -261,9 +278,37 @@ IdeDisk::write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data)
panic("Invalid 16-bit write, only allowed on data reg\n");
if (!byte)
- *((uint16_t *)&cmdReg.data0) = *(uint16_t *)data;
- else
- ((uint8_t *)&cmdReg)[offset] = *data;
+ *((uint16_t *)&cmdReg.data) = *(uint16_t *)data;
+ else {
+ switch (offset) {
+ case DATA_OFFSET:
+ cmdReg.data = *data;
+ 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 SELECT_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) {
@@ -744,8 +789,10 @@ IdeDisk::intrPost()
intrPending = true;
// talk to controller to set interrupt
- if (ctrl)
+ if (ctrl){
+ ctrl->bmi_regs[BMIS0] |= IDEINTS;
ctrl->intrPost();
+ }
}
void
@@ -864,7 +911,7 @@ IdeDisk::updateState(DevAction_t action)
}
// put the first two bytes into the data register
- memcpy((void *)&cmdReg.data0, (void *)dataBuffer,
+ memcpy((void *)&cmdReg.data, (void *)dataBuffer,
sizeof(uint16_t));
if (!isIENSet()) {
@@ -893,7 +940,7 @@ IdeDisk::updateState(DevAction_t action)
// copy next short into data registers
if (drqBytesLeft)
- memcpy((void *)&cmdReg.data0,
+ memcpy((void *)&cmdReg.data,
(void *)&dataBuffer[SectorSize - drqBytesLeft],
sizeof(uint16_t));
}
@@ -966,7 +1013,7 @@ IdeDisk::updateState(DevAction_t action)
} else {
// copy the latest short into the data buffer
memcpy((void *)&dataBuffer[SectorSize - drqBytesLeft],
- (void *)&cmdReg.data0,
+ (void *)&cmdReg.data,
sizeof(uint16_t));
drqBytesLeft -= 2;
@@ -1090,8 +1137,7 @@ IdeDisk::serialize(ostream &os)
SERIALIZE_ENUM(event);
// Serialize device registers
- SERIALIZE_SCALAR(cmdReg.data0);
- SERIALIZE_SCALAR(cmdReg.data1);
+ SERIALIZE_SCALAR(cmdReg.data);
SERIALIZE_SCALAR(cmdReg.sec_count);
SERIALIZE_SCALAR(cmdReg.sec_num);
SERIALIZE_SCALAR(cmdReg.cyl_low);
@@ -1143,8 +1189,7 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
}
// Unserialize device registers
- UNSERIALIZE_SCALAR(cmdReg.data0);
- UNSERIALIZE_SCALAR(cmdReg.data1);
+ UNSERIALIZE_SCALAR(cmdReg.data);
UNSERIALIZE_SCALAR(cmdReg.sec_count);
UNSERIALIZE_SCALAR(cmdReg.sec_num);
UNSERIALIZE_SCALAR(cmdReg.cyl_low);
diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh
index 506f0c7cb..0fcd863ec 100644
--- a/dev/ide_disk.hh
+++ b/dev/ide_disk.hh
@@ -35,6 +35,7 @@
#include "dev/disk_image.hh"
#include "dev/ide_atareg.h"
+#include "dev/ide_ctrl.hh"
#include "dev/ide_wdcreg.h"
#include "dev/io_device.hh"
#include "sim/eventq.hh"
@@ -103,9 +104,8 @@ class PrdTableEntry {
#define DEV1 (1)
typedef struct CommandReg {
- uint8_t data0;
+ uint16_t data;
union {
- uint8_t data1;
uint8_t error;
uint8_t features;
};
@@ -272,7 +272,7 @@ class IdeDisk : public SimObject
}
// Device register read/write
- void read(const Addr &offset, bool byte, bool cmdBlk, uint8_t *data);
+ uint16_t read(const Addr &offset, RegType_t type);
void write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data);
// Start/abort functions
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
index 4e7deba90..0d446214d 100644
--- a/dev/ns_gige.cc
+++ b/dev/ns_gige.cc
@@ -1360,7 +1360,7 @@ void
NSGigE::regsReset()
{
memset(&regs, 0, sizeof(regs));
- regs.config = CFGR_LNKSTS;
+ regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
regs.mear = 0x22;
regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
// fill threshold to 32 bytes
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
index 143460b64..67f1b7ef5 100644
--- a/dev/ns_gige.hh
+++ b/dev/ns_gige.hh
@@ -99,7 +99,7 @@ class Bus;
class PciConfigAll;
/**
- * NS DP82830 Ethernet device model
+ * NS DP83820 Ethernet device model
*/
class NSGigE : public PciDev
{
diff --git a/dev/pcidev.cc b/dev/pcidev.cc
index f2bce33ca..93200a8c7 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -138,7 +138,13 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
case PCI_LATENCY_TIMER:
*(uint8_t *)&config.data[offset] = htoa(byte_value);
break;
-
+ /* Do nothing for these read-only registers */
+ case PCI0_INTERRUPT_PIN:
+ case PCI0_MINIMUM_GRANT:
+ case PCI0_MAXIMUM_LATENCY:
+ case PCI_CLASS_CODE:
+ case PCI_REVISION_ID:
+ break;
default:
panic("writing to a read only register");
}
@@ -192,7 +198,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/tsunami_io.cc b/dev/tsunami_io.cc
index da1062237..963bdc321 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -52,6 +52,8 @@ 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)
@@ -63,10 +65,16 @@ TsunamiIO::RTCEvent::RTCEvent(Tsunami* t, Tick i)
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;
+
+ intr_count = (intr_count + 1) % 1024;
+
}
const char *
@@ -104,6 +112,11 @@ TsunamiIO::ClockEvent::ClockEvent()
DPRINTF(Tsunami, "Clock Event Initilizing\n");
mode = 0;
+
+ current_count.whole = 0;
+ latched_count.whole = 0;
+ latch_on = false;
+ read_msb = false;
}
void
@@ -114,6 +127,8 @@ TsunamiIO::ClockEvent::process()
status = 0x20; // set bit that linux is looking for
else
schedule(curTick + interval);
+
+ current_count.whole--; //decrement count
}
void
@@ -122,6 +137,8 @@ TsunamiIO::ClockEvent::Program(int count)
DPRINTF(Tsunami, "Timer set to curTick + %d\n", count * interval);
schedule(curTick + count * interval);
status = 0;
+
+ current_count.whole = count;
}
const char *
@@ -143,6 +160,38 @@ TsunamiIO::ClockEvent::Status()
}
void
+TsunamiIO::ClockEvent::LatchCount()
+{
+ if(!latch_on) {
+ latch_on = true;
+ read_msb = false;
+ latched_count.whole = current_count.whole;
+ }
+}
+
+uint8_t
+TsunamiIO::ClockEvent::Read()
+{
+ if(latch_on) {
+ if(!read_msb) {
+ read_msb = true;
+ return latched_count.half.lsb;
+ } else {
+ latch_on = false;
+ return latched_count.half.msb;
+ }
+ } else {
+ if(!read_msb) {
+ read_msb = true;
+ return current_count.half.lsb;
+ } else {
+ return current_count.half.msb;
+ }
+ }
+}
+
+
+void
TsunamiIO::ClockEvent::serialize(std::ostream &os)
{
Tick time = scheduled() ? when() : 0;
@@ -207,12 +256,19 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n",
req->vaddr, req->size, req->vaddr & 0xfff);
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) + 0x20;
switch(req->size) {
case sizeof(uint8_t):
switch(daddr) {
+ // PIC1 mask read
+ case TSDEV_PIC1_MASK:
+ *(uint8_t*)data = ~mask1;
+ return No_Fault;
+ case TSDEV_PIC2_MASK:
+ *(uint8_t*)data = ~mask2;
+ return No_Fault;
case TSDEV_PIC1_ISR:
// !!! If this is modified 64bit case needs to be too
// Pal code has to do a 64 bit physical read because there is
@@ -226,6 +282,9 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
case TSDEV_TMR_CTL:
*(uint8_t*)data = timer2.Status();
return No_Fault;
+ case TSDEV_TMR0_DATA:
+ *(uint8_t *)data = timer0.Read();
+ return No_Fault;
case TSDEV_RTC_DATA:
switch(RTCAddress) {
case RTC_CNTRL_REGA:
@@ -257,6 +316,7 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
return No_Fault;
case RTC_DOM:
*(uint8_t *)data = tm.tm_mday;
+ return No_Fault;
case RTC_MON:
*(uint8_t *)data = tm.tm_mon + 1;
return No_Fault;
@@ -267,6 +327,14 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
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);
}
@@ -309,7 +377,7 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
req->vaddr, req->size, req->vaddr & 0xfff, dt64);
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) + 0x20;
switch(req->size) {
case sizeof(uint8_t):
@@ -355,8 +423,24 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
case TSDEV_TMR_CTL:
return No_Fault;
case TSDEV_TMR2_CTL:
- if ((*(uint8_t*)data & 0x30) != 0x30)
- panic("Only L/M write supported\n");
+ switch((*(uint8_t*)data >> 4) & 0x3) {
+ case 0x0:
+ switch(*(uint8_t*)data >> 6) {
+ case 0:
+ timer0.LatchCount();
+ break;
+ case 2:
+ timer2.LatchCount();
+ break;
+ default:
+ panic("Read Back Command not implemented\n");
+ }
+ break;
+ case 0x3:
+ break;
+ default:
+ panic("Only L/M write and Counter-Latch read supported\n");
+ }
switch(*(uint8_t*)data >> 6) {
case 0:
@@ -396,8 +480,41 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
case TSDEV_RTC_ADDR:
RTCAddress = *(uint8_t*)data;
return No_Fault;
+ case TSDEV_KBD:
+ return No_Fault;
case TSDEV_RTC_DATA:
- panic("RTC Write not implmented (rtc.o won't work)\n");
+ switch(RTCAddress) {
+ case RTC_CNTRL_REGA:
+ return No_Fault;
+ case RTC_CNTRL_REGB:
+ return No_Fault;
+ case RTC_CNTRL_REGC:
+ return No_Fault;
+ case RTC_CNTRL_REGD:
+ return No_Fault;
+ case RTC_SEC:
+ tm.tm_sec = *(uint8_t *)data;
+ return No_Fault;
+ case RTC_MIN:
+ tm.tm_min = *(uint8_t *)data;
+ return No_Fault;
+ case RTC_HR:
+ tm.tm_hour = *(uint8_t *)data;
+ return No_Fault;
+ case RTC_DOW:
+ tm.tm_wday = *(uint8_t *)data;
+ return No_Fault;
+ case RTC_DOM:
+ tm.tm_mday = *(uint8_t *)data;
+ return No_Fault;
+ case RTC_MON:
+ tm.tm_mon = *(uint8_t *)data - 1;
+ return No_Fault;
+ case RTC_YEAR:
+ tm.tm_year = *(uint8_t *)data + UNIX_YEAR_OFFSET;
+ 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 d5d106db3..dca651d4b 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;
- struct tm tm;
+ static struct tm tm;
/**
* In Tsunami RTC only has two i/o ports one for data and one for
@@ -75,6 +75,18 @@ 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 */
+ bool latch_on;
+ bool read_msb;
public:
/**
@@ -111,6 +123,17 @@ class TsunamiIO : public PioDevice
uint8_t Status();
/**
+ * Latch the count of the PIT.
+ */
+ void LatchCount();
+
+ /**
+ * The current PIT count.
+ * @return the count of the PIT
+ */
+ uint8_t Read();
+
+ /**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
diff --git a/dev/tsunamireg.h b/dev/tsunamireg.h
index 5fbfd5c31..8b290deb1 100644
--- a/dev/tsunamireg.h
+++ b/dev/tsunamireg.h
@@ -123,6 +123,18 @@
#define TSDEV_TMR2_DATA 0x42
#define TSDEV_TMR0_DATA 0x40
+/* Added for keyboard accesses */
+#define TSDEV_KBD 0x64
+
+/* Added for ATA PCI DMA */
+#define ATA_PCI_DMA 0x00
+#define ATA_PCI_DMA2 0x02
+#define ATA_PCI_DMA3 0x16
+#define ATA_PCI_DMA4 0x17
+#define ATA_PCI_DMA5 0x1a
+#define ATA_PCI_DMA6 0x11
+#define ATA_PCI_DMA7 0x14
+
#define TSDEV_RTC_ADDR 0x70
#define TSDEV_RTC_DATA 0x71