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

📄 dm9000.c

📁 开发板用的事博创的arm2410-s
💻 C
📖 第 1 页 / 共 3 页
字号:
                                    *(ptr+1)    = tmpdata >> 16;
                                    break;
                          default:
                                    break;
                        }
                /* Packet status check */
                if (rx.desc.status & 0xbf)
                {
                        GoodPacket = FALSE;
                        if (rx.desc.status & 0x01) 
                        {
                                db->stats.rx_fifo_errors++;
                                printk("<RX FIFO error>\n");
                        }
                        if (rx.desc.status & 0x02) 
                        {
                                db->stats.rx_crc_errors++;
                                printk("<RX CRC error>\n");
                        }
                        if (rx.desc.status & 0x80) 
                        {
                                db->stats.rx_length_errors++;
                                printk("<RX Length error>\n");
                        }
                        if (rx.desc.status & 0x08)
                                printk("<Physical Layer error>\n");
                }
                if (!GoodPacket)
                {
                        // drop this packet!!!
                        switch (db->io_mode)
                        {
                                case DM9KS_BYTE_MODE:
                                         for (i=0; i<rx.desc.length; i++)
                                                GETB(db->io_data);
                                        break;
                                case DM9KS_WORD_MODE:
                                        tmplen = (rx.desc.length + 1) / 2;
                                        for (i = 0; i < tmplen; i++)
                                                GETW(db->io_data);
                                        break;
                                case DM9KS_DWORD_MODE:
                                        tmplen = (rx.desc.length + 3) / 4;
                                        for (i = 0; i < tmplen; i++)
                                                GETL(db->io_data);
                                        break;
                        }
                        continue;/*next the packet*/
                }
                
                skb = dev_alloc_skb(rx.desc.length+4);
                if (skb == NULL )
                { 
                        printk(KERN_INFO "%s: Memory squeeze.\n", dev->name);
                        /*re-load the value into Memory data read address register*/
                        iow(db,DM9KS_MDRAH,MDRAH);
                        iow(db,DM9KS_MDRAL,MDRAL);
                        return;
                }
                else
                {
                        /* Move data from DM9000 */
                        skb->dev = dev;
                        skb_reserve(skb, 2);
                        rdptr = (u8*)skb_put(skb, rx.desc.length - 4);
                        
                        /* Read received packet from RX SARM */
                        switch (db->io_mode)
                        {
                                case DM9KS_BYTE_MODE:
                                         for (i=0; i<rx.desc.length; i++)
                                                rdptr[i]=GETB(db->io_data);
                                        break;
                                case DM9KS_WORD_MODE:
                                        tmplen = (rx.desc.length + 1) / 2;
                                        for (i = 0; i < tmplen; i++)
                                                ((u16 *)rdptr)[i] = GETW(db->io_data);
                                        break;
                                case DM9KS_DWORD_MODE:
                                        tmplen = (rx.desc.length + 3) / 4;
                                        for (i = 0; i < tmplen; i++)
                                                ((u32 *)rdptr)[i] = GETL(db->io_data);
                                        break;
                        }
                
                        /* Pass to upper layer */
                        skb->protocol = eth_type_trans(skb,dev);
                        netif_rx(skb);
                        dev->last_rx=jiffies;
                        db->stats.rx_packets++;
                        db->stats.rx_bytes += rx.desc.length;
                        db->cont_rx_pkt_cnt++;
                                
                        if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)
                        {
                                dmfe_tx_done(0);
                                break;
                        }
                }
                        
        }while((rxbyte & 0x01) == DM9KS_PKT_RDY);
             
}

/*
  Set DM9000A/DM9010 multicast address
*/
static void dm9000_hash_table(struct net_device *dev)
{
        board_info_t *db = (board_info_t *)dev->priv;
        struct dev_mc_list *mcptr = dev->mc_list;
        int mc_cnt = dev->mc_count;
        u32 hash_val;
        u16 i, oft, hash_table[4];
       
        /* Set Node address */
        for (i = 0, oft = 0x10; i < 6; i++, oft++)
                iow(db, oft, dev->dev_addr[i]);
        /* Clear Hash Table */
        for (i = 0; i < 4; i++)
                hash_table[i] = 0x0;
        /* broadcast address */
        hash_table[3] = 0x8000;
        /* the multicast address in Hash Table : 64 bits */
        for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
                hash_val = cal_CRC((char *)mcptr->dmi_addr, 6, 0) & 0x3f; 
                hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
        }
        /* Write the hash table to MAC MD table */
        for (i = 0, oft = 0x16; i < 4; i++) {
                iow(db, oft++, hash_table[i] & 0xff);
                iow(db, oft++, (hash_table[i] >> 8) & 0xff);
        }
}
/*
  Calculate the CRC valude of the Rx packet
  flag = 1 : return the reverse CRC (for the received packet CRC)
         0 : return the normal CRC (for Hash Table index)
*/
static unsigned long cal_CRC(unsigned char * Data, unsigned int Len, u8 flag)
{
        
        u32 crc = ether_crc_le(Len, Data);
        if (flag) 
                return ~crc;
                
        return crc;
         
}
/*
   Read a byte from I/O port
*/
static u8 ior(board_info_t *db, int reg)
{
        PUTB(reg, db->io_addr);
        return GETB(db->io_data);
}
/*
   Write a byte to I/O port
*/
static void iow(board_info_t *db, int reg, u8 value)
{
        PUTB(reg, db->io_addr);
        PUTB(value, db->io_data);
}
/*
   Read a word from phyxcer
*/
static u16 phy_read(board_info_t *db, int reg)
{
        /* Fill the phyxcer register into REG_0C */
        iow(db, DM9KS_EPAR, DM9KS_PHY | reg);
        iow(db, DM9KS_EPCR, 0xc);  /* Issue phyxcer read command */
        udelay(100);   /* Wait read complete */
        iow(db, DM9KS_EPCR, 0x0);  /* Clear phyxcer read command */
        /* The read data keeps on REG_0D & REG_0E */
        return ( ior(db, DM9KS_EPDRH) << 8 ) | ior(db, DM9KS_EPDRL);
        
}
/*
   Write a word to phyxcer
*/
static void phy_write(board_info_t *db, int reg, u16 value)
{
        /* Fill the phyxcer register into REG_0C */
        iow(db, DM9KS_EPAR, DM9KS_PHY | reg);
        /* Fill the written data into REG_0D & REG_0E */
        iow(db, DM9KS_EPDRL, (value & 0xff));
        iow(db, DM9KS_EPDRH, ( (value >> 8) & 0xff));
        iow(db, DM9KS_EPCR, 0xa); /* Issue phyxcer write command */
        udelay(500);   /* Wait write complete */
        iow(db, DM9KS_EPCR, 0x0); /* Clear phyxcer write command */
}
/*
 * probe the driver
 */
