|
| 1 | +# SPDX-License-Identifier: MIT |
| 2 | +import struct |
| 3 | + |
| 4 | +from ..utils import * |
| 5 | + |
| 6 | +__all__ = ["DockChannel"] |
| 7 | + |
| 8 | +# DockChannel layout: |
| 9 | +# 00000 : Global regs |
| 10 | + |
| 11 | +# 08000 : IRQ regs (0) |
| 12 | +# 0c000 : IRQ regs (1) |
| 13 | +# 10000 : IRQ regs (2) |
| 14 | +# 14000 : IRQ regs (3) -> AIC #0 |
| 15 | +# 18000 : IRQ regs (4) -> AIC #1 |
| 16 | +# 1c000 : IRQ regs (5) (not always present) |
| 17 | + |
| 18 | +# 28000 : FIFO regs (1A) |
| 19 | +# 2c000 : Data regs (1A) |
| 20 | +# 30000 : FIFO regs (1B) |
| 21 | +# 34000 : Data regs (1B) |
| 22 | +# 38000 : FIFO regs (2A) |
| 23 | +# 3c000 : Data regs (2A) |
| 24 | +# 40000 : FIFO regs (2B) |
| 25 | +# 44000 : Data regs (2B) |
| 26 | +# (possibly more) |
| 27 | + |
| 28 | +class R_RX_DATA(Register32): |
| 29 | + DATA = 31, 8 |
| 30 | + COUNT = 7, 0 |
| 31 | + |
| 32 | +class DockChannelIRQRegs(RegMap): |
| 33 | + IRQ_MASK = 0x0, Register32 |
| 34 | + IRQ_FLAG = 0x4, Register32 |
| 35 | + |
| 36 | +class DockChannelConfigRegs(RegMap): |
| 37 | + TX_THRESH = 0x0, Register32 |
| 38 | + RX_THRESH = 0x4, Register32 |
| 39 | + |
| 40 | +class DockChannelDataRegs(RegMap): |
| 41 | + TX_8 = 0x4, Register32 |
| 42 | + TX_16 = 0x8, Register32 |
| 43 | + TX_24 = 0xc, Register32 |
| 44 | + TX_32 = 0x10, Register32 |
| 45 | + TX_FREE = 0x14, Register32 |
| 46 | + RX_8 = 0x1c, R_RX_DATA |
| 47 | + RX_16 = 0x20, R_RX_DATA |
| 48 | + RX_24 = 0x24, R_RX_DATA |
| 49 | + RX_32 = 0x28, Register32 |
| 50 | + RX_COUNT = 0x2c, Register32 |
| 51 | + |
| 52 | +class DockChannel: |
| 53 | + def __init__(self, u, irq_base, fifo_base, irq_idx): |
| 54 | + self.u = u |
| 55 | + self.p = u.proxy |
| 56 | + self.iface = u.iface |
| 57 | + self.config = DockChannelConfigRegs(u, fifo_base) |
| 58 | + self.data = DockChannelDataRegs(u, fifo_base + 0x4000) |
| 59 | + self.irq = DockChannelIRQRegs(u, irq_base) |
| 60 | + self.irq_idx = irq_idx |
| 61 | + self.irq.IRQ_MASK.val = 3 << (irq_idx * 2) |
| 62 | + |
| 63 | + @property |
| 64 | + def tx_irq(self): |
| 65 | + self.irq.IRQ_FLAG.val = 1 << (self.irq_idx * 2) |
| 66 | + return self.irq.IRQ_FLAG.val & (1 << (self.irq_idx * 2)) |
| 67 | + |
| 68 | + @property |
| 69 | + def rx_irq(self): |
| 70 | + self.irq.IRQ_FLAG.val = 2 << (self.irq_idx * 2) |
| 71 | + return self.irq.IRQ_FLAG.val & (2 << (self.irq_idx * 2)) |
| 72 | + |
| 73 | + @property |
| 74 | + def rx_count(self): |
| 75 | + return self.data.RX_COUNT.val |
| 76 | + |
| 77 | + @property |
| 78 | + def tx_free(self): |
| 79 | + return self.data.TX_FREE.val |
| 80 | + |
| 81 | + def set_tx_thresh(self, v): |
| 82 | + self.config.TX_THRESH.val = v |
| 83 | + |
| 84 | + def set_rx_thresh(self, v): |
| 85 | + self.config.RX_THRESH.val = v |
| 86 | + |
| 87 | + def write(self, data): |
| 88 | + p = 0 |
| 89 | + left = len(data) |
| 90 | + while left >= 4: |
| 91 | + while self.tx_free < 4: |
| 92 | + pass |
| 93 | + d = struct.unpack("<I", data[p:p+4])[0] |
| 94 | + self.data.TX_32.val = d |
| 95 | + p += 4 |
| 96 | + left -= 4 |
| 97 | + while left >= 1: |
| 98 | + while self.tx_free < 1: |
| 99 | + pass |
| 100 | + self.data.TX_8.val = data[p] |
| 101 | + p += 1 |
| 102 | + left -= 1 |
| 103 | + |
| 104 | + def read(self, count): |
| 105 | + data = [] |
| 106 | + left = count |
| 107 | + while left >= 4: |
| 108 | + while self.rx_count < 4: |
| 109 | + pass |
| 110 | + data.append(struct.pack("<I", self.data.RX_32.val)) |
| 111 | + left -= 4 |
| 112 | + while left >= 1: |
| 113 | + while self.rx_count < 1: |
| 114 | + pass |
| 115 | + data.append(bytes([self.data.RX_8.DATA])) |
| 116 | + left -= 1 |
| 117 | + return b"".join(data) |
| 118 | + |
| 119 | + def read_all(self): |
| 120 | + return self.read(self.rx_count) |
0 commit comments