打印
[嵌入式linux]

linux PCI 转串口驱动程序

[复制链接]
1866|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
haibin2011|  楼主 | 2014-7-29 21:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*PCI驱动*/
static int prj750_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{

        resource_size_t base = 0;
        void *map_base = NULL;
        u8 bar = 0;
        int ret = 0;
       
        DBG_POS();

        if ((NULL == pdev)||(NULL == id))
                return RETVALUE_FAILURE;

        ret = pci_enable_device(pdev);
        if (bar) {
                printk(KERN_ERR"###ERR: Can't enable  Device Vendor = 0x%x, Device = 0x%x\n",\
                                                                 id->vendor, id->device);
                goto err_pci_enable;
        }

        for (bar = 0; bar < PCI_ROM_RESOURCE; bar++) {
                if ((base = pci_resource_start(pdev, bar)) &&
                    (PRJ750_PCI_BAR_SIZE == pci_resource_len(pdev, bar))){
                        break;
                }
        }

        if (PCI_ROM_RESOURCE == bar) {
                printk(KERN_ERR"###ERR: No Resource for the Device Vendor = %x, Device = %x\n", \
                id->vendor, id->device);
                ret = -ENODEV;
                goto err_enum_resource;
        }
       
        ret = pci_request_regions(pdev, PRJ750_DRV_NAME);
        if(ret) {
               
                printk(KERN_ERR"###ERR: Can't request region %s\n", PRJ750_DRV_NAME);
                goto err_request_region;
        }

        map_base = ioremap(base, PRJ750_DUAL_RAM_SIZE);
        if (NULL == map_base) {

                printk(KERN_ERR"###ERR: Can't ioremap  base = 0x%x\n", base);
                ret = -ENOMEM;
                goto err_map_resource;
        }               
               
        prj750_dev.size = PRJ750_DUAL_RAM_SIZE;
        prj750_dev.virt_base = map_base;
        prj750_dev.phys_base = base;
        prj750_dev.dev = &pdev->dev;

        ret = prj750_uart_init(&pdev->dev, &prj750_dev);
        if (0 > ret) {

                printk(KERN_ERR"###ERR: Can not init uart!\n");
                ret = -ENODEV;
                goto err_uart_init;
        }


        return RETVALUE_SUCCESS;

err_uart_init:
        pci_release_regions(pdev);
        iounmap(map_base);

err_request_region:
err_map_resource:
err_enum_resource:
        pci_release_regions(pdev);
        pci_disable_device(pdev);

err_pci_enable:
        return ret;
}

/*调用串口初始化函数*/
int prj750_uart_init(struct device *dev, struct prj750_dev *prj750_dev)
{

        int ret = 0;
        int port_register_count = 0;

        if ((NULL == dev)||(NULL == prj750_dev))
                return NULL;
       
        prj750_uart_ports = kzalloc(PRJ750_UART_NR * sizeof(struct prj750_uart_port),GFP_KERNEL);       
        if (NULL == prj750_uart_ports) {
                printk(KERN_ERR"###ERR: kzalloc prj750_uart_ports failed!\n");
                ret = -ENOMEM;
                goto err_ret;
        }

        ret = prj750_uart_init_all(prj750_dev, PRJ750_UART_NR);
        if (RETVALUE_SUCCESS != ret) {
                printk(KERN_ERR"###ERR: Can't not init %d uart port!\n",\
                                                        PRJ750_UART_NR);
                goto err_uart_init;
        }
       
        ret = uart_register_driver(&prj750_uart_drv);
        if (RETVALUE_SUCCESS != ret) {
                printk(KERN_ERR"###ERR: Can't register uart driver!\n");
                goto err_uart_drv_register;
        }

        ret = prj750_register_all_dev(&prj750_uart_drv, PRJ750_UART_NUM, &port_register_count);
        if (ret < 0) {
                printk(KERN_ERR"###ERR: Register all dev failure!\n");
                goto err_uart_dev_register;
        }
        return RETVALUE_SUCCESS;


err_uart_dev_register:
        uart_unregister_driver(&prj750_uart_drv);       
        prj750_uart_deinit_all(prj750_dev);       
        kfree(prj750_uart_ports);

err_uart_drv_register:
        prj750_uart_deinit_all(prj750_dev);       
        kfree(prj750_uart_ports);

err_uart_init:
        kfree(prj750_uart_ports);

err_ret:
        return ret;
}

