use io::{Write, Error as IoError}; use board_misoc::{csr, cache}; use sched::{Io, TcpListener, TcpStream, Error as SchedError}; use analyzer_proto::*; const BUFFER_SIZE: usize = 512 * 1024; #[repr(align(64))] struct Buffer { data: [u8; BUFFER_SIZE], } static mut BUFFER: Buffer = Buffer { data: [0; BUFFER_SIZE] }; fn arm() { unsafe { let base_addr = &mut BUFFER.data[0] as *mut _ as usize; let last_addr = &mut BUFFER.data[BUFFER_SIZE - 1] as *mut _ as usize; csr::rtio_analyzer::message_encoder_overflow_reset_write(1); csr::rtio_analyzer::dma_base_address_write(base_addr as u64); csr::rtio_analyzer::dma_last_address_write(last_addr as u64); csr::rtio_analyzer::dma_reset_write(1); csr::rtio_analyzer::enable_write(1); } } fn disarm() { unsafe { csr::rtio_analyzer::enable_write(0); while csr::rtio_analyzer::busy_read() != 0 {} cache::flush_cpu_dcache(); cache::flush_l2_cache(); } } fn worker(stream: &mut TcpStream) -> Result<(), IoError> { let data = unsafe { &BUFFER.data[..] }; let overflow_occurred = unsafe { csr::rtio_analyzer::message_encoder_overflow_read() != 0 }; let total_byte_count = unsafe { csr::rtio_analyzer::dma_byte_count_read() }; let pointer = (total_byte_count % BUFFER_SIZE as u64) as usize; let wraparound = total_byte_count >= BUFFER_SIZE as u64; let header = Header { total_byte_count: total_byte_count, sent_bytes: if wraparound { BUFFER_SIZE as u32 } else { total_byte_count as u32 }, overflow_occurred: overflow_occurred, log_channel: csr::CONFIG_RTIO_LOG_CHANNEL as u8, dds_onehot_sel: true // kept for backward compatibility of analyzer dumps }; debug!("{:?}", header); stream.write_all("e".as_bytes())?; header.write_to(stream)?; if wraparound { stream.write_all(&data[pointer..])?; stream.write_all(&data[..pointer])?; } else { stream.write_all(&data[..pointer])?; } Ok(()) } pub fn thread(io: Io) { let listener = TcpListener::new(&io, 65535); listener.listen(1382).expect("analyzer: cannot listen"); loop { arm(); let mut stream = listener.accept().expect("analyzer: cannot accept"); info!("connection from {}", stream.remote_endpoint()); disarm(); match worker(&mut stream) { Ok(()) => (), Err(err) => error!("analyzer aborted: {}", err) } stream.close().expect("analyzer: close socket") } }