/* * SWIC driver for MCT-04EM-3U evaluation kit * * Copyright (c) 2020 Elvees (support@elvees.com) * Author: Dmitry Evtushenko * */ #include #include #include #include #include #include #include #include #include #include #include #include "ctl.h" #include "reg.h" #include "func.h" #include "swic.h" #include "../ua_mem.h" #define VAL_MSK_DFLT 0xFFFFFFFF //- defaulte value mask #define VAL_OFS_DFLT 0 //- defaulte value offset #define SWIC_ADDR_OFS 0xA000 // address complementation: #define COMPL_ADDR( addr) \ if( !(addr & 0xFFFF0000)) \ addr |= MC_BASE_ADDR; \ if( !(addr & 0xF000)) \ addr |= SWIC_ADDR_OFS; #define GET_REG( addr) (*(volatile unsigned *)addr) #define SET_REG( addr, val) *(volatile unsigned *)addr = val // 1 - connected, 0 - not connected, -1 - errors static int swic_is_connected( unsigned int port) { u32 link_stat; if( port >= MAX_SPW_PORT_QNT) return -1; link_stat = (SWIC_TX_SPEED_REG(port) >> SWIC_STAT_LINK_OFS) & SWIC_STAT_LINK_MSK; return (link_stat == SWIC_STAT_LINK_RUN) ? 1 : 0; } // 1 - set speed, 0 - no, -1 - errors int swic_set_tx_speed( unsigned port, unsigned speed) { unsigned rem = (((speed % 5) > 2) ? 1 : 0); //- remainder u32 coef; if( port >= MAX_SPW_PORT_QNT) return -1; if( speed < 5) speed = 5; if( speed > 400) speed = 400; coef = (speed / 5) + rem; SWIC_TX_SPEED_REG( port) &= ~(SWIC_TX_SPEED_COEF_MSK << SWIC_TX_SPEED_COEF_OFS); SWIC_TX_SPEED_REG( port) |= ((coef & SWIC_TX_SPEED_COEF_MSK) << SWIC_TX_SPEED_COEF_OFS); mdelay( 100); pr_info( "swic_set_tx_speed: port=%u, speed=%u, TX_SPEED=%Xh\n", port, speed, SWIC_TX_SPEED_REG(port)); return swic_is_connected( port); } /*static int swic_get_rx_speed( unsigned port) { if( port >= MAX_SPW_PORT_QNT) return -1; return (int )(GSPW_RX_SPEED_REG(port) & GSPW_SPW_RX_SPEED_MSK); }*/ static void swic_print_dbg_stat( swic_ctrl_t *pctl) { pr_info( "%s: cnt_int_con=%u\n", pctl->port.name, pctl->cnt_int_con); } void swic_mem_test( swic_ctrl_t *pctl) { // ... } void swic_reset_tx_rx( swic_ctrl_t *pctl) { pctl->is_reset_io = 1; wake_up_interruptible( &pctl->wq_txdata); wake_up_interruptible( &pctl->wq_txdesc); //wake_up_interruptible( &pctl->wq_txjob); fifo_reset( &pctl->dch_tx_desc.ff); fifo_reset( &pctl->dch_tx_data.ff); fifo_reset( &pctl->ff_tx_job); fifo_reset( &pctl->dch_rx_desc.ff); fifo_reset( &pctl->dch_rx_data.ff); pctl->is_reset_io = 0; } static int thread_stop_work_mode( void *pv) { swic_ctrl_t *pctl = pv; u32 tm_wait = 1000; u32 delay = 100; u32 i, cnt = (tm_wait / delay); int rc = RC_SPW_SUCCESS; for( i=0; (i < cnt); ++i) { if( pctl->is_rx_stop && pctl->is_tx_stop && pctl->is_tx_job_stop) { pctl->mode = SWIC_MODE_CONFIG; pr_info("%s interface have been stopped\n", pctl->port.name); goto l_end; } mdelay( delay); } pr_info( "%s interfaces will be forced stopped now\n", pctl->port.name); pctl->mode = SWIC_MODE_FORCE_STOP; wake_up_interruptible( &pctl->wq_rx); wake_up_interruptible( &pctl->wq_txdata); wake_up_interruptible( &pctl->wq_txdesc); wake_up_interruptible( &pctl->wq_txjob); mdelay( 200); if( (pctl->is_rx_stop == 0) || (pctl->is_tx_stop == 0) || (pctl->is_tx_job_stop == 0)) { pr_info( "Not all spaceware interfaces were stopped\n"); if( rc == RC_SPW_SUCCESS) rc = EBUSY; } l_end:; // disable interrupts: drv_swic_enable_dma_irqs( pctl->port.num, 0); drv_swic_enable_connect_irqs( pctl->port.num, 0); reset_all_dma( pctl); SWIC_MODE_REG( pctl->port.num) &= ~(SWIC_MODE_AUTOSTART | SWIC_MODE_LINKSTART /*| SWIC_MODE_AUTO_SPEED*/); SWIC_MODE_REG( pctl->port.num) |= (SWIC_MODE_LINK_DSBL | SWIC_MODE_LINK_RST); pctl->link_stat = SWIC_STAT_LINK_RST; pctl->connected = 0; pctl->mode = SWIC_MODE_CONFIG; pr_info( "thread_stop_work_mode: %s mode=%i END \n", pctl->port.name, pctl->mode); if( !pctl->is_tx_job_stop && pctl->p_task_tx_dma_job) { pr_info( "stop kthread thread_dma_tx_job\n"); if( (rc = kthread_stop( pctl->p_task_tx_dma_job))==-EINTR ) { pr_info("kthread_stop: ERROR(%i)\n", rc); } } pr_info( "thread_stop_work_mode: END \n"); return rc; } int set_configure_mode( swic_ctrl_t *pctl) { if( pctl->mode != SWIC_MODE_WORK) return -EPERM; pctl->is_rx_stop = 0; pctl->is_tx_stop = 0; pctl->is_tx_job_stop = 0; if( pctl->port.open == 0) { pctl->is_rx_stop |= 1; pctl->is_tx_stop |= 1; } pr_info("%s interface will be stopped now\n", pctl->port.name); pctl->mode = SWIC_MODE_STOP; wake_up_interruptible( &pctl->wq_rx); wake_up_interruptible( &pctl->wq_txdata); wake_up_interruptible( &pctl->wq_txdesc); wake_up_interruptible( &pctl->wq_txjob); pctl->p_task_stop_work_mode = kthread_run( &thread_stop_work_mode, pctl, "thread_stop_work_mode"); if( pctl->p_task_stop_work_mode==NULL && IS_ERR( pctl->p_task_stop_work_mode)) { pr_info( "Could not create 'thread_stop_work_mode' thread\n"); return -ENOMEM; } return RC_SPW_SUCCESS; } static int set_work_mode( swic_ctrl_t *pctl) { int rc; if( pctl->mode != SWIC_MODE_CONFIG) return -EPERM; pr_info("%s interface will be started now\n", pctl->port.name); pctl->is_rx_stop = 0; pctl->is_tx_stop = 0; pctl->is_tx_job_stop = 0; init_waitqueue_head( &pctl->wq_st); init_waitqueue_head( &pctl->wq_txdesc); init_waitqueue_head( &pctl->wq_txdata); init_waitqueue_head( &pctl->wq_txjob); reset_all_dma( pctl); if( (rc=swic_ctrl_init_job_task( pctl)) != RC_SPW_SUCCESS) return rc; pctl->mode = SWIC_MODE_WORK; SWIC_STAT_REG( pctl->port.num) = SWIC_STAT_ALL_ERRS /*| SWIC_STAT_CONNECTED*/; //SWIC_STAT_ALL_ERRS | SWIC_STAT_GOT_INT | SWIC_STAT_GOT_ACK; /*SWIC_STAT_REG( pctl->port.num) = SWIC_STAT_ALL_ERRS | SWIC_STAT_GOT_FIRST_BIT | SWIC_STAT_GOT_TIME | SWIC_STAT_GOT_INT | SWIC_STAT_GOT_ACK | SWIC_STAT_CC_11 | SWIC_STAT_CC_01;*/ SWIC_MODE_REG( pctl->port.num) &= ~(SWIC_MODE_LINK_DSBL | SWIC_MODE_LINK_RST); SWIC_MODE_REG( pctl->port.num) |= (SWIC_MODE_AUTOSTART | SWIC_MODE_LINKSTART /*| SWIC_MODE_AUTO_SPEED*/); drv_swic_enable_connect_irqs( pctl->port.num, 1); return RC_SPW_SUCCESS; } int apply_param_changes( swic_ctrl_t *pctl) { swic_set_t *pset = &pctl->set_new; u32 change_tx = 0; u32 change_rx = 0; u32 speed; int rc; /*gspw_ctrl_t *pspw; spw_set_t *pspws; int i, rc;*/ if( pctl->mode != SWIC_MODE_CONFIG) return -1; if( pset->dma_tx.qnt_desc != pctl->qnt_tx_desc) { pctl->qnt_tx_desc = pset->dma_tx.qnt_desc; ++change_tx; } if( pset->dma_tx.qnt_data != pctl->qnt_tx_data) { pctl->qnt_tx_data = pset->dma_tx.qnt_data; ++change_tx; } if( pset->dma_tx.sz_data_buf != pctl->sz_tx_data_buf) { pctl->sz_tx_data_buf = pset->dma_tx.sz_data_buf; ++change_tx; } if( pset->max_tx_pack_size != pctl->max_sz_tx_pack) pctl->max_sz_tx_pack = pset->max_tx_pack_size; if( change_tx) { dma_tx_chain_free( pctl); if( ((rc=dma_tx_chain_init( pctl)) != RC_SPW_SUCCESS) /*|| ((rc=gspw_cfg_ctrl_init_job_task( pctl)) != RC_SPW_SUCCESS)*/ ) { pctl->qnt_tx_desc = 0; pctl->qnt_tx_data = 0; pctl->sz_tx_data_buf = 0; return rc; } } if( pset->dma_rx.qnt_desc != pctl->qnt_rx_desc) { pctl->qnt_rx_desc = pset->dma_rx.qnt_desc; ++change_rx; } if( pset->dma_rx.qnt_data != pctl->qnt_rx_data) { pctl->qnt_rx_data = pset->dma_rx.qnt_data; ++change_rx; } if( pset->dma_rx.sz_data_buf != pctl->sz_rx_data_buf) { pctl->sz_rx_data_buf = pset->dma_rx.sz_data_buf; ++change_rx; } if( change_rx) { dma_rx_chain_free( pctl); if( (rc=dma_rx_chain_init( pctl)) != RC_SPW_SUCCESS ) { pctl->qnt_rx_desc = 0; pctl->qnt_rx_data = 0; pctl->sz_rx_data_buf = 0; return rc; } } if( pset->max_send_desc_qnt != pctl->max_send_desc_qnt) pctl->max_send_desc_qnt = pset->max_send_desc_qnt; speed = ((SWIC_TX_SPEED_REG(pctl->port.num) >> SWIC_TX_SPEED_COEF_OFS) & SWIC_TX_SPEED_COEF_MSK) * 5; if( (pctl->speed != pset->tx_speed) || (speed != pset->tx_speed)) { if( swic_set_tx_speed( pctl->port.num, pset->tx_speed) >= 0) pctl->speed = pset->tx_speed; } return RC_SPW_SUCCESS; } // // Функция-обработчик команд пользователя ioctl // long drv_swic_ioctl( struct file *file, unsigned int cmd, unsigned long arg) { const char *drv_name = SWIC_DEV_NAME; int ret = RC_SPW_SUCCESS; unsigned int dev_num = iminor( file->f_dentry->d_inode); //-[0,1] unsigned spw_port = dev_num; //-[0,1] swic_ctrl_t *pctl; swic_set_t *pset; //u32 addr=0; u32 val; //pr_info("drv_gspw_ioctl: chan_num=%u cmd=%Xh\n", dev_num, cmd); if( dev_num >= SWIC_DRV_PORT_QNT) return -ENXIO; if( (dev_num != PORT_SWIC0) && (dev_num != PORT_SWIC1)) { PRINT( "drv_swic_ioctl: Ioctl from unsupportable port=%d\n", dev_num); return -ENODEV; } pctl = &swic.a_ctrl[spw_port]; pset = &pctl->set_new; // common commands: switch (cmd) { // Actions: // GETs: // Получение значения регистра по адресу: case SWIC_GET_REG_VAL: { u32 addr=0; //addr = *((u32 *)arg); GET_USER( SWIC_GET_REG_VAL, addr, arg, __u32) //pr_info( "drv_gspw_ioctl: SWIC_GET_REG_VAL: addr=%Xh\n", addr); //*((u32 *)arg) = XPCIe_Get( addr); //reg = XPCIe_Get( addr); COMPL_ADDR( addr) PUT_USER( SWIC_GET_REG_VAL, GET_REG( addr), arg, __u32) //pr_info( "drv_gspw_ioctl: GET_REG_VAL: val=%Xh\n", GET_REG( addr)); return ret; } // SETs: // Установка значения регистра по адресу: case SWIC_SET_REG_VAL: { /*struct s_reg_val *p_rv = (struct s_reg_val *)arg; #ifndef USE_FREE_USER_MEM_ACCESS struct s_reg_val rv; #endif //- !USE_FREE_USER_MEM_ACCESS*/ struct s_reg_val_ext *p_rv = (struct s_reg_val_ext *)arg; #ifndef USE_FREE_USER_MEM_ACCESS struct s_reg_val_ext rv; #endif //- !USE_FREE_USER_MEM_ACCESS if( p_rv==NULL) return -EINVAL; SET_PNTR( p_rv, rv) COPY_FROM_USER( SWIC_SET_REG_VAL, p_rv, (void *)arg, sizeof(*p_rv)) if( p_rv) { COMPL_ADDR( p_rv->addr) if( (p_rv->msk != VAL_MSK_DFLT) || (p_rv->ofs != VAL_OFS_DFLT)) { val = GET_REG( p_rv->addr); val &= ~(p_rv->msk << p_rv->ofs); val |= ((p_rv->val & p_rv->msk) << p_rv->ofs); p_rv->val = val; } SET_REG( p_rv->addr, p_rv->val); //pr_info( "drv_gspw_ioctl: SWIC_SET_REG_VAL: addr=%.8Xh, val=%.8Xh (%.8Xh)\n", // p_rv->addr, p_rv->val, GET_REG( p_rv->addr)); //pr_info( "drv_gspw_ioctl: SWIC_SET_REG_VAL: addr=%.8Xh, val=%.8Xh (%.8Xh) msk=%Xh ofs=%u\n", // p_rv->addr, p_rv->val, GET_REG(p_rv->addr), p_rv->msk, p_rv->ofs); //COPY_TO_USER( SWIC_SET_REG_VAL, (void *)arg, p_rv, sizeof(*p_rv)) } return ret; } } // interface commands: switch (cmd) { // Actions: case SWIC_IO_START: //gspw_sw.mode_msk |= (1 << dev_num); ret = set_work_mode( pctl); break; case SWIC_IO_STOP: //gspw_sw.mode_msk &= ~(1 << dev_num); ret = set_configure_mode( pctl); break; case SWIC_IO_APPLY_CHANGES: if( pctl->mode != SWIC_MODE_CONFIG) { pr_info( "drv_swic_ioctl(%i): mode=%u\n", dev_num, pctl->mode); return -ECANCELED; } apply_param_changes( pctl); break; case SWIC_IO_RESET_TX_RX: swic_reset_tx_rx( pctl); break; // Сброс статистики: case SWIC_IO_RESET_STAT: pctl->rx_eop = 0; pctl->rx_eep = 0; pctl->rx_bytes = 0; pctl->rx_drop_pack = 0; pctl->rx_drop_bytes = 0; pctl->tx_packets = 0; pctl->tx_bytes = 0; //pctl->txdma_waits = 0; break; // print debug statistic: case SWIC_IO_PRINT_DBG_STAT: swic_print_dbg_stat( pctl); break; /*#ifdef USE_DMA_TEST case SWIC_IO_INERN_DMA_TEST: if( arg==IOCTL_ARG__INERN_DMA_TEST_PRINT) { pctl->test.tm_end = get_time_of_day(); gspw_dma_internal_test_print( &pctl->test); } else if( arg==IOCTL_ARG__INERN_DMA_TEST_START) gspw_dma_internal_test_start( pctl); else if( arg==IOCTL_ARG__INERN_DMA_TEST_STOP) gspw_dma_internal_test_stop( pctl); break; #endif //USE_DMA_TEST */ case SWIC_IO_MEM_TEST: swic_mem_test( pctl); break; // GETs: // Получение текущего режима работы: case SWIC_GET_MODE: PUT_USER( SWIC_GET_MODE, pctl->mode, arg, __u32) break; // Получение количества TX DMA дескрипторов: case SWIC_GET_DMA_TX_DESC_QNT: PUT_USER( SWIC_GET_DMA_TX_DESC_QNT, pctl->qnt_tx_desc, arg, __u32) break; // Получение количества TX DMA буферов данных: case SWIC_GET_DMA_TX_DATA_QNT: PUT_USER( SWIC_GET_DMA_TX_DATA_QNT, pctl->qnt_tx_data, arg, __u32) break; // Получение размера TX DMA буфера данных: case SWIC_GET_DMA_TX_DATA_BUF_SIZE: PUT_USER( SWIC_GET_DMA_TX_DATA_BUF_SIZE, pctl->sz_tx_data_buf, arg, __u32) break; // Получение максимального размера TX пакета данных: case SWIC_GET_DMA_TX_PACK_SIZE: PUT_USER( SWIC_GET_DMA_TX_PACK_SIZE, pctl->max_sz_tx_pack, arg, __u32) break; // Получение количества RX DMA дескрипторов: case SWIC_GET_DMA_RX_DESC_QNT: PUT_USER( SWIC_GET_DMA_RX_DESC_QNT, pctl->qnt_rx_desc, arg, __u32) break; // Получение количества RX DMA буферов данных: case SWIC_GET_DMA_RX_DATA_QNT: PUT_USER( SWIC_GET_DMA_RX_DATA_QNT, pctl->qnt_rx_data, arg, __u32) break; // Получение размера RX DMA буфера данных: case SWIC_GET_DMA_RX_DATA_BUF_SIZE: PUT_USER( SWIC_GET_DMA_RX_DATA_BUF_SIZE, pctl->sz_rx_data_buf, arg, __u32) break; // Settings (еще неустановленные параметры): // Получение количества TX DMA дескрипторов: case SWIC_GET_DMA_TX_DESC_QNT_NEW: PUT_USER( SWIC_GET_DMA_TX_DESC_QNT, pset->dma_tx.qnt_desc, arg, __u32) break; // Получение количества TX DMA буферов данных: case SWIC_GET_DMA_TX_DATA_QNT_NEW: PUT_USER( SWIC_GET_DMA_TX_DATA_QNT, pset->dma_tx.qnt_data, arg, __u32) break; // Получение размера TX DMA буфера данных: case SWIC_GET_DMA_TX_DATA_BUF_SIZE_NEW: PUT_USER( SWIC_GET_DMA_TX_DATA_BUF_SIZE, pset->dma_tx.sz_data_buf, arg, __u32) break; // Получение максимального размера TX пакета данных: case SWIC_GET_DMA_TX_PACK_SIZE_NEW: PUT_USER( SWIC_GET_DMA_TX_PACK_SIZE, pset->max_tx_pack_size, arg, __u32) break; // Получение количества RX DMA дескрипторов: case SWIC_GET_DMA_RX_DESC_QNT_NEW: PUT_USER( SWIC_GET_DMA_RX_DESC_QNT, pset->dma_rx.qnt_desc, arg, __u32) break; // Получение количества RX DMA буферов данных: case SWIC_GET_DMA_RX_DATA_QNT_NEW: PUT_USER( SWIC_GET_DMA_RX_DATA_QNT, pset->dma_rx.qnt_data, arg, __u32) break; // Получение размера RX DMA буфера данных: case SWIC_GET_DMA_RX_DATA_BUF_SIZE_NEW: PUT_USER( SWIC_GET_DMA_RX_DATA_BUF_SIZE, pset->dma_rx.sz_data_buf, arg, __u32) break; // Statistics: // Получение количества успешно принятых пакетов (EOP): case SWIC_GET_STAT_RX_EOP: PUT_USER( SWIC_GET_STAT_RX_EOP, pctl->rx_eop, arg, __u32) break; // Получение количества принятых пакетов с ошибкой (EEP): case SWIC_GET_STAT_RX_EEP: PUT_USER( SWIC_GET_STAT_RX_EEP, pctl->rx_eep, arg, __u32) break; // Получение количества принятых байт: case SWIC_GET_STAT_RX_BYTES: PUT_USER( SWIC_GET_STAT_RX_BYTES, pctl->rx_bytes, arg, __u32) break; // Получение количества переданных пакетов: case SWIC_GET_STAT_TX_PACKETS: PUT_USER( SWIC_GET_STAT_TX_PACKETS, pctl->tx_packets, arg, __u32) break; // Получение количества переданных байт: case SWIC_GET_STAT_TX_BYTES: PUT_USER( SWIC_GET_STAT_TX_BYTES, pctl->tx_bytes, arg, __u32) break; // Получение количества ожиданий освобождения DMA передачи: /*case SWIC_GET_STAT_TX_DMA_WAITS: PUT_USER( SWIC_GET_STAT_TX_DMA_WAITS, pctl->txdma_waits, arg, __u32) break;*/ // Получение значений RX DMA descriptor регистров: case SWIC_GET_DMA_DESC_RX: { dma_params_t *pdma = (dma_params_t *)arg; #ifndef USE_FREE_USER_MEM_ACCESS dma_params_t dma; #endif //- !USE_FREE_USER_MEM_ACCESS if( pdma==NULL) return EINVAL; SET_PNTR( pdma, dma) val = MC_SWIC_RX_DESC_RUN( spw_port); COPY_TO_USER( SWIC_GET_DMA_DESC_RX, &((dma_params_t *)arg)->run, &val, 4) val = MC_SWIC_RX_DESC_IR( spw_port); COPY_TO_USER( SWIC_GET_DMA_DESC_RX, &((dma_params_t *)arg)->ir, &val, 4) val = MC_SWIC_RX_DESC_CP( spw_port); COPY_TO_USER( SWIC_GET_DMA_DESC_RX, &((dma_params_t *)arg)->cp, &val, 4) break; } // Получение значений RX DMA data регистров: case SWIC_GET_DMA_DATA_RX: { dma_params_t *pdma = (dma_params_t *)arg; #ifndef USE_FREE_USER_MEM_ACCESS dma_params_t dma; #endif //- !USE_FREE_USER_MEM_ACCESS if( pdma==NULL) return EINVAL; SET_PNTR( pdma, dma) val = MC_SWIC_RX_DATA_RUN( spw_port); COPY_TO_USER( SWIC_GET_DMA_DATA_RX, &((dma_params_t *)arg)->run, &val, 4) val = MC_SWIC_RX_DATA_IR( spw_port); COPY_TO_USER( SWIC_GET_DMA_DATA_RX, &((dma_params_t *)arg)->ir, &val, 4) val = MC_SWIC_RX_DATA_CP( spw_port); COPY_TO_USER( SWIC_GET_DMA_DATA_RX, &((dma_params_t *)arg)->cp, &val, 4) break; } // Получение значений TX DMA descriptor регистров: case SWIC_GET_DMA_DESC_TX: { dma_params_t *pdma = (dma_params_t *)arg; #ifndef USE_FREE_USER_MEM_ACCESS dma_params_t dma; #endif //- !USE_FREE_USER_MEM_ACCESS if( pdma==NULL) return EINVAL; SET_PNTR( pdma, dma) val = MC_SWIC_TX_DESC_RUN( spw_port); COPY_TO_USER( SWIC_GET_DMA_DESC_TX, &((dma_params_t *)arg)->run, &val, 4) val = MC_SWIC_TX_DESC_IR( spw_port); COPY_TO_USER( SWIC_GET_DMA_DESC_TX, &((dma_params_t *)arg)->ir, &val, 4) val = MC_SWIC_TX_DESC_CP( spw_port); COPY_TO_USER( SWIC_GET_DMA_DESC_TX, &((dma_params_t *)arg)->cp, &val, 4) break; } // Получение значений TX DMA data регистров: case SWIC_GET_DMA_DATA_TX: { dma_params_t *pdma = (dma_params_t *)arg; #ifndef USE_FREE_USER_MEM_ACCESS dma_params_t dma; #endif //- !USE_FREE_USER_MEM_ACCESS if( pdma==NULL) return EINVAL; SET_PNTR( pdma, dma) val = MC_SWIC_TX_DATA_RUN( spw_port); COPY_TO_USER( SWIC_GET_DMA_DATA_TX, &((dma_params_t *)arg)->run, &val, 4) val = MC_SWIC_TX_DATA_IR( spw_port); COPY_TO_USER( SWIC_GET_DMA_DATA_TX, &((dma_params_t *)arg)->ir, &val, 4) val = MC_SWIC_TX_DATA_CP( spw_port); COPY_TO_USER( SWIC_GET_DMA_DATA_TX, &((dma_params_t *)arg)->cp, &val, 4) break; } // SETs: // Settings: // Установка количества TX DMA дескрипторов: case SWIC_SET_DMA_TX_DESC_QNT: //GET_USER( SWIC_SET_DMA_TX_DESC_QNT, pset->tx.dma.qnt_desc, arg, __u32) pset->dma_tx.qnt_desc = (u32 )arg; break; // Установка количества TX DMA буферов данных: case SWIC_SET_DMA_TX_DATA_QNT: //GET_USER( SWIC_SET_DMA_TX_DATA_QNT, pset->tx.dma.qnt_data, arg, __u32) pset->dma_tx.qnt_data = (u32 )arg; break; // Установка размера TX DMA буфера данных: case SWIC_SET_DMA_TX_DATA_BUF_SIZE: //GET_USER( SWIC_SET_DMA_TX_DATA_BUF_SIZE, pset->tx.dma.sz_data_buf, arg, __u32) pset->dma_tx.sz_data_buf = (u32 )arg; break; // Установка максимального размера TX пакета данных: case SWIC_SET_DMA_TX_PACK_SIZE: //GET_USER( SWIC_SET_DMA_TX_PACK_SIZE, pset->tx.max_sz_pack, arg, __u32) pset->max_tx_pack_size = (u32 )arg; break; // Установка количества RX DMA дескрипторов: case SWIC_SET_DMA_RX_DESC_QNT: //GET_USER( SWIC_SET_DMA_RX_DESC_QNT, pset->rx.dma.qnt_desc, arg, __u32) pset->dma_rx.qnt_desc = (u32 )arg; break; // Установка количества RX DMA буферов данных: case SWIC_SET_DMA_RX_DATA_QNT: //GET_USER( SWIC_SET_DMA_RX_DATA_QNT, pset->rx.dma.qnt_data, arg, __u32) pset->dma_rx.qnt_data = (u32 )arg; break; // Установка размера RX DMA буфера данных: case SWIC_SET_DMA_RX_DATA_BUF_SIZE: //T_USER( SWIC_SET_DMA_RX_DATA_BUF_SIZE, pset->rx.dma.sz_data_buf, arg, __u32) pset->dma_rx.sz_data_buf = (u32 )arg; break; // GETs: // Получение значения скорости приема: case SWIC_GET_RX_SPEED: //freq_mult_mhz = mc_frequency_multiplier() * MC_QUARTZ_CLOCK_FREQ; //val = ((MC_SWIC_SPW_RX_SPEED(spw_port) * freq_mult_mhz / 1000000) >> 7); val = SWIC_RX_SPEED_REG( spw_port); PUT_USER( SWIC_GET_RX_SPEED, val, arg, __u32) break; // Получение значения скорости передачи: case SWIC_GET_TX_SPEED: val = ((SWIC_TX_SPEED_REG(spw_port) >> SWIC_TX_SPEED_COEF_OFS) & SWIC_TX_SPEED_COEF_MSK) * 5; PUT_USER( SWIC_GET_TX_SPEED, val, arg, __u32) break; // Получение максимального количества дескрипторов на отправку (по данному порту): case SWIC_GET_MAX_SEND_DESC_QNT: PUT_USER( SWIC_GET_MAX_SEND_DESC_QNT, pctl->max_send_desc_qnt, arg, __u32) break; // GET new: // Получение значения новой скорости передачи: case SWIC_GET_TX_SPEED_NEW: PUT_USER( SWIC_GET_TX_SPEED_NEW, pset->tx_speed, arg, __u32) break; // Получение максимального количества дескрипторов на отправку (по данному порту): case SWIC_GET_MAX_SEND_DESC_QNT_NEW: PUT_USER( SWIC_GET_MAX_SEND_DESC_QNT_NEW, pset->max_send_desc_qnt, arg, __u32) break; // SETs: // Установка максимального количества дескрипторов на отправку (по данному порту): case SWIC_SET_MAX_SEND_DESC_QNT: pset->max_send_desc_qnt = (u32 )arg; //GET_USER( SWIC_GET_MAX_SEND_DESC_QNT, pset->a_spw[spw_port].max_send_desc_qnt, arg, __u32) break; // Установка значения скорости передачи: case SWIC_SET_TX_SPEED: if( arg < 5 || arg > 400) return (-EINVAL); pset->tx_speed = (u32 )arg; //pgsc->speed = arg; //swic_set_tx_speed( spw_port, arg); break; default: ret = -EINVAL; break; } return ret; }