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

📄 ag7100.c

📁 linux下atheros的ag7100驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
            spin_unlock_irqrestore(&mac->mac_lock, flags);        }        netif_wake_queue(mac->mac_dev);    }    return reaped;}/* * allocate and init rings, descriptors etc. */static intag7100_tx_alloc(ag7100_mac_t *mac){    ag7100_ring_t *r = &mac->mac_txring;    ag7100_desc_t *ds;    int i, next;    if (ag7100_ring_alloc(r, AG7100_TX_DESC_CNT))        return 1;    ag7100_trc(r->ring_desc,"ring_desc");    ds = r->ring_desc;    for(i = 0; i < r->ring_nelem; i++ )    {        ag7100_trc_new(ds,"tx alloc ds");        next                =   (i == (r->ring_nelem - 1)) ? 0 : (i + 1);        ds[i].next_desc     =   ag7100_desc_dma_addr(r, &ds[next]);        ag7100_tx_own(&ds[i]);    }    return 0;}static intag7100_rx_alloc(ag7100_mac_t *mac){    ag7100_ring_t *r  = &mac->mac_rxring;    ag7100_desc_t *ds;    int i, next, tail = r->ring_tail;    ag7100_buffer_t *bf;    if (ag7100_ring_alloc(r, AG7100_RX_DESC_CNT))        return 1;    ag7100_trc(r->ring_desc,"ring_desc");    ds = r->ring_desc;    for(i = 0; i < r->ring_nelem; i++ )    {        next                =   (i == (r->ring_nelem - 1)) ? 0 : (i + 1);        ds[i].next_desc     =   ag7100_desc_dma_addr(r, &ds[next]);    }    for (i = 0; i < AG7100_RX_DESC_CNT; i++)    {        bf                  = &r->ring_buffer[tail];        ds                  = &r->ring_desc[tail];        bf->buf_pkt         = ag7100_buffer_alloc();        if (!bf->buf_pkt)             goto error;        dma_cache_inv((unsigned long)bf->buf_pkt->data, AG7100_RX_BUF_SIZE);        ds->pkt_start_addr  = virt_to_phys(bf->buf_pkt->data);        ag7100_rx_give_to_dma(ds);        ag7100_ring_incr(tail);    }    return 0;error:    printk(MODULE_NAME ": unable to allocate rx\n");    ag7100_rx_free(mac);    return 1;}static voidag7100_tx_free(ag7100_mac_t *mac){    ag7100_ring_release(mac, &mac->mac_txring);    ag7100_ring_free(&mac->mac_txring);}static voidag7100_rx_free(ag7100_mac_t *mac){    ag7100_ring_release(mac, &mac->mac_rxring);    ag7100_ring_free(&mac->mac_rxring);}static intag7100_ring_alloc(ag7100_ring_t *r, int count){    int desc_alloc_size, buf_alloc_size;    desc_alloc_size = sizeof(ag7100_desc_t)   * count;    buf_alloc_size  = sizeof(ag7100_buffer_t) * count;    memset(r, 0, sizeof(ag7100_ring_t));    r->ring_buffer = (ag7100_buffer_t *)kmalloc(buf_alloc_size, GFP_KERNEL);    printk("%s Allocated %d at 0x%lx\n",__func__,buf_alloc_size,(unsigned long) r->ring_buffer);    if (!r->ring_buffer)    {        printk(MODULE_NAME ": unable to allocate buffers\n");        return 1;    }    r->ring_desc  =  (ag7100_desc_t *)dma_alloc_coherent(NULL,         desc_alloc_size,        &r->ring_desc_dma,         GFP_DMA);    if (! r->ring_desc)    {        printk(MODULE_NAME ": unable to allocate coherent descs\n");        kfree(r->ring_buffer);        printk("%s Freeing at 0x%lx\n",__func__,(unsigned long) r->ring_buffer);        return 1;    }    memset(r->ring_buffer, 0, buf_alloc_size);    memset(r->ring_desc,   0, desc_alloc_size);    r->ring_nelem   = count;    return 0;}static voidag7100_ring_release(ag7100_mac_t *mac, ag7100_ring_t  *r){    int i;    for(i = 0; i < r->ring_nelem; i++)        if (r->ring_buffer[i].buf_pkt)            ag7100_buffer_free(r->ring_buffer[i].buf_pkt);}static voidag7100_ring_free(ag7100_ring_t *r){    dma_free_coherent(NULL, sizeof(ag7100_desc_t)*r->ring_nelem, r->ring_desc,        r->ring_desc_dma);    kfree(r->ring_buffer);    printk("%s Freeing at 0x%lx\n",__func__,(unsigned long) r->ring_buffer);}/* * Error timers */static voidag7100_oom_timer(unsigned long data){    ag7100_mac_t *mac = (ag7100_mac_t *)data;    int val;    ag7100_trc(data,"data");    ag7100_rx_replenish(mac);    if (ag7100_rx_ring_full(mac))    {        val = mod_timer(&mac->mac_oom_timer, jiffies+1);        assert(!val);    }    else        netif_rx_schedule(mac->mac_dev);}static voidag7100_tx_timeout(struct net_device *dev){    ag7100_mac_t *mac = (ag7100_mac_t *)dev->priv;    ag7100_trc(dev,"dev");    printk("%s\n",__func__);    /*     * Do the reset outside of interrupt context     */    schedule_work(&mac->mac_tx_timeout);}static voidag7100_tx_timeout_task(ag7100_mac_t *mac){    ag7100_trc(mac,"mac");    ag7100_stop(mac->mac_dev);    ag7100_open(mac->mac_dev);}static voidag7100_get_default_macaddr(ag7100_mac_t *mac, u8 *mac_addr){    /* Use MAC address stored in Flash */        u8 *eep_mac_addr = (mac->mac_unit) ? AR7100_EEPROM_GE1_MAC_ADDR:        AR7100_EEPROM_GE0_MAC_ADDR;    printk(MODULE_NAME "CHH: Mac address for unit %d\n",mac->mac_unit);    printk(MODULE_NAME "CHH: %02x:%02x:%02x:%02x:%02x:%02x \n",        eep_mac_addr[0],eep_mac_addr[1],eep_mac_addr[2],        eep_mac_addr[3],eep_mac_addr[4],eep_mac_addr[5]);            /*    ** Check for a valid manufacturer prefix.  If not, then use the defaults    */        if(eep_mac_addr[0] == 0x00 &&        eep_mac_addr[1] == 0x03 &&        eep_mac_addr[2] == 0x7f)    {        memcpy(mac_addr, eep_mac_addr, 6);    }    else    {        /* Use Default address at top of range */        mac_addr[0] = 0x00;        mac_addr[1] = 0x03;        mac_addr[2] = 0x7F;        mac_addr[3] = 0xFF;        mac_addr[4] = 0xFF;        mac_addr[5] = 0xFF - mac->mac_unit;    }}static intag7100_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){#ifndef CONFIG_ATHRS26_PHY    printk(MODULE_NAME ": unsupported ioctl\n");    return -EOPNOTSUPP;#else    return athr_ioctl(ifr->ifr_data, cmd);#endif}static struct net_device_stats     *ag7100_get_stats(struct net_device *dev){    ag7100_mac_t *mac = dev->priv;    struct Qdisc *sch;    int i;    sch = rcu_dereference(dev->qdisc);    mac->mac_net_stats.tx_dropped = sch->qstats.drops;    i = ag7100_get_rx_count(mac) - mac->net_rx_packets;    if (i<0)        i=0;    mac->mac_net_stats.rx_missed_errors = i;    return &mac->mac_net_stats;}static voidag7100_vet_tx_len_per_pkt(unsigned int *len){    unsigned int l;    /* make it into words */    l = *len & ~3;    /*     * Not too small     */    if (l < AG7100_TX_MIN_DS_LEN)        l = AG7100_TX_MIN_DS_LEN;    else    /* Avoid len where we know we will deadlock, that    * is the range between fif_len/2 and the MTU size    */    if (l > AG7100_TX_FIFO_LEN/2)        if (l < AG7100_TX_MTU_LEN)            l = AG7100_TX_MTU_LEN;        else if (l > AG7100_TX_MAX_DS_LEN)            l = AG7100_TX_MAX_DS_LEN;        *len = l;}/* * All allocations (except irq and rings). */static int __initag7100_init(void){    int i;    struct net_device *dev;    ag7100_mac_t      *mac;    uint32_t mask;    /*     * tx_len_per_ds is the number of bytes per data transfer in word increments.    *     * If the value is 0 than we default the value to a known good value based    * on benchmarks. Otherwise we use the value specified - within some     * cosntraints of course.    *    * Tested working values are 256, 512, 768, 1024 & 1536.    *    * A value of 256 worked best in all benchmarks. That is the default.    *    */    /* Tested 256, 512, 768, 1024, 1536 OK, 1152 and 1280 failed*/    if (0 == tx_len_per_ds)        tx_len_per_ds = CONFIG_AG7100_LEN_PER_TX_DS;    ag7100_vet_tx_len_per_pkt( &tx_len_per_ds);    printk(MODULE_NAME ": Length per segment %d\n", tx_len_per_ds);    /*     * Compute the number of descriptors for an MTU     */#ifndef CONFIG_AR9100    tx_max_desc_per_ds_pkt = AG7100_TX_MAX_DS_LEN / tx_len_per_ds;    if (AG7100_TX_MAX_DS_LEN % tx_len_per_ds) tx_max_desc_per_ds_pkt++;#else    tx_max_desc_per_ds_pkt =1;#endif    printk(MODULE_NAME ": Max segments per packet %d\n", tx_max_desc_per_ds_pkt);    printk(MODULE_NAME ": Max tx descriptor count    %d\n", AG7100_TX_DESC_CNT);    printk(MODULE_NAME ": Max rx descriptor count    %d\n", AG7100_RX_DESC_CNT);    /*     * Let hydra know how much to put into the fifo in words (for tx)     */    if (0 == fifo_3)        fifo_3 = 0x000001ff | ((AG7100_TX_FIFO_LEN-tx_len_per_ds)/4)<<16;    printk(MODULE_NAME ": fifo cfg 3 %08x\n", fifo_3);    /*     ** Do the rest of the initializations     */    for(i = 0; i < AG7100_NMACS; i++)    {        mac = kmalloc(sizeof(ag7100_mac_t), GFP_KERNEL);        if (!mac)        {            printk(MODULE_NAME ": unable to allocate mac\n");            return 1;        }        memset(mac, 0, sizeof(ag7100_mac_t));        mac->mac_unit               =  i;        mac->mac_base               =  ag7100_mac_base(i);        mac->mac_irq                =  ag7100_mac_irq(i);        ag7100_macs[i]              =  mac;        spin_lock_init(&mac->mac_lock);        /*        * out of memory timer        */        init_timer(&mac->mac_oom_timer);        mac->mac_oom_timer.data     = (unsigned long)mac;        mac->mac_oom_timer.function = ag7100_oom_timer;        /*        * watchdog task        */        INIT_WORK(&mac->mac_tx_timeout, ag7100_tx_timeout_task, mac);        dev = alloc_etherdev(0);        if (!dev)        {            kfree(mac);            printk("%s Freeing at 0x%lx\n",__func__,(unsigned long) mac);            printk(MODULE_NAME ": unable to allocate etherdev\n");            return 1;        }        mac->mac_dev         =  dev;        dev->get_stats       =  ag7100_get_stats;        dev->open            =  ag7100_open;        dev->stop            =  ag7100_stop;        dev->hard_start_xmit =  ag7100_hard_start;#ifdef CONFIG_ATHRS26_PHY	          dev->do_ioctl        =  ag7100_do_ioctl;#else        dev->do_ioctl        =  NULL;#endif        dev->poll            =  ag7100_poll;        dev->weight          =  AG7100_NAPI_WEIGHT;        dev->tx_timeout      =  ag7100_tx_timeout;        dev->priv            =  mac;        ag7100_get_default_macaddr(mac, dev->dev_addr);        if (register_netdev(dev))        {            printk(MODULE_NAME ": register netdev failed\n");            goto failed;        }        ag7100_reg_rmw_set(mac, AG7100_MAC_CFG1, AG7100_MAC_CFG1_SOFT_RST);        udelay(20);        mask = ag7100_reset_mask(mac->mac_unit);        /*        * put into reset, hold, pull out.        */        ar7100_reg_rmw_set(AR7100_RESET, mask);        mdelay(100);        ar7100_reg_rmw_clear(AR7100_RESET, mask);        mdelay(100);    }    ag7100_trc_init();#if defined(CONFIG_ATHRS26_PHY)     athrs26_reg_dev(ag7100_macs);#endif        return 0;failed:    for(i = 0; i < AG7100_NMACS; i++)    {        if (!ag7100_macs[i])             continue;        if (ag7100_macs[i]->mac_dev)             free_netdev(ag7100_macs[i]->mac_dev);        kfree(ag7100_macs[i]);        printk("%s Freeing at 0x%lx\n",__func__,(unsigned long) ag7100_macs[i]);    }    return 1;}static void __exitag7100_cleanup(void){    int i;    for(i = 0; i < AG7100_NMACS; i++)    {        unregister_netdev(ag7100_macs[i]->mac_dev);        free_netdev(ag7100_macs[i]->mac_dev);        kfree(ag7100_macs[i]);        printk("%s Freeing at 0x%lx\n",__func__,(unsigned long) ag7100_macs[i]);    }    printk(MODULE_NAME ": cleanup done\n");}module_init(ag7100_init);module_exit(ag7100_cleanup);

⌨️ 快捷键说明

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