⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 at_main.c

📁 Linux* Base Driver for the Attansic(R) L1 Gigabit Ethernet Adapter
💻 C
📖 第 1 页 / 共 5 页
字号:

/**
 * at_irq_enable - Enable default interrupt generation settings
 * @adapter: board private structure
 **/
inline void
at_irq_enable(struct at_adapter *adapter)
{
    if(0 == atomic_dec_and_test(&adapter->irq_sem)) {
        AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);
    }
}

static int
at_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
{
    struct pci_dev *pdev = NULL;

    DEBUGFUNC("at_notify_reboot !");

    switch(event) {
    case SYS_DOWN:
    case SYS_HALT:
    case SYS_POWER_OFF:
        while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) {
            if(pci_dev_driver(pdev) == &at_driver)
                at_suspend(pdev, 3);
        }
    }
    return NOTIFY_DONE;
}


static int
at_suspend(struct pci_dev *pdev, uint32_t state)
{
    struct net_device *netdev = pci_get_drvdata(pdev);
    struct at_adapter *adapter = netdev_priv(netdev);
    struct at_hw * hw = &adapter->hw;
    uint32_t ctrl = 0;
    uint32_t wufc = adapter->wol;

    DEBUGFUNC("at_suspend !"); 

    netif_device_detach(netdev);

    if(netif_running(netdev))
        at_down(adapter);

    at_read_phy_reg(hw, MII_BMSR, (uint16_t*)&ctrl);
    at_read_phy_reg(hw, MII_BMSR, (uint16_t*)&ctrl);
    if(ctrl & BMSR_LSTATUS)
        wufc &= ~AT_WUFC_LNKC;
        
    // reduce speed to 10/100M
    if (wufc) {
        at_phy_enter_power_saving(hw);
        // if resume, let driver to re- setup link
        hw->phy_configured = FALSE; 
        set_mac_addr(hw);
        at_set_multi(netdev);
        
        ctrl = 0;
        /* turn on magic packet wol */
        if (wufc & AT_WUFC_MAG) {
            ctrl = WOL_MAGIC_EN|WOL_MAGIC_PME_EN;
        }
        // turn on Link change WOL */
        if (wufc & AT_WUFC_LNKC) {
            ctrl |= (WOL_LINK_CHG_EN|WOL_LINK_CHG_PME_EN);
        }
        AT_WRITE_REG(hw, REG_WOL_CTRL, ctrl);
            
        /* turn on all-multi mode if wake on multicast is enabled */
        ctrl = AT_READ_REG(hw, REG_MAC_CTRL);
        ctrl &= ~MAC_CTRL_DBG;
        ctrl &= ~MAC_CTRL_PROMIS_EN;
		if(wufc & AT_WUFC_MC) {
		    ctrl |= MAC_CTRL_MC_ALL_EN;
		} else {
		    ctrl &= ~MAC_CTRL_MC_ALL_EN;
		}
		/* turn on broadcast mode if wake on-BC is enabled */
		if (wufc & AT_WUFC_BC) {
		    ctrl |= MAC_CTRL_BC_EN;
		} else {
		    ctrl &= ~MAC_CTRL_BC_EN;
		}
		
		// enable RX
		ctrl |= MAC_CTRL_RX_EN;
		AT_WRITE_REG(hw, REG_MAC_CTRL, ctrl);
		
		pci_enable_wake(pdev, 3, 1);
		pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
	} else {
	    AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
		pci_enable_wake(pdev, 3, 0);
		pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
	}
		
	pci_save_state(pdev);
	pci_disable_device(pdev);

    state = (state > 0) ? 3 : 0;
    pci_set_power_state(pdev, state);

    return 0;
}

static int
at_resume(struct pci_dev *pdev)
{
    struct net_device *netdev = pci_get_drvdata(pdev);
    struct at_adapter *adapter = netdev_priv(netdev);
    uint32_t ret_val;

    DEBUGFUNC("at_resume !");

    pci_set_power_state(pdev, 0);
	pci_restore_state(pdev);
	
    ret_val = pci_enable_device(pdev);
    pci_enable_wake(pdev, 3, 0);
    pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
    
    AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
    at_reset(adapter);
    

    if(netif_running(netdev))
        at_up(adapter);

    netif_device_attach(netdev);

	at_via_workaround(adapter);

    return 0;
}


/**
 * at_sw_init - Initialize general software structures (struct at_adapter)
 * @adapter: board private structure to initialize
 *
 * at_sw_init initializes the Adapter private data structure.
 * Fields are initialized based on PCI device information and
 * OS network device settings (MTU size).
 **/

static int __devinit
at_sw_init(struct at_adapter *adapter)
{
    struct at_hw *hw = &adapter->hw;
    struct net_device *netdev = adapter->netdev;
    struct pci_dev *pdev = adapter->pdev;

    /* PCI config space info */

    hw->vendor_id = pdev->vendor;
    hw->device_id = pdev->device;
    hw->subsystem_vendor_id = pdev->subsystem_vendor;
    hw->subsystem_id = pdev->subsystem_device;

    pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);

    pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);


    hw->max_frame_size = netdev->mtu +
                 ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
    hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
    
    adapter->wol = 0;
    
    adapter->rx_buffer_len = (hw->max_frame_size+7)&~7;
    adapter->ict = 50000;  // 100ms
    
    adapter->link_speed = SPEED_0;   // hardware init
    adapter->link_duplex = FULL_DUPLEX; //

  
    hw->phy_configured = FALSE;
    hw->preamble_len = 7;
    hw->ipgt = 0x60;
    hw->min_ifg = 0x50;
    hw->ipgr1 = 0x40;
    hw->ipgr2 = 0x60;
    
    hw->max_retry = 0xf;
    hw->lcol = 0x37;
    hw->jam_ipg = 7;
    
    hw->rfd_burst = 8;
    hw->rrd_burst = 8;
    hw->rfd_fetch_gap = 1;
    hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
    hw->rx_jumbo_lkah = 1;
    hw->rrd_ret_timer = 16;
    
    hw->tpd_burst = 4;
    hw->tpd_fetch_th = 16; 
    hw->txf_burst = 0x100;
    hw->tx_jumbo_task_th = (hw->max_frame_size+7)>>3;
    hw->tpd_fetch_gap = 1;
    
    hw->rcb_value = at_rcb_128;
    hw->dma_ord = at_dma_ord_enh;
    hw->dmar_block = at_dma_req_256;
    hw->dmaw_block = at_dma_req_256;
    
    hw->cmb_rrd = 4;
    hw->cmb_tpd = 4;
    hw->cmb_rx_timer = 1; //about 2us
    hw->cmb_tx_timer = 1; //about 2us
    hw->smb_timer = 100000 ; // about 200ms
    atomic_set(&adapter->irq_sem, 0);
    spin_lock_init(&adapter->stats_lock);
    spin_lock_init(&adapter->tx_lock);
    spin_lock_init(&adapter->mb_lock);

    return 0;
}

int
at_reset(struct at_adapter *adapter)
{
    int ret;
    
    if (AT_SUCCESS != (ret = at_reset_hw(&adapter->hw)))
        return ret;

    return at_init_hw(&adapter->hw);
}

/**
 * at_open - Called when a network interface is made active
 * @netdev: network interface device structure
 *
 * Returns 0 on success, negative value on failure
 *
 * The open entry point is called when a network interface is made
 * active by the system (IFF_UP).  At this point all resources needed
 * for transmit and receive operations are allocated, the interrupt
 * handler is registered with the OS, the watchdog timer is started,
 * and the stack is notified that the interface is ready.
 **/

static int
at_open(struct net_device *netdev)
{
    struct at_adapter *adapter = netdev_priv(netdev);
    int err;

    DEBUGFUNC("at_open !");

    /* allocate transmit descriptors */

    if((err = at_setup_ring_resources(adapter)))
        return err;

    if((err = at_up(adapter)))
        goto err_up;
/* for test only */
/*    { uint32_t value;
       value = AT_READ_REG(&adapter->hw, 0x12FC);
       DEBUGOUT1("reg 0x12fc = 0x%x", value);
       value = AT_READ_REG(&adapter->hw, 0x1008);
       DEBUGOUT1("reg 0x1008 = 0x%x", value);
    }
*/
/**********end ****/



    return 0;

err_up:
    at_reset(adapter);

    return err;
}

/**
 * at_close - Disables a network interface
 * @netdev: network interface device structure
 *
 * Returns 0, this is not allowed to fail
 *
 * The close entry point is called when an interface is de-activated
 * by the OS.  The hardware is still under the drivers control, but
 * needs to be disabled.  A global MAC reset is issued to stop the
 * hardware, and all transmit and receive resources are freed.
 **/

static int
at_close(struct net_device *netdev)
{
    struct at_adapter *adapter = netdev_priv(netdev);
    DEBUGFUNC("at_close!");

    at_down(adapter);

    at_free_ring_resources(adapter);

    return 0;
}

/**
 * at_setup_mem_resources - allocate Tx / RX descriptor resources 
 * @adapter: board private structure
 *
 * Return 0 on success, negative on failure
 **/

