From 2f09c69e345826c80412be5440a07efb7de7e2f2 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 22 Apr 2019 16:43:21 -0700 Subject: [PATCH] Add wrappers for word access --- tb/pcie.py | 410 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 376 insertions(+), 34 deletions(-) diff --git a/tb/pcie.py b/tb/pcie.py index 592041383..1d82dda67 100644 --- a/tb/pcie.py +++ b/tb/pcie.py @@ -1873,6 +1873,38 @@ class Function(PMCapability, PCIECapability): return data[:length] + def io_read_words(self, addr, count, ws=2, timeout=0, attr=0, tc=0): + assert ws in (1, 2, 4, 8) + data = yield from self.io_read(addr, count*ws, timeout, attr, tc) + words = [] + for k in range(count): + words.append(int.from_bytes(data[ws*k:ws*(k+1)], 'little')) + return words + + def io_read_dwords(self, addr, count, timeout=0, attr=0, tc=0): + data = yield from self.io_read_words(addr, count, 4, timeout, attr, tc) + return data + + def io_read_qwords(self, addr, count, timeout=0, attr=0, tc=0): + data = yield from self.io_read_words(addr, count, 8, timeout, attr, tc) + return data + + def io_read_byte(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.io_read(addr, 1, timeout, attr, tc) + return data[0] + + def io_read_word(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.io_read_words(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + + def io_read_dword(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.io_read_dwords(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + + def io_read_qword(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.io_read_qwords(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + def io_write(self, addr, data, timeout=0): n = 0 @@ -1903,6 +1935,32 @@ class Function(PMCapability, PCIECapability): n += byte_length addr += byte_length + def io_write_words(self, addr, data, ws=2, timeout=0, attr=0, tc=0): + assert ws in (1, 2, 4, 8) + words = data + data = b'' + for w in words: + data += w.to_bytes(ws, 'little') + yield from self.io_write(addr, data, timeout, attr, tc) + + def io_write_dwords(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write_words(addr, data, 4, timeout, attr, tc) + + def io_write_qwords(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write_words(addr, data, 8, timeout, attr, tc) + + def io_write_byte(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write(addr, [data], timeout, attr, tc) + + def io_write_word(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write_words(addr, [data], timeout=timeout, attr=attr, tc=tc) + + def io_write_dword(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write_dwords(addr, [data], timeout=timeout, attr=attr, tc=tc) + + def io_write_qword(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write_qwords(addr, [data], timeout=timeout, attr=attr, tc=tc) + def mem_read(self, addr, length, timeout=0, attr=0, tc=0): n = 0 data = b'' @@ -1960,6 +2018,38 @@ class Function(PMCapability, PCIECapability): return data + def mem_read_words(self, addr, count, ws=2, timeout=0, attr=0, tc=0): + assert ws in (1, 2, 4, 8) + data = yield from self.mem_read(addr, count*ws, timeout, attr, tc) + words = [] + for k in range(count): + words.append(int.from_bytes(data[ws*k:ws*(k+1)], 'little')) + return words + + def mem_read_dwords(self, addr, count, timeout=0, attr=0, tc=0): + data = yield from self.mem_read_words(addr, count, 4, timeout, attr, tc) + return data + + def mem_read_qwords(self, addr, count, timeout=0, attr=0, tc=0): + data = yield from self.mem_read_words(addr, count, 8, timeout, attr, tc) + return data + + def mem_read_byte(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.mem_read(addr, 1, timeout, attr, tc) + return data[0] + + def mem_read_word(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.mem_read_words(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + + def mem_read_dword(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.mem_read_dwords(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + + def mem_read_qword(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.mem_read_qwords(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + def mem_write(self, addr, data, timeout=0, attr=0, tc=0): n = 0 @@ -1988,6 +2078,32 @@ class Function(PMCapability, PCIECapability): n += byte_length addr += byte_length + def mem_write_words(self, addr, data, ws=2, timeout=0, attr=0, tc=0): + assert ws in (1, 2, 4, 8) + words = data + data = b'' + for w in words: + data += w.to_bytes(ws, 'little') + yield from self.mem_write(addr, data, timeout, attr, tc) + + def mem_write_dwords(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write_words(addr, data, 4, timeout, attr, tc) + + def mem_write_qwords(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write_words(addr, data, 8, timeout, attr, tc) + + def mem_write_byte(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write(addr, [data], timeout, attr, tc) + + def mem_write_word(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write_words(addr, [data], timeout=timeout, attr=attr, tc=tc) + + def mem_write_dword(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write_dwords(addr, [data], timeout=timeout, attr=attr, tc=tc) + + def mem_write_qword(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write_qwords(addr, [data], timeout=timeout, attr=attr, tc=tc) + class Endpoint(Function): """PCIe endpoint function, implements endpoint config space""" @@ -3544,6 +3660,38 @@ class RootComplex(Switch): return data[:length] + def config_read_words(self, dev, addr, count, ws=2, timeout=0): + assert ws in (1, 2, 4, 8) + data = yield from self.config_read(dev, addr, count*ws, timeout) + words = [] + for k in range(count): + words.append(int.from_bytes(data[ws*k:ws*(k+1)], 'little')) + return words + + def config_read_dwords(self, dev, addr, count, timeout=0): + data = yield from self.config_read_words(dev, addr, count, 4, timeout) + return data + + def config_read_qwords(self, dev, addr, count, timeout=0): + data = yield from self.config_read_words(dev, addr, count, 8, timeout) + return data + + def config_read_byte(self, dev, addr, timeout=0): + data = yield from self.config_read(dev, addr, 1, timeout) + return data[0] + + def config_read_word(self, dev, addr, timeout=0): + data = yield from self.config_read_words(dev, addr, 1, timeout=timeout) + return data[0] + + def config_read_dword(self, dev, addr, timeout=0): + data = yield from self.config_read_dwords(dev, addr, 1, timeout=timeout) + return data[0] + + def config_read_qword(self, dev, addr, timeout=0): + data = yield from self.config_read_qwords(dev, addr, 1, timeout=timeout) + return data[0] + def config_write(self, dev, addr, data, timeout=0): n = 0 @@ -3568,6 +3716,32 @@ class RootComplex(Switch): n += byte_length addr += byte_length + def config_write_words(self, dev, addr, data, ws=2, timeout=0): + assert ws in (1, 2, 4, 8) + words = data + data = b'' + for w in words: + data += w.to_bytes(ws, 'little') + yield from self.config_write(dev, addr, data, timeout) + + def config_write_dwords(self, dev, addr, data, timeout=0): + yield from self.config_write_words(dev, addr, data, 4, timeout) + + def config_write_qwords(self, dev, addr, data, timeout=0): + yield from self.config_write_words(dev, addr, data, 8, timeout) + + def config_write_byte(self, dev, addr, data, timeout=0): + yield from self.config_write(dev, addr, [data], timeout) + + def config_write_word(self, dev, addr, data, timeout=0): + yield from self.config_write_words(dev, addr, [data], timeout=timeout) + + def config_write_dword(self, dev, addr, data, timeout=0): + yield from self.config_write_dwords(dev, addr, [data], timeout=timeout) + + def config_write_qword(self, dev, addr, data, timeout=0): + yield from self.config_write_qwords(dev, addr, [data], timeout=timeout) + def capability_read(self, dev, cap_id, addr, length, timeout=0): ti = self.tree.find_dev(dev) @@ -3582,6 +3756,38 @@ class RootComplex(Switch): val = yield from self.config_read(dev, addr+offset, length, timeout) return val + def capability_read_words(self, dev, cap_id, addr, count, ws=2, timeout=0): + assert ws in (1, 2, 4, 8) + data = yield from self.capability_read(dev, cap_id, addr, count*ws, timeout) + words = [] + for k in range(count): + words.append(int.from_bytes(data[ws*k:ws*(k+1)], 'little')) + return words + + def capability_read_dwords(self, dev, cap_id, addr, count, timeout=0): + data = yield from self.capability_read_words(dev, cap_id, addr, count, 4, timeout) + return data + + def capability_read_qwords(self, dev, cap_id, addr, count, timeout=0): + data = yield from self.capability_read_words(dev, cap_id, addr, count, 8, timeout) + return data + + def capability_read_byte(self, dev, cap_id, addr, timeout=0): + data = yield from self.capability_read(dev, cap_id, addr, 1, timeout) + return data[0] + + def capability_read_word(self, dev, cap_id, addr, timeout=0): + data = yield from self.capability_read_words(dev, cap_id, addr, 1, timeout=timeout) + return data[0] + + def capability_read_dword(self, dev, cap_id, addr, timeout=0): + data = yield from self.capability_read_dwords(dev, cap_id, addr, 1, timeout=timeout) + return data[0] + + def capability_read_qword(self, dev, cap_id, addr, timeout=0): + data = yield from self.capability_read_qwords(dev, cap_id, addr, 1, timeout=timeout) + return data[0] + def capability_write(self, dev, cap_id, addr, data, timeout=0): ti = self.tree.find_dev(dev) @@ -3595,6 +3801,32 @@ class RootComplex(Switch): yield from self.config_write(dev, addr+offset, data, timeout) + def capability_write_words(self, dev, cap_id, addr, data, ws=2, timeout=0): + assert ws in (1, 2, 4, 8) + words = data + data = b'' + for w in words: + data += w.to_bytes(ws, 'little') + yield from self.capability_write(dev, cap_id, addr, data, timeout) + + def capability_write_dwords(self, dev, cap_id, addr, data, timeout=0): + yield from self.capability_write_words(dev, cap_id, addr, data, 4, timeout) + + def capability_write_qwords(self, dev, cap_id, addr, data, timeout=0): + yield from self.capability_write_words(dev, cap_id, addr, data, 8, timeout) + + def capability_write_byte(self, dev, cap_id, addr, data, timeout=0): + yield from self.capability_write(dev, cap_id, addr, [data], timeout) + + def capability_write_word(self, dev, cap_id, addr, data, timeout=0): + yield from self.capability_write_words(dev, cap_id, addr, [data], timeout=timeout) + + def capability_write_dword(self, dev, cap_id, addr, data, timeout=0): + yield from self.capability_write_dwords(dev, cap_id, addr, [data], timeout=timeout) + + def capability_write_qword(self, dev, cap_id, addr, data, timeout=0): + yield from self.capability_write_qwords(dev, cap_id, addr, [data], timeout=timeout) + def io_read(self, addr, length, timeout=0): n = 0 data = b'' @@ -3633,6 +3865,38 @@ class RootComplex(Switch): return data[:length] + def io_read_words(self, addr, count, ws=2, timeout=0, attr=0, tc=0): + assert ws in (1, 2, 4, 8) + data = yield from self.io_read(addr, count*ws, timeout, attr, tc) + words = [] + for k in range(count): + words.append(int.from_bytes(data[ws*k:ws*(k+1)], 'little')) + return words + + def io_read_dwords(self, addr, count, timeout=0, attr=0, tc=0): + data = yield from self.io_read_words(addr, count, 4, timeout, attr, tc) + return data + + def io_read_qwords(self, addr, count, timeout=0, attr=0, tc=0): + data = yield from self.io_read_words(addr, count, 8, timeout, attr, tc) + return data + + def io_read_byte(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.io_read(addr, 1, timeout, attr, tc) + return data[0] + + def io_read_word(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.io_read_words(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + + def io_read_dword(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.io_read_dwords(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + + def io_read_qword(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.io_read_qwords(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + def io_write(self, addr, data, timeout=0): n = 0 @@ -3663,6 +3927,32 @@ class RootComplex(Switch): n += byte_length addr += byte_length + def io_write_words(self, addr, data, ws=2, timeout=0, attr=0, tc=0): + assert ws in (1, 2, 4, 8) + words = data + data = b'' + for w in words: + data += w.to_bytes(ws, 'little') + yield from self.io_write(addr, data, timeout, attr, tc) + + def io_write_dwords(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write_words(addr, data, 4, timeout, attr, tc) + + def io_write_qwords(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write_words(addr, data, 8, timeout, attr, tc) + + def io_write_byte(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write(addr, [data], timeout, attr, tc) + + def io_write_word(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write_words(addr, [data], timeout=timeout, attr=attr, tc=tc) + + def io_write_dword(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write_dwords(addr, [data], timeout=timeout, attr=attr, tc=tc) + + def io_write_qword(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.io_write_qwords(addr, [data], timeout=timeout, attr=attr, tc=tc) + def mem_read(self, addr, length, timeout=0, attr=0, tc=0): n = 0 data = b'' @@ -3720,6 +4010,38 @@ class RootComplex(Switch): return data + def mem_read_words(self, addr, count, ws=2, timeout=0, attr=0, tc=0): + assert ws in (1, 2, 4, 8) + data = yield from self.mem_read(addr, count*ws, timeout, attr, tc) + words = [] + for k in range(count): + words.append(int.from_bytes(data[ws*k:ws*(k+1)], 'little')) + return words + + def mem_read_dwords(self, addr, count, timeout=0, attr=0, tc=0): + data = yield from self.mem_read_words(addr, count, 4, timeout, attr, tc) + return data + + def mem_read_qwords(self, addr, count, timeout=0, attr=0, tc=0): + data = yield from self.mem_read_words(addr, count, 8, timeout, attr, tc) + return data + + def mem_read_byte(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.mem_read(addr, 1, timeout, attr, tc) + return data[0] + + def mem_read_word(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.mem_read_words(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + + def mem_read_dword(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.mem_read_dwords(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + + def mem_read_qword(self, addr, timeout=0, attr=0, tc=0): + data = yield from self.mem_read_qwords(addr, 1, timeout=timeout, attr=attr, tc=tc) + return data[0] + def mem_write(self, addr, data, timeout=0, attr=0, tc=0): n = 0 @@ -3748,6 +4070,32 @@ class RootComplex(Switch): n += byte_length addr += byte_length + def mem_write_words(self, addr, data, ws=2, timeout=0, attr=0, tc=0): + assert ws in (1, 2, 4, 8) + words = data + data = b'' + for w in words: + data += w.to_bytes(ws, 'little') + yield from self.mem_write(addr, data, timeout, attr, tc) + + def mem_write_dwords(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write_words(addr, data, 4, timeout, attr, tc) + + def mem_write_qwords(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write_words(addr, data, 8, timeout, attr, tc) + + def mem_write_byte(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write(addr, [data], timeout, attr, tc) + + def mem_write_word(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write_words(addr, [data], timeout=timeout, attr=attr, tc=tc) + + def mem_write_dword(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write_dwords(addr, [data], timeout=timeout, attr=attr, tc=tc) + + def mem_write_qword(self, addr, data, timeout=0, attr=0, tc=0): + yield from self.mem_write_qwords(addr, [data], timeout=timeout, attr=attr, tc=tc) + def msi_region_read(self, addr, length): return b'\x00'*length @@ -3776,29 +4124,28 @@ class RootComplex(Switch): if ti.get_capability_offset(MSI_CAP_ID) is None: return False - msg_ctrl = yield from self.capability_read(dev, MSI_CAP_ID, 0, 4) - msg_ctrl = struct.unpack('> 23 & 1 msi_mmcap = msg_ctrl >> 17 & 7 # message address - yield from self.capability_write(dev, MSI_CAP_ID, 4, struct.pack('> 32) & 0xffffffff)) + yield from self.capability_write_dword(dev, MSI_CAP_ID, 8, (self.msi_addr >> 32) & 0xffffffff) # message data - yield from self.capability_write(dev, MSI_CAP_ID, 12, struct.pack('> 32) & 0xffffffff)) + yield from self.config_write_dword(PcieId(bus, d, f), 0x010+bar*4, val & 0xffffffff) + yield from self.config_write_dword(PcieId(bus, d, f), 0x010+(bar+1)*4, (val >> 32) & 0xffffffff) bar += 2 else: @@ -4022,7 +4368,7 @@ class RootComplex(Switch): self.mem_limit += size # write BAR - yield from self.config_write(PcieId(bus, d, f), 0x010+bar*4, struct.pack(' 0: val = yield from self.config_read(PcieId(bus, d, f), ptr, 2) @@ -4044,10 +4390,8 @@ class RootComplex(Switch): # TODO # set max payload size, max read request size, and extended tag enable - val = yield from self.capability_read(PcieId(bus, d, f), PCIE_CAP_ID, 4, 4) - dev_cap = struct.unpack('