?? s2io.c
字號:
tmp_v_addr, tmp_p_addr); } } if (mac_control->stats_mem) { pci_free_consistent(nic->pdev, mac_control->stats_mem_sz, mac_control->stats_mem, mac_control->stats_mem_phy); }}/* * Input Arguments: * device peivate variable * Return Value: * SUCCESS on success and '-1' on failure (endian settings incorrect). * Description: * The function sequentially configures every block * of the H/W from their reset values. */static int initNic(struct s2io_nic *nic){ XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; struct net_device *dev = nic->dev; register u64 val64 = 0; void *add; u32 time; int i, j; mac_info_t *mac_control; struct config_param *config; int mdio_cnt = 0, dtx_cnt = 0; unsigned long long print_var, mem_share; mac_control = &nic->mac_control; config = &nic->config; /* Set proper endian settings and verify the same by * reading the PIF Feed-back register. */#ifdef __BIG_ENDIAN /* The device by default set to a big endian format, so * a big endian driver need not set anything. */ writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl); val64 = (SWAPPER_CTRL_PIF_R_FE | SWAPPER_CTRL_PIF_R_SE | SWAPPER_CTRL_PIF_W_FE | SWAPPER_CTRL_PIF_W_SE | SWAPPER_CTRL_TXP_FE | SWAPPER_CTRL_TXP_SE | SWAPPER_CTRL_TXD_R_FE | SWAPPER_CTRL_TXD_W_FE | SWAPPER_CTRL_TXF_R_FE | SWAPPER_CTRL_RXD_R_FE | SWAPPER_CTRL_RXD_W_FE | SWAPPER_CTRL_RXF_W_FE | SWAPPER_CTRL_XMSI_FE | SWAPPER_CTRL_XMSI_SE | SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE); writeq(val64, &bar0->swapper_ctrl);#else /* Initially we enable all bits to make it accessible by * the driver, then we selectively enable only those bits * that we want to set. */ writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl); val64 = (SWAPPER_CTRL_PIF_R_FE | SWAPPER_CTRL_PIF_R_SE | SWAPPER_CTRL_PIF_W_FE | SWAPPER_CTRL_PIF_W_SE | SWAPPER_CTRL_TXP_FE | SWAPPER_CTRL_TXP_SE | SWAPPER_CTRL_TXD_R_FE | SWAPPER_CTRL_TXD_R_SE | SWAPPER_CTRL_TXD_W_FE | SWAPPER_CTRL_TXD_W_SE | SWAPPER_CTRL_TXF_R_FE | SWAPPER_CTRL_RXD_R_FE | SWAPPER_CTRL_RXD_R_SE | SWAPPER_CTRL_RXD_W_FE | SWAPPER_CTRL_RXD_W_SE | SWAPPER_CTRL_RXF_W_FE | SWAPPER_CTRL_XMSI_FE | SWAPPER_CTRL_XMSI_SE | SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE); writeq(val64, &bar0->swapper_ctrl);#endif /* Verifying if endian settings are accurate by reading * a feedback register. */ val64 = readq(&bar0->pif_rd_swapper_fb); if (val64 != 0x0123456789ABCDEFULL) { /* Endian settings are incorrect, calls for another dekko. */ print_var = (unsigned long long) val64; DBG_PRINT(INIT_DBG, "%s: Endian settings are wrong", dev->name); DBG_PRINT(ERR_DBG, ", feedback read %llx\n", print_var); return FAILURE; } /* Remove XGXS from reset state */ val64 = 0; writeq(val64, &bar0->sw_reset); val64 = readq(&bar0->sw_reset); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ / 2); /* Enable Receiving broadcasts */ val64 = readq(&bar0->mac_cfg); val64 |= MAC_RMAC_BCAST_ENABLE; writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); writeq(val64, &bar0->mac_cfg); /* Read registers in all blocks */ val64 = readq(&bar0->mac_int_mask); val64 = readq(&bar0->mc_int_mask); val64 = readq(&bar0->xgxs_int_mask); /* Set MTU */ val64 = dev->mtu; writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); /* Configuring the XAUI Interface of Xena. ***************************************** * To Configure the Xena's XAUI, one has to write a series * of 64 bit values into two registers in a particular * sequence. Hence a macro 'SWITCH_SIGN' has been defined * which will be defined in the array of configuration values * (default_dtx_cfg & default_mdio_cfg) at appropriate places * to switch writing from one regsiter to another. We continue * writing these values until we encounter the 'END_SIGN' macro. * For example, After making a series of 21 writes into * dtx_control register the 'SWITCH_SIGN' appears and hence we * start writing into mdio_control until we encounter END_SIGN. */ while (1) { dtx_cfg: while (default_dtx_cfg[dtx_cnt] != END_SIGN) { if (default_dtx_cfg[dtx_cnt] == SWITCH_SIGN) { dtx_cnt++; goto mdio_cfg; } writeq(default_dtx_cfg[dtx_cnt], &bar0->dtx_control); val64 = readq(&bar0->dtx_control); dtx_cnt++; } mdio_cfg: while (default_mdio_cfg[mdio_cnt] != END_SIGN) { if (default_mdio_cfg[mdio_cnt] == SWITCH_SIGN) { mdio_cnt++; goto dtx_cfg; } writeq(default_mdio_cfg[mdio_cnt], &bar0->mdio_control); val64 = readq(&bar0->mdio_control); mdio_cnt++; } if ((default_dtx_cfg[dtx_cnt] == END_SIGN) && (default_mdio_cfg[mdio_cnt] == END_SIGN)) { break; } else { goto dtx_cfg; } } /* Tx DMA Initialization */ val64 = 0; writeq(val64, &bar0->tx_fifo_partition_0); writeq(val64, &bar0->tx_fifo_partition_1); writeq(val64, &bar0->tx_fifo_partition_2); writeq(val64, &bar0->tx_fifo_partition_3); for (i = 0, j = 0; i < config->TxFIFONum; i++) { val64 |= vBIT(config->TxCfg[i].FifoLen - 1, ((i * 32) + 19), 13) | vBIT(config->TxCfg[i].FifoPriority, ((i * 32) + 5), 3); if (i == (config->TxFIFONum - 1)) { if (i % 2 == 0) i++; } switch (i) { case 1: writeq(val64, &bar0->tx_fifo_partition_0); val64 = 0; break; case 3: writeq(val64, &bar0->tx_fifo_partition_1); val64 = 0; break; case 5: writeq(val64, &bar0->tx_fifo_partition_2); val64 = 0; break; case 7: writeq(val64, &bar0->tx_fifo_partition_3); break; } } /* Enable Tx FIFO partition 0. */ val64 = readq(&bar0->tx_fifo_partition_0); val64 |= BIT(0); /* To enable the FIFO partition. */ writeq(val64, &bar0->tx_fifo_partition_0); val64 = readq(&bar0->tx_fifo_partition_0); DBG_PRINT(INIT_DBG, "Fifo partition at: 0x%p is: 0x%llx\n", &bar0->tx_fifo_partition_0, (unsigned long long) val64); /* * Initialization of Tx_PA_CONFIG register to ignore packet * integrity checking. */ val64 = readq(&bar0->tx_pa_cfg); val64 |= TX_PA_CFG_IGNORE_FRM_ERR | TX_PA_CFG_IGNORE_SNAP_OUI | TX_PA_CFG_IGNORE_LLC_CTRL | TX_PA_CFG_IGNORE_L2_ERR; writeq(val64, &bar0->tx_pa_cfg); /* Rx DMA intialization. */ val64 = 0; for (i = 0; i < config->RxRingNum; i++) { val64 |= vBIT(config->RxCfg[i].RingPriority, (5 + (i * 8)), 3); } writeq(val64, &bar0->rx_queue_priority); /* Allocating equal share of memory to all the configured * Rings. */ val64 = 0; for (i = 0; i < config->RxRingNum; i++) { switch (i) { case 0: mem_share = (64 / config->RxRingNum + 64 % config->RxRingNum); val64 |= RX_QUEUE_CFG_Q0_SZ(mem_share); continue; case 1: mem_share = (64 / config->RxRingNum); val64 |= RX_QUEUE_CFG_Q1_SZ(mem_share); continue; case 2: mem_share = (64 / config->RxRingNum); val64 |= RX_QUEUE_CFG_Q2_SZ(mem_share); continue; case 3: mem_share = (64 / config->RxRingNum); val64 |= RX_QUEUE_CFG_Q3_SZ(mem_share); continue; case 4: mem_share = (64 / config->RxRingNum); val64 |= RX_QUEUE_CFG_Q4_SZ(mem_share); continue; case 5: mem_share = (64 / config->RxRingNum); val64 |= RX_QUEUE_CFG_Q5_SZ(mem_share); continue; case 6: mem_share = (64 / config->RxRingNum); val64 |= RX_QUEUE_CFG_Q6_SZ(mem_share); continue; case 7: mem_share = (64 / config->RxRingNum); val64 |= RX_QUEUE_CFG_Q7_SZ(mem_share); continue; } } writeq(val64, &bar0->rx_queue_cfg); /* Initializing the Tx round robin registers to 0. * Filling Tx and Rx round robin registers as per the * number of FIFOs and Rings is still TODO. */ writeq(0, &bar0->tx_w_round_robin_0); writeq(0, &bar0->tx_w_round_robin_1); writeq(0, &bar0->tx_w_round_robin_2); writeq(0, &bar0->tx_w_round_robin_3); writeq(0, &bar0->tx_w_round_robin_4); /* Disable Rx steering. Hard coding all packets be steered to * Queue 0 for now. * TODO*/ if (rx_prio) { u64 def = 0x8000000000000000ULL, tmp; for (i = 0; i < MAX_RX_RINGS; i++) { tmp = (u64) (def >> (i % config->RxRingNum)); val64 |= (u64) (tmp >> (i * 8)); } writeq(val64, &bar0->rts_qos_steering); } else { val64 = 0x8080808080808080ULL; writeq(val64, &bar0->rts_qos_steering); } /* UDP Fix */ val64 = 0; for (i = 1; i < 8; i++) writeq(val64, &bar0->rts_frm_len_n[i]); /* Set rts_frm_len register for fifo 0 */ writeq(MAC_RTS_FRM_LEN_SET(dev->mtu + 22), &bar0->rts_frm_len_n[0]); /* Enable statistics */ writeq(mac_control->stats_mem_phy, &bar0->stat_addr); val64 = SET_UPDT_PERIOD(8) | STAT_CFG_STAT_RO | STAT_CFG_STAT_EN; writeq(val64, &bar0->stat_cfg); /* Initializing the sampling rate for the device to calculate the * bandwidth utilization. */ val64 = MAC_TX_LINK_UTIL_VAL(0x5) | MAC_RX_LINK_UTIL_VAL(0x5); writeq(val64, &bar0->mac_link_util); /* Initializing the Transmit and Receive Traffic Interrupt * Scheme. */ /* TTI Initialization */ val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0xFFF) | TTI_DATA1_MEM_TX_URNG_A(0xA) | TTI_DATA1_MEM_TX_URNG_B(0x10) | TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN; writeq(val64, &bar0->tti_data1_mem); val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | TTI_DATA2_MEM_TX_UFC_B(0x20) | TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80); writeq(val64, &bar0->tti_data2_mem); val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD; writeq(val64, &bar0->tti_command_mem); /* Once the operation completes, the Strobe bit of the command * register will be reset. We poll for this particular condition * We wait for a maximum of 500ms for the operation to complete, * if it's not complete by then we return error. */ time = 0; while (TRUE) { val64 = readq(&bar0->tti_command_mem); if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) { break; } if (time > 10) { DBG_PRINT(ERR_DBG, "%s: TTI init Failed\n", dev->name); return -1; } set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ / 20); time++; } /* RTI Initialization */ val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF) | RTI_DATA1_MEM_RX_URNG_A(0xA) | RTI_DATA1_MEM_RX_URNG_B(0x10) | RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN; writeq(val64, &bar0->rti_data1_mem); val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) | RTI_DATA2_MEM_RX_UFC_B(0x2) | RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80); writeq(val64, &bar0->rti_data2_mem); val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD; writeq(val64, &bar0->rti_command_mem); /* Once the operation completes, the Strobe bit of the command * register will be reset. We poll for this particular condition * We wait for a maximum of 500ms for the operation to complete, * if it's not complete by then we return error. */ time = 0; while (TRUE) { val64 = readq(&bar0->rti_command_mem); if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) { break; } if (time > 10) { DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n", dev->name); return -1; } time++; set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ / 20); } /* Initializing proper values as Pause threshold into all * the 8 Queues on Rx side. */ writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q0q3); writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q4q7); /* Disable RMAC PAD STRIPPING */ add = (void *) &bar0->mac_cfg; val64 = readq(&bar0->mac_cfg); val64 &= ~(MAC_CFG_RMAC_STRIP_PAD); writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); writel((u32) (val64), add); writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); writel((u32) (val64 >> 32), (add + 4)); val64 = readq(&bar0->mac_cfg); return SUCCESS;}/* * Input Arguments: * device private variable, * A mask indicating which Intr block must be modified and, * A flag indicating whether to enable or disable the Intrs. * Return Value: * NONE. * Description: * This function will either disable or enable the interrupts * depending on the flag argument. The mask argument can be used to * enable/disable any Intr block. */static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag){ XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; register u64 val64 = 0, temp64 = 0; /* Top level interrupt classification */ /* PIC Interrupts */ if ((mask & (TX_PIC_INTR | RX_PIC_INTR))) { /* Enable PIC Intrs in the general intr mask register */ val64 = TXPIC_INT_M | PIC_RX_INT_M; if (flag == ENABLE_INTRS) { temp64 = readq(&bar0->general_int_mask); temp64 &= ~((u64) val64); writeq(temp64, &bar0->general_int_mask); /* Disabled all PCIX, Flash, MDIO, IIC and GPIO * interrupts for now. * TODO */ writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask); /* No MSI Support is available presently, so TTI and * RTI interrupts are also disabled. */ } else if (flag == DISABLE_INTRS) { /* Disable PIC Intrs in the general intr mask register */ writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -