ghgfsdf
dev/pciconfigall.cc: removed union. dev/pcidev.cc: . dev/rtcreg.h: more macros to avoid magic numbers. dev/tsunami_io.cc: replaced magic numbers, no more advancing RTC as it isn't reaaly necessary. dev/tsunami_io.hh: removed declarations of things that go unused. dev/uart8250.cc: reading the Interrupt ID register should clear TX interrupt flag. dev/uart8250.hh: useful #defines. kern/freebsd/freebsd_system.cc: kern/freebsd/freebsd_system.hh: nothing. python/m5/objects/Pci.py: new PciFake. --HG-- extra : convert_revision : 88259704f5b215591d1416360180810fcda14d26
This commit is contained in:
parent
4f2480a18b
commit
6a8ae7a6a0
10 changed files with 105 additions and 84 deletions
|
@ -152,21 +152,17 @@ PciConfigAll::write(MemReqPtr &req, const uint8_t *data)
|
|||
int func = (daddr >> 8) & 0x7;
|
||||
int reg = daddr & 0xFF;
|
||||
|
||||
union {
|
||||
uint8_t byte_value;
|
||||
uint16_t half_value;
|
||||
uint32_t word_value;
|
||||
};
|
||||
uint32_t word_value = 0;
|
||||
|
||||
if (devices[device][func] == NULL)
|
||||
panic("Attempting to write to config space on non-existant device\n");
|
||||
else {
|
||||
switch (req->size) {
|
||||
case sizeof(uint8_t):
|
||||
byte_value = *(uint8_t*)data;
|
||||
word_value = *(uint8_t*)data;
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
half_value = *(uint16_t*)data;
|
||||
word_value = *(uint16_t*)data;
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
word_value = *(uint32_t*)data;
|
||||
|
|
|
@ -73,41 +73,38 @@ PciDev::PciDev(Params *p)
|
|||
void
|
||||
PciDev::ReadConfig(int offset, int size, uint8_t *data)
|
||||
{
|
||||
union {
|
||||
uint8_t byte;
|
||||
uint16_t word;
|
||||
uint32_t dword;
|
||||
};
|
||||
|
||||
if (offset >= PCI_DEVICE_SPECIFIC)
|
||||
panic("Device specific PCI config space not implemented!\n");
|
||||
|
||||
dword = 0;
|
||||
|
||||
switch(size) {
|
||||
case 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*)data);
|
||||
break;
|
||||
|
||||
case 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*)data);
|
||||
break;
|
||||
|
||||
case 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,
|
||||
*data);
|
||||
memcpy(&byte, &config.data[offset], size);
|
||||
*data = byte;
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
memcpy(&byte, &config.data[offset], size);
|
||||
*(uint16_t*)data = htoa(word);
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
memcpy(&byte, &config.data[offset], size);
|
||||
*(uint32_t*)data = htoa(dword);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("Invalid PCI configuration read size!\n");
|
||||
}
|
||||
|
||||
DPRINTF(PCIDEV,
|
||||
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
|
||||
params()->deviceNum, params()->functionNum, offset, size,
|
||||
htoa(dword));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -118,22 +115,16 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
|
|||
|
||||
uint32_t barnum;
|
||||
|
||||
union {
|
||||
uint8_t byte_value;
|
||||
uint16_t half_value;
|
||||
uint32_t word_value;
|
||||
};
|
||||
word_value = data;
|
||||
|
||||
DPRINTF(PCIDEV,
|
||||
"write device: %#x function: %#x reg: %#x size: %d data: %#x\n",
|
||||
params()->deviceNum, params()->functionNum, offset, size,
|
||||
word_value);
|
||||
data);
|
||||
|
||||
barnum = (offset - PCI0_BASE_ADDR0) >> 2;
|
||||
|
||||
switch (size) {
|
||||
case sizeof(uint8_t): // 1-byte access
|
||||
uint8_t byte_value = data;
|
||||
switch (offset) {
|
||||
case PCI0_INTERRUPT_LINE:
|
||||
case PCI_CACHE_LINE_SIZE:
|
||||
|
@ -153,6 +144,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
|
|||
break;
|
||||
|
||||
case sizeof(uint16_t): // 2-byte access
|
||||
uint16_t half_value = data;
|
||||
switch (offset) {
|
||||
case PCI_COMMAND:
|
||||
case PCI_STATUS:
|
||||
|
@ -165,10 +157,8 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
|
|||
}
|
||||
break;
|
||||
|
||||
case sizeof(uint16_t)+1: // 3-byte access
|
||||
panic("invalid access size");
|
||||
|
||||
case sizeof(uint32_t): // 4-byte access
|
||||
uint32_t word_value = data;
|
||||
switch (offset) {
|
||||
case PCI0_BASE_ADDR0:
|
||||
case PCI0_BASE_ADDR1:
|
||||
|
@ -183,12 +173,12 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
|
|||
// This is I/O Space, bottom two bits are read only
|
||||
if (htoa(config.data[offset]) & 0x1) {
|
||||
*(uint32_t *)&config.data[offset] = htoa(
|
||||
~(BARSize[barnum] - 1) |
|
||||
(~(BARSize[barnum] - 1) & ~0x3) |
|
||||
(htoa(config.data[offset]) & 0x3));
|
||||
} else {
|
||||
// This is memory space, bottom four bits are read only
|
||||
*(uint32_t *)&config.data[offset] = htoa(
|
||||
~(BARSize[barnum] - 1) |
|
||||
(~(BARSize[barnum] - 1) & ~0xF) |
|
||||
(htoa(config.data[offset]) & 0xF));
|
||||
}
|
||||
} else {
|
||||
|
@ -200,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];
|
||||
|
||||
|
@ -263,6 +253,9 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
|
|||
DPRINTF(PCIDEV, "Writing to a read only register");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("invalid access size");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
14
dev/rtcreg.h
14
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
|
||||
|
||||
|
|
|
@ -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,12 +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 *
|
||||
|
@ -99,6 +90,11 @@ TsunamiIO::RTCEvent::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
reschedule(time);
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiIO::RTCEvent::scheduleIntr()
|
||||
{
|
||||
schedule(curTick + interval);
|
||||
}
|
||||
|
||||
// Timer Event for PIT Timers
|
||||
TsunamiIO::ClockEvent::ClockEvent()
|
||||
|
@ -126,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
|
||||
|
@ -270,7 +264,7 @@ 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)) + 0x20;
|
||||
Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
|
||||
|
||||
|
||||
switch(req->size) {
|
||||
|
@ -302,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
|
||||
|
@ -316,6 +310,12 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
|
|||
return No_Fault;
|
||||
case RTC_CNTRL_REGD:
|
||||
panic("RTC Control Register D not implemented");
|
||||
case RTC_SEC_ALRM:
|
||||
case RTC_MIN_ALRM:
|
||||
case RTC_HR_ALRM:
|
||||
// RTC alarm functionality is not currently implemented
|
||||
*(uint8_t *)data = 0x00;
|
||||
return No_Fault;
|
||||
case RTC_SEC:
|
||||
*(uint8_t *)data = tm.tm_sec;
|
||||
return No_Fault;
|
||||
|
@ -326,16 +326,16 @@ 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;
|
||||
*(uint8_t *)data = tm.tm_mday + 1;
|
||||
return No_Fault;
|
||||
case RTC_MON:
|
||||
*(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");
|
||||
|
@ -391,7 +391,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)) + 0x20;
|
||||
Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
|
||||
|
||||
switch(req->size) {
|
||||
case sizeof(uint8_t):
|
||||
|
@ -442,10 +442,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");
|
||||
}
|
||||
|
@ -483,9 +483,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;
|
||||
|
@ -499,12 +500,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;
|
||||
|
@ -522,10 +537,10 @@ 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");
|
||||
}
|
||||
|
|
|
@ -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 §ion);
|
||||
|
||||
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:
|
||||
/**
|
||||
|
|
|
@ -146,10 +146,11 @@ Uart8250::read(MemReqPtr &req, uint8_t *data)
|
|||
break;
|
||||
case 0x2: // Intr Identification Register (IIR)
|
||||
DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status);
|
||||
if (status)
|
||||
*(uint8_t*)data = 0;
|
||||
status &= ~TX_INT;
|
||||
if (status & RX_INT)
|
||||
*(uint8_t*)data = IIR_RXID;
|
||||
else
|
||||
*(uint8_t*)data = 1;
|
||||
*(uint8_t*)data = IIR_NOPEND;
|
||||
break;
|
||||
case 0x3: // Line Control Register (LCR)
|
||||
*(uint8_t*)data = LCR;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -65,7 +65,6 @@ FreebsdSystem::FreebsdSystem(Params *p)
|
|||
skipCalibrateClocks = new FreebsdSkipCalibrateClocksEvent(&pcEventQueue, "calibrate_clocks");
|
||||
if (kernelSymtab->findAddress("calibrate_clocks", addr))
|
||||
skipCalibrateClocks->schedule(addr + sizeof(MachInst) * 2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,9 +38,7 @@
|
|||
class FreebsdSystem : public System
|
||||
{
|
||||
private:
|
||||
|
||||
SkipFuncEvent *skipDelayEvent;
|
||||
|
||||
FreebsdSkipCalibrateClocksEvent *skipCalibrateClocks;
|
||||
|
||||
public:
|
||||
|
|
|
@ -50,3 +50,6 @@ class PciDevice(DmaDevice):
|
|||
pci_func = Param.Int("PCI function code")
|
||||
configdata = Param.PciConfigData(Parent.any, "PCI Config data")
|
||||
configspace = Param.PciConfigAll(Parent.any, "PCI Configspace")
|
||||
|
||||
class PciFake(PciDevice):
|
||||
type = 'PciFake'
|
||||
|
|
Loading…
Reference in a new issue