static int __init dm9k_drv_probe(struct platform_device *pdev)
{
        struct net_device *ndev;
        unsigned long base;
        unsigned int *addr = NULL;
        int ret = -ENODEV;
        ndev = alloc_etherdev(sizeof(struct board_info));
        if (!ndev) {
                printk("%s: could not allocate device.\n", CARDNAME);
                return -ENOMEM;
        }
        
        ndev->dma = (unsigned char)-1;
        if (pdev->num_resources < 2 || pdev->num_resources > 3) {
                printk("DM9000: Wrong num of resources %d\n", pdev->num_resources);
                ret = -ENODEV;
                goto out;
        }
        base = pdev->resource[0].start;
        ndev->irq = pdev->resource[1].start;
        /*
         * Request the regions.
         */
        if (!request_mem_region(base, 4, ndev->name)) {
                ret = -EBUSY;
                goto out;
        }

        addr = ioremap(base, 4);
        if (!addr) {
                ret = -ENOMEM;
                goto release_mem;
        }
        ret = dm9k_probe(ndev, (unsigned long)addr);
        if (ret != 0) {
         iounmap(addr);
 release_mem:
                release_mem_region(base, 4);
 out:
                printk("%s: not found (%d).\n", CARDNAME, ret);
                kfree(ndev);
        }
        return ret;
}
static int dm9k_drv_remove(struct platform_device *pdev)
{
       
        return 0;
}
static int dm9k_drv_suspend(struct platform_device *dev, pm_message_t state )
{
        return 0;
}
static int dm9k_drv_resume(struct platform_device *dev)
{
        return 0;
}

static struct platform_driver dm9k_driver = {
        .probe  = dm9k_drv_probe,
        .remove  = dm9k_drv_remove,
        .suspend = dm9k_drv_suspend,
        .resume  = dm9k_drv_resume,
 .driver         = {
   .name = "s3c2410-dm9ks",
   .owner = THIS_MODULE,
 }
};
static void  uptech_dm9k_init(void)
{
  u32 bwscon;
  bwscon = __raw_readl(S3C2410_BWSCON);
  bwscon &= ~(S3C2410_BWSCON_WS2|S3C2410_BWSCON_ST2|S3C2410_BWSCON_DW2_32);
  bwscon |= (S3C2410_BWSCON_ST2|S3C2410_BWSCON_DW2_16);
  __raw_writel(bwscon, S3C2410_BWSCON);
  __raw_writel(S3C2410_BANKCON_Tacs4|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh4|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm, S3C2410_BANKCON2);
  set_irq_type(IRQ_EINT2,IRQ_TYPE_LEVEL_HIGH);
  s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2);
  s3c2410_gpio_pullup(S3C2410_GPF2, 0);
  printk(KERN_INFO "Board init for dm9000a finished!\n");
}
/* Description: 
   when user used insmod to add module, system invoked init_module()
   to initilize and register.
*/
int dm9k_init_module(void)
{
        printk("*************** DM9000: dm9k_init_module\n");
        switch(mode) {
                case DM9KS_10MHD:
                case DM9KS_100MHD:
                case DM9KS_10MFD:
                case DM9KS_100MFD:
                        media_mode = mode;
                        break;
                default:
                        media_mode = DM9KS_AUTO;
        }
       uptech_dm9k_init();
       return platform_driver_register(&dm9k_driver);
}
/* Description: 
   when user used rmmod to delete module, system invoked clean_module()
   to  un-register DEVICE.
*/
void __exit dm9k_cleanup_module(void)
{
        struct net_device *dev = dmfe_dev;
        
        unregister_netdev(dmfe_dev);
        release_region(dev->base_addr, 2);
        free_netdev(dev);     
}
MODULE_LICENSE ("GPL");

module_init(dm9k_init_module);
module_exit(dm9k_cleanup_module);

⌨️ 快捷键说明

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