/* * GigaSpaceWire switch driver for MC-30SF6EM-6U evaluation kit * * Copyright (c) 2019 Elvees (support@elvees.com) * Author: Dmitry Evtushenko * */ #ifndef __gspwsw_h #define __gspwsw_h #include #include #ifdef CONFIG_MIPS //#include //#include //#include #include #endif //CONFIG_MIPS #include "fifo.h" #ifdef USE_DMA_TEST #include "test.h" #endif //USE_DMA_TEST #ifdef CONFIG_MIPS #define USE_ETHOSPW //- replace to definition from CONFIG_... #endif //CONFIG_MIPS //#define USE_RX_DBL_BUF //#define USE_TX_DBL_BUF #define GSPW_DEV_NAME "gspwsw" //#define DEV_NAME "gspw" #if defined(CONFIG_MC30SF6) // #define NB_OF_CHANNELS 2 #define NB_OF_CHANNELS 1 #endif //- defined(CONFIG_MC30SF6) ////////////////////////////////// DEFINES: ////////////////////////////////// #define SPW_EOP 1 #define SPW_EEP 2 // return codes: #define RC_SPW_SUCCESS 0 // MC-30SF6EM-6U board configuration: #define MAX_SPW_PORT_QNT 2 #define MAX_ALL_SPW_MSK 0x3 //#define MAX_GSPW_PORT_QNT 4 // DMA, buffers configuration: #define SPW_RX_DATA_BUFSZ 65536 #define SPW_RX_DESC_BUFSZ 384 #define SPW_TX_DATA_BUFSZ 2048 #define SPW_ONE_BUFFER_DESC_CNT (SPW_RX_DESC_BUFSZ / 48) #define SPW_RX_DATA_BUF_SIZE 65536 #define SPW_TX_DATA_BUF_SIZE 65536 // Биты масок портов в которые необходимо передать пакет: #define GSPW_PACK_PORT_OUT_CFG 1 #define GSPW_PACK_PORT_OUT_SWIC0 2 #define GSPW_PACK_PORT_OUT_SWIC1 4 #define GSPW_PACK_PORT_OUT_SWICS (GSPW_PACK_PORT_OUT_SWIC0 | GSPW_PACK_PORT_OUT_SWIC1) // Номер портов spaceware: #define GSPW_PORT_CFG 0 #define GSPW_PORT_SWIC0 1 #define GSPW_PORT_SWIC1 2 #define GSPW_PORT_GSPW0 3 #define GSPW_PORT_GSPW1 4 #define GSPW_PORT_GSPW2 5 #define GSPW_PORT_GSPW3 6 #define MAX_SPW_PORT_NAME_SIZE 30 #define GSPW_CFG_PORT_NUM 0 #define GSPW_CFG_PORT_QNT 1 #define GSPW_FIRST_SPW_PORT_NUM 1 #define GSPW_SPW_PORT_QNT 2 #define GSPW_DRV_PORT_QNT (GSPW_CFG_PORT_QNT + GSPW_SPW_PORT_QNT) // SpaceWire routing: #define SPW_RT_TRACK_ADDR_FIRST 0 #define SPW_RT_TRACK_ADDR_LAST 2 #define SPW_RT_LOGIC_ADDR_FIRST 32 #define SPW_RT_LOGIC_ADDR_LAST 255 #define SPW_RT_TABLE_SIZE 256 // IOCTL arguments: #define IOCTL_ARG__INERN_DMA_TEST_START 0 #define IOCTL_ARG__INERN_DMA_TEST_STOP 1 #define IOCTL_ARG__INERN_DMA_TEST_PRINT 2 #define XTI125_FREQ 125 //- 125 MGz enum EBdsStat { BDS_STAT_ERR_RST =0, //- ErrorReset BDS_STAT_ERR_WAIT =1, //- ErrorWait BDS_STAT_READY =2, //- Ready BDS_STAT_STARTED =3, //- Started BDS_STAT_CONNECTING =4, //- Connecting, BDS_STAT_RUN =5 //- Run }; //// port interface mode: // Gigaspacewire current mode: enum gspw_mode_e { GSPW_MODE_CONFIG =0, //- configure mode GSPW_MODE_WORK =1, //- working mode GSPW_MODE_STOP =2, //- stopping mode GSPW_MODE_FORCE_STOP =3 //- force stopping mode }; // Формат дескриптора пакета typedef struct __attribute__((__packed__)) gspw_descr_s { u64 size : 25; //- азмер данных u64 unused : 4; //- Не используется u64 type_ep /*type*/ : 2; //- Тип конца пакета: EOP или EEP u64 valid : 1; //- Признак заполнения дескриптора действительными данными u64 port_mask : 7; u64 unused1 : 25; //- Не используется } gspw_desc_t; extern void gspw_desc_print( gspw_desc_t *pd); // Один буфер двойной буферизации typedef struct one_buf_s { char *p_buf; //- Непосредственно буфер (должен быть выравнен на границу 8 байт для // нормальной работы DMA) char *p_reader; //- Текущий указатель, с которого производится чтение int empty; //- Признак пустого буфера unsigned chain_addr; //- Адрес цепочки инициализации (физ.), если она используется, иначе 0 } one_buf_t; // Двойной буфер typedef struct dbl_buf_s { one_buf_t half[2]; //- Две половины буфера int size; //- азмер одной половины int reader_idx; //- Индекс читателя int dma_idx; //- Индекс DMA int dma_chan; //- Канал DMA } dbl_buf_t; // Элемент цепочки DMA typedef struct __attribute__((__packed__)) dma_params_s { uint32_t run; //zero; //- Неиспользуемое поле uint32_t ir; //- Значение, загружаемое в IR uint32_t cp; //- Значение, загружаемое в CP uint32_t csr; //- Значение, загружаемое в CSR } dma_params_t; // spacewire port base structure: typedef struct spw_port_s { int num; //- Номер канала spacewire, считая от 0 [0,1] char name[MAX_SPW_PORT_NAME_SIZE]; //- Имя устройства int open; //- Признак открытия канала (1) int net_usage; //- Признак сетевого использования порта int nonblock; //- Признак неблокирующего ввода-вывода } spw_port_t; //extern int spw_port__init( spw_port_t *p_port); // SpaceWire controller base structure: /*typedef struct s_spw_ctrl { spw_port_t port; //- port data unsigned speed; //- абочая скорость канала int connected; //- connection sign } spw_ctrl_t;*/ //extern int spw_ctrl__init( spw_ctrl_t *p_ctrl); /* // GigaSpaceWire controller: struct s_gspw_ctrl { int port; //- Номер канала spacewire, считая от 0 unsigned speed; //- абочая скорость канала int open; //- Признак открытия канала int connected; int nonblock; //- Признак неблокирующего ввода-вывода char name[sizeof(DEV_NAME) + 1]; //- Имя устройства }; typedef struct s_gspw gspw_t; */ // fifo list item state: enum dma_fi_stat_e { DMA_FI_STAT__FREE =0, DMA_FI_STAT__FILLING =1, DMA_FI_STAT__FILLED =2, DMA_FI_STAT__SENT =3 }; // DMA descriptor fifo item: struct dma_desc_fi_s { struct dma_desc_fi_s *p_next; struct dma_desc_fi_s *p_prev; dma_params_t reg_init __attribute__ ((aligned (8))); gspw_desc_t desc; u32 flag; //- flags u32 pos_proc; //- processing data position by descriptor enum dma_fi_stat_e stat; //- статус }; typedef struct dma_desc_fi_s dma_desc_fi_t; static inline void dma_desc_fi_reset_proc( dma_desc_fi_t *pfi) { pfi->flag = 0; pfi->pos_proc = 0; *((u64 *)&pfi->desc) = 0LL; pfi->stat = DMA_FI_STAT__FREE;} extern void dma_desc_fi_print( dma_desc_fi_t *pd); // DMA data fifo item: struct dma_data_fi_s { struct dma_data_fi_s *p_next; struct dma_data_fi_s *p_prev; dma_params_t reg_init __attribute__ ((aligned (8))); char *p_buf; //u32 sz_buf; u32 pos_proc; //- buffer processing position //u32 is_ready; //- buffer is ready enum dma_fi_stat_e stat; //- статус }; typedef struct dma_data_fi_s dma_data_fi_t; static inline void dma_data_fi_reset_proc( dma_data_fi_t *pfi) { pfi->pos_proc = 0; pfi->stat = DMA_FI_STAT__FREE;} // DMA chain: struct dma_chain_s { fifo_t ff; //- FIFO chain (ring list) u32 qnt; //- item quantity in chain u32 szi; //- chain item size u32 sz_data_buf; //- data buffer size //dma_data_fi_t *pfi_cur; //- current item on under filling }; typedef struct dma_chain_s dma_chain_t; /*extern bool dma_chain_init( dma_chain_t *p_dch, u32 qnt, u32 szi, pf_delete_fitem_t pf_delete); extern bool dma_chain_create_data_bufs( dma_chain_t *p_dch, u32 sz_buf); extern void dma_chain_free( dma_chain_t *p_dch); extern int dma_chain_create_bufs( dma_chain_t *p_dch, u32 sz_buf);*/ // DMA job states: enum dma_job_stat_e { //DMA_JOB_STAT_NONE =0, //- undefined state DMA_JOB_STAT_FREE =0, //- job is free for using DMA_JOB_STAT_PREP =1, //- job is under of preparation DMA_JOB_STAT_READY =2, //- job is ready for run DMA_JOB_STAT_RUN =3, //- job is running DMA_JOB_STAT_FIN =4 //- job is finished }; struct gspw_ctrl_s; typedef struct gspw_ctrl_s gspw_ctrl_t; // DMA tx job: struct dma_tx_job_s { struct dma_tx_job_s *p_next; struct dma_tx_job_s *p_prev; dma_desc_fi_t *p_desc_first; dma_desc_fi_t *p_desc_last; dma_desc_fi_t *p_desc_cur; dma_data_fi_t *p_data_first; dma_data_fi_t *p_data_last; dma_data_fi_t *p_data_cur; gspw_ctrl_t *pspw; enum dma_job_stat_e stat; }; typedef struct dma_tx_job_s dma_tx_job_t; // GigaSpaceWire controller base structure: typedef struct gspw_ctrl_s { spw_port_t port; //- port data unsigned speed; //- рабочая скорость канала int connected; //- connection sign enum EBdsStat bds; //- BDS state uint32_t cnt_int_con; //- connection (discon.) interrupt counter u32 state; //- state //enum intf_mode_e mode; //- intf_mode_e //- Очереди ожидания для функций старта read (в режиме блокирующего ввода-вывода): //wait_queue_head_t rxdatawq; wait_queue_head_t wq_rx; //rxdescwq; u32 max_qnt_send_desc; //- максимальное количество дескрипторов на отправку u32 cnt_tx_desc_send; //- текущее количество сформированных дескрипторов на отправку #ifdef USE_ETHOSPW struct mutex mtx_rx; #endif //USE_ETHOSPW #if 0 // Очереди ожидания: wait_queue_head_t wq_st; //stwq; wait_queue_head_t wq_txdata; //txdatawq; //- Очередь ожидания свободного буфера DMA для записи в него данных wait_queue_head_t wq_txdesc; //txdescwq; //- Очередь ожидания свободного дескриптора DMA для формирования записываемого пакета данных wait_queue_head_t wq_txjob; //txjobwq; //- Очередь ожидания сформированных данных на отправку //- Очереди ожидания для функций старта read (в режиме блокирующего ввода-вывода): //wait_queue_head_t rxdatawq; wait_queue_head_t wq_rx; //rxdescwq; // TX: u32 qnt_tx_desc; //- TX buffer descriptor quantity u32 qnt_tx_data; //- TX data buffer quantity u32 sz_tx_data_buf; //- TX data buffer size dma_chain_t dch_tx_desc; dma_chain_t dch_tx_data; u32 max_sz_tx_pack; //- max SWIC TX packet size //u8 is_init_tx_desc_chain; fifo_t ff_tx_job; //dma_tx_job_t *p_cur_tx_job; struct task_struct *p_task_tx_dma_job; u32 max_qnt_send_desc; //- максимальное количество дескрипторов на отправку u32 cnt_tx_desc_send; //- текущее количество сформированных дескрипторов на отправку //u32 sz_tx_pack; // RX: u32 qnt_rx_desc; //- RX buffer descriptor quantity u32 qnt_rx_data; //- RX data buffer quantity u32 sz_rx_data_buf; //- RX data buffer size dma_chain_t dch_rx_desc; dma_chain_t dch_rx_data; u32 is_reset_io; // Статистика: unsigned rx_eop; //- Количество принятых пакетов с EOP unsigned rx_eep; //- Количество принятых пакетов с EEP unsigned rx_bytes; //- Количество принятых байт unsigned tx_packets; //- Количество переданных пакетов unsigned tx_bytes; //- Количество переданных байт unsigned txdma_waits; //- Количество ожиданий освобождения DMA передатчика #endif //0 } gspw_ctrl_t; //extern int gspw_ctrl__init( spw_ctrl_t *p_ctrl); // DMA settings: typedef struct dma_set_s { u32 qnt_desc; //- TX buffer descriptor quantity u32 qnt_data; //- TX data buffer quantity u32 sz_data_buf; //- TX data buffer size } dma_set_t; // DMA TX settings: typedef struct dma_tx_set_s { dma_set_t dma; u32 max_sz_pack; //- max SWIC TX packet size } dma_tx_set_t; // DMA RX settings: typedef struct dma_rx_set_s { dma_set_t dma; } dma_rx_set_t; // Spacewire settings: typedef struct spw_set_s { u32 tx_speed; u32 max_qnt_send_desc; //- максимальное количество дескрипторов на отправку (max_qnt_send_desc) } spw_set_t; // GigaSpaceware switch settings: typedef struct gspw_sw_settings_s { dma_rx_set_t rx; dma_tx_set_t tx; spw_set_t a_spw[MAX_SPW_PORT_QNT]; u16 a_rt[SPW_RT_TABLE_SIZE]; //- routing table } gspw_sw_set_t; // configure port controller: typedef struct gspw_cfg_ctrl_s { spw_port_t port; #ifdef CONFIG_MIPS //struct completion compl_tx; //struct mutex mut_tx; #endif //CONFIG_MIPS #if 1 // Очереди ожидания: wait_queue_head_t wq_st; //stwq; wait_queue_head_t wq_txdata; //txdatawq; //- Очередь ожидания свободного буфера DMA для записи в него данных wait_queue_head_t wq_txdesc; //txdescwq; //- Очередь ожидания свободного дескриптора DMA для формирования записываемого пакета данных wait_queue_head_t wq_txjob; //txjobwq; //- Очередь ожидания сформированных данных на отправку //- Очереди ожидания для функций старта read (в режиме блокирующего ввода-вывода): //wait_queue_head_t rxdatawq; //wait_queue_head_t wq_rx; //rxdescwq; // TX: u32 qnt_tx_desc; //- TX buffer descriptor quantity u32 qnt_tx_data; //- TX data buffer quantity u32 sz_tx_data_buf; //- TX data buffer size u32 max_sz_tx_pack; //- max SWIC TX packet size dma_chain_t dch_tx_desc; dma_chain_t dch_tx_data; //u8 is_init_tx_desc_chain; //dma_tx_job_t *p_cur_tx_job; struct task_struct *p_task_tx_dma_job; fifo_t ff_tx_job; //u32 sz_tx_pack; // RX: u32 qnt_rx_desc; //- RX buffer descriptor quantity u32 qnt_rx_data; //- RX data buffer quantity u32 sz_rx_data_buf; //- RX data buffer size dma_chain_t dch_rx_desc; dma_chain_t dch_rx_data; u32 is_reset_io; // Статистика: unsigned rx_eop; //- Количество принятых пакетов с EOP unsigned rx_eep; //- Количество принятых пакетов с EEP unsigned rx_bytes; //- Количество принятых байт unsigned rx_drop_pack; //- количество сброшенных пакетов (по проблемам верхнего уровня) unsigned rx_drop_bytes; //- количество сброшенных байт (по проблемам верхнего уровня) unsigned tx_packets; //- Количество переданных пакетов unsigned tx_bytes; //- Количество переданных байт //unsigned txdma_waits; //- Количество ожиданий освобождения DMA передатчика #endif //0 struct task_struct *p_task_stop_work_mode; #ifdef USE_DMA_TEST dma_test_t test; #endif //USE_DMA_TEST } gspw_cfg_ctrl_t; extern int gspw_cfg_ctrl__init( gspw_cfg_ctrl_t *pcfg); extern void gspw_cfg_ctrl_free( gspw_cfg_ctrl_t *pcfg); extern void print_fifo_held_qnt( gspw_cfg_ctrl_t *pcfg, const char *psMes); extern void dma_rx_chain_free( gspw_cfg_ctrl_t *pcfg); extern void dma_tx_chain_free( gspw_cfg_ctrl_t *pcfg); extern void gspw_cfg_ctrl_free( gspw_cfg_ctrl_t *pcfg); extern int dma_rx_chain_init( gspw_cfg_ctrl_t *pcfg); extern int dma_tx_chain_init( gspw_cfg_ctrl_t *pcfg); extern int gspw_cfg_ctrl_init_job_task( gspw_cfg_ctrl_t *pcfg); extern void init_dma_rx_desk_chain_reg( gspw_cfg_ctrl_t *pcfg); extern void init_dma_rx_data_chain_reg( gspw_cfg_ctrl_t *pcfg); /* // GigaSpaceWire: struct s_gspw { };*/ // routing block: typedef struct spw_routing_s { u16 a_rt[SPW_RT_TABLE_SIZE]; //- routing table //... } spw_routing_t; struct range_u16_s { u16 beg; u16 end; }; // routing table exchange: typedef struct spw_rt_exch_s { struct range_u16_s rng; u16 a_rt[SPW_RT_TABLE_SIZE]; } spw_rt_exch_t; //extern int spw_routing__init( spw_routing_t *p_rt); // GigaSpaceWire switch: typedef struct gspw_switch_s { char name[MAX_SPW_PORT_NAME_SIZE]; //- Имя устройства //u32 mode_msk; //- port working mode mask enum gspw_mode_e mode; // рабочие признаки по остановки работы TX & RX функционала: u32 is_rx_stop; u32 is_tx_stop; u32 is_tx_job_stop; gspw_cfg_ctrl_t cfg_ctrl; //- configure controller object //spw_ctrl_t a_spwc[MAX_SPW_PORT_QNT]; //- array of simple SpaceWire controller objects //gspw_ctrl_t a_gspwc[MAX_GSPW_PORT_QNT]; //- array of GigaSpaceWire controller objects gspw_ctrl_t a_gspwc[MAX_SPW_PORT_QNT]; #ifndef LINUX_APP struct mutex mtx_tx; #endif //LINUX_APP spw_routing_t rt; //- routing object gspw_sw_set_t set_new; //- new settings for applying } gspw_switch_t; //extern int gspw_switch__init( gspw_switch_t *p_sw); extern int is_init_gspwsw; extern gspw_switch_t gspw_sw; extern void gspw_sw_set_settings( void); extern void gspw_wake_up_all_rx_thread( void); extern void wake_up_next_rx_thread( fifo_t *pff_desc, u32 port_cur); extern int gspw_dev_close( unsigned dev_num, u32 is_net); extern int gspw_dev_open( unsigned dev_num, u32 is_net); extern ssize_t gspw_dev_write( unsigned dev_num, u32 is_net, const char *p_buf, size_t size, loff_t *ppos); #endif //__gspwsw_h