rtlp_lib/
lib.rs

1use std::convert::TryFrom;
2use std::fmt::Display;
3
4#[macro_use]
5extern crate bitfield;
6
7#[repr(u8)]
8#[derive(PartialEq, Copy, Clone)]
9pub enum TlpFmt {
10    NoDataHeader3DW     = 0b000,
11    NoDataHeader4DW     = 0b001,
12    WithDataHeader3DW   = 0b010,
13    WithDataHeader4DW   = 0b011,
14    TlpPrefix           = 0b100,
15}
16
17impl Display for TlpFmt {
18    fn fmt (&self, fmt: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
19        let name = match &self {
20            TlpFmt::NoDataHeader3DW => "3DW no Data Header",
21            TlpFmt::NoDataHeader4DW => "4DW no Data Header",
22            TlpFmt::WithDataHeader3DW => "3DW with Data Header",
23            TlpFmt::WithDataHeader4DW => "4DW with Data Header",
24            TlpFmt::TlpPrefix => "Tlp Prefix",
25        };
26        write!(fmt, "{}", name)
27    }
28}
29
30impl TryFrom<u32> for TlpFmt {
31    type Error = ();
32
33    fn try_from(v: u32) -> Result<Self, Self::Error> {
34        match v {
35            x if x == TlpFmt::NoDataHeader3DW as u32 => Ok(TlpFmt::NoDataHeader3DW),
36            x if x == TlpFmt::NoDataHeader4DW as u32 => Ok(TlpFmt::NoDataHeader4DW),
37            x if x == TlpFmt::WithDataHeader3DW as u32 => Ok(TlpFmt::WithDataHeader3DW),
38            x if x == TlpFmt::WithDataHeader4DW as u32 => Ok(TlpFmt::WithDataHeader4DW),
39            x if x == TlpFmt::TlpPrefix as u32 => Ok(TlpFmt::TlpPrefix),
40            _ => Err(()),
41        }
42    }
43}
44
45#[derive(PartialEq)]
46pub enum TlpFormatEncodingType {
47    MemoryRequest           = 0b00000,
48    MemoryLockRequest       = 0b00001,
49    IORequest               = 0b00010,
50    ConfigType0Request      = 0b00100,
51    ConfigType1Request      = 0b00101,
52    Completion              = 0b01010,
53    CompletionLocked        = 0b01011,
54    FetchAtomicOpRequest    = 0b01100,
55    UnconSwapAtomicOpRequest= 0b01101,
56    CompSwapAtomicOpRequest = 0b01110,
57}
58
59impl TryFrom<u32> for TlpFormatEncodingType {
60    type Error = ();
61
62    fn try_from(v: u32) -> Result<Self, Self::Error> {
63        match v {
64            x if x == TlpFormatEncodingType::MemoryRequest as u32 			=> Ok(TlpFormatEncodingType::MemoryRequest),
65            x if x == TlpFormatEncodingType::MemoryLockRequest as u32 		=> Ok(TlpFormatEncodingType::MemoryLockRequest),
66            x if x == TlpFormatEncodingType::IORequest as u32 				=> Ok(TlpFormatEncodingType::IORequest),
67            x if x == TlpFormatEncodingType::ConfigType0Request as u32 		=> Ok(TlpFormatEncodingType::ConfigType0Request),
68            x if x == TlpFormatEncodingType::ConfigType1Request as u32 		=> Ok(TlpFormatEncodingType::ConfigType1Request),
69            x if x == TlpFormatEncodingType::Completion as u32 				=> Ok(TlpFormatEncodingType::Completion),
70            x if x == TlpFormatEncodingType::CompletionLocked  as u32 		=> Ok(TlpFormatEncodingType::CompletionLocked),
71            x if x == TlpFormatEncodingType::FetchAtomicOpRequest as u32 	=> Ok(TlpFormatEncodingType::FetchAtomicOpRequest),
72            x if x == TlpFormatEncodingType::UnconSwapAtomicOpRequest as u32 => Ok(TlpFormatEncodingType::UnconSwapAtomicOpRequest),
73            x if x == TlpFormatEncodingType::CompSwapAtomicOpRequest as u32 => Ok(TlpFormatEncodingType::CompSwapAtomicOpRequest),
74            _ => Err(()),
75        }
76    }
77}
78
79#[derive(PartialEq)]
80#[derive(Debug)]
81pub enum TlpType {
82    MemReadReq,
83    MemReadLockReq,
84    MemWriteReq,
85    IOReadReq,
86    IOWriteReq,
87    ConfType0ReadReq,
88    ConfType0WriteReq,
89    ConfType1ReadReq,
90    ConfType1WriteReq,
91    MsgReq,
92    MsgReqData,
93    Cpl,
94    CplData,
95    CplLocked,
96    CplDataLocked,
97    FetchAddAtomicOpReq,
98    SwapAtomicOpReq,
99    CompareSwapAtomicOpReq,
100    LocalTlpPrefix,
101    EndToEndTlpPrefix,
102}
103
104impl Display for TlpType {
105    fn fmt (&self, fmt: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
106        let name = match &self {
107            TlpType::MemReadReq => "Memory Read Request",
108            TlpType::MemReadLockReq => "Locked Memory Read Request",
109            TlpType::MemWriteReq => "Memory Write Request",
110            TlpType::IOReadReq => "IO Read Request",
111            TlpType::IOWriteReq => "IO Write Request",
112            TlpType::ConfType0ReadReq => "Type 0 Config Read Request",
113            TlpType::ConfType0WriteReq => "Type 0 Config Write Request",
114            TlpType::ConfType1ReadReq => "Type 1 Config Read Request",
115            TlpType::ConfType1WriteReq => "Type 1 Config Write Request",
116            TlpType::MsgReq => "Message Request",
117            TlpType::MsgReqData => "Message with Data Request",
118            TlpType::Cpl => "Completion",
119            TlpType::CplData => "Completion with Data",
120            TlpType::CplLocked => "Locked Completion",
121            TlpType::CplDataLocked => "Locked Completion with Data",
122            TlpType::FetchAddAtomicOpReq => "Fetch Add Atomic Op Request",
123            TlpType::SwapAtomicOpReq => "Swap Atomic Op Request",
124            TlpType::CompareSwapAtomicOpReq => "Compare Swap Atomic Op Request",
125            TlpType::LocalTlpPrefix => "Local Tlp Prefix",
126            TlpType::EndToEndTlpPrefix => "End To End Tlp Prefix",
127        };
128        write!(fmt, "{}", name)
129    }
130}
131
132bitfield! {
133        struct TlpHeader(MSB0 [u8]);
134        u32;
135        get_format, _: 2, 0;
136        get_type,   _: 7, 3;
137        get_t9,     _: 8, 8;
138        get_tc,     _: 11, 9;
139        get_t8,     _: 12, 12;
140        get_attr_b2, _: 13, 13;
141        get_ln,     _: 14, 14;
142        get_th,     _: 15, 15;
143        get_td,     _: 16, 16;
144        get_ep,     _: 17, 17;
145        get_attr,   _: 19, 18;
146        get_at,     _: 21, 20;
147        get_length, _: 31, 22;
148}
149
150impl<T: AsRef<[u8]>> TlpHeader<T> {
151
152    fn get_tlp_type(&self) -> Result<TlpType, ()> {
153        let tlp_type = self.get_type();
154        let tlp_fmt = self.get_format();
155
156        match TlpFormatEncodingType::try_from(tlp_type) {
157            Ok(TlpFormatEncodingType::MemoryRequest) => {
158                match TlpFmt::try_from(tlp_fmt) {
159                    Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::MemReadReq),
160                    Ok(TlpFmt::NoDataHeader4DW) => Ok(TlpType::MemReadReq),
161                    Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::MemWriteReq),
162                    Ok(TlpFmt::WithDataHeader4DW) => Ok(TlpType::MemWriteReq),
163					_ => Err(()),
164                }
165            }
166            Ok(TlpFormatEncodingType::MemoryLockRequest) => {
167                match TlpFmt::try_from(tlp_fmt) {
168                    Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::MemReadLockReq),
169                    Ok(TlpFmt::NoDataHeader4DW) => Ok(TlpType::MemReadLockReq),
170					_ => Err(()),
171                }
172            }
173			Ok(TlpFormatEncodingType::IORequest) => {
174				match TlpFmt::try_from(tlp_fmt) {
175					Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::IOReadReq),
176					Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::IOWriteReq),
177					_ => Err(()),
178				}
179			}
180			Ok(TlpFormatEncodingType::ConfigType0Request) => {
181				match TlpFmt::try_from(tlp_fmt) {
182					Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::ConfType0ReadReq),
183					Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::ConfType0WriteReq),
184					_ => Err(()),
185				}
186			}
187            Ok(TlpFormatEncodingType::ConfigType1Request) => {
188                    match TlpFmt::try_from(tlp_fmt) {
189                            Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::ConfType1ReadReq),
190                            Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::ConfType1WriteReq),
191                            _ => Err(()),
192                    }
193            }
194			Ok(TlpFormatEncodingType::Completion) => {
195				println!("Completion fmt: {}", tlp_fmt);
196				match TlpFmt::try_from(tlp_fmt) {
197					Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::Cpl),
198					Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::CplData),
199					_ => Err(()),
200				}
201			}
202			Ok(TlpFormatEncodingType::CompletionLocked) => {
203				match TlpFmt::try_from(tlp_fmt) {
204					Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::CplLocked),
205					Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::CplDataLocked),
206					_ => Err(()),
207				}
208			}
209			Ok(TlpFormatEncodingType::FetchAtomicOpRequest) => {
210				match TlpFmt::try_from(tlp_fmt) {
211					Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::FetchAddAtomicOpReq),
212					Ok(TlpFmt::WithDataHeader4DW) => Ok(TlpType::FetchAddAtomicOpReq),
213					_ => Err(()),
214				}
215			}
216			Ok(TlpFormatEncodingType::UnconSwapAtomicOpRequest) => {
217				match TlpFmt::try_from(tlp_fmt) {
218					Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::SwapAtomicOpReq),
219					Ok(TlpFmt::WithDataHeader4DW) => Ok(TlpType::SwapAtomicOpReq),
220					_ => Err(()),
221				}
222			}
223			Ok(TlpFormatEncodingType::CompSwapAtomicOpRequest) => {
224				match TlpFmt::try_from(tlp_fmt) {
225					Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::CompareSwapAtomicOpReq),
226					Ok(TlpFmt::WithDataHeader4DW) => Ok(TlpType::CompareSwapAtomicOpReq),
227					_ => Err(()),
228				}
229			}
230			Err(_) => Err(())
231        }
232    }
233}
234
235/// Memory Request Trait:
236/// Applies to 32 and 64 bits requests as well as legacy IO-Request
237/// (Legacy IO Request has the same structure as MemRead3DW)
238/// Software using the library may want to use trait instead of bitfield structures
239/// Both 3DW (32-bit) and 4DW (64-bit) headers implement this trait
240/// 3DW header is also used for all Legacy IO Requests.
241pub trait MemRequest {
242    fn address(&self) -> u64;
243    fn req_id(&self) -> u16;
244    fn tag(&self) -> u8;
245    fn ldwbe(&self) -> u8;
246    fn fdwbe(&self) -> u8;
247}
248
249// Structure for both 3DW Memory Request as well as Legacy IO Request
250bitfield! {
251    pub struct MemRequest3DW(MSB0 [u8]);
252    u32;
253    pub get_requester_id,   _: 15, 0;
254    pub get_tag,            _: 23, 16;
255    pub get_last_dw_be,     _: 27, 24;
256    pub get_first_dw_be,    _: 31, 28;
257    pub get_address32,      _: 63, 32;
258}
259
260bitfield! {
261    pub struct MemRequest4DW(MSB0 [u8]);
262    u64;
263    pub get_requester_id,   _: 15, 0;
264    pub get_tag,            _: 23, 16;
265    pub get_last_dw_be,     _: 27, 24;
266    pub get_first_dw_be,    _: 31, 28;
267    pub get_address64,      _: 95, 32;
268}
269
270impl <T: AsRef<[u8]>> MemRequest for MemRequest3DW<T> {
271    fn address(&self) -> u64 {
272        self.get_address32().into()
273    }
274    fn req_id(&self) -> u16 {
275        self.get_requester_id() as u16
276    }
277    fn tag(&self) -> u8 {
278        self.get_tag() as u8
279    }
280    fn ldwbe(&self) -> u8 {
281        self.get_last_dw_be() as u8
282    }
283    fn fdwbe(&self) -> u8 {
284        self.get_first_dw_be() as u8
285    }
286}
287
288impl <T: AsRef<[u8]>> MemRequest for MemRequest4DW<T> {
289    fn address(&self) -> u64 {
290        self.get_address64()
291    }
292    fn req_id(&self) -> u16 {
293        self.get_requester_id() as u16
294    }
295    fn tag(&self) -> u8 {
296        self.get_tag() as u8
297    }
298    fn ldwbe(&self) -> u8 {
299        self.get_last_dw_be() as u8
300    }
301    fn fdwbe(&self) -> u8 {
302        self.get_first_dw_be() as u8
303    }
304}
305
306/// Obtain Memory Request trait from bytes in vector as dyn
307/// This is preffered way of dealing with TLP headers as exact format (32/64 bits) is not required
308///
309/// # Examples
310///
311/// ```
312/// use std::convert::TryFrom;
313///
314/// use rtlp_lib::TlpPacket;
315/// use rtlp_lib::TlpFmt;
316/// use rtlp_lib::MemRequest;
317/// use rtlp_lib::new_mem_req;
318///
319/// let bytes = vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
320/// let tlp = TlpPacket::new(bytes);
321///
322/// if let Ok(tlpfmt) = TlpFmt::try_from(tlp.get_tlp_format()) {
323///     // MemRequest contain only fields specific to PCI Memory Requests
324///     let mem_req: Box<dyn MemRequest> = new_mem_req(tlp.get_data(), &tlpfmt);
325///
326///     // Address is 64 bits regardles of TLP format
327///     //println!("Memory Request Address: {:x}", mem_req.address());
328///
329///     // Format of TLP (3DW vs 4DW) is stored in the TLP header
330///     println!("This TLP size is: {}", tlpfmt);
331///     // Type LegacyIO vs MemRead vs MemWrite is stored in first DW of TLP
332///     println!("This TLP type is: {}", tlp.get_tlp_type());
333/// }
334/// ```
335pub fn new_mem_req(bytes: Vec<u8>, format: &TlpFmt) -> Box<dyn MemRequest> {
336    match format {
337        TlpFmt::NoDataHeader3DW => Box::new(MemRequest3DW(bytes)),
338        TlpFmt::NoDataHeader4DW => Box::new(MemRequest4DW(bytes)),
339        TlpFmt::WithDataHeader3DW => Box::new(MemRequest3DW(bytes)),
340        TlpFmt::WithDataHeader4DW => Box::new(MemRequest4DW(bytes)),
341        TlpFmt::TlpPrefix => Box::new(MemRequest3DW(bytes)),
342    }
343}
344
345/// Configuration Request Trait:
346/// Configuration Requests Headers are always same size (3DW),
347/// this trait is provided to have same API as other headers with variable size
348pub trait ConfigurationRequest {
349    fn req_id(&self) -> u16;
350    fn tag(&self) -> u8;
351    fn bus_nr(&self) -> u8;
352    fn dev_nr(&self) -> u8;
353    fn func_nr(&self) -> u8;
354    fn ext_reg_nr(&self) -> u8;
355    fn reg_nr(&self) -> u8;
356}
357
358/// Obtain Configuration Request trait from bytes in vector as dyn
359///
360/// # Examples
361///
362/// ```
363/// use std::convert::TryFrom;
364///
365/// use rtlp_lib::TlpPacket;
366/// use rtlp_lib::TlpFmt;
367/// use rtlp_lib::ConfigurationRequest;
368/// use rtlp_lib::new_conf_req;
369///
370/// let bytes = vec![0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
371/// let tlp = TlpPacket::new(bytes);
372///
373/// if let Ok(tlpfmt) = TlpFmt::try_from(tlp.get_tlp_format()) {
374///     let config_req: Box<dyn ConfigurationRequest> = new_conf_req(tlp.get_data(), &tlpfmt);
375///
376///     //println!("Configuration Request Bus: {:x}", config_req.bus_nr());
377/// }
378/// ```
379pub fn new_conf_req(bytes: Vec<u8>, _format: &TlpFmt) -> Box<dyn ConfigurationRequest> {
380	Box::new(ConfigRequest(bytes))
381}
382
383bitfield! {
384    pub struct ConfigRequest(MSB0 [u8]);
385    u32;
386    pub get_requester_id,   _: 15, 0;
387    pub get_tag,            _: 23, 16;
388    pub get_last_dw_be,     _: 27, 24;
389    pub get_first_dw_be,    _: 31, 28;
390    pub get_bus_nr,         _: 39, 32;
391    pub get_dev_nr,         _: 44, 40;
392    pub get_func_nr,        _: 47, 45;
393    pub rsvd,               _: 51, 48;
394    pub get_ext_reg_nr,     _: 55, 52;
395    pub get_register_nr,    _: 61, 56;
396    r,                      _: 63, 62;
397}
398
399impl <T: AsRef<[u8]>> ConfigurationRequest for ConfigRequest<T> {
400    fn req_id(&self) -> u16 {
401        self.get_requester_id() as u16
402    }
403    fn tag(&self) -> u8 {
404        self.get_tag() as u8
405    }
406    fn bus_nr(&self) -> u8 {
407        self.get_bus_nr() as u8
408    }
409    fn dev_nr(&self) -> u8 {
410        self.get_dev_nr() as u8
411    }
412    fn func_nr(&self) -> u8 {
413        self.get_func_nr() as u8
414    }
415    fn ext_reg_nr(&self) -> u8 {
416        self.get_ext_reg_nr() as u8
417    }
418    fn reg_nr(&self) -> u8 {
419        self.get_register_nr() as u8
420    }
421}
422
423/// Completion Request Trait
424/// Completions are always 3DW (for with data (fmt = b010) and without data (fmt = b000) )
425/// This trait is provided to have same API as other headers with variable size
426/// To obtain this trait `new_cmpl_req()` function has to be used
427/// Trait release user from dealing with bitfield structures.
428pub trait CompletionRequest {
429    fn cmpl_id(&self) -> u16;
430    fn cmpl_stat(&self) -> u8;
431    fn bcm(&self) -> u8;
432    fn byte_cnt(&self) -> u16;
433    fn req_id(&self) -> u16;
434    fn tag(&self) -> u8;
435    fn laddr(&self) -> u8;
436}
437
438bitfield! {
439    pub struct CompletionReqDW23(MSB0 [u8]);
440    u16;
441    pub get_completer_id,   _: 15, 0;
442    pub get_cmpl_stat,      _: 18, 16;
443    pub get_bcm,            _: 19, 19;
444    pub get_byte_cnt,       _: 31, 20;
445    pub get_req_id,         _: 47, 32;
446    pub get_tag,            _: 55, 48;
447    r,                      _: 57, 56;
448    pub get_laddr,          _: 63, 58;
449}
450
451impl <T: AsRef<[u8]>> CompletionRequest for CompletionReqDW23<T> {
452    fn cmpl_id(&self) -> u16 {
453        self.get_completer_id() as u16
454    }
455    fn cmpl_stat(&self) -> u8 {
456        self.get_cmpl_stat() as u8
457    }
458    fn bcm(&self) -> u8 {
459        self.get_bcm() as u8
460    }
461    fn byte_cnt(&self) -> u16 {
462        self.get_byte_cnt() as u16
463    }
464    fn req_id(&self) -> u16 {
465        self.get_req_id() as u16
466    }
467    fn tag(&self) -> u8 {
468        self.get_tag() as u8
469    }
470    fn laddr(&self) -> u8 {
471        self.get_laddr() as u8
472    }
473}
474
475/// Obtain Completion Request dyn Trait:
476///
477/// # Examples
478///
479/// ```
480/// use rtlp_lib::TlpFmt;
481/// use rtlp_lib::CompletionRequest;
482/// use rtlp_lib::new_cmpl_req;
483///
484/// let bytes = vec![0x20, 0x01, 0xFF, 0xC2, 0x00, 0x00, 0x00, 0x00];
485/// // TLP Format usually comes from TlpPacket or Header here we made up one for example
486/// let tlpfmt = TlpFmt::WithDataHeader4DW;
487///
488/// let cmpl_req: Box<dyn CompletionRequest> = new_cmpl_req(bytes, &tlpfmt);
489///
490/// println!("Requester ID from Completion{}", cmpl_req.req_id());
491/// ```
492pub fn new_cmpl_req(bytes: Vec<u8>, _format: &TlpFmt) -> Box<dyn CompletionRequest> {
493	Box::new(CompletionReqDW23(bytes))
494}
495
496/// Message Request trait
497/// Provide method to access fields in DW2-4 header is handled by TlpHeader
498pub trait MessageRequest {
499    fn req_id(&self) -> u16;
500    fn tag(&self) -> u8;
501	fn msg_code(&self) -> u8;
502	/// DW3-4 vary with Message Code Field
503    fn dw3(&self) -> u32;
504    fn dw4(&self) -> u32;
505}
506
507bitfield! {
508    pub struct MessageReqDW24(MSB0 [u8]);
509    u16;
510    pub get_requester_id,   _: 15, 0;
511    pub get_tag,            _: 23, 16;
512    pub get_msg_code,       _: 31, 24;
513    pub get_dw3,            _: 63, 32;
514    pub get_dw4,            _: 96, 64;
515}
516
517impl <T: AsRef<[u8]>> MessageRequest for MessageReqDW24<T> {
518    fn req_id(&self) -> u16 {
519        self.get_requester_id() as u16
520    }
521    fn tag(&self) -> u8 {
522        self.get_tag() as u8
523    }
524    fn msg_code(&self) -> u8 {
525        self.get_msg_code() as u8
526    }
527    fn dw3(&self) -> u32 {
528        self.get_dw3() as u32
529    }
530    fn dw4(&self) -> u32 {
531        self.get_dw4() as u32
532    }
533    // TODO: implement routedby method based on type
534}
535
536/// Obtain Message Request dyn Trait:
537///
538/// # Examples
539///
540/// ```
541/// use rtlp_lib::TlpFmt;
542/// use rtlp_lib::MessageRequest;
543/// use rtlp_lib::new_msg_req;
544///
545/// let bytes = vec![0x20, 0x01, 0xFF, 0xC2, 0x00, 0x00, 0x00, 0x00];
546/// let tlpfmt = TlpFmt::NoDataHeader3DW;
547///
548/// let msg_req: Box<dyn MessageRequest> = new_msg_req(bytes, &tlpfmt);
549///
550/// println!("Requester ID from Message{}", msg_req.req_id());
551/// ```
552pub fn new_msg_req(bytes: Vec<u8>, _format: &TlpFmt) -> Box<dyn MessageRequest> {
553	Box::new(MessageReqDW24(bytes))
554}
555
556/// TLP Packet Header
557/// Contains bytes for Packet header and informations about TLP type
558pub struct TlpPacketHeader {
559    bytes: Vec<u8>,
560    header: TlpHeader<Vec<u8>>,
561}
562
563impl TlpPacketHeader {
564    pub fn new(bytes: Vec<u8>) -> TlpPacketHeader {
565        let mut dw0 = vec![0; 4];
566        dw0[..4].clone_from_slice(&bytes[0..4]);
567
568        TlpPacketHeader { bytes: bytes, header: TlpHeader(dw0) }
569    }
570
571    pub fn get_tlp_type(&self) -> Result<TlpType, ()> {
572        let mut dw0 = vec![0; 4];
573        dw0[..4].clone_from_slice(&self.bytes[0..4]);
574        let tlp_head = TlpHeader(dw0);
575
576        tlp_head.get_tlp_type()
577    }
578
579    pub fn get_format(&self) -> u32 {self.header.get_format()}
580    pub fn get_type(&self) -> u32 {self.header.get_type()}
581    pub fn get_t9(&self) -> u32 {self.header.get_t9()}
582    pub fn get_tc(&self) -> u32 {self.header.get_tc()}
583    pub fn get_t8(&self) -> u32 {self.header.get_t8()}
584    pub fn get_attr_b2(&self) -> u32 {self.header.get_attr_b2()}
585    pub fn get_ln(&self) -> u32 {self.header.get_ln()}
586    pub fn get_th(&self) -> u32 {self.header.get_th()}
587    pub fn get_td(&self) -> u32 {self.header.get_td()}
588    pub fn get_ep(&self) -> u32 {self.header.get_ep()}
589    pub fn get_attr(&self) -> u32 {self.header.get_attr()}
590    pub fn get_at(&self) -> u32 {self.header.get_at()}
591    pub fn get_length(&self) -> u32 {self.header.get_length()}
592
593}
594
595/// TLP Packet structure is high level abstraction for entire TLP packet
596/// Contains Header and Data
597///
598/// # Examples
599///
600/// ```
601/// use rtlp_lib::TlpPacket;
602/// use rtlp_lib::TlpFmt;
603/// use rtlp_lib::TlpType;
604/// use rtlp_lib::new_msg_req;
605/// use rtlp_lib::new_conf_req;
606/// use rtlp_lib::new_mem_req;
607/// use rtlp_lib::new_cmpl_req;
608///
609/// // Bytes for full TLP Packet
610/// //               <------- DW1 -------->  <------- DW2 -------->  <------- DW3 -------->  <------- DW4 -------->
611/// let bytes = vec![0x00, 0x00, 0x20, 0x01, 0x04, 0x00, 0x00, 0x01, 0x20, 0x01, 0xFF, 0x00, 0xC2, 0x81, 0xFF, 0x10];
612/// let packet = TlpPacket::new(bytes);
613///
614/// let header = packet.get_header();
615/// // TLP Type tells us what is this packet
616/// let tlp_type = header.get_tlp_type().unwrap();
617/// let tlp_format = packet.get_tlp_format();
618/// let requester_id;
619/// match (tlp_type) {
620///      TlpType::MemReadReq |
621///      TlpType::MemReadLockReq |
622///      TlpType::MemWriteReq |
623///      TlpType::IOReadReq |
624///      TlpType::IOWriteReq |
625///      TlpType::FetchAddAtomicOpReq |
626///      TlpType::SwapAtomicOpReq |
627///      TlpType::CompareSwapAtomicOpReq => requester_id = new_mem_req(packet.get_data(), &tlp_format).req_id(),
628///      TlpType::ConfType0ReadReq |
629///      TlpType::ConfType0WriteReq |
630///      TlpType::ConfType1ReadReq |
631///      TlpType::ConfType1WriteReq => requester_id = new_conf_req(packet.get_data(), &tlp_format).req_id(),
632///      TlpType::MsgReq |
633///      TlpType::MsgReqData => requester_id = new_msg_req(packet.get_data(), &tlp_format).req_id(),
634///      TlpType::Cpl |
635///      TlpType::CplData |
636///      TlpType::CplLocked |
637///      TlpType::CplDataLocked => requester_id = new_cmpl_req(packet.get_data(), &tlp_format).req_id(),
638///      TlpType::LocalTlpPrefix |
639///      TlpType::EndToEndTlpPrefix => println!("I need to implement TLP Type: {:?}", tlp_type),
640/// }
641/// ```
642pub struct TlpPacket {
643    header: TlpPacketHeader,
644    data: Vec<u8>,
645}
646
647impl TlpPacket {
648    pub fn new(bytes: Vec<u8>) -> TlpPacket {
649        let mut ownbytes = bytes.to_vec();
650        let mut header = vec![0; 4];
651        header.clone_from_slice(&ownbytes[0..4]);
652        let data = ownbytes.drain(4..).collect();
653        TlpPacket {
654            header: TlpPacketHeader::new(header),
655            data: data,
656        }
657    }
658
659    pub fn get_header(&self) -> &TlpPacketHeader {
660        &self.header
661    }
662
663    pub fn get_data(&self) -> Vec<u8> {
664        self.data.to_vec()
665    }
666
667    pub fn get_tlp_type(&self) -> TlpType {
668        self.header.get_tlp_type().expect("Cannot Parse TLP!")
669    }
670
671    pub fn get_tlp_format(&self) -> TlpFmt {
672        let fmt : TlpFmt = TlpFmt::try_from(self.header.get_format()).unwrap();
673
674        fmt
675    }
676}
677
678
679#[cfg(test)]
680mod tests {
681    use super::*;
682
683    #[test]
684    fn test_tlp_packet() {
685        let d = vec![0x04, 0x00, 0x00, 0x01, 0x20, 0x01, 0xFF, 0x00, 0xC2, 0x81, 0xFF, 0x10];
686        let tlp = TlpPacket::new(d);
687
688        assert_eq!(tlp.get_tlp_type(), TlpType::ConfType0ReadReq);
689        assert_eq!(tlp.get_data(), vec![0x20, 0x01, 0xFF, 0x00, 0xC2, 0x81, 0xFF, 0x10]);
690    }
691
692    #[test]
693    fn test_complreq_trait() {
694		let cmpl_req = CompletionReqDW23([0x20, 0x01, 0xFF, 0x00, 0xC2, 0x81, 0xFF, 0x10]);
695
696        assert_eq!(0x2001, cmpl_req.cmpl_id());
697        assert_eq!(0x7, cmpl_req.cmpl_stat());
698        assert_eq!(0x1, cmpl_req.bcm());
699        assert_eq!(0xF00, cmpl_req.byte_cnt());
700        assert_eq!(0xC281, cmpl_req.req_id());
701        assert_eq!(0xFF, cmpl_req.tag());
702        assert_eq!(0x10, cmpl_req.laddr());
703    }
704
705    #[test]
706    fn test_configreq_trait() {
707		let conf_req = ConfigRequest([0x20, 0x01, 0xFF, 0x00, 0xC2, 0x81, 0xFF, 0x10]);
708
709        assert_eq!(0x2001, conf_req.req_id());
710        assert_eq!(0xFF, conf_req.tag());
711        assert_eq!(0xC2, conf_req.bus_nr());
712        assert_eq!(0x10, conf_req.dev_nr());
713        assert_eq!(0x01, conf_req.func_nr());
714        assert_eq!(0x0F, conf_req.ext_reg_nr());
715        assert_eq!(0x04, conf_req.reg_nr());
716    }
717
718    #[test]
719    fn is_memreq_tag_works() {
720        let mr3dw1 = MemRequest3DW([0x00, 0x00, 0x20, 0x0F, 0xF6, 0x20, 0x00, 0x0C]);
721        let mr3dw2 = MemRequest3DW([0x00, 0x00, 0x01, 0x0F, 0xF6, 0x20, 0x00, 0x0C]);
722        let mr3dw3 = MemRequest3DW([0x00, 0x00, 0x10, 0x0F, 0xF6, 0x20, 0x00, 0x0C]);
723        let mr3dw4 = MemRequest3DW([0x00, 0x00, 0x81, 0x0F, 0xF6, 0x20, 0x00, 0x0C]);
724
725        assert_eq!(0x20, mr3dw1.tag());
726        assert_eq!(0x01, mr3dw2.tag());
727        assert_eq!(0x10, mr3dw3.tag());
728        assert_eq!(0x81, mr3dw4.tag());
729
730        let mr4dw1 = MemRequest4DW([0x00, 0x00, 0x01, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00]);
731        let mr4dw2 = MemRequest4DW([0x00, 0x00, 0x10, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00]);
732        let mr4dw3 = MemRequest4DW([0x00, 0x00, 0x81, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00]);
733        let mr4dw4 = MemRequest4DW([0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00]);
734        let mr4dw5 = MemRequest4DW([0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00]);
735
736        assert_eq!(0x01, mr4dw1.tag());
737        assert_eq!(0x10, mr4dw2.tag());
738        assert_eq!(0x81, mr4dw3.tag());
739        assert_eq!(0xFF, mr4dw4.tag());
740        assert_eq!(0x00, mr4dw5.tag());
741    }
742
743    #[test]
744    fn is_memreq_3dw_address_works() {
745        let memreq_3dw = [0x00, 0x00, 0x20, 0x0F, 0xF6, 0x20, 0x00, 0x0C];
746        let mr = MemRequest3DW(memreq_3dw);
747
748        assert_eq!(0xF620000C, mr.address());
749    }
750
751    #[test]
752    fn is_memreq_4dw_address_works() {
753        let memreq_4dw = [0x00, 0x00, 0x20, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00];
754        let mr = MemRequest4DW(memreq_4dw);
755
756        assert_eq!(0x17fc0000000, mr.address());
757    }
758
759    #[test]
760    fn is_tlppacket_creates() {
761        let memrd32_header = [0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x20, 0x0F, 0xF6, 0x20, 0x00, 0x0C];
762
763        let mr = TlpPacketHeader::new(memrd32_header.to_vec());
764        assert_eq!(mr.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::MemReadReq);
765    }
766
767    #[test]
768    fn tlp_header_type() {
769		// Empty packet is still MemREAD: FMT '000' Type '0 0000' Length 0
770        let memread = TlpHeader([0x0, 0x0, 0x0, 0x0]);
771        assert_eq!(memread.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::MemReadReq);
772
773		// MemRead32 FMT '000' Type '0 0000'
774		let memread32 = TlpHeader([0x00, 0x00, 0x20, 0x01]);
775		assert_eq!(memread32.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::MemReadReq);
776
777		// MemWrite32 FMT '010' Type '0 0000'
778		let memwrite32 = TlpHeader([0x40, 0x00, 0x00, 0x01]);
779		assert_eq!(memwrite32.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::MemWriteReq);
780
781		// CPL without Data: FMT '000' Type '0 1010'
782		let cpl_no_data = TlpHeader([0x0a, 0x00, 0x10, 0x00]);
783		assert_eq!(cpl_no_data.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::Cpl);
784
785		// CPL with Data: FMT '010' Type '0 1010'
786		let cpl_with_data = TlpHeader([0x4a, 0x00, 0x20, 0x40]);
787		assert_eq!(cpl_with_data.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::CplData);
788
789		// MemRead 4DW: FMT: '001' Type '0 0000'
790		let memread_4dw = TlpHeader([0x20, 0x00, 0x20, 0x40]);
791		assert_eq!(memread_4dw.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::MemReadReq);
792
793		// Config Type 0 Read request: FMT: '000' Type '0 0100'
794		let conf_t0_read = TlpHeader([0x04, 0x00, 0x00, 0x01]);
795		assert_eq!(conf_t0_read.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::ConfType0ReadReq);
796
797		// Config Type 0 Write request: FMT: '010' Type '0 0100'
798		let conf_t0_write = TlpHeader([0x44, 0x00, 0x00, 0x01]);
799		assert_eq!(conf_t0_write.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::ConfType0WriteReq);
800
801        // Config Type 1 Read request: FMT: '000' Type '0 0101'
802        let conf_t1_read = TlpHeader([0x05, 0x88, 0x80, 0x01]);
803               assert_eq!(conf_t1_read.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::ConfType1ReadReq);
804
805        // Config Type 1 Read request: FMT: '010' Type '0 0101'
806        let conf_t1_write = TlpHeader([0x45, 0x88, 0x80, 0x01]);
807               assert_eq!(conf_t1_write.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::ConfType1WriteReq);
808
809        // HeaderLog: 04000001 0000220f 01070000 af36fc70
810        // HeaderLog: 60009001 4000000f 00000280 4047605c
811        let memwrite64 = TlpHeader([0x60, 0x00, 0x90, 0x01]);
812        assert_eq!(memwrite64.get_tlp_type().expect("Cannot Parse TLP!"), TlpType::MemWriteReq);
813    }
814
815    #[test]
816    fn tlp_header_works_all_zeros() {
817        let bits_locations = TlpHeader([0x0, 0x0, 0x0, 0x0]);
818
819        assert_eq!(bits_locations.get_format(), 0);
820        assert_eq!(bits_locations.get_type(), 0);
821        assert_eq!(bits_locations.get_t9(), 0);
822        assert_eq!(bits_locations.get_tc(), 0);
823        assert_eq!(bits_locations.get_t8(), 0);
824        assert_eq!(bits_locations.get_attr_b2(), 0);
825        assert_eq!(bits_locations.get_ln(), 0);
826        assert_eq!(bits_locations.get_th(), 0);
827        assert_eq!(bits_locations.get_td(), 0);
828        assert_eq!(bits_locations.get_ep(), 0);
829        assert_eq!(bits_locations.get_attr(), 0);
830        assert_eq!(bits_locations.get_at(), 0);
831        assert_eq!(bits_locations.get_length(), 0);
832    }
833
834    #[test]
835    fn tlp_header_works_all_ones() {
836        let bits_locations = TlpHeader([0xff, 0xff, 0xff, 0xff]);
837
838        assert_eq!(bits_locations.get_format(), 0x7);
839        assert_eq!(bits_locations.get_type(), 0x1f);
840        assert_eq!(bits_locations.get_t9(), 0x1);
841        assert_eq!(bits_locations.get_tc(), 0x7);
842        assert_eq!(bits_locations.get_t8(), 0x1);
843        assert_eq!(bits_locations.get_attr_b2(), 0x1);
844        assert_eq!(bits_locations.get_ln(), 0x1);
845        assert_eq!(bits_locations.get_th(), 0x1);
846        assert_eq!(bits_locations.get_td(), 0x1);
847        assert_eq!(bits_locations.get_ep(), 0x1);
848        assert_eq!(bits_locations.get_attr(), 0x3);
849        assert_eq!(bits_locations.get_at(), 0x3);
850        assert_eq!(bits_locations.get_length(), 0x3ff);
851    }
852}