int32_t
at_setup_ring_resources(struct at_adapter *adapter)
{
    struct at_tpd_ring *tpd_ring = &adapter->tpd_ring;
    struct at_rfd_ring *rfd_ring = &adapter->rfd_ring;
    struct at_rrd_ring *rrd_ring = &adapter->rrd_ring;
    struct at_ring_header * ring_header = &adapter->ring_header;
    struct pci_dev *pdev = adapter->pdev;
    int size;
    uint8_t offset = 0;

//    DEBUGFUNC("at_setup_ring_resources !");

//    DEBUGOUT1("TPD count = %x  RFD cont = %x  RRD = %x", 
//        tpd_ring->count, rfd_ring->count, rrd_ring->count);
        
    DEBUGOUT1("sz TPD:%d, sz RFD:%d, sz RRD:%d", 
		    sizeof(tx_packet_desc_t),
		    sizeof(rx_free_desc_t),
		    sizeof(rx_return_desc_t));

    size = sizeof(struct at_buffer) * (tpd_ring->count+rfd_ring->count);
    tpd_ring->buffer_info = kmalloc(size, GFP_KERNEL);
    if(!tpd_ring->buffer_info) {
    DEBUGOUT1("kmalloc failed , size = D%d", size);
        return -ENOMEM;
    }
    rfd_ring->buffer_info = 
         (struct at_buffer*)(tpd_ring->buffer_info+tpd_ring->count);

    memset(tpd_ring->buffer_info, 0, size);

    /* real ring DMA buffer */
    ring_header->size = size =  sizeof(tx_packet_desc_t ) * tpd_ring->count 
                              + sizeof(rx_free_desc_t) *    rfd_ring->count 
                              + sizeof(rx_return_desc_t) *  rrd_ring->count
                              + sizeof(coals_msg_block_t)
                              + sizeof(stats_msg_block_t)
                              + 40; // 40: for 8 bytes align
         
    ring_header->desc = 
          pci_alloc_consistent(pdev, ring_header->size, &ring_header->dma);
    if(!ring_header->desc) {
        kfree(tpd_ring->buffer_info);
        DEBUGOUT1("pci_alloc_consistent failed , size = D%d", size);
        return -ENOMEM;
    }
    
    if (adapter->pci_using_64) 
    { // test whether HIDWORD dma buffer is not cross boundary
        if (    ((ring_header->dma       &0xffffffff00000000ULL)>>32)
             != (((ring_header->dma+size)&0xffffffff00000000ULL)>>32) )
        {
            kfree(tpd_ring->buffer_info);
            pci_free_consistent(
                     pdev, 
                     ring_header->size, 
                     ring_header->desc, 
                     ring_header->dma);
            DEBUGOUT("memory allocated cross 32bit boundary !");
            return -ENOMEM;
        }
    }

//    DEBUGOUT("memory allocated successfully !");    
    
    memset(ring_header->desc, 0, ring_header->size);
    DEBUGOUT1("whole ring dma addr=%x", ring_header->dma);

    // init TPD ring
    tpd_ring->dma = ring_header->dma;
    offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
    tpd_ring->dma += offset;
    tpd_ring->desc = (uint8_t*) ring_header->desc + offset;
    tpd_ring->size = sizeof(tx_packet_desc_t) * tpd_ring->count;
    atomic_set(&tpd_ring->next_to_use, 0);
    atomic_set(&tpd_ring->next_to_clean, 0);
    DEBUGOUT1("tpd ring dma addr=%x", tpd_ring->dma);
    
    // init RFD ring
    rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
    offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
    rfd_ring->dma += offset;
    rfd_ring->desc = (uint8_t*) tpd_ring->desc + (tpd_ring->size+offset);
    rfd_ring->size = sizeof(rx_free_desc_t) * rfd_ring->count;
        
    rfd_ring->next_to_clean = 0;
    //rfd_ring->next_to_use = rfd_ring->count - 1;
    atomic_set(&rfd_ring->next_to_use, 0);
    DEBUGOUT1("rfd ring dma addr=%x", rfd_ring->dma);
    
    // init RRD ring
    rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
    offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
    rrd_ring->dma += offset;
    rrd_ring->desc = (uint8_t*) rfd_ring->desc + (rfd_ring->size+offset);
    rrd_ring->size = sizeof(rx_return_desc_t) * rrd_ring->count;
    rrd_ring->next_to_use = 0;
    atomic_set(&rrd_ring->next_to_clean, 0);
    DEBUGOUT1("rrd ring dma addr=%x", rrd_ring->dma);
    
    // init CMB
    adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
    offset = (adapter->cmb.dma & 0x7)? (8-(adapter->cmb.dma & 0x7)) : 0;
    adapter->cmb.dma += offset;
    adapter->cmb.cmb = 
       (coals_msg_block_t*)
          ((uint8_t*)rrd_ring->desc + (rrd_ring->size+offset));
    DEBUGOUT1("cmd dma addr=%x", adapter->cmb.dma);
    
    // init SMB
    adapter->smb.dma = adapter->cmb.dma + sizeof(coals_msg_block_t);
    offset = (adapter->smb.dma&0x7) ? (8-(adapter->smb.dma&0x7)): 0;
    adapter->smb.dma += offset;
    adapter->smb.smb = 
	    (stats_msg_block_t*)
          ((uint8_t*)adapter->cmb.cmb + (sizeof(coals_msg_block_t)+offset));
    DEBUGOUT1("smb dma addr=%x", adapter->smb.dma);

    return AT_SUCCESS;
}

/**
 * at_free_ring_resources - Free Tx / RX descriptor Resources
 * @adapter: board private structure
 *
 * Free all transmit software resources

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -