dave_1981
驱动牛犊
驱动牛犊
  • 注册日期2004-12-27
  • 最后登录2005-03-03
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1438回复:7

请教关于寻找设备

楼主#
更多 发布于:2005-03-02 15:03
我初学,几乎一窍不通,我想请教各位大侠,能教我怎么去写程序来寻找硬件?

/*
1.block write
2.read or write size must be word align
3.only one rx buffer
*/

#define __KERNEL__
#define MODULE
#include<linux/kernel.h>
#include<linux/module.h>
#include<asm/io.h>
#include<linux/types.h>
#include<linux/pci.h>
#include<linux/fs.h>                        
#include<linux/errno.h>
#include<linux/wait.h>
#include<linux/sched.h>
#include<asm/uaccess.h>
#include<asm/semaphore.h>
#include<linux/ioctl.h>
#include<linux/time.h>
#include<asm/msr.h>

/***************************************************************************
 * Description:  Scatter-gather table
 */
#define ULONG unsigned long
#define USHORT unsigned short

struct  netb_card {    
    ULONG iobase; //iobaseAddr
    int irq;  
 
    void *dma_tx_buffer;
    void *dma_rx_buffer;  
    ULONG dma_tx_BaseAddr; //physical address correspond to dma_tx_buffer
    ULONG dma_rx_BaseAddr; //physical address correspond to dma_rx_buffer
    ULONG dma_tx_length;   //actual dma xfer length in DWORDS
    ULONG dma_rx_length;   //actual dma xfer length in DWORDS
    ULONG max_length;     // for ioctl get length
    
    USHORT rx_data_flag;      
    USHORT netb_major;             // for register use  
    USHORT netb_location;                //1:internel networks   0:externel networks
    char *name;        

    USHORT start_read;
    USHORT start_write;
    struct semaphore sem;
    int open_count;  
} *card ;


/*
 * PCI config Register offset
 */                        
#define REG_PCICMD          0x04    // command register
#define PCI_LTIMER          0x0d    //latency timer      

#define PCI_IOSEN           0x01    // Enable IO space
#define PCI_BMEN            0x04    // Enable IDE bus master  
#define PCI_CMD_WORDS       0x0145  // 0000 0001 0100 0101 Enable SERR_EN,PAR_ERR_EN,BUS_MST_EN,IO_SPACE_EN

// register define
#define BUS_MASTER_CMD    0x0      //pci bus master cmd register
#define BUS_MASTER_STATUS   0x2      //pci bus master status register
#define TX_BASE             0x4      //dma tx buffer initial address register
#define RX_BASE             0x8      //dma rx buffer initial address register
#define DMA_XFER_LENGTH     0x0c     //actual dma xfer length in DWORDS
#define SROM_CTL            0x10     // driver not use
#define MISC_CTL    0x14     // orther controls
#define TX_LENGTH    0x18     // dma tx length register in DWORDS

//bit define

//BUS_MASTER_STATUS
#define INT_MASK             0x04    //netb interrupt
#define DMA_TX               0x08    // 1:dma sending data           0:dma receiving data
//BUS_MASTER_CMD bit define
#define DMA_START_TX         0x01   //bus master cmmd register begin to send data
//MISC_CTL bit define
#define EN_RX                0x01

#define PCI_VENDOR_ID_netb  0x1103
#define PCI_DEVICE_ID_netb  0x0004
#define ORDER 8
#define MAX_LEN (1024*1024)     // read or write max length 1MB
#define TxCnt    10000

#define NET_LOC  1          //inside network

//define IOCTL command

#define NETBCTL_GET_LOC    _IOR(\'d\',0x11,0)
#define NETBCTL_GET_TSIZE   _IOR(\'d\',0x12,0)
#define NETBCTL_GET_LSIZE   _IOR(\'d\',0x13,0)

static DECLARE_WAIT_QUEUE_HEAD(rx_wq);
static DECLARE_WAIT_QUEUE_HEAD(tx_wq);

static void netb_interrupt(int irq, void *dev_id,struct pt_regs *regs);

static int netb_open(struct inode * inode,struct file *file);
ssize_t netb_read(struct file *filp,char *buf,size_t count,loff_t *f_pos);
ssize_t netb_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos);
static int netb_ioctl(struct inode *inode ,struct file *file,unsigned int cmd,unsigned long arg);
static int netb_release(struct inode *inode,struct file *file);


