1 //
2 // Copyright (c) 2010-2023 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using Antmicro.Renode.Utilities.Packets;
8 
9 namespace Antmicro.Renode.Peripherals.Storage
10 {
11     public enum UPIUTransactionCodeInitiatorToTarget : byte
12     {
13         NopOut = 0b000000,
14         Command = 0b000001,
15         DataOut = 0b000010,
16         TaskManagementRequest = 0b000100,
17         QueryRequest = 0b010110,
18     }
19 
20     public enum UPIUTransactionCodeTargetToInitiator : byte
21     {
22         NopIn = 0b100000,
23         Response = 0b100001,
24         DataIn = 0b100010,
25         TaskManagementResponse = 0b100100,
26         ReadyToTransfer = 0b110001,
27         QueryResponse = 0b110110,
28         RejectUPIU = 0b111111,
29     }
30 
31     public enum TaskAttribute
32     {
33         Simple = 0b00,
34         Ordered = 0b01,
35         HeadOfQueue = 0b10,
36         ACA = 0b11
37     }
38 
39     public enum QueryFunction : byte
40     {
41         StandardReadRequest = 0x01,
42         StandardWriteRequest = 0x81,
43     }
44 
45     public enum QueryFunctionOpcode : byte
46     {
47         Nop = 0x00,
48         ReadDescriptor = 0x01,
49         WriteDescriptor = 0x02,
50         ReadAttribute = 0x03,
51         WriteAttribute = 0x04,
52         ReadFlag = 0x05,
53         SetFlag = 0x06,
54         ClearFlag = 0x07,
55         ToggleFlag = 0x08
56     }
57 
58     public enum QueryResponseCode : byte
59     {
60         Success = 0x0,
61         ParameterNotReadable = 0xf6,
62         ParameterNotWriteable = 0xf7,
63         ParameterAlreadyWritten = 0xf8,
64         InvalidLength = 0xf9,
65         InvalidValue = 0xfa,
66         InvalidSelector = 0xfb,
67         InvalidIndex = 0xfc,
68         InvalidIdn = 0xfd,
69         InvalidOpcode = 0xfe,
70         GeneralFailure = 0xff
71     }
72 
73 #pragma warning disable 649, 169
74     public struct BasicUPIUHeader
75     {
76         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
77         public byte TransactionCode;
78         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
79         public bool DataSegmentsCRC;
80         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
81         public bool HeaderSegmentsCRC;
82         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
83         public byte Flags;
84         [PacketField, Offset(doubleWords: 0, bits: 16), Width(8)]
85         public byte LogicalUnitNumber;
86         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
87         public byte TaskTag;
88         [PacketField, Offset(doubleWords: 1, bits: 0), Width(4)]
89         public byte InitiatorID;
90         [PacketField, Offset(doubleWords: 1, bits: 4), Width(4)]
91         public byte CommandSetType;
92         [PacketField, Offset(doubleWords: 1, bits: 8), Width(8)]
93         public byte Function;
94         [PacketField, Offset(doubleWords: 1, bits: 16), Width(8)]
95         public byte Response;
96         [PacketField, Offset(doubleWords: 1, bits: 24), Width(8)]
97         public byte Status;
98         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
99         public byte TotalEHSLength;
100         [PacketField, Offset(doubleWords: 2, bits: 8), Width(8)]
101         public byte DeviceInformation;
102         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
103         public ushort DataSegmentLength;
104     }
105 
106     public struct CommandUPIU
107     {
108         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
109         public byte TransactionCode;
110         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
111         public bool DataSegmentsCRC;
112         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
113         public bool HeaderSegmentsCRC;
114         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
115         public byte Flags;
116         [PacketField, Offset(doubleWords: 0, bits: 16), Width(8)]
117         public byte LogicalUnitNumber;
118         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
119         public byte TaskTag;
120         [PacketField, Offset(doubleWords: 1, bits: 0), Width(4)]
121         public byte InitiatorID;
122         [PacketField, Offset(doubleWords: 1, bits: 4), Width(4)]
123         public byte CommandSetType;
124         [PacketField, Offset(doubleWords: 1, bits: 24), Width(4)]
125         public byte NexusInitiatorID;
126         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
127         public byte TotalEHSLength;
128         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
129         public ushort DataSegmentLength;
130         [PacketField, Offset(doubleWords: 3, bits: 0), Width(32)]
131         public uint ExpectedDataTransferLength;
132         [PacketField, Width(16)]
133         public byte[] CommandDescriptorBlock;
134     }
135 
136     public struct CommandUPIUFlags
137     {
138         [PacketField, Offset(bytes: 0, bits: 0), Width(2)]
139         public TaskAttribute TaskAttribute;
140         [PacketField, Offset(bytes: 0, bits: 2), Width(1)]
141         public bool CommandPriority;
142         [PacketField, Offset(bytes: 0, bits: 5), Width(1)]
143         public bool Write;
144         [PacketField, Offset(bytes: 0, bits: 6), Width(1)]
145         public bool Read;
146     }
147     public struct DataInUPIU
148     {
149         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
150         public byte TransactionCode;
151         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
152         public bool DataSegmentsCRC;
153         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
154         public bool HeaderSegmentsCRC;
155         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
156         public byte Flags;
157         [PacketField, Offset(doubleWords: 0, bits: 16), Width(8)]
158         public byte LogicalUnitNumber;
159         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
160         public byte TaskTag;
161         [PacketField, Offset(doubleWords: 1, bits: 0), Width(4)]
162         public byte InitiatorID;
163         [PacketField, Offset(doubleWords: 1, bits: 8), Width(4)]
164         public byte NexusInitiatorID;
165         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
166         public byte TotalEHSLength;
167         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
168         public ushort DataSegmentLength;
169         [PacketField, Offset(doubleWords: 3, bits: 0), Width(32)]
170         public uint DataBufferOffset;
171         [PacketField, Offset(doubleWords: 4, bits: 0), Width(32)]
172         public uint DataTransferCount;
173         [PacketField, Offset(doubleWords: 5, bits: 4), Width(4)]
174         public byte HintControl;
175         [PacketField, Offset(doubleWords: 5, bits: 8), Width(4)]
176         public byte HintNexusInitiatorID;
177         [PacketField, Offset(doubleWords: 5, bits: 12), Width(4)]
178         public byte HintInitiatorID;
179         [PacketField, Offset(doubleWords: 5, bits: 16), Width(8)]
180         public byte HintLogicalUnitNumber;
181         [PacketField, Offset(doubleWords: 5, bits: 24), Width(8)]
182         public byte HintTaskTag;
183         [PacketField, Offset(doubleWords: 6, bits: 0), Width(32)]
184         public uint HintDataBufferOffset;
185         [PacketField, Offset(doubleWords: 7, bits: 0), Width(32)]
186         public uint HintDataCount;
187     }
188 
189     public struct DataOutUPIU
190     {
191         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
192         public byte TransactionCode;
193         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
194         public bool DataSegmentsCRC;
195         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
196         public bool HeaderSegmentsCRC;
197         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
198         public byte Flags;
199         [PacketField, Offset(doubleWords: 0, bits: 16), Width(8)]
200         public byte LogicalUnitNumber;
201         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
202         public byte TaskTag;
203         [PacketField, Offset(doubleWords: 1, bits: 0), Width(4)]
204         public byte InitiatorID;
205         [PacketField, Offset(doubleWords: 1, bits: 24), Width(4)]
206         public byte NexusInitiatorID;
207         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
208         public byte TotalEHSLength;
209         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
210         public ushort DataSegmentLength;
211         [PacketField, Offset(doubleWords: 3, bits: 0), Width(32)]
212         public uint DataBufferOffset;
213         [PacketField, Offset(doubleWords: 4, bits: 0), Width(32)]
214         public uint DataTransferCount;
215     }
216 
217     public struct NopInUPIU
218     {
219         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
220         public byte TransactionCode;
221         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
222         public bool DataSegmentsCRC;
223         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
224         public bool HeaderSegmentsCRC;
225         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
226         public byte Flags;
227         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
228         public byte TaskTag;
229         [PacketField, Offset(doubleWords: 1, bits: 16), Width(8)]
230         public byte Response;
231         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
232         public byte TotalEHSLength;
233         [PacketField, Offset(doubleWords: 2, bits: 8), Width(8)]
234         public byte DeviceInformation;
235         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
236         public ushort DataSegmentLength;
237     }
238 
239     public struct NopOutUPIU
240     {
241         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
242         public byte TransactionCode;
243         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
244         public bool DataSegmentsCRC;
245         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
246         public bool HeaderSegmentsCRC;
247         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
248         public byte Flags;
249         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
250         public byte TaskTag;
251         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
252         public byte TotalEHSLength;
253         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
254         public ushort DataSegmentLength;
255     }
256 
257     public struct QueryRequestUPIU
258     {
259         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
260         public byte TransactionCode;
261         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
262         public bool DataSegmentsCRC;
263         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
264         public bool HeaderSegmentsCRC;
265         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
266         public byte Flags;
267         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
268         public byte TaskTag;
269         [PacketField, Offset(doubleWords: 1, bits: 8), Width(8)]
270         public QueryFunction QueryFunction;
271         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
272         public byte TotalEHSLength;
273         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
274         public ushort DataSegmentLength;
275         [PacketField, Width(16)]
276         public byte[] TransactionSpecificFields;
277     }
278 
279     public struct QueryResponseUPIU
280     {
281         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
282         public byte TransactionCode;
283         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
284         public bool DataSegmentsCRC;
285         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
286         public bool HeaderSegmentsCRC;
287         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
288         public byte Flags;
289         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
290         public byte TaskTag;
291         [PacketField, Offset(doubleWords: 1, bits: 8), Width(8)]
292         public QueryFunction QueryFunction;
293         [PacketField, Offset(doubleWords: 1, bits: 16), Width(8)]
294         public QueryResponseCode QueryResponse;
295         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
296         public byte TotalEHSLength;
297         [PacketField, Offset(doubleWords: 2, bits: 8), Width(8)]
298         public byte DeviceInformation;
299         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
300         public ushort DataSegmentLength;
301         [PacketField, Width(16)]
302         public byte[] TransactionSpecficFields;
303     }
304 
305     public struct ReadyToTransferUPIU
306     {
307         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
308         public byte TransactionCode;
309         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
310         public bool DataSegmentsCRC;
311         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
312         public bool HeaderSegmentsCRC;
313         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
314         public byte Flags;
315         [PacketField, Offset(doubleWords: 0, bits: 16), Width(8)]
316         public byte LogicalUnitNumber;
317         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
318         public byte TaskTag;
319         [PacketField, Offset(doubleWords: 1, bits: 0), Width(4)]
320         public byte InitiatorID;
321         [PacketField, Offset(doubleWords: 1, bits: 8), Width(4)]
322         public byte NexusInitiatorID;
323         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
324         public byte TotalEHSLength;
325         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
326         public ushort DataSegmentLength;
327         [PacketField, Offset(doubleWords: 3, bits: 0), Width(32)]
328         public uint DataBufferOffset;
329         [PacketField, Offset(doubleWords: 4, bits: 0), Width(32)]
330         public uint DataTransferCount;
331         [PacketField, Offset(doubleWords: 5, bits: 4), Width(4)]
332         public byte HintControl;
333         [PacketField, Offset(doubleWords: 5, bits: 8), Width(4)]
334         public byte HintNexusInitiatorID;
335         [PacketField, Offset(doubleWords: 5, bits: 12), Width(4)]
336         public byte HintInitiatorID;
337         [PacketField, Offset(doubleWords: 5, bits: 16), Width(8)]
338         public byte HintLogicalUnitNumber;
339         [PacketField, Offset(doubleWords: 5, bits: 24), Width(8)]
340         public byte HintTaskTag;
341         [PacketField, Offset(doubleWords: 6, bits: 0), Width(32)]
342         public uint HintDataBufferOffset;
343         [PacketField, Offset(doubleWords: 7, bits: 0), Width(32)]
344         public uint HintDataCount;
345     }
346 
347     public struct RejectUPIU
348     {
349         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
350         public byte TransactionCode;
351         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
352         public bool DataSegmentsCRC;
353         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
354         public bool HeaderSegmentsCRC;
355         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
356         public byte Flags;
357         [PacketField, Offset(doubleWords: 0, bits: 16), Width(8)]
358         public byte LogicalUnitNumber;
359         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
360         public byte TaskTag;
361         [PacketField, Offset(doubleWords: 1, bits: 0), Width(4)]
362         public byte InitiatorID;
363         [PacketField, Offset(doubleWords: 1, bits: 8), Width(4)]
364         public byte NexusInitiatorID;
365         [PacketField, Offset(doubleWords: 1, bits: 16), Width(8)]
366         public byte Response;
367         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
368         public byte TotalEHSLength;
369         [PacketField, Offset(doubleWords: 2, bits: 8), Width(8)]
370         public byte DeviceInformation;
371         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
372         public ushort DataSegmentLength;
373         [PacketField, Offset(doubleWords: 3, bits: 0), Width(8)]
374         public byte BasicHeaderStatus;
375         [PacketField, Offset(doubleWords: 3, bits: 16), Width(8)]
376         public byte E2EStatus;
377     }
378 
379     public struct ResponseUPIU
380     {
381         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
382         public byte TransactionCode;
383         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
384         public bool DataSegmentsCRC;
385         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
386         public bool HeaderSegmentsCRC;
387         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
388         public byte Flags;
389         [PacketField, Offset(doubleWords: 0, bits: 16), Width(8)]
390         public byte LogicalUnitNumber;
391         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
392         public byte TaskTag;
393         [PacketField, Offset(doubleWords: 1, bits: 0), Width(4)]
394         public byte InitiatorID;
395         [PacketField, Offset(doubleWords: 1, bits: 4), Width(4)]
396         public byte CommandSetType;
397         [PacketField, Offset(doubleWords: 1, bits: 8), Width(4)]
398         public byte NexusInitiatorID;
399         [PacketField, Offset(doubleWords: 1, bits: 16), Width(8)]
400         public byte Response;
401         [PacketField, Offset(doubleWords: 1, bits: 24), Width(8)]
402         public byte Status;
403         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
404         public byte TotalEHSLength;
405         [PacketField, Offset(doubleWords: 2, bits: 8), Width(8)]
406         public byte DeviceInformation;
407         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
408         public ushort DataSegmentLength;
409         [PacketField, Offset(doubleWords: 3, bits: 0), Width(32)]
410         public uint ResidualTransferCount;
411     }
412 
413     public struct ResponseUPIUFlags
414     {
415         [PacketField, Offset(bytes: 0, bits: 4), Width(1)]
416         public bool DataOutMismatch;
417         [PacketField, Offset(bytes: 0, bits: 5), Width(1)]
418         public bool DataUnderflow;
419         [PacketField, Offset(bytes: 0, bits: 6), Width(1)]
420         public bool DataOverflow;
421     }
422 
423     public struct TaskManagementRequestUPIU
424     {
425         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
426         public byte TransactionCode;
427         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
428         public bool DataSegmentsCRC;
429         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
430         public bool HeaderSegmentsCRC;
431         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
432         public byte Flags;
433         [PacketField, Offset(doubleWords: 0, bits: 16), Width(8)]
434         public byte LogicalUnitNumber;
435         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
436         public byte TaskTag;
437         [PacketField, Offset(doubleWords: 1, bits: 0), Width(4)]
438         public byte InitiatorID;
439         [PacketField, Offset(doubleWords: 1, bits: 8), Width(8)]
440         public byte TaskManagementFunction;
441         [PacketField, Offset(doubleWords: 1, bits: 16), Width(8)]
442         public byte Response;
443         [PacketField, Offset(doubleWords: 1, bits: 24), Width(4)]
444         public byte NexusInitiatorID;
445         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
446         public byte TotalEHSLength;
447         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
448         public ushort DataSegmentLength;
449         [PacketField, Offset(doubleWords: 3, bits: 0), Width(32)]
450         public uint InputParameter1;
451         [PacketField, Offset(doubleWords: 4, bits: 0), Width(32)]
452         public uint InputParameter2;
453         [PacketField, Offset(doubleWords: 5, bits: 0), Width(32)]
454         public uint InputParameter3;
455     }
456 
457     public struct TaskManagementResponseUPIU
458     {
459         [PacketField, Offset(doubleWords: 0, bits: 0), Width(6)]
460         public byte TransactionCode;
461         [PacketField, Offset(doubleWords: 0, bits: 6), Width(1)]
462         public bool DataSegmentsCRC;
463         [PacketField, Offset(doubleWords: 0, bits: 7), Width(1)]
464         public bool HeaderSegmentsCRC;
465         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
466         public byte Flags;
467         [PacketField, Offset(doubleWords: 0, bits: 16), Width(8)]
468         public byte LogicalUnitNumber;
469         [PacketField, Offset(doubleWords: 0, bits: 24), Width(8)]
470         public byte TaskTag;
471         [PacketField, Offset(doubleWords: 1, bits: 0), Width(4)]
472         public byte InitiatorID;
473         [PacketField, Offset(doubleWords: 1, bits: 8), Width(4)]
474         public byte NexusInitiatorID;
475         [PacketField, Offset(doubleWords: 1, bits: 16), Width(8)]
476         public byte Response;
477         [PacketField, Offset(doubleWords: 2, bits: 0), Width(8)]
478         public byte TotalEHSLength;
479         [PacketField, Offset(doubleWords: 2, bits: 16), Width(16)]
480         public ushort DataSegmentLength;
481         [PacketField, Offset(doubleWords: 3, bits: 0), Width(32)]
482         public uint OutputParameter1;
483         [PacketField, Offset(doubleWords: 4, bits: 0), Width(32)]
484         public uint OutputParameter2;
485     }
486 
487     public struct EHSEntry
488     {
489         [PacketField, Offset(doubleWords: 0, bits: 0), Width(8)]
490         public byte Length;
491         [PacketField, Offset(doubleWords: 0, bits: 8), Width(8)]
492         public byte EHSType;
493         [PacketField, Offset(doubleWords: 0, bits: 16), Width(16)]
494         public ushort EHSSubType;
495         // EHS data
496     }
497 #pragma warning restore 649, 169
498 }