阅读:1438回复:7
请教关于寻找设备
我初学,几乎一窍不通,我想请教各位大侠,能教我怎么去写程序来寻找硬件?
/* 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\" ); 上面是驱动的全部代码,读的有点糊涂 |
|
|
沙发#
发布于:2005-03-02 15:05
对了,需要说明的是这是linux下的设备驱动
这是一对卡的驱动,功能是硬件防火墙作用,两台主机互相传送数据的 |
|
|
板凳#
发布于:2005-03-02 15:59
寻找硬件一般是通过遍历总线,,,,插槽。。。完成。(因为不同得硬件对应不同的硬件ID)
通过两个for循环嵌套,,搞定。。。。。(PCI设备) 】 别的设备也应该一样的。。 网上好像有这样例子,,,, |
|
|
地板#
发布于:2005-03-02 16:35
Linux 下用 pci_find_device 就可以搞定
|
|
|
地下室#
发布于:2005-03-02 16:40
linux下找PCI设备,需要读写配置寄存器空间
|
|
|
5楼#
发布于:2005-03-03 09:21
哪位高手能详细的教我一点吗?
我以前没接触过一点linux的资料,驱动也是才开始的 几乎一片空白 |
|
|
6楼#
发布于:2005-03-03 09:23
哪位高手能详细的教我一点吗? 驱网上有关于LINUX驱动开发的书下载的,,, 下载了看看 |
|
|
7楼#
发布于:2005-03-03 10:16
哪位高手能详细的教我一点吗? 看linux源码也可以,里面带的东西是权威,而且适合你的linux版本 |
|
|