zoukankan      html  css  js  c++  java
  • [转]inux3.1.8内核移植到gt2440CS8900A驱动移植

    一.   根据原理图,确认网卡的地址和中断号
    地址:0x19000000

    中断号: EINT9

    二.   修改drivers/net/cs89x0.c,指定CS8900A使用的资源
    #elif defined(CONFIG_ARCH_S3C2410)
    #include
    #include3c2410/regs-mem.h>
    #define S3C24XX_PA_CS8900   0x19000000
    static unsigned int netcard_portlist[] __initdate = {0, 0};
    static unsigned int cs8900_irq_map[] = {IRQ_EINT9, 0, 0, 0};
    #else

    三.   修改入口函数cs89x0_probe
    1.      
    #if defined(CONFIG_ARCH_S3C2410)
           unsigned int oldval_bwscon;
           unsigned int oldval_bankcon3;
    #endif

    2.  设置MAC,总线宽度等:

    #if defined(CONFIG_ARCH_S3C2410)if(netcard_portlist[0])return -ENODEV;netcard_portlist[0] = (unsigned int)ioremap(S3C24XX_PA_CS8900, SZ_1M) + 0x300;
    dev->dev_addr[0] = 0x08;dev->dev_addr[1] = 0x89;dev->dev_addr[2] = 0x89;dev->dev_addr[3] = 0x89;dev->dev_addr[4] = 0x89;dev->dev_addr[5] = 0x89;
    oldval_bwscon = *((volatile unsigned int *)S3C2410_BWSCON);*((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<12)) | S3C2410_BWSCON_DW3_16 | S3C2410_BWSCON_WS3 | S3C2410_BWSCON_ST3;oldval_bankcon3 = *((volatile unsigned int *)S3C2410_BANKCON3);*((volatile unsigned int *)S3C2410_BANKCON3) = 0x1f7c;

    #endif

    3.   出错退出

    out:
    #if defined(CONFIG_ARCH_S3C2410)
           iounmap(netcard_portlist[0]);
           netcard_portlist[0] = 0;
           *((volatile unsigned int *)S3C2410_BWSCON) = oldval_bwscon;
            *((volatile unsigned int *)S3C2410_BANKCON3) = oldval_bankcon3;
    #endif

           free_netdev(dev);

    修改后函数cs89x0_probe为:

    struct net_device * __init cs89x0_probe(int unit)

    {

    struct net_device *dev = alloc_etherdev(sizeof(struct net_local));

    unsigned *port;

    int err = 0;

    int irq;

    unsigned int io;  /*修改*/

    /*添加*/

    #if defined(CONFIG_ARCH_S3C2410)  

    unsigned int oldval_bwscon;

    unsigned int oldval_bankcon3;

    #endif

    if (!dev)

    return ERR_PTR(-ENODEV);

    sprintf(dev->name, "eth%d", unit);

    netdev_boot_setup_check(dev);

    io = dev->base_addr;

    irq = dev->irq;

    /*添加*/

    #if defined(CONFIG_ARCH_S3C2410)    

    if(netcard_portlist[0])

    return -ENODEV;

    netcard_portlist[0] = (unsigned int)ioremap(S3C24XX_PA_CS8900, SZ_1M) + 0x300;

    dev->dev_addr[0] = 0x08;

    dev->dev_addr[1] = 0x89;

    dev->dev_addr[2] = 0x89;

    dev->dev_addr[3] = 0x89;

    dev->dev_addr[4] = 0x89;

    dev->dev_addr[5] = 0x89;

    oldval_bwscon = *((volatile unsigned int *)S3C2410_BWSCON);

    *((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<12)) | S3C2410_BWSCON_DW3_16 | S3C2410_BWSCON_WS3 | S3C2410_BWSCON_ST3;

    oldval_bankcon3 = *((volatile unsigned int *)S3C2410_BANKCON3);

    *((volatile unsigned int *)S3C2410_BANKCON3) = 0x1f7c;

    #endif

    if (net_debug)

    printk("cs89x0:cs89x0_probe(0x%x)\n", io);

    if (io > 0x1ff){/* Check a single specified location. */

    err = cs89x0_probe1(dev, io, 0);

    } else if (io != 0) {/* Don't probe at all. */

    err = -ENXIO;

    } else {

    for (port = netcard_portlist; *port; port++) {

    if (cs89x0_probe1(dev, *port, 0) == 0)

    break;

    dev->irq = irq;

    }

    if (!*port)

    err = -ENODEV;

    }

    if (err)

    goto out;

    return dev;

    out:

    #if defined(CONFIG_ARCH_S3C2410)   /*添加*/

    iounmap(netcard_portlist[0]);

    netcard_portlist[0] = 0;

    *((volatile unsigned int *)S3C2410_BWSCON) = oldval_bwscon;

    *((volatile unsigned int *)S3C2410_BANKCON3) = oldval_bankcon3;

    #endif

    free_netdev(dev);

    printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected.  Be sure to disable PnP with SETUP\n");

    return ERR_PTR(err);

    }

    四.   注册中断处理程序,指定中断触发方式,修改net_open函数
    #if 0
                  writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
    #endif
                  write_irq(dev, lp->chip_type, dev->irq);

    #if defined(CONFIG_ARCH_S3C2410)
                  ret = request_irq(dev->irq, &net_interrupt, IRQF_TRIGGER_RISING, dev->name, dev);
    #else
                  ret = request_irq(dev->irq, &net_interrupt, 0, dev->name, dev);
    #endif

    五.   在drivers/net/cs89x0.c中适当的位置加上CONFIG_ARCH_S3C2410宏编译开关,可以参考CONFIG_ARCH_PNX010X:
    1. net_open(struct net_device *dev)
    {
           struct net_local *lp = netdev_priv(dev);
           int result = 0;
           int i;
           int ret;

    2. #if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) && !defined(CONFIG_ARCH_S3C2410)
                  if (((1 irq) & lp->irq_map) == 0) {
                         printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
                                   dev->name, dev->irq, lp->irq_map);
                         ret = -EAGAIN;
                         goto bad_out;
                  }
    #endif

    3. #if defined(CONFIG_ARCH_PNX010X) || defined(CONFIG_ARCH_S3C2410)
           result = A_CNF_10B_T;
    #endif

    修改后net_open为:

    static int

    net_open(struct net_device *dev)

    {

    struct net_local *lp = netdev_priv(dev);

    int result = 0;

    int i;

    int ret;

    if (dev->irq < 2) {

    /* Allow interrupts to be generated by the chip */

    /* Cirrus' release had this: */

    #if 0

    writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );

    #endif

    /* And 2.3.47 had this: */

    writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);

    for (i = 2; i < CS8920_NO_INTS; i++) {

    if ((1 << i) & lp->irq_map) {

    if (request_irq(i, net_interrupt, 0, dev->name, dev) == 0) {

    dev->irq = i;

    write_irq(dev, lp->chip_type, i);

    /* writereg(dev, PP_BufCFG, GENERATE_SW_INTERRUPT); */

    break;

    }

    }

    }

    if (i >= CS8920_NO_INTS) {

    writereg(dev, PP_BusCTL, 0);/* disable interrupts. */

    printk(KERN_ERR "cs89x0: can't get an interrupt\n");

    ret = -EAGAIN;

    goto bad_out;

    }

    }

    else

    {

    #ifndef CONFIG_CS89x0_NONISA_IRQ

    if (((1 << dev->irq) & lp->irq_map) == 0) {

    printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",

                                   dev->name, dev->irq, lp->irq_map);

    ret = -EAGAIN;

    goto bad_out;

    }

    #endif

    /* FIXME: Cirrus' release had this: */

    writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );

    /* And 2.3.47 had this: */

    #if 0

    writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);

    #endif

    write_irq(dev, lp->chip_type, dev->irq);

    //ret = request_irq(dev->irq, net_interrupt, 0, dev->name, dev);  /*屏蔽掉*/

    #if defined(CONFIG_ARCH_S3C2410)                                          /*添加*/

    ret = request_irq(dev->irq, &net_interrupt, IRQF_TRIGGER_RISING, dev->name, dev);

    #else

    ret = request_irq(dev->irq, &net_interrupt, 0, dev->name, dev);

    #endif

    if (ret) {

    printk(KERN_ERR "cs89x0: request_irq(%d) failed\n", dev->irq);

    goto bad_out;

    }

    }

    #if ALLOW_DMA

    if (lp->use_dma) {

    if (lp->isa_config & ANY_ISA_DMA) {

    unsigned long flags;

    lp->dma_buff = (unsigned char *)__get_dma_pages(GFP_KERNEL,

    get_order(lp->dmasize * 1024));

    if (!lp->dma_buff) {

    printk(KERN_ERR "%s: cannot get %dK memory for DMA\n", dev->name, lp->dmasize);

    goto release_irq;

    }

    if (net_debug > 1) {

    printk("%s: dma %lx %lx\n",

    dev->name,

    (unsigned long)lp->dma_buff,

    (unsigned long)isa_virt_to_bus(lp->dma_buff));

    }

    if ((unsigned long) lp->dma_buff >= MAX_DMA_ADDRESS ||

       !dma_page_eq(lp->dma_buff, lp->dma_buff+lp->dmasize*1024-1)) {

    printk(KERN_ERR "%s: not usable as DMA buffer\n", dev->name);

    goto release_irq;

    }

    memset(lp->dma_buff, 0, lp->dmasize * 1024);/* Why? */

    if (request_dma(dev->dma, dev->name)) {

    printk(KERN_ERR "%s: cannot get dma channel %d\n", dev->name, dev->dma);

    goto release_irq;

    }

    write_dma(dev, lp->chip_type, dev->dma);

    lp->rx_dma_ptr = lp->dma_buff;

    lp->end_dma_buff = lp->dma_buff + lp->dmasize*1024;

    spin_lock_irqsave(&lp->lock, flags);

    disable_dma(dev->dma);

    clear_dma_ff(dev->dma);

    set_dma_mode(dev->dma, DMA_RX_MODE); /* auto_init as well */

    set_dma_addr(dev->dma, isa_virt_to_bus(lp->dma_buff));

    set_dma_count(dev->dma, lp->dmasize*1024);

    enable_dma(dev->dma);

    spin_unlock_irqrestore(&lp->lock, flags);

    }

    }

    #endif/* ALLOW_DMA */

    /* set the Ethernet address */

    for (i=0; i < ETH_ALEN/2; i++)

    writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));

    /* while we're testing the interface, leave interrupts disabled */

    writereg(dev, PP_BusCTL, MEMORY_ON);

    /* Set the LineCTL quintuplet based on adapter configuration read from EEPROM */

    if ((lp->adapter_cnf & A_CNF_EXTND_10B_2) && (lp->adapter_cnf & A_CNF_LOW_RX_SQUELCH))

                    lp->linectl = LOW_RX_SQUELCH;

    else

                    lp->linectl = 0;

            /* check to make sure that they have the "right" hardware available */

    switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {

    case A_CNF_MEDIA_10B_T: result = lp->adapter_cnf & A_CNF_10B_T; break;

    case A_CNF_MEDIA_AUI:   result = lp->adapter_cnf & A_CNF_AUI; break;

    case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;

            default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);

            }

    #if defined(CONFIG_ARCH_PNX010X) || defined(CONFIG_ARCH_S3C2410)   /*添加*/

    result = A_CNF_10B_T;

    #endif

            if (!result) {

                    printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name);

    release_dma:

    #if ALLOW_DMA

    free_dma(dev->dma);

    release_irq:

    release_dma_buff(lp);

    #endif

                    writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));

                    free_irq(dev->irq, dev);

    ret = -EAGAIN;

    goto bad_out;

    }

            /* set the hardware to the configured choice */

    switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {

    case A_CNF_MEDIA_10B_T:

                    result = detect_tp(dev);

                    if (result==DETECTED_NONE) {

                            printk(KERN_WARNING "%s: 10Base-T (RJ-45) has no cable\n", dev->name);

                            if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */

                                    result = DETECTED_RJ45H; /* Yes! I don't care if I see a link pulse */

                    }

    break;

    case A_CNF_MEDIA_AUI:

                    result = detect_aui(dev);

                    if (result==DETECTED_NONE) {

                            printk(KERN_WARNING "%s: 10Base-5 (AUI) has no cable\n", dev->name);

                            if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */

                                    result = DETECTED_AUI; /* Yes! I don't care if I see a carrrier */

                    }

    break;

    case A_CNF_MEDIA_10B_2:

                    result = detect_bnc(dev);

                    if (result==DETECTED_NONE) {

                            printk(KERN_WARNING "%s: 10Base-2 (BNC) has no cable\n", dev->name);

                            if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */

                                    result = DETECTED_BNC; /* Yes! I don't care if I can xmit a packet */

                    }

    break;

    case A_CNF_MEDIA_AUTO:

    writereg(dev, PP_LineCTL, lp->linectl | AUTO_AUI_10BASET);

    if (lp->adapter_cnf & A_CNF_10B_T)

    if ((result = detect_tp(dev)) != DETECTED_NONE)

    break;

    if (lp->adapter_cnf & A_CNF_AUI)

    if ((result = detect_aui(dev)) != DETECTED_NONE)

    break;

    if (lp->adapter_cnf & A_CNF_10B_2)

    if ((result = detect_bnc(dev)) != DETECTED_NONE)

    break;

    printk(KERN_ERR "%s: no media detected\n", dev->name);

    goto release_dma;

    }

    switch(result) {

    case DETECTED_NONE:

    printk(KERN_ERR "%s: no network cable attached to configured media\n", dev->name);

    goto release_dma;

    case DETECTED_RJ45H:

    printk(KERN_INFO "%s: using half-duplex 10Base-T (RJ-45)\n", dev->name);

    break;

    case DETECTED_RJ45F:

    printk(KERN_INFO "%s: using full-duplex 10Base-T (RJ-45)\n", dev->name);

    break;

    case DETECTED_AUI:

    printk(KERN_INFO "%s: using 10Base-5 (AUI)\n", dev->name);

    break;

    case DETECTED_BNC:

    printk(KERN_INFO "%s: using 10Base-2 (BNC)\n", dev->name);

    break;

    }

    /* Turn on both receive and transmit operations */

    writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);

    /* Receive only error free packets addressed to this card */

    lp->rx_mode = 0;

    writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);

    lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;

    if (lp->isa_config & STREAM_TRANSFER)

    lp->curr_rx_cfg |= RX_STREAM_ENBL;

    #if ALLOW_DMA

    set_dma_cfg(dev);

    #endif

    writereg(dev, PP_RxCFG, lp->curr_rx_cfg);

    writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |

    TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);

    writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |

    #if ALLOW_DMA

    dma_bufcfg(dev) |

    #endif

    TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);

    /* now that we've got our act together, enable everything */

    writereg(dev, PP_BusCTL, ENABLE_IRQ

    | (dev->mem_start?MEMORY_ON : 0) /* turn memory on */

    #if ALLOW_DMA

    | dma_busctl(dev)

    #endif);

            netif_start_queue(dev);

    if (net_debug > 1)

    printk("cs89x0: net_open() succeeded\n");

    return 0;

    bad_out:

    return ret;

    }

    六.   修改cs89x0_probe函数中的  int io 为 unsigned int io;

    七.   内核配置文件修改:
    修改drivers/net/kconfig中的描述

    config CS89x0

    tristate "CS89x0 support"

    depends on NET_ETHERNET && (ISA || EISA || MACH_IXDP2351 \

    || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440) ||ARCH_S3C2410

    ---help---

     Support for CS89x0 chipset based Ethernet cards. If you have a

     network (Ethernet) card of this type, say Y and read the

     Ethernet-HOWTO, available from

     <http://www.tldp.org/docs.html#howto> as well as

     <file:Documentation/networking/cs89x0.txt>.

     To compile this driver as a module, choose M here. The module

     will be called cs89x0.

    config CS89x0_NONISA_IRQ

    def_bool y

    depends on CS89x0 != n

    depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440 ||ARCH_S3C2410

    /*必须添加ARCH_S3C2410,否则出现eth0: IRQ 53 is not in our map of allowable IRQs, which is 1c20的错误*/

    八.   使用CS8900A网卡,在内核目录下执行make menuconfig后,选中

    Device Drivers --->

    [*] Network device support --->

    [*]Ethernet (10 or 100Mbit) --->

    < >   DM9000 support                                              

    <*>   CS89x0 support  

    九.编译

    编译出现一下的警告:

    drivers/net/cs89x0.c: In function 'cs89x0_probe':

    drivers/net/cs89x0.c:335: warning: return makes pointer from integer without a cast

    drivers/net/cs89x0.c:373: warning: passing argument 1 of '__iounmap' makes pointer from integer without a cast

    十.测试

    # ifconfig lo 127.0.0.1

    #ifconfig eth0 172.19.69.211

    #ping 172.19.69.254

    PING 172.19.69.254 (172.19.69.254): 56 data bytes                               

    64 bytes from 172.19.69.254: seq=0 ttl=64 time=1.552 ms                         

    64 bytes from 172.19.69.254: seq=1 ttl=64 time=1.018 ms                         

    64 bytes from 172.19.69.254: seq=2 ttl=64 time=1.028 ms                         

    64 bytes from 172.19.69.254: seq=3 ttl=64 time=1.003 ms                         

    64 bytes from 172.19.69.254: seq=4 ttl=64 time=0.998 ms                         

    64 bytes from 172.19.69.254: seq=5 ttl=64 time=1.019 ms                         

    64 bytes from 172.19.69.254: seq=6 ttl=64 time=0.972 ms                                                                                      

    --- 172.19.69.254 ping statistics ---                                           

    7 packets transmitted, 7 packets received, 0% packet loss                       

    round-trip min/avg/max = 0.972/1.084/1.552 ms  

    CS8900A驱动移植成功。

  • 相关阅读:
    目标检测应用化之web页面(YOLO、SSD等)
    传统候选区域提取方法
    非极大值抑制(Non-Maximum Suppression,NMS)
    Darknet windows移植(YOLO v2)
    线性判别分析 LDA
    SVM 支持向量机
    特征-相似度衡量
    布隆过滤器 Bloom Filter
    聚类算法
    图论--最大流
  • 原文地址:https://www.cnblogs.com/dolphi/p/2642151.html
Copyright © 2011-2022 走看看