summaryrefslogtreecommitdiff
path: root/dev/pcidev.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dev/pcidev.cc')
-rw-r--r--dev/pcidev.cc79
1 files changed, 42 insertions, 37 deletions
diff --git a/dev/pcidev.cc b/dev/pcidev.cc
index f2bce33ca..31c44bffa 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -73,39 +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((uint8_t*)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));
+ case sizeof(uint8_t):
+ memcpy(&byte, &config.data[offset], size);
+ *data = byte;
break;
-
case sizeof(uint16_t):
- memcpy((uint8_t*)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));
+ memcpy(&byte, &config.data[offset], size);
+ *(uint16_t*)data = htoa(word);
break;
-
- case sizeof(uint8_t):
- memcpy((uint8_t*)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)));
+ case sizeof(uint32_t):
+ memcpy(&byte, &config.data[offset], size);
+ *(uint32_t*)data = htoa(dword);
break;
-
default:
- panic("Invalid Read Size");
+ 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
@@ -116,35 +115,40 @@ 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;
+ 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,
- word_value);
+ data);
barnum = (offset - PCI0_BASE_ADDR0) >> 2;
switch (size) {
case sizeof(uint8_t): // 1-byte access
+ byte_value = data;
switch (offset) {
case PCI0_INTERRUPT_LINE:
case PCI_CACHE_LINE_SIZE:
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");
}
break;
case sizeof(uint16_t): // 2-byte access
+ half_value = data;
switch (offset) {
case PCI_COMMAND:
case PCI_STATUS:
@@ -157,10 +161,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
+ word_value = data;
switch (offset) {
case PCI0_BASE_ADDR0:
case PCI0_BASE_ADDR1:
@@ -175,12 +177,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 {
@@ -192,7 +194,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];
@@ -255,6 +257,9 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
DPRINTF(PCIDEV, "Writing to a read only register");
}
break;
+
+ default:
+ panic("invalid access size");
}
}