Skip to content

Commit 755d6e1

Browse files
committed
m1n1.hw.sio: Start SIO client
Signed-off-by: Martin Povišer <povik@cutebit.org>
1 parent 0129a65 commit 755d6e1

File tree

1 file changed

+217
-0
lines changed

1 file changed

+217
-0
lines changed

proxyclient/m1n1/hw/sio.py

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
from enum import IntEnum
2+
from construct import Struct, Default, Container, Int32ul
3+
4+
import traceback
5+
from m1n1.setup import * # remove
6+
7+
from m1n1.utils import *
8+
from m1n1.hw.dart import DART
9+
from m1n1.fw.asc import StandardASC, ASCBaseEndpoint, ASCTimeout
10+
from m1n1.fw.asc.base import msg_handler
11+
12+
class SIOMessage(Register64):
13+
EP = 7, 0
14+
TAG = 13, 8
15+
TYPE = 23, 16
16+
PARAM = 31, 24
17+
DATA = 63, 32
18+
19+
class SIOStart(SIOMessage):
20+
TYPE = 23, 16, Constant(2)
21+
22+
class SIOSetup(SIOMessage):
23+
TYPE = 23, 16, Constant(3)
24+
25+
class SIOReadyChannel(SIOMessage):
26+
TYPE = 23, 16, Constant(5)
27+
28+
class SIOIssueDescriptor(SIOMessage):
29+
TYPE = 23, 16, Constant(6)
30+
31+
class SIOTerminate(SIOMessage):
32+
TYPE = 23, 16, Constant(8)
33+
34+
class SIOAck(SIOMessage):
35+
TYPE = 23, 16, Constant(0x65)
36+
37+
class SIONack(SIOMessage):
38+
TYPE = 23, 16, Constant(0x66)
39+
40+
class SIOStarted(SIOMessage):
41+
TYPE = 23, 16, Constant(0x67)
42+
43+
class SIODescriptorDone(SIOMessage):
44+
TYPE = 23, 16, Constant(0x68)
45+
46+
class SIOShmem(IntEnum):
47+
MAIN = 0x1
48+
49+
UNK_0b = 0xb # macos size: 0x1b80
50+
UNK_0f = 0xf # 0x1e000
51+
UNK_1a = 0x1a # 0x50
52+
UNK_1c = 0x1c # 0x40
53+
UNK_1e = 0x1e # 0x30
54+
UNK_22 = 0x22 # 0xa0
55+
56+
UNK_EP3_0d = 0x3_0d # 0x4000
57+
58+
class SIOChannel:
59+
def __init__(self, parent, channo):
60+
self.p = parent
61+
self.ch = channo
62+
63+
SIOChannelConfig = Struct(
64+
"unk_0" / Default(Int32ul, 0),
65+
"unk_4" / Default(Int32ul, 0),
66+
"unk_8" / Default(Int32ul, 0),
67+
"unk_c" / Default(Int32ul, 0),
68+
"unk_10" / Default(Int32ul, 0),
69+
)
70+
71+
def undump(text):
72+
return b"".join([int(v, 16).to_bytes(4, byteorder="little") for v in text.strip().split()])
73+
74+
class SIOEndpoint(ASCBaseEndpoint):
75+
BASE_MESSAGE = SIOMessage
76+
SHORT = "sioep"
77+
78+
def __init__(self, *args, **kwargs):
79+
super().__init__(*args, **kwargs)
80+
self.tag = 0
81+
self.acked, self.nacked = set(), set()
82+
self.bufs = {}
83+
self.started = False
84+
85+
@msg_handler(0x65, SIOAck)
86+
def Ack(self, msg):
87+
self.acked.add(msg.TAG)
88+
return True
89+
90+
@msg_handler(0x66, SIONack)
91+
def Nack(self, msg):
92+
self.nacked.add(msg.TAG)
93+
return True
94+
95+
@msg_handler(0x67, SIOStarted)
96+
def Started(self, msg):
97+
self.started = True
98+
return True
99+
100+
def next_tag(self):
101+
self.tag = (self.tag + 1) % 0x10
102+
return self.tag
103+
104+
def roundtrip(self, msg, timeout=0.1):
105+
msg.TAG = self.next_tag()
106+
self.send(msg)
107+
self.acked.discard(msg.TAG)
108+
self.nacked.discard(msg.TAG)
109+
deadline = time.time() + timeout
110+
while time.time() < deadline and msg.TAG not in self.acked:
111+
self.asc.work()
112+
if msg.TAG in self.nacked:
113+
raise Exception("ASC nacked a message")
114+
if msg.TAG not in self.acked:
115+
raise ASCTimeout("ASC reply timed out")
116+
117+
def wait_for_started_msg(self, timeout=0.1):
118+
deadline = time.time() + timeout
119+
while time.time() < deadline and not self.started:
120+
self.asc.work()
121+
if not self.started:
122+
raise ASCTimeout("ASC reply timed out")
123+
124+
def alloc_buf(self, param_id, size, data=b""):
125+
paddr, iova = self.asc.ioalloc(size)
126+
self.bufs[param_id] = (iova, size)
127+
self.write_shmem(param_id, 0, data)
128+
ep = param_id >> 8; param_id &= 0xff
129+
self.roundtrip(SIOSetup(EP=ep, PARAM=param_id, DATA=iova >> 12))
130+
self.roundtrip(SIOSetup(EP=ep, PARAM=param_id + 1, DATA=size))
131+
132+
def start(self):
133+
self.send(SIOStart())
134+
self.wait_for_started_msg()
135+
self.alloc_buf(SIOShmem.UNK_0f, 0x1e000)
136+
self.alloc_buf(SIOShmem.UNK_1a, 0x50, # map-range=
137+
undump("""
138+
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
139+
00000000 00000000 00000000 00000000 35000000 00000002 00004000 00000000
140+
00000000 00000000 00000000 00000000
141+
"""))
142+
self.alloc_buf(SIOShmem.UNK_1e, 0x30, # asio-ascwrap-tunables=
143+
undump("""
144+
00000040 00000004 0000ff00 00000000 00000400 00000000 0000080c 00000004
145+
60000001 00000000 60000001 00000000
146+
"""))
147+
dmashim_data = b"".join([
148+
v.to_bytes(4, byteorder="little") \
149+
for data in self.asc.node.dmashim
150+
for v in data.unk
151+
])
152+
self.alloc_buf(SIOShmem.UNK_22, 0xa0, dmashim_data)
153+
self.alloc_buf(SIOShmem.UNK_1c, 0x40, # device-type=
154+
undump("""
155+
00000005 00000000 00000009 00000000 00000000 00000000 00000002 0000000c
156+
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
157+
"""))
158+
self.alloc_buf(SIOShmem.UNK_EP3_0d, 0x4000)
159+
self.alloc_buf(SIOShmem.MAIN, 0xaaa)
160+
self.alloc_buf(SIOShmem.UNK_0b, 0x1b80)
161+
162+
def write_shmem(self, area, base, data):
163+
iova, shmem_size = self.bufs[area]
164+
assert base + len(data) <= shmem_size
165+
print(iova + base, chexdump(data))
166+
self.asc.iowrite(iova + base, data)
167+
168+
def open_channel(self, channo, **config):
169+
self.write_shmem(
170+
SIOShmem.MAIN, 0,
171+
SIOChannelConfig.build(Container(**config))
172+
)
173+
self.roundtrip(SIOReadyChannel(EP=channo))
174+
return SIOChannel(self, channo)
175+
176+
class SIOClient(StandardASC):
177+
ENDPOINTS = {
178+
0x20: SIOEndpoint,
179+
}
180+
181+
def __init__(self, u, adtpath, dart=None):
182+
node = u.adt[adtpath]
183+
self.node = node
184+
self.base = node.get_reg(0)[0]
185+
super().__init__(u, self.base, dart)
186+
187+
def map_data(self):
188+
segments = struct.unpack("<8q", self.node.segment_ranges)
189+
self.dart.iomap_at(0, segments[6], segments[4], segments[7] & ~(-1 << 32))
190+
191+
p.pmgr_adt_clocks_enable("/arm-io/dart-sio")
192+
p.pmgr_adt_clocks_enable("/arm-io/sio")
193+
p.pmgr_adt_clocks_enable("/arm-io/dp-audio0")
194+
195+
dart = DART.from_adt(u, "/arm-io/dart-sio", iova_range=(0x30000, 0x10_000_000))
196+
197+
dart.initialize()
198+
dart.regs.TCR[0].set(BYPASS_DAPF=0, BYPASS_DART=0, TRANSLATE_ENABLE=1)
199+
dart.regs.TCR[15].set(BYPASS_DAPF=0, BYPASS_DART=1, TRANSLATE_ENABLE=0)
200+
201+
sio = SIOClient(u, "/arm-io/sio", dart)
202+
sio.asc.CPU_CONTROL.val = 0x0
203+
sio.verbose = 4
204+
sio.map_data()
205+
sio.boot()
206+
207+
try:
208+
sio.start_ep(0x20)
209+
dpaudio0 = sio.sioep.open_channel(0x64,
210+
unk_0=0x2,
211+
unk_8=0x800,
212+
unk_c=0x800,
213+
unk_10=0x800,
214+
)
215+
except:
216+
traceback.print_exc()
217+
p.reboot()

0 commit comments

Comments
 (0)