/*
device file operation interface
*/
static struct file_operations netb_fops ={
    read:    netb_read,
    write:   netb_write,
    ioctl:   netb_ioctl,
    open:    netb_open,
    release: netb_release,
};


int Init_netb(void)
{                    
    struct pci_dev *dev = NULL;    
    int result,index =0;      

    if( ! pci_present()) {
        printk(\"Init_netb pci not surported!\\n\");
        return -ENODEV;
    }
    dev = pci_find_device(PCI_VENDOR_ID_netb ,PCI_DEVICE_ID_netb,dev);
    if( ! dev ){
        printk(\"no  pci card specified!\\n\");
        return -ENODEV ;
    }
    if(pci_enable_device(dev))
        return -EIO;

    /*set dma mask */
    if( pci_set_dma_mask(dev,0xffffffff) )
        return -ENODEV;
    pci_set_master(dev);    

    if((card = kmalloc(sizeof(struct netb_card),GFP_KERNEL))==NULL){
        printk(KERN_ERR \"pci_netb:out of memory!\\n\");
        return -ENOMEM;
    }
    memset(card,0,sizeof(struct netb_card));  
    
    // read pci config info
    card->iobase = pci_resource_start(dev,0);    
    printk(\"pci iobase:%lx\\n\",card->iobase);
    // card->pci_id = pci_id->device;
    card->irq = dev->irq;      
  
    card->dma_tx_length = 0;
    card->dma_rx_length = 0;

    card->max_length = MAX_LEN;    
    card->rx_data_flag = 0; //no rx data
    card->netb_major = 250; // revise
    card->netb_location =NET_LOC;  
    card->name = \"net_break\";

    card->start_read = 0; //init value,no read started
    card->start_write = 0;
    card->open_count =0;
    sema_init(&card->sem,1);

    ////requst io
    if(!request_region(card->iobase,0x40,card->name) ) {
        printk(\"request io error!\\n\");
        goto err_io;
    }
    
    //requst irq
    result = request_irq ( card->irq,netb_interrupt,SA_SHIRQ,card->name,card );
    if(result) {
        printk(\"netb_init  request irq num error \\n\");
        dev->irq = -1;      
        goto err_irq;
    }
    //allocate dma buffers
    //card->dma_rx_buffer = kmalloc(card->max_length,GFP_KERNEL | __GFP_DMA);
    card->dma_rx_buffer = (void *) __get_free_pages(GFP_KERNEL | __GFP_DMA,ORDER);
    if( !(card->dma_rx_buffer) ){
        printk(\"netb_init  dma_rx_buffer alloc fail!\\n\");
        goto err_rxbuffer;
    }
    printk(\"dma_rx_buffer:%lx\\n\",  card->dma_rx_buffer);
    memset(card->dma_rx_buffer,0,card->max_length);

   //card->dma_tx_buffer = kmalloc(card->max_length,GFP_KERNEL | __GFP_DMA);
   card->dma_tx_buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_DMA,ORDER);
   if( !(card->dma_tx_buffer) ){
       printk(\"netb_open  dma_tx_buffer alloc fail!\\n\");
       goto err_txbuffer;
   }
   printk(\"dma_tx_buffer:%lx\\n\",  card->dma_tx_buffer);
   memset(card->dma_tx_buffer,0,card->max_length);  
    
    //get bus_address
    card->dma_rx_BaseAddr = virt_to_bus((void *) card->dma_rx_buffer);    
    printk(\"dma_rx_BaseAddr:%lx\\n\",card->dma_rx_BaseAddr);  
    card->dma_tx_BaseAddr = virt_to_bus((void *) card->dma_tx_buffer);    
    printk(\"dma_tx_BaseAddr:%lx\\n\",card->dma_tx_BaseAddr);  
    
    // device init
    //write dma_rx_sgBaseAddr register
    outl_p(card->dma_rx_BaseAddr,card->iobase + RX_BASE);    
    //init MISC_CTL, enable the chanel  and enable rx data
    outl_p(0x01000001,card->iobase + MISC_CTL);    
  
    pci_write_config_dword(dev, REG_PCICMD ,PCI_CMD_WORDS);   //Enable SERR_EN,PAR_ERR_EN,BUS_MST_EN,IO_SPACE_EN
    pci_write_config_byte(dev,PCI_LTIMER,128);  // new setting

    init_waitqueue_head(&rx_wq);
    init_waitqueue_head(&tx_wq);
    printk(\"Init_netb success!\\n\");
    return 0;
  

err_txbuffer:
    free_pages((ULONG)card->dma_tx_buffer,ORDER);
    free_pages((ULONG)card->dma_rx_buffer,ORDER);
err_rxbuffer:
    free_irq(card->irq,dev);
err_irq:
    release_region(card->iobase,0x40);
err_io:
    kfree(card);  
    printk(\"Init_netb fail!\\n\");
    return -1;  
}


void exit_netb()
{
    outl_p(0,card->iobase + MISC_CTL);
    release_region(card->iobase,0x40);
    free_irq(card->irq,card);
    //kfree( card->dma_rx_buffer);
    //kfree( card->dma_tx_buffer );    
    free_pages((ULONG)card->dma_tx_buffer,ORDER);
    free_pages((ULONG)card->dma_rx_buffer,ORDER);
    kfree(card);
    printk(\"exit_netb succeed!\\n\");

}

//count in BYTES
ssize_t netb_read(struct file *filp,char *buf,size_t count,loff_t *f_pos)
{
  
    ssize_t cnt;    // return value    
    unsigned long length,misc_words;   //dma data length    
    char * buffer;                
    int index = 0;
  
    wait_queue_t wait;
    init_waitqueue_entry(&wait,current);  
    struct netb_card *dev = filp->private_data;
 


    //printk(\"netb_read  start netb_read!\\n\");
    if(count>MAX_LEN) {
        printk(\"netb_read read size(%ld) too large!\\n\",count);
        return -1;
    }  
    add_wait_queue(&rx_wq,&wait);
    while( 1 ) {  // no data recieved should be blocked!
         set_current_state(TASK_INTERRUPTIBLE);
         if ( dev->rx_data_flag == 1 )
            break;
         //dev->start_read =1 ;  // start read cmd  need to be waked up          
         schedule();
         //printk(\"netb_read waked up from interrupt!\\n\");
    }                          
    // interruptible_sleep_on(&rx_wq);    
    set_current_state(TASK_RUNNING);
    remove_wait_queue(&rx_wq,&wait);
    dev->start_read = 0;  
    //dma_rx_sgBaseAddr = inl_p( dev->iobase + RX_SGL_BASE);
    //printk(\" read dma_base_addr_out:%lx\\n\", dma_rx_sgBaseAddr );  
copy:  
    length = dev->dma_rx_length ;      
    //printk(\"dma_rx_data_length:%lx\\n\",length);  
    length = length<<2;  //inbytes
    if(!length){
        printk(\"netb_read  dma data length 0!\\n\");
        return -1;
    }
    // caculate the return count
    cnt = length < count ? length : count ;      
    if ( copy_to_user((void *)buf, (void *)dev->dma_rx_buffer,cnt) ) {
        cnt = -EFAULT;
        printk(\"netb_read copy to user error! \\n\");
        goto out;
    }
    dev->rx_data_flag = 0;
    //write dma_rx_sgBaseAddr register  for next time to receive
    outl(dev->dma_rx_BaseAddr,dev->iobase + RX_BASE);  
    // enable rx data      
    outb( EN_RX , dev->iobase + MISC_CTL+3);        
    //printk(\"netb_read read succeed!\\n\");
out:
    return cnt;  
}

//count in BYTES
ssize_t netb_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{
    int result,i;
    int cnt = TxCnt;
    //struct timeval tm_begin,tm_end;
    //time_t time;

    //printk(\"netb_write start netb_write!\\n\");
    struct netb_card *dev = filp->private_data;  
    
    if(count>MAX_LEN) {
        printk(\"netb_write write size too large!\\n\");
        return -1;
    }
    //check write size--it must be word_size aligned!\\n
    
    result =copy_from_user(dev->dma_tx_buffer,(void *)buf,count);
    if(result) {
        printk(\"netb_write copy from user err!\\n\");
        return -1;
    }
    
     //set dma tx base addr
    outl(dev->dma_tx_BaseAddr,dev->iobase + TX_BASE);  
    outl(count >> 2,dev->iobase + TX_LENGTH);
    // now start dma                              
    dev->start_write = 1; // need to be waked up!
    outb_p(DMA_START_TX,dev->iobase + BUS_MASTER_CMD);
    if( wait_event_interruptible(tx_wq,dev->start_write == 0) ) {                   printk(\"write wakedup but start_write = %d\\n\",dev->start_write);
           return -1;            
    }              
    
    return dev->dma_tx_length <<2;        
}  

static int netb_open(struct inode * inode,struct file *file)
{
    struct netb_card *dev;
    int result;      
    printk(\" start netb_open!\\n\");  
    dev = (struct netb_card *) file->private_data;
    if(!dev) {  
        dev = card ;
        file->private_data = dev ;

    }
 
    //request to own the control right
    if(down_interruptible(&dev->sem) ) {
        printk(\"netb_open  lock sem error!\\n\");
        return -ERESTARTSYS;
    }
    if(file->f_flags &O_NONBLOCK ) {
        up(&dev->sem);
        return -EBUSY;
    }                    
    dev->open_count ++;
    up(&dev->sem);      
    MOD_INC_USE_COUNT;
    printk(\"netb_open success!\\n\");    
    return 0;          
}


static int netb_release(struct inode *inode,struct file *file)
{

    struct netb_card *dev = file->private_data;
    //request to own the control right
    if(down_interruptible(&dev->sem) ) {
        printk(\"netb_release  lock sem error!\\n\");
        return -ERESTARTSYS;
    }
    dev->open_count --;        
    up(&dev->sem);
    MOD_DEC_USE_COUNT;
    printk(\"exit release\\n\");
    return 0;  
}

static int netb_ioctl(struct inode *inode ,struct file *file,unsigned int cmd,unsigned long arg)
{
    struct netb_card *dev = file->private_data;
    switch (cmd) {
        case NETBCTL_GET_TSIZE :
        case NETBCTL_GET_LSIZE :
            return put_user(dev->max_length,(int *) arg);        
        case NETBCTL_GET_LOC :
            return put_user(dev->netb_location,(int *)arg);
        default :
            return -1;
    }
}


/*                                                        
  Interrup handling module
*/
static void netb_interrupt(int irq, void *dev_id,struct pt_regs *regs)


{
    u8 status;    
    unsigned long flags;
    unsigned long tx_len;
    save_and_cli(flags);
  
    struct netb_card *card_int =(struct netb_card *) dev_id;
    //printk(\"start interrupt!\\n\");
    status = inb(card_int->iobase +BUS_MASTER_STATUS);

    if(!(status & INT_MASK)) {
        //printk(\"interrupt not for us!\\n\");
        restore_flags(flags);
        return; //not for us
    }  
    if( ! (status & DMA_TX) ) {   // DMA rx data      
        card_int->dma_rx_length = inl(card_int->iobase + DMA_XFER_LENGTH);   //read dma data length          
        // disable rx data
        outb( 0 , card_int->iobase + MISC_CTL+3);
         //clear interrupt flag
        outb(status,card_int->iobase +BUS_MASTER_STATUS);
        //printk(\"clear dma rx int flag!\\n\");
        card_int->rx_data_flag = 1; // new data received!
        //if( card_int-> start_read ) { // interrupt happens after read()
            wake_up(&rx_wq);
        //    printk(\"interrupt wake up read!\\n\");
        //}
        //else  interrupt happens before  read()  ,no process to wakeup!
    }
    else {                     //DMA tx data
        card_int->dma_tx_length = inl(card_int->iobase + DMA_XFER_LENGTH);   //read dma data length
        outb(status,card_int->iobase +BUS_MASTER_STATUS);   //clear interrupt flag
        //stop dma transfer
        outb(0,card_int->iobase + BUS_MASTER_CMD);
       //printk(\"clear dma tx int flag!tx_len:%lx\\n\",card_int->dma_tx_length);
        card_int->start_write =0;
        wake_up(&tx_wq);    
    }    
    //wakeup....
    // printk(\"status_register:%x\\n exit interrupt !\\n\",inb_p(card_int->iobase +BUS_MASTER_STATUS));  
    
    //printk(\"exit interrupts! \\n\");
    restore_flags(flags);  
    /* add other handlers */
}

/*
device module info
*/
static int init_module(void)
{
    Init_netb();
    int result;
    result = register_chrdev(250,\"tnetb\",&netb_fops);
    if(result<0){                        

        printk(\"init_module register char device error\\n\");
        return result;
    }
    printk(\"init_module success!\\n\");
    return 0 ;
}

static void cleanup_module(void)
{
    unregister_chrdev(250,\"tnetb\");
    exit_netb();
    printk(\"<5> module netb is unloaded!\\n\");
}

MODULE_LICENSE(\"GPL\" );

上面是驱动的全部代码,读的有点糊涂
在路上----有人专著于脚下;有人心不在焉的仰望天空;有人迷恋于路边的景色. 结果----看脚的被车撞死;看天的掉进坑里摔死;还有一个因迷路而吓死。
dave_1981
驱动牛犊
驱动牛犊
  • 注册日期2004-12-27
  • 最后登录2005-03-03
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2005-03-02 15:05
对了,需要说明的是这是linux下的设备驱动
这是一对卡的驱动,功能是硬件防火墙作用,两台主机互相传送数据的
在路上----有人专著于脚下;有人心不在焉的仰望天空;有人迷恋于路边的景色. 结果----看脚的被车撞死;看天的掉进坑里摔死;还有一个因迷路而吓死。
aiwadgj
驱动老牛
驱动老牛
  • 注册日期2004-11-13
  • 最后登录2020-12-24
  • 粉丝0
  • 关注0
  • 积分119分
  • 威望84点
  • 贡献值0点
  • 好评度14点
  • 原创分0分
  • 专家分0分
  • 社区居民
板凳#
发布于:2005-03-02 15:59
寻找硬件一般是通过遍历总线,,,,插槽。。。完成。(因为不同得硬件对应不同的硬件ID)

通过两个for循环嵌套,,搞定。。。。。(PCI设备)

别的设备也应该一样的。。

网上好像有这样例子,,,,
酒也在沉溺,何时麻醉我抑郁。过去了的一切会平息。。。。。。。
seaquester
驱动大牛
驱动大牛
  • 注册日期2002-05-22
  • 最后登录2016-06-16
  • 粉丝0
  • 关注0
  • 积分500分
  • 威望115点
  • 贡献值0点
  • 好评度107点
  • 原创分0分
  • 专家分52分
地板#
发布于:2005-03-02 16:35
Linux 下用 pci_find_device 就可以搞定
八风舞遥翩,九野弄清音。 鸣高常向月,善舞不迎人。
bmyyyud
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2010-01-21
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望130点
  • 贡献值0点
  • 好评度106点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2005-03-02 16:40
linux下找PCI设备,需要读写配置寄存器空间
滚滚长江东逝水 浪花淘尽英雄 是非成败转头空 青山依旧在 几度夕阳红 白发渔樵江渚上 惯看秋月春风 一壶浊酒喜相逢 古今多少事 尽付笑谈中
dave_1981
驱动牛犊
驱动牛犊
  • 注册日期2004-12-27
  • 最后登录2005-03-03
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2005-03-03 09:21
哪位高手能详细的教我一点吗?
我以前没接触过一点linux的资料,驱动也是才开始的
几乎一片空白
在路上----有人专著于脚下;有人心不在焉的仰望天空;有人迷恋于路边的景色. 结果----看脚的被车撞死;看天的掉进坑里摔死;还有一个因迷路而吓死。
aiwadgj
驱动老牛
驱动老牛
  • 注册日期2004-11-13
  • 最后登录2020-12-24
  • 粉丝0
  • 关注0
  • 积分119分
  • 威望84点
  • 贡献值0点
  • 好评度14点
  • 原创分0分
  • 专家分0分
  • 社区居民
6楼#
发布于:2005-03-03 09:23
哪位高手能详细的教我一点吗?
我以前没接触过一点linux的资料,驱动也是才开始的
几乎一片空白


驱网上有关于LINUX驱动开发的书下载的,,,

下载了看看
酒也在沉溺,何时麻醉我抑郁。过去了的一切会平息。。。。。。。
bmyyyud
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2010-01-21
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望130点
  • 贡献值0点
  • 好评度106点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2005-03-03 10:16
哪位高手能详细的教我一点吗?
我以前没接触过一点linux的资料,驱动也是才开始的
几乎一片空白

看linux源码也可以,里面带的东西是权威,而且适合你的linux版本
滚滚长江东逝水 浪花淘尽英雄 是非成败转头空 青山依旧在 几度夕阳红 白发渔樵江渚上 惯看秋月春风 一壶浊酒喜相逢 古今多少事 尽付笑谈中
游客

返回顶部