static int prj750_uart_init_one(const struct prj750_dev *dev, const int port)
{
        struct prj750_uart_port *prj750_port = NULL;
        char *base = NULL;

        DBG_POS();
       
        if (NULL == dev)
                return NULL;

        base = dev->virt_base;
        prj750_port = prj750_uart_ports + port;
       
        prj750_port->receive_base = base + port * PRJ750_RAM_SZ_PER_PORT;
        prj750_port->send_base = prj750_port->receive_base + PRJ750_UART_COUNT_TX;
        prj750_port->receive_size = PRJ750_UART_MAX_RX_SZ;
        prj750_port->send_size = PRJ750_UART_MAX_TX_SZ;
       
        prj750_port->open = PRJ750_UART_CLOSE;
       
       
        prj750_port->conf.baudrate = PRJ750_UART_BAUDRATE115200;
        prj750_port->conf.word = PRJ750_UART_DATAWIDTH_8BIT;
        prj750_port->conf.parity = PRJ750_UART_PARITY_NONE;
        prj750_port->conf.stopbit = PRJ750_UART_STOPBIT_1;
        prj750_port->conf.protocol = PRJ750_UART_PROT_RS422;
        prj750_port->conf.mode = PRJ750_UART_OP_NORMAL;
       
        if (dev->dev)
                prj750_port->port.dev = dev->dev;
       
       
        prj750_port->port.mapbase = dev->phys_base + port * PRJ750_RAM_SZ_PER_PORT;
        prj750_port->port.membase = prj750_port->receive_base + port * PRJ750_RAM_SZ_PER_PORT;
        prj750_port->port.ops = &prj750_uart_ops;
        prj750_port->port.iotype = UPIO_MEM;
        prj750_port->port.flags = UPF_BOOT_AUTOCONF;
        prj750_port->port.type = PORT_PRJ750;
        prj750_port->port.line = port;
        prj750_port->port.fifosize = PRJ750_RAM_SZ_PER_PORT;

        return RETVALUE_SUCCESS;
}

static int prj750_register_all_dev(struct uart_driver* drv, const int num, int *ss)
{
        int port = 0;
        int ret = 0;

        if (NULL == drv)
                return NULL;
       
        for (port = 0; port < num; port++) {       
                ret = uart_add_one_port(drv, &(prj750_uart_ports + port)->port);
                if (ret < 0) {
                        printk(KERN_ERR"###ERR: uart_add_one_port failure!\n");
                        break;
                }
        }         
       
        *ss = port;
        return ret;
}


static struct uart_ops        prj750_uart_ops = {
        .tx_empty = prj750_tx_empty,
        .set_mctrl = prj750_set_mctrl,
        .get_mctrl = prj750_get_mctrl,
        .stop_tx = prj750_stop_tx,
        .start_tx = prj750_start_tx,
        .send_xchar = prj750_send_xchar,
        .stop_rx = prj750_stop_rx,
        .enable_ms = prj750_enable_ms,
        .break_ctl = prj750_break_ctl,
        .startup = prj750_startup,
        .shutdown = prj750_shutdown,
        .flush_buffer = prj750_flush_buffer,
        .set_termios = prj750_set_termios,
        .set_ldisc = prj750_set_ldisc,
        .set_wake = prj750_set_wake,
        .type = prj750_type,
        .release_port = prj750_release_port,
        .request_port = prj750_request_port,
        .config_port = prj750_config_port,
        .verify_port = prj750_verify_port,
        .ioctl = prj750_ioctl,       
};

static struct uart_driver prj750_uart_drv = {
        .owner = THIS_MODULE,
        .driver_name = PRJ750_UART_DRV_NAME,
        .dev_name = PRJ750_UART_DEV_NAME,
        .major        = PRJ750_UART_MAJOR,
        .minor = PRJ750_UART_MINOR_START,
        .nr = PRJ750_UART_NR,
};
求助:请各位大神帮忙!
一、基本信息:
1.项目是PCI转串口卡;
2.内核版本是2.6.32;
3.硬件平台是x86架构。
二、遇到的奇怪问题:
1.insmod 驱动之后,用lsmod 看到驱动应用数为2,未显示调用者;
2.insmod 驱动之后,自动调用prj750_startup->prj750_set_termios->prj750_start_tx函数,并发出了24个数字,分别是94、64、94、67等等,此时只是加载驱动,并没有执行应用程序;
3.疑问是,没有执行应用程序,是线程规程为什么会自动调用prj750_startup->prj750_set_termios->prj750_start_tx,在xmit环形缓冲区的数据是怎么得到的呢?

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

68

帖子

3

粉丝