Mercurial > pt1
comparison driver/pt1_pci.c @ 31:289794dc265f
adapted to use of multiple number of pt1:
- now pt1_open() checks major number.
- passes unique device name to device_create().
- handles device[] bit carefully.
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Tue, 03 Mar 2009 05:15:40 +0900 |
parents | eb694d8e4c7e |
children | 65c8ac567074 |
comparison
equal
deleted
inserted
replaced
30:eb694d8e4c7e | 31:289794dc265f |
---|---|
49 MODULE_AUTHOR("Tomoaki Ishikawa tomy@users.sourceforge.jp"); | 49 MODULE_AUTHOR("Tomoaki Ishikawa tomy@users.sourceforge.jp"); |
50 #define DRIVER_DESC "PCI earthsoft PT1 driver" | 50 #define DRIVER_DESC "PCI earthsoft PT1 driver" |
51 MODULE_DESCRIPTION(DRIVER_DESC); | 51 MODULE_DESCRIPTION(DRIVER_DESC); |
52 MODULE_LICENSE("GPL"); | 52 MODULE_LICENSE("GPL"); |
53 | 53 |
54 static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ | 54 static int debug = 7; /* 1 normal messages, 0 quiet .. 7 verbose. */ |
55 static int lnb = 0; /* LNB OFF:0 +11V:1 +15V:2 */ | 55 static int lnb = 0; /* LNB OFF:0 +11V:1 +15V:2 */ |
56 | 56 |
57 module_param(debug, int, 0); | 57 module_param(debug, int, 0); |
58 module_param(lnb, int, 0); | 58 module_param(lnb, int, 0); |
59 MODULE_PARM_DESC(debug, "debug level (1-2)"); | 59 MODULE_PARM_DESC(debug, "debug level (1-2)"); |
95 struct mutex lock ; | 95 struct mutex lock ; |
96 dma_addr_t ring_dma[DMA_RING_SIZE] ; // DMA¾ðÊó | 96 dma_addr_t ring_dma[DMA_RING_SIZE] ; // DMA¾ðÊó |
97 void *dmaptr[DMA_RING_SIZE] ; | 97 void *dmaptr[DMA_RING_SIZE] ; |
98 struct task_struct *kthread; | 98 struct task_struct *kthread; |
99 dev_t dev ; | 99 dev_t dev ; |
100 int card_number; | |
100 __u32 base_minor ; | 101 __u32 base_minor ; |
101 struct cdev cdev[MAX_CHANNEL]; | 102 struct cdev cdev[MAX_CHANNEL]; |
102 wait_queue_head_t dma_wait_q ;// for poll on reading | 103 wait_queue_head_t dma_wait_q ;// for poll on reading |
103 DMA_CONTROL dmactl[DMA_RING_SIZE]; | 104 DMA_CONTROL dmactl[DMA_RING_SIZE]; |
104 PT1_CHANNEL *channel[MAX_CHANNEL]; | 105 PT1_CHANNEL *channel[MAX_CHANNEL]; |
282 return 0 ; | 283 return 0 ; |
283 } | 284 } |
284 static int pt1_open(struct inode *inode, struct file *file) | 285 static int pt1_open(struct inode *inode, struct file *file) |
285 { | 286 { |
286 | 287 |
288 int major = imajor(inode); | |
287 int minor = iminor(inode); | 289 int minor = iminor(inode); |
288 int lp ; | 290 int lp ; |
289 int lp2 ; | 291 int lp2 ; |
290 PT1_CHANNEL *channel ; | 292 PT1_CHANNEL *channel ; |
291 | 293 |
292 for(lp = 0 ; lp < MAX_PCI_DEVICE ; lp++){ | 294 for(lp = 0 ; lp < MAX_PCI_DEVICE ; lp++){ |
293 if(device[lp] == NULL){ | 295 if(device[lp] == NULL){ |
294 return -EIO ; | 296 return -EIO ; |
295 } | 297 } |
296 if((device[lp]->base_minor <= minor) && | 298 |
297 ((device[lp]->base_minor + MAX_CHANNEL) > minor)){ | 299 if(MAJOR(device[lp]->dev) == major && |
300 device[lp]->base_minor <= minor && | |
301 device[lp]->base_minor + MAX_CHANNEL > minor) { | |
302 | |
298 mutex_lock(&device[lp]->lock); | 303 mutex_lock(&device[lp]->lock); |
299 for(lp2 = 0 ; lp2 < MAX_CHANNEL ; lp2++){ | 304 for(lp2 = 0 ; lp2 < MAX_CHANNEL ; lp2++){ |
300 channel = device[lp]->channel[lp2] ; | 305 channel = device[lp]->channel[lp2] ; |
301 if(channel->minor == minor){ | 306 if(channel->minor == minor){ |
302 if(channel->valid == TRUE){ | 307 if(channel->valid == TRUE){ |
327 PT1_CHANNEL *channel = file->private_data; | 332 PT1_CHANNEL *channel = file->private_data; |
328 | 333 |
329 mutex_lock(&channel->ptr->lock); | 334 mutex_lock(&channel->ptr->lock); |
330 SetStream(channel->ptr->regs, channel->channel, FALSE); | 335 SetStream(channel->ptr->regs, channel->channel, FALSE); |
331 channel->valid = FALSE ; | 336 channel->valid = FALSE ; |
332 printk(KERN_INFO "(%d)Drop=%08d:%08d:%08d:%08d\n", iminor(inode), channel->drop, | 337 printk(KERN_INFO "(%d:%d)Drop=%08d:%08d:%08d:%08d\n", imajor(inode), iminor(inode), channel->drop, |
333 channel->overflow, channel->counetererr, channel->transerr); | 338 channel->overflow, channel->counetererr, channel->transerr); |
334 channel->overflow = 0 ; | 339 channel->overflow = 0 ; |
335 channel->counetererr = 0 ; | 340 channel->counetererr = 0 ; |
336 channel->transerr = 0 ; | 341 channel->transerr = 0 ; |
337 channel->drop = 0 ; | 342 channel->drop = 0 ; |
651 init_waitqueue_head(&dev_conf->dma_wait_q); | 656 init_waitqueue_head(&dev_conf->dma_wait_q); |
652 | 657 |
653 minor = MINOR(dev_conf->dev) ; | 658 minor = MINOR(dev_conf->dev) ; |
654 dev_conf->base_minor = minor ; | 659 dev_conf->base_minor = minor ; |
655 for(lp = 0 ; lp < MAX_PCI_DEVICE ; lp++){ | 660 for(lp = 0 ; lp < MAX_PCI_DEVICE ; lp++){ |
661 printk(KERN_INFO "PT1: device[%d]=%p\n", lp, device[lp]); | |
656 if(device[lp] == NULL){ | 662 if(device[lp] == NULL){ |
657 device[lp] = dev_conf ; | 663 device[lp] = dev_conf ; |
664 dev_conf->card_number = lp; | |
658 break ; | 665 break ; |
659 } | 666 } |
660 } | 667 } |
661 for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ | 668 for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ |
662 cdev_init(&dev_conf->cdev[lp], &pt1_fops); | 669 cdev_init(&dev_conf->cdev[lp], &pt1_fops); |
663 dev_conf->cdev[lp].owner = THIS_MODULE; | 670 dev_conf->cdev[lp].owner = THIS_MODULE; |
664 cdev_add(&dev_conf->cdev[lp], MKDEV(MAJOR(dev_conf->dev), (MINOR(dev_conf->dev) + lp)), 1); | 671 cdev_add(&dev_conf->cdev[lp], |
672 MKDEV(MAJOR(dev_conf->dev), (MINOR(dev_conf->dev) + lp)), 1); | |
665 channel = kzalloc(sizeof(PT1_CHANNEL), GFP_KERNEL); | 673 channel = kzalloc(sizeof(PT1_CHANNEL), GFP_KERNEL); |
666 if(!channel){ | 674 if(!channel){ |
667 printk(KERN_ERR "PT1:out of memory !"); | 675 printk(KERN_ERR "PT1:out of memory !"); |
668 return -ENOMEM ; | 676 return -ENOMEM ; |
669 } | 677 } |
697 } | 705 } |
698 if(channel->buf == NULL){ | 706 if(channel->buf == NULL){ |
699 goto out_err_v4l; | 707 goto out_err_v4l; |
700 } | 708 } |
701 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) | 709 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
702 device_create(pt1video_class, NULL, MKDEV(MAJOR(dev_conf->dev), | 710 printk(KERN_INFO "PT1: card_number = %d\n", |
703 (MINOR(dev_conf->dev) + lp)), NULL, | 711 dev_conf->card_number); |
704 "pt1video%u", MINOR(dev_conf->dev) + lp); | 712 device_create(pt1video_class, |
713 NULL, | |
714 MKDEV(MAJOR(dev_conf->dev), | |
715 (MINOR(dev_conf->dev) + lp)), | |
716 NULL, | |
717 "pt1video%u", | |
718 MINOR(dev_conf->dev) + lp + | |
719 dev_conf->card_number * MAX_CHANNEL); | |
705 #else | 720 #else |
706 device_create(pt1video_class, NULL, MKDEV(MAJOR(dev_conf->dev), | 721 device_create(pt1video_class, |
707 (MINOR(dev_conf->dev) + lp)), | 722 NULL, |
708 "pt1video%u", MINOR(dev_conf->dev) + lp); | 723 MKDEV(MAJOR(dev_conf->dev), |
724 (MINOR(dev_conf->dev) + lp)), | |
725 "pt1video%u", | |
726 MINOR(dev_conf->dev) + lp + | |
727 dev_conf->card_number * MAX_CHANNEL); | |
709 #endif | 728 #endif |
710 | 729 |
711 #if 0 | 730 #if 0 |
712 dev_conf->vdev[lp] = video_device_alloc(); | 731 dev_conf->vdev[lp] = video_device_alloc(); |
713 memcpy(dev_conf->vdev[lp], &pt1_template, sizeof(pt1_template)); | 732 memcpy(dev_conf->vdev[lp], &pt1_template, sizeof(pt1_template)); |
714 video_set_drvdata(dev_conf->vdev[lp], channel); | 733 video_set_drvdata(dev_conf->vdev[lp], channel); |
715 video_register_device(dev_conf->vdev[lp], VFL_TYPE_GRABBER, -1); | 734 video_register_device(dev_conf->vdev[lp], VFL_TYPE_GRABBER, -1); |
716 #endif | 735 #endif |
717 } | 736 } |
737 | |
718 if(pt1_dma_init(pdev, dev_conf) < 0){ | 738 if(pt1_dma_init(pdev, dev_conf) < 0){ |
719 goto out_err_dma; | 739 goto out_err_dma; |
720 } | 740 } |
721 dev_conf->kthread = kthread_run(pt1_thread, dev_conf, "pt1"); | 741 dev_conf->kthread = kthread_run(pt1_thread, dev_conf, "pt1"); |
722 pci_set_drvdata(pdev, dev_conf); | 742 pci_set_drvdata(pdev, dev_conf); |
771 if(dev_conf->channel[lp] != NULL){ | 791 if(dev_conf->channel[lp] != NULL){ |
772 cdev_del(&dev_conf->cdev[lp]); | 792 cdev_del(&dev_conf->cdev[lp]); |
773 kfree(dev_conf->channel[lp]->buf); | 793 kfree(dev_conf->channel[lp]->buf); |
774 kfree(dev_conf->channel[lp]); | 794 kfree(dev_conf->channel[lp]); |
775 } | 795 } |
776 device_destroy(pt1video_class, | 796 device_destroy(pt1video_class, |
777 MKDEV(MAJOR(dev_conf->dev), (MINOR(dev_conf->dev) + lp))); | 797 MKDEV(MAJOR(dev_conf->dev), |
778 } | 798 (MINOR(dev_conf->dev) + lp))); |
799 } | |
800 | |
779 unregister_chrdev_region(dev_conf->dev, MAX_CHANNEL); | 801 unregister_chrdev_region(dev_conf->dev, MAX_CHANNEL); |
780 writel(0xb0b0000, dev_conf->regs); | 802 writel(0xb0b0000, dev_conf->regs); |
781 writel(0, dev_conf->regs + 4); | 803 writel(0, dev_conf->regs + 4); |
782 settuner_reset(dev_conf->regs, LNB_OFF, TUNER_POWER_OFF); | 804 settuner_reset(dev_conf->regs, LNB_OFF, TUNER_POWER_OFF); |
783 release_mem_region(dev_conf->mmio_start, dev_conf->mmio_len); | 805 release_mem_region(dev_conf->mmio_start, dev_conf->mmio_len); |
784 iounmap(dev_conf->regs); | 806 iounmap(dev_conf->regs); |
807 device[dev_conf->card_number] = NULL; | |
785 kfree(dev_conf); | 808 kfree(dev_conf); |
786 } | 809 } |
787 pci_set_drvdata(pdev, NULL); | 810 pci_set_drvdata(pdev, NULL); |
788 } | 811 } |
789 #ifdef CONFIG_PM | 812 #ifdef CONFIG_PM |
824 | 847 |
825 | 848 |
826 static void __exit pt1_pci_cleanup(void) | 849 static void __exit pt1_pci_cleanup(void) |
827 { | 850 { |
828 class_destroy(pt1video_class); | 851 class_destroy(pt1video_class); |
829 pci_unregister_driver (&pt1_driver); | 852 pci_unregister_driver(&pt1_driver); |
830 } | 853 } |
831 | 854 |
832 module_init(pt1_pci_init); | 855 module_init(pt1_pci_init); |
833 module_exit(pt1_pci_cleanup); | 856 module_exit(pt1_pci_cleanup); |