// // Description: // This routine deal with the Power Configuration CMDs parsing for RTL8723/RTL8188E Series IC. // // Assumption: // We should follow specific format which was released from HW SD. // // 2011.07.07, added by Roger. // unsigned int HalPwrSeqCmdParsing(struct rtl8192cd_priv *priv, unsigned char CutVersion, unsigned char FabVersion, unsigned char InterfaceType, WLAN_PWR_CFG PwrSeqCmd[]) { WLAN_PWR_CFG PwrCfgCmd = {0}; unsigned int bPollingBit = FALSE; unsigned int AryIdx=0; unsigned char value = 0; unsigned int offset = 0; unsigned int pollingCount = 0; // polling autoload done. unsigned int maxPollingCnt = 5000; do { PwrCfgCmd=PwrSeqCmd[AryIdx]; DEBUG_INFO("%s %d, ENTRY, offset:0x%x, cut_msk:0x%x, fab_msk:0x%x, if_msk:0x%x, base:0x%x, cmd:0x%x, msk:0x%x, value:0x%x\n", __FUNCTION__, __LINE__, GET_PWR_CFG_OFFSET(PwrCfgCmd), GET_PWR_CFG_CUT_MASK(PwrCfgCmd), GET_PWR_CFG_FAB_MASK(PwrCfgCmd), GET_PWR_CFG_INTF_MASK(PwrCfgCmd), GET_PWR_CFG_BASE(PwrCfgCmd), GET_PWR_CFG_CMD(PwrCfgCmd), GET_PWR_CFG_MASK(PwrCfgCmd), GET_PWR_CFG_VALUE(PwrCfgCmd)); //2 Only Handle the command whose FAB, CUT, and Interface are matched if((GET_PWR_CFG_FAB_MASK(PwrCfgCmd)&FabVersion)&& (GET_PWR_CFG_CUT_MASK(PwrCfgCmd)&CutVersion)&& (GET_PWR_CFG_INTF_MASK(PwrCfgCmd)&InterfaceType)) { switch(GET_PWR_CFG_CMD(PwrCfgCmd)) { case PWR_CMD_READ: DEBUG_INFO("%s %d, PWR_CMD_READ\n", __FUNCTION__, __LINE__); break; case PWR_CMD_WRITE: DEBUG_INFO("%s %d, PWR_CMD_WRITE\n", __FUNCTION__, __LINE__); offset = GET_PWR_CFG_OFFSET(PwrCfgCmd); #ifdef CONFIG_SDIO_HCI // // <Roger_Notes> We should deal with interface specific address mapping for some interfaces, e.g., SDIO interface // 2011.07.07. // if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO) { // Read Back SDIO Local value value = SdioLocalCmd52Read1Byte(priv, offset); value &= ~(GET_PWR_CFG_MASK(PwrCfgCmd)); value |= (GET_PWR_CFG_VALUE(PwrCfgCmd) & GET_PWR_CFG_MASK(PwrCfgCmd)); // Write Back SDIO Local value SdioLocalCmd52Write1Byte(priv, offset, value); } else #endif { //Read the value from system register value = RTL_R8(offset); value = value&(~(GET_PWR_CFG_MASK(PwrCfgCmd))); value = value|(GET_PWR_CFG_VALUE(PwrCfgCmd)&GET_PWR_CFG_MASK(PwrCfgCmd)); //Write the value back to sytem register RTL_W8(offset, value); } break; case PWR_CMD_POLLING: DEBUG_INFO("%s %d, PWR_CMD_POLLING\n", __FUNCTION__, __LINE__); bPollingBit = FALSE; offset = GET_PWR_CFG_OFFSET(PwrCfgCmd); do { #ifdef CONFIG_SDIO_HCI if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO) value = SdioLocalCmd52Read1Byte(priv, offset); else #endif value = RTL_R8(offset); value=value&GET_PWR_CFG_MASK(PwrCfgCmd); if(value==(GET_PWR_CFG_VALUE(PwrCfgCmd)&GET_PWR_CFG_MASK(PwrCfgCmd))) bPollingBit=TRUE; else delay_us(10); if(pollingCount++ > maxPollingCnt){ DEBUG_WARN("%s %d, PWR_CMD_POLLING, Fail to polling Offset[0x%x]\n", __FUNCTION__, __LINE__, offset); return FALSE; } }while(!bPollingBit); break; case PWR_CMD_DELAY: DEBUG_INFO("%s %d, PWR_CMD_DELAY\n", __FUNCTION__, __LINE__); if(GET_PWR_CFG_VALUE(PwrCfgCmd) == PWRSEQ_DELAY_US) delay_us(GET_PWR_CFG_OFFSET(PwrCfgCmd)); else delay_us(GET_PWR_CFG_OFFSET(PwrCfgCmd)*1000); break; case PWR_CMD_END: // When this command is parsed, end the process DEBUG_INFO("%s %d, PWR_CMD_END\n", __FUNCTION__, __LINE__); return TRUE; break; default: DEBUG_ERR("%s %d, Unknown CMD!!\n", __FUNCTION__, __LINE__); break; } } AryIdx++;//Add Array Index }while(1); return TRUE; }
/************************************************************************** SEND - Transmit a frame ***************************************************************************/ static int rtl_send(struct eth_device *dev, void *packet, int length) { /* send the packet to destination */ u32 to; u8 *ptxb; int entry = tpc->cur_tx % NUM_TX_DESC; u32 len = length; int ret; #ifdef DEBUG_RTL8169_TX int stime = currticks(); printf ("%s\n", __FUNCTION__); printf("sending %d bytes\n", len); #endif ioaddr = dev->iobase; /* point to the current txb incase multiple tx_rings are used */ ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE]; memcpy(ptxb, (char *)packet, (int)length); rtl_flush_buffer(ptxb, length); while (len < ETH_ZLEN) ptxb[len++] = '\0'; tpc->TxDescArray[entry].buf_Haddr = 0; tpc->TxDescArray[entry].buf_addr = cpu_to_le32(bus_to_phys(ptxb)); if (entry != (NUM_TX_DESC - 1)) { tpc->TxDescArray[entry].status = cpu_to_le32((OWNbit | FSbit | LSbit) | ((len > ETH_ZLEN) ? len : ETH_ZLEN)); } else { tpc->TxDescArray[entry].status = cpu_to_le32((OWNbit | EORbit | FSbit | LSbit) | ((len > ETH_ZLEN) ? len : ETH_ZLEN)); } rtl_flush_tx_desc(&tpc->TxDescArray[entry]); RTL_W8(TxPoll, 0x40); /* set polling bit */ tpc->cur_tx++; to = currticks() + TX_TIMEOUT; do { rtl_inval_tx_desc(&tpc->TxDescArray[entry]); } while ((le32_to_cpu(tpc->TxDescArray[entry].status) & OWNbit) && (currticks() < to)); /* wait */ if (currticks() >= to) { #ifdef DEBUG_RTL8169_TX puts("tx timeout/error\n"); printf("%s elapsed time : %lu\n", __func__, currticks()-stime); #endif ret = 0; } else { #ifdef DEBUG_RTL8169_TX puts("tx done\n"); #endif ret = length; } /* Delay to make net console (nc) work properly */ udelay(20); return ret; }
static void rtl8169_hw_start(struct eth_device *dev) { u32 i; #ifdef DEBUG_RTL8169 int stime = currticks(); printf ("%s\n", __FUNCTION__); #endif #if 0 /* Soft reset the chip. */ RTL_W8(ChipCmd, CmdReset); /* Check that the chip has finished the reset. */ for (i = 1000; i > 0; i--) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; else udelay(10); } #endif RTL_W8(Cfg9346, Cfg9346_Unlock); /* RTL-8169sb/8110sb or previous version */ if (tpc->chipset <= 5) RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); RTL_W8(EarlyTxThres, EarlyTxThld); /* For gigabit rtl8169 */ RTL_W16(RxMaxSize, RxPacketMaxSize); /* Set Rx Config register */ i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tpc->chipset].RxConfigMask); RTL_W32(RxConfig, i); /* Set DMA burst size and Interframe Gap Time */ RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | (InterFrameGap << TxInterFrameGapShift)); tpc->cur_rx = 0; RTL_W32(TxDescStartAddrLow, bus_to_phys(tpc->TxDescArray)); RTL_W32(TxDescStartAddrHigh, (unsigned long)0); RTL_W32(RxDescStartAddrLow, bus_to_phys(tpc->RxDescArray)); RTL_W32(RxDescStartAddrHigh, (unsigned long)0); /* RTL-8169sc/8110sc or later version */ if (tpc->chipset > 5) RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); RTL_W8(Cfg9346, Cfg9346_Lock); udelay(10); RTL_W32(RxMissed, 0); rtl8169_set_rx_mode(dev); /* no early-rx interrupts */ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); #ifdef DEBUG_RTL8169 printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); #endif }
void rtl_raise_clock(u8 *x, void __iomem *ioaddr) { *x = *x | Cfg9346_EESK; RTL_W8(Cfg9346, *x); udelay(RTL_CLOCK_RATE); }
static int OOB_set_ip_mac(struct rtl8168_private *tp, struct sockaddr_in *sa, u8 *mac) { u32 data; if (tp->mcfg == CFG_METHOD_13) { OCP_write(tp, 0xF, 0xd0, be32_to_cpu(sa->sin_addr.s_addr)); memcpy(&data, mac, 4); OCP_write(tp, 0xF, 0x00, le32_to_cpu(data)); data = 0; memcpy(&data, mac + 4, 2); OCP_write(tp, 0x3, 0x04, le32_to_cpu(data)); OOB_notify(tp, OOB_CMD_SET_IPMAC); } else if (tp->mcfg == CFG_METHOD_17) { void __iomem *ioaddr = tp->mmio_addr; struct net_device *dev = tp->dev; u32 rx_mode; rx_mode = RTL_R32(RxConfig); if (netif_running(dev)) { netif_stop_queue(dev); RTL_W32(RxConfig, rx_mode & ~0x3f); while ((RTL_R8(0xd3) & (BIT_5 | BIT_4)) != ((BIT_5 | BIT_4))) udelay(20); RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb)); // } else { // unsigned long flags; // // spin_lock_irqsave(&tp->phy_lock, flags); // mdio_write(tp, 0x1f, 0x0000); // data = mdio_read(tp, MII_CTRL1000); // data &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); // mdio_write(tp, MII_CTRL1000, data); // mdio_write(tp, 0x00, 0x9200); // spin_unlock_irqrestore(&tp->phy_lock, flags); // // ssleep(3); // RTL_W16(IntrStatus, RTL_R16(IntrStatus)); // // RTL_W32(MAR0, 0); // RTL_W32(MAR0 + 4, 0); // RTL_W16(RxMaxSize, 0x05f3); } RTL_W8(0xD3, RTL_R8(0xD3) & ~BIT_7); rtl8168_eri_write(ioaddr, 0x180, 4, 0x06080888, ERIAR_ExGMAC); rtl8168_eri_write(ioaddr, 0x184, 4, 0xdd860008, ERIAR_ExGMAC); memcpy(&data, mac, 2); rtl8168_eri_write(ioaddr, 0xf0, 4, (le32_to_cpu(data) << 16), ERIAR_ExGMAC); memcpy(&data, mac + 2, 4); rtl8168_eri_write(ioaddr, 0xf4, 4, le32_to_cpu(data), ERIAR_ExGMAC); rtl8168_eri_write(ioaddr, 0x190, 4, 0x3c110600, ERIAR_ExGMAC); rtl8168_eri_write(ioaddr, 0x194, 4, 0x2c32332b, ERIAR_ExGMAC); rtl8168_eri_write(ioaddr, 0x198, 4, 0x003a0201, ERIAR_ExGMAC); rtl8168_eri_write(ioaddr, 0x19c, 4, 0x00000000, ERIAR_ExGMAC); rtl8168_eri_write(ioaddr, 0x1f0, 4, cpu_to_le32(sa->sin_addr.s_addr), ERIAR_ExGMAC); memcpy(&data, mac, 4); rtl8168_eri_write(ioaddr, 0x258, 4, le32_to_cpu(data), ERIAR_ExGMAC); memcpy(&data, mac + 4, 2); rtl8168_eri_write(ioaddr, 0x25c, 2, le32_to_cpu(data), ERIAR_ExGMAC); RTL_W8(0xe0, RTL_R8(0xe0) | BIT_6); while (!(RTL_R8(0xd3) & BIT_1)) udelay(20); RTL_W32(0xb0, 0x9800e035); RTL_W32(0xb0, 0x9801e034); RTL_W32(0xb0, 0x9802e019); RTL_W32(0xb0, 0x98039918); RTL_W32(0xb0, 0x9804c011); RTL_W32(0xb0, 0x98057100); RTL_W32(0xb0, 0x9806499f); RTL_W32(0xb0, 0x9807f011); RTL_W32(0xb0, 0x9808c00e); RTL_W32(0xb0, 0x98097100); RTL_W32(0xb0, 0x980A4995); RTL_W32(0xb0, 0x980Bf00d); RTL_W32(0xb0, 0x980C4895); RTL_W32(0xb0, 0x980D9900); RTL_W32(0xb0, 0x980Ec009); RTL_W32(0xb0, 0x980F7100); RTL_W32(0xb0, 0x98104890); RTL_W32(0xb0, 0x98119900); RTL_W32(0xb0, 0x98124810); RTL_W32(0xb0, 0x98139900); RTL_W32(0xb0, 0x9814e004); RTL_W32(0xb0, 0x9815d44e); RTL_W32(0xb0, 0x9816d506); RTL_W32(0xb0, 0x9817c0b4); RTL_W32(0xb0, 0x9818c002); RTL_W32(0xb0, 0x9819b800); RTL_W32(0xb0, 0x981A0500); RTL_W32(0xb0, 0x981B1a26); RTL_W32(0xb0, 0x981Ca4ca); RTL_W32(0xb0, 0x981D21bc); RTL_W32(0xb0, 0x981E25bc); RTL_W32(0xb0, 0x981F1305); RTL_W32(0xb0, 0x9820f00d); RTL_W32(0xb0, 0x9821c213); RTL_W32(0xb0, 0x98227340); RTL_W32(0xb0, 0x982349b0); RTL_W32(0xb0, 0x9824f009); RTL_W32(0xb0, 0x98251a3a); RTL_W32(0xb0, 0x9826a4ca); RTL_W32(0xb0, 0x982721b9); RTL_W32(0xb0, 0x982825b9); RTL_W32(0xb0, 0x98291303); RTL_W32(0xb0, 0x982Af006); RTL_W32(0xb0, 0x982B1309); RTL_W32(0xb0, 0x982Cf004); RTL_W32(0xb0, 0x982Dc306); RTL_W32(0xb0, 0x982E1a26); RTL_W32(0xb0, 0x982Fbb00); RTL_W32(0xb0, 0x9830c302); RTL_W32(0xb0, 0x9831bb00); RTL_W32(0xb0, 0x98320f3e); RTL_W32(0xb0, 0x98330f4e); RTL_W32(0xb0, 0x9834c0ae); RTL_W32(0xb0, 0x98351800); RTL_W32(0xb0, 0x9836b800); RTL_W32(0xb0, 0xfe173000); RTL_W32(0xb0, 0xfe1604ff); RTL_W32(0xb0, 0xfe150f4d); data = rtl8168_eri_read(ioaddr, 0xd6, 1, ERIAR_ExGMAC); rtl8168_eri_write(ioaddr, 0xd6, 1, data | BIT_0, ERIAR_ExGMAC); if (netif_running(dev)) { rtl8168_init_ring_indexes(tp); RTL_W8(ChipCmd, CmdRxEnb | CmdTxEnb); RTL_W32(RxConfig, rx_mode); netif_wake_queue(dev); } else { RTL_W8(0xD3, RTL_R8(0xD3) | BIT_7); // data = rtl8168_eri_read(ioaddr, 0xDC, 1, ERIAR_ExGMAC); // data &= ~BIT_0; // rtl8168_eri_write( ioaddr, 0xDC, 1, data, ERIAR_ExGMAC); // data |= BIT_0; // rtl8168_eri_write( ioaddr, 0xDC, 1, data, ERIAR_ExGMAC); RTL_W32(RxConfig, rx_mode | 0x0e); } } else { return -EFAULT; } return 0; }
void Scan_BB_PSD( IN PDM_ODM_T pDM_Odm, int *PSD_report_right, int *PSD_report_left, int len, int initial_gain) { struct rtl8192cd_priv *priv=pDM_Odm->priv; pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable; u1Byte ST_TH_origin; u1Byte idx[20]={//96,99,102,106,109,112,115,118,122,125, 224,227,230,234,237,240,243,246,250,253, 0,3,6,10,13,16,19,22,26,29}; int tone_idx, channel_org, channel, i; // set DFS ST_TH to max value ST_TH_origin = RTL_R8(0x91c); RTL_W8(0x91c, 0x4e); // Turn off CCK ODM_SetBBReg(pDM_Odm, 0x808, BIT28, 0); //808[28] // Turn off TX // Pause TX Queue if (!priv->pmib->dot11DFSEntry.disable_tx) ODM_Write1Byte(pDM_Odm, 0x522, 0xFF); //REG_TXPAUSE 改為0x522 // Turn off CCA if(GET_CHIP_VER(priv) == VERSION_8814A){ ODM_SetBBReg(pDM_Odm, 0x838, BIT1, 0x1); //838[1] 設為1 } else{ ODM_SetBBReg(pDM_Odm, 0x838, BIT3, 0x1); //838[3] 設為1 } // PHYTXON while loop PHY_SetBBReg(priv, 0x8fc, 0xfff, 0); i = 0; while (ODM_GetBBReg(pDM_Odm, 0xfa0, BIT18)) { i++; if (i > 1000000) { panic_printk("Wait in %s() more than %d times!\n", __FUNCTION__, i); break; } } // backup IGI_origin , set IGI = 0x3e; pDM_DigTable->bPSDInProgress = TRUE; odm_PauseDIG(pDM_Odm, PHYDM_PAUSE, PHYDM_PAUSE_LEVEL_7, initial_gain); // Turn off 3-wire ODM_SetBBReg(pDM_Odm, 0xC00, BIT1|BIT0, 0x0); //c00[1:0] 寫0 // pts value = 128, 256, 512, 1024 ODM_SetBBReg(pDM_Odm, 0x910, BIT14|BIT15, 0x1); //910[15:14]設為1, 用256點 ODM_SetBBReg(pDM_Odm, 0x910, BIT12|BIT13, 0x1); //910[13:12]設為1, avg 8 次 // scan in-band PSD channel_org = ODM_GetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, 0x3FF); if(priv, priv->pshare->CurrentChannelBW != HT_CHANNEL_WIDTH_20){ priv->pshare->No_RF_Write = 0; SwBWMode(priv, HT_CHANNEL_WIDTH_20, 0); priv->pshare->No_RF_Write = 1; } if (priv->pshare->rf_ft_var.dfs_scan_inband) { int PSD_report_inband[20]; for (tone_idx=0;tone_idx<len;tone_idx++) PSD_report_inband[tone_idx] = GetPSDData_8812(pDM_Odm, idx[tone_idx], initial_gain); panic_printk("PSD inband: "); for (i=0; i<len; i++) panic_printk("%d ", PSD_report_inband[i]); panic_printk("\n"); } // scan right(higher) neighbor channel if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) channel = channel_org + 4; else if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) channel = channel_org + 6; else channel = channel_org + 10; delay_us(300); // for idle 20M, it will emit signal in right 20M channel priv->pshare->No_RF_Write = 0; ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, 0x3FF, channel); priv->pshare->No_RF_Write = 1; for (tone_idx=0;tone_idx<len;tone_idx++) PSD_report_right[tone_idx] = GetPSDData_8812(pDM_Odm, idx[tone_idx], initial_gain); // scan left(lower) neighbor channel if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) channel = channel_org - 4; else if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) channel = channel_org - 6; else channel = channel_org - 10; priv->pshare->No_RF_Write = 0; ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, 0x3FF, channel); priv->pshare->No_RF_Write = 1; for (tone_idx=0;tone_idx<len;tone_idx++) PSD_report_left[tone_idx] = GetPSDData_8812(pDM_Odm, idx[tone_idx], initial_gain); // restore originl center frequency if(priv, priv->pshare->CurrentChannelBW != HT_CHANNEL_WIDTH_20){ priv->pshare->No_RF_Write = 0; SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); priv->pshare->No_RF_Write = 1; } priv->pshare->No_RF_Write = 0; ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, 0x3FF, channel_org); priv->pshare->No_RF_Write = 1; // Turn on 3-wire ODM_SetBBReg(pDM_Odm, 0xc00, BIT1|BIT0, 0x3); //c00[1:0] 寫3 // Restore Current Settings // Resume DIG pDM_DigTable->bPSDInProgress = FALSE; odm_PauseDIG(pDM_Odm, PHYDM_RESUME, PHYDM_PAUSE_LEVEL_7, NONE); //Turn on CCA if(GET_CHIP_VER(priv) == VERSION_8814A){ ODM_SetBBReg(pDM_Odm, 0x838, BIT1, 0); //838[1] 設為0 } else{ ODM_SetBBReg(pDM_Odm, 0x838, BIT3, 0); //838[3] 設為0 } // Turn on TX // Resume TX Queue if (!priv->pmib->dot11DFSEntry.disable_tx) ODM_Write1Byte(pDM_Odm, 0x522, 0x00); //REG_TXPAUSE 改為0x522 // CCK on if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) ODM_SetBBReg(pDM_Odm, 0x808, BIT28, 1); //808[28] // Resume DFS ST_TH RTL_W8(0x91c, ST_TH_origin); }
static int __devinit rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev = NULL; struct rtl8169_private *tp = NULL; void *ioaddr = NULL; static int board_idx = -1; static int printed_version = 0; int i, rc; int option = -1, Cap10_100 = 0, Cap1000 = 0; assert(pdev != NULL); assert(ent != NULL); board_idx++; if (!printed_version) { printk(KERN_INFO RTL8169_DRIVER_NAME " loaded\n"); printed_version = 1; } rc = rtl8169_init_board(pdev, &dev, &ioaddr); if (rc) return rc; tp = dev->priv; assert(ioaddr != NULL); assert(dev != NULL); assert(tp != NULL); // Get MAC address. FIXME: read EEPROM for (i = 0; i < MAC_ADDR_LEN; i++) dev->dev_addr[i] = RTL_R8(MAC0 + i); dev->open = rtl8169_open; dev->hard_start_xmit = rtl8169_start_xmit; dev->get_stats = rtl8169_get_stats; dev->ethtool_ops = &rtl8169_ethtool_ops; dev->stop = rtl8169_close; dev->tx_timeout = rtl8169_tx_timeout; dev->set_multicast_list = rtl8169_set_rx_mode; dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; // dev->do_ioctl = mii_ioctl; tp = dev->priv; // private data // tp->pci_dev = pdev; tp->mmio_addr = ioaddr; spin_lock_init(&tp->lock); rc = register_netdev(dev); if (rc) { iounmap(ioaddr); pci_release_regions(pdev); pci_disable_device(pdev); free_netdev(dev); return rc; } printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n", dev->name, rtl_chip_info[tp->chipset].name); pci_set_drvdata(pdev, dev); printk(KERN_INFO "%s: %s at 0x%lx, " "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " "IRQ %d\n", dev->name, rtl_chip_info[ent->driver_data].name, dev->base_addr, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], dev->irq); rtl8169_hw_phy_config(dev); dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); RTL_W8(0x82, 0x01); if (tp->mac_version < RTL_GIGA_MAC_VER_E) { dprintk("Set PCI Latency=0x40\n"); pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); } if (tp->mac_version == RTL_GIGA_MAC_VER_D) { dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); RTL_W8(0x82, 0x01); dprintk("Set PHY Reg 0x0bh = 0x00h\n"); mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 } // if TBI is not endbled if (!(RTL_R8(PHYstatus) & TBI_Enable)) { int val = mdio_read(ioaddr, PHY_AUTO_NEGO_REG); option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; // Force RTL8169 in 10/100/1000 Full/Half mode. if (option > 0) { printk(KERN_INFO "%s: Force-mode Enabled.\n", dev->name); Cap10_100 = 0, Cap1000 = 0; switch (option) { case _10_Half: Cap10_100 = PHY_Cap_10_Half_Or_Less; Cap1000 = PHY_Cap_Null; break; case _10_Full: Cap10_100 = PHY_Cap_10_Full_Or_Less; Cap1000 = PHY_Cap_Null; break; case _100_Half: Cap10_100 = PHY_Cap_100_Half_Or_Less; Cap1000 = PHY_Cap_Null; break; case _100_Full: Cap10_100 = PHY_Cap_100_Full_Or_Less; Cap1000 = PHY_Cap_Null; break; case _1000_Full: Cap10_100 = PHY_Cap_100_Full_Or_Less; Cap1000 = PHY_Cap_1000_Full; break; default: break; } mdio_write(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F)); //leave PHY_AUTO_NEGO_REG bit4:0 unchanged mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000); } else { printk(KERN_INFO "%s: Auto-negotiation Enabled.\n", dev->name); // enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged mdio_write(ioaddr, PHY_AUTO_NEGO_REG, PHY_Cap_100_Full_Or_Less | (val & 0x1f)); // enable 1000 Full Mode mdio_write(ioaddr, PHY_1000_CTRL_REG, PHY_Cap_1000_Full); } // Enable auto-negotiation and restart auto-nigotiation mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); udelay(100); // wait for auto-negotiation process for (i = 10000; i > 0; i--) { //check if auto-negotiation complete if (mdio_read(ioaddr, PHY_STAT_REG) & PHY_Auto_Neco_Comp) { udelay(100); option = RTL_R8(PHYstatus); if (option & _1000bpsF) { printk(KERN_INFO "%s: 1000Mbps Full-duplex operation.\n", dev->name); } else { printk(KERN_INFO "%s: %sMbps %s-duplex operation.\n", dev->name, (option & _100bps) ? "100" : "10", (option & FullDup) ? "Full" : "Half"); } break; } else { udelay(100); } } // end for-loop to wait for auto-negotiation process } else { udelay(100); printk(KERN_INFO "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n", dev->name, (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed"); } return 0; }
static int __devinit rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, void **ioaddr_out) { void *ioaddr = NULL; struct net_device *dev; struct rtl8169_private *tp; unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; int rc, i, acpi_idle_state = 0, pm_cap; assert(pdev != NULL); assert(ioaddr_out != NULL); *ioaddr_out = NULL; *dev_out = NULL; // dev zeroed in alloc_etherdev dev = alloc_etherdev(sizeof (*tp)); if (dev == NULL) { printk(KERN_ERR PFX "unable to alloc new ethernet\n"); return -ENOMEM; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); tp = dev->priv; // enable device (incl. PCI PM wakeup and hotplug setup) rc = pci_enable_device(pdev); if (rc) { printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name); goto err_out; } /* save power state before pci_enable_device overwrites it */ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (pm_cap) { u16 pwr_command; pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; } else { printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n"); goto err_out_free_res; } mmio_start = pci_resource_start(pdev, 1); mmio_end = pci_resource_end(pdev, 1); mmio_flags = pci_resource_flags(pdev, 1); mmio_len = pci_resource_len(pdev, 1); // make sure PCI base addr 1 is MMIO if (!(mmio_flags & IORESOURCE_MEM)) { printk(KERN_ERR PFX "region #1 not an MMIO resource, aborting\n"); rc = -ENODEV; goto err_out_disable; } // check for weird/broken PCI region reporting if (mmio_len < RTL_MIN_IO_SIZE) { printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n"); rc = -ENODEV; goto err_out_disable; } rc = pci_request_regions(pdev, dev->name); if (rc) { printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name); goto err_out_disable; } tp->cp_cmd = PCIMulRW | RxChkSum; if ((sizeof(dma_addr_t) > 32) && !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) tp->cp_cmd |= PCIDAC; else { rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc < 0) { printk(KERN_ERR PFX "DMA configuration failed.\n"); goto err_out_free_res; } } // enable PCI bus-mastering pci_set_master(pdev); // ioremap MMIO region ioaddr = ioremap(mmio_start, mmio_len); if (ioaddr == NULL) { printk(KERN_ERR PFX "cannot remap MMIO, aborting\n"); rc = -EIO; goto err_out_free_res; } // Soft reset the chip. RTL_W8(ChipCmd, CmdReset); // Check that the chip has finished the reset. for (i = 1000; i > 0; i--) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; udelay(10); } // Identify chip attached to board rtl8169_get_mac_version(tp, ioaddr); rtl8169_get_phy_version(tp, ioaddr); rtl8169_print_mac_version(tp); rtl8169_print_phy_version(tp); for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { if (tp->mac_version == rtl_chip_info[i].mac_version) break; } if (i < 0) { /* Unknown chip: assume array element #0, original RTL-8169 */ printk(KERN_DEBUG PFX "PCI device %s: unknown chip version, assuming %s\n", pci_name(pdev), rtl_chip_info[0].name); i++; } tp->chipset = i; *ioaddr_out = ioaddr; *dev_out = dev; return 0; err_out_free_res: pci_release_regions(pdev); err_out_disable: pci_disable_device(pdev); err_out: free_netdev(dev); return rc; }
static void rtl8169_hw_start(struct net_device *dev) { struct rtl8169_private *tp = dev->priv; void *ioaddr = tp->mmio_addr; u32 i; /* Soft reset the chip. */ RTL_W8(ChipCmd, CmdReset); /* Check that the chip has finished the reset. */ for (i = 1000; i > 0; i--) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; else udelay(10); } RTL_W8(Cfg9346, Cfg9346_Unlock); RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); RTL_W8(EarlyTxThres, EarlyTxThld); // For gigabit rtl8169 RTL_W16(RxMaxSize, RxPacketMaxSize); // Set Rx Config register i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset]. RxConfigMask); RTL_W32(RxConfig, i); /* Set DMA burst size and Interframe Gap Time */ RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | (InterFrameGap << TxInterFrameGapShift)); tp->cp_cmd |= RTL_R16(CPlusCmd); RTL_W16(CPlusCmd, tp->cp_cmd); if (tp->mac_version == RTL_GIGA_MAC_VER_D) { dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n"); tp->cp_cmd |= (1 << 14) | PCIMulRW; RTL_W16(CPlusCmd, tp->cp_cmd); } tp->cur_rx = 0; RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK)); RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32)); RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK)); RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32)); RTL_W8(Cfg9346, Cfg9346_Lock); udelay(10); RTL_W32(RxMissed, 0); rtl8169_set_rx_mode(dev); /* no early-rx interrupts */ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); /* Enable all known interrupts by setting the interrupt mask. */ RTL_W16(IntrMask, rtl8169_intr_mask); netif_start_queue(dev); }