diff options
Diffstat (limited to 'drivers')
186 files changed, 11294 insertions, 4916 deletions
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index 638db06de2..3410b4d294 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c | |||
@@ -1871,20 +1871,22 @@ static int as_init_queue(request_queue_t *q, elevator_t *e) | |||
1871 | if (!arq_pool) | 1871 | if (!arq_pool) |
1872 | return -ENOMEM; | 1872 | return -ENOMEM; |
1873 | 1873 | ||
1874 | ad = kmalloc(sizeof(*ad), GFP_KERNEL); | 1874 | ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node); |
1875 | if (!ad) | 1875 | if (!ad) |
1876 | return -ENOMEM; | 1876 | return -ENOMEM; |
1877 | memset(ad, 0, sizeof(*ad)); | 1877 | memset(ad, 0, sizeof(*ad)); |
1878 | 1878 | ||
1879 | ad->q = q; /* Identify what queue the data belongs to */ | 1879 | ad->q = q; /* Identify what queue the data belongs to */ |
1880 | 1880 | ||
1881 | ad->hash = kmalloc(sizeof(struct list_head)*AS_HASH_ENTRIES,GFP_KERNEL); | 1881 | ad->hash = kmalloc_node(sizeof(struct list_head)*AS_HASH_ENTRIES, |
1882 | GFP_KERNEL, q->node); | ||
1882 | if (!ad->hash) { | 1883 | if (!ad->hash) { |
1883 | kfree(ad); | 1884 | kfree(ad); |
1884 | return -ENOMEM; | 1885 | return -ENOMEM; |
1885 | } | 1886 | } |
1886 | 1887 | ||
1887 | ad->arq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, arq_pool); | 1888 | ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, |
1889 | mempool_free_slab, arq_pool, q->node); | ||
1888 | if (!ad->arq_pool) { | 1890 | if (!ad->arq_pool) { |
1889 | kfree(ad->hash); | 1891 | kfree(ad->hash); |
1890 | kfree(ad); | 1892 | kfree(ad); |
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c index 7f79f3dd01..4bc2fea732 100644 --- a/drivers/block/deadline-iosched.c +++ b/drivers/block/deadline-iosched.c | |||
@@ -711,18 +711,20 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e) | |||
711 | if (!drq_pool) | 711 | if (!drq_pool) |
712 | return -ENOMEM; | 712 | return -ENOMEM; |
713 | 713 | ||
714 | dd = kmalloc(sizeof(*dd), GFP_KERNEL); | 714 | dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node); |
715 | if (!dd) | 715 | if (!dd) |
716 | return -ENOMEM; | 716 | return -ENOMEM; |
717 | memset(dd, 0, sizeof(*dd)); | 717 | memset(dd, 0, sizeof(*dd)); |
718 | 718 | ||
719 | dd->hash = kmalloc(sizeof(struct list_head)*DL_HASH_ENTRIES,GFP_KERNEL); | 719 | dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES, |
720 | GFP_KERNEL, q->node); | ||
720 | if (!dd->hash) { | 721 | if (!dd->hash) { |
721 | kfree(dd); | 722 | kfree(dd); |
722 | return -ENOMEM; | 723 | return -ENOMEM; |
723 | } | 724 | } |
724 | 725 | ||
725 | dd->drq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, drq_pool); | 726 | dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, |
727 | mempool_free_slab, drq_pool, q->node); | ||
726 | if (!dd->drq_pool) { | 728 | if (!dd->drq_pool) { |
727 | kfree(dd->hash); | 729 | kfree(dd->hash); |
728 | kfree(dd); | 730 | kfree(dd); |
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index 53f7d846b7..47fd3659a0 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c | |||
@@ -40,7 +40,7 @@ static inline int major_to_index(int major) | |||
40 | 40 | ||
41 | #ifdef CONFIG_PROC_FS | 41 | #ifdef CONFIG_PROC_FS |
42 | /* get block device names in somewhat random order */ | 42 | /* get block device names in somewhat random order */ |
43 | int get_blkdev_list(char *p) | 43 | int get_blkdev_list(char *p, int used) |
44 | { | 44 | { |
45 | struct blk_major_name *n; | 45 | struct blk_major_name *n; |
46 | int i, len; | 46 | int i, len; |
@@ -49,10 +49,18 @@ int get_blkdev_list(char *p) | |||
49 | 49 | ||
50 | down(&block_subsys_sem); | 50 | down(&block_subsys_sem); |
51 | for (i = 0; i < ARRAY_SIZE(major_names); i++) { | 51 | for (i = 0; i < ARRAY_SIZE(major_names); i++) { |
52 | for (n = major_names[i]; n; n = n->next) | 52 | for (n = major_names[i]; n; n = n->next) { |
53 | /* | ||
54 | * If the curent string plus the 5 extra characters | ||
55 | * in the line would run us off the page, then we're done | ||
56 | */ | ||
57 | if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE) | ||
58 | goto page_full; | ||
53 | len += sprintf(p+len, "%3d %s\n", | 59 | len += sprintf(p+len, "%3d %s\n", |
54 | n->major, n->name); | 60 | n->major, n->name); |
61 | } | ||
55 | } | 62 | } |
63 | page_full: | ||
56 | up(&block_subsys_sem); | 64 | up(&block_subsys_sem); |
57 | 65 | ||
58 | return len; | 66 | return len; |
@@ -582,10 +590,16 @@ struct seq_operations diskstats_op = { | |||
582 | .show = diskstats_show | 590 | .show = diskstats_show |
583 | }; | 591 | }; |
584 | 592 | ||
585 | |||
586 | struct gendisk *alloc_disk(int minors) | 593 | struct gendisk *alloc_disk(int minors) |
587 | { | 594 | { |
588 | struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL); | 595 | return alloc_disk_node(minors, -1); |
596 | } | ||
597 | |||
598 | struct gendisk *alloc_disk_node(int minors, int node_id) | ||
599 | { | ||
600 | struct gendisk *disk; | ||
601 | |||
602 | disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id); | ||
589 | if (disk) { | 603 | if (disk) { |
590 | memset(disk, 0, sizeof(struct gendisk)); | 604 | memset(disk, 0, sizeof(struct gendisk)); |
591 | if (!init_disk_stats(disk)) { | 605 | if (!init_disk_stats(disk)) { |
@@ -594,7 +608,7 @@ struct gendisk *alloc_disk(int minors) | |||
594 | } | 608 | } |
595 | if (minors > 1) { | 609 | if (minors > 1) { |
596 | int size = (minors - 1) * sizeof(struct hd_struct *); | 610 | int size = (minors - 1) * sizeof(struct hd_struct *); |
597 | disk->part = kmalloc(size, GFP_KERNEL); | 611 | disk->part = kmalloc_node(size, GFP_KERNEL, node_id); |
598 | if (!disk->part) { | 612 | if (!disk->part) { |
599 | kfree(disk); | 613 | kfree(disk); |
600 | return NULL; | 614 | return NULL; |
@@ -610,6 +624,7 @@ struct gendisk *alloc_disk(int minors) | |||
610 | } | 624 | } |
611 | 625 | ||
612 | EXPORT_SYMBOL(alloc_disk); | 626 | EXPORT_SYMBOL(alloc_disk); |
627 | EXPORT_SYMBOL(alloc_disk_node); | ||
613 | 628 | ||
614 | struct kobject *get_disk(struct gendisk *disk) | 629 | struct kobject *get_disk(struct gendisk *disk) |
615 | { | 630 | { |
diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c index 6d7bcc9da9..6e278474f9 100644 --- a/drivers/block/ioctl.c +++ b/drivers/block/ioctl.c | |||
@@ -133,11 +133,9 @@ static int put_u64(unsigned long arg, u64 val) | |||
133 | return put_user(val, (u64 __user *)arg); | 133 | return put_user(val, (u64 __user *)arg); |
134 | } | 134 | } |
135 | 135 | ||
136 | int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | 136 | static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, |
137 | unsigned long arg) | 137 | unsigned cmd, unsigned long arg) |
138 | { | 138 | { |
139 | struct block_device *bdev = inode->i_bdev; | ||
140 | struct gendisk *disk = bdev->bd_disk; | ||
141 | struct backing_dev_info *bdi; | 139 | struct backing_dev_info *bdi; |
142 | int ret, n; | 140 | int ret, n; |
143 | 141 | ||
@@ -190,36 +188,72 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | |||
190 | return put_ulong(arg, bdev->bd_inode->i_size >> 9); | 188 | return put_ulong(arg, bdev->bd_inode->i_size >> 9); |
191 | case BLKGETSIZE64: | 189 | case BLKGETSIZE64: |
192 | return put_u64(arg, bdev->bd_inode->i_size); | 190 | return put_u64(arg, bdev->bd_inode->i_size); |
191 | } | ||
192 | return -ENOIOCTLCMD; | ||
193 | } | ||
194 | |||
195 | static int blkdev_driver_ioctl(struct inode *inode, struct file *file, | ||
196 | struct gendisk *disk, unsigned cmd, unsigned long arg) | ||
197 | { | ||
198 | int ret; | ||
199 | if (disk->fops->unlocked_ioctl) | ||
200 | return disk->fops->unlocked_ioctl(file, cmd, arg); | ||
201 | |||
202 | if (disk->fops->ioctl) { | ||
203 | lock_kernel(); | ||
204 | ret = disk->fops->ioctl(inode, file, cmd, arg); | ||
205 | unlock_kernel(); | ||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | return -ENOTTY; | ||
210 | } | ||
211 | |||
212 | int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | ||
213 | unsigned long arg) | ||
214 | { | ||
215 | struct block_device *bdev = inode->i_bdev; | ||
216 | struct gendisk *disk = bdev->bd_disk; | ||
217 | int ret, n; | ||
218 | |||
219 | switch(cmd) { | ||
193 | case BLKFLSBUF: | 220 | case BLKFLSBUF: |
194 | if (!capable(CAP_SYS_ADMIN)) | 221 | if (!capable(CAP_SYS_ADMIN)) |
195 | return -EACCES; | 222 | return -EACCES; |
196 | if (disk->fops->ioctl) { | 223 | |
197 | ret = disk->fops->ioctl(inode, file, cmd, arg); | 224 | ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); |
198 | /* -EINVAL to handle old uncorrected drivers */ | 225 | /* -EINVAL to handle old uncorrected drivers */ |
199 | if (ret != -EINVAL && ret != -ENOTTY) | 226 | if (ret != -EINVAL && ret != -ENOTTY) |
200 | return ret; | 227 | return ret; |
201 | } | 228 | |
229 | lock_kernel(); | ||
202 | fsync_bdev(bdev); | 230 | fsync_bdev(bdev); |
203 | invalidate_bdev(bdev, 0); | 231 | invalidate_bdev(bdev, 0); |
232 | unlock_kernel(); | ||
204 | return 0; | 233 | return 0; |
234 | |||
205 | case BLKROSET: | 235 | case BLKROSET: |
206 | if (disk->fops->ioctl) { | 236 | ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); |
207 | ret = disk->fops->ioctl(inode, file, cmd, arg); | 237 | /* -EINVAL to handle old uncorrected drivers */ |
208 | /* -EINVAL to handle old uncorrected drivers */ | 238 | if (ret != -EINVAL && ret != -ENOTTY) |
209 | if (ret != -EINVAL && ret != -ENOTTY) | 239 | return ret; |
210 | return ret; | ||
211 | } | ||
212 | if (!capable(CAP_SYS_ADMIN)) | 240 | if (!capable(CAP_SYS_ADMIN)) |
213 | return -EACCES; | 241 | return -EACCES; |
214 | if (get_user(n, (int __user *)(arg))) | 242 | if (get_user(n, (int __user *)(arg))) |
215 | return -EFAULT; | 243 | return -EFAULT; |
244 | lock_kernel(); | ||
216 | set_device_ro(bdev, n); | 245 | set_device_ro(bdev, n); |
246 | unlock_kernel(); | ||
217 | return 0; | 247 | return 0; |
218 | default: | ||
219 | if (disk->fops->ioctl) | ||
220 | return disk->fops->ioctl(inode, file, cmd, arg); | ||
221 | } | 248 | } |
222 | return -ENOTTY; | 249 | |
250 | lock_kernel(); | ||
251 | ret = blkdev_locked_ioctl(file, bdev, cmd, arg); | ||
252 | unlock_kernel(); | ||
253 | if (ret != -ENOIOCTLCMD) | ||
254 | return ret; | ||
255 | |||
256 | return blkdev_driver_ioctl(inode, file, disk, cmd, arg); | ||
223 | } | 257 | } |
224 | 258 | ||
225 | /* Most of the generic ioctls are handled in the normal fallback path. | 259 | /* Most of the generic ioctls are handled in the normal fallback path. |
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 81fe3a0c1f..fd94ea27d5 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/swap.h> | 29 | #include <linux/swap.h> |
30 | #include <linux/writeback.h> | 30 | #include <linux/writeback.h> |
31 | #include <linux/blkdev.h> | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * for max sense size | 34 | * for max sense size |
@@ -716,7 +717,7 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag) | |||
716 | { | 717 | { |
717 | struct blk_queue_tag *bqt = q->queue_tags; | 718 | struct blk_queue_tag *bqt = q->queue_tags; |
718 | 719 | ||
719 | if (unlikely(bqt == NULL || tag >= bqt->real_max_depth)) | 720 | if (unlikely(bqt == NULL || tag >= bqt->max_depth)) |
720 | return NULL; | 721 | return NULL; |
721 | 722 | ||
722 | return bqt->tag_index[tag]; | 723 | return bqt->tag_index[tag]; |
@@ -774,9 +775,9 @@ EXPORT_SYMBOL(blk_queue_free_tags); | |||
774 | static int | 775 | static int |
775 | init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) | 776 | init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) |
776 | { | 777 | { |
777 | int bits, i; | ||
778 | struct request **tag_index; | 778 | struct request **tag_index; |
779 | unsigned long *tag_map; | 779 | unsigned long *tag_map; |
780 | int nr_ulongs; | ||
780 | 781 | ||
781 | if (depth > q->nr_requests * 2) { | 782 | if (depth > q->nr_requests * 2) { |
782 | depth = q->nr_requests * 2; | 783 | depth = q->nr_requests * 2; |
@@ -788,24 +789,17 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) | |||
788 | if (!tag_index) | 789 | if (!tag_index) |
789 | goto fail; | 790 | goto fail; |
790 | 791 | ||
791 | bits = (depth / BLK_TAGS_PER_LONG) + 1; | 792 | nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG; |
792 | tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC); | 793 | tag_map = kmalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC); |
793 | if (!tag_map) | 794 | if (!tag_map) |
794 | goto fail; | 795 | goto fail; |
795 | 796 | ||
796 | memset(tag_index, 0, depth * sizeof(struct request *)); | 797 | memset(tag_index, 0, depth * sizeof(struct request *)); |
797 | memset(tag_map, 0, bits * sizeof(unsigned long)); | 798 | memset(tag_map, 0, nr_ulongs * sizeof(unsigned long)); |
798 | tags->max_depth = depth; | 799 | tags->max_depth = depth; |
799 | tags->real_max_depth = bits * BITS_PER_LONG; | ||
800 | tags->tag_index = tag_index; | 800 | tags->tag_index = tag_index; |
801 | tags->tag_map = tag_map; | 801 | tags->tag_map = tag_map; |
802 | 802 | ||
803 | /* | ||
804 | * set the upper bits if the depth isn't a multiple of the word size | ||
805 | */ | ||
806 | for (i = depth; i < bits * BLK_TAGS_PER_LONG; i++) | ||
807 | __set_bit(i, tag_map); | ||
808 | |||
809 | return 0; | 803 | return 0; |
810 | fail: | 804 | fail: |
811 | kfree(tag_index); | 805 | kfree(tag_index); |
@@ -870,32 +864,24 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth) | |||
870 | struct blk_queue_tag *bqt = q->queue_tags; | 864 | struct blk_queue_tag *bqt = q->queue_tags; |
871 | struct request **tag_index; | 865 | struct request **tag_index; |
872 | unsigned long *tag_map; | 866 | unsigned long *tag_map; |
873 | int bits, max_depth; | 867 | int max_depth, nr_ulongs; |
874 | 868 | ||
875 | if (!bqt) | 869 | if (!bqt) |
876 | return -ENXIO; | 870 | return -ENXIO; |
877 | 871 | ||
878 | /* | 872 | /* |
879 | * don't bother sizing down | ||
880 | */ | ||
881 | if (new_depth <= bqt->real_max_depth) { | ||
882 | bqt->max_depth = new_depth; | ||
883 | return 0; | ||
884 | } | ||
885 | |||
886 | /* | ||
887 | * save the old state info, so we can copy it back | 873 | * save the old state info, so we can copy it back |
888 | */ | 874 | */ |
889 | tag_index = bqt->tag_index; | 875 | tag_index = bqt->tag_index; |
890 | tag_map = bqt->tag_map; | 876 | tag_map = bqt->tag_map; |
891 | max_depth = bqt->real_max_depth; | 877 | max_depth = bqt->max_depth; |
892 | 878 | ||
893 | if (init_tag_map(q, bqt, new_depth)) | 879 | if (init_tag_map(q, bqt, new_depth)) |
894 | return -ENOMEM; | 880 | return -ENOMEM; |
895 | 881 | ||
896 | memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *)); | 882 | memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *)); |
897 | bits = max_depth / BLK_TAGS_PER_LONG; | 883 | nr_ulongs = ALIGN(max_depth, BITS_PER_LONG) / BITS_PER_LONG; |
898 | memcpy(bqt->tag_map, tag_map, bits * sizeof(unsigned long)); | 884 | memcpy(bqt->tag_map, tag_map, nr_ulongs * sizeof(unsigned long)); |
899 | 885 | ||
900 | kfree(tag_index); | 886 | kfree(tag_index); |
901 | kfree(tag_map); | 887 | kfree(tag_map); |
@@ -925,11 +911,16 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq) | |||
925 | 911 | ||
926 | BUG_ON(tag == -1); | 912 | BUG_ON(tag == -1); |
927 | 913 | ||
928 | if (unlikely(tag >= bqt->real_max_depth)) | 914 | if (unlikely(tag >= bqt->max_depth)) |
915 | /* | ||
916 | * This can happen after tag depth has been reduced. | ||
917 | * FIXME: how about a warning or info message here? | ||
918 | */ | ||
929 | return; | 919 | return; |
930 | 920 | ||
931 | if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) { | 921 | if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) { |
932 | printk("attempt to clear non-busy tag (%d)\n", tag); | 922 | printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n", |
923 | __FUNCTION__, tag); | ||
933 | return; | 924 | return; |
934 | } | 925 | } |
935 | 926 | ||
@@ -938,7 +929,8 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq) | |||
938 | rq->tag = -1; | 929 | rq->tag = -1; |
939 | 930 | ||
940 | if (unlikely(bqt->tag_index[tag] == NULL)) | 931 | if (unlikely(bqt->tag_index[tag] == NULL)) |
941 | printk("tag %d is missing\n", tag); | 932 | printk(KERN_ERR "%s: tag %d is missing\n", |
933 | __FUNCTION__, tag); | ||
942 | 934 | ||
943 | bqt->tag_index[tag] = NULL; | 935 | bqt->tag_index[tag] = NULL; |
944 | bqt->busy--; | 936 | bqt->busy--; |
@@ -967,24 +959,20 @@ EXPORT_SYMBOL(blk_queue_end_tag); | |||
967 | int blk_queue_start_tag(request_queue_t *q, struct request *rq) | 959 | int blk_queue_start_tag(request_queue_t *q, struct request *rq) |
968 | { | 960 | { |
969 | struct blk_queue_tag *bqt = q->queue_tags; | 961 | struct blk_queue_tag *bqt = q->queue_tags; |
970 | unsigned long *map = bqt->tag_map; | 962 | int tag; |
971 | int tag = 0; | ||
972 | 963 | ||
973 | if (unlikely((rq->flags & REQ_QUEUED))) { | 964 | if (unlikely((rq->flags & REQ_QUEUED))) { |
974 | printk(KERN_ERR | 965 | printk(KERN_ERR |
975 | "request %p for device [%s] already tagged %d", | 966 | "%s: request %p for device [%s] already tagged %d", |
976 | rq, rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag); | 967 | __FUNCTION__, rq, |
968 | rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag); | ||
977 | BUG(); | 969 | BUG(); |
978 | } | 970 | } |
979 | 971 | ||
980 | for (map = bqt->tag_map; *map == -1UL; map++) { | 972 | tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth); |
981 | tag += BLK_TAGS_PER_LONG; | 973 | if (tag >= bqt->max_depth) |
982 | 974 | return 1; | |
983 | if (tag >= bqt->max_depth) | ||
984 | return 1; | ||
985 | } | ||
986 | 975 | ||
987 | tag += ffz(*map); | ||
988 | __set_bit(tag, bqt->tag_map); | 976 | __set_bit(tag, bqt->tag_map); |
989 | 977 | ||
990 | rq->flags |= REQ_QUEUED; | 978 | rq->flags |= REQ_QUEUED; |
@@ -1020,7 +1008,8 @@ void blk_queue_invalidate_tags(request_queue_t *q) | |||
1020 | rq = list_entry_rq(tmp); | 1008 | rq = list_entry_rq(tmp); |
1021 | 1009 | ||
1022 | if (rq->tag == -1) { | 1010 | if (rq->tag == -1) { |
1023 | printk("bad tag found on list\n"); | 1011 | printk(KERN_ERR |
1012 | "%s: bad tag found on list\n", __FUNCTION__); | ||
1024 | list_del_init(&rq->queuelist); | 1013 | list_del_init(&rq->queuelist); |
1025 | rq->flags &= ~REQ_QUEUED; | 1014 | rq->flags &= ~REQ_QUEUED; |
1026 | } else | 1015 | } else |
@@ -1450,7 +1439,7 @@ EXPORT_SYMBOL(blk_remove_plug); | |||
1450 | */ | 1439 | */ |
1451 | void __generic_unplug_device(request_queue_t *q) | 1440 | void __generic_unplug_device(request_queue_t *q) |
1452 | { | 1441 | { |
1453 | if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)) | 1442 | if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))) |
1454 | return; | 1443 | return; |
1455 | 1444 | ||
1456 | if (!blk_remove_plug(q)) | 1445 | if (!blk_remove_plug(q)) |
@@ -1645,7 +1634,8 @@ static int blk_init_free_list(request_queue_t *q) | |||
1645 | init_waitqueue_head(&rl->wait[WRITE]); | 1634 | init_waitqueue_head(&rl->wait[WRITE]); |
1646 | init_waitqueue_head(&rl->drain); | 1635 | init_waitqueue_head(&rl->drain); |
1647 | 1636 | ||
1648 | rl->rq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, request_cachep); | 1637 | rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, |
1638 | mempool_free_slab, request_cachep, q->node); | ||
1649 | 1639 | ||
1650 | if (!rl->rq_pool) | 1640 | if (!rl->rq_pool) |
1651 | return -ENOMEM; | 1641 | return -ENOMEM; |
@@ -1657,8 +1647,15 @@ static int __make_request(request_queue_t *, struct bio *); | |||
1657 | 1647 | ||
1658 | request_queue_t *blk_alloc_queue(int gfp_mask) | 1648 | request_queue_t *blk_alloc_queue(int gfp_mask) |
1659 | { | 1649 | { |
1660 | request_queue_t *q = kmem_cache_alloc(requestq_cachep, gfp_mask); | 1650 | return blk_alloc_queue_node(gfp_mask, -1); |
1651 | } | ||
1652 | EXPORT_SYMBOL(blk_alloc_queue); | ||
1653 | |||
1654 | request_queue_t *blk_alloc_queue_node(int gfp_mask, int node_id) | ||
1655 | { | ||
1656 | request_queue_t *q; | ||
1661 | 1657 | ||
1658 | q = kmem_cache_alloc_node(requestq_cachep, gfp_mask, node_id); | ||
1662 | if (!q) | 1659 | if (!q) |
1663 | return NULL; | 1660 | return NULL; |
1664 | 1661 | ||
@@ -1671,8 +1668,7 @@ request_queue_t *blk_alloc_queue(int gfp_mask) | |||
1671 | 1668 | ||
1672 | return q; | 1669 | return q; |
1673 | } | 1670 | } |
1674 | 1671 | EXPORT_SYMBOL(blk_alloc_queue_node); | |
1675 | EXPORT_SYMBOL(blk_alloc_queue); | ||
1676 | 1672 | ||
1677 | /** | 1673 | /** |
1678 | * blk_init_queue - prepare a request queue for use with a block device | 1674 | * blk_init_queue - prepare a request queue for use with a block device |
@@ -1705,13 +1701,22 @@ EXPORT_SYMBOL(blk_alloc_queue); | |||
1705 | * blk_init_queue() must be paired with a blk_cleanup_queue() call | 1701 | * blk_init_queue() must be paired with a blk_cleanup_queue() call |
1706 | * when the block device is deactivated (such as at module unload). | 1702 | * when the block device is deactivated (such as at module unload). |
1707 | **/ | 1703 | **/ |
1704 | |||
1708 | request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock) | 1705 | request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock) |
1709 | { | 1706 | { |
1710 | request_queue_t *q = blk_alloc_queue(GFP_KERNEL); | 1707 | return blk_init_queue_node(rfn, lock, -1); |
1708 | } | ||
1709 | EXPORT_SYMBOL(blk_init_queue); | ||
1710 | |||
1711 | request_queue_t * | ||
1712 | blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) | ||
1713 | { | ||
1714 | request_queue_t *q = blk_alloc_queue_node(GFP_KERNEL, node_id); | ||
1711 | 1715 | ||
1712 | if (!q) | 1716 | if (!q) |
1713 | return NULL; | 1717 | return NULL; |
1714 | 1718 | ||
1719 | q->node = node_id; | ||
1715 | if (blk_init_free_list(q)) | 1720 | if (blk_init_free_list(q)) |
1716 | goto out_init; | 1721 | goto out_init; |
1717 | 1722 | ||
@@ -1754,12 +1759,11 @@ out_init: | |||
1754 | kmem_cache_free(requestq_cachep, q); | 1759 | kmem_cache_free(requestq_cachep, q); |
1755 | return NULL; | 1760 | return NULL; |
1756 | } | 1761 | } |
1757 | 1762 | EXPORT_SYMBOL(blk_init_queue_node); | |
1758 | EXPORT_SYMBOL(blk_init_queue); | ||
1759 | 1763 | ||
1760 | int blk_get_queue(request_queue_t *q) | 1764 | int blk_get_queue(request_queue_t *q) |
1761 | { | 1765 | { |
1762 | if (!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) { | 1766 | if (likely(!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) { |
1763 | atomic_inc(&q->refcnt); | 1767 | atomic_inc(&q->refcnt); |
1764 | return 0; | 1768 | return 0; |
1765 | } | 1769 | } |
@@ -1838,7 +1842,6 @@ static void __freed_request(request_queue_t *q, int rw) | |||
1838 | clear_queue_congested(q, rw); | 1842 | clear_queue_congested(q, rw); |
1839 | 1843 | ||
1840 | if (rl->count[rw] + 1 <= q->nr_requests) { | 1844 | if (rl->count[rw] + 1 <= q->nr_requests) { |
1841 | smp_mb(); | ||
1842 | if (waitqueue_active(&rl->wait[rw])) | 1845 | if (waitqueue_active(&rl->wait[rw])) |
1843 | wake_up(&rl->wait[rw]); | 1846 | wake_up(&rl->wait[rw]); |
1844 | 1847 | ||
@@ -1966,7 +1969,6 @@ static struct request *get_request_wait(request_queue_t *q, int rw) | |||
1966 | DEFINE_WAIT(wait); | 1969 | DEFINE_WAIT(wait); |
1967 | struct request *rq; | 1970 | struct request *rq; |
1968 | 1971 | ||
1969 | generic_unplug_device(q); | ||
1970 | do { | 1972 | do { |
1971 | struct request_list *rl = &q->rq; | 1973 | struct request_list *rl = &q->rq; |
1972 | 1974 | ||
@@ -1978,6 +1980,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw) | |||
1978 | if (!rq) { | 1980 | if (!rq) { |
1979 | struct io_context *ioc; | 1981 | struct io_context *ioc; |
1980 | 1982 | ||
1983 | generic_unplug_device(q); | ||
1981 | io_schedule(); | 1984 | io_schedule(); |
1982 | 1985 | ||
1983 | /* | 1986 | /* |
@@ -2581,7 +2584,7 @@ static int __make_request(request_queue_t *q, struct bio *bio) | |||
2581 | spin_lock_prefetch(q->queue_lock); | 2584 | spin_lock_prefetch(q->queue_lock); |
2582 | 2585 | ||
2583 | barrier = bio_barrier(bio); | 2586 | barrier = bio_barrier(bio); |
2584 | if (barrier && (q->ordered == QUEUE_ORDERED_NONE)) { | 2587 | if (unlikely(barrier) && (q->ordered == QUEUE_ORDERED_NONE)) { |
2585 | err = -EOPNOTSUPP; | 2588 | err = -EOPNOTSUPP; |
2586 | goto end_io; | 2589 | goto end_io; |
2587 | } | 2590 | } |
@@ -2682,7 +2685,7 @@ get_rq: | |||
2682 | /* | 2685 | /* |
2683 | * REQ_BARRIER implies no merging, but lets make it explicit | 2686 | * REQ_BARRIER implies no merging, but lets make it explicit |
2684 | */ | 2687 | */ |
2685 | if (barrier) | 2688 | if (unlikely(barrier)) |
2686 | req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE); | 2689 | req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE); |
2687 | 2690 | ||
2688 | req->errors = 0; | 2691 | req->errors = 0; |
@@ -2806,7 +2809,7 @@ static inline void block_wait_queue_running(request_queue_t *q) | |||
2806 | { | 2809 | { |
2807 | DEFINE_WAIT(wait); | 2810 | DEFINE_WAIT(wait); |
2808 | 2811 | ||
2809 | while (test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) { | 2812 | while (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) { |
2810 | struct request_list *rl = &q->rq; | 2813 | struct request_list *rl = &q->rq; |
2811 | 2814 | ||
2812 | prepare_to_wait_exclusive(&rl->drain, &wait, | 2815 | prepare_to_wait_exclusive(&rl->drain, &wait, |
@@ -2915,7 +2918,7 @@ end_io: | |||
2915 | goto end_io; | 2918 | goto end_io; |
2916 | } | 2919 | } |
2917 | 2920 | ||
2918 | if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) | 2921 | if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) |
2919 | goto end_io; | 2922 | goto end_io; |
2920 | 2923 | ||
2921 | block_wait_queue_running(q); | 2924 | block_wait_queue_running(q); |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6f011d0d8e..b35e08876d 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -472,17 +472,11 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) | |||
472 | */ | 472 | */ |
473 | static void loop_add_bio(struct loop_device *lo, struct bio *bio) | 473 | static void loop_add_bio(struct loop_device *lo, struct bio *bio) |
474 | { | 474 | { |
475 | unsigned long flags; | ||
476 | |||
477 | spin_lock_irqsave(&lo->lo_lock, flags); | ||
478 | if (lo->lo_biotail) { | 475 | if (lo->lo_biotail) { |
479 | lo->lo_biotail->bi_next = bio; | 476 | lo->lo_biotail->bi_next = bio; |
480 | lo->lo_biotail = bio; | 477 | lo->lo_biotail = bio; |
481 | } else | 478 | } else |
482 | lo->lo_bio = lo->lo_biotail = bio; | 479 | lo->lo_bio = lo->lo_biotail = bio; |
483 | spin_unlock_irqrestore(&lo->lo_lock, flags); | ||
484 | |||
485 | up(&lo->lo_bh_mutex); | ||
486 | } | 480 | } |
487 | 481 | ||
488 | /* | 482 | /* |
@@ -492,14 +486,12 @@ static struct bio *loop_get_bio(struct loop_device *lo) | |||
492 | { | 486 | { |
493 | struct bio *bio; | 487 | struct bio *bio; |
494 | 488 | ||
495 | spin_lock_irq(&lo->lo_lock); | ||
496 | if ((bio = lo->lo_bio)) { | 489 | if ((bio = lo->lo_bio)) { |
497 | if (bio == lo->lo_biotail) | 490 | if (bio == lo->lo_biotail) |
498 | lo->lo_biotail = NULL; | 491 | lo->lo_biotail = NULL; |
499 | lo->lo_bio = bio->bi_next; | 492 | lo->lo_bio = bio->bi_next; |
500 | bio->bi_next = NULL; | 493 | bio->bi_next = NULL; |
501 | } | 494 | } |
502 | spin_unlock_irq(&lo->lo_lock); | ||
503 | 495 | ||
504 | return bio; | 496 | return bio; |
505 | } | 497 | } |
@@ -509,35 +501,28 @@ static int loop_make_request(request_queue_t *q, struct bio *old_bio) | |||
509 | struct loop_device *lo = q->queuedata; | 501 | struct loop_device *lo = q->queuedata; |
510 | int rw = bio_rw(old_bio); | 502 | int rw = bio_rw(old_bio); |
511 | 503 | ||
512 | if (!lo) | 504 | if (rw == READA) |
513 | goto out; | 505 | rw = READ; |
506 | |||
507 | BUG_ON(!lo || (rw != READ && rw != WRITE)); | ||
514 | 508 | ||
515 | spin_lock_irq(&lo->lo_lock); | 509 | spin_lock_irq(&lo->lo_lock); |
516 | if (lo->lo_state != Lo_bound) | 510 | if (lo->lo_state != Lo_bound) |
517 | goto inactive; | 511 | goto out; |
518 | atomic_inc(&lo->lo_pending); | 512 | if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY))) |
519 | spin_unlock_irq(&lo->lo_lock); | 513 | goto out; |
520 | 514 | lo->lo_pending++; | |
521 | if (rw == WRITE) { | ||
522 | if (lo->lo_flags & LO_FLAGS_READ_ONLY) | ||
523 | goto err; | ||
524 | } else if (rw == READA) { | ||
525 | rw = READ; | ||
526 | } else if (rw != READ) { | ||
527 | printk(KERN_ERR "loop: unknown command (%x)\n", rw); | ||
528 | goto err; | ||
529 | } | ||
530 | loop_add_bio(lo, old_bio); | 515 | loop_add_bio(lo, old_bio); |
516 | spin_unlock_irq(&lo->lo_lock); | ||
517 | up(&lo->lo_bh_mutex); | ||
531 | return 0; | 518 | return 0; |
532 | err: | 519 | |
533 | if (atomic_dec_and_test(&lo->lo_pending)) | ||
534 | up(&lo->lo_bh_mutex); | ||
535 | out: | 520 | out: |
521 | if (lo->lo_pending == 0) | ||
522 | up(&lo->lo_bh_mutex); | ||
523 | spin_unlock_irq(&lo->lo_lock); | ||
536 | bio_io_error(old_bio, old_bio->bi_size); | 524 | bio_io_error(old_bio, old_bio->bi_size); |
537 | return 0; | 525 | return 0; |
538 | inactive: | ||
539 | spin_unlock_irq(&lo->lo_lock); | ||
540 | goto out; | ||
541 | } | 526 | } |
542 | 527 | ||
543 | /* | 528 | /* |
@@ -560,13 +545,11 @@ static void do_loop_switch(struct loop_device *, struct switch_request *); | |||
560 | 545 | ||
561 | static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio) | 546 | static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio) |
562 | { | 547 | { |
563 | int ret; | ||
564 | |||
565 | if (unlikely(!bio->bi_bdev)) { | 548 | if (unlikely(!bio->bi_bdev)) { |
566 | do_loop_switch(lo, bio->bi_private); | 549 | do_loop_switch(lo, bio->bi_private); |
567 | bio_put(bio); | 550 | bio_put(bio); |
568 | } else { | 551 | } else { |
569 | ret = do_bio_filebacked(lo, bio); | 552 | int ret = do_bio_filebacked(lo, bio); |
570 | bio_endio(bio, bio->bi_size, ret); | 553 | bio_endio(bio, bio->bi_size, ret); |
571 | } | 554 | } |
572 | } | 555 | } |
@@ -594,7 +577,7 @@ static int loop_thread(void *data) | |||
594 | set_user_nice(current, -20); | 577 | set_user_nice(current, -20); |
595 | 578 | ||
596 | lo->lo_state = Lo_bound; | 579 | lo->lo_state = Lo_bound; |
597 | atomic_inc(&lo->lo_pending); | 580 | lo->lo_pending = 1; |
598 | 581 | ||
599 | /* | 582 | /* |
600 | * up sem, we are running | 583 | * up sem, we are running |
@@ -602,26 +585,37 @@ static int loop_thread(void *data) | |||
602 | up(&lo->lo_sem); | 585 | up(&lo->lo_sem); |
603 | 586 | ||
604 | for (;;) { | 587 | for (;;) { |
605 | down_interruptible(&lo->lo_bh_mutex); | 588 | int pending; |
589 | |||
606 | /* | 590 | /* |
607 | * could be upped because of tear-down, not because of | 591 | * interruptible just to not contribute to load avg |
608 | * pending work | ||
609 | */ | 592 | */ |
610 | if (!atomic_read(&lo->lo_pending)) | 593 | if (down_interruptible(&lo->lo_bh_mutex)) |
594 | continue; | ||
595 | |||
596 | spin_lock_irq(&lo->lo_lock); | ||
597 | |||
598 | /* | ||
599 | * could be upped because of tear-down, not pending work | ||
600 | */ | ||
601 | if (unlikely(!lo->lo_pending)) { | ||
602 | spin_unlock_irq(&lo->lo_lock); | ||
611 | break; | 603 | break; |
604 | } | ||
612 | 605 | ||
613 | bio = loop_get_bio(lo); | 606 | bio = loop_get_bio(lo); |
614 | if (!bio) { | 607 | lo->lo_pending--; |
615 | printk("loop: missing bio\n"); | 608 | pending = lo->lo_pending; |
616 | continue; | 609 | spin_unlock_irq(&lo->lo_lock); |
617 | } | 610 | |
611 | BUG_ON(!bio); | ||
618 | loop_handle_bio(lo, bio); | 612 | loop_handle_bio(lo, bio); |
619 | 613 | ||
620 | /* | 614 | /* |
621 | * upped both for pending work and tear-down, lo_pending | 615 | * upped both for pending work and tear-down, lo_pending |
622 | * will hit zero then | 616 | * will hit zero then |
623 | */ | 617 | */ |
624 | if (atomic_dec_and_test(&lo->lo_pending)) | 618 | if (unlikely(!pending)) |
625 | break; | 619 | break; |
626 | } | 620 | } |
627 | 621 | ||
@@ -900,7 +894,8 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | |||
900 | 894 | ||
901 | spin_lock_irq(&lo->lo_lock); | 895 | spin_lock_irq(&lo->lo_lock); |
902 | lo->lo_state = Lo_rundown; | 896 | lo->lo_state = Lo_rundown; |
903 | if (atomic_dec_and_test(&lo->lo_pending)) | 897 | lo->lo_pending--; |
898 | if (!lo->lo_pending) | ||
904 | up(&lo->lo_bh_mutex); | 899 | up(&lo->lo_bh_mutex); |
905 | spin_unlock_irq(&lo->lo_lock); | 900 | spin_unlock_irq(&lo->lo_lock); |
906 | 901 | ||
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index bc56770bcc..7f3d78de26 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -467,14 +467,12 @@ static int pkt_set_speed(struct pktcdvd_device *pd, unsigned write_speed, unsign | |||
467 | * Queue a bio for processing by the low-level CD device. Must be called | 467 | * Queue a bio for processing by the low-level CD device. Must be called |
468 | * from process context. | 468 | * from process context. |
469 | */ | 469 | */ |
470 | static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio, int high_prio_read) | 470 | static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio) |
471 | { | 471 | { |
472 | spin_lock(&pd->iosched.lock); | 472 | spin_lock(&pd->iosched.lock); |
473 | if (bio_data_dir(bio) == READ) { | 473 | if (bio_data_dir(bio) == READ) { |
474 | pkt_add_list_last(bio, &pd->iosched.read_queue, | 474 | pkt_add_list_last(bio, &pd->iosched.read_queue, |
475 | &pd->iosched.read_queue_tail); | 475 | &pd->iosched.read_queue_tail); |
476 | if (high_prio_read) | ||
477 | pd->iosched.high_prio_read = 1; | ||
478 | } else { | 476 | } else { |
479 | pkt_add_list_last(bio, &pd->iosched.write_queue, | 477 | pkt_add_list_last(bio, &pd->iosched.write_queue, |
480 | &pd->iosched.write_queue_tail); | 478 | &pd->iosched.write_queue_tail); |
@@ -490,15 +488,16 @@ static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio, int high_p | |||
490 | * requirements for CDRW drives: | 488 | * requirements for CDRW drives: |
491 | * - A cache flush command must be inserted before a read request if the | 489 | * - A cache flush command must be inserted before a read request if the |
492 | * previous request was a write. | 490 | * previous request was a write. |
493 | * - Switching between reading and writing is slow, so don't it more often | 491 | * - Switching between reading and writing is slow, so don't do it more often |
494 | * than necessary. | 492 | * than necessary. |
493 | * - Optimize for throughput at the expense of latency. This means that streaming | ||
494 | * writes will never be interrupted by a read, but if the drive has to seek | ||
495 | * before the next write, switch to reading instead if there are any pending | ||
496 | * read requests. | ||
495 | * - Set the read speed according to current usage pattern. When only reading | 497 | * - Set the read speed according to current usage pattern. When only reading |
496 | * from the device, it's best to use the highest possible read speed, but | 498 | * from the device, it's best to use the highest possible read speed, but |
497 | * when switching often between reading and writing, it's better to have the | 499 | * when switching often between reading and writing, it's better to have the |
498 | * same read and write speeds. | 500 | * same read and write speeds. |
499 | * - Reads originating from user space should have higher priority than reads | ||
500 | * originating from pkt_gather_data, because some process is usually waiting | ||
501 | * on reads of the first kind. | ||
502 | */ | 501 | */ |
503 | static void pkt_iosched_process_queue(struct pktcdvd_device *pd) | 502 | static void pkt_iosched_process_queue(struct pktcdvd_device *pd) |
504 | { | 503 | { |
@@ -512,21 +511,24 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) | |||
512 | 511 | ||
513 | for (;;) { | 512 | for (;;) { |
514 | struct bio *bio; | 513 | struct bio *bio; |
515 | int reads_queued, writes_queued, high_prio_read; | 514 | int reads_queued, writes_queued; |
516 | 515 | ||
517 | spin_lock(&pd->iosched.lock); | 516 | spin_lock(&pd->iosched.lock); |
518 | reads_queued = (pd->iosched.read_queue != NULL); | 517 | reads_queued = (pd->iosched.read_queue != NULL); |
519 | writes_queued = (pd->iosched.write_queue != NULL); | 518 | writes_queued = (pd->iosched.write_queue != NULL); |
520 | if (!reads_queued) | ||
521 | pd->iosched.high_prio_read = 0; | ||
522 | high_prio_read = pd->iosched.high_prio_read; | ||
523 | spin_unlock(&pd->iosched.lock); | 519 | spin_unlock(&pd->iosched.lock); |
524 | 520 | ||
525 | if (!reads_queued && !writes_queued) | 521 | if (!reads_queued && !writes_queued) |
526 | break; | 522 | break; |
527 | 523 | ||
528 | if (pd->iosched.writing) { | 524 | if (pd->iosched.writing) { |
529 | if (high_prio_read || (!writes_queued && reads_queued)) { | 525 | int need_write_seek = 1; |
526 | spin_lock(&pd->iosched.lock); | ||
527 | bio = pd->iosched.write_queue; | ||
528 | spin_unlock(&pd->iosched.lock); | ||
529 | if (bio && (bio->bi_sector == pd->iosched.last_write)) | ||
530 | need_write_seek = 0; | ||
531 | if (need_write_seek && reads_queued) { | ||
530 | if (atomic_read(&pd->cdrw.pending_bios) > 0) { | 532 | if (atomic_read(&pd->cdrw.pending_bios) > 0) { |
531 | VPRINTK("pktcdvd: write, waiting\n"); | 533 | VPRINTK("pktcdvd: write, waiting\n"); |
532 | break; | 534 | break; |
@@ -559,8 +561,10 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) | |||
559 | 561 | ||
560 | if (bio_data_dir(bio) == READ) | 562 | if (bio_data_dir(bio) == READ) |
561 | pd->iosched.successive_reads += bio->bi_size >> 10; | 563 | pd->iosched.successive_reads += bio->bi_size >> 10; |
562 | else | 564 | else { |
563 | pd->iosched.successive_reads = 0; | 565 | pd->iosched.successive_reads = 0; |
566 | pd->iosched.last_write = bio->bi_sector + bio_sectors(bio); | ||
567 | } | ||
564 | if (pd->iosched.successive_reads >= HI_SPEED_SWITCH) { | 568 | if (pd->iosched.successive_reads >= HI_SPEED_SWITCH) { |
565 | if (pd->read_speed == pd->write_speed) { | 569 | if (pd->read_speed == pd->write_speed) { |
566 | pd->read_speed = MAX_SPEED; | 570 | pd->read_speed = MAX_SPEED; |
@@ -765,7 +769,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
765 | 769 | ||
766 | atomic_inc(&pkt->io_wait); | 770 | atomic_inc(&pkt->io_wait); |
767 | bio->bi_rw = READ; | 771 | bio->bi_rw = READ; |
768 | pkt_queue_bio(pd, bio, 0); | 772 | pkt_queue_bio(pd, bio); |
769 | frames_read++; | 773 | frames_read++; |
770 | } | 774 | } |
771 | 775 | ||
@@ -1062,7 +1066,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
1062 | 1066 | ||
1063 | atomic_set(&pkt->io_wait, 1); | 1067 | atomic_set(&pkt->io_wait, 1); |
1064 | pkt->w_bio->bi_rw = WRITE; | 1068 | pkt->w_bio->bi_rw = WRITE; |
1065 | pkt_queue_bio(pd, pkt->w_bio, 0); | 1069 | pkt_queue_bio(pd, pkt->w_bio); |
1066 | } | 1070 | } |
1067 | 1071 | ||
1068 | static void pkt_finish_packet(struct packet_data *pkt, int uptodate) | 1072 | static void pkt_finish_packet(struct packet_data *pkt, int uptodate) |
@@ -2120,7 +2124,7 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio) | |||
2120 | cloned_bio->bi_private = psd; | 2124 | cloned_bio->bi_private = psd; |
2121 | cloned_bio->bi_end_io = pkt_end_io_read_cloned; | 2125 | cloned_bio->bi_end_io = pkt_end_io_read_cloned; |
2122 | pd->stats.secs_r += bio->bi_size >> 9; | 2126 | pd->stats.secs_r += bio->bi_size >> 9; |
2123 | pkt_queue_bio(pd, cloned_bio, 1); | 2127 | pkt_queue_bio(pd, cloned_bio); |
2124 | return 0; | 2128 | return 0; |
2125 | } | 2129 | } |
2126 | 2130 | ||
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 9075bbb56a..f766bc22c6 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
@@ -576,7 +576,7 @@ static void __exit hci_uart_exit(void) | |||
576 | #endif | 576 | #endif |
577 | 577 | ||
578 | /* Release tty registration of line discipline */ | 578 | /* Release tty registration of line discipline */ |
579 | if ((err = tty_register_ldisc(N_HCI, NULL))) | 579 | if ((err = tty_unregister_ldisc(N_HCI))) |
580 | BT_ERR("Can't unregister HCI line discipline (%d)", err); | 580 | BT_ERR("Can't unregister HCI line discipline (%d)", err); |
581 | } | 581 | } |
582 | 582 | ||
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 1dc4259213..777bc499bb 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -861,13 +861,18 @@ static void change_speed(struct async_struct *info, | |||
861 | 861 | ||
862 | static void rs_put_char(struct tty_struct *tty, unsigned char ch) | 862 | static void rs_put_char(struct tty_struct *tty, unsigned char ch) |
863 | { | 863 | { |
864 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 864 | struct async_struct *info; |
865 | unsigned long flags; | 865 | unsigned long flags; |
866 | 866 | ||
867 | if (!tty) | ||
868 | return; | ||
869 | |||
870 | info = tty->driver_data; | ||
871 | |||
867 | if (serial_paranoia_check(info, tty->name, "rs_put_char")) | 872 | if (serial_paranoia_check(info, tty->name, "rs_put_char")) |
868 | return; | 873 | return; |
869 | 874 | ||
870 | if (!tty || !info->xmit.buf) | 875 | if (!info->xmit.buf) |
871 | return; | 876 | return; |
872 | 877 | ||
873 | local_irq_save(flags); | 878 | local_irq_save(flags); |
@@ -910,13 +915,18 @@ static void rs_flush_chars(struct tty_struct *tty) | |||
910 | static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) | 915 | static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) |
911 | { | 916 | { |
912 | int c, ret = 0; | 917 | int c, ret = 0; |
913 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 918 | struct async_struct *info; |
914 | unsigned long flags; | 919 | unsigned long flags; |
915 | 920 | ||
921 | if (!tty) | ||
922 | return 0; | ||
923 | |||
924 | info = tty->driver_data; | ||
925 | |||
916 | if (serial_paranoia_check(info, tty->name, "rs_write")) | 926 | if (serial_paranoia_check(info, tty->name, "rs_write")) |
917 | return 0; | 927 | return 0; |
918 | 928 | ||
919 | if (!tty || !info->xmit.buf || !tmp_buf) | 929 | if (!info->xmit.buf || !tmp_buf) |
920 | return 0; | 930 | return 0; |
921 | 931 | ||
922 | local_save_flags(flags); | 932 | local_save_flags(flags); |
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 88d1ad656e..e0a53570fe 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <asm/semaphore.h> | 45 | #include <asm/semaphore.h> |
46 | #include <linux/init.h> | 46 | #include <linux/init.h> |
47 | #include <linux/device.h> | 47 | #include <linux/device.h> |
48 | #include <linux/compat.h> | ||
48 | 49 | ||
49 | #define IPMI_DEVINTF_VERSION "v33" | 50 | #define IPMI_DEVINTF_VERSION "v33" |
50 | 51 | ||
@@ -500,10 +501,205 @@ static int ipmi_ioctl(struct inode *inode, | |||
500 | return rv; | 501 | return rv; |
501 | } | 502 | } |
502 | 503 | ||
504 | #ifdef CONFIG_COMPAT | ||
505 | |||
506 | /* | ||
507 | * The following code contains code for supporting 32-bit compatible | ||
508 | * ioctls on 64-bit kernels. This allows running 32-bit apps on the | ||
509 | * 64-bit kernel | ||
510 | */ | ||
511 | #define COMPAT_IPMICTL_SEND_COMMAND \ | ||
512 | _IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req) | ||
513 | #define COMPAT_IPMICTL_SEND_COMMAND_SETTIME \ | ||
514 | _IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime) | ||
515 | #define COMPAT_IPMICTL_RECEIVE_MSG \ | ||
516 | _IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv) | ||
517 | #define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC \ | ||
518 | _IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv) | ||
519 | |||
520 | struct compat_ipmi_msg { | ||
521 | u8 netfn; | ||
522 | u8 cmd; | ||
523 | u16 data_len; | ||
524 | compat_uptr_t data; | ||
525 | }; | ||
526 | |||
527 | struct compat_ipmi_req { | ||
528 | compat_uptr_t addr; | ||
529 | compat_uint_t addr_len; | ||
530 | compat_long_t msgid; | ||
531 | struct compat_ipmi_msg msg; | ||
532 | }; | ||
533 | |||
534 | struct compat_ipmi_recv { | ||
535 | compat_int_t recv_type; | ||
536 | compat_uptr_t addr; | ||
537 | compat_uint_t addr_len; | ||
538 | compat_long_t msgid; | ||
539 | struct compat_ipmi_msg msg; | ||
540 | }; | ||
541 | |||
542 | struct compat_ipmi_req_settime { | ||
543 | struct compat_ipmi_req req; | ||
544 | compat_int_t retries; | ||
545 | compat_uint_t retry_time_ms; | ||
546 | }; | ||
547 | |||
548 | /* | ||
549 | * Define some helper functions for copying IPMI data | ||
550 | */ | ||
551 | static long get_compat_ipmi_msg(struct ipmi_msg *p64, | ||
552 | struct compat_ipmi_msg __user *p32) | ||
553 | { | ||
554 | compat_uptr_t tmp; | ||
555 | |||
556 | if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || | ||
557 | __get_user(p64->netfn, &p32->netfn) || | ||
558 | __get_user(p64->cmd, &p32->cmd) || | ||
559 | __get_user(p64->data_len, &p32->data_len) || | ||
560 | __get_user(tmp, &p32->data)) | ||
561 | return -EFAULT; | ||
562 | p64->data = compat_ptr(tmp); | ||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static long put_compat_ipmi_msg(struct ipmi_msg *p64, | ||
567 | struct compat_ipmi_msg __user *p32) | ||
568 | { | ||
569 | if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || | ||
570 | __put_user(p64->netfn, &p32->netfn) || | ||
571 | __put_user(p64->cmd, &p32->cmd) || | ||
572 | __put_user(p64->data_len, &p32->data_len)) | ||
573 | return -EFAULT; | ||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static long get_compat_ipmi_req(struct ipmi_req *p64, | ||
578 | struct compat_ipmi_req __user *p32) | ||
579 | { | ||
580 | |||
581 | compat_uptr_t tmp; | ||
582 | |||
583 | if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || | ||
584 | __get_user(tmp, &p32->addr) || | ||
585 | __get_user(p64->addr_len, &p32->addr_len) || | ||
586 | __get_user(p64->msgid, &p32->msgid) || | ||
587 | get_compat_ipmi_msg(&p64->msg, &p32->msg)) | ||
588 | return -EFAULT; | ||
589 | p64->addr = compat_ptr(tmp); | ||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | static long get_compat_ipmi_req_settime(struct ipmi_req_settime *p64, | ||
594 | struct compat_ipmi_req_settime __user *p32) | ||
595 | { | ||
596 | if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || | ||
597 | get_compat_ipmi_req(&p64->req, &p32->req) || | ||
598 | __get_user(p64->retries, &p32->retries) || | ||
599 | __get_user(p64->retry_time_ms, &p32->retry_time_ms)) | ||
600 | return -EFAULT; | ||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static long get_compat_ipmi_recv(struct ipmi_recv *p64, | ||
605 | struct compat_ipmi_recv __user *p32) | ||
606 | { | ||
607 | compat_uptr_t tmp; | ||
608 | |||
609 | if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || | ||
610 | __get_user(p64->recv_type, &p32->recv_type) || | ||
611 | __get_user(tmp, &p32->addr) || | ||
612 | __get_user(p64->addr_len, &p32->addr_len) || | ||
613 | __get_user(p64->msgid, &p32->msgid) || | ||
614 | get_compat_ipmi_msg(&p64->msg, &p32->msg)) | ||
615 | return -EFAULT; | ||
616 | p64->addr = compat_ptr(tmp); | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static long put_compat_ipmi_recv(struct ipmi_recv *p64, | ||
621 | struct compat_ipmi_recv __user *p32) | ||
622 | { | ||
623 | if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || | ||
624 | __put_user(p64->recv_type, &p32->recv_type) || | ||
625 | __put_user(p64->addr_len, &p32->addr_len) || | ||
626 | __put_user(p64->msgid, &p32->msgid) || | ||
627 | put_compat_ipmi_msg(&p64->msg, &p32->msg)) | ||
628 | return -EFAULT; | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | /* | ||
633 | * Handle compatibility ioctls | ||
634 | */ | ||
635 | static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, | ||
636 | unsigned long arg) | ||
637 | { | ||
638 | int rc; | ||
639 | struct ipmi_file_private *priv = filep->private_data; | ||
640 | |||
641 | switch(cmd) { | ||
642 | case COMPAT_IPMICTL_SEND_COMMAND: | ||
643 | { | ||
644 | struct ipmi_req rp; | ||
645 | |||
646 | if (get_compat_ipmi_req(&rp, compat_ptr(arg))) | ||
647 | return -EFAULT; | ||
648 | |||
649 | return handle_send_req(priv->user, &rp, | ||
650 | priv->default_retries, | ||
651 | priv->default_retry_time_ms); | ||
652 | } | ||
653 | case COMPAT_IPMICTL_SEND_COMMAND_SETTIME: | ||
654 | { | ||
655 | struct ipmi_req_settime sp; | ||
656 | |||
657 | if (get_compat_ipmi_req_settime(&sp, compat_ptr(arg))) | ||
658 | return -EFAULT; | ||
659 | |||
660 | return handle_send_req(priv->user, &sp.req, | ||
661 | sp.retries, sp.retry_time_ms); | ||
662 | } | ||
663 | case COMPAT_IPMICTL_RECEIVE_MSG: | ||
664 | case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC: | ||
665 | { | ||
666 | struct ipmi_recv *precv64, recv64; | ||
667 | |||
668 | if (get_compat_ipmi_recv(&recv64, compat_ptr(arg))) | ||
669 | return -EFAULT; | ||
670 | |||
671 | precv64 = compat_alloc_user_space(sizeof(recv64)); | ||
672 | if (copy_to_user(precv64, &recv64, sizeof(recv64))) | ||
673 | return -EFAULT; | ||
674 | |||
675 | rc = ipmi_ioctl(filep->f_dentry->d_inode, filep, | ||
676 | ((cmd == COMPAT_IPMICTL_RECEIVE_MSG) | ||
677 | ? IPMICTL_RECEIVE_MSG | ||
678 | : IPMICTL_RECEIVE_MSG_TRUNC), | ||
679 | (long) precv64); | ||
680 | if (rc != 0) | ||
681 | return rc; | ||
682 | |||
683 | if (copy_from_user(&recv64, precv64, sizeof(recv64))) | ||
684 | return -EFAULT; | ||
685 | |||
686 | if (put_compat_ipmi_recv(&recv64, compat_ptr(arg))) | ||
687 | return -EFAULT; | ||
688 | |||
689 | return rc; | ||
690 | } | ||
691 | default: | ||
692 | return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg); | ||
693 | } | ||
694 | } | ||
695 | #endif | ||
503 | 696 | ||
504 | static struct file_operations ipmi_fops = { | 697 | static struct file_operations ipmi_fops = { |
505 | .owner = THIS_MODULE, | 698 | .owner = THIS_MODULE, |
506 | .ioctl = ipmi_ioctl, | 699 | .ioctl = ipmi_ioctl, |
700 | #ifdef CONFIG_COMPAT | ||
701 | .compat_ioctl = compat_ipmi_ioctl, | ||
702 | #endif | ||
507 | .open = ipmi_open, | 703 | .open = ipmi_open, |
508 | .release = ipmi_release, | 704 | .release = ipmi_release, |
509 | .fasync = ipmi_fasync, | 705 | .fasync = ipmi_fasync, |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 0c81652eab..1813d0d198 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -54,7 +54,9 @@ static int ipmi_init_msghandler(void); | |||
54 | 54 | ||
55 | static int initialized = 0; | 55 | static int initialized = 0; |
56 | 56 | ||
57 | static struct proc_dir_entry *proc_ipmi_root = NULL; | 57 | #ifdef CONFIG_PROC_FS |
58 | struct proc_dir_entry *proc_ipmi_root = NULL; | ||
59 | #endif /* CONFIG_PROC_FS */ | ||
58 | 60 | ||
59 | #define MAX_EVENTS_IN_QUEUE 25 | 61 | #define MAX_EVENTS_IN_QUEUE 25 |
60 | 62 | ||
@@ -124,11 +126,13 @@ struct ipmi_channel | |||
124 | unsigned char protocol; | 126 | unsigned char protocol; |
125 | }; | 127 | }; |
126 | 128 | ||
129 | #ifdef CONFIG_PROC_FS | ||
127 | struct ipmi_proc_entry | 130 | struct ipmi_proc_entry |
128 | { | 131 | { |
129 | char *name; | 132 | char *name; |
130 | struct ipmi_proc_entry *next; | 133 | struct ipmi_proc_entry *next; |
131 | }; | 134 | }; |
135 | #endif | ||
132 | 136 | ||
133 | #define IPMI_IPMB_NUM_SEQ 64 | 137 | #define IPMI_IPMB_NUM_SEQ 64 |
134 | #define IPMI_MAX_CHANNELS 8 | 138 | #define IPMI_MAX_CHANNELS 8 |
@@ -156,10 +160,13 @@ struct ipmi_smi | |||
156 | struct ipmi_smi_handlers *handlers; | 160 | struct ipmi_smi_handlers *handlers; |
157 | void *send_info; | 161 | void *send_info; |
158 | 162 | ||
163 | #ifdef CONFIG_PROC_FS | ||
159 | /* A list of proc entries for this interface. This does not | 164 | /* A list of proc entries for this interface. This does not |
160 | need a lock, only one thread creates it and only one thread | 165 | need a lock, only one thread creates it and only one thread |
161 | destroys it. */ | 166 | destroys it. */ |
167 | spinlock_t proc_entry_lock; | ||
162 | struct ipmi_proc_entry *proc_entries; | 168 | struct ipmi_proc_entry *proc_entries; |
169 | #endif | ||
163 | 170 | ||
164 | /* A table of sequence numbers for this interface. We use the | 171 | /* A table of sequence numbers for this interface. We use the |
165 | sequence numbers for IPMB messages that go out of the | 172 | sequence numbers for IPMB messages that go out of the |
@@ -1470,8 +1477,9 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, | |||
1470 | read_proc_t *read_proc, write_proc_t *write_proc, | 1477 | read_proc_t *read_proc, write_proc_t *write_proc, |
1471 | void *data, struct module *owner) | 1478 | void *data, struct module *owner) |
1472 | { | 1479 | { |
1473 | struct proc_dir_entry *file; | ||
1474 | int rv = 0; | 1480 | int rv = 0; |
1481 | #ifdef CONFIG_PROC_FS | ||
1482 | struct proc_dir_entry *file; | ||
1475 | struct ipmi_proc_entry *entry; | 1483 | struct ipmi_proc_entry *entry; |
1476 | 1484 | ||
1477 | /* Create a list element. */ | 1485 | /* Create a list element. */ |
@@ -1497,10 +1505,13 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, | |||
1497 | file->write_proc = write_proc; | 1505 | file->write_proc = write_proc; |
1498 | file->owner = owner; | 1506 | file->owner = owner; |
1499 | 1507 | ||
1508 | spin_lock(&smi->proc_entry_lock); | ||
1500 | /* Stick it on the list. */ | 1509 | /* Stick it on the list. */ |
1501 | entry->next = smi->proc_entries; | 1510 | entry->next = smi->proc_entries; |
1502 | smi->proc_entries = entry; | 1511 | smi->proc_entries = entry; |
1512 | spin_unlock(&smi->proc_entry_lock); | ||
1503 | } | 1513 | } |
1514 | #endif /* CONFIG_PROC_FS */ | ||
1504 | 1515 | ||
1505 | return rv; | 1516 | return rv; |
1506 | } | 1517 | } |
@@ -1509,6 +1520,7 @@ static int add_proc_entries(ipmi_smi_t smi, int num) | |||
1509 | { | 1520 | { |
1510 | int rv = 0; | 1521 | int rv = 0; |
1511 | 1522 | ||
1523 | #ifdef CONFIG_PROC_FS | ||
1512 | sprintf(smi->proc_dir_name, "%d", num); | 1524 | sprintf(smi->proc_dir_name, "%d", num); |
1513 | smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root); | 1525 | smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root); |
1514 | if (!smi->proc_dir) | 1526 | if (!smi->proc_dir) |
@@ -1531,14 +1543,17 @@ static int add_proc_entries(ipmi_smi_t smi, int num) | |||
1531 | rv = ipmi_smi_add_proc_entry(smi, "version", | 1543 | rv = ipmi_smi_add_proc_entry(smi, "version", |
1532 | version_file_read_proc, NULL, | 1544 | version_file_read_proc, NULL, |
1533 | smi, THIS_MODULE); | 1545 | smi, THIS_MODULE); |
1546 | #endif /* CONFIG_PROC_FS */ | ||
1534 | 1547 | ||
1535 | return rv; | 1548 | return rv; |
1536 | } | 1549 | } |
1537 | 1550 | ||
1538 | static void remove_proc_entries(ipmi_smi_t smi) | 1551 | static void remove_proc_entries(ipmi_smi_t smi) |
1539 | { | 1552 | { |
1553 | #ifdef CONFIG_PROC_FS | ||
1540 | struct ipmi_proc_entry *entry; | 1554 | struct ipmi_proc_entry *entry; |
1541 | 1555 | ||
1556 | spin_lock(&smi->proc_entry_lock); | ||
1542 | while (smi->proc_entries) { | 1557 | while (smi->proc_entries) { |
1543 | entry = smi->proc_entries; | 1558 | entry = smi->proc_entries; |
1544 | smi->proc_entries = entry->next; | 1559 | smi->proc_entries = entry->next; |
@@ -1547,7 +1562,9 @@ static void remove_proc_entries(ipmi_smi_t smi) | |||
1547 | kfree(entry->name); | 1562 | kfree(entry->name); |
1548 | kfree(entry); | 1563 | kfree(entry); |
1549 | } | 1564 | } |
1565 | spin_unlock(&smi->proc_entry_lock); | ||
1550 | remove_proc_entry(smi->proc_dir_name, proc_ipmi_root); | 1566 | remove_proc_entry(smi->proc_dir_name, proc_ipmi_root); |
1567 | #endif /* CONFIG_PROC_FS */ | ||
1551 | } | 1568 | } |
1552 | 1569 | ||
1553 | static int | 1570 | static int |
@@ -1694,6 +1711,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1694 | new_intf->seq_table[j].seqid = 0; | 1711 | new_intf->seq_table[j].seqid = 0; |
1695 | } | 1712 | } |
1696 | new_intf->curr_seq = 0; | 1713 | new_intf->curr_seq = 0; |
1714 | #ifdef CONFIG_PROC_FS | ||
1715 | spin_lock_init(&(new_intf->proc_entry_lock)); | ||
1716 | #endif | ||
1697 | spin_lock_init(&(new_intf->waiting_msgs_lock)); | 1717 | spin_lock_init(&(new_intf->waiting_msgs_lock)); |
1698 | INIT_LIST_HEAD(&(new_intf->waiting_msgs)); | 1718 | INIT_LIST_HEAD(&(new_intf->waiting_msgs)); |
1699 | spin_lock_init(&(new_intf->events_lock)); | 1719 | spin_lock_init(&(new_intf->events_lock)); |
@@ -2747,16 +2767,13 @@ static struct timer_list ipmi_timer; | |||
2747 | the queue and this silliness can go away. */ | 2767 | the queue and this silliness can go away. */ |
2748 | #define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME)) | 2768 | #define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME)) |
2749 | 2769 | ||
2750 | static volatile int stop_operation = 0; | 2770 | static atomic_t stop_operation; |
2751 | static volatile int timer_stopped = 0; | ||
2752 | static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME; | 2771 | static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME; |
2753 | 2772 | ||
2754 | static void ipmi_timeout(unsigned long data) | 2773 | static void ipmi_timeout(unsigned long data) |
2755 | { | 2774 | { |
2756 | if (stop_operation) { | 2775 | if (atomic_read(&stop_operation)) |
2757 | timer_stopped = 1; | ||
2758 | return; | 2776 | return; |
2759 | } | ||
2760 | 2777 | ||
2761 | ticks_to_req_ev--; | 2778 | ticks_to_req_ev--; |
2762 | if (ticks_to_req_ev == 0) { | 2779 | if (ticks_to_req_ev == 0) { |
@@ -2766,8 +2783,7 @@ static void ipmi_timeout(unsigned long data) | |||
2766 | 2783 | ||
2767 | ipmi_timeout_handler(IPMI_TIMEOUT_TIME); | 2784 | ipmi_timeout_handler(IPMI_TIMEOUT_TIME); |
2768 | 2785 | ||
2769 | ipmi_timer.expires += IPMI_TIMEOUT_JIFFIES; | 2786 | mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES); |
2770 | add_timer(&ipmi_timer); | ||
2771 | } | 2787 | } |
2772 | 2788 | ||
2773 | 2789 | ||
@@ -3089,6 +3105,7 @@ static int ipmi_init_msghandler(void) | |||
3089 | ipmi_interfaces[i] = NULL; | 3105 | ipmi_interfaces[i] = NULL; |
3090 | } | 3106 | } |
3091 | 3107 | ||
3108 | #ifdef CONFIG_PROC_FS | ||
3092 | proc_ipmi_root = proc_mkdir("ipmi", NULL); | 3109 | proc_ipmi_root = proc_mkdir("ipmi", NULL); |
3093 | if (!proc_ipmi_root) { | 3110 | if (!proc_ipmi_root) { |
3094 | printk(KERN_ERR PFX "Unable to create IPMI proc dir"); | 3111 | printk(KERN_ERR PFX "Unable to create IPMI proc dir"); |
@@ -3096,6 +3113,7 @@ static int ipmi_init_msghandler(void) | |||
3096 | } | 3113 | } |
3097 | 3114 | ||
3098 | proc_ipmi_root->owner = THIS_MODULE; | 3115 | proc_ipmi_root->owner = THIS_MODULE; |
3116 | #endif /* CONFIG_PROC_FS */ | ||
3099 | 3117 | ||
3100 | init_timer(&ipmi_timer); | 3118 | init_timer(&ipmi_timer); |
3101 | ipmi_timer.data = 0; | 3119 | ipmi_timer.data = 0; |
@@ -3130,13 +3148,12 @@ static __exit void cleanup_ipmi(void) | |||
3130 | 3148 | ||
3131 | /* Tell the timer to stop, then wait for it to stop. This avoids | 3149 | /* Tell the timer to stop, then wait for it to stop. This avoids |
3132 | problems with race conditions removing the timer here. */ | 3150 | problems with race conditions removing the timer here. */ |
3133 | stop_operation = 1; | 3151 | atomic_inc(&stop_operation); |
3134 | while (!timer_stopped) { | 3152 | del_timer_sync(&ipmi_timer); |
3135 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
3136 | schedule_timeout(1); | ||
3137 | } | ||
3138 | 3153 | ||
3154 | #ifdef CONFIG_PROC_FS | ||
3139 | remove_proc_entry(proc_ipmi_root->name, &proc_root); | 3155 | remove_proc_entry(proc_ipmi_root->name, &proc_root); |
3156 | #endif /* CONFIG_PROC_FS */ | ||
3140 | 3157 | ||
3141 | initialized = 0; | 3158 | initialized = 0; |
3142 | 3159 | ||
@@ -3177,4 +3194,5 @@ EXPORT_SYMBOL(ipmi_get_my_address); | |||
3177 | EXPORT_SYMBOL(ipmi_set_my_LUN); | 3194 | EXPORT_SYMBOL(ipmi_set_my_LUN); |
3178 | EXPORT_SYMBOL(ipmi_get_my_LUN); | 3195 | EXPORT_SYMBOL(ipmi_get_my_LUN); |
3179 | EXPORT_SYMBOL(ipmi_smi_add_proc_entry); | 3196 | EXPORT_SYMBOL(ipmi_smi_add_proc_entry); |
3197 | EXPORT_SYMBOL(proc_ipmi_root); | ||
3180 | EXPORT_SYMBOL(ipmi_user_set_run_to_completion); | 3198 | EXPORT_SYMBOL(ipmi_user_set_run_to_completion); |
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index cb5cdc6f14..f951c30236 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c | |||
@@ -31,10 +31,13 @@ | |||
31 | * with this program; if not, write to the Free Software Foundation, Inc., | 31 | * with this program; if not, write to the Free Software Foundation, Inc., |
32 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 32 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
33 | */ | 33 | */ |
34 | #include <asm/semaphore.h> | 34 | #include <linux/config.h> |
35 | #include <linux/kdev_t.h> | ||
36 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/moduleparam.h> | ||
37 | #include <linux/proc_fs.h> | ||
37 | #include <linux/string.h> | 38 | #include <linux/string.h> |
39 | #include <linux/completion.h> | ||
40 | #include <linux/kdev_t.h> | ||
38 | #include <linux/ipmi.h> | 41 | #include <linux/ipmi.h> |
39 | #include <linux/ipmi_smi.h> | 42 | #include <linux/ipmi_smi.h> |
40 | 43 | ||
@@ -44,6 +47,18 @@ | |||
44 | /* Where to we insert our poweroff function? */ | 47 | /* Where to we insert our poweroff function? */ |
45 | extern void (*pm_power_off)(void); | 48 | extern void (*pm_power_off)(void); |
46 | 49 | ||
50 | /* Definitions for controlling power off (if the system supports it). It | ||
51 | * conveniently matches the IPMI chassis control values. */ | ||
52 | #define IPMI_CHASSIS_POWER_DOWN 0 /* power down, the default. */ | ||
53 | #define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */ | ||
54 | |||
55 | /* the IPMI data command */ | ||
56 | static int poweroff_control = IPMI_CHASSIS_POWER_DOWN; | ||
57 | |||
58 | /* parameter definition to allow user to flag power cycle */ | ||
59 | module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN); | ||
60 | MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); | ||
61 | |||
47 | /* Stuff from the get device id command. */ | 62 | /* Stuff from the get device id command. */ |
48 | static unsigned int mfg_id; | 63 | static unsigned int mfg_id; |
49 | static unsigned int prod_id; | 64 | static unsigned int prod_id; |
@@ -75,10 +90,10 @@ static struct ipmi_recv_msg halt_recv_msg = | |||
75 | 90 | ||
76 | static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data) | 91 | static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data) |
77 | { | 92 | { |
78 | struct semaphore *sem = recv_msg->user_msg_data; | 93 | struct completion *comp = recv_msg->user_msg_data; |
79 | 94 | ||
80 | if (sem) | 95 | if (comp) |
81 | up(sem); | 96 | complete(comp); |
82 | } | 97 | } |
83 | 98 | ||
84 | static struct ipmi_user_hndl ipmi_poweroff_handler = | 99 | static struct ipmi_user_hndl ipmi_poweroff_handler = |
@@ -91,27 +106,27 @@ static int ipmi_request_wait_for_response(ipmi_user_t user, | |||
91 | struct ipmi_addr *addr, | 106 | struct ipmi_addr *addr, |
92 | struct kernel_ipmi_msg *send_msg) | 107 | struct kernel_ipmi_msg *send_msg) |
93 | { | 108 | { |
94 | int rv; | 109 | int rv; |
95 | struct semaphore sem; | 110 | struct completion comp; |
96 | 111 | ||
97 | sema_init (&sem, 0); | 112 | init_completion(&comp); |
98 | 113 | ||
99 | rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &sem, | 114 | rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &comp, |
100 | &halt_smi_msg, &halt_recv_msg, 0); | 115 | &halt_smi_msg, &halt_recv_msg, 0); |
101 | if (rv) | 116 | if (rv) |
102 | return rv; | 117 | return rv; |
103 | 118 | ||
104 | down (&sem); | 119 | wait_for_completion(&comp); |
105 | 120 | ||
106 | return halt_recv_msg.msg.data[0]; | 121 | return halt_recv_msg.msg.data[0]; |
107 | } | 122 | } |
108 | 123 | ||
109 | /* We are in run-to-completion mode, no semaphore is desired. */ | 124 | /* We are in run-to-completion mode, no completion is desired. */ |
110 | static int ipmi_request_in_rc_mode(ipmi_user_t user, | 125 | static int ipmi_request_in_rc_mode(ipmi_user_t user, |
111 | struct ipmi_addr *addr, | 126 | struct ipmi_addr *addr, |
112 | struct kernel_ipmi_msg *send_msg) | 127 | struct kernel_ipmi_msg *send_msg) |
113 | { | 128 | { |
114 | int rv; | 129 | int rv; |
115 | 130 | ||
116 | rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL, | 131 | rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL, |
117 | &halt_smi_msg, &halt_recv_msg, 0); | 132 | &halt_smi_msg, &halt_recv_msg, 0); |
@@ -349,26 +364,38 @@ static void ipmi_poweroff_chassis (ipmi_user_t user) | |||
349 | smi_addr.channel = IPMI_BMC_CHANNEL; | 364 | smi_addr.channel = IPMI_BMC_CHANNEL; |
350 | smi_addr.lun = 0; | 365 | smi_addr.lun = 0; |
351 | 366 | ||
352 | printk(KERN_INFO PFX "Powering down via IPMI chassis control command\n"); | 367 | powercyclefailed: |
368 | printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n", | ||
369 | ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle")); | ||
353 | 370 | ||
354 | /* | 371 | /* |
355 | * Power down | 372 | * Power down |
356 | */ | 373 | */ |
357 | send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; | 374 | send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; |
358 | send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; | 375 | send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; |
359 | data[0] = 0; /* Power down */ | 376 | data[0] = poweroff_control; |
360 | send_msg.data = data; | 377 | send_msg.data = data; |
361 | send_msg.data_len = sizeof(data); | 378 | send_msg.data_len = sizeof(data); |
362 | rv = ipmi_request_in_rc_mode(user, | 379 | rv = ipmi_request_in_rc_mode(user, |
363 | (struct ipmi_addr *) &smi_addr, | 380 | (struct ipmi_addr *) &smi_addr, |
364 | &send_msg); | 381 | &send_msg); |
365 | if (rv) { | 382 | if (rv) { |
366 | printk(KERN_ERR PFX "Unable to send chassis powerdown message," | 383 | switch (poweroff_control) { |
367 | " IPMI error 0x%x\n", rv); | 384 | case IPMI_CHASSIS_POWER_CYCLE: |
368 | goto out; | 385 | /* power cycle failed, default to power down */ |
386 | printk(KERN_ERR PFX "Unable to send chassis power " \ | ||
387 | "cycle message, IPMI error 0x%x\n", rv); | ||
388 | poweroff_control = IPMI_CHASSIS_POWER_DOWN; | ||
389 | goto powercyclefailed; | ||
390 | |||
391 | case IPMI_CHASSIS_POWER_DOWN: | ||
392 | default: | ||
393 | printk(KERN_ERR PFX "Unable to send chassis power " \ | ||
394 | "down message, IPMI error 0x%x\n", rv); | ||
395 | break; | ||
396 | } | ||
369 | } | 397 | } |
370 | 398 | ||
371 | out: | ||
372 | return; | 399 | return; |
373 | } | 400 | } |
374 | 401 | ||
@@ -430,7 +457,8 @@ static void ipmi_po_new_smi(int if_num) | |||
430 | if (ready) | 457 | if (ready) |
431 | return; | 458 | return; |
432 | 459 | ||
433 | rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, &ipmi_user); | 460 | rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, |
461 | &ipmi_user); | ||
434 | if (rv) { | 462 | if (rv) { |
435 | printk(KERN_ERR PFX "could not create IPMI user, error %d\n", | 463 | printk(KERN_ERR PFX "could not create IPMI user, error %d\n", |
436 | rv); | 464 | rv); |
@@ -509,21 +537,84 @@ static struct ipmi_smi_watcher smi_watcher = | |||
509 | }; | 537 | }; |
510 | 538 | ||
511 | 539 | ||
540 | #ifdef CONFIG_PROC_FS | ||
541 | /* displays properties to proc */ | ||
542 | static int proc_read_chassctrl(char *page, char **start, off_t off, int count, | ||
543 | int *eof, void *data) | ||
544 | { | ||
545 | return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n", | ||
546 | poweroff_control); | ||
547 | } | ||
548 | |||
549 | /* process property writes from proc */ | ||
550 | static int proc_write_chassctrl(struct file *file, const char *buffer, | ||
551 | unsigned long count, void *data) | ||
552 | { | ||
553 | int rv = count; | ||
554 | unsigned int newval = 0; | ||
555 | |||
556 | sscanf(buffer, "%d", &newval); | ||
557 | switch (newval) { | ||
558 | case IPMI_CHASSIS_POWER_CYCLE: | ||
559 | printk(KERN_INFO PFX "power cycle is now enabled\n"); | ||
560 | poweroff_control = newval; | ||
561 | break; | ||
562 | |||
563 | case IPMI_CHASSIS_POWER_DOWN: | ||
564 | poweroff_control = IPMI_CHASSIS_POWER_DOWN; | ||
565 | break; | ||
566 | |||
567 | default: | ||
568 | rv = -EINVAL; | ||
569 | break; | ||
570 | } | ||
571 | |||
572 | return rv; | ||
573 | } | ||
574 | #endif /* CONFIG_PROC_FS */ | ||
575 | |||
512 | /* | 576 | /* |
513 | * Startup and shutdown functions. | 577 | * Startup and shutdown functions. |
514 | */ | 578 | */ |
515 | static int ipmi_poweroff_init (void) | 579 | static int ipmi_poweroff_init (void) |
516 | { | 580 | { |
517 | int rv; | 581 | int rv; |
582 | struct proc_dir_entry *file; | ||
518 | 583 | ||
519 | printk ("Copyright (C) 2004 MontaVista Software -" | 584 | printk ("Copyright (C) 2004 MontaVista Software -" |
520 | " IPMI Powerdown via sys_reboot version " | 585 | " IPMI Powerdown via sys_reboot version " |
521 | IPMI_POWEROFF_VERSION ".\n"); | 586 | IPMI_POWEROFF_VERSION ".\n"); |
522 | 587 | ||
588 | switch (poweroff_control) { | ||
589 | case IPMI_CHASSIS_POWER_CYCLE: | ||
590 | printk(KERN_INFO PFX "Power cycle is enabled.\n"); | ||
591 | break; | ||
592 | |||
593 | case IPMI_CHASSIS_POWER_DOWN: | ||
594 | default: | ||
595 | poweroff_control = IPMI_CHASSIS_POWER_DOWN; | ||
596 | break; | ||
597 | } | ||
598 | |||
523 | rv = ipmi_smi_watcher_register(&smi_watcher); | 599 | rv = ipmi_smi_watcher_register(&smi_watcher); |
524 | if (rv) | 600 | if (rv) { |
525 | printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); | 601 | printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); |
602 | goto out_err; | ||
603 | } | ||
604 | |||
605 | #ifdef CONFIG_PROC_FS | ||
606 | file = create_proc_entry("poweroff_control", 0, proc_ipmi_root); | ||
607 | if (!file) { | ||
608 | printk(KERN_ERR PFX "Unable to create proc power control\n"); | ||
609 | } else { | ||
610 | file->nlink = 1; | ||
611 | file->read_proc = proc_read_chassctrl; | ||
612 | file->write_proc = proc_write_chassctrl; | ||
613 | file->owner = THIS_MODULE; | ||
614 | } | ||
615 | #endif | ||
526 | 616 | ||
617 | out_err: | ||
527 | return rv; | 618 | return rv; |
528 | } | 619 | } |
529 | 620 | ||
@@ -532,6 +623,10 @@ static __exit void ipmi_poweroff_cleanup(void) | |||
532 | { | 623 | { |
533 | int rv; | 624 | int rv; |
534 | 625 | ||
626 | #ifdef CONFIG_PROC_FS | ||
627 | remove_proc_entry("poweroff_control", proc_ipmi_root); | ||
628 | #endif | ||
629 | |||
535 | ipmi_smi_watcher_unregister(&smi_watcher); | 630 | ipmi_smi_watcher_unregister(&smi_watcher); |
536 | 631 | ||
537 | if (ready) { | 632 | if (ready) { |
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index b3dbff1cf9..5079beda69 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
@@ -960,7 +960,7 @@ static char hdlc_unregister_fail[] __exitdata = | |||
960 | static void __exit n_hdlc_exit(void) | 960 | static void __exit n_hdlc_exit(void) |
961 | { | 961 | { |
962 | /* Release tty registration of line discipline */ | 962 | /* Release tty registration of line discipline */ |
963 | int status = tty_register_ldisc(N_HDLC, NULL); | 963 | int status = tty_unregister_ldisc(N_HDLC); |
964 | 964 | ||
965 | if (status) | 965 | if (status) |
966 | printk(hdlc_unregister_fail, status); | 966 | printk(hdlc_unregister_fail, status); |
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 3883073ab4..2291a87e8a 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -200,7 +200,7 @@ static void __exit r3964_exit(void) | |||
200 | 200 | ||
201 | TRACE_M ("cleanup_module()"); | 201 | TRACE_M ("cleanup_module()"); |
202 | 202 | ||
203 | status=tty_register_ldisc(N_R3964, NULL); | 203 | status=tty_unregister_ldisc(N_R3964); |
204 | 204 | ||
205 | if(status!=0) | 205 | if(status!=0) |
206 | { | 206 | { |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 8ce508b298..5c843c9bf8 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * | 19 | * |
20 | * Note, the TPM chip is not interrupt driven (only polling) | 20 | * Note, the TPM chip is not interrupt driven (only polling) |
21 | * and can have very long timeouts (minutes!). Hence the unusual | 21 | * and can have very long timeouts (minutes!). Hence the unusual |
22 | * calls to schedule_timeout. | 22 | * calls to msleep. |
23 | * | 23 | * |
24 | */ | 24 | */ |
25 | 25 | ||
@@ -28,19 +28,16 @@ | |||
28 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
29 | #include "tpm.h" | 29 | #include "tpm.h" |
30 | 30 | ||
31 | #define TPM_MINOR 224 /* officially assigned */ | 31 | enum tpm_const { |
32 | 32 | TPM_MINOR = 224, /* officially assigned */ | |
33 | #define TPM_BUFSIZE 2048 | 33 | TPM_BUFSIZE = 2048, |
34 | 34 | TPM_NUM_DEVICES = 256, | |
35 | /* PCI configuration addresses */ | 35 | TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int)) |
36 | #define PCI_GEN_PMCON_1 0xA0 | 36 | }; |
37 | #define PCI_GEN1_DEC 0xE4 | ||
38 | #define PCI_LPC_EN 0xE6 | ||
39 | #define PCI_GEN2_DEC 0xEC | ||
40 | 37 | ||
41 | static LIST_HEAD(tpm_chip_list); | 38 | static LIST_HEAD(tpm_chip_list); |
42 | static DEFINE_SPINLOCK(driver_lock); | 39 | static DEFINE_SPINLOCK(driver_lock); |
43 | static int dev_mask[32]; | 40 | static int dev_mask[TPM_NUM_MASK_ENTRIES]; |
44 | 41 | ||
45 | static void user_reader_timeout(unsigned long ptr) | 42 | static void user_reader_timeout(unsigned long ptr) |
46 | { | 43 | { |
@@ -52,92 +49,17 @@ static void user_reader_timeout(unsigned long ptr) | |||
52 | up(&chip->buffer_mutex); | 49 | up(&chip->buffer_mutex); |
53 | } | 50 | } |
54 | 51 | ||
55 | void tpm_time_expired(unsigned long ptr) | ||
56 | { | ||
57 | int *exp = (int *) ptr; | ||
58 | *exp = 1; | ||
59 | } | ||
60 | |||
61 | EXPORT_SYMBOL_GPL(tpm_time_expired); | ||
62 | |||
63 | /* | ||
64 | * Initialize the LPC bus and enable the TPM ports | ||
65 | */ | ||
66 | int tpm_lpc_bus_init(struct pci_dev *pci_dev, u16 base) | ||
67 | { | ||
68 | u32 lpcenable, tmp; | ||
69 | int is_lpcm = 0; | ||
70 | |||
71 | switch (pci_dev->vendor) { | ||
72 | case PCI_VENDOR_ID_INTEL: | ||
73 | switch (pci_dev->device) { | ||
74 | case PCI_DEVICE_ID_INTEL_82801CA_12: | ||
75 | case PCI_DEVICE_ID_INTEL_82801DB_12: | ||
76 | is_lpcm = 1; | ||
77 | break; | ||
78 | } | ||
79 | /* init ICH (enable LPC) */ | ||
80 | pci_read_config_dword(pci_dev, PCI_GEN1_DEC, &lpcenable); | ||
81 | lpcenable |= 0x20000000; | ||
82 | pci_write_config_dword(pci_dev, PCI_GEN1_DEC, lpcenable); | ||
83 | |||
84 | if (is_lpcm) { | ||
85 | pci_read_config_dword(pci_dev, PCI_GEN1_DEC, | ||
86 | &lpcenable); | ||
87 | if ((lpcenable & 0x20000000) == 0) { | ||
88 | dev_err(&pci_dev->dev, | ||
89 | "cannot enable LPC\n"); | ||
90 | return -ENODEV; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | /* initialize TPM registers */ | ||
95 | pci_read_config_dword(pci_dev, PCI_GEN2_DEC, &tmp); | ||
96 | |||
97 | if (!is_lpcm) | ||
98 | tmp = (tmp & 0xFFFF0000) | (base & 0xFFF0); | ||
99 | else | ||
100 | tmp = | ||
101 | (tmp & 0xFFFF0000) | (base & 0xFFF0) | | ||
102 | 0x00000001; | ||
103 | |||
104 | pci_write_config_dword(pci_dev, PCI_GEN2_DEC, tmp); | ||
105 | |||
106 | if (is_lpcm) { | ||
107 | pci_read_config_dword(pci_dev, PCI_GEN_PMCON_1, | ||
108 | &tmp); | ||
109 | tmp |= 0x00000004; /* enable CLKRUN */ | ||
110 | pci_write_config_dword(pci_dev, PCI_GEN_PMCON_1, | ||
111 | tmp); | ||
112 | } | ||
113 | tpm_write_index(0x0D, 0x55); /* unlock 4F */ | ||
114 | tpm_write_index(0x0A, 0x00); /* int disable */ | ||
115 | tpm_write_index(0x08, base); /* base addr lo */ | ||
116 | tpm_write_index(0x09, (base & 0xFF00) >> 8); /* base addr hi */ | ||
117 | tpm_write_index(0x0D, 0xAA); /* lock 4F */ | ||
118 | break; | ||
119 | case PCI_VENDOR_ID_AMD: | ||
120 | /* nothing yet */ | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | EXPORT_SYMBOL_GPL(tpm_lpc_bus_init); | ||
128 | |||
129 | /* | 52 | /* |
130 | * Internal kernel interface to transmit TPM commands | 53 | * Internal kernel interface to transmit TPM commands |
131 | */ | 54 | */ |
132 | static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | 55 | static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, |
133 | size_t bufsiz) | 56 | size_t bufsiz) |
134 | { | 57 | { |
135 | ssize_t len; | 58 | ssize_t rc; |
136 | u32 count; | 59 | u32 count; |
137 | __be32 *native_size; | 60 | unsigned long stop; |
138 | 61 | ||
139 | native_size = (__force __be32 *) (buf + 2); | 62 | count = be32_to_cpu(*((__be32 *) (buf + 2))); |
140 | count = be32_to_cpu(*native_size); | ||
141 | 63 | ||
142 | if (count == 0) | 64 | if (count == 0) |
143 | return -ENODATA; | 65 | return -ENODATA; |
@@ -149,53 +71,49 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
149 | 71 | ||
150 | down(&chip->tpm_mutex); | 72 | down(&chip->tpm_mutex); |
151 | 73 | ||
152 | if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) { | 74 | if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) { |
153 | dev_err(&chip->pci_dev->dev, | 75 | dev_err(&chip->pci_dev->dev, |
154 | "tpm_transmit: tpm_send: error %zd\n", len); | 76 | "tpm_transmit: tpm_send: error %zd\n", rc); |
155 | return len; | 77 | goto out; |
156 | } | 78 | } |
157 | 79 | ||
158 | down(&chip->timer_manipulation_mutex); | 80 | stop = jiffies + 2 * 60 * HZ; |
159 | chip->time_expired = 0; | ||
160 | init_timer(&chip->device_timer); | ||
161 | chip->device_timer.function = tpm_time_expired; | ||
162 | chip->device_timer.expires = jiffies + 2 * 60 * HZ; | ||
163 | chip->device_timer.data = (unsigned long) &chip->time_expired; | ||
164 | add_timer(&chip->device_timer); | ||
165 | up(&chip->timer_manipulation_mutex); | ||
166 | |||
167 | do { | 81 | do { |
168 | u8 status = inb(chip->vendor->base + 1); | 82 | u8 status = inb(chip->vendor->base + 1); |
169 | if ((status & chip->vendor->req_complete_mask) == | 83 | if ((status & chip->vendor->req_complete_mask) == |
170 | chip->vendor->req_complete_val) { | 84 | chip->vendor->req_complete_val) { |
171 | down(&chip->timer_manipulation_mutex); | ||
172 | del_singleshot_timer_sync(&chip->device_timer); | ||
173 | up(&chip->timer_manipulation_mutex); | ||
174 | goto out_recv; | 85 | goto out_recv; |
175 | } | 86 | } |
176 | set_current_state(TASK_UNINTERRUPTIBLE); | 87 | |
177 | schedule_timeout(TPM_TIMEOUT); | 88 | if ((status == chip->vendor->req_canceled)) { |
89 | dev_err(&chip->pci_dev->dev, "Operation Canceled\n"); | ||
90 | rc = -ECANCELED; | ||
91 | goto out; | ||
92 | } | ||
93 | |||
94 | msleep(TPM_TIMEOUT); /* CHECK */ | ||
178 | rmb(); | 95 | rmb(); |
179 | } while (!chip->time_expired); | 96 | } while (time_before(jiffies, stop)); |
180 | 97 | ||
181 | 98 | ||
182 | chip->vendor->cancel(chip); | 99 | chip->vendor->cancel(chip); |
183 | dev_err(&chip->pci_dev->dev, "Time expired\n"); | 100 | dev_err(&chip->pci_dev->dev, "Operation Timed out\n"); |
184 | up(&chip->tpm_mutex); | 101 | rc = -ETIME; |
185 | return -EIO; | 102 | goto out; |
186 | 103 | ||
187 | out_recv: | 104 | out_recv: |
188 | len = chip->vendor->recv(chip, (u8 *) buf, bufsiz); | 105 | rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz); |
189 | if (len < 0) | 106 | if (rc < 0) |
190 | dev_err(&chip->pci_dev->dev, | 107 | dev_err(&chip->pci_dev->dev, |
191 | "tpm_transmit: tpm_recv: error %zd\n", len); | 108 | "tpm_transmit: tpm_recv: error %zd\n", rc); |
109 | out: | ||
192 | up(&chip->tpm_mutex); | 110 | up(&chip->tpm_mutex); |
193 | return len; | 111 | return rc; |
194 | } | 112 | } |
195 | 113 | ||
196 | #define TPM_DIGEST_SIZE 20 | 114 | #define TPM_DIGEST_SIZE 20 |
197 | #define CAP_PCR_RESULT_SIZE 18 | 115 | #define CAP_PCR_RESULT_SIZE 18 |
198 | static u8 cap_pcr[] = { | 116 | static const u8 cap_pcr[] = { |
199 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 117 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
200 | 0, 0, 0, 22, /* length */ | 118 | 0, 0, 0, 22, /* length */ |
201 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | 119 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ |
@@ -205,75 +123,94 @@ static u8 cap_pcr[] = { | |||
205 | }; | 123 | }; |
206 | 124 | ||
207 | #define READ_PCR_RESULT_SIZE 30 | 125 | #define READ_PCR_RESULT_SIZE 30 |
208 | static u8 pcrread[] = { | 126 | static const u8 pcrread[] = { |
209 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 127 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
210 | 0, 0, 0, 14, /* length */ | 128 | 0, 0, 0, 14, /* length */ |
211 | 0, 0, 0, 21, /* TPM_ORD_PcrRead */ | 129 | 0, 0, 0, 21, /* TPM_ORD_PcrRead */ |
212 | 0, 0, 0, 0 /* PCR index */ | 130 | 0, 0, 0, 0 /* PCR index */ |
213 | }; | 131 | }; |
214 | 132 | ||
215 | static ssize_t show_pcrs(struct device *dev, struct device_attribute *attr, char *buf) | 133 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, |
134 | char *buf) | ||
216 | { | 135 | { |
217 | u8 data[READ_PCR_RESULT_SIZE]; | 136 | u8 data[READ_PCR_RESULT_SIZE]; |
218 | ssize_t len; | 137 | ssize_t len; |
219 | int i, j, index, num_pcrs; | 138 | int i, j, num_pcrs; |
139 | __be32 index; | ||
220 | char *str = buf; | 140 | char *str = buf; |
221 | 141 | ||
222 | struct tpm_chip *chip = | 142 | struct tpm_chip *chip = |
223 | pci_get_drvdata(container_of(dev, struct pci_dev, dev)); | 143 | pci_get_drvdata(to_pci_dev(dev)); |
224 | if (chip == NULL) | 144 | if (chip == NULL) |
225 | return -ENODEV; | 145 | return -ENODEV; |
226 | 146 | ||
227 | memcpy(data, cap_pcr, sizeof(cap_pcr)); | 147 | memcpy(data, cap_pcr, sizeof(cap_pcr)); |
228 | if ((len = tpm_transmit(chip, data, sizeof(data))) | 148 | if ((len = tpm_transmit(chip, data, sizeof(data))) |
229 | < CAP_PCR_RESULT_SIZE) | 149 | < CAP_PCR_RESULT_SIZE) { |
230 | return len; | 150 | dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred " |
151 | "attempting to determine the number of PCRS\n", | ||
152 | be32_to_cpu(*((__be32 *) (data + 6)))); | ||
153 | return 0; | ||
154 | } | ||
231 | 155 | ||
232 | num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14))); | 156 | num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); |
233 | 157 | ||
234 | for (i = 0; i < num_pcrs; i++) { | 158 | for (i = 0; i < num_pcrs; i++) { |
235 | memcpy(data, pcrread, sizeof(pcrread)); | 159 | memcpy(data, pcrread, sizeof(pcrread)); |
236 | index = cpu_to_be32(i); | 160 | index = cpu_to_be32(i); |
237 | memcpy(data + 10, &index, 4); | 161 | memcpy(data + 10, &index, 4); |
238 | if ((len = tpm_transmit(chip, data, sizeof(data))) | 162 | if ((len = tpm_transmit(chip, data, sizeof(data))) |
239 | < READ_PCR_RESULT_SIZE) | 163 | < READ_PCR_RESULT_SIZE){ |
240 | return len; | 164 | dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred" |
165 | " attempting to read PCR %d of %d\n", | ||
166 | be32_to_cpu(*((__be32 *) (data + 6))), i, num_pcrs); | ||
167 | goto out; | ||
168 | } | ||
241 | str += sprintf(str, "PCR-%02d: ", i); | 169 | str += sprintf(str, "PCR-%02d: ", i); |
242 | for (j = 0; j < TPM_DIGEST_SIZE; j++) | 170 | for (j = 0; j < TPM_DIGEST_SIZE; j++) |
243 | str += sprintf(str, "%02X ", *(data + 10 + j)); | 171 | str += sprintf(str, "%02X ", *(data + 10 + j)); |
244 | str += sprintf(str, "\n"); | 172 | str += sprintf(str, "\n"); |
245 | } | 173 | } |
174 | out: | ||
246 | return str - buf; | 175 | return str - buf; |
247 | } | 176 | } |
248 | 177 | EXPORT_SYMBOL_GPL(tpm_show_pcrs); | |
249 | static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL); | ||
250 | 178 | ||
251 | #define READ_PUBEK_RESULT_SIZE 314 | 179 | #define READ_PUBEK_RESULT_SIZE 314 |
252 | static u8 readpubek[] = { | 180 | static const u8 readpubek[] = { |
253 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 181 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
254 | 0, 0, 0, 30, /* length */ | 182 | 0, 0, 0, 30, /* length */ |
255 | 0, 0, 0, 124, /* TPM_ORD_ReadPubek */ | 183 | 0, 0, 0, 124, /* TPM_ORD_ReadPubek */ |
256 | }; | 184 | }; |
257 | 185 | ||
258 | static ssize_t show_pubek(struct device *dev, struct device_attribute *attr, char *buf) | 186 | ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, |
187 | char *buf) | ||
259 | { | 188 | { |
260 | u8 data[READ_PUBEK_RESULT_SIZE]; | 189 | u8 *data; |
261 | ssize_t len; | 190 | ssize_t len; |
262 | __be32 *native_val; | 191 | int i, rc; |
263 | int i; | ||
264 | char *str = buf; | 192 | char *str = buf; |
265 | 193 | ||
266 | struct tpm_chip *chip = | 194 | struct tpm_chip *chip = |
267 | pci_get_drvdata(container_of(dev, struct pci_dev, dev)); | 195 | pci_get_drvdata(to_pci_dev(dev)); |
268 | if (chip == NULL) | 196 | if (chip == NULL) |
269 | return -ENODEV; | 197 | return -ENODEV; |
270 | 198 | ||
199 | data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL); | ||
200 | if (!data) | ||
201 | return -ENOMEM; | ||
202 | |||
271 | memcpy(data, readpubek, sizeof(readpubek)); | 203 | memcpy(data, readpubek, sizeof(readpubek)); |
272 | memset(data + sizeof(readpubek), 0, 20); /* zero nonce */ | 204 | memset(data + sizeof(readpubek), 0, 20); /* zero nonce */ |
273 | 205 | ||
274 | if ((len = tpm_transmit(chip, data, sizeof(data))) < | 206 | if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) < |
275 | READ_PUBEK_RESULT_SIZE) | 207 | READ_PUBEK_RESULT_SIZE) { |
276 | return len; | 208 | dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred " |
209 | "attempting to read the PUBEK\n", | ||
210 | be32_to_cpu(*((__be32 *) (data + 6)))); | ||
211 | rc = 0; | ||
212 | goto out; | ||
213 | } | ||
277 | 214 | ||
278 | /* | 215 | /* |
279 | ignore header 10 bytes | 216 | ignore header 10 bytes |
@@ -286,8 +223,6 @@ static ssize_t show_pubek(struct device *dev, struct device_attribute *attr, cha | |||
286 | ignore checksum 20 bytes | 223 | ignore checksum 20 bytes |
287 | */ | 224 | */ |
288 | 225 | ||
289 | native_val = (__force __be32 *) (data + 34); | ||
290 | |||
291 | str += | 226 | str += |
292 | sprintf(str, | 227 | sprintf(str, |
293 | "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" | 228 | "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" |
@@ -298,21 +233,23 @@ static ssize_t show_pubek(struct device *dev, struct device_attribute *attr, cha | |||
298 | data[15], data[16], data[17], data[22], data[23], | 233 | data[15], data[16], data[17], data[22], data[23], |
299 | data[24], data[25], data[26], data[27], data[28], | 234 | data[24], data[25], data[26], data[27], data[28], |
300 | data[29], data[30], data[31], data[32], data[33], | 235 | data[29], data[30], data[31], data[32], data[33], |
301 | be32_to_cpu(*native_val) | 236 | be32_to_cpu(*((__be32 *) (data + 32)))); |
302 | ); | ||
303 | 237 | ||
304 | for (i = 0; i < 256; i++) { | 238 | for (i = 0; i < 256; i++) { |
305 | str += sprintf(str, "%02X ", data[i + 39]); | 239 | str += sprintf(str, "%02X ", data[i + 39]); |
306 | if ((i + 1) % 16 == 0) | 240 | if ((i + 1) % 16 == 0) |
307 | str += sprintf(str, "\n"); | 241 | str += sprintf(str, "\n"); |
308 | } | 242 | } |
309 | return str - buf; | 243 | rc = str - buf; |
244 | out: | ||
245 | kfree(data); | ||
246 | return rc; | ||
310 | } | 247 | } |
311 | 248 | ||
312 | static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL); | 249 | EXPORT_SYMBOL_GPL(tpm_show_pubek); |
313 | 250 | ||
314 | #define CAP_VER_RESULT_SIZE 18 | 251 | #define CAP_VER_RESULT_SIZE 18 |
315 | static u8 cap_version[] = { | 252 | static const u8 cap_version[] = { |
316 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 253 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
317 | 0, 0, 0, 18, /* length */ | 254 | 0, 0, 0, 18, /* length */ |
318 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | 255 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ |
@@ -321,7 +258,7 @@ static u8 cap_version[] = { | |||
321 | }; | 258 | }; |
322 | 259 | ||
323 | #define CAP_MANUFACTURER_RESULT_SIZE 18 | 260 | #define CAP_MANUFACTURER_RESULT_SIZE 18 |
324 | static u8 cap_manufacturer[] = { | 261 | static const u8 cap_manufacturer[] = { |
325 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 262 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
326 | 0, 0, 0, 22, /* length */ | 263 | 0, 0, 0, 22, /* length */ |
327 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | 264 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ |
@@ -330,14 +267,15 @@ static u8 cap_manufacturer[] = { | |||
330 | 0, 0, 1, 3 | 267 | 0, 0, 1, 3 |
331 | }; | 268 | }; |
332 | 269 | ||
333 | static ssize_t show_caps(struct device *dev, struct device_attribute *attr, char *buf) | 270 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, |
271 | char *buf) | ||
334 | { | 272 | { |
335 | u8 data[READ_PUBEK_RESULT_SIZE]; | 273 | u8 data[sizeof(cap_manufacturer)]; |
336 | ssize_t len; | 274 | ssize_t len; |
337 | char *str = buf; | 275 | char *str = buf; |
338 | 276 | ||
339 | struct tpm_chip *chip = | 277 | struct tpm_chip *chip = |
340 | pci_get_drvdata(container_of(dev, struct pci_dev, dev)); | 278 | pci_get_drvdata(to_pci_dev(dev)); |
341 | if (chip == NULL) | 279 | if (chip == NULL) |
342 | return -ENODEV; | 280 | return -ENODEV; |
343 | 281 | ||
@@ -348,7 +286,7 @@ static ssize_t show_caps(struct device *dev, struct device_attribute *attr, char | |||
348 | return len; | 286 | return len; |
349 | 287 | ||
350 | str += sprintf(str, "Manufacturer: 0x%x\n", | 288 | str += sprintf(str, "Manufacturer: 0x%x\n", |
351 | be32_to_cpu(*(data + 14))); | 289 | be32_to_cpu(*((__be32 *) (data + 14)))); |
352 | 290 | ||
353 | memcpy(data, cap_version, sizeof(cap_version)); | 291 | memcpy(data, cap_version, sizeof(cap_version)); |
354 | 292 | ||
@@ -363,8 +301,20 @@ static ssize_t show_caps(struct device *dev, struct device_attribute *attr, char | |||
363 | 301 | ||
364 | return str - buf; | 302 | return str - buf; |
365 | } | 303 | } |
304 | EXPORT_SYMBOL_GPL(tpm_show_caps); | ||
305 | |||
306 | ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, | ||
307 | const char *buf, size_t count) | ||
308 | { | ||
309 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
310 | if (chip == NULL) | ||
311 | return 0; | ||
312 | |||
313 | chip->vendor->cancel(chip); | ||
314 | return count; | ||
315 | } | ||
316 | EXPORT_SYMBOL_GPL(tpm_store_cancel); | ||
366 | 317 | ||
367 | static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL); | ||
368 | 318 | ||
369 | /* | 319 | /* |
370 | * Device file system interface to the TPM | 320 | * Device file system interface to the TPM |
@@ -422,24 +372,15 @@ EXPORT_SYMBOL_GPL(tpm_open); | |||
422 | int tpm_release(struct inode *inode, struct file *file) | 372 | int tpm_release(struct inode *inode, struct file *file) |
423 | { | 373 | { |
424 | struct tpm_chip *chip = file->private_data; | 374 | struct tpm_chip *chip = file->private_data; |
425 | |||
426 | file->private_data = NULL; | ||
427 | 375 | ||
428 | spin_lock(&driver_lock); | 376 | spin_lock(&driver_lock); |
377 | file->private_data = NULL; | ||
429 | chip->num_opens--; | 378 | chip->num_opens--; |
430 | spin_unlock(&driver_lock); | 379 | del_singleshot_timer_sync(&chip->user_read_timer); |
431 | |||
432 | down(&chip->timer_manipulation_mutex); | ||
433 | if (timer_pending(&chip->user_read_timer)) | ||
434 | del_singleshot_timer_sync(&chip->user_read_timer); | ||
435 | else if (timer_pending(&chip->device_timer)) | ||
436 | del_singleshot_timer_sync(&chip->device_timer); | ||
437 | up(&chip->timer_manipulation_mutex); | ||
438 | |||
439 | kfree(chip->data_buffer); | ||
440 | atomic_set(&chip->data_pending, 0); | 380 | atomic_set(&chip->data_pending, 0); |
441 | |||
442 | pci_dev_put(chip->pci_dev); | 381 | pci_dev_put(chip->pci_dev); |
382 | kfree(chip->data_buffer); | ||
383 | spin_unlock(&driver_lock); | ||
443 | return 0; | 384 | return 0; |
444 | } | 385 | } |
445 | 386 | ||
@@ -453,10 +394,8 @@ ssize_t tpm_write(struct file * file, const char __user * buf, | |||
453 | 394 | ||
454 | /* cannot perform a write until the read has cleared | 395 | /* cannot perform a write until the read has cleared |
455 | either via tpm_read or a user_read_timer timeout */ | 396 | either via tpm_read or a user_read_timer timeout */ |
456 | while (atomic_read(&chip->data_pending) != 0) { | 397 | while (atomic_read(&chip->data_pending) != 0) |
457 | set_current_state(TASK_UNINTERRUPTIBLE); | 398 | msleep(TPM_TIMEOUT); |
458 | schedule_timeout(TPM_TIMEOUT); | ||
459 | } | ||
460 | 399 | ||
461 | down(&chip->buffer_mutex); | 400 | down(&chip->buffer_mutex); |
462 | 401 | ||
@@ -476,13 +415,7 @@ ssize_t tpm_write(struct file * file, const char __user * buf, | |||
476 | up(&chip->buffer_mutex); | 415 | up(&chip->buffer_mutex); |
477 | 416 | ||
478 | /* Set a timeout by which the reader must come claim the result */ | 417 | /* Set a timeout by which the reader must come claim the result */ |
479 | down(&chip->timer_manipulation_mutex); | 418 | mod_timer(&chip->user_read_timer, jiffies + (60 * HZ)); |
480 | init_timer(&chip->user_read_timer); | ||
481 | chip->user_read_timer.function = user_reader_timeout; | ||
482 | chip->user_read_timer.data = (unsigned long) chip; | ||
483 | chip->user_read_timer.expires = jiffies + (60 * HZ); | ||
484 | add_timer(&chip->user_read_timer); | ||
485 | up(&chip->timer_manipulation_mutex); | ||
486 | 419 | ||
487 | return in_size; | 420 | return in_size; |
488 | } | 421 | } |
@@ -493,29 +426,19 @@ ssize_t tpm_read(struct file * file, char __user * buf, | |||
493 | size_t size, loff_t * off) | 426 | size_t size, loff_t * off) |
494 | { | 427 | { |
495 | struct tpm_chip *chip = file->private_data; | 428 | struct tpm_chip *chip = file->private_data; |
496 | int ret_size = -ENODATA; | 429 | int ret_size; |
497 | 430 | ||
498 | if (atomic_read(&chip->data_pending) != 0) { /* Result available */ | 431 | del_singleshot_timer_sync(&chip->user_read_timer); |
499 | down(&chip->timer_manipulation_mutex); | 432 | ret_size = atomic_read(&chip->data_pending); |
500 | del_singleshot_timer_sync(&chip->user_read_timer); | 433 | atomic_set(&chip->data_pending, 0); |
501 | up(&chip->timer_manipulation_mutex); | 434 | if (ret_size > 0) { /* relay data */ |
435 | if (size < ret_size) | ||
436 | ret_size = size; | ||
502 | 437 | ||
503 | down(&chip->buffer_mutex); | 438 | down(&chip->buffer_mutex); |
504 | 439 | if (copy_to_user | |
505 | ret_size = atomic_read(&chip->data_pending); | 440 | ((void __user *) buf, chip->data_buffer, ret_size)) |
506 | atomic_set(&chip->data_pending, 0); | 441 | ret_size = -EFAULT; |
507 | |||
508 | if (ret_size == 0) /* timeout just occurred */ | ||
509 | ret_size = -ETIME; | ||
510 | else if (ret_size > 0) { /* relay data */ | ||
511 | if (size < ret_size) | ||
512 | ret_size = size; | ||
513 | |||
514 | if (copy_to_user((void __user *) buf, | ||
515 | chip->data_buffer, ret_size)) { | ||
516 | ret_size = -EFAULT; | ||
517 | } | ||
518 | } | ||
519 | up(&chip->buffer_mutex); | 442 | up(&chip->buffer_mutex); |
520 | } | 443 | } |
521 | 444 | ||
@@ -542,13 +465,11 @@ void __devexit tpm_remove(struct pci_dev *pci_dev) | |||
542 | pci_set_drvdata(pci_dev, NULL); | 465 | pci_set_drvdata(pci_dev, NULL); |
543 | misc_deregister(&chip->vendor->miscdev); | 466 | misc_deregister(&chip->vendor->miscdev); |
544 | 467 | ||
545 | device_remove_file(&pci_dev->dev, &dev_attr_pubek); | 468 | sysfs_remove_group(&pci_dev->dev.kobj, chip->vendor->attr_group); |
546 | device_remove_file(&pci_dev->dev, &dev_attr_pcrs); | ||
547 | device_remove_file(&pci_dev->dev, &dev_attr_caps); | ||
548 | 469 | ||
549 | pci_disable_device(pci_dev); | 470 | pci_disable_device(pci_dev); |
550 | 471 | ||
551 | dev_mask[chip->dev_num / 32] &= !(1 << (chip->dev_num % 32)); | 472 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); |
552 | 473 | ||
553 | kfree(chip); | 474 | kfree(chip); |
554 | 475 | ||
@@ -590,10 +511,6 @@ int tpm_pm_resume(struct pci_dev *pci_dev) | |||
590 | if (chip == NULL) | 511 | if (chip == NULL) |
591 | return -ENODEV; | 512 | return -ENODEV; |
592 | 513 | ||
593 | spin_lock(&driver_lock); | ||
594 | tpm_lpc_bus_init(pci_dev, chip->vendor->base); | ||
595 | spin_unlock(&driver_lock); | ||
596 | |||
597 | return 0; | 514 | return 0; |
598 | } | 515 | } |
599 | 516 | ||
@@ -622,17 +539,21 @@ int tpm_register_hardware(struct pci_dev *pci_dev, | |||
622 | 539 | ||
623 | init_MUTEX(&chip->buffer_mutex); | 540 | init_MUTEX(&chip->buffer_mutex); |
624 | init_MUTEX(&chip->tpm_mutex); | 541 | init_MUTEX(&chip->tpm_mutex); |
625 | init_MUTEX(&chip->timer_manipulation_mutex); | ||
626 | INIT_LIST_HEAD(&chip->list); | 542 | INIT_LIST_HEAD(&chip->list); |
627 | 543 | ||
544 | init_timer(&chip->user_read_timer); | ||
545 | chip->user_read_timer.function = user_reader_timeout; | ||
546 | chip->user_read_timer.data = (unsigned long) chip; | ||
547 | |||
628 | chip->vendor = entry; | 548 | chip->vendor = entry; |
629 | 549 | ||
630 | chip->dev_num = -1; | 550 | chip->dev_num = -1; |
631 | 551 | ||
632 | for (i = 0; i < 32; i++) | 552 | for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++) |
633 | for (j = 0; j < 8; j++) | 553 | for (j = 0; j < 8 * sizeof(int); j++) |
634 | if ((dev_mask[i] & (1 << j)) == 0) { | 554 | if ((dev_mask[i] & (1 << j)) == 0) { |
635 | chip->dev_num = i * 32 + j; | 555 | chip->dev_num = |
556 | i * TPM_NUM_MASK_ENTRIES + j; | ||
636 | dev_mask[i] |= 1 << j; | 557 | dev_mask[i] |= 1 << j; |
637 | goto dev_num_search_complete; | 558 | goto dev_num_search_complete; |
638 | } | 559 | } |
@@ -665,31 +586,20 @@ dev_num_search_complete: | |||
665 | return -ENODEV; | 586 | return -ENODEV; |
666 | } | 587 | } |
667 | 588 | ||
589 | spin_lock(&driver_lock); | ||
590 | |||
668 | pci_set_drvdata(pci_dev, chip); | 591 | pci_set_drvdata(pci_dev, chip); |
669 | 592 | ||
670 | list_add(&chip->list, &tpm_chip_list); | 593 | list_add(&chip->list, &tpm_chip_list); |
671 | 594 | ||
672 | device_create_file(&pci_dev->dev, &dev_attr_pubek); | 595 | spin_unlock(&driver_lock); |
673 | device_create_file(&pci_dev->dev, &dev_attr_pcrs); | ||
674 | device_create_file(&pci_dev->dev, &dev_attr_caps); | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | 596 | ||
679 | EXPORT_SYMBOL_GPL(tpm_register_hardware); | 597 | sysfs_create_group(&pci_dev->dev.kobj, chip->vendor->attr_group); |
680 | 598 | ||
681 | static int __init init_tpm(void) | ||
682 | { | ||
683 | return 0; | 599 | return 0; |
684 | } | 600 | } |
685 | 601 | ||
686 | static void __exit cleanup_tpm(void) | 602 | EXPORT_SYMBOL_GPL(tpm_register_hardware); |
687 | { | ||
688 | |||
689 | } | ||
690 | |||
691 | module_init(init_tpm); | ||
692 | module_exit(cleanup_tpm); | ||
693 | 603 | ||
694 | MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); | 604 | MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); |
695 | MODULE_DESCRIPTION("TPM Driver"); | 605 | MODULE_DESCRIPTION("TPM Driver"); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index de0c796fce..10cb450191 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -25,23 +25,38 @@ | |||
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/miscdevice.h> | 26 | #include <linux/miscdevice.h> |
27 | 27 | ||
28 | #define TPM_TIMEOUT msecs_to_jiffies(5) | 28 | enum tpm_timeout { |
29 | TPM_TIMEOUT = 5, /* msecs */ | ||
30 | }; | ||
29 | 31 | ||
30 | /* TPM addresses */ | 32 | /* TPM addresses */ |
31 | #define TPM_ADDR 0x4E | 33 | enum tpm_addr { |
32 | #define TPM_DATA 0x4F | 34 | TPM_ADDR = 0x4E, |
35 | TPM_DATA = 0x4F | ||
36 | }; | ||
37 | |||
38 | extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, | ||
39 | char *); | ||
40 | extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, | ||
41 | char *); | ||
42 | extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr, | ||
43 | char *); | ||
44 | extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr, | ||
45 | const char *, size_t); | ||
33 | 46 | ||
34 | struct tpm_chip; | 47 | struct tpm_chip; |
35 | 48 | ||
36 | struct tpm_vendor_specific { | 49 | struct tpm_vendor_specific { |
37 | u8 req_complete_mask; | 50 | u8 req_complete_mask; |
38 | u8 req_complete_val; | 51 | u8 req_complete_val; |
52 | u8 req_canceled; | ||
39 | u16 base; /* TPM base address */ | 53 | u16 base; /* TPM base address */ |
40 | 54 | ||
41 | int (*recv) (struct tpm_chip *, u8 *, size_t); | 55 | int (*recv) (struct tpm_chip *, u8 *, size_t); |
42 | int (*send) (struct tpm_chip *, u8 *, size_t); | 56 | int (*send) (struct tpm_chip *, u8 *, size_t); |
43 | void (*cancel) (struct tpm_chip *); | 57 | void (*cancel) (struct tpm_chip *); |
44 | struct miscdevice miscdev; | 58 | struct miscdevice miscdev; |
59 | struct attribute_group *attr_group; | ||
45 | }; | 60 | }; |
46 | 61 | ||
47 | struct tpm_chip { | 62 | struct tpm_chip { |
@@ -58,8 +73,6 @@ struct tpm_chip { | |||
58 | 73 | ||
59 | struct timer_list user_read_timer; /* user needs to claim result */ | 74 | struct timer_list user_read_timer; /* user needs to claim result */ |
60 | struct semaphore tpm_mutex; /* tpm is processing */ | 75 | struct semaphore tpm_mutex; /* tpm is processing */ |
61 | struct timer_list device_timer; /* tpm is processing */ | ||
62 | struct semaphore timer_manipulation_mutex; | ||
63 | 76 | ||
64 | struct tpm_vendor_specific *vendor; | 77 | struct tpm_vendor_specific *vendor; |
65 | 78 | ||
@@ -78,9 +91,6 @@ static inline void tpm_write_index(int index, int value) | |||
78 | outb(value & 0xFF, TPM_DATA); | 91 | outb(value & 0xFF, TPM_DATA); |
79 | } | 92 | } |
80 | 93 | ||
81 | extern void tpm_time_expired(unsigned long); | ||
82 | extern int tpm_lpc_bus_init(struct pci_dev *, u16); | ||
83 | |||
84 | extern int tpm_register_hardware(struct pci_dev *, | 94 | extern int tpm_register_hardware(struct pci_dev *, |
85 | struct tpm_vendor_specific *); | 95 | struct tpm_vendor_specific *); |
86 | extern int tpm_open(struct inode *, struct file *); | 96 | extern int tpm_open(struct inode *, struct file *); |
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index f9333e729b..61fe14a771 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -22,17 +22,23 @@ | |||
22 | #include "tpm.h" | 22 | #include "tpm.h" |
23 | 23 | ||
24 | /* Atmel definitions */ | 24 | /* Atmel definitions */ |
25 | #define TPM_ATML_BASE 0x400 | 25 | enum tpm_atmel_addr { |
26 | TPM_ATMEL_BASE_ADDR_LO = 0x08, | ||
27 | TPM_ATMEL_BASE_ADDR_HI = 0x09 | ||
28 | }; | ||
26 | 29 | ||
27 | /* write status bits */ | 30 | /* write status bits */ |
28 | #define ATML_STATUS_ABORT 0x01 | 31 | enum tpm_atmel_write_status { |
29 | #define ATML_STATUS_LASTBYTE 0x04 | 32 | ATML_STATUS_ABORT = 0x01, |
30 | 33 | ATML_STATUS_LASTBYTE = 0x04 | |
34 | }; | ||
31 | /* read status bits */ | 35 | /* read status bits */ |
32 | #define ATML_STATUS_BUSY 0x01 | 36 | enum tpm_atmel_read_status { |
33 | #define ATML_STATUS_DATA_AVAIL 0x02 | 37 | ATML_STATUS_BUSY = 0x01, |
34 | #define ATML_STATUS_REWRITE 0x04 | 38 | ATML_STATUS_DATA_AVAIL = 0x02, |
35 | 39 | ATML_STATUS_REWRITE = 0x04, | |
40 | ATML_STATUS_READY = 0x08 | ||
41 | }; | ||
36 | 42 | ||
37 | static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count) | 43 | static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count) |
38 | { | 44 | { |
@@ -121,13 +127,29 @@ static struct file_operations atmel_ops = { | |||
121 | .release = tpm_release, | 127 | .release = tpm_release, |
122 | }; | 128 | }; |
123 | 129 | ||
130 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | ||
131 | static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); | ||
132 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); | ||
133 | static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel); | ||
134 | |||
135 | static struct attribute* atmel_attrs[] = { | ||
136 | &dev_attr_pubek.attr, | ||
137 | &dev_attr_pcrs.attr, | ||
138 | &dev_attr_caps.attr, | ||
139 | &dev_attr_cancel.attr, | ||
140 | 0, | ||
141 | }; | ||
142 | |||
143 | static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs }; | ||
144 | |||
124 | static struct tpm_vendor_specific tpm_atmel = { | 145 | static struct tpm_vendor_specific tpm_atmel = { |
125 | .recv = tpm_atml_recv, | 146 | .recv = tpm_atml_recv, |
126 | .send = tpm_atml_send, | 147 | .send = tpm_atml_send, |
127 | .cancel = tpm_atml_cancel, | 148 | .cancel = tpm_atml_cancel, |
128 | .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL, | 149 | .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL, |
129 | .req_complete_val = ATML_STATUS_DATA_AVAIL, | 150 | .req_complete_val = ATML_STATUS_DATA_AVAIL, |
130 | .base = TPM_ATML_BASE, | 151 | .req_canceled = ATML_STATUS_READY, |
152 | .attr_group = &atmel_attr_grp, | ||
131 | .miscdev = { .fops = &atmel_ops, }, | 153 | .miscdev = { .fops = &atmel_ops, }, |
132 | }; | 154 | }; |
133 | 155 | ||
@@ -136,14 +158,16 @@ static int __devinit tpm_atml_init(struct pci_dev *pci_dev, | |||
136 | { | 158 | { |
137 | u8 version[4]; | 159 | u8 version[4]; |
138 | int rc = 0; | 160 | int rc = 0; |
161 | int lo, hi; | ||
139 | 162 | ||
140 | if (pci_enable_device(pci_dev)) | 163 | if (pci_enable_device(pci_dev)) |
141 | return -EIO; | 164 | return -EIO; |
142 | 165 | ||
143 | if (tpm_lpc_bus_init(pci_dev, TPM_ATML_BASE)) { | 166 | lo = tpm_read_index( TPM_ATMEL_BASE_ADDR_LO ); |
144 | rc = -ENODEV; | 167 | hi = tpm_read_index( TPM_ATMEL_BASE_ADDR_HI ); |
145 | goto out_err; | 168 | |
146 | } | 169 | tpm_atmel.base = (hi<<8)|lo; |
170 | dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base); | ||
147 | 171 | ||
148 | /* verify that it is an Atmel part */ | 172 | /* verify that it is an Atmel part */ |
149 | if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T' | 173 | if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T' |
@@ -183,6 +207,7 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = { | |||
183 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, | 207 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, |
184 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, | 208 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, |
185 | {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)}, | 209 | {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)}, |
210 | {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)}, | ||
186 | {0,} | 211 | {0,} |
187 | }; | 212 | }; |
188 | 213 | ||
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 9cce833a09..1a45e7dfc1 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
@@ -22,43 +22,52 @@ | |||
22 | #include "tpm.h" | 22 | #include "tpm.h" |
23 | 23 | ||
24 | /* National definitions */ | 24 | /* National definitions */ |
25 | #define TPM_NSC_BASE 0x360 | 25 | enum tpm_nsc_addr{ |
26 | #define TPM_NSC_IRQ 0x07 | 26 | TPM_NSC_BASE = 0x360, |
27 | TPM_NSC_IRQ = 0x07, | ||
28 | TPM_NSC_BASE0_HI = 0x60, | ||
29 | TPM_NSC_BASE0_LO = 0x61, | ||
30 | TPM_NSC_BASE1_HI = 0x62, | ||
31 | TPM_NSC_BASE1_LO = 0x63 | ||
32 | }; | ||
27 | 33 | ||
28 | #define NSC_LDN_INDEX 0x07 | 34 | enum tpm_nsc_index { |
29 | #define NSC_SID_INDEX 0x20 | 35 | NSC_LDN_INDEX = 0x07, |
30 | #define NSC_LDC_INDEX 0x30 | 36 | NSC_SID_INDEX = 0x20, |
31 | #define NSC_DIO_INDEX 0x60 | 37 | NSC_LDC_INDEX = 0x30, |
32 | #define NSC_CIO_INDEX 0x62 | 38 | NSC_DIO_INDEX = 0x60, |
33 | #define NSC_IRQ_INDEX 0x70 | 39 | NSC_CIO_INDEX = 0x62, |
34 | #define NSC_ITS_INDEX 0x71 | 40 | NSC_IRQ_INDEX = 0x70, |
41 | NSC_ITS_INDEX = 0x71 | ||
42 | }; | ||
35 | 43 | ||
36 | #define NSC_STATUS 0x01 | 44 | enum tpm_nsc_status_loc { |
37 | #define NSC_COMMAND 0x01 | 45 | NSC_STATUS = 0x01, |
38 | #define NSC_DATA 0x00 | 46 | NSC_COMMAND = 0x01, |
47 | NSC_DATA = 0x00 | ||
48 | }; | ||
39 | 49 | ||
40 | /* status bits */ | 50 | /* status bits */ |
41 | #define NSC_STATUS_OBF 0x01 /* output buffer full */ | 51 | enum tpm_nsc_status { |
42 | #define NSC_STATUS_IBF 0x02 /* input buffer full */ | 52 | NSC_STATUS_OBF = 0x01, /* output buffer full */ |
43 | #define NSC_STATUS_F0 0x04 /* F0 */ | 53 | NSC_STATUS_IBF = 0x02, /* input buffer full */ |
44 | #define NSC_STATUS_A2 0x08 /* A2 */ | 54 | NSC_STATUS_F0 = 0x04, /* F0 */ |
45 | #define NSC_STATUS_RDY 0x10 /* ready to receive command */ | 55 | NSC_STATUS_A2 = 0x08, /* A2 */ |
46 | #define NSC_STATUS_IBR 0x20 /* ready to receive data */ | 56 | NSC_STATUS_RDY = 0x10, /* ready to receive command */ |
47 | 57 | NSC_STATUS_IBR = 0x20 /* ready to receive data */ | |
58 | }; | ||
48 | /* command bits */ | 59 | /* command bits */ |
49 | #define NSC_COMMAND_NORMAL 0x01 /* normal mode */ | 60 | enum tpm_nsc_cmd_mode { |
50 | #define NSC_COMMAND_EOC 0x03 | 61 | NSC_COMMAND_NORMAL = 0x01, /* normal mode */ |
51 | #define NSC_COMMAND_CANCEL 0x22 | 62 | NSC_COMMAND_EOC = 0x03, |
52 | 63 | NSC_COMMAND_CANCEL = 0x22 | |
64 | }; | ||
53 | /* | 65 | /* |
54 | * Wait for a certain status to appear | 66 | * Wait for a certain status to appear |
55 | */ | 67 | */ |
56 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) | 68 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) |
57 | { | 69 | { |
58 | int expired = 0; | 70 | unsigned long stop; |
59 | struct timer_list status_timer = | ||
60 | TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ, | ||
61 | (unsigned long) &expired); | ||
62 | 71 | ||
63 | /* status immediately available check */ | 72 | /* status immediately available check */ |
64 | *data = inb(chip->vendor->base + NSC_STATUS); | 73 | *data = inb(chip->vendor->base + NSC_STATUS); |
@@ -66,17 +75,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) | |||
66 | return 0; | 75 | return 0; |
67 | 76 | ||
68 | /* wait for status */ | 77 | /* wait for status */ |
69 | add_timer(&status_timer); | 78 | stop = jiffies + 10 * HZ; |
70 | do { | 79 | do { |
71 | set_current_state(TASK_UNINTERRUPTIBLE); | 80 | msleep(TPM_TIMEOUT); |
72 | schedule_timeout(TPM_TIMEOUT); | ||
73 | *data = inb(chip->vendor->base + 1); | 81 | *data = inb(chip->vendor->base + 1); |
74 | if ((*data & mask) == val) { | 82 | if ((*data & mask) == val) |
75 | del_singleshot_timer_sync(&status_timer); | ||
76 | return 0; | 83 | return 0; |
77 | } | ||
78 | } | 84 | } |
79 | while (!expired); | 85 | while (time_before(jiffies, stop)); |
80 | 86 | ||
81 | return -EBUSY; | 87 | return -EBUSY; |
82 | } | 88 | } |
@@ -84,10 +90,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) | |||
84 | static int nsc_wait_for_ready(struct tpm_chip *chip) | 90 | static int nsc_wait_for_ready(struct tpm_chip *chip) |
85 | { | 91 | { |
86 | int status; | 92 | int status; |
87 | int expired = 0; | 93 | unsigned long stop; |
88 | struct timer_list status_timer = | ||
89 | TIMER_INITIALIZER(tpm_time_expired, jiffies + 100, | ||
90 | (unsigned long) &expired); | ||
91 | 94 | ||
92 | /* status immediately available check */ | 95 | /* status immediately available check */ |
93 | status = inb(chip->vendor->base + NSC_STATUS); | 96 | status = inb(chip->vendor->base + NSC_STATUS); |
@@ -97,19 +100,16 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) | |||
97 | return 0; | 100 | return 0; |
98 | 101 | ||
99 | /* wait for status */ | 102 | /* wait for status */ |
100 | add_timer(&status_timer); | 103 | stop = jiffies + 100; |
101 | do { | 104 | do { |
102 | set_current_state(TASK_UNINTERRUPTIBLE); | 105 | msleep(TPM_TIMEOUT); |
103 | schedule_timeout(TPM_TIMEOUT); | ||
104 | status = inb(chip->vendor->base + NSC_STATUS); | 106 | status = inb(chip->vendor->base + NSC_STATUS); |
105 | if (status & NSC_STATUS_OBF) | 107 | if (status & NSC_STATUS_OBF) |
106 | status = inb(chip->vendor->base + NSC_DATA); | 108 | status = inb(chip->vendor->base + NSC_DATA); |
107 | if (status & NSC_STATUS_RDY) { | 109 | if (status & NSC_STATUS_RDY) |
108 | del_singleshot_timer_sync(&status_timer); | ||
109 | return 0; | 110 | return 0; |
110 | } | ||
111 | } | 111 | } |
112 | while (!expired); | 112 | while (time_before(jiffies, stop)); |
113 | 113 | ||
114 | dev_info(&chip->pci_dev->dev, "wait for ready failed\n"); | 114 | dev_info(&chip->pci_dev->dev, "wait for ready failed\n"); |
115 | return -EBUSY; | 115 | return -EBUSY; |
@@ -228,30 +228,46 @@ static struct file_operations nsc_ops = { | |||
228 | .release = tpm_release, | 228 | .release = tpm_release, |
229 | }; | 229 | }; |
230 | 230 | ||
231 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | ||
232 | static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); | ||
233 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); | ||
234 | static DEVICE_ATTR(cancel, S_IWUSR|S_IWGRP, NULL, tpm_store_cancel); | ||
235 | |||
236 | static struct attribute * nsc_attrs[] = { | ||
237 | &dev_attr_pubek.attr, | ||
238 | &dev_attr_pcrs.attr, | ||
239 | &dev_attr_caps.attr, | ||
240 | &dev_attr_cancel.attr, | ||
241 | 0, | ||
242 | }; | ||
243 | |||
244 | static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs }; | ||
245 | |||
231 | static struct tpm_vendor_specific tpm_nsc = { | 246 | static struct tpm_vendor_specific tpm_nsc = { |
232 | .recv = tpm_nsc_recv, | 247 | .recv = tpm_nsc_recv, |
233 | .send = tpm_nsc_send, | 248 | .send = tpm_nsc_send, |
234 | .cancel = tpm_nsc_cancel, | 249 | .cancel = tpm_nsc_cancel, |
235 | .req_complete_mask = NSC_STATUS_OBF, | 250 | .req_complete_mask = NSC_STATUS_OBF, |
236 | .req_complete_val = NSC_STATUS_OBF, | 251 | .req_complete_val = NSC_STATUS_OBF, |
237 | .base = TPM_NSC_BASE, | 252 | .req_canceled = NSC_STATUS_RDY, |
253 | .attr_group = &nsc_attr_grp, | ||
238 | .miscdev = { .fops = &nsc_ops, }, | 254 | .miscdev = { .fops = &nsc_ops, }, |
239 | |||
240 | }; | 255 | }; |
241 | 256 | ||
242 | static int __devinit tpm_nsc_init(struct pci_dev *pci_dev, | 257 | static int __devinit tpm_nsc_init(struct pci_dev *pci_dev, |
243 | const struct pci_device_id *pci_id) | 258 | const struct pci_device_id *pci_id) |
244 | { | 259 | { |
245 | int rc = 0; | 260 | int rc = 0; |
261 | int lo, hi; | ||
262 | |||
263 | hi = tpm_read_index(TPM_NSC_BASE0_HI); | ||
264 | lo = tpm_read_index(TPM_NSC_BASE0_LO); | ||
265 | |||
266 | tpm_nsc.base = (hi<<8) | lo; | ||
246 | 267 | ||
247 | if (pci_enable_device(pci_dev)) | 268 | if (pci_enable_device(pci_dev)) |
248 | return -EIO; | 269 | return -EIO; |
249 | 270 | ||
250 | if (tpm_lpc_bus_init(pci_dev, TPM_NSC_BASE)) { | ||
251 | rc = -ENODEV; | ||
252 | goto out_err; | ||
253 | } | ||
254 | |||
255 | /* verify that it is a National part (SID) */ | 271 | /* verify that it is a National part (SID) */ |
256 | if (tpm_read_index(NSC_SID_INDEX) != 0xEF) { | 272 | if (tpm_read_index(NSC_SID_INDEX) != 0xEF) { |
257 | rc = -ENODEV; | 273 | rc = -ENODEV; |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 31831030f7..cc4b43bad7 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -251,7 +251,7 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
251 | 251 | ||
252 | static DEFINE_SPINLOCK(tty_ldisc_lock); | 252 | static DEFINE_SPINLOCK(tty_ldisc_lock); |
253 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); | 253 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); |
254 | static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ | 254 | static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ |
255 | 255 | ||
256 | int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) | 256 | int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) |
257 | { | 257 | { |
@@ -262,24 +262,35 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) | |||
262 | return -EINVAL; | 262 | return -EINVAL; |
263 | 263 | ||
264 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 264 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
265 | if (new_ldisc) { | 265 | tty_ldiscs[disc] = *new_ldisc; |
266 | tty_ldiscs[disc] = *new_ldisc; | 266 | tty_ldiscs[disc].num = disc; |
267 | tty_ldiscs[disc].num = disc; | 267 | tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED; |
268 | tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED; | 268 | tty_ldiscs[disc].refcount = 0; |
269 | tty_ldiscs[disc].refcount = 0; | ||
270 | } else { | ||
271 | if(tty_ldiscs[disc].refcount) | ||
272 | ret = -EBUSY; | ||
273 | else | ||
274 | tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED; | ||
275 | } | ||
276 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 269 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
277 | 270 | ||
278 | return ret; | 271 | return ret; |
279 | } | 272 | } |
280 | |||
281 | EXPORT_SYMBOL(tty_register_ldisc); | 273 | EXPORT_SYMBOL(tty_register_ldisc); |
282 | 274 | ||
275 | int tty_unregister_ldisc(int disc) | ||
276 | { | ||
277 | unsigned long flags; | ||
278 | int ret = 0; | ||
279 | |||
280 | if (disc < N_TTY || disc >= NR_LDISCS) | ||
281 | return -EINVAL; | ||
282 | |||
283 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
284 | if (tty_ldiscs[disc].refcount) | ||
285 | ret = -EBUSY; | ||
286 | else | ||
287 | tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED; | ||
288 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
289 | |||
290 | return ret; | ||
291 | } | ||
292 | EXPORT_SYMBOL(tty_unregister_ldisc); | ||
293 | |||
283 | struct tty_ldisc *tty_ldisc_get(int disc) | 294 | struct tty_ldisc *tty_ldisc_get(int disc) |
284 | { | 295 | { |
285 | unsigned long flags; | 296 | unsigned long flags; |
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 06a31da238..b53e2e2b5a 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig | |||
@@ -414,6 +414,16 @@ config WATCHDOG_RIO | |||
414 | machines. The watchdog timeout period is normally one minute but | 414 | machines. The watchdog timeout period is normally one minute but |
415 | can be changed with a boot-time parameter. | 415 | can be changed with a boot-time parameter. |
416 | 416 | ||
417 | # ppc64 RTAS watchdog | ||
418 | config WATCHDOG_RTAS | ||
419 | tristate "RTAS watchdog" | ||
420 | depends on WATCHDOG && PPC_RTAS | ||
421 | help | ||
422 | This driver adds watchdog support for the RTAS watchdog. | ||
423 | |||
424 | To compile this driver as a module, choose M here. The module | ||
425 | will be called wdrtas. | ||
426 | |||
417 | # | 427 | # |
418 | # ISA-based Watchdog Cards | 428 | # ISA-based Watchdog Cards |
419 | # | 429 | # |
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 1cd27efa35..c1838834ea 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile | |||
@@ -33,6 +33,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o | |||
33 | obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o | 33 | obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o |
34 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o | 34 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o |
35 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o | 35 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o |
36 | obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o | ||
36 | 37 | ||
37 | # Only one watchdog can succeed. We probe the hardware watchdog | 38 | # Only one watchdog can succeed. We probe the hardware watchdog |
38 | # drivers first, then the softdog driver. This means if your hardware | 39 | # drivers first, then the softdog driver. This means if your hardware |
diff --git a/drivers/char/watchdog/wdrtas.c b/drivers/char/watchdog/wdrtas.c new file mode 100644 index 0000000000..619e2ffca3 --- /dev/null +++ b/drivers/char/watchdog/wdrtas.c | |||
@@ -0,0 +1,696 @@ | |||
1 | /* | ||
2 | * FIXME: add wdrtas_get_status and wdrtas_get_boot_status as soon as | ||
3 | * RTAS calls are available | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | * RTAS watchdog driver | ||
8 | * | ||
9 | * (C) Copyright IBM Corp. 2005 | ||
10 | * device driver to exploit watchdog RTAS functions | ||
11 | * | ||
12 | * Authors : Utz Bacher <utz.bacher@de.ibm.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2, or (at your option) | ||
17 | * any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | */ | ||
28 | |||
29 | #include <linux/config.h> | ||
30 | #include <linux/fs.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/miscdevice.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/notifier.h> | ||
36 | #include <linux/reboot.h> | ||
37 | #include <linux/types.h> | ||
38 | #include <linux/watchdog.h> | ||
39 | |||
40 | #include <asm/rtas.h> | ||
41 | #include <asm/uaccess.h> | ||
42 | |||
43 | #define WDRTAS_MAGIC_CHAR 42 | ||
44 | #define WDRTAS_SUPPORTED_MASK (WDIOF_SETTIMEOUT | \ | ||
45 | WDIOF_MAGICCLOSE) | ||
46 | |||
47 | MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); | ||
48 | MODULE_DESCRIPTION("RTAS watchdog driver"); | ||
49 | MODULE_LICENSE("GPL"); | ||
50 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
51 | MODULE_ALIAS_MISCDEV(TEMP_MINOR); | ||
52 | |||
53 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | ||
54 | static int wdrtas_nowayout = 1; | ||
55 | #else | ||
56 | static int wdrtas_nowayout = 0; | ||
57 | #endif | ||
58 | |||
59 | static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0); | ||
60 | static char wdrtas_expect_close = 0; | ||
61 | |||
62 | static int wdrtas_interval; | ||
63 | |||
64 | #define WDRTAS_THERMAL_SENSOR 3 | ||
65 | static int wdrtas_token_get_sensor_state; | ||
66 | #define WDRTAS_SURVEILLANCE_IND 9000 | ||
67 | static int wdrtas_token_set_indicator; | ||
68 | #define WDRTAS_SP_SPI 28 | ||
69 | static int wdrtas_token_get_sp; | ||
70 | static int wdrtas_token_event_scan; | ||
71 | |||
72 | #define WDRTAS_DEFAULT_INTERVAL 300 | ||
73 | |||
74 | #define WDRTAS_LOGBUFFER_LEN 128 | ||
75 | static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN]; | ||
76 | |||
77 | |||
78 | /*** watchdog access functions */ | ||
79 | |||
80 | /** | ||
81 | * wdrtas_set_interval - sets the watchdog interval | ||
82 | * @interval: new interval | ||
83 | * | ||
84 | * returns 0 on success, <0 on failures | ||
85 | * | ||
86 | * wdrtas_set_interval sets the watchdog keepalive interval by calling the | ||
87 | * RTAS function set-indicator (surveillance). The unit of interval is | ||
88 | * seconds. | ||
89 | */ | ||
90 | static int | ||
91 | wdrtas_set_interval(int interval) | ||
92 | { | ||
93 | long result; | ||
94 | static int print_msg = 10; | ||
95 | |||
96 | /* rtas uses minutes */ | ||
97 | interval = (interval + 59) / 60; | ||
98 | |||
99 | result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL, | ||
100 | WDRTAS_SURVEILLANCE_IND, 0, interval); | ||
101 | if ( (result < 0) && (print_msg) ) { | ||
102 | printk(KERN_ERR "wdrtas: setting the watchdog to %i " | ||
103 | "timeout failed: %li\n", interval, result); | ||
104 | print_msg--; | ||
105 | } | ||
106 | |||
107 | return result; | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * wdrtas_get_interval - returns the current watchdog interval | ||
112 | * @fallback_value: value (in seconds) to use, if the RTAS call fails | ||
113 | * | ||
114 | * returns the interval | ||
115 | * | ||
116 | * wdrtas_get_interval returns the current watchdog keepalive interval | ||
117 | * as reported by the RTAS function ibm,get-system-parameter. The unit | ||
118 | * of the return value is seconds. | ||
119 | */ | ||
120 | static int | ||
121 | wdrtas_get_interval(int fallback_value) | ||
122 | { | ||
123 | long result; | ||
124 | char value[4]; | ||
125 | |||
126 | result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL, | ||
127 | WDRTAS_SP_SPI, (void *)__pa(&value), 4); | ||
128 | if ( (value[0] != 0) || (value[1] != 2) || (value[3] != 0) || | ||
129 | (result < 0) ) { | ||
130 | printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog " | ||
131 | "timeout (%li). Continuing\n", result); | ||
132 | return fallback_value; | ||
133 | } | ||
134 | |||
135 | /* rtas uses minutes */ | ||
136 | return ((int)value[2]) * 60; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * wdrtas_timer_start - starts watchdog | ||
141 | * | ||
142 | * wdrtas_timer_start starts the watchdog by calling the RTAS function | ||
143 | * set-interval (surveillance) | ||
144 | */ | ||
145 | static void | ||
146 | wdrtas_timer_start(void) | ||
147 | { | ||
148 | wdrtas_set_interval(wdrtas_interval); | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * wdrtas_timer_stop - stops watchdog | ||
153 | * | ||
154 | * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function | ||
155 | * set-interval (surveillance) | ||
156 | */ | ||
157 | static void | ||
158 | wdrtas_timer_stop(void) | ||
159 | { | ||
160 | wdrtas_set_interval(0); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * wdrtas_log_scanned_event - logs an event we received during keepalive | ||
165 | * | ||
166 | * wdrtas_log_scanned_event prints a message to the log buffer dumping | ||
167 | * the results of the last event-scan call | ||
168 | */ | ||
169 | static void | ||
170 | wdrtas_log_scanned_event(void) | ||
171 | { | ||
172 | int i; | ||
173 | |||
174 | for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16) | ||
175 | printk(KERN_INFO "wdrtas: dumping event (line %i/%i), data = " | ||
176 | "%02x %02x %02x %02x %02x %02x %02x %02x " | ||
177 | "%02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
178 | (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16), | ||
179 | wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1], | ||
180 | wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3], | ||
181 | wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5], | ||
182 | wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7], | ||
183 | wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9], | ||
184 | wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11], | ||
185 | wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13], | ||
186 | wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]); | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * wdrtas_timer_keepalive - resets watchdog timer to keep system alive | ||
191 | * | ||
192 | * wdrtas_timer_keepalive restarts the watchdog timer by calling the | ||
193 | * RTAS function event-scan and repeats these calls as long as there are | ||
194 | * events available. All events will be dumped. | ||
195 | */ | ||
196 | static void | ||
197 | wdrtas_timer_keepalive(void) | ||
198 | { | ||
199 | long result; | ||
200 | |||
201 | do { | ||
202 | result = rtas_call(wdrtas_token_event_scan, 4, 1, NULL, | ||
203 | RTAS_EVENT_SCAN_ALL_EVENTS, 0, | ||
204 | (void *)__pa(wdrtas_logbuffer), | ||
205 | WDRTAS_LOGBUFFER_LEN); | ||
206 | if (result < 0) | ||
207 | printk(KERN_ERR "wdrtas: event-scan failed: %li\n", | ||
208 | result); | ||
209 | if (result == 0) | ||
210 | wdrtas_log_scanned_event(); | ||
211 | } while (result == 0); | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * wdrtas_get_temperature - returns current temperature | ||
216 | * | ||
217 | * returns temperature or <0 on failures | ||
218 | * | ||
219 | * wdrtas_get_temperature returns the current temperature in Fahrenheit. It | ||
220 | * uses the RTAS call get-sensor-state, token 3 to do so | ||
221 | */ | ||
222 | static int | ||
223 | wdrtas_get_temperature(void) | ||
224 | { | ||
225 | long result; | ||
226 | int temperature = 0; | ||
227 | |||
228 | result = rtas_call(wdrtas_token_get_sensor_state, 2, 2, | ||
229 | (void *)__pa(&temperature), | ||
230 | WDRTAS_THERMAL_SENSOR, 0); | ||
231 | |||
232 | if (result < 0) | ||
233 | printk(KERN_WARNING "wdrtas: reading the thermal sensor " | ||
234 | "faild: %li\n", result); | ||
235 | else | ||
236 | temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */ | ||
237 | |||
238 | return temperature; | ||
239 | } | ||
240 | |||
241 | /** | ||
242 | * wdrtas_get_status - returns the status of the watchdog | ||
243 | * | ||
244 | * returns a bitmask of defines WDIOF_... as defined in | ||
245 | * include/linux/watchdog.h | ||
246 | */ | ||
247 | static int | ||
248 | wdrtas_get_status(void) | ||
249 | { | ||
250 | return 0; /* TODO */ | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * wdrtas_get_boot_status - returns the reason for the last boot | ||
255 | * | ||
256 | * returns a bitmask of defines WDIOF_... as defined in | ||
257 | * include/linux/watchdog.h, indicating why the watchdog rebooted the system | ||
258 | */ | ||
259 | static int | ||
260 | wdrtas_get_boot_status(void) | ||
261 | { | ||
262 | return 0; /* TODO */ | ||
263 | } | ||
264 | |||
265 | /*** watchdog API and operations stuff */ | ||
266 | |||
267 | /* wdrtas_write - called when watchdog device is written to | ||
268 | * @file: file structure | ||
269 | * @buf: user buffer with data | ||
270 | * @len: amount to data written | ||
271 | * @ppos: position in file | ||
272 | * | ||
273 | * returns the number of successfully processed characters, which is always | ||
274 | * the number of bytes passed to this function | ||
275 | * | ||
276 | * wdrtas_write processes all the data given to it and looks for the magic | ||
277 | * character 'V'. This character allows the watchdog device to be closed | ||
278 | * properly. | ||
279 | */ | ||
280 | static ssize_t | ||
281 | wdrtas_write(struct file *file, const char __user *buf, | ||
282 | size_t len, loff_t *ppos) | ||
283 | { | ||
284 | int i; | ||
285 | char c; | ||
286 | |||
287 | if (!len) | ||
288 | goto out; | ||
289 | |||
290 | if (!wdrtas_nowayout) { | ||
291 | wdrtas_expect_close = 0; | ||
292 | /* look for 'V' */ | ||
293 | for (i = 0; i < len; i++) { | ||
294 | if (get_user(c, buf + i)) | ||
295 | return -EFAULT; | ||
296 | /* allow to close device */ | ||
297 | if (c == 'V') | ||
298 | wdrtas_expect_close = WDRTAS_MAGIC_CHAR; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | wdrtas_timer_keepalive(); | ||
303 | |||
304 | out: | ||
305 | return len; | ||
306 | } | ||
307 | |||
308 | /** | ||
309 | * wdrtas_ioctl - ioctl function for the watchdog device | ||
310 | * @inode: inode structure | ||
311 | * @file: file structure | ||
312 | * @cmd: command for ioctl | ||
313 | * @arg: argument pointer | ||
314 | * | ||
315 | * returns 0 on success, <0 on failure | ||
316 | * | ||
317 | * wdrtas_ioctl implements the watchdog API ioctls | ||
318 | */ | ||
319 | static int | ||
320 | wdrtas_ioctl(struct inode *inode, struct file *file, | ||
321 | unsigned int cmd, unsigned long arg) | ||
322 | { | ||
323 | int __user *argp = (void *)arg; | ||
324 | int i; | ||
325 | static struct watchdog_info wdinfo = { | ||
326 | .options = WDRTAS_SUPPORTED_MASK, | ||
327 | .firmware_version = 0, | ||
328 | .identity = "wdrtas" | ||
329 | }; | ||
330 | |||
331 | switch (cmd) { | ||
332 | case WDIOC_GETSUPPORT: | ||
333 | if (copy_to_user(argp, &wdinfo, sizeof(wdinfo))) | ||
334 | return -EFAULT; | ||
335 | return 0; | ||
336 | |||
337 | case WDIOC_GETSTATUS: | ||
338 | i = wdrtas_get_status(); | ||
339 | return put_user(i, argp); | ||
340 | |||
341 | case WDIOC_GETBOOTSTATUS: | ||
342 | i = wdrtas_get_boot_status(); | ||
343 | return put_user(i, argp); | ||
344 | |||
345 | case WDIOC_GETTEMP: | ||
346 | if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) | ||
347 | return -EOPNOTSUPP; | ||
348 | |||
349 | i = wdrtas_get_temperature(); | ||
350 | return put_user(i, argp); | ||
351 | |||
352 | case WDIOC_SETOPTIONS: | ||
353 | if (get_user(i, argp)) | ||
354 | return -EFAULT; | ||
355 | if (i & WDIOS_DISABLECARD) | ||
356 | wdrtas_timer_stop(); | ||
357 | if (i & WDIOS_ENABLECARD) { | ||
358 | wdrtas_timer_keepalive(); | ||
359 | wdrtas_timer_start(); | ||
360 | } | ||
361 | if (i & WDIOS_TEMPPANIC) { | ||
362 | /* not implemented. Done by H8 */ | ||
363 | } | ||
364 | return 0; | ||
365 | |||
366 | case WDIOC_KEEPALIVE: | ||
367 | wdrtas_timer_keepalive(); | ||
368 | return 0; | ||
369 | |||
370 | case WDIOC_SETTIMEOUT: | ||
371 | if (get_user(i, argp)) | ||
372 | return -EFAULT; | ||
373 | |||
374 | if (wdrtas_set_interval(i)) | ||
375 | return -EINVAL; | ||
376 | |||
377 | wdrtas_timer_keepalive(); | ||
378 | |||
379 | if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) | ||
380 | wdrtas_interval = i; | ||
381 | else | ||
382 | wdrtas_interval = wdrtas_get_interval(i); | ||
383 | /* fallthrough */ | ||
384 | |||
385 | case WDIOC_GETTIMEOUT: | ||
386 | return put_user(wdrtas_interval, argp); | ||
387 | |||
388 | default: | ||
389 | return -ENOIOCTLCMD; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | /** | ||
394 | * wdrtas_open - open function of watchdog device | ||
395 | * @inode: inode structure | ||
396 | * @file: file structure | ||
397 | * | ||
398 | * returns 0 on success, -EBUSY if the file has been opened already, <0 on | ||
399 | * other failures | ||
400 | * | ||
401 | * function called when watchdog device is opened | ||
402 | */ | ||
403 | static int | ||
404 | wdrtas_open(struct inode *inode, struct file *file) | ||
405 | { | ||
406 | /* only open once */ | ||
407 | if (atomic_inc_return(&wdrtas_miscdev_open) > 1) { | ||
408 | atomic_dec(&wdrtas_miscdev_open); | ||
409 | return -EBUSY; | ||
410 | } | ||
411 | |||
412 | wdrtas_timer_start(); | ||
413 | wdrtas_timer_keepalive(); | ||
414 | |||
415 | return nonseekable_open(inode, file); | ||
416 | } | ||
417 | |||
418 | /** | ||
419 | * wdrtas_close - close function of watchdog device | ||
420 | * @inode: inode structure | ||
421 | * @file: file structure | ||
422 | * | ||
423 | * returns 0 on success | ||
424 | * | ||
425 | * close function. Always succeeds | ||
426 | */ | ||
427 | static int | ||
428 | wdrtas_close(struct inode *inode, struct file *file) | ||
429 | { | ||
430 | /* only stop watchdog, if this was announced using 'V' before */ | ||
431 | if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR) | ||
432 | wdrtas_timer_stop(); | ||
433 | else { | ||
434 | printk(KERN_WARNING "wdrtas: got unexpected close. Watchdog " | ||
435 | "not stopped.\n"); | ||
436 | wdrtas_timer_keepalive(); | ||
437 | } | ||
438 | |||
439 | wdrtas_expect_close = 0; | ||
440 | atomic_dec(&wdrtas_miscdev_open); | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | /** | ||
445 | * wdrtas_temp_read - gives back the temperature in fahrenheit | ||
446 | * @file: file structure | ||
447 | * @buf: user buffer | ||
448 | * @count: number of bytes to be read | ||
449 | * @ppos: position in file | ||
450 | * | ||
451 | * returns always 1 or -EFAULT in case of user space copy failures, <0 on | ||
452 | * other failures | ||
453 | * | ||
454 | * wdrtas_temp_read gives the temperature to the users by copying this | ||
455 | * value as one byte into the user space buffer. The unit is Fahrenheit... | ||
456 | */ | ||
457 | static ssize_t | ||
458 | wdrtas_temp_read(struct file *file, char __user *buf, | ||
459 | size_t count, loff_t *ppos) | ||
460 | { | ||
461 | int temperature = 0; | ||
462 | |||
463 | temperature = wdrtas_get_temperature(); | ||
464 | if (temperature < 0) | ||
465 | return temperature; | ||
466 | |||
467 | if (copy_to_user(buf, &temperature, 1)) | ||
468 | return -EFAULT; | ||
469 | |||
470 | return 1; | ||
471 | } | ||
472 | |||
473 | /** | ||
474 | * wdrtas_temp_open - open function of temperature device | ||
475 | * @inode: inode structure | ||
476 | * @file: file structure | ||
477 | * | ||
478 | * returns 0 on success, <0 on failure | ||
479 | * | ||
480 | * function called when temperature device is opened | ||
481 | */ | ||
482 | static int | ||
483 | wdrtas_temp_open(struct inode *inode, struct file *file) | ||
484 | { | ||
485 | return nonseekable_open(inode, file); | ||
486 | } | ||
487 | |||
488 | /** | ||
489 | * wdrtas_temp_close - close function of temperature device | ||
490 | * @inode: inode structure | ||
491 | * @file: file structure | ||
492 | * | ||
493 | * returns 0 on success | ||
494 | * | ||
495 | * close function. Always succeeds | ||
496 | */ | ||
497 | static int | ||
498 | wdrtas_temp_close(struct inode *inode, struct file *file) | ||
499 | { | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | /** | ||
504 | * wdrtas_reboot - reboot notifier function | ||
505 | * @nb: notifier block structure | ||
506 | * @code: reboot code | ||
507 | * @ptr: unused | ||
508 | * | ||
509 | * returns NOTIFY_DONE | ||
510 | * | ||
511 | * wdrtas_reboot stops the watchdog in case of a reboot | ||
512 | */ | ||
513 | static int | ||
514 | wdrtas_reboot(struct notifier_block *this, unsigned long code, void *ptr) | ||
515 | { | ||
516 | if ( (code==SYS_DOWN) || (code==SYS_HALT) ) | ||
517 | wdrtas_timer_stop(); | ||
518 | |||
519 | return NOTIFY_DONE; | ||
520 | } | ||
521 | |||
522 | /*** initialization stuff */ | ||
523 | |||
524 | static struct file_operations wdrtas_fops = { | ||
525 | .owner = THIS_MODULE, | ||
526 | .llseek = no_llseek, | ||
527 | .write = wdrtas_write, | ||
528 | .ioctl = wdrtas_ioctl, | ||
529 | .open = wdrtas_open, | ||
530 | .release = wdrtas_close, | ||
531 | }; | ||
532 | |||
533 | static struct miscdevice wdrtas_miscdev = { | ||
534 | .minor = WATCHDOG_MINOR, | ||
535 | .name = "watchdog", | ||
536 | .fops = &wdrtas_fops, | ||
537 | }; | ||
538 | |||
539 | static struct file_operations wdrtas_temp_fops = { | ||
540 | .owner = THIS_MODULE, | ||
541 | .llseek = no_llseek, | ||
542 | .read = wdrtas_temp_read, | ||
543 | .open = wdrtas_temp_open, | ||
544 | .release = wdrtas_temp_close, | ||
545 | }; | ||
546 | |||
547 | static struct miscdevice wdrtas_tempdev = { | ||
548 | .minor = TEMP_MINOR, | ||
549 | .name = "temperature", | ||
550 | .fops = &wdrtas_temp_fops, | ||
551 | }; | ||
552 | |||
553 | static struct notifier_block wdrtas_notifier = { | ||
554 | .notifier_call = wdrtas_reboot, | ||
555 | }; | ||
556 | |||
557 | /** | ||
558 | * wdrtas_get_tokens - reads in RTAS tokens | ||
559 | * | ||
560 | * returns 0 on succes, <0 on failure | ||
561 | * | ||
562 | * wdrtas_get_tokens reads in the tokens for the RTAS calls used in | ||
563 | * this watchdog driver. It tolerates, if "get-sensor-state" and | ||
564 | * "ibm,get-system-parameter" are not available. | ||
565 | */ | ||
566 | static int | ||
567 | wdrtas_get_tokens(void) | ||
568 | { | ||
569 | wdrtas_token_get_sensor_state = rtas_token("get-sensor-state"); | ||
570 | if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) { | ||
571 | printk(KERN_WARNING "wdrtas: couldn't get token for " | ||
572 | "get-sensor-state. Trying to continue without " | ||
573 | "temperature support.\n"); | ||
574 | } | ||
575 | |||
576 | wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter"); | ||
577 | if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) { | ||
578 | printk(KERN_WARNING "wdrtas: couldn't get token for " | ||
579 | "ibm,get-system-parameter. Trying to continue with " | ||
580 | "a default timeout value of %i seconds.\n", | ||
581 | WDRTAS_DEFAULT_INTERVAL); | ||
582 | } | ||
583 | |||
584 | wdrtas_token_set_indicator = rtas_token("set-indicator"); | ||
585 | if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) { | ||
586 | printk(KERN_ERR "wdrtas: couldn't get token for " | ||
587 | "set-indicator. Terminating watchdog code.\n"); | ||
588 | return -EIO; | ||
589 | } | ||
590 | |||
591 | wdrtas_token_event_scan = rtas_token("event-scan"); | ||
592 | if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) { | ||
593 | printk(KERN_ERR "wdrtas: couldn't get token for event-scan. " | ||
594 | "Terminating watchdog code.\n"); | ||
595 | return -EIO; | ||
596 | } | ||
597 | |||
598 | return 0; | ||
599 | } | ||
600 | |||
601 | /** | ||
602 | * wdrtas_unregister_devs - unregisters the misc dev handlers | ||
603 | * | ||
604 | * wdrtas_register_devs unregisters the watchdog and temperature watchdog | ||
605 | * misc devs | ||
606 | */ | ||
607 | static void | ||
608 | wdrtas_unregister_devs(void) | ||
609 | { | ||
610 | misc_deregister(&wdrtas_miscdev); | ||
611 | if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) | ||
612 | misc_deregister(&wdrtas_tempdev); | ||
613 | } | ||
614 | |||
615 | /** | ||
616 | * wdrtas_register_devs - registers the misc dev handlers | ||
617 | * | ||
618 | * returns 0 on succes, <0 on failure | ||
619 | * | ||
620 | * wdrtas_register_devs registers the watchdog and temperature watchdog | ||
621 | * misc devs | ||
622 | */ | ||
623 | static int | ||
624 | wdrtas_register_devs(void) | ||
625 | { | ||
626 | int result; | ||
627 | |||
628 | result = misc_register(&wdrtas_miscdev); | ||
629 | if (result) { | ||
630 | printk(KERN_ERR "wdrtas: couldn't register watchdog misc " | ||
631 | "device. Terminating watchdog code.\n"); | ||
632 | return result; | ||
633 | } | ||
634 | |||
635 | if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) { | ||
636 | result = misc_register(&wdrtas_tempdev); | ||
637 | if (result) { | ||
638 | printk(KERN_WARNING "wdrtas: couldn't register " | ||
639 | "watchdog temperature misc device. Continuing " | ||
640 | "without temperature support.\n"); | ||
641 | wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | /** | ||
649 | * wdrtas_init - init function of the watchdog driver | ||
650 | * | ||
651 | * returns 0 on succes, <0 on failure | ||
652 | * | ||
653 | * registers the file handlers and the reboot notifier | ||
654 | */ | ||
655 | static int __init | ||
656 | wdrtas_init(void) | ||
657 | { | ||
658 | if (wdrtas_get_tokens()) | ||
659 | return -ENODEV; | ||
660 | |||
661 | if (wdrtas_register_devs()) | ||
662 | return -ENODEV; | ||
663 | |||
664 | if (register_reboot_notifier(&wdrtas_notifier)) { | ||
665 | printk(KERN_ERR "wdrtas: could not register reboot notifier. " | ||
666 | "Terminating watchdog code.\n"); | ||
667 | wdrtas_unregister_devs(); | ||
668 | return -ENODEV; | ||
669 | } | ||
670 | |||
671 | if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) | ||
672 | wdrtas_interval = WDRTAS_DEFAULT_INTERVAL; | ||
673 | else | ||
674 | wdrtas_interval = wdrtas_get_interval(WDRTAS_DEFAULT_INTERVAL); | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | /** | ||
680 | * wdrtas_exit - exit function of the watchdog driver | ||
681 | * | ||
682 | * unregisters the file handlers and the reboot notifier | ||
683 | */ | ||
684 | static void __exit | ||
685 | wdrtas_exit(void) | ||
686 | { | ||
687 | if (!wdrtas_nowayout) | ||
688 | wdrtas_timer_stop(); | ||
689 | |||
690 | wdrtas_unregister_devs(); | ||
691 | |||
692 | unregister_reboot_notifier(&wdrtas_notifier); | ||
693 | } | ||
694 | |||
695 | module_init(wdrtas_init); | ||
696 | module_exit(wdrtas_exit); | ||
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c index df1b721154..839b44a7e0 100644 --- a/drivers/firmware/pcdp.c +++ b/drivers/firmware/pcdp.c | |||
@@ -23,12 +23,15 @@ setup_serial_console(struct pcdp_uart *uart) | |||
23 | { | 23 | { |
24 | #ifdef CONFIG_SERIAL_8250_CONSOLE | 24 | #ifdef CONFIG_SERIAL_8250_CONSOLE |
25 | int mmio; | 25 | int mmio; |
26 | static char options[64]; | 26 | static char options[64], *p = options; |
27 | 27 | ||
28 | mmio = (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY); | 28 | mmio = (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY); |
29 | snprintf(options, sizeof(options), "console=uart,%s,0x%lx,%lun%d", | 29 | p += sprintf(p, "console=uart,%s,0x%lx", |
30 | mmio ? "mmio" : "io", uart->addr.address, uart->baud, | 30 | mmio ? "mmio" : "io", uart->addr.address); |
31 | uart->bits ? uart->bits : 8); | 31 | if (uart->baud) |
32 | p += sprintf(p, ",%lu", uart->baud); | ||
33 | if (uart->bits) | ||
34 | p += sprintf(p, "n%d", uart->bits); | ||
32 | 35 | ||
33 | return early_serial_console_init(options); | 36 | return early_serial_console_init(options); |
34 | #else | 37 | #else |
diff --git a/drivers/firmware/pcdp.h b/drivers/firmware/pcdp.h index 863bb6f768..1dc7c88b7b 100644 --- a/drivers/firmware/pcdp.h +++ b/drivers/firmware/pcdp.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * Definitions for PCDP-defined console devices | 2 | * Definitions for PCDP-defined console devices |
3 | * | 3 | * |
4 | * v1.0a: http://www.dig64.org/specifications/DIG64_HCDPv10a_01.pdf | 4 | * v1.0a: http://www.dig64.org/specifications/DIG64_HCDPv10a_01.pdf |
5 | * v2.0: http://www.dig64.org/specifications/DIG64_HCDPv20_042804.pdf | 5 | * v2.0: http://www.dig64.org/specifications/DIG64_PCDPv20.pdf |
6 | * | 6 | * |
7 | * (c) Copyright 2002, 2004 Hewlett-Packard Development Company, L.P. | 7 | * (c) Copyright 2002, 2004 Hewlett-Packard Development Company, L.P. |
8 | * Khalid Aziz <khalid.aziz@hp.com> | 8 | * Khalid Aziz <khalid.aziz@hp.com> |
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c index ec943cad23..1956af382c 100644 --- a/drivers/i2c/busses/i2c-ixp2000.c +++ b/drivers/i2c/busses/i2c-ixp2000.c | |||
@@ -33,7 +33,8 @@ | |||
33 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
34 | #include <linux/i2c-algo-bit.h> | 34 | #include <linux/i2c-algo-bit.h> |
35 | 35 | ||
36 | #include <asm/hardware.h> /* Pick up IXP42000-specific bits */ | 36 | #include <asm/hardware.h> /* Pick up IXP2000-specific bits */ |
37 | #include <asm/arch/gpio.h> | ||
37 | 38 | ||
38 | static inline int ixp2000_scl_pin(void *data) | 39 | static inline int ixp2000_scl_pin(void *data) |
39 | { | 40 | { |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 39f3e9101e..0a31cfda08 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -2657,16 +2657,63 @@ int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock) | |||
2657 | } | 2657 | } |
2658 | 2658 | ||
2659 | static | 2659 | static |
2660 | int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap) | ||
2661 | { | ||
2662 | struct cdrom_info *info = drive->driver_data; | ||
2663 | struct cdrom_device_info *cdi = &info->devinfo; | ||
2664 | struct packet_command cgc; | ||
2665 | int stat, attempts = 3, size = sizeof(*cap); | ||
2666 | |||
2667 | /* | ||
2668 | * ACER50 (and others?) require the full spec length mode sense | ||
2669 | * page capabilities size, but older drives break. | ||
2670 | */ | ||
2671 | if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") || | ||
2672 | !strcmp(drive->id->model, "WPI CDS-32X"))) | ||
2673 | size -= sizeof(cap->pad); | ||
2674 | |||
2675 | init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN); | ||
2676 | do { /* we seem to get stat=0x01,err=0x00 the first time (??) */ | ||
2677 | stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); | ||
2678 | if (!stat) | ||
2679 | break; | ||
2680 | } while (--attempts); | ||
2681 | return stat; | ||
2682 | } | ||
2683 | |||
2684 | static | ||
2685 | void ide_cdrom_update_speed (ide_drive_t *drive, struct atapi_capabilities_page *cap) | ||
2686 | { | ||
2687 | /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */ | ||
2688 | if (!drive->id->model[0] && | ||
2689 | !strncmp(drive->id->fw_rev, "241N", 4)) { | ||
2690 | CDROM_STATE_FLAGS(drive)->current_speed = | ||
2691 | (((unsigned int)cap->curspeed) + (176/2)) / 176; | ||
2692 | CDROM_CONFIG_FLAGS(drive)->max_speed = | ||
2693 | (((unsigned int)cap->maxspeed) + (176/2)) / 176; | ||
2694 | } else { | ||
2695 | CDROM_STATE_FLAGS(drive)->current_speed = | ||
2696 | (ntohs(cap->curspeed) + (176/2)) / 176; | ||
2697 | CDROM_CONFIG_FLAGS(drive)->max_speed = | ||
2698 | (ntohs(cap->maxspeed) + (176/2)) / 176; | ||
2699 | } | ||
2700 | } | ||
2701 | |||
2702 | static | ||
2660 | int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed) | 2703 | int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed) |
2661 | { | 2704 | { |
2662 | ide_drive_t *drive = (ide_drive_t*) cdi->handle; | 2705 | ide_drive_t *drive = (ide_drive_t*) cdi->handle; |
2663 | struct request_sense sense; | 2706 | struct request_sense sense; |
2707 | struct atapi_capabilities_page cap; | ||
2664 | int stat; | 2708 | int stat; |
2665 | 2709 | ||
2666 | if ((stat = cdrom_select_speed(drive, speed, &sense)) < 0) | 2710 | if ((stat = cdrom_select_speed(drive, speed, &sense)) < 0) |
2667 | return stat; | 2711 | return stat; |
2668 | 2712 | ||
2669 | cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed; | 2713 | if (!ide_cdrom_get_capabilities(drive, &cap)) { |
2714 | ide_cdrom_update_speed(drive, &cap); | ||
2715 | cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed; | ||
2716 | } | ||
2670 | return 0; | 2717 | return 0; |
2671 | } | 2718 | } |
2672 | 2719 | ||
@@ -2869,31 +2916,6 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots) | |||
2869 | } | 2916 | } |
2870 | 2917 | ||
2871 | static | 2918 | static |
2872 | int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap) | ||
2873 | { | ||
2874 | struct cdrom_info *info = drive->driver_data; | ||
2875 | struct cdrom_device_info *cdi = &info->devinfo; | ||
2876 | struct packet_command cgc; | ||
2877 | int stat, attempts = 3, size = sizeof(*cap); | ||
2878 | |||
2879 | /* | ||
2880 | * ACER50 (and others?) require the full spec length mode sense | ||
2881 | * page capabilities size, but older drives break. | ||
2882 | */ | ||
2883 | if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") || | ||
2884 | !strcmp(drive->id->model, "WPI CDS-32X"))) | ||
2885 | size -= sizeof(cap->pad); | ||
2886 | |||
2887 | init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN); | ||
2888 | do { /* we seem to get stat=0x01,err=0x00 the first time (??) */ | ||
2889 | stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); | ||
2890 | if (!stat) | ||
2891 | break; | ||
2892 | } while (--attempts); | ||
2893 | return stat; | ||
2894 | } | ||
2895 | |||
2896 | static | ||
2897 | int ide_cdrom_probe_capabilities (ide_drive_t *drive) | 2919 | int ide_cdrom_probe_capabilities (ide_drive_t *drive) |
2898 | { | 2920 | { |
2899 | struct cdrom_info *info = drive->driver_data; | 2921 | struct cdrom_info *info = drive->driver_data; |
@@ -2978,20 +3000,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) | |||
2978 | } | 3000 | } |
2979 | } | 3001 | } |
2980 | 3002 | ||
2981 | /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */ | 3003 | ide_cdrom_update_speed(drive, &cap); |
2982 | if (!drive->id->model[0] && | ||
2983 | !strncmp(drive->id->fw_rev, "241N", 4)) { | ||
2984 | CDROM_STATE_FLAGS(drive)->current_speed = | ||
2985 | (((unsigned int)cap.curspeed) + (176/2)) / 176; | ||
2986 | CDROM_CONFIG_FLAGS(drive)->max_speed = | ||
2987 | (((unsigned int)cap.maxspeed) + (176/2)) / 176; | ||
2988 | } else { | ||
2989 | CDROM_STATE_FLAGS(drive)->current_speed = | ||
2990 | (ntohs(cap.curspeed) + (176/2)) / 176; | ||
2991 | CDROM_CONFIG_FLAGS(drive)->max_speed = | ||
2992 | (ntohs(cap.maxspeed) + (176/2)) / 176; | ||
2993 | } | ||
2994 | |||
2995 | /* don't print speed if the drive reported 0. | 3004 | /* don't print speed if the drive reported 0. |
2996 | */ | 3005 | */ |
2997 | printk(KERN_INFO "%s: ATAPI", drive->name); | 3006 | printk(KERN_INFO "%s: ATAPI", drive->name); |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 3302cd8eab..d6f934886b 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -1215,7 +1215,8 @@ static int ide_disk_probe(struct device *dev) | |||
1215 | if (!idkp) | 1215 | if (!idkp) |
1216 | goto failed; | 1216 | goto failed; |
1217 | 1217 | ||
1218 | g = alloc_disk(1 << PARTN_BITS); | 1218 | g = alloc_disk_node(1 << PARTN_BITS, |
1219 | pcibus_to_node(drive->hwif->pci_dev->bus)); | ||
1219 | if (!g) | 1220 | if (!g) |
1220 | goto out_free_idkp; | 1221 | goto out_free_idkp; |
1221 | 1222 | ||
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index c949e98df4..9eab642614 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -661,10 +661,12 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un | |||
661 | 661 | ||
662 | idefloppy_do_end_request(drive, 1, done >> 9); | 662 | idefloppy_do_end_request(drive, 1, done >> 9); |
663 | 663 | ||
664 | #if IDEFLOPPY_DEBUG_BUGS | ||
664 | if (bcount) { | 665 | if (bcount) { |
665 | printk(KERN_ERR "%s: leftover data in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount); | 666 | printk(KERN_ERR "%s: leftover data in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount); |
666 | idefloppy_write_zeros(drive, bcount); | 667 | idefloppy_write_zeros(drive, bcount); |
667 | } | 668 | } |
669 | #endif | ||
668 | } | 670 | } |
669 | 671 | ||
670 | static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc) | 672 | static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc) |
@@ -1048,6 +1050,9 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p | |||
1048 | atapi_bcount_t bcount; | 1050 | atapi_bcount_t bcount; |
1049 | ide_handler_t *pkt_xfer_routine; | 1051 | ide_handler_t *pkt_xfer_routine; |
1050 | 1052 | ||
1053 | #if 0 /* Accessing floppy->pc is not valid here, the previous pc may be gone | ||
1054 | and have lived on another thread's stack; that stack may have become | ||
1055 | unmapped meanwhile (CONFIG_DEBUG_PAGEALLOC). */ | ||
1051 | #if IDEFLOPPY_DEBUG_BUGS | 1056 | #if IDEFLOPPY_DEBUG_BUGS |
1052 | if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD && | 1057 | if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD && |
1053 | pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { | 1058 | pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { |
@@ -1055,6 +1060,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p | |||
1055 | "Two request sense in serial were issued\n"); | 1060 | "Two request sense in serial were issued\n"); |
1056 | } | 1061 | } |
1057 | #endif /* IDEFLOPPY_DEBUG_BUGS */ | 1062 | #endif /* IDEFLOPPY_DEBUG_BUGS */ |
1063 | #endif | ||
1058 | 1064 | ||
1059 | if (floppy->failed_pc == NULL && | 1065 | if (floppy->failed_pc == NULL && |
1060 | pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD) | 1066 | pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD) |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 5d876f53c6..7df85af753 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -977,8 +977,9 @@ static int ide_init_queue(ide_drive_t *drive) | |||
977 | * limits and LBA48 we could raise it but as yet | 977 | * limits and LBA48 we could raise it but as yet |
978 | * do not. | 978 | * do not. |
979 | */ | 979 | */ |
980 | 980 | ||
981 | q = blk_init_queue(do_ide_request, &ide_lock); | 981 | q = blk_init_queue_node(do_ide_request, &ide_lock, |
982 | pcibus_to_node(drive->hwif->pci_dev->bus)); | ||
982 | if (!q) | 983 | if (!q) |
983 | return 1; | 984 | return 1; |
984 | 985 | ||
@@ -1095,7 +1096,8 @@ static int init_irq (ide_hwif_t *hwif) | |||
1095 | hwgroup->hwif->next = hwif; | 1096 | hwgroup->hwif->next = hwif; |
1096 | spin_unlock_irq(&ide_lock); | 1097 | spin_unlock_irq(&ide_lock); |
1097 | } else { | 1098 | } else { |
1098 | hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL); | 1099 | hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL, |
1100 | pcibus_to_node(hwif->drives[0].hwif->pci_dev->bus)); | ||
1099 | if (!hwgroup) | 1101 | if (!hwgroup) |
1100 | goto out_up; | 1102 | goto out_up; |
1101 | 1103 | ||
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index f6b85222ba..79ca384691 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c | |||
@@ -257,7 +257,7 @@ static int __init serport_init(void) | |||
257 | 257 | ||
258 | static void __exit serport_exit(void) | 258 | static void __exit serport_exit(void) |
259 | { | 259 | { |
260 | tty_register_ldisc(N_MOUSE, NULL); | 260 | tty_unregister_ldisc(N_MOUSE); |
261 | } | 261 | } |
262 | 262 | ||
263 | module_init(serport_init); | 263 | module_init(serport_init); |
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index ee3c869d97..200a0688f7 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
@@ -122,14 +122,6 @@ static struct hash_cell *__get_uuid_cell(const char *str) | |||
122 | /*----------------------------------------------------------------- | 122 | /*----------------------------------------------------------------- |
123 | * Inserting, removing and renaming a device. | 123 | * Inserting, removing and renaming a device. |
124 | *---------------------------------------------------------------*/ | 124 | *---------------------------------------------------------------*/ |
125 | static inline char *kstrdup(const char *str) | ||
126 | { | ||
127 | char *r = kmalloc(strlen(str) + 1, GFP_KERNEL); | ||
128 | if (r) | ||
129 | strcpy(r, str); | ||
130 | return r; | ||
131 | } | ||
132 | |||
133 | static struct hash_cell *alloc_cell(const char *name, const char *uuid, | 125 | static struct hash_cell *alloc_cell(const char *name, const char *uuid, |
134 | struct mapped_device *md) | 126 | struct mapped_device *md) |
135 | { | 127 | { |
@@ -139,7 +131,7 @@ static struct hash_cell *alloc_cell(const char *name, const char *uuid, | |||
139 | if (!hc) | 131 | if (!hc) |
140 | return NULL; | 132 | return NULL; |
141 | 133 | ||
142 | hc->name = kstrdup(name); | 134 | hc->name = kstrdup(name, GFP_KERNEL); |
143 | if (!hc->name) { | 135 | if (!hc->name) { |
144 | kfree(hc); | 136 | kfree(hc); |
145 | return NULL; | 137 | return NULL; |
@@ -149,7 +141,7 @@ static struct hash_cell *alloc_cell(const char *name, const char *uuid, | |||
149 | hc->uuid = NULL; | 141 | hc->uuid = NULL; |
150 | 142 | ||
151 | else { | 143 | else { |
152 | hc->uuid = kstrdup(uuid); | 144 | hc->uuid = kstrdup(uuid, GFP_KERNEL); |
153 | if (!hc->uuid) { | 145 | if (!hc->uuid) { |
154 | kfree(hc->name); | 146 | kfree(hc->name); |
155 | kfree(hc); | 147 | kfree(hc); |
@@ -273,7 +265,7 @@ static int dm_hash_rename(const char *old, const char *new) | |||
273 | /* | 265 | /* |
274 | * duplicate new. | 266 | * duplicate new. |
275 | */ | 267 | */ |
276 | new_name = kstrdup(new); | 268 | new_name = kstrdup(new, GFP_KERNEL); |
277 | if (!new_name) | 269 | if (!new_name) |
278 | return -ENOMEM; | 270 | return -ENOMEM; |
279 | 271 | ||
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c index 84a49d2ec9..4adb2843f8 100644 --- a/drivers/media/common/ir-common.c +++ b/drivers/media/common/ir-common.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: ir-common.c,v 1.8 2005/02/22 12:28:40 kraxel Exp $ | 2 | * $Id: ir-common.c,v 1.10 2005/05/22 19:23:39 nsh Exp $ |
3 | * | 3 | * |
4 | * some common structs and functions to handle infrared remotes via | 4 | * some common structs and functions to handle infrared remotes via |
5 | * input layer ... | 5 | * input layer ... |
@@ -131,10 +131,10 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { | |||
131 | [ 18 ] = KEY_KP0, | 131 | [ 18 ] = KEY_KP0, |
132 | 132 | ||
133 | [ 0 ] = KEY_POWER, | 133 | [ 0 ] = KEY_POWER, |
134 | [ 27 ] = KEY_LANGUAGE, //MTS button | 134 | // [ 27 ] = MTS button |
135 | [ 2 ] = KEY_TUNER, // TV/FM | 135 | [ 2 ] = KEY_TUNER, // TV/FM |
136 | [ 30 ] = KEY_VIDEO, | 136 | [ 30 ] = KEY_VIDEO, |
137 | [ 22 ] = KEY_INFO, //display button | 137 | // [ 22 ] = display button |
138 | [ 4 ] = KEY_VOLUMEUP, | 138 | [ 4 ] = KEY_VOLUMEUP, |
139 | [ 8 ] = KEY_VOLUMEDOWN, | 139 | [ 8 ] = KEY_VOLUMEDOWN, |
140 | [ 12 ] = KEY_CHANNELUP, | 140 | [ 12 ] = KEY_CHANNELUP, |
@@ -142,7 +142,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { | |||
142 | [ 3 ] = KEY_ZOOM, // fullscreen | 142 | [ 3 ] = KEY_ZOOM, // fullscreen |
143 | [ 31 ] = KEY_SUBTITLE, // closed caption/teletext | 143 | [ 31 ] = KEY_SUBTITLE, // closed caption/teletext |
144 | [ 32 ] = KEY_SLEEP, | 144 | [ 32 ] = KEY_SLEEP, |
145 | [ 41 ] = KEY_SEARCH, //boss key | 145 | // [ 41 ] = boss key |
146 | [ 20 ] = KEY_MUTE, | 146 | [ 20 ] = KEY_MUTE, |
147 | [ 43 ] = KEY_RED, | 147 | [ 43 ] = KEY_RED, |
148 | [ 44 ] = KEY_GREEN, | 148 | [ 44 ] = KEY_GREEN, |
@@ -150,17 +150,17 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { | |||
150 | [ 46 ] = KEY_BLUE, | 150 | [ 46 ] = KEY_BLUE, |
151 | [ 24 ] = KEY_KPPLUS, //fine tune + | 151 | [ 24 ] = KEY_KPPLUS, //fine tune + |
152 | [ 25 ] = KEY_KPMINUS, //fine tune - | 152 | [ 25 ] = KEY_KPMINUS, //fine tune - |
153 | [ 42 ] = KEY_ANGLE, //picture in picture | 153 | // [ 42 ] = picture in picture |
154 | [ 33 ] = KEY_KPDOT, | 154 | [ 33 ] = KEY_KPDOT, |
155 | [ 19 ] = KEY_KPENTER, | 155 | [ 19 ] = KEY_KPENTER, |
156 | [ 17 ] = KEY_AGAIN, //recall | 156 | // [ 17 ] = recall |
157 | [ 34 ] = KEY_BACK, | 157 | [ 34 ] = KEY_BACK, |
158 | [ 35 ] = KEY_PLAYPAUSE, | 158 | [ 35 ] = KEY_PLAYPAUSE, |
159 | [ 36 ] = KEY_NEXT, | 159 | [ 36 ] = KEY_NEXT, |
160 | [ 37 ] = KEY_T, //time shifting | 160 | // [ 37 ] = time shifting |
161 | [ 38 ] = KEY_STOP, | 161 | [ 38 ] = KEY_STOP, |
162 | [ 39 ] = KEY_RECORD, | 162 | [ 39 ] = KEY_RECORD |
163 | [ 40 ] = KEY_SHUFFLE //snapshot | 163 | // [ 40 ] = snapshot |
164 | }; | 164 | }; |
165 | EXPORT_SYMBOL_GPL(ir_codes_winfast); | 165 | EXPORT_SYMBOL_GPL(ir_codes_winfast); |
166 | 166 | ||
@@ -184,18 +184,30 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { | |||
184 | [ 0x07 ] = KEY_KP7, // 7 | 184 | [ 0x07 ] = KEY_KP7, // 7 |
185 | [ 0x08 ] = KEY_KP8, // 8 | 185 | [ 0x08 ] = KEY_KP8, // 8 |
186 | [ 0x09 ] = KEY_KP9, // 9 | 186 | [ 0x09 ] = KEY_KP9, // 9 |
187 | [ 0x0a ] = KEY_TEXT, // keypad asterisk as well | ||
187 | [ 0x0b ] = KEY_RED, // red button | 188 | [ 0x0b ] = KEY_RED, // red button |
188 | [ 0x0c ] = KEY_OPTION, // black key without text | 189 | [ 0x0c ] = KEY_RADIO, // radio |
189 | [ 0x0d ] = KEY_MENU, // menu | 190 | [ 0x0d ] = KEY_MENU, // menu |
191 | [ 0x0e ] = KEY_SUBTITLE, // also the # key | ||
190 | [ 0x0f ] = KEY_MUTE, // mute | 192 | [ 0x0f ] = KEY_MUTE, // mute |
191 | [ 0x10 ] = KEY_VOLUMEUP, // volume + | 193 | [ 0x10 ] = KEY_VOLUMEUP, // volume + |
192 | [ 0x11 ] = KEY_VOLUMEDOWN, // volume - | 194 | [ 0x11 ] = KEY_VOLUMEDOWN, // volume - |
193 | [ 0x1e ] = KEY_NEXT, // skip >| | 195 | [ 0x12 ] = KEY_PREVIOUS, // previous channel |
196 | [ 0x14 ] = KEY_UP, // up | ||
197 | [ 0x15 ] = KEY_DOWN, // down | ||
198 | [ 0x16 ] = KEY_LEFT, // left | ||
199 | [ 0x17 ] = KEY_RIGHT, // right | ||
200 | [ 0x18 ] = KEY_VIDEO, // Videos | ||
201 | [ 0x19 ] = KEY_AUDIO, // Music | ||
202 | [ 0x1a ] = KEY_MHP, // Pictures - presume this means "Multimedia Home Platform"- no "PICTURES" key in input.h | ||
203 | [ 0x1b ] = KEY_EPG, // Guide | ||
204 | [ 0x1c ] = KEY_TV, // TV | ||
205 | [ 0x1e ] = KEY_NEXTSONG, // skip >| | ||
194 | [ 0x1f ] = KEY_EXIT, // back/exit | 206 | [ 0x1f ] = KEY_EXIT, // back/exit |
195 | [ 0x20 ] = KEY_CHANNELUP, // channel / program + | 207 | [ 0x20 ] = KEY_CHANNELUP, // channel / program + |
196 | [ 0x21 ] = KEY_CHANNELDOWN, // channel / program - | 208 | [ 0x21 ] = KEY_CHANNELDOWN, // channel / program - |
197 | [ 0x22 ] = KEY_CHANNEL, // source (old black remote) | 209 | [ 0x22 ] = KEY_CHANNEL, // source (old black remote) |
198 | [ 0x24 ] = KEY_PREVIOUS, // replay |< | 210 | [ 0x24 ] = KEY_PREVIOUSSONG, // replay |< |
199 | [ 0x25 ] = KEY_ENTER, // OK | 211 | [ 0x25 ] = KEY_ENTER, // OK |
200 | [ 0x26 ] = KEY_SLEEP, // minimize (old black remote) | 212 | [ 0x26 ] = KEY_SLEEP, // minimize (old black remote) |
201 | [ 0x29 ] = KEY_BLUE, // blue key | 213 | [ 0x29 ] = KEY_BLUE, // blue key |
@@ -213,6 +225,39 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { | |||
213 | }; | 225 | }; |
214 | EXPORT_SYMBOL(ir_codes_hauppauge_new); | 226 | EXPORT_SYMBOL(ir_codes_hauppauge_new); |
215 | 227 | ||
228 | IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { | ||
229 | [ 2 ] = KEY_KP0, | ||
230 | [ 1 ] = KEY_KP1, | ||
231 | [ 11 ] = KEY_KP2, | ||
232 | [ 27 ] = KEY_KP3, | ||
233 | [ 5 ] = KEY_KP4, | ||
234 | [ 9 ] = KEY_KP5, | ||
235 | [ 21 ] = KEY_KP6, | ||
236 | [ 6 ] = KEY_KP7, | ||
237 | [ 10 ] = KEY_KP8, | ||
238 | [ 18 ] = KEY_KP9, | ||
239 | |||
240 | [ 3 ] = KEY_TUNER, // TV/FM | ||
241 | [ 7 ] = KEY_SEARCH, // scan | ||
242 | [ 28 ] = KEY_ZOOM, // full screen | ||
243 | [ 30 ] = KEY_POWER, | ||
244 | [ 23 ] = KEY_VOLUMEDOWN, | ||
245 | [ 31 ] = KEY_VOLUMEUP, | ||
246 | [ 20 ] = KEY_CHANNELDOWN, | ||
247 | [ 22 ] = KEY_CHANNELUP, | ||
248 | [ 24 ] = KEY_MUTE, | ||
249 | |||
250 | [ 0 ] = KEY_LIST, // source | ||
251 | [ 19 ] = KEY_INFO, // loop | ||
252 | [ 16 ] = KEY_LAST, // +100 | ||
253 | [ 13 ] = KEY_CLEAR, // reset | ||
254 | [ 12 ] = BTN_RIGHT, // fun++ | ||
255 | [ 4 ] = BTN_LEFT, // fun-- | ||
256 | [ 14 ] = KEY_GOTO, // function | ||
257 | [ 15 ] = KEY_STOP, // freeze | ||
258 | }; | ||
259 | EXPORT_SYMBOL(ir_codes_pixelview); | ||
260 | |||
216 | /* -------------------------------------------------------------------------- */ | 261 | /* -------------------------------------------------------------------------- */ |
217 | 262 | ||
218 | static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) | 263 | static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) |
@@ -379,3 +424,4 @@ EXPORT_SYMBOL_GPL(ir_decode_biphase); | |||
379 | * c-basic-offset: 8 | 424 | * c-basic-offset: 8 |
380 | * End: | 425 | * End: |
381 | */ | 426 | */ |
427 | |||
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index cb826c9adf..c04fd11526 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c | |||
@@ -403,7 +403,7 @@ static struct file_operations video_fops = | |||
403 | .llseek = no_llseek, | 403 | .llseek = no_llseek, |
404 | }; | 404 | }; |
405 | 405 | ||
406 | void vv_callback(struct saa7146_dev *dev, unsigned long status) | 406 | static void vv_callback(struct saa7146_dev *dev, unsigned long status) |
407 | { | 407 | { |
408 | u32 isr = status; | 408 | u32 isr = status; |
409 | 409 | ||
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 4983e1b1bb..01387f883c 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig | |||
@@ -27,9 +27,9 @@ source "drivers/media/dvb/ttpci/Kconfig" | |||
27 | 27 | ||
28 | comment "Supported USB Adapters" | 28 | comment "Supported USB Adapters" |
29 | depends on DVB_CORE && USB | 29 | depends on DVB_CORE && USB |
30 | source "drivers/media/dvb/dvb-usb/Kconfig" | ||
30 | source "drivers/media/dvb/ttusb-budget/Kconfig" | 31 | source "drivers/media/dvb/ttusb-budget/Kconfig" |
31 | source "drivers/media/dvb/ttusb-dec/Kconfig" | 32 | source "drivers/media/dvb/ttusb-dec/Kconfig" |
32 | source "drivers/media/dvb/dibusb/Kconfig" | ||
33 | source "drivers/media/dvb/cinergyT2/Kconfig" | 33 | source "drivers/media/dvb/cinergyT2/Kconfig" |
34 | 34 | ||
35 | comment "Supported FlexCopII (B2C2) Adapters" | 35 | comment "Supported FlexCopII (B2C2) Adapters" |
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index 520fc39028..3c6ff16191 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile | |||
@@ -2,4 +2,4 @@ | |||
2 | # Makefile for the kernel multimedia device drivers. | 2 | # Makefile for the kernel multimedia device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dibusb/ cinergyT2/ | 5 | obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ |
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index 99bd675df9..fafd0ab3a2 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig | |||
@@ -6,6 +6,7 @@ config DVB_B2C2_FLEXCOP | |||
6 | select DVB_MT312 | 6 | select DVB_MT312 |
7 | select DVB_NXT2002 | 7 | select DVB_NXT2002 |
8 | select DVB_STV0297 | 8 | select DVB_STV0297 |
9 | select DVB_BCM3510 | ||
9 | help | 10 | help |
10 | Support for the digital TV receiver chip made by B2C2 Inc. included in | 11 | Support for the digital TV receiver chip made by B2C2 Inc. included in |
11 | Technisats PCI cards and USB boxes. | 12 | Technisats PCI cards and USB boxes. |
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 71be400e9a..0410cc96a4 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "stv0299.h" | 10 | #include "stv0299.h" |
11 | #include "mt352.h" | 11 | #include "mt352.h" |
12 | #include "nxt2002.h" | 12 | #include "nxt2002.h" |
13 | #include "bcm3510.h" | ||
13 | #include "stv0297.h" | 14 | #include "stv0297.h" |
14 | #include "mt312.h" | 15 | #include "mt312.h" |
15 | 16 | ||
@@ -285,21 +286,25 @@ static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_front | |||
285 | } | 286 | } |
286 | 287 | ||
287 | static struct mt352_config samsung_tdtc9251dh0_config = { | 288 | static struct mt352_config samsung_tdtc9251dh0_config = { |
288 | |||
289 | .demod_address = 0x0f, | 289 | .demod_address = 0x0f, |
290 | .demod_init = samsung_tdtc9251dh0_demod_init, | 290 | .demod_init = samsung_tdtc9251dh0_demod_init, |
291 | .pll_set = samsung_tdtc9251dh0_pll_set, | 291 | .pll_set = samsung_tdtc9251dh0_pll_set, |
292 | }; | 292 | }; |
293 | 293 | ||
294 | static int nxt2002_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) | 294 | static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) |
295 | { | 295 | { |
296 | struct flexcop_device *fc = fe->dvb->priv; | 296 | struct flexcop_device *fc = fe->dvb->priv; |
297 | return request_firmware(fw, name, fc->dev); | 297 | return request_firmware(fw, name, fc->dev); |
298 | } | 298 | } |
299 | 299 | ||
300 | static struct nxt2002_config samsung_tbmv_config = { | 300 | static struct nxt2002_config samsung_tbmv_config = { |
301 | .demod_address = 0x0a, | 301 | .demod_address = 0x0a, |
302 | .request_firmware = nxt2002_request_firmware, | 302 | .request_firmware = flexcop_fe_request_firmware, |
303 | }; | ||
304 | |||
305 | static struct bcm3510_config air2pc_atsc_first_gen_config = { | ||
306 | .demod_address = 0x0f, | ||
307 | .request_firmware = flexcop_fe_request_firmware, | ||
303 | }; | 308 | }; |
304 | 309 | ||
305 | static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) | 310 | static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) |
@@ -354,11 +359,16 @@ int flexcop_frontend_init(struct flexcop_device *fc) | |||
354 | fc->dev_type = FC_AIR_DVB; | 359 | fc->dev_type = FC_AIR_DVB; |
355 | info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); | 360 | info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); |
356 | } else | 361 | } else |
357 | /* try the air atsc (nxt2002) */ | 362 | /* try the air atsc 2nd generation (nxt2002) */ |
358 | if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { | 363 | if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { |
359 | fc->dev_type = FC_AIR_ATSC; | 364 | fc->dev_type = FC_AIR_ATSC2; |
360 | info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); | 365 | info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); |
361 | } else | 366 | } else |
367 | /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ | ||
368 | if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) { | ||
369 | fc->dev_type = FC_AIR_ATSC1; | ||
370 | info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address); | ||
371 | } else | ||
362 | /* try the cable dvb (stv0297) */ | 372 | /* try the cable dvb (stv0297) */ |
363 | if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) { | 373 | if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) { |
364 | fc->dev_type = FC_CABLE; | 374 | fc->dev_type = FC_CABLE; |
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c index 19e06da467..2308254565 100644 --- a/drivers/media/dvb/b2c2/flexcop-misc.c +++ b/drivers/media/dvb/b2c2/flexcop-misc.c | |||
@@ -45,11 +45,12 @@ const char *flexcop_revision_names[] = { | |||
45 | 45 | ||
46 | const char *flexcop_device_names[] = { | 46 | const char *flexcop_device_names[] = { |
47 | "Unkown device", | 47 | "Unkown device", |
48 | "AirStar 2 DVB-T", | 48 | "Air2PC/AirStar 2 DVB-T", |
49 | "AirStar 2 ATSC", | 49 | "Air2PC/AirStar 2 ATSC 1st generation", |
50 | "SkyStar 2 DVB-S", | 50 | "Air2PC/AirStar 2 ATSC 2nd generation", |
51 | "SkyStar 2 DVB-S (old version)", | 51 | "Sky2PC/SkyStar 2 DVB-S", |
52 | "CableStar 2 DVB-C", | 52 | "Sky2PC/SkyStar 2 DVB-S (old version)", |
53 | "Cable2PC/CableStar 2 DVB-C", | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | const char *flexcop_bus_names[] = { | 56 | const char *flexcop_bus_names[] = { |
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h index 5e131be55c..75b50f21af 100644 --- a/drivers/media/dvb/b2c2/flexcop-reg.h +++ b/drivers/media/dvb/b2c2/flexcop-reg.h | |||
@@ -21,7 +21,8 @@ extern const char *flexcop_revision_names[]; | |||
21 | typedef enum { | 21 | typedef enum { |
22 | FC_UNK = 0, | 22 | FC_UNK = 0, |
23 | FC_AIR_DVB, | 23 | FC_AIR_DVB, |
24 | FC_AIR_ATSC, | 24 | FC_AIR_ATSC1, |
25 | FC_AIR_ATSC2, | ||
25 | FC_SKY, | 26 | FC_SKY, |
26 | FC_SKY_OLD, | 27 | FC_SKY_OLD, |
27 | FC_CABLE, | 28 | FC_CABLE, |
diff --git a/drivers/media/dvb/dibusb/Kconfig b/drivers/media/dvb/dibusb/Kconfig deleted file mode 100644 index 74dfc73ae5..0000000000 --- a/drivers/media/dvb/dibusb/Kconfig +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | config DVB_DIBUSB | ||
2 | tristate "DiBcom USB DVB-T devices (see help for a complete device list)" | ||
3 | depends on DVB_CORE && USB | ||
4 | select FW_LOADER | ||
5 | select DVB_DIB3000MB | ||
6 | select DVB_DIB3000MC | ||
7 | select DVB_MT352 | ||
8 | help | ||
9 | Support for USB 1.1 and 2.0 DVB-T devices based on reference designs made by | ||
10 | DiBcom (http://www.dibcom.fr) and C&E. | ||
11 | |||
12 | Devices supported by this driver: | ||
13 | |||
14 | TwinhanDTV USB-Ter (VP7041) | ||
15 | TwinhanDTV Magic Box (VP7041e) | ||
16 | KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0 | ||
17 | Hama DVB-T USB-Box | ||
18 | DiBcom reference devices (non-public) | ||
19 | Ultima Electronic/Artec T1 USB TVBOX | ||
20 | Compro Videomate DVB-U2000 - DVB-T USB | ||
21 | Grandtec DVB-T USB | ||
22 | Avermedia AverTV DVBT USB | ||
23 | Artec T1 USB1.1 and USB2.0 boxes | ||
24 | Yakumo/Typhoon DVB-T USB2.0 | ||
25 | Hanftek UMT-010 USB2.0 | ||
26 | Hauppauge WinTV NOVA-T USB2 | ||
27 | |||
28 | The VP7041 seems to be identical to "CTS Portable" (Chinese | ||
29 | Television System). | ||
30 | |||
31 | These devices can be understood as budget ones, they "only" deliver | ||
32 | (a part of) the MPEG2 transport stream. | ||
33 | |||
34 | A firmware is needed to get the device working. See Documentation/dvb/README.dibusb | ||
35 | details. | ||
36 | |||
37 | Say Y if you own such a device and want to use it. You should build it as | ||
38 | a module. | ||
39 | |||
40 | config DVB_DIBUSB_MISDESIGNED_DEVICES | ||
41 | bool "Enable support for some misdesigned (see help) devices, which identify with wrong IDs" | ||
42 | depends on DVB_DIBUSB | ||
43 | help | ||
44 | Somehow Artec/Ultima Electronic forgot to program the eeprom of some of their | ||
45 | USB1.1/USB2.0 devices. | ||
46 | So comes that they identify with the default Vendor and Product ID of the Cypress | ||
47 | CY7C64613 (AN2235) or Cypress FX2. | ||
48 | |||
49 | Affected device IDs: | ||
50 | 0x0574:0x2235 (Artec T1 USB1.1, cold) | ||
51 | 0x04b4:0x8613 (Artec T1 USB2.0, cold) | ||
52 | 0x0574:0x1002 (Artec T1 USB2.0, warm) | ||
53 | 0x0574:0x2131 (aged DiBcom USB1.1 test device) | ||
54 | |||
55 | Say Y if your device has one of the mentioned IDs. | ||
56 | |||
57 | config DVB_DIBCOM_DEBUG | ||
58 | bool "Enable extended debug support for DiBcom USB device" | ||
59 | depends on DVB_DIBUSB | ||
60 | help | ||
61 | Say Y if you want to enable debuging. See modinfo dvb-dibusb for | ||
62 | debug levels. | ||
diff --git a/drivers/media/dvb/dibusb/Makefile b/drivers/media/dvb/dibusb/Makefile deleted file mode 100644 index e941c50862..0000000000 --- a/drivers/media/dvb/dibusb/Makefile +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | dvb-dibusb-objs = dvb-dibusb-core.o \ | ||
2 | dvb-dibusb-dvb.o \ | ||
3 | dvb-dibusb-fe-i2c.o \ | ||
4 | dvb-dibusb-firmware.o \ | ||
5 | dvb-dibusb-remote.o \ | ||
6 | dvb-dibusb-usb.o \ | ||
7 | dvb-fe-dtt200u.o | ||
8 | |||
9 | obj-$(CONFIG_DVB_DIBUSB) += dvb-dibusb.o | ||
10 | |||
11 | EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | ||
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-core.c b/drivers/media/dvb/dibusb/dvb-dibusb-core.c deleted file mode 100644 index 26235f9247..0000000000 --- a/drivers/media/dvb/dibusb/dvb-dibusb-core.c +++ /dev/null | |||
@@ -1,558 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for mobile USB Budget DVB-T devices based on reference | ||
3 | * design made by DiBcom (http://www.dibcom.fr/) | ||
4 | * | ||
5 | * dvb-dibusb-core.c | ||
6 | * | ||
7 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
8 | * | ||
9 | * based on GPL code from DiBcom, which has | ||
10 | * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) | ||
11 | * | ||
12 | * Remote control code added by David Matthews (dm@prolingua.co.uk) | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License as | ||
16 | * published by the Free Software Foundation, version 2. | ||
17 | * | ||
18 | * Acknowledgements | ||
19 | * | ||
20 | * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver | ||
21 | * sources, on which this driver (and the dib3000mb/mc/p frontends) are based. | ||
22 | * | ||
23 | * see Documentation/dvb/README.dibusb for more information | ||
24 | */ | ||
25 | #include "dvb-dibusb.h" | ||
26 | |||
27 | #include <linux/moduleparam.h> | ||
28 | |||
29 | /* debug */ | ||
30 | int dvb_dibusb_debug; | ||
31 | module_param_named(debug, dvb_dibusb_debug, int, 0644); | ||
32 | |||
33 | #ifdef CONFIG_DVB_DIBCOM_DEBUG | ||
34 | #define DBSTATUS "" | ||
35 | #else | ||
36 | #define DBSTATUS " (debugging is not enabled)" | ||
37 | #endif | ||
38 | MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err,32=rc (|-able))." DBSTATUS); | ||
39 | #undef DBSTATUS | ||
40 | |||
41 | static int pid_parse; | ||
42 | module_param(pid_parse, int, 0644); | ||
43 | MODULE_PARM_DESC(pid_parse, "enable pid parsing (filtering) when running at USB2.0"); | ||
44 | |||
45 | static int rc_query_interval = 100; | ||
46 | module_param(rc_query_interval, int, 0644); | ||
47 | MODULE_PARM_DESC(rc_query_interval, "interval in msecs for remote control query (default: 100; min: 40)"); | ||
48 | |||
49 | static int rc_key_repeat_count = 2; | ||
50 | module_param(rc_key_repeat_count, int, 0644); | ||
51 | MODULE_PARM_DESC(rc_key_repeat_count, "how many key repeats will be dropped before passing the key event again (default: 2)"); | ||
52 | |||
53 | /* Vendor IDs */ | ||
54 | #define USB_VID_ADSTECH 0x06e1 | ||
55 | #define USB_VID_ANCHOR 0x0547 | ||
56 | #define USB_VID_AVERMEDIA 0x14aa | ||
57 | #define USB_VID_COMPRO 0x185b | ||
58 | #define USB_VID_COMPRO_UNK 0x145f | ||
59 | #define USB_VID_CYPRESS 0x04b4 | ||
60 | #define USB_VID_DIBCOM 0x10b8 | ||
61 | #define USB_VID_EMPIA 0xeb1a | ||
62 | #define USB_VID_GRANDTEC 0x5032 | ||
63 | #define USB_VID_HANFTEK 0x15f4 | ||
64 | #define USB_VID_HAUPPAUGE 0x2040 | ||
65 | #define USB_VID_HYPER_PALTEK 0x1025 | ||
66 | #define USB_VID_IMC_NETWORKS 0x13d3 | ||
67 | #define USB_VID_TWINHAN 0x1822 | ||
68 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 | ||
69 | |||
70 | /* Product IDs */ | ||
71 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 | ||
72 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 | ||
73 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 | ||
74 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 | ||
75 | #define USB_PID_COMPRO_DVBU2000_COLD 0xd000 | ||
76 | #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 | ||
77 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c | ||
78 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d | ||
79 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | ||
80 | #define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9 | ||
81 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 | ||
82 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 | ||
83 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 | ||
84 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 | ||
85 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 | ||
86 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de | ||
87 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df | ||
88 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 | ||
89 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 | ||
90 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 | ||
91 | #define USB_PID_ULTIMA_TVBOX_WARM 0x8106 | ||
92 | #define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107 | ||
93 | #define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108 | ||
94 | #define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235 | ||
95 | #define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109 | ||
96 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613 | ||
97 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002 | ||
98 | #define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e | ||
99 | #define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f | ||
100 | #define USB_PID_HANFTEK_UMT_010_COLD 0x0001 | ||
101 | #define USB_PID_HANFTEK_UMT_010_WARM 0x0015 | ||
102 | #define USB_PID_YAKUMO_DTT200U_COLD 0x0201 | ||
103 | #define USB_PID_YAKUMO_DTT200U_WARM 0x0301 | ||
104 | #define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300 | ||
105 | #define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 | ||
106 | |||
107 | /* USB Driver stuff | ||
108 | * table of devices that this driver is working with | ||
109 | * | ||
110 | * ATTENTION: Never ever change the order of this table, the particular | ||
111 | * devices depend on this order | ||
112 | * | ||
113 | * Each entry is used as a reference in the device_struct. Currently this is | ||
114 | * the only non-redundant way of assigning USB ids to actual devices I'm aware | ||
115 | * of, because there is only one place in the code where the assignment of | ||
116 | * vendor and product id is done, here. | ||
117 | */ | ||
118 | static struct usb_device_id dib_table [] = { | ||
119 | /* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_COLD)}, | ||
120 | /* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_WARM)}, | ||
121 | /* 02 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_COLD) }, | ||
122 | /* 03 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_WARM) }, | ||
123 | |||
124 | /* 04 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) }, | ||
125 | /* 05 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) }, | ||
126 | /* 06 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) }, | ||
127 | /* 07 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) }, | ||
128 | /* 08 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) }, | ||
129 | /* 09 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) }, | ||
130 | /* 10 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) }, | ||
131 | /* 11 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) }, | ||
132 | /* 12 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) }, | ||
133 | /* 13 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) }, | ||
134 | /* 14 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) }, | ||
135 | /* 15 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) }, | ||
136 | /* 16 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) }, | ||
137 | /* 17 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) }, | ||
138 | /* 18 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) }, | ||
139 | /* 19 */ { USB_DEVICE(USB_VID_IMC_NETWORKS, USB_PID_TWINHAN_VP7041_COLD) }, | ||
140 | /* 20 */ { USB_DEVICE(USB_VID_IMC_NETWORKS, USB_PID_TWINHAN_VP7041_WARM) }, | ||
141 | /* 21 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) }, | ||
142 | /* 22 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) }, | ||
143 | /* 23 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) }, | ||
144 | /* 24 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) }, | ||
145 | /* 25 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) }, | ||
146 | /* 26 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) }, | ||
147 | /* 27 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, | ||
148 | |||
149 | /* 28 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) }, | ||
150 | /* 29 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) }, | ||
151 | |||
152 | /* 30 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_COLD) }, | ||
153 | /* 31 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) }, | ||
154 | /* 32 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) }, | ||
155 | /* 33 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) }, | ||
156 | /* | ||
157 | * activate the following define when you have one of the devices and want to | ||
158 | * build it from build-2.6 in dvb-kernel | ||
159 | */ | ||
160 | // #define CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES | ||
161 | #ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES | ||
162 | /* 34 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) }, | ||
163 | /* 35 */ { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ULTIMA_TVBOX_USB2_FX_COLD) }, | ||
164 | /* 36 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_USB2_FX_WARM) }, | ||
165 | /* 37 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_DIBCOM_ANCHOR_2135_COLD) }, | ||
166 | #endif | ||
167 | { } /* Terminating entry */ | ||
168 | }; | ||
169 | |||
170 | MODULE_DEVICE_TABLE (usb, dib_table); | ||
171 | |||
172 | static struct dibusb_usb_controller dibusb_usb_ctrl[] = { | ||
173 | { .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 }, | ||
174 | { .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 }, | ||
175 | { .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, | ||
176 | }; | ||
177 | |||
178 | struct dibusb_tuner dibusb_tuner[] = { | ||
179 | { DIBUSB_TUNER_CABLE_THOMSON, | ||
180 | 0x61 | ||
181 | }, | ||
182 | { DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5, | ||
183 | 0x60 | ||
184 | }, | ||
185 | { DIBUSB_TUNER_CABLE_LG_TDTP_E102P, | ||
186 | 0x61 | ||
187 | }, | ||
188 | { DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5, | ||
189 | 0x60 | ||
190 | }, | ||
191 | }; | ||
192 | |||
193 | static struct dibusb_demod dibusb_demod[] = { | ||
194 | { DIBUSB_DIB3000MB, | ||
195 | 16, | ||
196 | { 0x8, 0 }, | ||
197 | }, | ||
198 | { DIBUSB_DIB3000MC, | ||
199 | 32, | ||
200 | { 0x9, 0xa, 0xb, 0xc }, | ||
201 | }, | ||
202 | { DIBUSB_MT352, | ||
203 | 254, | ||
204 | { 0xf, 0 }, | ||
205 | }, | ||
206 | { DTT200U_FE, | ||
207 | 8, | ||
208 | { 0xff,0 }, /* there is no i2c bus in this device */ | ||
209 | } | ||
210 | }; | ||
211 | |||
212 | static struct dibusb_device_class dibusb_device_classes[] = { | ||
213 | { .id = DIBUSB1_1, .usb_ctrl = &dibusb_usb_ctrl[0], | ||
214 | .firmware = "dvb-dibusb-5.0.0.11.fw", | ||
215 | .pipe_cmd = 0x01, .pipe_data = 0x02, | ||
216 | .urb_count = 7, .urb_buffer_size = 4096, | ||
217 | DIBUSB_RC_NEC_PROTOCOL, | ||
218 | &dibusb_demod[DIBUSB_DIB3000MB], | ||
219 | &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON], | ||
220 | }, | ||
221 | { DIBUSB1_1_AN2235, &dibusb_usb_ctrl[1], | ||
222 | "dvb-dibusb-an2235-1.fw", | ||
223 | 0x01, 0x02, | ||
224 | 7, 4096, | ||
225 | DIBUSB_RC_NEC_PROTOCOL, | ||
226 | &dibusb_demod[DIBUSB_DIB3000MB], | ||
227 | &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON], | ||
228 | }, | ||
229 | { DIBUSB2_0,&dibusb_usb_ctrl[2], | ||
230 | "dvb-dibusb-6.0.0.5.fw", | ||
231 | 0x01, 0x06, | ||
232 | 7, 4096, | ||
233 | DIBUSB_RC_NEC_PROTOCOL, | ||
234 | &dibusb_demod[DIBUSB_DIB3000MC], | ||
235 | &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5], | ||
236 | }, | ||
237 | { UMT2_0, &dibusb_usb_ctrl[2], | ||
238 | "dvb-dibusb-umt-2.fw", | ||
239 | 0x01, 0x06, | ||
240 | 20, 512, | ||
241 | DIBUSB_RC_NO, | ||
242 | &dibusb_demod[DIBUSB_MT352], | ||
243 | &dibusb_tuner[DIBUSB_TUNER_CABLE_LG_TDTP_E102P], | ||
244 | }, | ||
245 | { DIBUSB2_0B,&dibusb_usb_ctrl[2], | ||
246 | "dvb-dibusb-adstech-usb2-1.fw", | ||
247 | 0x01, 0x06, | ||
248 | 7, 4096, | ||
249 | DIBUSB_RC_NEC_PROTOCOL, | ||
250 | &dibusb_demod[DIBUSB_DIB3000MB], | ||
251 | &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON], | ||
252 | }, | ||
253 | { NOVAT_USB2,&dibusb_usb_ctrl[2], | ||
254 | "dvb-dibusb-nova-t-1.fw", | ||
255 | 0x01, 0x06, | ||
256 | 7, 4096, | ||
257 | DIBUSB_RC_HAUPPAUGE_PROTO, | ||
258 | &dibusb_demod[DIBUSB_DIB3000MC], | ||
259 | &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5], | ||
260 | }, | ||
261 | { DTT200U,&dibusb_usb_ctrl[2], | ||
262 | "dvb-dtt200u-1.fw", | ||
263 | 0x01, 0x02, | ||
264 | 7, 4096, | ||
265 | DIBUSB_RC_NO, | ||
266 | &dibusb_demod[DTT200U_FE], | ||
267 | NULL, /* no explicit tuner/pll-programming necessary (it has the ENV57H1XD5) */ | ||
268 | }, | ||
269 | }; | ||
270 | |||
271 | static struct dibusb_usb_device dibusb_devices[] = { | ||
272 | { "TwinhanDTV USB1.1 / Magic Box / HAMA USB1.1 DVB-T device", | ||
273 | &dibusb_device_classes[DIBUSB1_1], | ||
274 | { &dib_table[19], &dib_table[21], NULL}, | ||
275 | { &dib_table[20], &dib_table[22], NULL}, | ||
276 | }, | ||
277 | { "KWorld V-Stream XPERT DTV - DVB-T USB1.1", | ||
278 | &dibusb_device_classes[DIBUSB1_1], | ||
279 | { &dib_table[11], NULL }, | ||
280 | { &dib_table[12], NULL }, | ||
281 | }, | ||
282 | { "Grandtec USB1.1 DVB-T", | ||
283 | &dibusb_device_classes[DIBUSB1_1], | ||
284 | { &dib_table[13], &dib_table[15], NULL }, | ||
285 | { &dib_table[14], &dib_table[16], NULL }, | ||
286 | }, | ||
287 | { "DiBcom USB1.1 DVB-T reference design (MOD3000)", | ||
288 | &dibusb_device_classes[DIBUSB1_1], | ||
289 | { &dib_table[7], NULL }, | ||
290 | { &dib_table[8], NULL }, | ||
291 | }, | ||
292 | { "Artec T1 USB1.1 TVBOX with AN2135", | ||
293 | &dibusb_device_classes[DIBUSB1_1], | ||
294 | { &dib_table[23], NULL }, | ||
295 | { &dib_table[24], NULL }, | ||
296 | }, | ||
297 | { "Artec T1 USB1.1 TVBOX with AN2235", | ||
298 | &dibusb_device_classes[DIBUSB1_1_AN2235], | ||
299 | { &dib_table[25], NULL }, | ||
300 | { &dib_table[26], NULL }, | ||
301 | }, | ||
302 | { "Avermedia AverTV DVBT USB1.1", | ||
303 | &dibusb_device_classes[DIBUSB1_1], | ||
304 | { &dib_table[0], NULL }, | ||
305 | { &dib_table[1], NULL }, | ||
306 | }, | ||
307 | { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)", | ||
308 | &dibusb_device_classes[DIBUSB1_1], | ||
309 | { &dib_table[4], &dib_table[6], NULL}, | ||
310 | { &dib_table[5], NULL }, | ||
311 | }, | ||
312 | { "Unkown USB1.1 DVB-T device ???? please report the name to the author", | ||
313 | &dibusb_device_classes[DIBUSB1_1], | ||
314 | { &dib_table[17], NULL }, | ||
315 | { &dib_table[18], NULL }, | ||
316 | }, | ||
317 | { "DiBcom USB2.0 DVB-T reference design (MOD3000P)", | ||
318 | &dibusb_device_classes[DIBUSB2_0], | ||
319 | { &dib_table[9], NULL }, | ||
320 | { &dib_table[10], NULL }, | ||
321 | }, | ||
322 | { "Artec T1 USB2.0 TVBOX (please report the warm ID)", | ||
323 | &dibusb_device_classes[DIBUSB2_0], | ||
324 | { &dib_table[27], NULL }, | ||
325 | { NULL }, | ||
326 | }, | ||
327 | { "Hauppauge WinTV NOVA-T USB2", | ||
328 | &dibusb_device_classes[NOVAT_USB2], | ||
329 | { &dib_table[30], NULL }, | ||
330 | { &dib_table[31], NULL }, | ||
331 | }, | ||
332 | { "DTT200U (Yakumo/Hama/Typhoon) DVB-T USB2.0", | ||
333 | &dibusb_device_classes[DTT200U], | ||
334 | { &dib_table[2], NULL }, | ||
335 | { &dib_table[3], NULL }, | ||
336 | }, | ||
337 | { "Hanftek UMT-010 DVB-T USB2.0", | ||
338 | &dibusb_device_classes[UMT2_0], | ||
339 | { &dib_table[28], NULL }, | ||
340 | { &dib_table[29], NULL }, | ||
341 | }, | ||
342 | { "KWorld/ADSTech Instant DVB-T USB 2.0", | ||
343 | &dibusb_device_classes[DIBUSB2_0B], | ||
344 | { &dib_table[32], NULL }, | ||
345 | { &dib_table[33], NULL }, /* device ID with default DIBUSB2_0-firmware */ | ||
346 | }, | ||
347 | #ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES | ||
348 | { "Artec T1 USB1.1 TVBOX with AN2235 (misdesigned)", | ||
349 | &dibusb_device_classes[DIBUSB1_1_AN2235], | ||
350 | { &dib_table[34], NULL }, | ||
351 | { NULL }, | ||
352 | }, | ||
353 | { "Artec T1 USB2.0 TVBOX with FX2 IDs (misdesigned, please report the warm ID)", | ||
354 | &dibusb_device_classes[DTT200U], | ||
355 | { &dib_table[35], NULL }, | ||
356 | { &dib_table[36], NULL }, /* undefined, it could be that the device will get another USB ID in warm state */ | ||
357 | }, | ||
358 | { "DiBcom USB1.1 DVB-T reference design (MOD3000) with AN2135 default IDs", | ||
359 | &dibusb_device_classes[DIBUSB1_1], | ||
360 | { &dib_table[37], NULL }, | ||
361 | { NULL }, | ||
362 | }, | ||
363 | #endif | ||
364 | }; | ||
365 | |||
366 | static int dibusb_exit(struct usb_dibusb *dib) | ||
367 | { | ||
368 | deb_info("init_state before exiting everything: %x\n",dib->init_state); | ||
369 | dibusb_remote_exit(dib); | ||
370 | dibusb_fe_exit(dib); | ||
371 | dibusb_i2c_exit(dib); | ||
372 | dibusb_dvb_exit(dib); | ||
373 | dibusb_urb_exit(dib); | ||
374 | deb_info("init_state should be zero now: %x\n",dib->init_state); | ||
375 | dib->init_state = DIBUSB_STATE_INIT; | ||
376 | kfree(dib); | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static int dibusb_init(struct usb_dibusb *dib) | ||
381 | { | ||
382 | int ret = 0; | ||
383 | sema_init(&dib->usb_sem, 1); | ||
384 | sema_init(&dib->i2c_sem, 1); | ||
385 | |||
386 | dib->init_state = DIBUSB_STATE_INIT; | ||
387 | |||
388 | if ((ret = dibusb_urb_init(dib)) || | ||
389 | (ret = dibusb_dvb_init(dib)) || | ||
390 | (ret = dibusb_i2c_init(dib))) { | ||
391 | dibusb_exit(dib); | ||
392 | return ret; | ||
393 | } | ||
394 | |||
395 | if ((ret = dibusb_fe_init(dib))) | ||
396 | err("could not initialize a frontend."); | ||
397 | |||
398 | if ((ret = dibusb_remote_init(dib))) | ||
399 | err("could not initialize remote control."); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static struct dibusb_usb_device * dibusb_device_class_quirk(struct usb_device *udev, struct dibusb_usb_device *dev) | ||
405 | { | ||
406 | int i; | ||
407 | |||
408 | /* Quirk for the Kworld/ADSTech Instant USB2.0 device. It has the same USB | ||
409 | * IDs like the USB1.1 KWorld after loading the firmware. Which is a bad | ||
410 | * idea and make this quirk necessary. | ||
411 | */ | ||
412 | if (dev->dev_cl->id == DIBUSB1_1 && udev->speed == USB_SPEED_HIGH) { | ||
413 | info("this seems to be the Kworld/ADSTech Instant USB2.0 device or equal."); | ||
414 | for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) { | ||
415 | if (dibusb_devices[i].dev_cl->id == DIBUSB2_0B) { | ||
416 | dev = &dibusb_devices[i]; | ||
417 | break; | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | |||
422 | return dev; | ||
423 | } | ||
424 | |||
425 | static struct dibusb_usb_device * dibusb_find_device (struct usb_device *udev,int *cold) | ||
426 | { | ||
427 | int i,j; | ||
428 | struct dibusb_usb_device *dev = NULL; | ||
429 | *cold = -1; | ||
430 | |||
431 | for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) { | ||
432 | for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].cold_ids[j] != NULL; j++) { | ||
433 | deb_info("check for cold %x %x\n",dibusb_devices[i].cold_ids[j]->idVendor, dibusb_devices[i].cold_ids[j]->idProduct); | ||
434 | if (dibusb_devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) && | ||
435 | dibusb_devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) { | ||
436 | *cold = 1; | ||
437 | dev = &dibusb_devices[i]; | ||
438 | break; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | if (dev != NULL) | ||
443 | break; | ||
444 | |||
445 | for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].warm_ids[j] != NULL; j++) { | ||
446 | deb_info("check for warm %x %x\n",dibusb_devices[i].warm_ids[j]->idVendor, dibusb_devices[i].warm_ids[j]->idProduct); | ||
447 | if (dibusb_devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) && | ||
448 | dibusb_devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) { | ||
449 | *cold = 0; | ||
450 | dev = &dibusb_devices[i]; | ||
451 | break; | ||
452 | } | ||
453 | } | ||
454 | } | ||
455 | |||
456 | if (dev != NULL) | ||
457 | dev = dibusb_device_class_quirk(udev,dev); | ||
458 | |||
459 | return dev; | ||
460 | } | ||
461 | |||
462 | /* | ||
463 | * USB | ||
464 | */ | ||
465 | static int dibusb_probe(struct usb_interface *intf, | ||
466 | const struct usb_device_id *id) | ||
467 | { | ||
468 | struct usb_device *udev = interface_to_usbdev(intf); | ||
469 | struct usb_dibusb *dib = NULL; | ||
470 | struct dibusb_usb_device *dibdev = NULL; | ||
471 | |||
472 | int ret = -ENOMEM,cold=0; | ||
473 | |||
474 | if ((dibdev = dibusb_find_device(udev,&cold)) == NULL) { | ||
475 | err("something went very wrong, " | ||
476 | "unknown product ID: %.4x",le16_to_cpu(udev->descriptor.idProduct)); | ||
477 | return -ENODEV; | ||
478 | } | ||
479 | |||
480 | if (cold == 1) { | ||
481 | info("found a '%s' in cold state, will try to load a firmware",dibdev->name); | ||
482 | ret = dibusb_loadfirmware(udev,dibdev); | ||
483 | } else { | ||
484 | info("found a '%s' in warm state.",dibdev->name); | ||
485 | dib = kmalloc(sizeof(struct usb_dibusb),GFP_KERNEL); | ||
486 | if (dib == NULL) { | ||
487 | err("no memory"); | ||
488 | return ret; | ||
489 | } | ||
490 | memset(dib,0,sizeof(struct usb_dibusb)); | ||
491 | |||
492 | dib->udev = udev; | ||
493 | dib->dibdev = dibdev; | ||
494 | |||
495 | /* store parameters to structures */ | ||
496 | dib->rc_query_interval = rc_query_interval; | ||
497 | dib->pid_parse = pid_parse; | ||
498 | dib->rc_key_repeat_count = rc_key_repeat_count; | ||
499 | |||
500 | usb_set_intfdata(intf, dib); | ||
501 | |||
502 | ret = dibusb_init(dib); | ||
503 | } | ||
504 | |||
505 | if (ret == 0) | ||
506 | info("%s successfully initialized and connected.",dibdev->name); | ||
507 | else | ||
508 | info("%s error while loading driver (%d)",dibdev->name,ret); | ||
509 | return ret; | ||
510 | } | ||
511 | |||
512 | static void dibusb_disconnect(struct usb_interface *intf) | ||
513 | { | ||
514 | struct usb_dibusb *dib = usb_get_intfdata(intf); | ||
515 | const char *name = DRIVER_DESC; | ||
516 | |||
517 | usb_set_intfdata(intf,NULL); | ||
518 | if (dib != NULL && dib->dibdev != NULL) { | ||
519 | name = dib->dibdev->name; | ||
520 | dibusb_exit(dib); | ||
521 | } | ||
522 | info("%s successfully deinitialized and disconnected.",name); | ||
523 | |||
524 | } | ||
525 | |||
526 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
527 | static struct usb_driver dibusb_driver = { | ||
528 | .owner = THIS_MODULE, | ||
529 | .name = DRIVER_DESC, | ||
530 | .probe = dibusb_probe, | ||
531 | .disconnect = dibusb_disconnect, | ||
532 | .id_table = dib_table, | ||
533 | }; | ||
534 | |||
535 | /* module stuff */ | ||
536 | static int __init usb_dibusb_init(void) | ||
537 | { | ||
538 | int result; | ||
539 | if ((result = usb_register(&dibusb_driver))) { | ||
540 | err("usb_register failed. Error number %d",result); | ||
541 | return result; | ||
542 | } | ||
543 | |||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static void __exit usb_dibusb_exit(void) | ||
548 | { | ||
549 | /* deregister this driver from the USB subsystem */ | ||
550 | usb_deregister(&dibusb_driver); | ||
551 | } | ||
552 | |||
553 | module_init (usb_dibusb_init); | ||
554 | module_exit (usb_dibusb_exit); | ||
555 | |||
556 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
557 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
558 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c b/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c deleted file mode 100644 index 400b439e80..0000000000 --- a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c +++ /dev/null | |||
@@ -1,185 +0,0 @@ | |||
1 | /* | ||
2 | * dvb-dibusb-dvb.c is part of the driver for mobile USB Budget DVB-T devices | ||
3 | * based on reference design made by DiBcom (http://www.dibcom.fr/) | ||
4 | * | ||
5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
6 | * | ||
7 | * see dvb-dibusb-core.c for more copyright details. | ||
8 | * | ||
9 | * This file contains functions for initializing and handling the | ||
10 | * linux-dvb API. | ||
11 | */ | ||
12 | #include "dvb-dibusb.h" | ||
13 | |||
14 | #include <linux/usb.h> | ||
15 | #include <linux/version.h> | ||
16 | |||
17 | static u32 urb_compl_count; | ||
18 | |||
19 | /* | ||
20 | * MPEG2 TS DVB stuff | ||
21 | */ | ||
22 | void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs) | ||
23 | { | ||
24 | struct usb_dibusb *dib = urb->context; | ||
25 | |||
26 | deb_ts("urb complete feedcount: %d, status: %d, length: %d\n",dib->feedcount,urb->status, | ||
27 | urb->actual_length); | ||
28 | |||
29 | urb_compl_count++; | ||
30 | if (urb_compl_count % 1000 == 0) | ||
31 | deb_info("%d urbs completed so far.\n",urb_compl_count); | ||
32 | |||
33 | switch (urb->status) { | ||
34 | case 0: /* success */ | ||
35 | case -ETIMEDOUT: /* NAK */ | ||
36 | break; | ||
37 | case -ECONNRESET: /* kill */ | ||
38 | case -ENOENT: | ||
39 | case -ESHUTDOWN: | ||
40 | return; | ||
41 | default: /* error */ | ||
42 | deb_ts("urb completition error %d.", urb->status); | ||
43 | break; | ||
44 | } | ||
45 | |||
46 | if (dib->feedcount > 0 && urb->actual_length > 0) { | ||
47 | if (dib->init_state & DIBUSB_STATE_DVB) | ||
48 | dvb_dmx_swfilter(&dib->demux, (u8*) urb->transfer_buffer,urb->actual_length); | ||
49 | } else | ||
50 | deb_ts("URB dropped because of feedcount.\n"); | ||
51 | |||
52 | usb_submit_urb(urb,GFP_ATOMIC); | ||
53 | } | ||
54 | |||
55 | static int dibusb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) | ||
56 | { | ||
57 | struct usb_dibusb *dib = dvbdmxfeed->demux->priv; | ||
58 | int newfeedcount; | ||
59 | |||
60 | if (dib == NULL) | ||
61 | return -ENODEV; | ||
62 | |||
63 | newfeedcount = dib->feedcount + (onoff ? 1 : -1); | ||
64 | |||
65 | /* | ||
66 | * stop feed before setting a new pid if there will be no pid anymore | ||
67 | */ | ||
68 | if (newfeedcount == 0) { | ||
69 | deb_ts("stop feeding\n"); | ||
70 | if (dib->xfer_ops.fifo_ctrl != NULL) { | ||
71 | if (dib->xfer_ops.fifo_ctrl(dib->fe,0)) { | ||
72 | err("error while inhibiting fifo."); | ||
73 | return -ENODEV; | ||
74 | } | ||
75 | } | ||
76 | dibusb_streaming(dib,0); | ||
77 | } | ||
78 | |||
79 | dib->feedcount = newfeedcount; | ||
80 | |||
81 | /* activate the pid on the device specific pid_filter */ | ||
82 | deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off"); | ||
83 | if (dib->pid_parse && dib->xfer_ops.pid_ctrl != NULL) | ||
84 | dib->xfer_ops.pid_ctrl(dib->fe,dvbdmxfeed->index,dvbdmxfeed->pid,onoff); | ||
85 | |||
86 | /* | ||
87 | * start the feed if this was the first pid to set and there is still a pid | ||
88 | * for reception. | ||
89 | */ | ||
90 | if (dib->feedcount == onoff && dib->feedcount > 0) { | ||
91 | |||
92 | deb_ts("controlling pid parser\n"); | ||
93 | if (dib->xfer_ops.pid_parse != NULL) { | ||
94 | if (dib->xfer_ops.pid_parse(dib->fe,dib->pid_parse) < 0) { | ||
95 | err("could not handle pid_parser"); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | deb_ts("start feeding\n"); | ||
100 | if (dib->xfer_ops.fifo_ctrl != NULL) { | ||
101 | if (dib->xfer_ops.fifo_ctrl(dib->fe,1)) { | ||
102 | err("error while enabling fifo."); | ||
103 | return -ENODEV; | ||
104 | } | ||
105 | } | ||
106 | dibusb_streaming(dib,1); | ||
107 | } | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static int dibusb_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
112 | { | ||
113 | deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type); | ||
114 | return dibusb_ctrl_feed(dvbdmxfeed,1); | ||
115 | } | ||
116 | |||
117 | static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
118 | { | ||
119 | deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type); | ||
120 | return dibusb_ctrl_feed(dvbdmxfeed,0); | ||
121 | } | ||
122 | |||
123 | int dibusb_dvb_init(struct usb_dibusb *dib) | ||
124 | { | ||
125 | int ret; | ||
126 | |||
127 | urb_compl_count = 0; | ||
128 | |||
129 | if ((ret = dvb_register_adapter(&dib->adapter, DRIVER_DESC, | ||
130 | THIS_MODULE)) < 0) { | ||
131 | deb_info("dvb_register_adapter failed: error %d", ret); | ||
132 | goto err; | ||
133 | } | ||
134 | dib->adapter.priv = dib; | ||
135 | |||
136 | /* i2c is done in dibusb_i2c_init */ | ||
137 | |||
138 | dib->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | ||
139 | |||
140 | dib->demux.priv = (void *)dib; | ||
141 | /* get pidcount from demod */ | ||
142 | dib->demux.feednum = dib->demux.filternum = 255; | ||
143 | dib->demux.start_feed = dibusb_start_feed; | ||
144 | dib->demux.stop_feed = dibusb_stop_feed; | ||
145 | dib->demux.write_to_decoder = NULL; | ||
146 | if ((ret = dvb_dmx_init(&dib->demux)) < 0) { | ||
147 | err("dvb_dmx_init failed: error %d",ret); | ||
148 | goto err_dmx; | ||
149 | } | ||
150 | |||
151 | dib->dmxdev.filternum = dib->demux.filternum; | ||
152 | dib->dmxdev.demux = &dib->demux.dmx; | ||
153 | dib->dmxdev.capabilities = 0; | ||
154 | if ((ret = dvb_dmxdev_init(&dib->dmxdev, &dib->adapter)) < 0) { | ||
155 | err("dvb_dmxdev_init failed: error %d",ret); | ||
156 | goto err_dmx_dev; | ||
157 | } | ||
158 | |||
159 | dvb_net_init(&dib->adapter, &dib->dvb_net, &dib->demux.dmx); | ||
160 | |||
161 | goto success; | ||
162 | err_dmx_dev: | ||
163 | dvb_dmx_release(&dib->demux); | ||
164 | err_dmx: | ||
165 | dvb_unregister_adapter(&dib->adapter); | ||
166 | err: | ||
167 | return ret; | ||
168 | success: | ||
169 | dib->init_state |= DIBUSB_STATE_DVB; | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | int dibusb_dvb_exit(struct usb_dibusb *dib) | ||
174 | { | ||
175 | if (dib->init_state & DIBUSB_STATE_DVB) { | ||
176 | dib->init_state &= ~DIBUSB_STATE_DVB; | ||
177 | deb_info("unregistering DVB part\n"); | ||
178 | dvb_net_release(&dib->dvb_net); | ||
179 | dib->demux.dmx.close(&dib->demux.dmx); | ||
180 | dvb_dmxdev_release(&dib->dmxdev); | ||
181 | dvb_dmx_release(&dib->demux); | ||
182 | dvb_unregister_adapter(&dib->adapter); | ||
183 | } | ||
184 | return 0; | ||
185 | } | ||
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c b/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c deleted file mode 100644 index 5a71b88797..0000000000 --- a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c +++ /dev/null | |||
@@ -1,582 +0,0 @@ | |||
1 | /* | ||
2 | * dvb-dibusb-fe-i2c.c is part of the driver for mobile USB Budget DVB-T devices | ||
3 | * based on reference design made by DiBcom (http://www.dibcom.fr/) | ||
4 | * | ||
5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
6 | * | ||
7 | * see dvb-dibusb-core.c for more copyright details. | ||
8 | * | ||
9 | * This file contains functions for attaching, initializing of an appropriate | ||
10 | * demodulator/frontend. I2C-stuff is also located here. | ||
11 | * | ||
12 | */ | ||
13 | #include "dvb-dibusb.h" | ||
14 | |||
15 | #include <linux/usb.h> | ||
16 | |||
17 | static int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr, | ||
18 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
19 | { | ||
20 | u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */ | ||
21 | /* write only ? */ | ||
22 | int wo = (rbuf == NULL || rlen == 0), | ||
23 | len = 2 + wlen + (wo ? 0 : 2); | ||
24 | |||
25 | sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ; | ||
26 | sndbuf[1] = (addr << 1) | (wo ? 0 : 1); | ||
27 | |||
28 | memcpy(&sndbuf[2],wbuf,wlen); | ||
29 | |||
30 | if (!wo) { | ||
31 | sndbuf[wlen+2] = (rlen >> 8) & 0xff; | ||
32 | sndbuf[wlen+3] = rlen & 0xff; | ||
33 | } | ||
34 | |||
35 | return dibusb_readwrite_usb(dib,sndbuf,len,rbuf,rlen); | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | * I2C master xfer function | ||
40 | */ | ||
41 | static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num) | ||
42 | { | ||
43 | struct usb_dibusb *dib = i2c_get_adapdata(adap); | ||
44 | int i; | ||
45 | |||
46 | if (down_interruptible(&dib->i2c_sem) < 0) | ||
47 | return -EAGAIN; | ||
48 | |||
49 | if (num > 2) | ||
50 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
51 | |||
52 | for (i = 0; i < num; i++) { | ||
53 | /* write/read request */ | ||
54 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
55 | if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len, | ||
56 | msg[i+1].buf,msg[i+1].len) < 0) | ||
57 | break; | ||
58 | i++; | ||
59 | } else | ||
60 | if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0) | ||
61 | break; | ||
62 | } | ||
63 | |||
64 | up(&dib->i2c_sem); | ||
65 | return i; | ||
66 | } | ||
67 | |||
68 | static u32 dibusb_i2c_func(struct i2c_adapter *adapter) | ||
69 | { | ||
70 | return I2C_FUNC_I2C; | ||
71 | } | ||
72 | |||
73 | static struct i2c_algorithm dibusb_algo = { | ||
74 | .name = "DiBcom USB i2c algorithm", | ||
75 | .id = I2C_ALGO_BIT, | ||
76 | .master_xfer = dibusb_i2c_xfer, | ||
77 | .functionality = dibusb_i2c_func, | ||
78 | }; | ||
79 | |||
80 | static int dibusb_general_demod_init(struct dvb_frontend *fe); | ||
81 | static u8 dibusb_general_pll_addr(struct dvb_frontend *fe); | ||
82 | static int dibusb_general_pll_init(struct dvb_frontend *fe, u8 pll_buf[5]); | ||
83 | static int dibusb_general_pll_set(struct dvb_frontend *fe, | ||
84 | struct dvb_frontend_parameters* params, u8 pll_buf[5]); | ||
85 | |||
86 | static struct mt352_config mt352_hanftek_umt_010_config = { | ||
87 | .demod_address = 0x1e, | ||
88 | .demod_init = dibusb_general_demod_init, | ||
89 | .pll_set = dibusb_general_pll_set, | ||
90 | }; | ||
91 | |||
92 | static int dibusb_tuner_quirk(struct usb_dibusb *dib) | ||
93 | { | ||
94 | switch (dib->dibdev->dev_cl->id) { | ||
95 | case DIBUSB1_1: /* some these device have the ENV77H11D5 and some the THOMSON CABLE */ | ||
96 | case DIBUSB1_1_AN2235: { /* actually its this device, but in warm state they are indistinguishable */ | ||
97 | struct dibusb_tuner *t; | ||
98 | u8 b[2] = { 0,0 } ,b2[1]; | ||
99 | struct i2c_msg msg[2] = { | ||
100 | { .flags = 0, .buf = b, .len = 2 }, | ||
101 | { .flags = I2C_M_RD, .buf = b2, .len = 1}, | ||
102 | }; | ||
103 | |||
104 | t = &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5]; | ||
105 | |||
106 | msg[0].addr = msg[1].addr = t->pll_addr; | ||
107 | |||
108 | if (dib->xfer_ops.tuner_pass_ctrl != NULL) | ||
109 | dib->xfer_ops.tuner_pass_ctrl(dib->fe,1,t->pll_addr); | ||
110 | dibusb_i2c_xfer(&dib->i2c_adap,msg,2); | ||
111 | if (dib->xfer_ops.tuner_pass_ctrl != NULL) | ||
112 | dib->xfer_ops.tuner_pass_ctrl(dib->fe,0,t->pll_addr); | ||
113 | |||
114 | if (b2[0] == 0xfe) | ||
115 | info("this device has the Thomson Cable onboard. Which is default."); | ||
116 | else { | ||
117 | dib->tuner = t; | ||
118 | info("this device has the Panasonic ENV77H11D5 onboard."); | ||
119 | } | ||
120 | break; | ||
121 | } | ||
122 | default: | ||
123 | break; | ||
124 | } | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | int dibusb_fe_init(struct usb_dibusb* dib) | ||
129 | { | ||
130 | struct dib3000_config demod_cfg; | ||
131 | int i; | ||
132 | |||
133 | if (dib->init_state & DIBUSB_STATE_I2C) { | ||
134 | for (i = 0; i < sizeof(dib->dibdev->dev_cl->demod->i2c_addrs) / sizeof(unsigned char) && | ||
135 | dib->dibdev->dev_cl->demod->i2c_addrs[i] != 0; i++) { | ||
136 | |||
137 | demod_cfg.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i]; | ||
138 | demod_cfg.pll_addr = dibusb_general_pll_addr; | ||
139 | demod_cfg.pll_set = dibusb_general_pll_set; | ||
140 | demod_cfg.pll_init = dibusb_general_pll_init; | ||
141 | |||
142 | deb_info("demod id: %d %d\n",dib->dibdev->dev_cl->demod->id,DTT200U_FE); | ||
143 | |||
144 | switch (dib->dibdev->dev_cl->demod->id) { | ||
145 | case DIBUSB_DIB3000MB: | ||
146 | dib->fe = dib3000mb_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops); | ||
147 | break; | ||
148 | case DIBUSB_DIB3000MC: | ||
149 | dib->fe = dib3000mc_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops); | ||
150 | break; | ||
151 | case DIBUSB_MT352: | ||
152 | mt352_hanftek_umt_010_config.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i]; | ||
153 | dib->fe = mt352_attach(&mt352_hanftek_umt_010_config, &dib->i2c_adap); | ||
154 | break; | ||
155 | case DTT200U_FE: | ||
156 | dib->fe = dtt200u_fe_attach(dib,&dib->xfer_ops); | ||
157 | break; | ||
158 | } | ||
159 | if (dib->fe != NULL) { | ||
160 | info("found demodulator at i2c address 0x%x",dib->dibdev->dev_cl->demod->i2c_addrs[i]); | ||
161 | break; | ||
162 | } | ||
163 | } | ||
164 | /* if a frontend was found */ | ||
165 | if (dib->fe != NULL) { | ||
166 | if (dib->fe->ops->sleep != NULL) | ||
167 | dib->fe_sleep = dib->fe->ops->sleep; | ||
168 | dib->fe->ops->sleep = dibusb_hw_sleep; | ||
169 | |||
170 | if (dib->fe->ops->init != NULL ) | ||
171 | dib->fe_init = dib->fe->ops->init; | ||
172 | dib->fe->ops->init = dibusb_hw_wakeup; | ||
173 | |||
174 | /* setting the default tuner */ | ||
175 | dib->tuner = dib->dibdev->dev_cl->tuner; | ||
176 | |||
177 | /* check which tuner is mounted on this device, in case this is unsure */ | ||
178 | dibusb_tuner_quirk(dib); | ||
179 | } | ||
180 | } | ||
181 | if (dib->fe == NULL) { | ||
182 | err("A frontend driver was not found for device '%s'.", | ||
183 | dib->dibdev->name); | ||
184 | return -ENODEV; | ||
185 | } else { | ||
186 | if (dvb_register_frontend(&dib->adapter, dib->fe)) { | ||
187 | err("Frontend registration failed."); | ||
188 | if (dib->fe->ops->release) | ||
189 | dib->fe->ops->release(dib->fe); | ||
190 | dib->fe = NULL; | ||
191 | return -ENODEV; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | int dibusb_fe_exit(struct usb_dibusb *dib) | ||
199 | { | ||
200 | if (dib->fe != NULL) | ||
201 | dvb_unregister_frontend(dib->fe); | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | int dibusb_i2c_init(struct usb_dibusb *dib) | ||
206 | { | ||
207 | int ret = 0; | ||
208 | |||
209 | dib->adapter.priv = dib; | ||
210 | |||
211 | strncpy(dib->i2c_adap.name,dib->dibdev->name,I2C_NAME_SIZE); | ||
212 | #ifdef I2C_ADAP_CLASS_TV_DIGITAL | ||
213 | dib->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL, | ||
214 | #else | ||
215 | dib->i2c_adap.class = I2C_CLASS_TV_DIGITAL, | ||
216 | #endif | ||
217 | dib->i2c_adap.algo = &dibusb_algo; | ||
218 | dib->i2c_adap.algo_data = NULL; | ||
219 | dib->i2c_adap.id = I2C_ALGO_BIT; | ||
220 | |||
221 | i2c_set_adapdata(&dib->i2c_adap, dib); | ||
222 | |||
223 | if ((ret = i2c_add_adapter(&dib->i2c_adap)) < 0) | ||
224 | err("could not add i2c adapter"); | ||
225 | |||
226 | dib->init_state |= DIBUSB_STATE_I2C; | ||
227 | |||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | int dibusb_i2c_exit(struct usb_dibusb *dib) | ||
232 | { | ||
233 | if (dib->init_state & DIBUSB_STATE_I2C) | ||
234 | i2c_del_adapter(&dib->i2c_adap); | ||
235 | dib->init_state &= ~DIBUSB_STATE_I2C; | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | |||
240 | /* pll stuff, maybe removed soon (thx to Gerd/Andrew in advance) */ | ||
241 | static int thomson_cable_eu_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4]) | ||
242 | { | ||
243 | u32 tfreq = (fep->frequency + 36125000) / 62500; | ||
244 | int vu,p0,p1,p2; | ||
245 | |||
246 | if (fep->frequency > 403250000) | ||
247 | vu = 1, p2 = 1, p1 = 0, p0 = 1; | ||
248 | else if (fep->frequency > 115750000) | ||
249 | vu = 0, p2 = 1, p1 = 1, p0 = 0; | ||
250 | else if (fep->frequency > 44250000) | ||
251 | vu = 0, p2 = 0, p1 = 1, p0 = 1; | ||
252 | else | ||
253 | return -EINVAL; | ||
254 | |||
255 | pllbuf[0] = (tfreq >> 8) & 0x7f; | ||
256 | pllbuf[1] = tfreq & 0xff; | ||
257 | pllbuf[2] = 0x8e; | ||
258 | pllbuf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0; | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4]) | ||
263 | { | ||
264 | u32 freq_khz = fep->frequency / 1000; | ||
265 | u32 tfreq = ((freq_khz + 36125)*6 + 500) / 1000; | ||
266 | u8 TA, T210, R210, ctrl1, cp210, p4321; | ||
267 | if (freq_khz > 858000) { | ||
268 | err("frequency cannot be larger than 858 MHz."); | ||
269 | return -EINVAL; | ||
270 | } | ||
271 | |||
272 | // contol data 1 : 1 | T/A=1 | T2,T1,T0 = 0,0,0 | R2,R1,R0 = 0,1,0 | ||
273 | TA = 1; | ||
274 | T210 = 0; | ||
275 | R210 = 0x2; | ||
276 | ctrl1 = (1 << 7) | (TA << 6) | (T210 << 3) | R210; | ||
277 | |||
278 | // ******** CHARGE PUMP CONFIG vs RF FREQUENCIES ***************** | ||
279 | if (freq_khz < 470000) | ||
280 | cp210 = 2; // VHF Low and High band ch E12 to E4 to E12 | ||
281 | else if (freq_khz < 526000) | ||
282 | cp210 = 4; // UHF band Ch E21 to E27 | ||
283 | else // if (freq < 862000000) | ||
284 | cp210 = 5; // UHF band ch E28 to E69 | ||
285 | |||
286 | //********************* BW select ******************************* | ||
287 | if (freq_khz < 153000) | ||
288 | p4321 = 1; // BW selected for VHF low | ||
289 | else if (freq_khz < 470000) | ||
290 | p4321 = 2; // BW selected for VHF high E5 to E12 | ||
291 | else // if (freq < 862000000) | ||
292 | p4321 = 4; // BW selection for UHF E21 to E69 | ||
293 | |||
294 | pllbuf[0] = (tfreq >> 8) & 0xff; | ||
295 | pllbuf[1] = (tfreq >> 0) & 0xff; | ||
296 | pllbuf[2] = 0xff & ctrl1; | ||
297 | pllbuf[3] = (cp210 << 5) | (p4321); | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * 7 6 5 4 3 2 1 0 | ||
304 | * Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0 | ||
305 | * | ||
306 | * Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8 | ||
307 | * Program divider byte 2 n7 n6 n5 n4 n3 n2 n1 n0 | ||
308 | * | ||
309 | * Control byte 1 1 T/A=1 T2 T1 T0 R2 R1 R0 | ||
310 | * 1 T/A=0 0 0 ATC AL2 AL1 AL0 | ||
311 | * | ||
312 | * Control byte 2 CP2 CP1 CP0 BS5 BS4 BS3 BS2 BS1 | ||
313 | * | ||
314 | * MA0/1 = programmable address bits | ||
315 | * R/~W = read/write bit (0 for writing) | ||
316 | * N14-0 = programmable LO frequency | ||
317 | * | ||
318 | * T/A = test AGC bit (0 = next 6 bits AGC setting, | ||
319 | * 1 = next 6 bits test and reference divider ratio settings) | ||
320 | * T2-0 = test bits | ||
321 | * R2-0 = reference divider ratio and programmable frequency step | ||
322 | * ATC = AGC current setting and time constant | ||
323 | * ATC = 0: AGC current = 220nA, AGC time constant = 2s | ||
324 | * ATC = 1: AGC current = 9uA, AGC time constant = 50ms | ||
325 | * AL2-0 = AGC take-over point bits | ||
326 | * CP2-0 = charge pump current | ||
327 | * BS5-1 = PMOS ports control bits; | ||
328 | * BSn = 0 corresponding port is off, high-impedance state (at power-on) | ||
329 | * BSn = 1 corresponding port is on | ||
330 | */ | ||
331 | static int panasonic_cofdm_env77h11d5_tda6650_init(struct dvb_frontend *fe, u8 pllbuf[4]) | ||
332 | { | ||
333 | pllbuf[0] = 0x0b; | ||
334 | pllbuf[1] = 0xf5; | ||
335 | pllbuf[2] = 0x85; | ||
336 | pllbuf[3] = 0xab; | ||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend_parameters *fep,u8 pllbuf[4]) | ||
341 | { | ||
342 | int tuner_frequency = 0; | ||
343 | u8 band, cp, filter; | ||
344 | |||
345 | // determine charge pump | ||
346 | tuner_frequency = fep->frequency + 36166000; | ||
347 | if (tuner_frequency < 87000000) | ||
348 | return -EINVAL; | ||
349 | else if (tuner_frequency < 130000000) | ||
350 | cp = 3; | ||
351 | else if (tuner_frequency < 160000000) | ||
352 | cp = 5; | ||
353 | else if (tuner_frequency < 200000000) | ||
354 | cp = 6; | ||
355 | else if (tuner_frequency < 290000000) | ||
356 | cp = 3; | ||
357 | else if (tuner_frequency < 420000000) | ||
358 | cp = 5; | ||
359 | else if (tuner_frequency < 480000000) | ||
360 | cp = 6; | ||
361 | else if (tuner_frequency < 620000000) | ||
362 | cp = 3; | ||
363 | else if (tuner_frequency < 830000000) | ||
364 | cp = 5; | ||
365 | else if (tuner_frequency < 895000000) | ||
366 | cp = 7; | ||
367 | else | ||
368 | return -EINVAL; | ||
369 | |||
370 | // determine band | ||
371 | if (fep->frequency < 49000000) | ||
372 | return -EINVAL; | ||
373 | else if (fep->frequency < 161000000) | ||
374 | band = 1; | ||
375 | else if (fep->frequency < 444000000) | ||
376 | band = 2; | ||
377 | else if (fep->frequency < 861000000) | ||
378 | band = 4; | ||
379 | else | ||
380 | return -EINVAL; | ||
381 | |||
382 | // setup PLL filter | ||
383 | switch (fep->u.ofdm.bandwidth) { | ||
384 | case BANDWIDTH_6_MHZ: | ||
385 | case BANDWIDTH_7_MHZ: | ||
386 | filter = 0; | ||
387 | break; | ||
388 | case BANDWIDTH_8_MHZ: | ||
389 | filter = 1; | ||
390 | break; | ||
391 | default: | ||
392 | return -EINVAL; | ||
393 | } | ||
394 | |||
395 | // calculate divisor | ||
396 | // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6) | ||
397 | tuner_frequency = (((fep->frequency / 1000) * 6) + 217496) / 1000; | ||
398 | |||
399 | // setup tuner buffer | ||
400 | pllbuf[0] = (tuner_frequency >> 8) & 0x7f; | ||
401 | pllbuf[1] = tuner_frequency & 0xff; | ||
402 | pllbuf[2] = 0xca; | ||
403 | pllbuf[3] = (cp << 5) | (filter << 3) | band; | ||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | /* | ||
408 | * 7 6 5 4 3 2 1 0 | ||
409 | * Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0 | ||
410 | * | ||
411 | * Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8 | ||
412 | * Program divider byte 2 n7 n6 n5 n4 n3 n2 n1 n0 | ||
413 | * | ||
414 | * Control byte 1 CP T2 T1 T0 RSA RSB OS | ||
415 | * | ||
416 | * Band Switch byte X X X P4 P3 P2 P1 P0 | ||
417 | * | ||
418 | * Auxiliary byte ATC AL2 AL1 AL0 0 0 0 0 | ||
419 | * | ||
420 | * Address: MA1 MA0 Address | ||
421 | * 0 0 c0 | ||
422 | * 0 1 c2 (always valid) | ||
423 | * 1 0 c4 | ||
424 | * 1 1 c6 | ||
425 | */ | ||
426 | static int lg_tdtp_e102p_tua6034(struct dvb_frontend_parameters* fep, u8 pllbuf[4]) | ||
427 | { | ||
428 | u32 div; | ||
429 | u8 p210, p3; | ||
430 | |||
431 | #define TUNER_MUL 62500 | ||
432 | |||
433 | div = (fep->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL; | ||
434 | // div = ((fep->frequency/1000 + 36166) * 6) / 1000; | ||
435 | |||
436 | if (fep->frequency < 174500000) | ||
437 | p210 = 1; // not supported by the tdtp_e102p | ||
438 | else if (fep->frequency < 230000000) // VHF | ||
439 | p210 = 2; | ||
440 | else | ||
441 | p210 = 4; | ||
442 | |||
443 | if (fep->u.ofdm.bandwidth == BANDWIDTH_7_MHZ) | ||
444 | p3 = 0; | ||
445 | else | ||
446 | p3 = 1; | ||
447 | |||
448 | pllbuf[0] = (div >> 8) & 0x7f; | ||
449 | pllbuf[1] = div & 0xff; | ||
450 | pllbuf[2] = 0xce; | ||
451 | // pllbuf[2] = 0xcc; | ||
452 | pllbuf[3] = (p3 << 3) | p210; | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static int lg_tdtp_e102p_mt352_demod_init(struct dvb_frontend *fe) | ||
458 | { | ||
459 | static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d }; | ||
460 | static u8 mt352_reset[] = { 0x50, 0x80 }; | ||
461 | static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 }; | ||
462 | static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 }; | ||
463 | static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 }; | ||
464 | |||
465 | static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff }; | ||
466 | static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff }; | ||
467 | static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 }; | ||
468 | static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 }; | ||
469 | static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f }; | ||
470 | |||
471 | static u8 mt352_acq_ctl[] = { 0x53, 0x50 }; | ||
472 | static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 }; | ||
473 | |||
474 | mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); | ||
475 | udelay(2000); | ||
476 | mt352_write(fe, mt352_reset, sizeof(mt352_reset)); | ||
477 | mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio)); | ||
478 | |||
479 | mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); | ||
480 | mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); | ||
481 | |||
482 | mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1)); | ||
483 | mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2)); | ||
484 | mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3)); | ||
485 | mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4)); | ||
486 | mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5)); | ||
487 | |||
488 | mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl)); | ||
489 | mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1)); | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static int dibusb_general_demod_init(struct dvb_frontend *fe) | ||
495 | { | ||
496 | struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; | ||
497 | switch (dib->dibdev->dev_cl->id) { | ||
498 | case UMT2_0: | ||
499 | return lg_tdtp_e102p_mt352_demod_init(fe); | ||
500 | default: /* other device classes do not have device specific demod inits */ | ||
501 | break; | ||
502 | } | ||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | static u8 dibusb_general_pll_addr(struct dvb_frontend *fe) | ||
507 | { | ||
508 | struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; | ||
509 | return dib->tuner->pll_addr; | ||
510 | } | ||
511 | |||
512 | static int dibusb_pll_i2c_helper(struct usb_dibusb *dib, u8 pll_buf[5], u8 buf[4]) | ||
513 | { | ||
514 | if (pll_buf == NULL) { | ||
515 | struct i2c_msg msg = { | ||
516 | .addr = dib->tuner->pll_addr, | ||
517 | .flags = 0, | ||
518 | .buf = buf, | ||
519 | .len = sizeof(buf) | ||
520 | }; | ||
521 | if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1) | ||
522 | return -EIO; | ||
523 | msleep(1); | ||
524 | } else { | ||
525 | pll_buf[0] = dib->tuner->pll_addr << 1; | ||
526 | memcpy(&pll_buf[1],buf,4); | ||
527 | } | ||
528 | |||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | static int dibusb_general_pll_init(struct dvb_frontend *fe, | ||
533 | u8 pll_buf[5]) | ||
534 | { | ||
535 | struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; | ||
536 | u8 buf[4]; | ||
537 | int ret=0; | ||
538 | switch (dib->tuner->id) { | ||
539 | case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5: | ||
540 | ret = panasonic_cofdm_env77h11d5_tda6650_init(fe,buf); | ||
541 | break; | ||
542 | default: | ||
543 | break; | ||
544 | } | ||
545 | |||
546 | if (ret) | ||
547 | return ret; | ||
548 | |||
549 | return dibusb_pll_i2c_helper(dib,pll_buf,buf); | ||
550 | } | ||
551 | |||
552 | static int dibusb_general_pll_set(struct dvb_frontend *fe, | ||
553 | struct dvb_frontend_parameters *fep, u8 pll_buf[5]) | ||
554 | { | ||
555 | struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; | ||
556 | u8 buf[4]; | ||
557 | int ret=0; | ||
558 | |||
559 | switch (dib->tuner->id) { | ||
560 | case DIBUSB_TUNER_CABLE_THOMSON: | ||
561 | ret = thomson_cable_eu_pll_set(fep, buf); | ||
562 | break; | ||
563 | case DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5: | ||
564 | ret = panasonic_cofdm_env57h1xd5_pll_set(fep, buf); | ||
565 | break; | ||
566 | case DIBUSB_TUNER_CABLE_LG_TDTP_E102P: | ||
567 | ret = lg_tdtp_e102p_tua6034(fep, buf); | ||
568 | break; | ||
569 | case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5: | ||
570 | ret = panasonic_cofdm_env77h11d5_tda6650_set(fep,buf); | ||
571 | break; | ||
572 | default: | ||
573 | warn("no pll programming routine found for tuner %d.\n",dib->tuner->id); | ||
574 | ret = -ENODEV; | ||
575 | break; | ||
576 | } | ||
577 | |||
578 | if (ret) | ||
579 | return ret; | ||
580 | |||
581 | return dibusb_pll_i2c_helper(dib,pll_buf,buf); | ||
582 | } | ||
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c b/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c deleted file mode 100644 index 504ba47afd..0000000000 --- a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c +++ /dev/null | |||
@@ -1,87 +0,0 @@ | |||
1 | /* | ||
2 | * dvb-dibusb-firmware.c is part of the driver for mobile USB Budget DVB-T devices | ||
3 | * based on reference design made by DiBcom (http://www.dibcom.fr/) | ||
4 | * | ||
5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
6 | * | ||
7 | * see dvb-dibusb-core.c for more copyright details. | ||
8 | * | ||
9 | * This file contains functions for downloading the firmware to the device. | ||
10 | */ | ||
11 | #include "dvb-dibusb.h" | ||
12 | |||
13 | #include <linux/firmware.h> | ||
14 | #include <linux/usb.h> | ||
15 | |||
16 | /* | ||
17 | * load a firmware packet to the device | ||
18 | */ | ||
19 | static int dibusb_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len) | ||
20 | { | ||
21 | return usb_control_msg(udev, usb_sndctrlpipe(udev,0), | ||
22 | 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000); | ||
23 | } | ||
24 | |||
25 | int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_usb_device *dibdev) | ||
26 | { | ||
27 | const struct firmware *fw = NULL; | ||
28 | u16 addr; | ||
29 | u8 *b,*p; | ||
30 | int ret = 0,i; | ||
31 | |||
32 | if ((ret = request_firmware(&fw, dibdev->dev_cl->firmware, &udev->dev)) != 0) { | ||
33 | err("did not find the firmware file. (%s) " | ||
34 | "Please see linux/Documentation/dvb/ for more details on firmware-problems.", | ||
35 | dibdev->dev_cl->firmware); | ||
36 | return ret; | ||
37 | } | ||
38 | |||
39 | info("downloading firmware from file '%s'.",dibdev->dev_cl->firmware); | ||
40 | |||
41 | p = kmalloc(fw->size,GFP_KERNEL); | ||
42 | if (p != NULL) { | ||
43 | u8 reset; | ||
44 | /* | ||
45 | * you cannot use the fw->data as buffer for | ||
46 | * usb_control_msg, a new buffer has to be | ||
47 | * created | ||
48 | */ | ||
49 | memcpy(p,fw->data,fw->size); | ||
50 | |||
51 | /* stop the CPU */ | ||
52 | reset = 1; | ||
53 | if ((ret = dibusb_writemem(udev,dibdev->dev_cl->usb_ctrl->cpu_cs_register,&reset,1)) != 1) | ||
54 | err("could not stop the USB controller CPU."); | ||
55 | for(i = 0; p[i+3] == 0 && i < fw->size; ) { | ||
56 | b = (u8 *) &p[i]; | ||
57 | addr = *((u16 *) &b[1]); | ||
58 | |||
59 | ret = dibusb_writemem(udev,addr,&b[4],b[0]); | ||
60 | |||
61 | if (ret != b[0]) { | ||
62 | err("error while transferring firmware " | ||
63 | "(transferred size: %d, block size: %d)", | ||
64 | ret,b[0]); | ||
65 | ret = -EINVAL; | ||
66 | break; | ||
67 | } | ||
68 | i += 5 + b[0]; | ||
69 | } | ||
70 | /* length in ret */ | ||
71 | if (ret > 0) | ||
72 | ret = 0; | ||
73 | /* restart the CPU */ | ||
74 | reset = 0; | ||
75 | if (ret || dibusb_writemem(udev,dibdev->dev_cl->usb_ctrl->cpu_cs_register,&reset,1) != 1) { | ||
76 | err("could not restart the USB controller CPU."); | ||
77 | ret = -EINVAL; | ||
78 | } | ||
79 | |||
80 | kfree(p); | ||
81 | } else { | ||
82 | ret = -ENOMEM; | ||
83 | } | ||
84 | release_firmware(fw); | ||
85 | |||
86 | return ret; | ||
87 | } | ||
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-remote.c b/drivers/media/dvb/dibusb/dvb-dibusb-remote.c deleted file mode 100644 index 9dc8b15517..0000000000 --- a/drivers/media/dvb/dibusb/dvb-dibusb-remote.c +++ /dev/null | |||
@@ -1,316 +0,0 @@ | |||
1 | /* | ||
2 | * dvb-dibusb-remote.c is part of the driver for mobile USB Budget DVB-T devices | ||
3 | * based on reference design made by DiBcom (http://www.dibcom.fr/) | ||
4 | * | ||
5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
6 | * | ||
7 | * see dvb-dibusb-core.c for more copyright details. | ||
8 | * | ||
9 | * This file contains functions for handling the event device on the software | ||
10 | * side and the remote control on the hardware side. | ||
11 | */ | ||
12 | #include "dvb-dibusb.h" | ||
13 | |||
14 | /* Table to map raw key codes to key events. This should not be hard-wired | ||
15 | into the kernel. */ | ||
16 | static const struct { u8 c0, c1, c2; uint32_t key; } nec_rc_keys [] = | ||
17 | { | ||
18 | /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */ | ||
19 | { 0x00, 0xff, 0x16, KEY_POWER }, | ||
20 | { 0x00, 0xff, 0x10, KEY_MUTE }, | ||
21 | { 0x00, 0xff, 0x03, KEY_1 }, | ||
22 | { 0x00, 0xff, 0x01, KEY_2 }, | ||
23 | { 0x00, 0xff, 0x06, KEY_3 }, | ||
24 | { 0x00, 0xff, 0x09, KEY_4 }, | ||
25 | { 0x00, 0xff, 0x1d, KEY_5 }, | ||
26 | { 0x00, 0xff, 0x1f, KEY_6 }, | ||
27 | { 0x00, 0xff, 0x0d, KEY_7 }, | ||
28 | { 0x00, 0xff, 0x19, KEY_8 }, | ||
29 | { 0x00, 0xff, 0x1b, KEY_9 }, | ||
30 | { 0x00, 0xff, 0x15, KEY_0 }, | ||
31 | { 0x00, 0xff, 0x05, KEY_CHANNELUP }, | ||
32 | { 0x00, 0xff, 0x02, KEY_CHANNELDOWN }, | ||
33 | { 0x00, 0xff, 0x1e, KEY_VOLUMEUP }, | ||
34 | { 0x00, 0xff, 0x0a, KEY_VOLUMEDOWN }, | ||
35 | { 0x00, 0xff, 0x11, KEY_RECORD }, | ||
36 | { 0x00, 0xff, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */ | ||
37 | { 0x00, 0xff, 0x14, KEY_PLAY }, | ||
38 | { 0x00, 0xff, 0x1a, KEY_STOP }, | ||
39 | { 0x00, 0xff, 0x40, KEY_REWIND }, | ||
40 | { 0x00, 0xff, 0x12, KEY_FASTFORWARD }, | ||
41 | { 0x00, 0xff, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */ | ||
42 | { 0x00, 0xff, 0x4c, KEY_PAUSE }, | ||
43 | { 0x00, 0xff, 0x4d, KEY_SCREEN }, /* Full screen mode. */ | ||
44 | { 0x00, 0xff, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ | ||
45 | /* additional keys TwinHan VisionPlus, the Artec seemingly not have */ | ||
46 | { 0x00, 0xff, 0x0c, KEY_CANCEL }, /* Cancel */ | ||
47 | { 0x00, 0xff, 0x1c, KEY_EPG }, /* EPG */ | ||
48 | { 0x00, 0xff, 0x00, KEY_TAB }, /* Tab */ | ||
49 | { 0x00, 0xff, 0x48, KEY_INFO }, /* Preview */ | ||
50 | { 0x00, 0xff, 0x04, KEY_LIST }, /* RecordList */ | ||
51 | { 0x00, 0xff, 0x0f, KEY_TEXT }, /* Teletext */ | ||
52 | /* Key codes for the KWorld/ADSTech/JetWay remote. */ | ||
53 | { 0x86, 0x6b, 0x12, KEY_POWER }, | ||
54 | { 0x86, 0x6b, 0x0f, KEY_SELECT }, /* source */ | ||
55 | { 0x86, 0x6b, 0x0c, KEY_UNKNOWN }, /* scan */ | ||
56 | { 0x86, 0x6b, 0x0b, KEY_EPG }, | ||
57 | { 0x86, 0x6b, 0x10, KEY_MUTE }, | ||
58 | { 0x86, 0x6b, 0x01, KEY_1 }, | ||
59 | { 0x86, 0x6b, 0x02, KEY_2 }, | ||
60 | { 0x86, 0x6b, 0x03, KEY_3 }, | ||
61 | { 0x86, 0x6b, 0x04, KEY_4 }, | ||
62 | { 0x86, 0x6b, 0x05, KEY_5 }, | ||
63 | { 0x86, 0x6b, 0x06, KEY_6 }, | ||
64 | { 0x86, 0x6b, 0x07, KEY_7 }, | ||
65 | { 0x86, 0x6b, 0x08, KEY_8 }, | ||
66 | { 0x86, 0x6b, 0x09, KEY_9 }, | ||
67 | { 0x86, 0x6b, 0x0a, KEY_0 }, | ||
68 | { 0x86, 0x6b, 0x18, KEY_ZOOM }, | ||
69 | { 0x86, 0x6b, 0x1c, KEY_UNKNOWN }, /* preview */ | ||
70 | { 0x86, 0x6b, 0x13, KEY_UNKNOWN }, /* snap */ | ||
71 | { 0x86, 0x6b, 0x00, KEY_UNDO }, | ||
72 | { 0x86, 0x6b, 0x1d, KEY_RECORD }, | ||
73 | { 0x86, 0x6b, 0x0d, KEY_STOP }, | ||
74 | { 0x86, 0x6b, 0x0e, KEY_PAUSE }, | ||
75 | { 0x86, 0x6b, 0x16, KEY_PLAY }, | ||
76 | { 0x86, 0x6b, 0x11, KEY_BACK }, | ||
77 | { 0x86, 0x6b, 0x19, KEY_FORWARD }, | ||
78 | { 0x86, 0x6b, 0x14, KEY_UNKNOWN }, /* pip */ | ||
79 | { 0x86, 0x6b, 0x15, KEY_ESC }, | ||
80 | { 0x86, 0x6b, 0x1a, KEY_UP }, | ||
81 | { 0x86, 0x6b, 0x1e, KEY_DOWN }, | ||
82 | { 0x86, 0x6b, 0x1f, KEY_LEFT }, | ||
83 | { 0x86, 0x6b, 0x1b, KEY_RIGHT }, | ||
84 | }; | ||
85 | |||
86 | /* Hauppauge NOVA-T USB2 keys */ | ||
87 | static const struct { u16 raw; uint32_t key; } haupp_rc_keys [] = { | ||
88 | { 0xddf, KEY_GOTO }, | ||
89 | { 0xdef, KEY_POWER }, | ||
90 | { 0xce7, KEY_TV }, | ||
91 | { 0xcc7, KEY_VIDEO }, | ||
92 | { 0xccf, KEY_AUDIO }, | ||
93 | { 0xcd7, KEY_MEDIA }, | ||
94 | { 0xcdf, KEY_EPG }, | ||
95 | { 0xca7, KEY_UP }, | ||
96 | { 0xc67, KEY_RADIO }, | ||
97 | { 0xcb7, KEY_LEFT }, | ||
98 | { 0xd2f, KEY_OK }, | ||
99 | { 0xcbf, KEY_RIGHT }, | ||
100 | { 0xcff, KEY_BACK }, | ||
101 | { 0xcaf, KEY_DOWN }, | ||
102 | { 0xc6f, KEY_MENU }, | ||
103 | { 0xc87, KEY_VOLUMEUP }, | ||
104 | { 0xc8f, KEY_VOLUMEDOWN }, | ||
105 | { 0xc97, KEY_CHANNEL }, | ||
106 | { 0xc7f, KEY_MUTE }, | ||
107 | { 0xd07, KEY_CHANNELUP }, | ||
108 | { 0xd0f, KEY_CHANNELDOWN }, | ||
109 | { 0xdbf, KEY_RECORD }, | ||
110 | { 0xdb7, KEY_STOP }, | ||
111 | { 0xd97, KEY_REWIND }, | ||
112 | { 0xdaf, KEY_PLAY }, | ||
113 | { 0xda7, KEY_FASTFORWARD }, | ||
114 | { 0xd27, KEY_LAST }, /* Skip backwards */ | ||
115 | { 0xd87, KEY_PAUSE }, | ||
116 | { 0xcf7, KEY_NEXT }, | ||
117 | { 0xc07, KEY_0 }, | ||
118 | { 0xc0f, KEY_1 }, | ||
119 | { 0xc17, KEY_2 }, | ||
120 | { 0xc1f, KEY_3 }, | ||
121 | { 0xc27, KEY_4 }, | ||
122 | { 0xc2f, KEY_5 }, | ||
123 | { 0xc37, KEY_6 }, | ||
124 | { 0xc3f, KEY_7 }, | ||
125 | { 0xc47, KEY_8 }, | ||
126 | { 0xc4f, KEY_9 }, | ||
127 | { 0xc57, KEY_KPASTERISK }, | ||
128 | { 0xc77, KEY_GRAVE }, /* # */ | ||
129 | { 0xc5f, KEY_RED }, | ||
130 | { 0xd77, KEY_GREEN }, | ||
131 | { 0xdc7, KEY_YELLOW }, | ||
132 | { 0xd4f, KEY_BLUE}, | ||
133 | }; | ||
134 | |||
135 | static int dibusb_key2event_nec(struct usb_dibusb *dib,u8 rb[5]) | ||
136 | { | ||
137 | int i; | ||
138 | switch (rb[0]) { | ||
139 | case DIBUSB_RC_NEC_KEY_PRESSED: | ||
140 | /* rb[1-3] is the actual key, rb[4] is a checksum */ | ||
141 | deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", | ||
142 | rb[1], rb[2], rb[3], rb[4]); | ||
143 | |||
144 | if ((0xff - rb[3]) != rb[4]) { | ||
145 | deb_rc("remote control checksum failed.\n"); | ||
146 | break; | ||
147 | } | ||
148 | |||
149 | /* See if we can match the raw key code. */ | ||
150 | for (i = 0; i < sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++) { | ||
151 | if (nec_rc_keys[i].c0 == rb[1] && | ||
152 | nec_rc_keys[i].c1 == rb[2] && | ||
153 | nec_rc_keys[i].c2 == rb[3]) { | ||
154 | |||
155 | dib->last_event = nec_rc_keys[i].key; | ||
156 | return 1; | ||
157 | } | ||
158 | } | ||
159 | break; | ||
160 | case DIBUSB_RC_NEC_KEY_REPEATED: | ||
161 | /* rb[1]..rb[4] are always zero.*/ | ||
162 | /* Repeats often seem to occur so for the moment just ignore this. */ | ||
163 | return 0; | ||
164 | case DIBUSB_RC_NEC_EMPTY: /* No (more) remote control keys. */ | ||
165 | default: | ||
166 | break; | ||
167 | } | ||
168 | return -1; | ||
169 | } | ||
170 | |||
171 | static int dibusb_key2event_hauppauge(struct usb_dibusb *dib,u8 rb[4]) | ||
172 | { | ||
173 | u16 raw; | ||
174 | int i,state; | ||
175 | switch (rb[0]) { | ||
176 | case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED: | ||
177 | raw = ((rb[1] & 0x0f) << 8) | rb[2]; | ||
178 | |||
179 | state = !!(rb[1] & 0x40); | ||
180 | |||
181 | deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to %04x state: %d\n",rb[1],rb[2],rb[3],raw,state); | ||
182 | for (i = 0; i < sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++) { | ||
183 | if (haupp_rc_keys[i].raw == raw) { | ||
184 | if (dib->last_event == haupp_rc_keys[i].key && | ||
185 | dib->last_state == state) { | ||
186 | deb_rc("key repeat\n"); | ||
187 | return 0; | ||
188 | } else { | ||
189 | dib->last_event = haupp_rc_keys[i].key; | ||
190 | dib->last_state = state; | ||
191 | return 1; | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | |||
196 | break; | ||
197 | case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY: | ||
198 | default: | ||
199 | break; | ||
200 | } | ||
201 | return -1; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * Read the remote control and feed the appropriate event. | ||
206 | * NEC protocol is used for remote controls | ||
207 | */ | ||
208 | static int dibusb_read_remote_control(struct usb_dibusb *dib) | ||
209 | { | ||
210 | u8 b[1] = { DIBUSB_REQ_POLL_REMOTE }, rb[5]; | ||
211 | int ret,event = 0; | ||
212 | |||
213 | if ((ret = dibusb_readwrite_usb(dib,b,1,rb,5))) | ||
214 | return ret; | ||
215 | |||
216 | switch (dib->dibdev->dev_cl->remote_type) { | ||
217 | case DIBUSB_RC_NEC_PROTOCOL: | ||
218 | event = dibusb_key2event_nec(dib,rb); | ||
219 | break; | ||
220 | case DIBUSB_RC_HAUPPAUGE_PROTO: | ||
221 | event = dibusb_key2event_hauppauge(dib,rb); | ||
222 | default: | ||
223 | break; | ||
224 | } | ||
225 | |||
226 | /* key repeat */ | ||
227 | if (event == 0) | ||
228 | if (++dib->repeat_key_count < dib->rc_key_repeat_count) { | ||
229 | deb_rc("key repeat dropped. (%d)\n",dib->repeat_key_count); | ||
230 | event = -1; /* skip this key repeat */ | ||
231 | } | ||
232 | |||
233 | if (event == 1 || event == 0) { | ||
234 | deb_rc("Translated key 0x%04x\n",event); | ||
235 | |||
236 | /* Signal down and up events for this key. */ | ||
237 | input_report_key(&dib->rc_input_dev, dib->last_event, 1); | ||
238 | input_report_key(&dib->rc_input_dev, dib->last_event, 0); | ||
239 | input_sync(&dib->rc_input_dev); | ||
240 | |||
241 | if (event == 1) | ||
242 | dib->repeat_key_count = 0; | ||
243 | } | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | /* Remote-control poll function - called every dib->rc_query_interval ms to see | ||
248 | whether the remote control has received anything. */ | ||
249 | static void dibusb_remote_query(void *data) | ||
250 | { | ||
251 | struct usb_dibusb *dib = (struct usb_dibusb *) data; | ||
252 | /* TODO: need a lock here. We can simply skip checking for the remote control | ||
253 | if we're busy. */ | ||
254 | dibusb_read_remote_control(dib); | ||
255 | schedule_delayed_work(&dib->rc_query_work, | ||
256 | msecs_to_jiffies(dib->rc_query_interval)); | ||
257 | } | ||
258 | |||
259 | int dibusb_remote_init(struct usb_dibusb *dib) | ||
260 | { | ||
261 | int i; | ||
262 | |||
263 | if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO) | ||
264 | return 0; | ||
265 | |||
266 | /* Initialise the remote-control structures.*/ | ||
267 | init_input_dev(&dib->rc_input_dev); | ||
268 | |||
269 | dib->rc_input_dev.evbit[0] = BIT(EV_KEY); | ||
270 | dib->rc_input_dev.keycodesize = sizeof(unsigned char); | ||
271 | dib->rc_input_dev.keycodemax = KEY_MAX; | ||
272 | dib->rc_input_dev.name = DRIVER_DESC " remote control"; | ||
273 | |||
274 | switch (dib->dibdev->dev_cl->remote_type) { | ||
275 | case DIBUSB_RC_NEC_PROTOCOL: | ||
276 | for (i=0; i<sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++) | ||
277 | set_bit(nec_rc_keys[i].key, dib->rc_input_dev.keybit); | ||
278 | break; | ||
279 | case DIBUSB_RC_HAUPPAUGE_PROTO: | ||
280 | for (i=0; i<sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++) | ||
281 | set_bit(haupp_rc_keys[i].key, dib->rc_input_dev.keybit); | ||
282 | break; | ||
283 | default: | ||
284 | break; | ||
285 | } | ||
286 | |||
287 | |||
288 | input_register_device(&dib->rc_input_dev); | ||
289 | |||
290 | INIT_WORK(&dib->rc_query_work, dibusb_remote_query, dib); | ||
291 | |||
292 | /* Start the remote-control polling. */ | ||
293 | if (dib->rc_query_interval < 40) | ||
294 | dib->rc_query_interval = 100; /* default */ | ||
295 | |||
296 | info("schedule remote query interval to %d msecs.",dib->rc_query_interval); | ||
297 | schedule_delayed_work(&dib->rc_query_work,msecs_to_jiffies(dib->rc_query_interval)); | ||
298 | |||
299 | dib->init_state |= DIBUSB_STATE_REMOTE; | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | int dibusb_remote_exit(struct usb_dibusb *dib) | ||
305 | { | ||
306 | if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO) | ||
307 | return 0; | ||
308 | |||
309 | if (dib->init_state & DIBUSB_STATE_REMOTE) { | ||
310 | cancel_delayed_work(&dib->rc_query_work); | ||
311 | flush_scheduled_work(); | ||
312 | input_unregister_device(&dib->rc_input_dev); | ||
313 | } | ||
314 | dib->init_state &= ~DIBUSB_STATE_REMOTE; | ||
315 | return 0; | ||
316 | } | ||
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-usb.c b/drivers/media/dvb/dibusb/dvb-dibusb-usb.c deleted file mode 100644 index 642f0596a5..0000000000 --- a/drivers/media/dvb/dibusb/dvb-dibusb-usb.c +++ /dev/null | |||
@@ -1,303 +0,0 @@ | |||
1 | /* | ||
2 | * dvb-dibusb-usb.c is part of the driver for mobile USB Budget DVB-T devices | ||
3 | * based on reference design made by DiBcom (http://www.dibcom.fr/) | ||
4 | * | ||
5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
6 | * | ||
7 | * see dvb-dibusb-core.c for more copyright details. | ||
8 | * | ||
9 | * This file contains functions for initializing and handling the | ||
10 | * usb specific stuff. | ||
11 | */ | ||
12 | #include "dvb-dibusb.h" | ||
13 | |||
14 | #include <linux/version.h> | ||
15 | #include <linux/pci.h> | ||
16 | |||
17 | int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf, | ||
18 | u16 rlen) | ||
19 | { | ||
20 | int actlen,ret = -ENOMEM; | ||
21 | |||
22 | if (wbuf == NULL || wlen == 0) | ||
23 | return -EINVAL; | ||
24 | |||
25 | if ((ret = down_interruptible(&dib->usb_sem))) | ||
26 | return ret; | ||
27 | |||
28 | debug_dump(wbuf,wlen); | ||
29 | |||
30 | ret = usb_bulk_msg(dib->udev,usb_sndbulkpipe(dib->udev, | ||
31 | dib->dibdev->dev_cl->pipe_cmd), wbuf,wlen,&actlen, | ||
32 | DIBUSB_I2C_TIMEOUT); | ||
33 | |||
34 | if (ret) | ||
35 | err("bulk message failed: %d (%d/%d)",ret,wlen,actlen); | ||
36 | else | ||
37 | ret = actlen != wlen ? -1 : 0; | ||
38 | |||
39 | /* an answer is expected, and no error before */ | ||
40 | if (!ret && rbuf && rlen) { | ||
41 | ret = usb_bulk_msg(dib->udev,usb_rcvbulkpipe(dib->udev, | ||
42 | dib->dibdev->dev_cl->pipe_cmd),rbuf,rlen,&actlen, | ||
43 | DIBUSB_I2C_TIMEOUT); | ||
44 | |||
45 | if (ret) | ||
46 | err("recv bulk message failed: %d",ret); | ||
47 | else { | ||
48 | deb_alot("rlen: %d\n",rlen); | ||
49 | debug_dump(rbuf,actlen); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | up(&dib->usb_sem); | ||
54 | return ret; | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * Cypress controls | ||
59 | */ | ||
60 | int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len) | ||
61 | { | ||
62 | return dibusb_readwrite_usb(dib,buf,len,NULL,0); | ||
63 | } | ||
64 | |||
65 | #if 0 | ||
66 | /* | ||
67 | * #if 0'ing the following functions as they are not in use _now_, | ||
68 | * but probably will be sometime. | ||
69 | */ | ||
70 | /* | ||
71 | * do not use this, just a workaround for a bug, | ||
72 | * which will hopefully never occur :). | ||
73 | */ | ||
74 | int dibusb_interrupt_read_loop(struct usb_dibusb *dib) | ||
75 | { | ||
76 | u8 b[1] = { DIBUSB_REQ_INTR_READ }; | ||
77 | return dibusb_write_usb(dib,b,1); | ||
78 | } | ||
79 | #endif | ||
80 | |||
81 | /* | ||
82 | * ioctl for the firmware | ||
83 | */ | ||
84 | static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen) | ||
85 | { | ||
86 | u8 b[34]; | ||
87 | int size = plen > 32 ? 32 : plen; | ||
88 | memset(b,0,34); | ||
89 | b[0] = DIBUSB_REQ_SET_IOCTL; | ||
90 | b[1] = cmd; | ||
91 | |||
92 | if (size > 0) | ||
93 | memcpy(&b[2],param,size); | ||
94 | |||
95 | return dibusb_write_usb(dib,b,34); //2+size); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * ioctl for power control | ||
100 | */ | ||
101 | int dibusb_hw_wakeup(struct dvb_frontend *fe) | ||
102 | { | ||
103 | struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv; | ||
104 | u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP }; | ||
105 | deb_info("dibusb-device is getting up.\n"); | ||
106 | |||
107 | switch (dib->dibdev->dev_cl->id) { | ||
108 | case DTT200U: | ||
109 | break; | ||
110 | default: | ||
111 | dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1); | ||
112 | break; | ||
113 | } | ||
114 | |||
115 | if (dib->fe_init) | ||
116 | return dib->fe_init(fe); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | int dibusb_hw_sleep(struct dvb_frontend *fe) | ||
122 | { | ||
123 | struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv; | ||
124 | u8 b[1] = { DIBUSB_IOCTL_POWER_SLEEP }; | ||
125 | deb_info("dibusb-device is going to bed.\n"); | ||
126 | /* workaround, something is wrong, when dibusb 1.1 device are going to bed too late */ | ||
127 | switch (dib->dibdev->dev_cl->id) { | ||
128 | case DIBUSB1_1: | ||
129 | case NOVAT_USB2: | ||
130 | case DTT200U: | ||
131 | break; | ||
132 | default: | ||
133 | dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1); | ||
134 | break; | ||
135 | } | ||
136 | if (dib->fe_sleep) | ||
137 | return dib->fe_sleep(fe); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | int dibusb_set_streaming_mode(struct usb_dibusb *dib,u8 mode) | ||
143 | { | ||
144 | u8 b[2] = { DIBUSB_REQ_SET_STREAMING_MODE, mode }; | ||
145 | return dibusb_readwrite_usb(dib,b,2,NULL,0); | ||
146 | } | ||
147 | |||
148 | static int dibusb_urb_kill(struct usb_dibusb *dib) | ||
149 | { | ||
150 | int i; | ||
151 | deb_info("trying to kill urbs\n"); | ||
152 | if (dib->init_state & DIBUSB_STATE_URB_SUBMIT) { | ||
153 | for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) { | ||
154 | deb_info("killing URB no. %d.\n",i); | ||
155 | |||
156 | /* stop the URB */ | ||
157 | usb_kill_urb(dib->urb_list[i]); | ||
158 | } | ||
159 | } else | ||
160 | deb_info(" URBs not killed.\n"); | ||
161 | dib->init_state &= ~DIBUSB_STATE_URB_SUBMIT; | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int dibusb_urb_submit(struct usb_dibusb *dib) | ||
166 | { | ||
167 | int i,ret; | ||
168 | if (dib->init_state & DIBUSB_STATE_URB_INIT) { | ||
169 | for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) { | ||
170 | deb_info("submitting URB no. %d\n",i); | ||
171 | if ((ret = usb_submit_urb(dib->urb_list[i],GFP_ATOMIC))) { | ||
172 | err("could not submit buffer urb no. %d - get them all back\n",i); | ||
173 | dibusb_urb_kill(dib); | ||
174 | return ret; | ||
175 | } | ||
176 | dib->init_state |= DIBUSB_STATE_URB_SUBMIT; | ||
177 | } | ||
178 | } | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | int dibusb_streaming(struct usb_dibusb *dib,int onoff) | ||
183 | { | ||
184 | if (onoff) | ||
185 | dibusb_urb_submit(dib); | ||
186 | else | ||
187 | dibusb_urb_kill(dib); | ||
188 | |||
189 | switch (dib->dibdev->dev_cl->id) { | ||
190 | case DIBUSB2_0: | ||
191 | case DIBUSB2_0B: | ||
192 | case NOVAT_USB2: | ||
193 | case UMT2_0: | ||
194 | if (onoff) | ||
195 | return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_ENABLE_STREAM,NULL,0); | ||
196 | else | ||
197 | return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_DISABLE_STREAM,NULL,0); | ||
198 | break; | ||
199 | default: | ||
200 | break; | ||
201 | } | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | int dibusb_urb_init(struct usb_dibusb *dib) | ||
206 | { | ||
207 | int i,bufsize,def_pid_parse = 1; | ||
208 | |||
209 | /* | ||
210 | * when reloading the driver w/o replugging the device | ||
211 | * a timeout occures, this helps | ||
212 | */ | ||
213 | usb_clear_halt(dib->udev,usb_sndbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd)); | ||
214 | usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd)); | ||
215 | usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data)); | ||
216 | |||
217 | /* allocate the array for the data transfer URBs */ | ||
218 | dib->urb_list = kmalloc(dib->dibdev->dev_cl->urb_count*sizeof(struct urb *),GFP_KERNEL); | ||
219 | if (dib->urb_list == NULL) | ||
220 | return -ENOMEM; | ||
221 | memset(dib->urb_list,0,dib->dibdev->dev_cl->urb_count*sizeof(struct urb *)); | ||
222 | |||
223 | dib->init_state |= DIBUSB_STATE_URB_LIST; | ||
224 | |||
225 | bufsize = dib->dibdev->dev_cl->urb_count*dib->dibdev->dev_cl->urb_buffer_size; | ||
226 | deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize); | ||
227 | /* allocate the actual buffer for the URBs */ | ||
228 | if ((dib->buffer = pci_alloc_consistent(NULL,bufsize,&dib->dma_handle)) == NULL) { | ||
229 | deb_info("not enough memory.\n"); | ||
230 | return -ENOMEM; | ||
231 | } | ||
232 | deb_info("allocation complete\n"); | ||
233 | memset(dib->buffer,0,bufsize); | ||
234 | |||
235 | dib->init_state |= DIBUSB_STATE_URB_BUF; | ||
236 | |||
237 | /* allocate and submit the URBs */ | ||
238 | for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) { | ||
239 | if (!(dib->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) { | ||
240 | return -ENOMEM; | ||
241 | } | ||
242 | |||
243 | usb_fill_bulk_urb( dib->urb_list[i], dib->udev, | ||
244 | usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data), | ||
245 | &dib->buffer[i*dib->dibdev->dev_cl->urb_buffer_size], | ||
246 | dib->dibdev->dev_cl->urb_buffer_size, | ||
247 | dibusb_urb_complete, dib); | ||
248 | |||
249 | dib->urb_list[i]->transfer_flags = 0; | ||
250 | |||
251 | dib->init_state |= DIBUSB_STATE_URB_INIT; | ||
252 | } | ||
253 | |||
254 | /* dib->pid_parse here contains the value of the module parameter */ | ||
255 | /* decide if pid parsing can be deactivated: | ||
256 | * is possible (by device type) and wanted (by user) | ||
257 | */ | ||
258 | switch (dib->dibdev->dev_cl->id) { | ||
259 | case DIBUSB2_0: | ||
260 | case DIBUSB2_0B: | ||
261 | if (dib->udev->speed == USB_SPEED_HIGH && !dib->pid_parse) { | ||
262 | def_pid_parse = 0; | ||
263 | info("running at HIGH speed, will deliver the complete TS."); | ||
264 | } else | ||
265 | info("will use pid_parsing."); | ||
266 | break; | ||
267 | default: | ||
268 | break; | ||
269 | } | ||
270 | /* from here on it contains the device and user decision */ | ||
271 | dib->pid_parse = def_pid_parse; | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | int dibusb_urb_exit(struct usb_dibusb *dib) | ||
277 | { | ||
278 | int i; | ||
279 | |||
280 | dibusb_urb_kill(dib); | ||
281 | |||
282 | if (dib->init_state & DIBUSB_STATE_URB_LIST) { | ||
283 | for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) { | ||
284 | if (dib->urb_list[i] != NULL) { | ||
285 | deb_info("freeing URB no. %d.\n",i); | ||
286 | /* free the URBs */ | ||
287 | usb_free_urb(dib->urb_list[i]); | ||
288 | } | ||
289 | } | ||
290 | /* free the urb array */ | ||
291 | kfree(dib->urb_list); | ||
292 | dib->init_state &= ~DIBUSB_STATE_URB_LIST; | ||
293 | } | ||
294 | |||
295 | if (dib->init_state & DIBUSB_STATE_URB_BUF) | ||
296 | pci_free_consistent(NULL, | ||
297 | dib->dibdev->dev_cl->urb_buffer_size*dib->dibdev->dev_cl->urb_count, | ||
298 | dib->buffer,dib->dma_handle); | ||
299 | |||
300 | dib->init_state &= ~DIBUSB_STATE_URB_BUF; | ||
301 | dib->init_state &= ~DIBUSB_STATE_URB_INIT; | ||
302 | return 0; | ||
303 | } | ||
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb.h b/drivers/media/dvb/dibusb/dvb-dibusb.h deleted file mode 100644 index c965b64fb1..0000000000 --- a/drivers/media/dvb/dibusb/dvb-dibusb.h +++ /dev/null | |||
@@ -1,327 +0,0 @@ | |||
1 | /* | ||
2 | * dvb-dibusb.h | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | * for more information see dvb-dibusb-core.c . | ||
11 | */ | ||
12 | #ifndef __DVB_DIBUSB_H__ | ||
13 | #define __DVB_DIBUSB_H__ | ||
14 | |||
15 | #include <linux/input.h> | ||
16 | #include <linux/config.h> | ||
17 | #include <linux/usb.h> | ||
18 | |||
19 | #include "dvb_frontend.h" | ||
20 | #include "dvb_demux.h" | ||
21 | #include "dvb_net.h" | ||
22 | #include "dmxdev.h" | ||
23 | |||
24 | #include "dib3000.h" | ||
25 | #include "mt352.h" | ||
26 | |||
27 | /* debug */ | ||
28 | #ifdef CONFIG_DVB_DIBCOM_DEBUG | ||
29 | #define dprintk(level,args...) \ | ||
30 | do { if ((dvb_dibusb_debug & level)) { printk(args); } } while (0) | ||
31 | |||
32 | #define debug_dump(b,l) {\ | ||
33 | int i; \ | ||
34 | for (i = 0; i < l; i++) deb_xfer("%02x ", b[i]); \ | ||
35 | deb_xfer("\n");\ | ||
36 | } | ||
37 | |||
38 | #else | ||
39 | #define dprintk(args...) | ||
40 | #define debug_dump(b,l) | ||
41 | #endif | ||
42 | |||
43 | extern int dvb_dibusb_debug; | ||
44 | |||
45 | /* Version information */ | ||
46 | #define DRIVER_VERSION "0.3" | ||
47 | #define DRIVER_DESC "DiBcom based USB Budget DVB-T device" | ||
48 | #define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de" | ||
49 | |||
50 | #define deb_info(args...) dprintk(0x01,args) | ||
51 | #define deb_xfer(args...) dprintk(0x02,args) | ||
52 | #define deb_alot(args...) dprintk(0x04,args) | ||
53 | #define deb_ts(args...) dprintk(0x08,args) | ||
54 | #define deb_err(args...) dprintk(0x10,args) | ||
55 | #define deb_rc(args...) dprintk(0x20,args) | ||
56 | |||
57 | /* generic log methods - taken from usb.h */ | ||
58 | #undef err | ||
59 | #define err(format, arg...) printk(KERN_ERR "dvb-dibusb: " format "\n" , ## arg) | ||
60 | #undef info | ||
61 | #define info(format, arg...) printk(KERN_INFO "dvb-dibusb: " format "\n" , ## arg) | ||
62 | #undef warn | ||
63 | #define warn(format, arg...) printk(KERN_WARNING "dvb-dibusb: " format "\n" , ## arg) | ||
64 | |||
65 | struct dibusb_usb_controller { | ||
66 | const char *name; /* name of the usb controller */ | ||
67 | u16 cpu_cs_register; /* needs to be restarted, when the firmware has been downloaded. */ | ||
68 | }; | ||
69 | |||
70 | typedef enum { | ||
71 | DIBUSB1_1 = 0, | ||
72 | DIBUSB1_1_AN2235, | ||
73 | DIBUSB2_0, | ||
74 | UMT2_0, | ||
75 | DIBUSB2_0B, | ||
76 | NOVAT_USB2, | ||
77 | DTT200U, | ||
78 | } dibusb_class_t; | ||
79 | |||
80 | typedef enum { | ||
81 | DIBUSB_TUNER_CABLE_THOMSON = 0, | ||
82 | DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5, | ||
83 | DIBUSB_TUNER_CABLE_LG_TDTP_E102P, | ||
84 | DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5, | ||
85 | } dibusb_tuner_t; | ||
86 | |||
87 | typedef enum { | ||
88 | DIBUSB_DIB3000MB = 0, | ||
89 | DIBUSB_DIB3000MC, | ||
90 | DIBUSB_MT352, | ||
91 | DTT200U_FE, | ||
92 | } dibusb_demodulator_t; | ||
93 | |||
94 | typedef enum { | ||
95 | DIBUSB_RC_NO = 0, | ||
96 | DIBUSB_RC_NEC_PROTOCOL, | ||
97 | DIBUSB_RC_HAUPPAUGE_PROTO, | ||
98 | } dibusb_remote_t; | ||
99 | |||
100 | struct dibusb_tuner { | ||
101 | dibusb_tuner_t id; | ||
102 | |||
103 | u8 pll_addr; /* tuner i2c address */ | ||
104 | }; | ||
105 | extern struct dibusb_tuner dibusb_tuner[]; | ||
106 | |||
107 | #define DIBUSB_POSSIBLE_I2C_ADDR_NUM 4 | ||
108 | struct dibusb_demod { | ||
109 | dibusb_demodulator_t id; | ||
110 | |||
111 | int pid_filter_count; /* counter of the internal pid_filter */ | ||
112 | u8 i2c_addrs[DIBUSB_POSSIBLE_I2C_ADDR_NUM]; /* list of possible i2c addresses of the demod */ | ||
113 | }; | ||
114 | |||
115 | #define DIBUSB_MAX_TUNER_NUM 2 | ||
116 | struct dibusb_device_class { | ||
117 | dibusb_class_t id; | ||
118 | |||
119 | const struct dibusb_usb_controller *usb_ctrl; /* usb controller */ | ||
120 | const char *firmware; /* valid firmware filenames */ | ||
121 | |||
122 | int pipe_cmd; /* command pipe (read/write) */ | ||
123 | int pipe_data; /* data pipe */ | ||
124 | |||
125 | int urb_count; /* number of data URBs to be submitted */ | ||
126 | int urb_buffer_size; /* the size of the buffer for each URB */ | ||
127 | |||
128 | dibusb_remote_t remote_type; /* does this device have a ir-receiver */ | ||
129 | |||
130 | struct dibusb_demod *demod; /* which demodulator is mount */ | ||
131 | struct dibusb_tuner *tuner; /* which tuner can be found here */ | ||
132 | }; | ||
133 | |||
134 | #define DIBUSB_ID_MAX_NUM 15 | ||
135 | struct dibusb_usb_device { | ||
136 | const char *name; /* real name of the box */ | ||
137 | struct dibusb_device_class *dev_cl; /* which dibusb_device_class is this device part of */ | ||
138 | |||
139 | struct usb_device_id *cold_ids[DIBUSB_ID_MAX_NUM]; /* list of USB ids when this device is at pre firmware state */ | ||
140 | struct usb_device_id *warm_ids[DIBUSB_ID_MAX_NUM]; /* list of USB ids when this device is at post firmware state */ | ||
141 | }; | ||
142 | |||
143 | /* a PID for the pid_filter list, when in use */ | ||
144 | struct dibusb_pid | ||
145 | { | ||
146 | int index; | ||
147 | u16 pid; | ||
148 | int active; | ||
149 | }; | ||
150 | |||
151 | struct usb_dibusb { | ||
152 | /* usb */ | ||
153 | struct usb_device * udev; | ||
154 | |||
155 | struct dibusb_usb_device * dibdev; | ||
156 | |||
157 | #define DIBUSB_STATE_INIT 0x000 | ||
158 | #define DIBUSB_STATE_URB_LIST 0x001 | ||
159 | #define DIBUSB_STATE_URB_BUF 0x002 | ||
160 | #define DIBUSB_STATE_URB_INIT 0x004 | ||
161 | #define DIBUSB_STATE_DVB 0x008 | ||
162 | #define DIBUSB_STATE_I2C 0x010 | ||
163 | #define DIBUSB_STATE_REMOTE 0x020 | ||
164 | #define DIBUSB_STATE_URB_SUBMIT 0x040 | ||
165 | int init_state; | ||
166 | |||
167 | int feedcount; | ||
168 | struct dib_fe_xfer_ops xfer_ops; | ||
169 | |||
170 | struct dibusb_tuner *tuner; | ||
171 | |||
172 | struct urb **urb_list; | ||
173 | u8 *buffer; | ||
174 | dma_addr_t dma_handle; | ||
175 | |||
176 | /* I2C */ | ||
177 | struct i2c_adapter i2c_adap; | ||
178 | |||
179 | /* locking */ | ||
180 | struct semaphore usb_sem; | ||
181 | struct semaphore i2c_sem; | ||
182 | |||
183 | /* dvb */ | ||
184 | struct dvb_adapter adapter; | ||
185 | struct dmxdev dmxdev; | ||
186 | struct dvb_demux demux; | ||
187 | struct dvb_net dvb_net; | ||
188 | struct dvb_frontend* fe; | ||
189 | |||
190 | int (*fe_sleep) (struct dvb_frontend *); | ||
191 | int (*fe_init) (struct dvb_frontend *); | ||
192 | |||
193 | /* remote control */ | ||
194 | struct input_dev rc_input_dev; | ||
195 | struct work_struct rc_query_work; | ||
196 | int last_event; | ||
197 | int last_state; /* for Hauppauge RC protocol */ | ||
198 | int repeat_key_count; | ||
199 | int rc_key_repeat_count; /* module parameter */ | ||
200 | |||
201 | /* module parameters */ | ||
202 | int pid_parse; | ||
203 | int rc_query_interval; | ||
204 | }; | ||
205 | |||
206 | /* commonly used functions in the separated files */ | ||
207 | |||
208 | /* dvb-dibusb-firmware.c */ | ||
209 | int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_usb_device *dibdev); | ||
210 | |||
211 | /* dvb-dibusb-remote.c */ | ||
212 | int dibusb_remote_exit(struct usb_dibusb *dib); | ||
213 | int dibusb_remote_init(struct usb_dibusb *dib); | ||
214 | |||
215 | /* dvb-dibusb-fe-i2c.c */ | ||
216 | int dibusb_fe_init(struct usb_dibusb* dib); | ||
217 | int dibusb_fe_exit(struct usb_dibusb *dib); | ||
218 | int dibusb_i2c_init(struct usb_dibusb *dib); | ||
219 | int dibusb_i2c_exit(struct usb_dibusb *dib); | ||
220 | |||
221 | /* dvb-dibusb-dvb.c */ | ||
222 | void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs); | ||
223 | int dibusb_dvb_init(struct usb_dibusb *dib); | ||
224 | int dibusb_dvb_exit(struct usb_dibusb *dib); | ||
225 | |||
226 | /* dvb-dibusb-usb.c */ | ||
227 | int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf, | ||
228 | u16 rlen); | ||
229 | int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len); | ||
230 | |||
231 | int dibusb_hw_wakeup(struct dvb_frontend *); | ||
232 | int dibusb_hw_sleep(struct dvb_frontend *); | ||
233 | int dibusb_set_streaming_mode(struct usb_dibusb *,u8); | ||
234 | int dibusb_streaming(struct usb_dibusb *,int); | ||
235 | |||
236 | int dibusb_urb_init(struct usb_dibusb *); | ||
237 | int dibusb_urb_exit(struct usb_dibusb *); | ||
238 | |||
239 | /* dvb-fe-dtt200u.c */ | ||
240 | struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *,struct dib_fe_xfer_ops *); | ||
241 | |||
242 | /* i2c and transfer stuff */ | ||
243 | #define DIBUSB_I2C_TIMEOUT 5000 | ||
244 | |||
245 | /* | ||
246 | * protocol of all dibusb related devices | ||
247 | */ | ||
248 | |||
249 | /* | ||
250 | * bulk msg to/from endpoint 0x01 | ||
251 | * | ||
252 | * general structure: | ||
253 | * request_byte parameter_bytes | ||
254 | */ | ||
255 | |||
256 | #define DIBUSB_REQ_START_READ 0x00 | ||
257 | #define DIBUSB_REQ_START_DEMOD 0x01 | ||
258 | |||
259 | /* | ||
260 | * i2c read | ||
261 | * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word | ||
262 | * bulk read: byte_buffer (length_word bytes) | ||
263 | */ | ||
264 | #define DIBUSB_REQ_I2C_READ 0x02 | ||
265 | |||
266 | /* | ||
267 | * i2c write | ||
268 | * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes | ||
269 | */ | ||
270 | #define DIBUSB_REQ_I2C_WRITE 0x03 | ||
271 | |||
272 | /* | ||
273 | * polling the value of the remote control | ||
274 | * bulk write: 0x04 | ||
275 | * bulk read: byte_buffer (5 bytes) | ||
276 | * | ||
277 | * first byte of byte_buffer shows the status (0x00, 0x01, 0x02) | ||
278 | */ | ||
279 | #define DIBUSB_REQ_POLL_REMOTE 0x04 | ||
280 | |||
281 | #define DIBUSB_RC_NEC_EMPTY 0x00 | ||
282 | #define DIBUSB_RC_NEC_KEY_PRESSED 0x01 | ||
283 | #define DIBUSB_RC_NEC_KEY_REPEATED 0x02 | ||
284 | |||
285 | /* additional status values for Hauppauge Remote Control Protocol */ | ||
286 | #define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED 0x01 | ||
287 | #define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY 0x03 | ||
288 | |||
289 | /* streaming mode: | ||
290 | * bulk write: 0x05 mode_byte | ||
291 | * | ||
292 | * mode_byte is mostly 0x00 | ||
293 | */ | ||
294 | #define DIBUSB_REQ_SET_STREAMING_MODE 0x05 | ||
295 | |||
296 | /* interrupt the internal read loop, when blocking */ | ||
297 | #define DIBUSB_REQ_INTR_READ 0x06 | ||
298 | |||
299 | /* io control | ||
300 | * 0x07 cmd_byte param_bytes | ||
301 | * | ||
302 | * param_bytes can be up to 32 bytes | ||
303 | * | ||
304 | * cmd_byte function parameter name | ||
305 | * 0x00 power mode | ||
306 | * 0x00 sleep | ||
307 | * 0x01 wakeup | ||
308 | * | ||
309 | * 0x01 enable streaming | ||
310 | * 0x02 disable streaming | ||
311 | * | ||
312 | * | ||
313 | */ | ||
314 | #define DIBUSB_REQ_SET_IOCTL 0x07 | ||
315 | |||
316 | /* IOCTL commands */ | ||
317 | |||
318 | /* change the power mode in firmware */ | ||
319 | #define DIBUSB_IOCTL_CMD_POWER_MODE 0x00 | ||
320 | #define DIBUSB_IOCTL_POWER_SLEEP 0x00 | ||
321 | #define DIBUSB_IOCTL_POWER_WAKEUP 0x01 | ||
322 | |||
323 | /* modify streaming of the FX2 */ | ||
324 | #define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01 | ||
325 | #define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02 | ||
326 | |||
327 | #endif | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index d19301d90a..d6b7a9de47 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
36 | #include <linux/list.h> | 36 | #include <linux/list.h> |
37 | #include <linux/suspend.h> | 37 | #include <linux/suspend.h> |
38 | #include <linux/jiffies.h> | ||
38 | #include <asm/processor.h> | 39 | #include <asm/processor.h> |
39 | #include <asm/semaphore.h> | 40 | #include <asm/semaphore.h> |
40 | 41 | ||
@@ -327,7 +328,8 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe) | |||
327 | return 1; | 328 | return 1; |
328 | 329 | ||
329 | if (fepriv->dvbdev->writers == 1) | 330 | if (fepriv->dvbdev->writers == 1) |
330 | if (jiffies - fepriv->release_jiffies > dvb_shutdown_timeout * HZ) | 331 | if (time_after(jiffies, fepriv->release_jiffies + |
332 | dvb_shutdown_timeout * HZ)) | ||
331 | return 1; | 333 | return 1; |
332 | 334 | ||
333 | return 0; | 335 | return 0; |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig new file mode 100644 index 0000000000..8aa32f6e44 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -0,0 +1,99 @@ | |||
1 | config DVB_USB | ||
2 | tristate "Support for various USB DVB devices" | ||
3 | depends on DVB_CORE && USB | ||
4 | select FW_LOADER | ||
5 | help | ||
6 | By enabling this you will be able to choose the various USB 1.1 and | ||
7 | USB2.0 DVB devices. | ||
8 | |||
9 | Almost every USB device needs a firmware, please look into | ||
10 | <file:Documentation/dvb/README.dvb-usb> | ||
11 | |||
12 | Say Y if you own an USB DVB device. | ||
13 | |||
14 | config DVB_USB_DEBUG | ||
15 | bool "Enable extended debug support for all DVB-USB devices" | ||
16 | depends on DVB_USB | ||
17 | help | ||
18 | Say Y if you want to enable debuging. See modinfo dvb-usb (and the | ||
19 | appropriate drivers) for debug levels. | ||
20 | |||
21 | config DVB_USB_A800 | ||
22 | tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" | ||
23 | depends on DVB_USB | ||
24 | help | ||
25 | Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. | ||
26 | |||
27 | config DVB_USB_DIBUSB_MB | ||
28 | tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)" | ||
29 | depends on DVB_USB | ||
30 | help | ||
31 | Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by | ||
32 | DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator. | ||
33 | |||
34 | Devices supported by this driver: | ||
35 | TwinhanDTV USB-Ter (VP7041) | ||
36 | TwinhanDTV Magic Box (VP7041e) | ||
37 | KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0 | ||
38 | Hama DVB-T USB1.1-Box | ||
39 | DiBcom USB1.1 reference devices (non-public) | ||
40 | Ultima Electronic/Artec T1 USB TVBOX | ||
41 | Compro Videomate DVB-U2000 - DVB-T USB | ||
42 | Grandtec DVB-T USB | ||
43 | Avermedia AverTV DVBT USB1.1 | ||
44 | Artec T1 USB1.1 boxes | ||
45 | |||
46 | The VP7041 seems to be identical to "CTS Portable" (Chinese | ||
47 | Television System). | ||
48 | |||
49 | Say Y if you own such a device and want to use it. You should build it as | ||
50 | a module. | ||
51 | |||
52 | config DVB_USB_DIBUSB_MC | ||
53 | tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" | ||
54 | depends on DVB_USB | ||
55 | help | ||
56 | Support for 2.0 DVB-T receivers based on reference designs made by | ||
57 | DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator. | ||
58 | |||
59 | Devices supported by this driver: | ||
60 | DiBcom USB2.0 reference devices (non-public) | ||
61 | Artec T1 USB2.0 boxes | ||
62 | |||
63 | Say Y if you own such a device and want to use it. You should build it as | ||
64 | a module. | ||
65 | |||
66 | config DVB_USB_UMT_010 | ||
67 | tristate "HanfTek UMT-010 DVB-T USB2.0 support" | ||
68 | depends on DVB_USB | ||
69 | help | ||
70 | Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. | ||
71 | |||
72 | config DVB_USB_DIGITV | ||
73 | tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" | ||
74 | depends on DVB_USB | ||
75 | help | ||
76 | Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver. | ||
77 | |||
78 | config DVB_USB_VP7045 | ||
79 | tristate "TwinhanDTV Alpha/MagicBoxII and DNTV tinyUSB2 DVB-T USB2.0 support" | ||
80 | depends on DVB_USB | ||
81 | help | ||
82 | Say Y here to support the | ||
83 | TwinhanDTV Alpha (stick) (VP-7045), | ||
84 | TwinhanDTV MagicBox II (VP-7046) and | ||
85 | DigitalNow TinyUSB 2 DVB-t DVB-T USB2.0 receivers. | ||
86 | |||
87 | config DVB_USB_NOVA_T_USB2 | ||
88 | tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" | ||
89 | depends on DVB_USB | ||
90 | help | ||
91 | Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. | ||
92 | |||
93 | config DVB_USB_DTT200U | ||
94 | tristate "Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 support" | ||
95 | depends on DVB_USB | ||
96 | help | ||
97 | Say Y here to support the Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver. | ||
98 | |||
99 | The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan). | ||
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile new file mode 100644 index 0000000000..d65b50f9ab --- /dev/null +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -0,0 +1,30 @@ | |||
1 | dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o | ||
2 | obj-$(CONFIG_DVB_USB) += dvb-usb.o | ||
3 | |||
4 | dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o | ||
5 | obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o | ||
6 | |||
7 | dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o | ||
8 | obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o | ||
9 | |||
10 | dvb-usb-dibusb-common-objs = dibusb-common.o | ||
11 | |||
12 | dvb-usb-a800-objs = a800.o | ||
13 | obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o | ||
14 | |||
15 | dvb-usb-dibusb-mb-objs = dibusb-mb.o | ||
16 | obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o | ||
17 | |||
18 | dvb-usb-dibusb-mc-objs = dibusb-mc.o | ||
19 | obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o | ||
20 | |||
21 | dvb-usb-nova-t-usb2-objs = nova-t-usb2.o | ||
22 | obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o | ||
23 | |||
24 | dvb-usb-umt-010-objs = umt-010.o | ||
25 | obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o | ||
26 | |||
27 | dvb-usb-digitv-objs = digitv.o | ||
28 | obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o | ||
29 | |||
30 | EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | ||
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c new file mode 100644 index 0000000000..a354293560 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/a800.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T | ||
2 | * USB2.0 (A800) DVB-T receiver. | ||
3 | * | ||
4 | * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * Thanks to | ||
7 | * - AVerMedia who kindly provided information and | ||
8 | * - Glen Harris who suffered from my mistakes during development. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the Free | ||
12 | * Software Foundation, version 2. | ||
13 | * | ||
14 | * see Documentation/dvb/README.dvb-usb for more information | ||
15 | */ | ||
16 | #include "dibusb.h" | ||
17 | |||
18 | static int debug; | ||
19 | module_param(debug, int, 0644); | ||
20 | MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS); | ||
21 | #define deb_rc(args...) dprintk(debug,0x01,args) | ||
22 | |||
23 | static int a800_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
24 | { | ||
25 | /* do nothing for the AVerMedia */ | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | static struct dvb_usb_rc_key a800_rc_keys[] = { | ||
30 | { 0x02, 0x01, KEY_PROG1 }, /* SOURCE */ | ||
31 | { 0x02, 0x00, KEY_POWER }, /* POWER */ | ||
32 | { 0x02, 0x05, KEY_1 }, /* 1 */ | ||
33 | { 0x02, 0x06, KEY_2 }, /* 2 */ | ||
34 | { 0x02, 0x07, KEY_3 }, /* 3 */ | ||
35 | { 0x02, 0x09, KEY_4 }, /* 4 */ | ||
36 | { 0x02, 0x0a, KEY_5 }, /* 5 */ | ||
37 | { 0x02, 0x0b, KEY_6 }, /* 6 */ | ||
38 | { 0x02, 0x0d, KEY_7 }, /* 7 */ | ||
39 | { 0x02, 0x0e, KEY_8 }, /* 8 */ | ||
40 | { 0x02, 0x0f, KEY_9 }, /* 9 */ | ||
41 | { 0x02, 0x12, KEY_LEFT }, /* L / DISPLAY */ | ||
42 | { 0x02, 0x11, KEY_0 }, /* 0 */ | ||
43 | { 0x02, 0x13, KEY_RIGHT }, /* R / CH RTN */ | ||
44 | { 0x02, 0x17, KEY_PROG2 }, /* SNAP SHOT */ | ||
45 | { 0x02, 0x10, KEY_PROG3 }, /* 16-CH PREV */ | ||
46 | { 0x02, 0x03, KEY_CHANNELUP }, /* CH UP */ | ||
47 | { 0x02, 0x1e, KEY_VOLUMEDOWN }, /* VOL DOWN */ | ||
48 | { 0x02, 0x0c, KEY_ZOOM }, /* FULL SCREEN */ | ||
49 | { 0x02, 0x1f, KEY_VOLUMEUP }, /* VOL UP */ | ||
50 | { 0x02, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */ | ||
51 | { 0x02, 0x14, KEY_MUTE }, /* MUTE */ | ||
52 | { 0x02, 0x08, KEY_AUDIO }, /* AUDIO */ | ||
53 | { 0x02, 0x19, KEY_RECORD }, /* RECORD */ | ||
54 | { 0x02, 0x18, KEY_PLAY }, /* PLAY */ | ||
55 | { 0x02, 0x1b, KEY_STOP }, /* STOP */ | ||
56 | { 0x02, 0x1a, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */ | ||
57 | { 0x02, 0x1d, KEY_BACK }, /* << / RED */ | ||
58 | { 0x02, 0x1c, KEY_FORWARD }, /* >> / YELLOW */ | ||
59 | { 0x02, 0x03, KEY_TEXT }, /* TELETEXT */ | ||
60 | { 0x02, 0x01, KEY_FIRST }, /* |<< / GREEN */ | ||
61 | { 0x02, 0x00, KEY_LAST }, /* >>| / BLUE */ | ||
62 | { 0x02, 0x04, KEY_EPG }, /* EPG */ | ||
63 | { 0x02, 0x15, KEY_MENU }, /* MENU */ | ||
64 | }; | ||
65 | |||
66 | int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
67 | { | ||
68 | u8 key[5]; | ||
69 | if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0), | ||
70 | 0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5, | ||
71 | 2*HZ) != 5) | ||
72 | return -ENODEV; | ||
73 | |||
74 | /* call the universal NEC remote processor, to find out the key's state and event */ | ||
75 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | ||
76 | if (key[0] != 0) | ||
77 | deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | /* USB Driver stuff */ | ||
82 | static struct dvb_usb_properties a800_properties; | ||
83 | |||
84 | static int a800_probe(struct usb_interface *intf, | ||
85 | const struct usb_device_id *id) | ||
86 | { | ||
87 | return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE); | ||
88 | } | ||
89 | |||
90 | /* do not change the order of the ID table */ | ||
91 | static struct usb_device_id a800_table [] = { | ||
92 | /* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_COLD) }, | ||
93 | /* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_WARM) }, | ||
94 | { } /* Terminating entry */ | ||
95 | }; | ||
96 | MODULE_DEVICE_TABLE (usb, a800_table); | ||
97 | |||
98 | static struct dvb_usb_properties a800_properties = { | ||
99 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
100 | .pid_filter_count = 32, | ||
101 | |||
102 | .usb_ctrl = CYPRESS_FX2, | ||
103 | |||
104 | .firmware = "dvb-usb-avertv-a800-02.fw", | ||
105 | |||
106 | .size_of_priv = sizeof(struct dibusb_state), | ||
107 | |||
108 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
109 | .pid_filter = dibusb_pid_filter, | ||
110 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
111 | .power_ctrl = a800_power_ctrl, | ||
112 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | ||
113 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | ||
114 | |||
115 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
116 | .rc_key_map = a800_rc_keys, | ||
117 | .rc_key_map_size = ARRAY_SIZE(a800_rc_keys), | ||
118 | .rc_query = a800_rc_query, | ||
119 | |||
120 | .i2c_algo = &dibusb_i2c_algo, | ||
121 | |||
122 | .generic_bulk_ctrl_endpoint = 0x01, | ||
123 | /* parameter for the MPEG2-data transfer */ | ||
124 | .urb = { | ||
125 | .type = DVB_USB_BULK, | ||
126 | .count = 7, | ||
127 | .endpoint = 0x06, | ||
128 | .u = { | ||
129 | .bulk = { | ||
130 | .buffersize = 4096, | ||
131 | } | ||
132 | } | ||
133 | }, | ||
134 | |||
135 | .num_device_descs = 1, | ||
136 | .devices = { | ||
137 | { "AVerMedia AverTV DVB-T USB 2.0 (A800)", | ||
138 | { &a800_table[0], NULL }, | ||
139 | { &a800_table[1], NULL }, | ||
140 | }, | ||
141 | } | ||
142 | }; | ||
143 | |||
144 | static struct usb_driver a800_driver = { | ||
145 | .owner = THIS_MODULE, | ||
146 | .name = "AVerMedia AverTV DVB-T USB 2.0 (A800)", | ||
147 | .probe = a800_probe, | ||
148 | .disconnect = dvb_usb_device_exit, | ||
149 | .id_table = a800_table, | ||
150 | }; | ||
151 | |||
152 | /* module stuff */ | ||
153 | static int __init a800_module_init(void) | ||
154 | { | ||
155 | int result; | ||
156 | if ((result = usb_register(&a800_driver))) { | ||
157 | err("usb_register failed. Error number %d",result); | ||
158 | return result; | ||
159 | } | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static void __exit a800_module_exit(void) | ||
165 | { | ||
166 | /* deregister this driver from the USB subsystem */ | ||
167 | usb_deregister(&a800_driver); | ||
168 | } | ||
169 | |||
170 | module_init (a800_module_init); | ||
171 | module_exit (a800_module_exit); | ||
172 | |||
173 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
174 | MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)"); | ||
175 | MODULE_VERSION("1.0"); | ||
176 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c new file mode 100644 index 0000000000..63b626f70c --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c | |||
@@ -0,0 +1,272 @@ | |||
1 | /* Common methods for dibusb-based-receivers. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the Free | ||
7 | * Software Foundation, version 2. | ||
8 | * | ||
9 | * see Documentation/dvb/README.dvb-usb for more information | ||
10 | */ | ||
11 | #include "dibusb.h" | ||
12 | |||
13 | static int debug; | ||
14 | module_param(debug, int, 0644); | ||
15 | MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS); | ||
16 | MODULE_LICENSE("GPL"); | ||
17 | |||
18 | #define deb_info(args...) dprintk(debug,0x01,args) | ||
19 | |||
20 | /* common stuff used by the different dibusb modules */ | ||
21 | int dibusb_streaming_ctrl(struct dvb_usb_device *d, int onoff) | ||
22 | { | ||
23 | if (d->priv != NULL) { | ||
24 | struct dib_fe_xfer_ops *ops = d->priv; | ||
25 | if (ops->fifo_ctrl != NULL) | ||
26 | if (ops->fifo_ctrl(d->fe,onoff)) { | ||
27 | err("error while controlling the fifo of the demod."); | ||
28 | return -ENODEV; | ||
29 | } | ||
30 | } | ||
31 | return 0; | ||
32 | } | ||
33 | EXPORT_SYMBOL(dibusb_streaming_ctrl); | ||
34 | |||
35 | int dibusb_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff) | ||
36 | { | ||
37 | if (d->priv != NULL) { | ||
38 | struct dib_fe_xfer_ops *ops = d->priv; | ||
39 | if (d->pid_filtering && ops->pid_ctrl != NULL) | ||
40 | ops->pid_ctrl(d->fe,index,pid,onoff); | ||
41 | } | ||
42 | return 0; | ||
43 | } | ||
44 | EXPORT_SYMBOL(dibusb_pid_filter); | ||
45 | |||
46 | int dibusb_pid_filter_ctrl(struct dvb_usb_device *d, int onoff) | ||
47 | { | ||
48 | if (d->priv != NULL) { | ||
49 | struct dib_fe_xfer_ops *ops = d->priv; | ||
50 | if (ops->pid_parse != NULL) | ||
51 | if (ops->pid_parse(d->fe,onoff) < 0) | ||
52 | err("could not handle pid_parser"); | ||
53 | } | ||
54 | return 0; | ||
55 | } | ||
56 | EXPORT_SYMBOL(dibusb_pid_filter_ctrl); | ||
57 | |||
58 | int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
59 | { | ||
60 | u8 b[3]; | ||
61 | int ret; | ||
62 | b[0] = DIBUSB_REQ_SET_IOCTL; | ||
63 | b[1] = DIBUSB_IOCTL_CMD_POWER_MODE; | ||
64 | b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP; | ||
65 | ret = dvb_usb_generic_write(d,b,3); | ||
66 | msleep(10); | ||
67 | return ret; | ||
68 | } | ||
69 | EXPORT_SYMBOL(dibusb_power_ctrl); | ||
70 | |||
71 | int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff) | ||
72 | { | ||
73 | u8 b[2]; | ||
74 | b[0] = DIBUSB_REQ_SET_IOCTL; | ||
75 | b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM; | ||
76 | |||
77 | dvb_usb_generic_write(d,b,3); | ||
78 | |||
79 | return dibusb_streaming_ctrl(d,onoff); | ||
80 | } | ||
81 | EXPORT_SYMBOL(dibusb2_0_streaming_ctrl); | ||
82 | |||
83 | int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
84 | { | ||
85 | if (onoff) { | ||
86 | u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP }; | ||
87 | return dvb_usb_generic_write(d,b,3); | ||
88 | } else | ||
89 | return 0; | ||
90 | } | ||
91 | EXPORT_SYMBOL(dibusb2_0_power_ctrl); | ||
92 | |||
93 | static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
94 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
95 | { | ||
96 | u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */ | ||
97 | /* write only ? */ | ||
98 | int wo = (rbuf == NULL || rlen == 0), | ||
99 | len = 2 + wlen + (wo ? 0 : 2); | ||
100 | |||
101 | sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ; | ||
102 | sndbuf[1] = (addr << 1) | (wo ? 0 : 1); | ||
103 | |||
104 | memcpy(&sndbuf[2],wbuf,wlen); | ||
105 | |||
106 | if (!wo) { | ||
107 | sndbuf[wlen+2] = (rlen >> 8) & 0xff; | ||
108 | sndbuf[wlen+3] = rlen & 0xff; | ||
109 | } | ||
110 | |||
111 | return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0); | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * I2C master xfer function | ||
116 | */ | ||
117 | static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | ||
118 | { | ||
119 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
120 | int i; | ||
121 | |||
122 | if (down_interruptible(&d->i2c_sem) < 0) | ||
123 | return -EAGAIN; | ||
124 | |||
125 | if (num > 2) | ||
126 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
127 | |||
128 | for (i = 0; i < num; i++) { | ||
129 | /* write/read request */ | ||
130 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
131 | if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len, | ||
132 | msg[i+1].buf,msg[i+1].len) < 0) | ||
133 | break; | ||
134 | i++; | ||
135 | } else | ||
136 | if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0) | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | up(&d->i2c_sem); | ||
141 | return i; | ||
142 | } | ||
143 | |||
144 | static u32 dibusb_i2c_func(struct i2c_adapter *adapter) | ||
145 | { | ||
146 | return I2C_FUNC_I2C; | ||
147 | } | ||
148 | |||
149 | struct i2c_algorithm dibusb_i2c_algo = { | ||
150 | .name = "DiBcom USB I2C algorithm", | ||
151 | .id = I2C_ALGO_BIT, | ||
152 | .master_xfer = dibusb_i2c_xfer, | ||
153 | .functionality = dibusb_i2c_func, | ||
154 | }; | ||
155 | EXPORT_SYMBOL(dibusb_i2c_algo); | ||
156 | |||
157 | int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val) | ||
158 | { | ||
159 | u8 wbuf[1] = { offs }; | ||
160 | return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1); | ||
161 | } | ||
162 | EXPORT_SYMBOL(dibusb_read_eeprom_byte); | ||
163 | |||
164 | int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d) | ||
165 | { | ||
166 | struct dib3000_config demod_cfg; | ||
167 | struct dibusb_state *st = d->priv; | ||
168 | |||
169 | demod_cfg.pll_set = dvb_usb_pll_set_i2c; | ||
170 | demod_cfg.pll_init = dvb_usb_pll_init_i2c; | ||
171 | |||
172 | for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++) | ||
173 | if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) { | ||
174 | d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl; | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | return -ENODEV; | ||
179 | } | ||
180 | EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach); | ||
181 | |||
182 | int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d) | ||
183 | { | ||
184 | d->pll_addr = 0x60; | ||
185 | d->pll_desc = &dvb_pll_env57h1xd5; | ||
186 | return 0; | ||
187 | } | ||
188 | EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach); | ||
189 | |||
190 | /* | ||
191 | * common remote control stuff | ||
192 | */ | ||
193 | struct dvb_usb_rc_key dibusb_rc_keys[] = { | ||
194 | /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */ | ||
195 | { 0x00, 0x16, KEY_POWER }, | ||
196 | { 0x00, 0x10, KEY_MUTE }, | ||
197 | { 0x00, 0x03, KEY_1 }, | ||
198 | { 0x00, 0x01, KEY_2 }, | ||
199 | { 0x00, 0x06, KEY_3 }, | ||
200 | { 0x00, 0x09, KEY_4 }, | ||
201 | { 0x00, 0x1d, KEY_5 }, | ||
202 | { 0x00, 0x1f, KEY_6 }, | ||
203 | { 0x00, 0x0d, KEY_7 }, | ||
204 | { 0x00, 0x19, KEY_8 }, | ||
205 | { 0x00, 0x1b, KEY_9 }, | ||
206 | { 0x00, 0x15, KEY_0 }, | ||
207 | { 0x00, 0x05, KEY_CHANNELUP }, | ||
208 | { 0x00, 0x02, KEY_CHANNELDOWN }, | ||
209 | { 0x00, 0x1e, KEY_VOLUMEUP }, | ||
210 | { 0x00, 0x0a, KEY_VOLUMEDOWN }, | ||
211 | { 0x00, 0x11, KEY_RECORD }, | ||
212 | { 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */ | ||
213 | { 0x00, 0x14, KEY_PLAY }, | ||
214 | { 0x00, 0x1a, KEY_STOP }, | ||
215 | { 0x00, 0x40, KEY_REWIND }, | ||
216 | { 0x00, 0x12, KEY_FASTFORWARD }, | ||
217 | { 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */ | ||
218 | { 0x00, 0x4c, KEY_PAUSE }, | ||
219 | { 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */ | ||
220 | { 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ | ||
221 | /* additional keys TwinHan VisionPlus, the Artec seemingly not have */ | ||
222 | { 0x00, 0x0c, KEY_CANCEL }, /* Cancel */ | ||
223 | { 0x00, 0x1c, KEY_EPG }, /* EPG */ | ||
224 | { 0x00, 0x00, KEY_TAB }, /* Tab */ | ||
225 | { 0x00, 0x48, KEY_INFO }, /* Preview */ | ||
226 | { 0x00, 0x04, KEY_LIST }, /* RecordList */ | ||
227 | { 0x00, 0x0f, KEY_TEXT }, /* Teletext */ | ||
228 | /* Key codes for the KWorld/ADSTech/JetWay remote. */ | ||
229 | { 0x86, 0x12, KEY_POWER }, | ||
230 | { 0x86, 0x0f, KEY_SELECT }, /* source */ | ||
231 | { 0x86, 0x0c, KEY_UNKNOWN }, /* scan */ | ||
232 | { 0x86, 0x0b, KEY_EPG }, | ||
233 | { 0x86, 0x10, KEY_MUTE }, | ||
234 | { 0x86, 0x01, KEY_1 }, | ||
235 | { 0x86, 0x02, KEY_2 }, | ||
236 | { 0x86, 0x03, KEY_3 }, | ||
237 | { 0x86, 0x04, KEY_4 }, | ||
238 | { 0x86, 0x05, KEY_5 }, | ||
239 | { 0x86, 0x06, KEY_6 }, | ||
240 | { 0x86, 0x07, KEY_7 }, | ||
241 | { 0x86, 0x08, KEY_8 }, | ||
242 | { 0x86, 0x09, KEY_9 }, | ||
243 | { 0x86, 0x0a, KEY_0 }, | ||
244 | { 0x86, 0x18, KEY_ZOOM }, | ||
245 | { 0x86, 0x1c, KEY_UNKNOWN }, /* preview */ | ||
246 | { 0x86, 0x13, KEY_UNKNOWN }, /* snap */ | ||
247 | { 0x86, 0x00, KEY_UNDO }, | ||
248 | { 0x86, 0x1d, KEY_RECORD }, | ||
249 | { 0x86, 0x0d, KEY_STOP }, | ||
250 | { 0x86, 0x0e, KEY_PAUSE }, | ||
251 | { 0x86, 0x16, KEY_PLAY }, | ||
252 | { 0x86, 0x11, KEY_BACK }, | ||
253 | { 0x86, 0x19, KEY_FORWARD }, | ||
254 | { 0x86, 0x14, KEY_UNKNOWN }, /* pip */ | ||
255 | { 0x86, 0x15, KEY_ESC }, | ||
256 | { 0x86, 0x1a, KEY_UP }, | ||
257 | { 0x86, 0x1e, KEY_DOWN }, | ||
258 | { 0x86, 0x1f, KEY_LEFT }, | ||
259 | { 0x86, 0x1b, KEY_RIGHT }, | ||
260 | }; | ||
261 | EXPORT_SYMBOL(dibusb_rc_keys); | ||
262 | |||
263 | int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
264 | { | ||
265 | u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE; | ||
266 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); | ||
267 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | ||
268 | if (key[0] != 0) | ||
269 | deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
270 | return 0; | ||
271 | } | ||
272 | EXPORT_SYMBOL(dibusb_rc_query); | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c new file mode 100644 index 0000000000..a0ffbb59fa --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c | |||
@@ -0,0 +1,316 @@ | |||
1 | /* DVB USB compliant linux driver for mobile DVB-T USB devices based on | ||
2 | * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B) | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * based on GPL code from DiBcom, which has | ||
7 | * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation, version 2. | ||
12 | * | ||
13 | * see Documentation/dvb/README.dvb-usb for more information | ||
14 | */ | ||
15 | #include "dibusb.h" | ||
16 | |||
17 | static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d) | ||
18 | { | ||
19 | struct dib3000_config demod_cfg; | ||
20 | struct dibusb_state *st = d->priv; | ||
21 | |||
22 | demod_cfg.demod_address = 0x8; | ||
23 | demod_cfg.pll_set = dvb_usb_pll_set_i2c; | ||
24 | demod_cfg.pll_init = dvb_usb_pll_init_i2c; | ||
25 | |||
26 | if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) | ||
27 | return -ENODEV; | ||
28 | |||
29 | d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl; | ||
30 | |||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | /* some of the dibusb 1.1 device aren't equipped with the default tuner | ||
35 | * (Thomson Cable), but with a Panasonic ENV77H11D5. This function figures | ||
36 | * this out. */ | ||
37 | static int dibusb_dib3000mb_tuner_attach (struct dvb_usb_device *d) | ||
38 | { | ||
39 | u8 b[2] = { 0,0 }, b2[1]; | ||
40 | int ret = 0; | ||
41 | struct i2c_msg msg[2] = { | ||
42 | { .flags = 0, .buf = b, .len = 2 }, | ||
43 | { .flags = I2C_M_RD, .buf = b2, .len = 1 }, | ||
44 | }; | ||
45 | |||
46 | /* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */ | ||
47 | msg[0].addr = msg[1].addr = 0x60; | ||
48 | |||
49 | if (d->tuner_pass_ctrl) | ||
50 | d->tuner_pass_ctrl(d->fe,1,msg[0].addr); | ||
51 | |||
52 | if (i2c_transfer (&d->i2c_adap, msg, 2) != 2) { | ||
53 | err("tuner i2c write failed."); | ||
54 | ret = -EREMOTEIO; | ||
55 | } | ||
56 | |||
57 | if (d->tuner_pass_ctrl) | ||
58 | d->tuner_pass_ctrl(d->fe,0,msg[0].addr); | ||
59 | |||
60 | if (b2[0] == 0xfe) { | ||
61 | info("this device has the Thomson Cable onboard. Which is default."); | ||
62 | d->pll_addr = 0x61; | ||
63 | d->pll_desc = &dvb_pll_tua6010xs; | ||
64 | } else { | ||
65 | u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab }; | ||
66 | info("this device has the Panasonic ENV77H11D5 onboard."); | ||
67 | d->pll_addr = 0x60; | ||
68 | memcpy(d->pll_init,bpll,4); | ||
69 | d->pll_desc = &dvb_pll_tda665x; | ||
70 | } | ||
71 | |||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | /* USB Driver stuff */ | ||
76 | static struct dvb_usb_properties dibusb1_1_properties; | ||
77 | static struct dvb_usb_properties dibusb1_1_an2235_properties; | ||
78 | static struct dvb_usb_properties dibusb2_0b_properties; | ||
79 | |||
80 | static int dibusb_probe(struct usb_interface *intf, | ||
81 | const struct usb_device_id *id) | ||
82 | { | ||
83 | if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE) == 0 || | ||
84 | dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE) == 0 || | ||
85 | dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE) == 0) | ||
86 | return 0; | ||
87 | |||
88 | return -EINVAL; | ||
89 | } | ||
90 | |||
91 | /* do not change the order of the ID table */ | ||
92 | static struct usb_device_id dibusb_dib3000mb_table [] = { | ||
93 | /* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_AVERMEDIA_DVBT_USB_COLD)}, | ||
94 | /* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_AVERMEDIA_DVBT_USB_WARM)}, | ||
95 | /* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) }, | ||
96 | /* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) }, | ||
97 | /* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) }, | ||
98 | /* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) }, | ||
99 | /* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) }, | ||
100 | /* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) }, | ||
101 | /* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) }, | ||
102 | /* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) }, | ||
103 | /* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) }, | ||
104 | /* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) }, | ||
105 | /* 12 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) }, | ||
106 | /* 13 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) }, | ||
107 | /* 14 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) }, | ||
108 | /* 15 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_COLD) }, | ||
109 | /* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) }, | ||
110 | /* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) }, | ||
111 | /* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) }, | ||
112 | /* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) }, | ||
113 | /* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) }, | ||
114 | /* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) }, | ||
115 | /* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) }, | ||
116 | /* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) }, | ||
117 | /* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) }, | ||
118 | { } /* Terminating entry */ | ||
119 | }; | ||
120 | MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table); | ||
121 | |||
122 | static struct dvb_usb_properties dibusb1_1_properties = { | ||
123 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
124 | .pid_filter_count = 16, | ||
125 | |||
126 | .usb_ctrl = CYPRESS_AN2135, | ||
127 | |||
128 | .firmware = "dvb-usb-dibusb-5.0.0.11.fw", | ||
129 | |||
130 | .size_of_priv = sizeof(struct dibusb_state), | ||
131 | |||
132 | .streaming_ctrl = dibusb_streaming_ctrl, | ||
133 | .pid_filter = dibusb_pid_filter, | ||
134 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
135 | .power_ctrl = dibusb_power_ctrl, | ||
136 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | ||
137 | .tuner_attach = dibusb_dib3000mb_tuner_attach, | ||
138 | |||
139 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
140 | .rc_key_map = dibusb_rc_keys, | ||
141 | .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */ | ||
142 | .rc_query = dibusb_rc_query, | ||
143 | |||
144 | .i2c_algo = &dibusb_i2c_algo, | ||
145 | |||
146 | .generic_bulk_ctrl_endpoint = 0x01, | ||
147 | /* parameter for the MPEG2-data transfer */ | ||
148 | .urb = { | ||
149 | .type = DVB_USB_BULK, | ||
150 | .count = 7, | ||
151 | .endpoint = 0x02, | ||
152 | .u = { | ||
153 | .bulk = { | ||
154 | .buffersize = 4096, | ||
155 | } | ||
156 | } | ||
157 | }, | ||
158 | |||
159 | .num_device_descs = 8, | ||
160 | .devices = { | ||
161 | { "AVerMedia AverTV DVBT USB1.1", | ||
162 | { &dibusb_dib3000mb_table[0], NULL }, | ||
163 | { &dibusb_dib3000mb_table[1], NULL }, | ||
164 | }, | ||
165 | { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)", | ||
166 | { &dibusb_dib3000mb_table[2], &dibusb_dib3000mb_table[4], NULL}, | ||
167 | { &dibusb_dib3000mb_table[3], NULL }, | ||
168 | }, | ||
169 | { "DiBcom USB1.1 DVB-T reference design (MOD3000)", | ||
170 | { &dibusb_dib3000mb_table[5], NULL }, | ||
171 | { &dibusb_dib3000mb_table[6], NULL }, | ||
172 | }, | ||
173 | { "KWorld V-Stream XPERT DTV - DVB-T USB1.1", | ||
174 | { &dibusb_dib3000mb_table[7], NULL }, | ||
175 | { &dibusb_dib3000mb_table[8], NULL }, | ||
176 | }, | ||
177 | { "Grandtec USB1.1 DVB-T", | ||
178 | { &dibusb_dib3000mb_table[9], &dibusb_dib3000mb_table[11], NULL }, | ||
179 | { &dibusb_dib3000mb_table[10], &dibusb_dib3000mb_table[12], NULL }, | ||
180 | }, | ||
181 | { "Unkown USB1.1 DVB-T device ???? please report the name to the author", | ||
182 | { &dibusb_dib3000mb_table[13], NULL }, | ||
183 | { &dibusb_dib3000mb_table[14], NULL }, | ||
184 | }, | ||
185 | { "TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device", | ||
186 | { &dibusb_dib3000mb_table[15], &dibusb_dib3000mb_table[17], NULL}, | ||
187 | { &dibusb_dib3000mb_table[16], &dibusb_dib3000mb_table[18], NULL}, | ||
188 | }, | ||
189 | { "Artec T1 USB1.1 TVBOX with AN2135", | ||
190 | { &dibusb_dib3000mb_table[19], NULL }, | ||
191 | { &dibusb_dib3000mb_table[20], NULL }, | ||
192 | }, | ||
193 | } | ||
194 | }; | ||
195 | |||
196 | static struct dvb_usb_properties dibusb1_1_an2235_properties = { | ||
197 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
198 | .usb_ctrl = CYPRESS_AN2235, | ||
199 | |||
200 | .firmware = "dvb-usb-dibusb-an2235-01.fw", | ||
201 | |||
202 | .size_of_priv = sizeof(struct dibusb_state), | ||
203 | |||
204 | .streaming_ctrl = dibusb_streaming_ctrl, | ||
205 | .pid_filter = dibusb_pid_filter, | ||
206 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
207 | .power_ctrl = dibusb_power_ctrl, | ||
208 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | ||
209 | .tuner_attach = dibusb_dib3000mb_tuner_attach, | ||
210 | |||
211 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
212 | .rc_key_map = dibusb_rc_keys, | ||
213 | .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */ | ||
214 | .rc_query = dibusb_rc_query, | ||
215 | |||
216 | .i2c_algo = &dibusb_i2c_algo, | ||
217 | |||
218 | .generic_bulk_ctrl_endpoint = 0x01, | ||
219 | /* parameter for the MPEG2-data transfer */ | ||
220 | .urb = { | ||
221 | .type = DVB_USB_BULK, | ||
222 | .count = 7, | ||
223 | .endpoint = 0x02, | ||
224 | .u = { | ||
225 | .bulk = { | ||
226 | .buffersize = 4096, | ||
227 | } | ||
228 | } | ||
229 | }, | ||
230 | |||
231 | .num_device_descs = 1, | ||
232 | .devices = { | ||
233 | { "Artec T1 USB1.1 TVBOX with AN2235", | ||
234 | { &dibusb_dib3000mb_table[20], NULL }, | ||
235 | { &dibusb_dib3000mb_table[21], NULL }, | ||
236 | }, | ||
237 | } | ||
238 | }; | ||
239 | |||
240 | static struct dvb_usb_properties dibusb2_0b_properties = { | ||
241 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
242 | .usb_ctrl = CYPRESS_FX2, | ||
243 | |||
244 | .firmware = "dvb-usb-adstech-usb2-01.fw", | ||
245 | |||
246 | .size_of_priv = sizeof(struct dibusb_state), | ||
247 | |||
248 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
249 | .pid_filter = dibusb_pid_filter, | ||
250 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
251 | .power_ctrl = dibusb2_0_power_ctrl, | ||
252 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | ||
253 | .tuner_attach = dibusb_dib3000mb_tuner_attach, | ||
254 | |||
255 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
256 | .rc_key_map = dibusb_rc_keys, | ||
257 | .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */ | ||
258 | .rc_query = dibusb_rc_query, | ||
259 | |||
260 | .i2c_algo = &dibusb_i2c_algo, | ||
261 | |||
262 | .generic_bulk_ctrl_endpoint = 0x01, | ||
263 | /* parameter for the MPEG2-data transfer */ | ||
264 | .urb = { | ||
265 | .type = DVB_USB_BULK, | ||
266 | .count = 7, | ||
267 | .endpoint = 0x06, | ||
268 | .u = { | ||
269 | .bulk = { | ||
270 | .buffersize = 4096, | ||
271 | } | ||
272 | } | ||
273 | }, | ||
274 | |||
275 | .num_device_descs = 2, | ||
276 | .devices = { | ||
277 | { "KWorld/ADSTech Instant DVB-T USB 2.0", | ||
278 | { &dibusb_dib3000mb_table[23], NULL }, | ||
279 | { &dibusb_dib3000mb_table[24], NULL }, /* device ID with default DIBUSB2_0-firmware */ | ||
280 | }, | ||
281 | } | ||
282 | }; | ||
283 | |||
284 | static struct usb_driver dibusb_driver = { | ||
285 | .owner = THIS_MODULE, | ||
286 | .name = "DiBcom based USB DVB-T devices (DiB3000M-B based)", | ||
287 | .probe = dibusb_probe, | ||
288 | .disconnect = dvb_usb_device_exit, | ||
289 | .id_table = dibusb_dib3000mb_table, | ||
290 | }; | ||
291 | |||
292 | /* module stuff */ | ||
293 | static int __init dibusb_module_init(void) | ||
294 | { | ||
295 | int result; | ||
296 | if ((result = usb_register(&dibusb_driver))) { | ||
297 | err("usb_register failed. Error number %d",result); | ||
298 | return result; | ||
299 | } | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static void __exit dibusb_module_exit(void) | ||
305 | { | ||
306 | /* deregister this driver from the USB subsystem */ | ||
307 | usb_deregister(&dibusb_driver); | ||
308 | } | ||
309 | |||
310 | module_init (dibusb_module_init); | ||
311 | module_exit (dibusb_module_exit); | ||
312 | |||
313 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
314 | MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)"); | ||
315 | MODULE_VERSION("1.0"); | ||
316 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c new file mode 100644 index 0000000000..aad8ed3fe0 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* DVB USB compliant linux driver for mobile DVB-T USB devices based on | ||
2 | * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P) | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * based on GPL code from DiBcom, which has | ||
7 | * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation, version 2. | ||
12 | * | ||
13 | * see Documentation/dvb/README.dvb-usb for more information | ||
14 | */ | ||
15 | #include "dibusb.h" | ||
16 | |||
17 | /* USB Driver stuff */ | ||
18 | static struct dvb_usb_properties dibusb_mc_properties; | ||
19 | |||
20 | static int dibusb_mc_probe(struct usb_interface *intf, | ||
21 | const struct usb_device_id *id) | ||
22 | { | ||
23 | return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE); | ||
24 | } | ||
25 | |||
26 | /* do not change the order of the ID table */ | ||
27 | static struct usb_device_id dibusb_dib3000mc_table [] = { | ||
28 | /* 00 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) }, | ||
29 | /* 01 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) }, | ||
30 | /* 02 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, | ||
31 | { } /* Terminating entry */ | ||
32 | }; | ||
33 | MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table); | ||
34 | |||
35 | static struct dvb_usb_properties dibusb_mc_properties = { | ||
36 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
37 | .pid_filter_count = 32, | ||
38 | |||
39 | .usb_ctrl = CYPRESS_FX2, | ||
40 | .firmware = "dvb-usb-dibusb-6.0.0.8.fw", | ||
41 | |||
42 | .size_of_priv = sizeof(struct dibusb_state), | ||
43 | |||
44 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
45 | .pid_filter = dibusb_pid_filter, | ||
46 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
47 | .power_ctrl = dibusb2_0_power_ctrl, | ||
48 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | ||
49 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | ||
50 | |||
51 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
52 | .rc_key_map = dibusb_rc_keys, | ||
53 | .rc_key_map_size = 63, /* FIXME */ | ||
54 | .rc_query = dibusb_rc_query, | ||
55 | |||
56 | .i2c_algo = &dibusb_i2c_algo, | ||
57 | |||
58 | .generic_bulk_ctrl_endpoint = 0x01, | ||
59 | /* parameter for the MPEG2-data transfer */ | ||
60 | .urb = { | ||
61 | .type = DVB_USB_BULK, | ||
62 | .count = 7, | ||
63 | .endpoint = 0x06, | ||
64 | .u = { | ||
65 | .bulk = { | ||
66 | .buffersize = 4096, | ||
67 | } | ||
68 | } | ||
69 | }, | ||
70 | |||
71 | .num_device_descs = 2, | ||
72 | .devices = { | ||
73 | { "DiBcom USB2.0 DVB-T reference design (MOD3000P)", | ||
74 | { &dibusb_dib3000mc_table[0], NULL }, | ||
75 | { &dibusb_dib3000mc_table[1], NULL }, | ||
76 | }, | ||
77 | { "Artec T1 USB2.0 TVBOX (please report the warm ID)", | ||
78 | { &dibusb_dib3000mc_table[2], NULL }, | ||
79 | { NULL }, | ||
80 | }, | ||
81 | } | ||
82 | }; | ||
83 | |||
84 | static struct usb_driver dibusb_mc_driver = { | ||
85 | .owner = THIS_MODULE, | ||
86 | .name = "DiBcom based USB2.0 DVB-T (DiB3000M-C/P based) devices", | ||
87 | .probe = dibusb_mc_probe, | ||
88 | .disconnect = dvb_usb_device_exit, | ||
89 | .id_table = dibusb_dib3000mc_table, | ||
90 | }; | ||
91 | |||
92 | /* module stuff */ | ||
93 | static int __init dibusb_mc_module_init(void) | ||
94 | { | ||
95 | int result; | ||
96 | if ((result = usb_register(&dibusb_mc_driver))) { | ||
97 | err("usb_register failed. Error number %d",result); | ||
98 | return result; | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static void __exit dibusb_mc_module_exit(void) | ||
105 | { | ||
106 | /* deregister this driver from the USB subsystem */ | ||
107 | usb_deregister(&dibusb_mc_driver); | ||
108 | } | ||
109 | |||
110 | module_init (dibusb_mc_module_init); | ||
111 | module_exit (dibusb_mc_module_exit); | ||
112 | |||
113 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
114 | MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices"); | ||
115 | MODULE_VERSION("1.0"); | ||
116 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h new file mode 100644 index 0000000000..6611f62977 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb.h | |||
@@ -0,0 +1,122 @@ | |||
1 | /* Header file for all dibusb-based-receivers. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the Free | ||
7 | * Software Foundation, version 2. | ||
8 | * | ||
9 | * see Documentation/dvb/README.dvb-usb for more information | ||
10 | */ | ||
11 | #ifndef _DVB_USB_DIBUSB_H_ | ||
12 | #define _DVB_USB_DIBUSB_H_ | ||
13 | |||
14 | #define DVB_USB_LOG_PREFIX "dibusb" | ||
15 | #include "dvb-usb.h" | ||
16 | |||
17 | #include "dib3000.h" | ||
18 | |||
19 | /* | ||
20 | * protocol of all dibusb related devices | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * bulk msg to/from endpoint 0x01 | ||
25 | * | ||
26 | * general structure: | ||
27 | * request_byte parameter_bytes | ||
28 | */ | ||
29 | |||
30 | #define DIBUSB_REQ_START_READ 0x00 | ||
31 | #define DIBUSB_REQ_START_DEMOD 0x01 | ||
32 | |||
33 | /* | ||
34 | * i2c read | ||
35 | * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word | ||
36 | * bulk read: byte_buffer (length_word bytes) | ||
37 | */ | ||
38 | #define DIBUSB_REQ_I2C_READ 0x02 | ||
39 | |||
40 | /* | ||
41 | * i2c write | ||
42 | * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes | ||
43 | */ | ||
44 | #define DIBUSB_REQ_I2C_WRITE 0x03 | ||
45 | |||
46 | /* | ||
47 | * polling the value of the remote control | ||
48 | * bulk write: 0x04 | ||
49 | * bulk read: byte_buffer (5 bytes) | ||
50 | */ | ||
51 | #define DIBUSB_REQ_POLL_REMOTE 0x04 | ||
52 | |||
53 | /* additional status values for Hauppauge Remote Control Protocol */ | ||
54 | #define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED 0x01 | ||
55 | #define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY 0x03 | ||
56 | |||
57 | /* streaming mode: | ||
58 | * bulk write: 0x05 mode_byte | ||
59 | * | ||
60 | * mode_byte is mostly 0x00 | ||
61 | */ | ||
62 | #define DIBUSB_REQ_SET_STREAMING_MODE 0x05 | ||
63 | |||
64 | /* interrupt the internal read loop, when blocking */ | ||
65 | #define DIBUSB_REQ_INTR_READ 0x06 | ||
66 | |||
67 | /* io control | ||
68 | * 0x07 cmd_byte param_bytes | ||
69 | * | ||
70 | * param_bytes can be up to 32 bytes | ||
71 | * | ||
72 | * cmd_byte function parameter name | ||
73 | * 0x00 power mode | ||
74 | * 0x00 sleep | ||
75 | * 0x01 wakeup | ||
76 | * | ||
77 | * 0x01 enable streaming | ||
78 | * 0x02 disable streaming | ||
79 | * | ||
80 | * | ||
81 | */ | ||
82 | #define DIBUSB_REQ_SET_IOCTL 0x07 | ||
83 | |||
84 | /* IOCTL commands */ | ||
85 | |||
86 | /* change the power mode in firmware */ | ||
87 | #define DIBUSB_IOCTL_CMD_POWER_MODE 0x00 | ||
88 | #define DIBUSB_IOCTL_POWER_SLEEP 0x00 | ||
89 | #define DIBUSB_IOCTL_POWER_WAKEUP 0x01 | ||
90 | |||
91 | /* modify streaming of the FX2 */ | ||
92 | #define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01 | ||
93 | #define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02 | ||
94 | |||
95 | struct dibusb_state { | ||
96 | struct dib_fe_xfer_ops ops; | ||
97 | |||
98 | /* for RC5 remote control */ | ||
99 | int old_toggle; | ||
100 | int last_repeat_count; | ||
101 | }; | ||
102 | |||
103 | extern struct i2c_algorithm dibusb_i2c_algo; | ||
104 | |||
105 | extern int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *); | ||
106 | extern int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *); | ||
107 | |||
108 | extern int dibusb_streaming_ctrl(struct dvb_usb_device *, int); | ||
109 | extern int dibusb_pid_filter(struct dvb_usb_device *, int, u16, int); | ||
110 | extern int dibusb_pid_filter_ctrl(struct dvb_usb_device *, int); | ||
111 | extern int dibusb_power_ctrl(struct dvb_usb_device *, int); | ||
112 | extern int dibusb2_0_streaming_ctrl(struct dvb_usb_device *, int); | ||
113 | extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int); | ||
114 | |||
115 | #define DEFAULT_RC_INTERVAL 150 | ||
116 | //#define DEFAULT_RC_INTERVAL 100000 | ||
117 | |||
118 | extern struct dvb_usb_rc_key dibusb_rc_keys[]; | ||
119 | extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *); | ||
120 | extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *); | ||
121 | |||
122 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c new file mode 100644 index 0000000000..5acf3fde95 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/digitv.c | |||
@@ -0,0 +1,282 @@ | |||
1 | /* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0 | ||
2 | * receiver | ||
3 | * | ||
4 | * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) and | ||
5 | * Allan Third (allan.third@cs.man.ac.uk) | ||
6 | * | ||
7 | * partly based on the SDK published by Nebula Electronics (TODO do we want this line ?) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation, version 2. | ||
12 | * | ||
13 | * see Documentation/dvb/README.dvb-usb for more information | ||
14 | */ | ||
15 | #include "digitv.h" | ||
16 | |||
17 | #include "mt352.h" | ||
18 | #include "nxt6000.h" | ||
19 | |||
20 | /* debug */ | ||
21 | int dvb_usb_digitv_debug; | ||
22 | module_param_named(debug,dvb_usb_digitv_debug, int, 0644); | ||
23 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | ||
24 | |||
25 | static int digitv_ctrl_msg(struct dvb_usb_device *d, | ||
26 | u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
27 | { | ||
28 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
29 | u8 sndbuf[7],rcvbuf[7]; | ||
30 | memset(sndbuf,0,7); memset(rcvbuf,0,7); | ||
31 | |||
32 | sndbuf[0] = cmd; | ||
33 | sndbuf[1] = vv; | ||
34 | sndbuf[2] = wo ? wlen : rlen; | ||
35 | |||
36 | if (!wo) { | ||
37 | memcpy(&sndbuf[3],wbuf,wlen); | ||
38 | dvb_usb_generic_write(d,sndbuf,7); | ||
39 | } else { | ||
40 | dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10); | ||
41 | memcpy(&rbuf,&rcvbuf[3],rlen); | ||
42 | } | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | /* I2C */ | ||
47 | static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | ||
48 | { | ||
49 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
50 | int i; | ||
51 | |||
52 | if (down_interruptible(&d->i2c_sem) < 0) | ||
53 | return -EAGAIN; | ||
54 | |||
55 | if (num > 2) | ||
56 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
57 | |||
58 | for (i = 0; i < num; i++) { | ||
59 | /* write/read request */ | ||
60 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
61 | if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0, | ||
62 | msg[i+1].buf,msg[i+1].len) < 0) | ||
63 | break; | ||
64 | i++; | ||
65 | } else | ||
66 | if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0], | ||
67 | &msg[i].buf[1],msg[i].len-1,NULL,0) < 0) | ||
68 | break; | ||
69 | } | ||
70 | |||
71 | up(&d->i2c_sem); | ||
72 | return i; | ||
73 | } | ||
74 | |||
75 | static u32 digitv_i2c_func(struct i2c_adapter *adapter) | ||
76 | { | ||
77 | return I2C_FUNC_I2C; | ||
78 | } | ||
79 | |||
80 | static struct i2c_algorithm digitv_i2c_algo = { | ||
81 | .name = "Nebula DigiTV USB I2C algorithm", | ||
82 | .id = I2C_ALGO_BIT, | ||
83 | .master_xfer = digitv_i2c_xfer, | ||
84 | .functionality = digitv_i2c_func, | ||
85 | }; | ||
86 | |||
87 | /* Callbacks for DVB USB */ | ||
88 | static int digitv_identify_state (struct usb_device *udev, struct | ||
89 | dvb_usb_properties *props, struct dvb_usb_device_description **desc, | ||
90 | int *cold) | ||
91 | { | ||
92 | *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0; | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int digitv_mt352_demod_init(struct dvb_frontend *fe) | ||
97 | { | ||
98 | static u8 mt352_clock_config[] = { 0x89, 0x38, 0x2d }; | ||
99 | static u8 mt352_reset[] = { 0x50, 0x80 }; | ||
100 | static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 }; | ||
101 | |||
102 | static u8 mt352_agc_cfg[] = { 0x68, 0xa0 }; | ||
103 | static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0xa0 }; | ||
104 | static u8 mt352_acq_ctl[] = { 0x53, 0x50 }; | ||
105 | static u8 mt352_agc_target[] = { 0x67, 0x20 }; | ||
106 | |||
107 | static u8 mt352_rs_err_per[] = { 0x7c, 0x00, 0x01 }; | ||
108 | static u8 mt352_snr_select[] = { 0x79, 0x00, 0x20 }; | ||
109 | |||
110 | static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x05 }; | ||
111 | |||
112 | static u8 mt352_scan_ctl[] = { 0x88, 0x0f }; | ||
113 | static u8 mt352_capt_range[] = { 0x75, 0x32 }; | ||
114 | |||
115 | mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); | ||
116 | mt352_write(fe, mt352_reset, sizeof(mt352_reset)); | ||
117 | msleep(1); | ||
118 | mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio)); | ||
119 | |||
120 | mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); | ||
121 | mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); | ||
122 | mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl)); | ||
123 | mt352_write(fe, mt352_agc_target, sizeof(mt352_agc_target)); | ||
124 | |||
125 | |||
126 | mt352_write(fe, mt352_rs_err_per, sizeof(mt352_rs_err_per)); | ||
127 | mt352_write(fe, mt352_snr_select, sizeof(mt352_snr_select)); | ||
128 | |||
129 | mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1)); | ||
130 | |||
131 | mt352_write(fe, mt352_scan_ctl, sizeof(mt352_scan_ctl)); | ||
132 | mt352_write(fe, mt352_capt_range, sizeof(mt352_capt_range)); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static struct mt352_config digitv_mt352_config = { | ||
138 | .demod_address = 0x0, /* ignored by the digitv anyway */ | ||
139 | .demod_init = digitv_mt352_demod_init, | ||
140 | .pll_set = NULL, /* TODO */ | ||
141 | }; | ||
142 | |||
143 | static struct nxt6000_config digitv_nxt6000_config = { | ||
144 | .demod_address = 0x0, /* ignored by the digitv anyway */ | ||
145 | .clock_inversion = 0x0, | ||
146 | |||
147 | .pll_init = NULL, | ||
148 | .pll_set = NULL, | ||
149 | }; | ||
150 | |||
151 | static int digitv_frontend_attach(struct dvb_usb_device *d) | ||
152 | { | ||
153 | if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) == NULL) | ||
154 | return 0; | ||
155 | if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) == NULL) { | ||
156 | |||
157 | warn("nxt6000 support is not done yet, in fact you are one of the first " | ||
158 | "person who wants to use this device in Linux. Please report to " | ||
159 | "linux-dvb@linuxtv.org"); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | return -EIO; | ||
164 | } | ||
165 | |||
166 | static struct dvb_usb_rc_key digitv_rc_keys[] = { | ||
167 | { 0x00, 0x16, KEY_POWER }, /* dummy key */ | ||
168 | }; | ||
169 | |||
170 | /* TODO is it really the NEC protocol ? */ | ||
171 | int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
172 | { | ||
173 | u8 key[5]; | ||
174 | |||
175 | digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4); | ||
176 | /* TODO state, maybe it is VV ? */ | ||
177 | if (key[1] != 0) | ||
178 | key[0] = 0x01; /* if something is inside the buffer, simulate key press */ | ||
179 | |||
180 | /* call the universal NEC remote processor, to find out the key's state and event */ | ||
181 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | ||
182 | if (key[0] != 0) | ||
183 | deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | |||
188 | /* DVB USB Driver stuff */ | ||
189 | static struct dvb_usb_properties digitv_properties; | ||
190 | |||
191 | static int digitv_probe(struct usb_interface *intf, | ||
192 | const struct usb_device_id *id) | ||
193 | { | ||
194 | return dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE); | ||
195 | } | ||
196 | |||
197 | static struct usb_device_id digitv_table [] = { | ||
198 | { USB_DEVICE(USB_VID_ANCHOR, USB_PID_NEBULA_DIGITV) }, | ||
199 | { } /* Terminating entry */ | ||
200 | }; | ||
201 | MODULE_DEVICE_TABLE (usb, digitv_table); | ||
202 | |||
203 | static struct dvb_usb_properties digitv_properties = { | ||
204 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
205 | |||
206 | .usb_ctrl = CYPRESS_FX2, | ||
207 | .firmware = "dvb-usb-digitv-01.fw", | ||
208 | |||
209 | .size_of_priv = 0, | ||
210 | |||
211 | .streaming_ctrl = NULL, | ||
212 | .pid_filter = NULL, | ||
213 | .pid_filter_ctrl = NULL, | ||
214 | .power_ctrl = NULL, | ||
215 | .frontend_attach = digitv_frontend_attach, | ||
216 | .tuner_attach = NULL, // digitv_tuner_attach, | ||
217 | .read_mac_address = NULL, | ||
218 | |||
219 | .rc_interval = 1000, | ||
220 | .rc_key_map = digitv_rc_keys, | ||
221 | .rc_key_map_size = ARRAY_SIZE(digitv_rc_keys), | ||
222 | .rc_query = digitv_rc_query, | ||
223 | |||
224 | .identify_state = digitv_identify_state, | ||
225 | |||
226 | .i2c_algo = &digitv_i2c_algo, | ||
227 | |||
228 | .generic_bulk_ctrl_endpoint = 0x01, | ||
229 | /* parameter for the MPEG2-data transfer */ | ||
230 | .urb = { | ||
231 | .type = DVB_USB_BULK, | ||
232 | .count = 7, | ||
233 | .endpoint = 0x02, | ||
234 | .u = { | ||
235 | .bulk = { | ||
236 | .buffersize = 4096, | ||
237 | } | ||
238 | } | ||
239 | }, | ||
240 | |||
241 | .num_device_descs = 2, | ||
242 | .devices = { | ||
243 | { "Nebula Electronics uDigiTV DVB-T USB2.0)", | ||
244 | { &digitv_table[0], NULL }, | ||
245 | { NULL }, | ||
246 | }, | ||
247 | } | ||
248 | }; | ||
249 | |||
250 | static struct usb_driver digitv_driver = { | ||
251 | .owner = THIS_MODULE, | ||
252 | .name = "Nebula Electronics uDigiTV DVB-T USB2.0 device", | ||
253 | .probe = digitv_probe, | ||
254 | .disconnect = dvb_usb_device_exit, | ||
255 | .id_table = digitv_table, | ||
256 | }; | ||
257 | |||
258 | /* module stuff */ | ||
259 | static int __init digitv_module_init(void) | ||
260 | { | ||
261 | int result; | ||
262 | if ((result = usb_register(&digitv_driver))) { | ||
263 | err("usb_register failed. Error number %d",result); | ||
264 | return result; | ||
265 | } | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static void __exit digitv_module_exit(void) | ||
271 | { | ||
272 | /* deregister this driver from the USB subsystem */ | ||
273 | usb_deregister(&digitv_driver); | ||
274 | } | ||
275 | |||
276 | module_init (digitv_module_init); | ||
277 | module_exit (digitv_module_exit); | ||
278 | |||
279 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
280 | MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0"); | ||
281 | MODULE_VERSION("1.0-alpha"); | ||
282 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/digitv.h b/drivers/media/dvb/dvb-usb/digitv.h new file mode 100644 index 0000000000..477ee428a7 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/digitv.h | |||
@@ -0,0 +1,65 @@ | |||
1 | #ifndef _DVB_USB_DIGITV_H_ | ||
2 | #define _DVB_USB_DIGITV_H_ | ||
3 | |||
4 | #define DVB_USB_LOG_PREFIX "digitv" | ||
5 | #include "dvb-usb.h" | ||
6 | |||
7 | extern int dvb_usb_digitv_debug; | ||
8 | #define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args) | ||
9 | |||
10 | /* protocol (from usblogging and the SDK: | ||
11 | * | ||
12 | * Always 7 bytes bulk message(s) for controlling | ||
13 | * | ||
14 | * First byte describes the command. Reads are 2 consecutive transfer (as always). | ||
15 | * | ||
16 | * General structure: | ||
17 | * | ||
18 | * write or first message of a read: | ||
19 | * <cmdbyte> VV <len> B0 B1 B2 B3 | ||
20 | * | ||
21 | * second message of a read | ||
22 | * <cmdbyte> VV <len> R0 R1 R2 R3 | ||
23 | * | ||
24 | * whereas 0 < len <= 4 | ||
25 | * | ||
26 | * I2C address is stored somewhere inside the device. | ||
27 | * | ||
28 | * 0x01 read from EEPROM | ||
29 | * VV = offset; B* = 0; R* = value(s) | ||
30 | * | ||
31 | * 0x02 read register of the COFDM | ||
32 | * VV = register; B* = 0; R* = value(s) | ||
33 | * | ||
34 | * 0x05 write register of the COFDM | ||
35 | * VV = register; B* = value(s); | ||
36 | * | ||
37 | * 0x06 write to the tuner (only for NXT6000) | ||
38 | * VV = 0; B* = PLL data; len = 4; | ||
39 | * | ||
40 | * 0x03 read remote control | ||
41 | * VV = 0; B* = 0; len = 4; R* = key | ||
42 | * | ||
43 | * 0x07 write to the remote (don't know why one should this, resetting ?) | ||
44 | * VV = 0; B* = key; len = 4; | ||
45 | * | ||
46 | * 0x08 write remote type | ||
47 | * VV = 0; B[0] = 0x01, len = 4 | ||
48 | * | ||
49 | * 0x09 write device init | ||
50 | * TODO | ||
51 | */ | ||
52 | #define USB_READ_EEPROM 1 | ||
53 | |||
54 | #define USB_READ_COFDM 2 | ||
55 | #define USB_WRITE_COFDM 5 | ||
56 | |||
57 | #define USB_WRITE_TUNER 6 | ||
58 | |||
59 | #define USB_READ_REMOTE 3 | ||
60 | #define USB_WRITE_REMOTE 7 | ||
61 | #define USB_WRITE_REMOTE_TYPE 8 | ||
62 | |||
63 | #define USB_DEV_INIT 9 | ||
64 | |||
65 | #endif | ||
diff --git a/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c index 1872aa6d20..d17d768038 100644 --- a/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c | |||
@@ -1,42 +1,18 @@ | |||
1 | /* | 1 | /* Frontend part of the Linux driver for the Yakumo/Hama/Typhoon DVB-T |
2 | * dvb-dtt200u-fe.c is a driver which implements the frontend-part of the | 2 | * USB2.0 receiver. |
3 | * Yakumo/Typhoon/Hama USB2.0 boxes. It is hard-wired to the dibusb-driver as | ||
4 | * it uses the usb-transfer functions directly (maybe creating a | ||
5 | * generic-dvb-usb-lib for all usb-drivers will be reduce some more code.) | ||
6 | * | 3 | * |
7 | * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de> | 4 | * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de> |
8 | * | 5 | * |
9 | * see dvb-dibusb-core.c for copyright details. | 6 | * This program is free software; you can redistribute it and/or modify it |
10 | */ | 7 | * under the terms of the GNU General Public License as published by the Free |
11 | 8 | * Software Foundation, version 2. | |
12 | /* guessed protocol description (reverse engineered): | ||
13 | * read | ||
14 | * 00 - USB type 0x02 for usb2.0, 0x01 for usb1.1 | ||
15 | * 81 - <TS_LOCK> <current frequency divided by 250000> | ||
16 | * 82 - crash - do not touch | ||
17 | * 83 - crash - do not touch | ||
18 | * 84 - remote control | ||
19 | * 85 - crash - do not touch (OK, stop testing here) | ||
20 | * 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal) | ||
21 | * 89 - noise-to-signal | ||
22 | * 8a - unkown 1 byte - signal_strength | ||
23 | * 8c - ber ??? | ||
24 | * 8d - ber | ||
25 | * 8e - unc | ||
26 | * | 9 | * |
27 | * write | 10 | * see Documentation/dvb/README.dvb-usb for more information |
28 | * 02 - bandwidth | ||
29 | * 03 - frequency (divided by 250000) | ||
30 | * 04 - pid table (index pid(7:0) pid(12:8)) | ||
31 | * 05 - reset the pid table | ||
32 | * 08 - demod transfer enabled or not (FX2 transfer is enabled by default) | ||
33 | */ | 11 | */ |
34 | 12 | #include "dtt200u.h" | |
35 | #include "dvb-dibusb.h" | ||
36 | #include "dvb_frontend.h" | ||
37 | 13 | ||
38 | struct dtt200u_fe_state { | 14 | struct dtt200u_fe_state { |
39 | struct usb_dibusb *dib; | 15 | struct dvb_usb_device *d; |
40 | 16 | ||
41 | struct dvb_frontend_parameters fep; | 17 | struct dvb_frontend_parameters fep; |
42 | struct dvb_frontend frontend; | 18 | struct dvb_frontend frontend; |
@@ -47,11 +23,11 @@ struct dtt200u_fe_state { | |||
47 | static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat) | 23 | static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat) |
48 | { | 24 | { |
49 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 25 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
50 | u8 bw[1] = { 0x81 }; | 26 | u8 bw = GET_TUNE_STAT; |
51 | u8 br[3] = { 0 }; | 27 | u8 br[3] = { 0 }; |
52 | // u8 bdeb[5] = { 0 }; | 28 | // u8 bdeb[5] = { 0 }; |
53 | 29 | ||
54 | dibusb_readwrite_usb(state->dib,bw,1,br,3); | 30 | dvb_usb_generic_rw(state->d,&bw,1,br,3,0); |
55 | switch (br[0]) { | 31 | switch (br[0]) { |
56 | case 0x01: | 32 | case 0x01: |
57 | *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | 33 | *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; |
@@ -60,12 +36,12 @@ static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat) | |||
60 | *stat = 0; | 36 | *stat = 0; |
61 | break; | 37 | break; |
62 | default: | 38 | default: |
63 | moan("br[0]",0x81); | 39 | moan("br[0]",GET_TUNE_STAT); |
64 | break; | 40 | break; |
65 | } | 41 | } |
66 | 42 | ||
67 | // bw[0] = 0x88; | 43 | // bw[0] = 0x88; |
68 | // dibusb_readwrite_usb(state->dib,bw,1,bdeb,5); | 44 | // dvb_usb_generic_rw(state->d,bw,1,bdeb,5,0); |
69 | 45 | ||
70 | // deb_info("%02x: %02x %02x %02x %02x %02x\n",bw[0],bdeb[0],bdeb[1],bdeb[2],bdeb[3],bdeb[4]); | 46 | // deb_info("%02x: %02x %02x %02x %02x %02x\n",bw[0],bdeb[0],bdeb[1],bdeb[2],bdeb[3],bdeb[4]); |
71 | 47 | ||
@@ -74,27 +50,26 @@ static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat) | |||
74 | static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber) | 50 | static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber) |
75 | { | 51 | { |
76 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 52 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
77 | u8 bw[1] = { 0x8d }; | 53 | u8 bw = GET_BER; |
78 | *ber = 0; | 54 | *ber = 0; |
79 | dibusb_readwrite_usb(state->dib,bw,1,(u8*) ber, 3); | 55 | dvb_usb_generic_rw(state->d,&bw,1,(u8*) ber,3,0); |
80 | return 0; | 56 | return 0; |
81 | } | 57 | } |
82 | 58 | ||
83 | static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | 59 | static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) |
84 | { | 60 | { |
85 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 61 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
86 | u8 bw[1] = { 0x8c }; | 62 | u8 bw = GET_UNK; |
87 | *unc = 0; | 63 | *unc = 0; |
88 | dibusb_readwrite_usb(state->dib,bw,1,(u8*) unc, 3); | 64 | dvb_usb_generic_rw(state->d,&bw,1,(u8*) unc,3,0); |
89 | return 0; | 65 | return 0; |
90 | } | 66 | } |
91 | 67 | ||
92 | static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) | 68 | static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) |
93 | { | 69 | { |
94 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 70 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
95 | u8 bw[1] = { 0x8a }; | 71 | u8 bw = GET_SIG_STRENGTH, b; |
96 | u8 b; | 72 | dvb_usb_generic_rw(state->d,&bw,1,&b,1,0); |
97 | dibusb_readwrite_usb(state->dib,bw,1,&b, 1); | ||
98 | *strength = (b << 8) | b; | 73 | *strength = (b << 8) | b; |
99 | return 0; | 74 | return 0; |
100 | } | 75 | } |
@@ -102,18 +77,17 @@ static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strengt | |||
102 | static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr) | 77 | static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr) |
103 | { | 78 | { |
104 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 79 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
105 | u8 bw[1] = { 0x89 }; | 80 | u8 bw = GET_SNR,br; |
106 | u8 br[1] = { 0 }; | 81 | dvb_usb_generic_rw(state->d,&bw,1,&br,1,0); |
107 | dibusb_readwrite_usb(state->dib,bw,1,br,1); | 82 | *snr = ~((br << 8) | br); |
108 | *snr = ((0xff - br[0]) << 8) | (0xff - br[0]); | ||
109 | return 0; | 83 | return 0; |
110 | } | 84 | } |
111 | 85 | ||
112 | static int dtt200u_fe_init(struct dvb_frontend* fe) | 86 | static int dtt200u_fe_init(struct dvb_frontend* fe) |
113 | { | 87 | { |
114 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 88 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
115 | u8 b[] = { 0x01 }; | 89 | u8 b = RESET_DEMOD; |
116 | return dibusb_write_usb(state->dib,b,1); | 90 | return dvb_usb_generic_write(state->d,&b,1); |
117 | } | 91 | } |
118 | 92 | ||
119 | static int dtt200u_fe_sleep(struct dvb_frontend* fe) | 93 | static int dtt200u_fe_sleep(struct dvb_frontend* fe) |
@@ -134,7 +108,7 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend* fe, | |||
134 | { | 108 | { |
135 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 109 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
136 | u16 freq = fep->frequency / 250000; | 110 | u16 freq = fep->frequency / 250000; |
137 | u8 bw,bwbuf[2] = { 0x03, 0 }, freqbuf[3] = { 0x02, 0, 0 }; | 111 | u8 bw,bwbuf[2] = { SET_BANDWIDTH, 0 }, freqbuf[3] = { SET_FREQUENCY, 0, 0 }; |
138 | 112 | ||
139 | switch (fep->u.ofdm.bandwidth) { | 113 | switch (fep->u.ofdm.bandwidth) { |
140 | case BANDWIDTH_8_MHZ: bw = 8; break; | 114 | case BANDWIDTH_8_MHZ: bw = 8; break; |
@@ -147,11 +121,11 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend* fe, | |||
147 | deb_info("set_frontend\n"); | 121 | deb_info("set_frontend\n"); |
148 | 122 | ||
149 | bwbuf[1] = bw; | 123 | bwbuf[1] = bw; |
150 | dibusb_write_usb(state->dib,bwbuf,2); | 124 | dvb_usb_generic_write(state->d,bwbuf,2); |
151 | 125 | ||
152 | freqbuf[1] = freq & 0xff; | 126 | freqbuf[1] = freq & 0xff; |
153 | freqbuf[2] = (freq >> 8) & 0xff; | 127 | freqbuf[2] = (freq >> 8) & 0xff; |
154 | dibusb_write_usb(state->dib,freqbuf,3); | 128 | dvb_usb_generic_write(state->d,freqbuf,3); |
155 | 129 | ||
156 | memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters)); | 130 | memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters)); |
157 | 131 | ||
@@ -172,37 +146,9 @@ static void dtt200u_fe_release(struct dvb_frontend* fe) | |||
172 | kfree(state); | 146 | kfree(state); |
173 | } | 147 | } |
174 | 148 | ||
175 | static int dtt200u_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff) | ||
176 | { | ||
177 | struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv; | ||
178 | u8 b_pid[4]; | ||
179 | pid = onoff ? pid : 0; | ||
180 | |||
181 | b_pid[0] = 0x04; | ||
182 | b_pid[1] = index; | ||
183 | b_pid[2] = pid & 0xff; | ||
184 | b_pid[3] = (pid >> 8) & 0xff; | ||
185 | |||
186 | dibusb_write_usb(state->dib,b_pid,4); | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int dtt200u_fifo_control(struct dvb_frontend *fe, int onoff) | ||
191 | { | ||
192 | struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv; | ||
193 | u8 b_streaming[2] = { 0x08, onoff }; | ||
194 | u8 b_rst_pid[1] = { 0x05 }; | ||
195 | |||
196 | dibusb_write_usb(state->dib,b_streaming,2); | ||
197 | |||
198 | if (!onoff) | ||
199 | dibusb_write_usb(state->dib,b_rst_pid,1); | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static struct dvb_frontend_ops dtt200u_fe_ops; | 149 | static struct dvb_frontend_ops dtt200u_fe_ops; |
204 | 150 | ||
205 | struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *dib, struct dib_fe_xfer_ops *xfer_ops) | 151 | struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d) |
206 | { | 152 | { |
207 | struct dtt200u_fe_state* state = NULL; | 153 | struct dtt200u_fe_state* state = NULL; |
208 | 154 | ||
@@ -214,14 +160,11 @@ struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *dib, struct dib_fe_xfe | |||
214 | 160 | ||
215 | deb_info("attaching frontend dtt200u\n"); | 161 | deb_info("attaching frontend dtt200u\n"); |
216 | 162 | ||
217 | state->dib = dib; | 163 | state->d = d; |
218 | 164 | ||
219 | state->frontend.ops = &dtt200u_fe_ops; | 165 | state->frontend.ops = &dtt200u_fe_ops; |
220 | state->frontend.demodulator_priv = state; | 166 | state->frontend.demodulator_priv = state; |
221 | 167 | ||
222 | xfer_ops->fifo_ctrl = dtt200u_fifo_control; | ||
223 | xfer_ops->pid_ctrl = dtt200u_pid_control; | ||
224 | |||
225 | goto success; | 168 | goto success; |
226 | error: | 169 | error: |
227 | return NULL; | 170 | return NULL; |
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c new file mode 100644 index 0000000000..fb2b5a2da1 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtt200u.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* DVB USB library compliant Linux driver for the Yakumo/Hama/Typhoon DVB-T | ||
2 | * USB2.0 receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation, version 2. | ||
9 | * | ||
10 | * see Documentation/dvb/README.dvb-usb for more information | ||
11 | */ | ||
12 | #include "dtt200u.h" | ||
13 | |||
14 | /* debug */ | ||
15 | int dvb_usb_dtt200u_debug; | ||
16 | module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644); | ||
17 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS); | ||
18 | |||
19 | static int dtt200u_streaming_ctrl(struct dvb_usb_device *d, int onoff) | ||
20 | { | ||
21 | u8 b_streaming[2] = { SET_TS_CTRL, onoff }; | ||
22 | u8 b_rst_pid = RESET_PID_FILTER; | ||
23 | |||
24 | dvb_usb_generic_write(d,b_streaming,2); | ||
25 | |||
26 | if (!onoff) | ||
27 | dvb_usb_generic_write(d,&b_rst_pid,1); | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | static int dtt200u_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff) | ||
32 | { | ||
33 | u8 b_pid[4]; | ||
34 | pid = onoff ? pid : 0; | ||
35 | |||
36 | b_pid[0] = SET_PID_FILTER; | ||
37 | b_pid[1] = index; | ||
38 | b_pid[2] = pid & 0xff; | ||
39 | b_pid[3] = (pid >> 8) & 0xff; | ||
40 | |||
41 | return dvb_usb_generic_write(d,b_pid,4); | ||
42 | } | ||
43 | |||
44 | /* remote control */ | ||
45 | /* key list for the tiny remote control (Yakumo, don't know about the others) */ | ||
46 | static struct dvb_usb_rc_key dtt200u_rc_keys[] = { | ||
47 | { 0x80, 0x01, KEY_MUTE }, | ||
48 | { 0x80, 0x02, KEY_CHANNELDOWN }, | ||
49 | { 0x80, 0x03, KEY_VOLUMEDOWN }, | ||
50 | { 0x80, 0x04, KEY_1 }, | ||
51 | { 0x80, 0x05, KEY_2 }, | ||
52 | { 0x80, 0x06, KEY_3 }, | ||
53 | { 0x80, 0x07, KEY_4 }, | ||
54 | { 0x80, 0x08, KEY_5 }, | ||
55 | { 0x80, 0x09, KEY_6 }, | ||
56 | { 0x80, 0x0a, KEY_7 }, | ||
57 | { 0x00, 0x0c, KEY_ZOOM }, | ||
58 | { 0x80, 0x0d, KEY_0 }, | ||
59 | { 0x00, 0x0e, KEY_SELECT }, | ||
60 | { 0x80, 0x12, KEY_POWER }, | ||
61 | { 0x80, 0x1a, KEY_CHANNELUP }, | ||
62 | { 0x80, 0x1b, KEY_8 }, | ||
63 | { 0x80, 0x1e, KEY_VOLUMEUP }, | ||
64 | { 0x80, 0x1f, KEY_9 }, | ||
65 | }; | ||
66 | |||
67 | static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
68 | { | ||
69 | u8 key[5],cmd = GET_RC_KEY; | ||
70 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); | ||
71 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | ||
72 | if (key[0] != 0) | ||
73 | deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int dtt200u_frontend_attach(struct dvb_usb_device *d) | ||
78 | { | ||
79 | d->fe = dtt200u_fe_attach(d); | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static struct dvb_usb_properties dtt200u_properties; | ||
84 | |||
85 | static int dtt200u_usb_probe(struct usb_interface *intf, | ||
86 | const struct usb_device_id *id) | ||
87 | { | ||
88 | return dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE); | ||
89 | } | ||
90 | |||
91 | static struct usb_device_id dtt200u_usb_table [] = { | ||
92 | { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_COLD) }, | ||
93 | { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_WARM) }, | ||
94 | { 0 }, | ||
95 | }; | ||
96 | MODULE_DEVICE_TABLE(usb, dtt200u_usb_table); | ||
97 | |||
98 | static struct dvb_usb_properties dtt200u_properties = { | ||
99 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING, | ||
100 | .pid_filter_count = 255, /* It is a guess, but there are at least 10 */ | ||
101 | |||
102 | .usb_ctrl = CYPRESS_FX2, | ||
103 | .firmware = "dvb-usb-dtt200u-01.fw", | ||
104 | |||
105 | .streaming_ctrl = dtt200u_streaming_ctrl, | ||
106 | .pid_filter = dtt200u_pid_filter, | ||
107 | .frontend_attach = dtt200u_frontend_attach, | ||
108 | |||
109 | .rc_interval = 200, | ||
110 | .rc_key_map = dtt200u_rc_keys, | ||
111 | .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys), | ||
112 | .rc_query = dtt200u_rc_query, | ||
113 | |||
114 | .generic_bulk_ctrl_endpoint = 0x01, | ||
115 | |||
116 | /* parameter for the MPEG2-data transfer */ | ||
117 | .urb = { | ||
118 | .type = DVB_USB_BULK, | ||
119 | .count = 7, | ||
120 | .endpoint = 0x02, | ||
121 | .u = { | ||
122 | .bulk = { | ||
123 | .buffersize = 4096, | ||
124 | } | ||
125 | } | ||
126 | }, | ||
127 | |||
128 | .num_device_descs = 1, | ||
129 | .devices = { | ||
130 | { .name = "Yakumo/Hama/Typhoon DVB-T USB2.0)", | ||
131 | .cold_ids = { &dtt200u_usb_table[0], &dtt200u_usb_table[2] }, | ||
132 | .warm_ids = { &dtt200u_usb_table[1], NULL }, | ||
133 | }, | ||
134 | { 0 }, | ||
135 | } | ||
136 | }; | ||
137 | |||
138 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
139 | static struct usb_driver dtt200u_usb_driver = { | ||
140 | .owner = THIS_MODULE, | ||
141 | .name = "Yakumo/Hama/Typhoon DVB-T USB2.0", | ||
142 | .probe = dtt200u_usb_probe, | ||
143 | .disconnect = dvb_usb_device_exit, | ||
144 | .id_table = dtt200u_usb_table, | ||
145 | }; | ||
146 | |||
147 | /* module stuff */ | ||
148 | static int __init dtt200u_usb_module_init(void) | ||
149 | { | ||
150 | int result; | ||
151 | if ((result = usb_register(&dtt200u_usb_driver))) { | ||
152 | err("usb_register failed. (%d)",result); | ||
153 | return result; | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static void __exit dtt200u_usb_module_exit(void) | ||
160 | { | ||
161 | /* deregister this driver from the USB subsystem */ | ||
162 | usb_deregister(&dtt200u_usb_driver); | ||
163 | } | ||
164 | |||
165 | module_init(dtt200u_usb_module_init); | ||
166 | module_exit(dtt200u_usb_module_exit); | ||
167 | |||
168 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
169 | MODULE_DESCRIPTION("Driver for the Yakumo/Hama/Typhoon DVB-T USB2.0 device"); | ||
170 | MODULE_VERSION("1.0"); | ||
171 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/dvb/dvb-usb/dtt200u.h new file mode 100644 index 0000000000..ed41420715 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtt200u.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* Common header file of Linux driver for the Yakumo/Hama/Typhoon DVB-T | ||
2 | * USB2.0 receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation, version 2. | ||
9 | * | ||
10 | * see Documentation/dvb/README.dvb-usb for more information | ||
11 | */ | ||
12 | #ifndef _DVB_USB_DTT200U_H_ | ||
13 | #define _DVB_USB_DTT200U_H_ | ||
14 | |||
15 | #define DVB_USB_LOG_PREFIX "dtt200u" | ||
16 | #include "dvb-usb.h" | ||
17 | |||
18 | extern int dvb_usb_dtt200u_debug; | ||
19 | #define deb_info(args...) dprintk(dvb_usb_dtt200u_debug,0x01,args) | ||
20 | #define deb_xfer(args...) dprintk(dvb_usb_dtt200u_debug,0x02,args) | ||
21 | |||
22 | /* guessed protocol description (reverse engineered): | ||
23 | * read | ||
24 | * 00 - USB type 0x02 for usb2.0, 0x01 for usb1.1 | ||
25 | * 81 - <TS_LOCK> <current frequency divided by 250000> | ||
26 | * 82 - crash - do not touch | ||
27 | * 83 - crash - do not touch | ||
28 | * 84 - remote control | ||
29 | * 85 - crash - do not touch (OK, stop testing here) | ||
30 | * 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal) | ||
31 | * 89 - noise-to-signal | ||
32 | * 8a - unkown 1 byte - signal_strength | ||
33 | * 8c - ber ??? | ||
34 | * 8d - ber | ||
35 | * 8e - unc | ||
36 | */ | ||
37 | |||
38 | #define GET_SPEED 0x00 | ||
39 | #define GET_TUNE_STAT 0x81 | ||
40 | #define GET_RC_KEY 0x84 | ||
41 | #define GET_STATUS 0x88 | ||
42 | #define GET_SNR 0x89 | ||
43 | #define GET_SIG_STRENGTH 0x8a | ||
44 | #define GET_UNK 0x8c | ||
45 | #define GET_BER 0x8d | ||
46 | #define GET_UNC 0x8e | ||
47 | |||
48 | /* write | ||
49 | * 01 - reset the demod | ||
50 | * 02 - frequency (divided by 250000) | ||
51 | * 03 - bandwidth | ||
52 | * 04 - pid table (index pid(7:0) pid(12:8)) | ||
53 | * 05 - reset the pid table | ||
54 | * 08 - demod transfer enabled or not (FX2 transfer is enabled by default) | ||
55 | */ | ||
56 | |||
57 | #define RESET_DEMOD 0x01 | ||
58 | #define SET_FREQUENCY 0x02 | ||
59 | #define SET_BANDWIDTH 0x03 | ||
60 | #define SET_PID_FILTER 0x04 | ||
61 | #define RESET_PID_FILTER 0x05 | ||
62 | #define SET_TS_CTRL 0x08 | ||
63 | |||
64 | extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d); | ||
65 | |||
66 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h new file mode 100644 index 0000000000..67e0d73fbc --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* dvb-usb-common.h is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * a header file containing prototypes and types for internal use of the dvb-usb-lib | ||
7 | */ | ||
8 | #ifndef _DVB_USB_COMMON_H_ | ||
9 | #define _DVB_USB_COMMON_H_ | ||
10 | |||
11 | #define DVB_USB_LOG_PREFIX "dvb-usb" | ||
12 | #include "dvb-usb.h" | ||
13 | |||
14 | extern int dvb_usb_debug; | ||
15 | |||
16 | #define deb_info(args...) dprintk(dvb_usb_debug,0x01,args) | ||
17 | #define deb_xfer(args...) dprintk(dvb_usb_debug,0x02,args) | ||
18 | #define deb_pll(args...) dprintk(dvb_usb_debug,0x04,args) | ||
19 | #define deb_ts(args...) dprintk(dvb_usb_debug,0x08,args) | ||
20 | #define deb_err(args...) dprintk(dvb_usb_debug,0x10,args) | ||
21 | #define deb_rc(args...) dprintk(dvb_usb_debug,0x20,args) | ||
22 | #define deb_fw(args...) dprintk(dvb_usb_debug,0x40,args) | ||
23 | |||
24 | /* commonly used methods */ | ||
25 | extern int usb_cypress_load_firmware(struct usb_device *, const char *, int); | ||
26 | |||
27 | extern int dvb_usb_urb_submit(struct dvb_usb_device *); | ||
28 | extern int dvb_usb_urb_kill(struct dvb_usb_device *); | ||
29 | extern int dvb_usb_urb_init(struct dvb_usb_device *); | ||
30 | extern int dvb_usb_urb_exit(struct dvb_usb_device *); | ||
31 | |||
32 | extern int dvb_usb_i2c_init(struct dvb_usb_device *); | ||
33 | extern int dvb_usb_i2c_exit(struct dvb_usb_device *); | ||
34 | |||
35 | extern int dvb_usb_dvb_init(struct dvb_usb_device *); | ||
36 | extern int dvb_usb_dvb_exit(struct dvb_usb_device *); | ||
37 | |||
38 | extern int dvb_usb_fe_init(struct dvb_usb_device *); | ||
39 | extern int dvb_usb_fe_exit(struct dvb_usb_device *); | ||
40 | |||
41 | extern int dvb_usb_remote_init(struct dvb_usb_device *); | ||
42 | extern int dvb_usb_remote_exit(struct dvb_usb_device *); | ||
43 | |||
44 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c new file mode 100644 index 0000000000..bdd72f7797 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c | |||
@@ -0,0 +1,210 @@ | |||
1 | /* dvb-usb-dvb.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for initializing and handling the | ||
7 | * linux-dvb API. | ||
8 | */ | ||
9 | #include "dvb-usb-common.h" | ||
10 | |||
11 | static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) | ||
12 | { | ||
13 | struct dvb_usb_device *d = dvbdmxfeed->demux->priv; | ||
14 | int newfeedcount,ret; | ||
15 | |||
16 | if (d == NULL) | ||
17 | return -ENODEV; | ||
18 | |||
19 | newfeedcount = d->feedcount + (onoff ? 1 : -1); | ||
20 | |||
21 | /* | ||
22 | * stop feed before setting a new pid if there will be no pid anymore | ||
23 | */ | ||
24 | if (newfeedcount == 0) { | ||
25 | deb_ts("stop feeding\n"); | ||
26 | |||
27 | if (d->props.streaming_ctrl != NULL) | ||
28 | if ((ret = d->props.streaming_ctrl(d,0))) | ||
29 | err("error while stopping stream."); | ||
30 | |||
31 | dvb_usb_urb_kill(d); | ||
32 | } | ||
33 | |||
34 | d->feedcount = newfeedcount; | ||
35 | |||
36 | /* activate the pid on the device specific pid_filter */ | ||
37 | deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off"); | ||
38 | if (d->props.caps & DVB_USB_HAS_PID_FILTER && | ||
39 | d->pid_filtering && | ||
40 | d->props.pid_filter != NULL) | ||
41 | d->props.pid_filter(d,dvbdmxfeed->index,dvbdmxfeed->pid,onoff); | ||
42 | |||
43 | /* start the feed if this was the first feed and there is still a feed | ||
44 | * for reception. | ||
45 | */ | ||
46 | if (d->feedcount == onoff && d->feedcount > 0) { | ||
47 | |||
48 | deb_ts("controlling pid parser\n"); | ||
49 | if (d->props.caps & DVB_USB_HAS_PID_FILTER && | ||
50 | d->props.caps & DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF && | ||
51 | d->props.pid_filter_ctrl != NULL) | ||
52 | if (d->props.pid_filter_ctrl(d,d->pid_filtering) < 0) | ||
53 | err("could not handle pid_parser"); | ||
54 | |||
55 | deb_ts("start feeding\n"); | ||
56 | if (d->props.streaming_ctrl != NULL) | ||
57 | if (d->props.streaming_ctrl(d,1)) { | ||
58 | err("error while enabling fifo."); | ||
59 | return -ENODEV; | ||
60 | } | ||
61 | |||
62 | dvb_usb_urb_submit(d); | ||
63 | } | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
68 | { | ||
69 | deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type); | ||
70 | return dvb_usb_ctrl_feed(dvbdmxfeed,1); | ||
71 | } | ||
72 | |||
73 | static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
74 | { | ||
75 | deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type); | ||
76 | return dvb_usb_ctrl_feed(dvbdmxfeed,0); | ||
77 | } | ||
78 | |||
79 | int dvb_usb_dvb_init(struct dvb_usb_device *d) | ||
80 | { | ||
81 | int ret; | ||
82 | |||
83 | if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name, | ||
84 | d->owner)) < 0) { | ||
85 | deb_info("dvb_register_adapter failed: error %d", ret); | ||
86 | goto err; | ||
87 | } | ||
88 | d->dvb_adap.priv = d; | ||
89 | |||
90 | if (d->props.read_mac_address) { | ||
91 | if (d->props.read_mac_address(d,d->dvb_adap.proposed_mac) == 0) | ||
92 | info("MAC address: %02x:%02x:%02x:%02x:%02x:%02x",d->dvb_adap.proposed_mac[0], | ||
93 | d->dvb_adap.proposed_mac[1],d->dvb_adap.proposed_mac[2], | ||
94 | d->dvb_adap.proposed_mac[3],d->dvb_adap.proposed_mac[4], | ||
95 | d->dvb_adap.proposed_mac[5]); | ||
96 | else | ||
97 | err("MAC address reading failed."); | ||
98 | } | ||
99 | |||
100 | |||
101 | d->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | ||
102 | d->demux.priv = d; | ||
103 | |||
104 | d->demux.feednum = d->demux.filternum = d->max_feed_count; | ||
105 | d->demux.start_feed = dvb_usb_start_feed; | ||
106 | d->demux.stop_feed = dvb_usb_stop_feed; | ||
107 | d->demux.write_to_decoder = NULL; | ||
108 | if ((ret = dvb_dmx_init(&d->demux)) < 0) { | ||
109 | err("dvb_dmx_init failed: error %d",ret); | ||
110 | goto err_dmx; | ||
111 | } | ||
112 | |||
113 | d->dmxdev.filternum = d->demux.filternum; | ||
114 | d->dmxdev.demux = &d->demux.dmx; | ||
115 | d->dmxdev.capabilities = 0; | ||
116 | if ((ret = dvb_dmxdev_init(&d->dmxdev, &d->dvb_adap)) < 0) { | ||
117 | err("dvb_dmxdev_init failed: error %d",ret); | ||
118 | goto err_dmx_dev; | ||
119 | } | ||
120 | |||
121 | dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx); | ||
122 | |||
123 | goto success; | ||
124 | err_dmx_dev: | ||
125 | dvb_dmx_release(&d->demux); | ||
126 | err_dmx: | ||
127 | dvb_unregister_adapter(&d->dvb_adap); | ||
128 | err: | ||
129 | return ret; | ||
130 | success: | ||
131 | d->state |= DVB_USB_STATE_DVB; | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | int dvb_usb_dvb_exit(struct dvb_usb_device *d) | ||
136 | { | ||
137 | if (d->state & DVB_USB_STATE_DVB) { | ||
138 | deb_info("unregistering DVB part\n"); | ||
139 | dvb_net_release(&d->dvb_net); | ||
140 | d->demux.dmx.close(&d->demux.dmx); | ||
141 | dvb_dmxdev_release(&d->dmxdev); | ||
142 | dvb_dmx_release(&d->demux); | ||
143 | dvb_unregister_adapter(&d->dvb_adap); | ||
144 | d->state &= ~DVB_USB_STATE_DVB; | ||
145 | } | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int dvb_usb_fe_wakeup(struct dvb_frontend *fe) | ||
150 | { | ||
151 | struct dvb_usb_device *d = fe->dvb->priv; | ||
152 | |||
153 | if (d->props.power_ctrl) | ||
154 | d->props.power_ctrl(d,1); | ||
155 | |||
156 | if (d->fe_init) | ||
157 | d->fe_init(fe); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int dvb_usb_fe_sleep(struct dvb_frontend *fe) | ||
163 | { | ||
164 | struct dvb_usb_device *d = fe->dvb->priv; | ||
165 | |||
166 | if (d->fe_sleep) | ||
167 | d->fe_sleep(fe); | ||
168 | |||
169 | if (d->props.power_ctrl) | ||
170 | d->props.power_ctrl(d,0); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | int dvb_usb_fe_init(struct dvb_usb_device* d) | ||
176 | { | ||
177 | if (d->props.frontend_attach == NULL) { | ||
178 | err("strange '%s' don't want to attach a frontend.",d->desc->name); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | d->props.frontend_attach(d); | ||
183 | |||
184 | /* re-assign sleep and wakeup functions */ | ||
185 | if (d->fe != NULL) { | ||
186 | d->fe_init = d->fe->ops->init; d->fe->ops->init = dvb_usb_fe_wakeup; | ||
187 | d->fe_sleep = d->fe->ops->sleep; d->fe->ops->sleep = dvb_usb_fe_sleep; | ||
188 | |||
189 | if (dvb_register_frontend(&d->dvb_adap, d->fe)) { | ||
190 | err("Frontend registration failed."); | ||
191 | if (d->fe->ops->release) | ||
192 | d->fe->ops->release(d->fe); | ||
193 | d->fe = NULL; | ||
194 | return -ENODEV; | ||
195 | } | ||
196 | } else | ||
197 | err("no frontend was attached by '%s'",d->desc->name); | ||
198 | |||
199 | if (d->props.tuner_attach != NULL) | ||
200 | d->props.tuner_attach(d); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | int dvb_usb_fe_exit(struct dvb_usb_device *d) | ||
206 | { | ||
207 | if (d->fe != NULL) | ||
208 | dvb_unregister_frontend(d->fe); | ||
209 | return 0; | ||
210 | } | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c new file mode 100644 index 0000000000..5244e39770 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* dvb-usb-firmware.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices. | ||
7 | * | ||
8 | * FIXME: This part does actually not belong to dvb-usb, but to the usb-subsystem. | ||
9 | */ | ||
10 | #include "dvb-usb-common.h" | ||
11 | |||
12 | #include <linux/firmware.h> | ||
13 | #include <linux/usb.h> | ||
14 | |||
15 | struct usb_cypress_controller { | ||
16 | int id; | ||
17 | const char *name; /* name of the usb controller */ | ||
18 | u16 cpu_cs_register; /* needs to be restarted, when the firmware has been downloaded. */ | ||
19 | }; | ||
20 | |||
21 | static struct usb_cypress_controller cypress[] = { | ||
22 | { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 }, | ||
23 | { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 }, | ||
24 | { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, | ||
25 | }; | ||
26 | |||
27 | /* | ||
28 | * load a firmware packet to the device | ||
29 | */ | ||
30 | static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len) | ||
31 | { | ||
32 | return usb_control_msg(udev, usb_sndctrlpipe(udev,0), | ||
33 | 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ); | ||
34 | } | ||
35 | |||
36 | int usb_cypress_load_firmware(struct usb_device *udev, const char *filename, int type) | ||
37 | { | ||
38 | const struct firmware *fw = NULL; | ||
39 | u16 addr; | ||
40 | u8 *b,*p; | ||
41 | int ret = 0,i; | ||
42 | |||
43 | if ((ret = request_firmware(&fw, filename, &udev->dev)) != 0) { | ||
44 | err("did not find the firmware file. (%s) " | ||
45 | "Please see linux/Documentation/dvb/ for more details on firmware-problems.", | ||
46 | filename); | ||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | info("downloading firmware from file '%s' to the '%s'",filename,cypress[type].name); | ||
51 | |||
52 | p = kmalloc(fw->size,GFP_KERNEL); | ||
53 | if (p != NULL) { | ||
54 | u8 reset; | ||
55 | /* | ||
56 | * you cannot use the fw->data as buffer for | ||
57 | * usb_control_msg, a new buffer has to be | ||
58 | * created | ||
59 | */ | ||
60 | memcpy(p,fw->data,fw->size); | ||
61 | |||
62 | /* stop the CPU */ | ||
63 | reset = 1; | ||
64 | if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1) | ||
65 | err("could not stop the USB controller CPU."); | ||
66 | for(i = 0; p[i+3] == 0 && i < fw->size; ) { | ||
67 | b = (u8 *) &p[i]; | ||
68 | addr = cpu_to_le16( *((u16 *) &b[1]) ); | ||
69 | |||
70 | deb_fw("writing to address 0x%04x (buffer: 0x%02x%02x)\n",addr,b[1],b[2]); | ||
71 | |||
72 | ret = usb_cypress_writemem(udev,addr,&b[4],b[0]); | ||
73 | |||
74 | if (ret != b[0]) { | ||
75 | err("error while transferring firmware " | ||
76 | "(transferred size: %d, block size: %d)", | ||
77 | ret,b[0]); | ||
78 | ret = -EINVAL; | ||
79 | break; | ||
80 | } | ||
81 | i += 5 + b[0]; | ||
82 | } | ||
83 | /* length in ret */ | ||
84 | if (ret > 0) | ||
85 | ret = 0; | ||
86 | /* restart the CPU */ | ||
87 | reset = 0; | ||
88 | if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) { | ||
89 | err("could not restart the USB controller CPU."); | ||
90 | ret = -EINVAL; | ||
91 | } | ||
92 | |||
93 | kfree(p); | ||
94 | } else { | ||
95 | ret = -ENOMEM; | ||
96 | } | ||
97 | release_firmware(fw); | ||
98 | |||
99 | return ret; | ||
100 | } | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c new file mode 100644 index 0000000000..9f0a8d90d1 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* dvb-usb-i2c.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for (de-)initializing an I2C adapter. | ||
7 | */ | ||
8 | #include "dvb-usb-common.h" | ||
9 | |||
10 | int dvb_usb_i2c_init(struct dvb_usb_device *d) | ||
11 | { | ||
12 | int ret = 0; | ||
13 | |||
14 | if (!(d->props.caps & DVB_USB_IS_AN_I2C_ADAPTER)) | ||
15 | return 0; | ||
16 | |||
17 | if (d->props.i2c_algo == NULL) { | ||
18 | err("no i2c algorithm specified"); | ||
19 | return -EINVAL; | ||
20 | } | ||
21 | |||
22 | strncpy(d->i2c_adap.name,d->desc->name,I2C_NAME_SIZE); | ||
23 | #ifdef I2C_ADAP_CLASS_TV_DIGITAL | ||
24 | d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL, | ||
25 | #else | ||
26 | d->i2c_adap.class = I2C_CLASS_TV_DIGITAL, | ||
27 | #endif | ||
28 | d->i2c_adap.algo = d->props.i2c_algo; | ||
29 | d->i2c_adap.algo_data = NULL; | ||
30 | d->i2c_adap.id = I2C_ALGO_BIT; | ||
31 | |||
32 | i2c_set_adapdata(&d->i2c_adap, d); | ||
33 | |||
34 | if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0) | ||
35 | err("could not add i2c adapter"); | ||
36 | |||
37 | d->state |= DVB_USB_STATE_I2C; | ||
38 | |||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | int dvb_usb_i2c_exit(struct dvb_usb_device *d) | ||
43 | { | ||
44 | if (d->state & DVB_USB_STATE_I2C) | ||
45 | i2c_del_adapter(&d->i2c_adap); | ||
46 | d->state &= ~DVB_USB_STATE_I2C; | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | int dvb_usb_pll_init_i2c(struct dvb_frontend *fe) | ||
51 | { | ||
52 | struct dvb_usb_device *d = fe->dvb->priv; | ||
53 | struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 }; | ||
54 | int ret = 0; | ||
55 | |||
56 | /* if there is nothing to initialize */ | ||
57 | if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 && | ||
58 | d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00) | ||
59 | return 0; | ||
60 | |||
61 | if (d->tuner_pass_ctrl) | ||
62 | d->tuner_pass_ctrl(fe,1,d->pll_addr); | ||
63 | |||
64 | deb_pll("pll init: %x\n",d->pll_addr); | ||
65 | deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1], | ||
66 | d->pll_init[2],d->pll_init[3]); | ||
67 | |||
68 | if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) { | ||
69 | err("tuner i2c write failed for pll_init."); | ||
70 | ret = -EREMOTEIO; | ||
71 | } | ||
72 | msleep(1); | ||
73 | |||
74 | if (d->tuner_pass_ctrl) | ||
75 | d->tuner_pass_ctrl(fe,0,d->pll_addr); | ||
76 | return ret; | ||
77 | } | ||
78 | EXPORT_SYMBOL(dvb_usb_pll_init_i2c); | ||
79 | |||
80 | int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5]) | ||
81 | { | ||
82 | struct dvb_usb_device *d = fe->dvb->priv; | ||
83 | |||
84 | deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc); | ||
85 | |||
86 | b[0] = d->pll_addr << 1; | ||
87 | dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth); | ||
88 | |||
89 | deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | EXPORT_SYMBOL(dvb_usb_pll_set); | ||
94 | |||
95 | int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | ||
96 | { | ||
97 | struct dvb_usb_device *d = fe->dvb->priv; | ||
98 | int ret = 0; | ||
99 | u8 b[5]; | ||
100 | struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 }; | ||
101 | |||
102 | dvb_usb_pll_set(fe,fep,b); | ||
103 | |||
104 | if (d->tuner_pass_ctrl) | ||
105 | d->tuner_pass_ctrl(fe,1,d->pll_addr); | ||
106 | |||
107 | if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) { | ||
108 | err("tuner i2c write failed for pll_set."); | ||
109 | ret = -EREMOTEIO; | ||
110 | } | ||
111 | msleep(1); | ||
112 | |||
113 | if (d->tuner_pass_ctrl) | ||
114 | d->tuner_pass_ctrl(fe,0,d->pll_addr); | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | EXPORT_SYMBOL(dvb_usb_pll_set_i2c); | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h new file mode 100644 index 0000000000..bcb3419186 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* dvb-usb-ids.h is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) see | ||
4 | * dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * a header file containing define's for the USB device supported by the | ||
7 | * various drivers. | ||
8 | */ | ||
9 | #ifndef _DVB_USB_IDS_H_ | ||
10 | #define _DVB_USB_IDS_H_ | ||
11 | |||
12 | /* Vendor IDs */ | ||
13 | #define USB_VID_ADSTECH 0x06e1 | ||
14 | #define USB_VID_ANCHOR 0x0547 | ||
15 | #define USB_VID_AVERMEDIA_UNK 0x14aa | ||
16 | #define USB_VID_AVERMEDIA 0x07ca | ||
17 | #define USB_VID_COMPRO 0x185b | ||
18 | #define USB_VID_COMPRO_UNK 0x145f | ||
19 | #define USB_VID_CYPRESS 0x04b4 | ||
20 | #define USB_VID_DIBCOM 0x10b8 | ||
21 | #define USB_VID_DVICO 0x0fe9 | ||
22 | #define USB_VID_EMPIA 0xeb1a | ||
23 | #define USB_VID_GRANDTEC 0x5032 | ||
24 | #define USB_VID_HANFTEK 0x15f4 | ||
25 | #define USB_VID_HAUPPAUGE 0x2040 | ||
26 | #define USB_VID_HYPER_PALTEK 0x1025 | ||
27 | #define USB_VID_VISIONPLUS 0x13d3 | ||
28 | #define USB_VID_TWINHAN 0x1822 | ||
29 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 | ||
30 | |||
31 | /* Product IDs */ | ||
32 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 | ||
33 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 | ||
34 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 | ||
35 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 | ||
36 | #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 | ||
37 | #define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801 | ||
38 | #define USB_PID_COMPRO_DVBU2000_COLD 0xd000 | ||
39 | #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 | ||
40 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c | ||
41 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d | ||
42 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | ||
43 | #define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9 | ||
44 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 | ||
45 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 | ||
46 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 | ||
47 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 | ||
48 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 | ||
49 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de | ||
50 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df | ||
51 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 | ||
52 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 | ||
53 | #define USB_PID_TWINHAN_VP7045_COLD 0x3205 | ||
54 | #define USB_PID_TWINHAN_VP7045_WARM 0x3206 | ||
55 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 | ||
56 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 | ||
57 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 | ||
58 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 | ||
59 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 | ||
60 | #define USB_PID_ULTIMA_TVBOX_WARM 0x8106 | ||
61 | #define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107 | ||
62 | #define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108 | ||
63 | #define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235 | ||
64 | #define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109 | ||
65 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613 | ||
66 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002 | ||
67 | #define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e | ||
68 | #define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f | ||
69 | #define USB_PID_HANFTEK_UMT_010_COLD 0x0001 | ||
70 | #define USB_PID_HANFTEK_UMT_010_WARM 0x0015 | ||
71 | #define USB_PID_DTT200U_COLD 0x0201 | ||
72 | #define USB_PID_DTT200U_WARM 0x0301 | ||
73 | #define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300 | ||
74 | #define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 | ||
75 | #define USB_PID_NEBULA_DIGITV 0x0201 | ||
76 | #define USB_PID_DVICO_BLUEBIRD_LGZ201 0xdb00 | ||
77 | #define USB_PID_DVICO_BLUEBIRD_TH7579 0xdb10 | ||
78 | #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 | ||
79 | #define USB_PID_DVICO_BLUEBIRD_LGZ201_1 0xdb01 | ||
80 | #define USB_PID_DVICO_BLUEBIRD_TH7579_2 0xdb11 | ||
81 | |||
82 | |||
83 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c new file mode 100644 index 0000000000..3aadec974c --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * DVB USB library - provides a generic interface for a DVB USB device driver. | ||
3 | * | ||
4 | * dvb-usb-init.c | ||
5 | * | ||
6 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation, version 2. | ||
11 | * | ||
12 | * see Documentation/dvb/README.dvb-usb for more information | ||
13 | */ | ||
14 | #include "dvb-usb-common.h" | ||
15 | |||
16 | /* debug */ | ||
17 | int dvb_usb_debug; | ||
18 | module_param_named(debug,dvb_usb_debug, int, 0644); | ||
19 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." DVB_USB_DEBUG_STATUS); | ||
20 | |||
21 | /* general initialization functions */ | ||
22 | int dvb_usb_exit(struct dvb_usb_device *d) | ||
23 | { | ||
24 | deb_info("state before exiting everything: %x\n",d->state); | ||
25 | dvb_usb_remote_exit(d); | ||
26 | dvb_usb_fe_exit(d); | ||
27 | dvb_usb_i2c_exit(d); | ||
28 | dvb_usb_dvb_exit(d); | ||
29 | dvb_usb_urb_exit(d); | ||
30 | deb_info("state should be zero now: %x\n",d->state); | ||
31 | d->state = DVB_USB_STATE_INIT; | ||
32 | kfree(d->priv); | ||
33 | kfree(d); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int dvb_usb_init(struct dvb_usb_device *d) | ||
38 | { | ||
39 | int ret = 0; | ||
40 | |||
41 | sema_init(&d->usb_sem, 1); | ||
42 | sema_init(&d->i2c_sem, 1); | ||
43 | |||
44 | d->state = DVB_USB_STATE_INIT; | ||
45 | |||
46 | /* check the capabilites and set appropriate variables */ | ||
47 | |||
48 | /* speed - when running at FULL speed we need a HW PID filter */ | ||
49 | if (d->udev->speed == USB_SPEED_FULL && !(d->props.caps & DVB_USB_HAS_PID_FILTER)) { | ||
50 | err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a HW PID filter)"); | ||
51 | return -ENODEV; | ||
52 | } | ||
53 | |||
54 | if ((d->udev->speed == USB_SPEED_FULL && d->props.caps & DVB_USB_HAS_PID_FILTER) || | ||
55 | (d->props.caps & DVB_USB_NEED_PID_FILTERING)) { | ||
56 | info("will use the device's hw PID filter."); | ||
57 | d->pid_filtering = 1; | ||
58 | d->max_feed_count = d->props.pid_filter_count; | ||
59 | } else { | ||
60 | info("will pass the complete MPEG2 transport stream to the demuxer."); | ||
61 | d->pid_filtering = 0; | ||
62 | d->max_feed_count = 255; | ||
63 | } | ||
64 | |||
65 | if (d->props.power_ctrl) | ||
66 | d->props.power_ctrl(d,1); | ||
67 | |||
68 | if ((ret = dvb_usb_urb_init(d)) || | ||
69 | (ret = dvb_usb_dvb_init(d)) || | ||
70 | (ret = dvb_usb_i2c_init(d)) || | ||
71 | (ret = dvb_usb_fe_init(d))) { | ||
72 | dvb_usb_exit(d); | ||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | if ((ret = dvb_usb_remote_init(d))) | ||
77 | err("could not initialize remote control."); | ||
78 | |||
79 | if (d->props.power_ctrl) | ||
80 | d->props.power_ctrl(d,0); | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | /* determine the name and the state of the just found USB device */ | ||
86 | static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device *udev,struct dvb_usb_properties *props, int *cold) | ||
87 | { | ||
88 | int i,j; | ||
89 | struct dvb_usb_device_description *desc = NULL; | ||
90 | *cold = -1; | ||
91 | |||
92 | for (i = 0; i < props->num_device_descs; i++) { | ||
93 | |||
94 | for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].cold_ids[j] != NULL; j++) { | ||
95 | deb_info("check for cold %x %x\n",props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct); | ||
96 | if (props->devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) && | ||
97 | props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) { | ||
98 | *cold = 1; | ||
99 | desc = &props->devices[i]; | ||
100 | break; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | if (desc != NULL) | ||
105 | break; | ||
106 | |||
107 | for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].warm_ids[j] != NULL; j++) { | ||
108 | deb_info("check for warm %x %x\n",props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct); | ||
109 | if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) && | ||
110 | props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) { | ||
111 | *cold = 0; | ||
112 | desc = &props->devices[i]; | ||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | if (desc != NULL && props->identify_state != NULL) | ||
119 | props->identify_state(udev,props,&desc,cold); | ||
120 | |||
121 | return desc; | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * USB | ||
126 | */ | ||
127 | int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *props, struct module *owner) | ||
128 | { | ||
129 | struct usb_device *udev = interface_to_usbdev(intf); | ||
130 | struct dvb_usb_device *d = NULL; | ||
131 | struct dvb_usb_device_description *desc = NULL; | ||
132 | |||
133 | int ret = -ENOMEM,cold=0; | ||
134 | |||
135 | if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) { | ||
136 | deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n"); | ||
137 | return -ENODEV; | ||
138 | } | ||
139 | |||
140 | if (cold) { | ||
141 | info("found a '%s' in cold state, will try to load a firmware",desc->name); | ||
142 | ret = usb_cypress_load_firmware(udev,props->firmware,props->usb_ctrl); | ||
143 | } else { | ||
144 | info("found a '%s' in warm state.",desc->name); | ||
145 | d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL); | ||
146 | if (d == NULL) { | ||
147 | err("no memory for 'struct dvb_usb_device'"); | ||
148 | return ret; | ||
149 | } | ||
150 | memset(d,0,sizeof(struct dvb_usb_device)); | ||
151 | |||
152 | d->udev = udev; | ||
153 | memcpy(&d->props,props,sizeof(struct dvb_usb_properties)); | ||
154 | d->desc = desc; | ||
155 | d->owner = owner; | ||
156 | |||
157 | if (d->props.size_of_priv > 0) { | ||
158 | d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL); | ||
159 | if (d->priv == NULL) { | ||
160 | err("no memory for priv in 'struct dvb_usb_device'"); | ||
161 | kfree(d); | ||
162 | return -ENOMEM; | ||
163 | } | ||
164 | memset(d->priv,0,d->props.size_of_priv); | ||
165 | } | ||
166 | |||
167 | usb_set_intfdata(intf, d); | ||
168 | |||
169 | ret = dvb_usb_init(d); | ||
170 | } | ||
171 | |||
172 | if (ret == 0) | ||
173 | info("%s successfully initialized and connected.",desc->name); | ||
174 | else | ||
175 | info("%s error while loading driver (%d)",desc->name,ret); | ||
176 | return ret; | ||
177 | } | ||
178 | EXPORT_SYMBOL(dvb_usb_device_init); | ||
179 | |||
180 | void dvb_usb_device_exit(struct usb_interface *intf) | ||
181 | { | ||
182 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
183 | const char *name = "generic DVB-USB module"; | ||
184 | |||
185 | usb_set_intfdata(intf,NULL); | ||
186 | if (d != NULL && d->desc != NULL) { | ||
187 | name = d->desc->name; | ||
188 | dvb_usb_exit(d); | ||
189 | } | ||
190 | info("%s successfully deinitialized and disconnected.",name); | ||
191 | |||
192 | } | ||
193 | EXPORT_SYMBOL(dvb_usb_device_exit); | ||
194 | |||
195 | /* module stuff */ | ||
196 | static int __init dvb_usb_module_init(void) | ||
197 | { | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static void __exit dvb_usb_module_exit(void) | ||
202 | { | ||
203 | } | ||
204 | |||
205 | module_init (dvb_usb_module_init); | ||
206 | module_exit (dvb_usb_module_exit); | ||
207 | |||
208 | MODULE_VERSION("0.3"); | ||
209 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
210 | MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices"); | ||
211 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c new file mode 100644 index 0000000000..9f1e23f82b --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* dvb-usb-remote.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for initializing the the input-device and for handling remote-control-queries. | ||
7 | */ | ||
8 | #include "dvb-usb-common.h" | ||
9 | |||
10 | /* Remote-control poll function - called every dib->rc_query_interval ms to see | ||
11 | * whether the remote control has received anything. | ||
12 | * | ||
13 | * TODO: Fix the repeat rate of the input device. | ||
14 | */ | ||
15 | static void dvb_usb_read_remote_control(void *data) | ||
16 | { | ||
17 | struct dvb_usb_device *d = data; | ||
18 | u32 event; | ||
19 | int state; | ||
20 | |||
21 | /* TODO: need a lock here. We can simply skip checking for the remote control | ||
22 | if we're busy. */ | ||
23 | |||
24 | if (d->props.rc_query(d,&event,&state)) { | ||
25 | err("error while querying for an remote control event."); | ||
26 | goto schedule; | ||
27 | } | ||
28 | |||
29 | |||
30 | switch (state) { | ||
31 | case REMOTE_NO_KEY_PRESSED: | ||
32 | break; | ||
33 | case REMOTE_KEY_PRESSED: | ||
34 | deb_rc("key pressed\n"); | ||
35 | d->last_event = event; | ||
36 | case REMOTE_KEY_REPEAT: | ||
37 | deb_rc("key repeated\n"); | ||
38 | input_event(&d->rc_input_dev, EV_KEY, event, 1); | ||
39 | input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0); | ||
40 | input_sync(&d->rc_input_dev); | ||
41 | break; | ||
42 | default: | ||
43 | break; | ||
44 | } | ||
45 | |||
46 | /* improved repeat handling ??? | ||
47 | switch (state) { | ||
48 | case REMOTE_NO_KEY_PRESSED: | ||
49 | deb_rc("NO KEY PRESSED\n"); | ||
50 | if (d->last_state != REMOTE_NO_KEY_PRESSED) { | ||
51 | deb_rc("releasing event %d\n",d->last_event); | ||
52 | input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0); | ||
53 | input_sync(&d->rc_input_dev); | ||
54 | } | ||
55 | d->last_state = REMOTE_NO_KEY_PRESSED; | ||
56 | d->last_event = 0; | ||
57 | break; | ||
58 | case REMOTE_KEY_PRESSED: | ||
59 | deb_rc("KEY PRESSED\n"); | ||
60 | deb_rc("pressing event %d\n",event); | ||
61 | |||
62 | input_event(&d->rc_input_dev, EV_KEY, event, 1); | ||
63 | input_sync(&d->rc_input_dev); | ||
64 | |||
65 | d->last_event = event; | ||
66 | d->last_state = REMOTE_KEY_PRESSED; | ||
67 | break; | ||
68 | case REMOTE_KEY_REPEAT: | ||
69 | deb_rc("KEY_REPEAT\n"); | ||
70 | if (d->last_state != REMOTE_NO_KEY_PRESSED) { | ||
71 | deb_rc("repeating event %d\n",d->last_event); | ||
72 | input_event(&d->rc_input_dev, EV_KEY, d->last_event, 2); | ||
73 | input_sync(&d->rc_input_dev); | ||
74 | d->last_state = REMOTE_KEY_REPEAT; | ||
75 | } | ||
76 | default: | ||
77 | break; | ||
78 | } | ||
79 | */ | ||
80 | |||
81 | schedule: | ||
82 | schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); | ||
83 | } | ||
84 | |||
85 | int dvb_usb_remote_init(struct dvb_usb_device *d) | ||
86 | { | ||
87 | int i; | ||
88 | if (d->props.rc_key_map == NULL) | ||
89 | return 0; | ||
90 | |||
91 | /* Initialise the remote-control structures.*/ | ||
92 | init_input_dev(&d->rc_input_dev); | ||
93 | |||
94 | d->rc_input_dev.evbit[0] = BIT(EV_KEY); | ||
95 | d->rc_input_dev.keycodesize = sizeof(unsigned char); | ||
96 | d->rc_input_dev.keycodemax = KEY_MAX; | ||
97 | d->rc_input_dev.name = "IR-receiver inside an USB DVB receiver"; | ||
98 | |||
99 | /* set the bits for the keys */ | ||
100 | deb_rc("key map size: %d\n",d->props.rc_key_map_size); | ||
101 | for (i = 0; i < d->props.rc_key_map_size; i++) { | ||
102 | deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i); | ||
103 | set_bit(d->props.rc_key_map[i].event, d->rc_input_dev.keybit); | ||
104 | } | ||
105 | |||
106 | /* Start the remote-control polling. */ | ||
107 | if (d->props.rc_interval < 40) | ||
108 | d->props.rc_interval = 100; /* default */ | ||
109 | |||
110 | /* setting these two values to non-zero, we have to manage key repeats */ | ||
111 | d->rc_input_dev.rep[REP_PERIOD] = d->props.rc_interval; | ||
112 | d->rc_input_dev.rep[REP_DELAY] = d->props.rc_interval + 150; | ||
113 | |||
114 | input_register_device(&d->rc_input_dev); | ||
115 | |||
116 | INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d); | ||
117 | |||
118 | info("schedule remote query interval to %d msecs.",d->props.rc_interval); | ||
119 | schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); | ||
120 | |||
121 | d->state |= DVB_USB_STATE_REMOTE; | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | int dvb_usb_remote_exit(struct dvb_usb_device *d) | ||
127 | { | ||
128 | if (d->state & DVB_USB_STATE_REMOTE) { | ||
129 | cancel_delayed_work(&d->rc_query_work); | ||
130 | flush_scheduled_work(); | ||
131 | input_unregister_device(&d->rc_input_dev); | ||
132 | } | ||
133 | d->state &= ~DVB_USB_STATE_REMOTE; | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | #define DVB_USB_RC_NEC_EMPTY 0x00 | ||
138 | #define DVB_USB_RC_NEC_KEY_PRESSED 0x01 | ||
139 | #define DVB_USB_RC_NEC_KEY_REPEATED 0x02 | ||
140 | int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, | ||
141 | u8 keybuf[5], u32 *event, int *state) | ||
142 | { | ||
143 | int i; | ||
144 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | ||
145 | *event = 0; | ||
146 | *state = REMOTE_NO_KEY_PRESSED; | ||
147 | switch (keybuf[0]) { | ||
148 | case DVB_USB_RC_NEC_EMPTY: | ||
149 | break; | ||
150 | case DVB_USB_RC_NEC_KEY_PRESSED: | ||
151 | if ((u8) ~keybuf[1] != keybuf[2] || | ||
152 | (u8) ~keybuf[3] != keybuf[4]) { | ||
153 | deb_err("remote control checksum failed.\n"); | ||
154 | break; | ||
155 | } | ||
156 | /* See if we can match the raw key code. */ | ||
157 | for (i = 0; i < sizeof(keymap)/sizeof(struct dvb_usb_rc_key); i++) | ||
158 | if (keymap[i].custom == keybuf[1] && | ||
159 | keymap[i].data == keybuf[3]) { | ||
160 | *event = keymap[i].event; | ||
161 | *state = REMOTE_KEY_PRESSED; | ||
162 | break; | ||
163 | } | ||
164 | deb_err("key mapping failed - no appropriate key found in keymapping\n"); | ||
165 | break; | ||
166 | case DVB_USB_RC_NEC_KEY_REPEATED: | ||
167 | *state = REMOTE_KEY_REPEAT; | ||
168 | break; | ||
169 | default: | ||
170 | deb_err("unkown type of remote status: %d\n",keybuf[0]); | ||
171 | break; | ||
172 | } | ||
173 | return 0; | ||
174 | } | ||
175 | EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event); | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c new file mode 100644 index 0000000000..83d476fb41 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* dvb-usb-urb.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for initializing and handling the | ||
7 | * USB and URB stuff. | ||
8 | */ | ||
9 | #include "dvb-usb-common.h" | ||
10 | |||
11 | int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, | ||
12 | u16 rlen, int delay_ms) | ||
13 | { | ||
14 | int actlen,ret = -ENOMEM; | ||
15 | |||
16 | if (d->props.generic_bulk_ctrl_endpoint == 0) { | ||
17 | err("endpoint for generic control not specified."); | ||
18 | return -EINVAL; | ||
19 | } | ||
20 | |||
21 | if (wbuf == NULL || wlen == 0) | ||
22 | return -EINVAL; | ||
23 | |||
24 | if ((ret = down_interruptible(&d->usb_sem))) | ||
25 | return ret; | ||
26 | |||
27 | debug_dump(wbuf,wlen,deb_xfer); | ||
28 | |||
29 | ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev, | ||
30 | d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen, | ||
31 | 2*HZ); | ||
32 | |||
33 | if (ret) | ||
34 | err("bulk message failed: %d (%d/%d)",ret,wlen,actlen); | ||
35 | else | ||
36 | ret = actlen != wlen ? -1 : 0; | ||
37 | |||
38 | /* an answer is expected, and no error before */ | ||
39 | if (!ret && rbuf && rlen) { | ||
40 | if (delay_ms) | ||
41 | msleep(delay_ms); | ||
42 | |||
43 | ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev, | ||
44 | d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen, | ||
45 | 2*HZ); | ||
46 | |||
47 | if (ret) | ||
48 | err("recv bulk message failed: %d",ret); | ||
49 | else | ||
50 | debug_dump(rbuf,actlen,deb_xfer); | ||
51 | } | ||
52 | |||
53 | up(&d->usb_sem); | ||
54 | return ret; | ||
55 | } | ||
56 | EXPORT_SYMBOL(dvb_usb_generic_rw); | ||
57 | |||
58 | int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len) | ||
59 | { | ||
60 | return dvb_usb_generic_rw(d,buf,len,NULL,0,0); | ||
61 | } | ||
62 | EXPORT_SYMBOL(dvb_usb_generic_write); | ||
63 | |||
64 | static void dvb_usb_bulk_urb_complete(struct urb *urb, struct pt_regs *ptregs) | ||
65 | { | ||
66 | struct dvb_usb_device *d = urb->context; | ||
67 | |||
68 | deb_ts("bulk urb completed. feedcount: %d, status: %d, length: %d\n",d->feedcount,urb->status, | ||
69 | urb->actual_length); | ||
70 | |||
71 | switch (urb->status) { | ||
72 | case 0: /* success */ | ||
73 | case -ETIMEDOUT: /* NAK */ | ||
74 | break; | ||
75 | case -ECONNRESET: /* kill */ | ||
76 | case -ENOENT: | ||
77 | case -ESHUTDOWN: | ||
78 | return; | ||
79 | default: /* error */ | ||
80 | deb_ts("urb completition error %d.", urb->status); | ||
81 | break; | ||
82 | } | ||
83 | |||
84 | if (d->feedcount > 0 && urb->actual_length > 0) { | ||
85 | if (d->state & DVB_USB_STATE_DVB) | ||
86 | dvb_dmx_swfilter(&d->demux, (u8*) urb->transfer_buffer,urb->actual_length); | ||
87 | } else | ||
88 | deb_ts("URB dropped because of feedcount.\n"); | ||
89 | |||
90 | usb_submit_urb(urb,GFP_ATOMIC); | ||
91 | } | ||
92 | |||
93 | int dvb_usb_urb_kill(struct dvb_usb_device *d) | ||
94 | { | ||
95 | int i; | ||
96 | for (i = 0; i < d->urbs_submitted; i++) { | ||
97 | deb_info("killing URB no. %d.\n",i); | ||
98 | |||
99 | /* stop the URB */ | ||
100 | usb_kill_urb(d->urb_list[i]); | ||
101 | } | ||
102 | d->urbs_submitted = 0; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | int dvb_usb_urb_submit(struct dvb_usb_device *d) | ||
107 | { | ||
108 | int i,ret; | ||
109 | for (i = 0; i < d->urbs_initialized; i++) { | ||
110 | deb_info("submitting URB no. %d\n",i); | ||
111 | if ((ret = usb_submit_urb(d->urb_list[i],GFP_ATOMIC))) { | ||
112 | err("could not submit URB no. %d - get them all back\n",i); | ||
113 | dvb_usb_urb_kill(d); | ||
114 | return ret; | ||
115 | } | ||
116 | d->urbs_submitted++; | ||
117 | } | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d) | ||
122 | { | ||
123 | int i,bufsize = d->props.urb.count * d->props.urb.u.bulk.buffersize; | ||
124 | |||
125 | deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize); | ||
126 | /* allocate the actual buffer for the URBs */ | ||
127 | if ((d->buffer = usb_buffer_alloc(d->udev, bufsize, SLAB_ATOMIC, &d->dma_handle)) == NULL) { | ||
128 | deb_info("not enough memory for urb-buffer allocation.\n"); | ||
129 | return -ENOMEM; | ||
130 | } | ||
131 | deb_info("allocation successful\n"); | ||
132 | memset(d->buffer,0,bufsize); | ||
133 | |||
134 | d->state |= DVB_USB_STATE_URB_BUF; | ||
135 | |||
136 | /* allocate the URBs */ | ||
137 | for (i = 0; i < d->props.urb.count; i++) { | ||
138 | if (!(d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) { | ||
139 | return -ENOMEM; | ||
140 | } | ||
141 | |||
142 | usb_fill_bulk_urb( d->urb_list[i], d->udev, | ||
143 | usb_rcvbulkpipe(d->udev,d->props.urb.endpoint), | ||
144 | &d->buffer[i*d->props.urb.u.bulk.buffersize], | ||
145 | d->props.urb.u.bulk.buffersize, | ||
146 | dvb_usb_bulk_urb_complete, d); | ||
147 | |||
148 | d->urb_list[i]->transfer_flags = 0; | ||
149 | d->urbs_initialized++; | ||
150 | } | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | int dvb_usb_urb_init(struct dvb_usb_device *d) | ||
155 | { | ||
156 | /* | ||
157 | * when reloading the driver w/o replugging the device | ||
158 | * sometimes a timeout occures, this helps | ||
159 | */ | ||
160 | if (d->props.generic_bulk_ctrl_endpoint != 0) { | ||
161 | usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint)); | ||
162 | usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint)); | ||
163 | } | ||
164 | usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint)); | ||
165 | |||
166 | /* allocate the array for the data transfer URBs */ | ||
167 | d->urb_list = kmalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL); | ||
168 | if (d->urb_list == NULL) | ||
169 | return -ENOMEM; | ||
170 | memset(d->urb_list,0,d->props.urb.count * sizeof(struct urb *)); | ||
171 | d->state |= DVB_USB_STATE_URB_LIST; | ||
172 | |||
173 | switch (d->props.urb.type) { | ||
174 | case DVB_USB_BULK: | ||
175 | return dvb_usb_bulk_urb_init(d); | ||
176 | case DVB_USB_ISOC: | ||
177 | err("isochronous transfer not yet implemented in dvb-usb."); | ||
178 | return -EINVAL; | ||
179 | default: | ||
180 | err("unkown URB-type for data transfer."); | ||
181 | return -EINVAL; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | int dvb_usb_urb_exit(struct dvb_usb_device *d) | ||
186 | { | ||
187 | int i; | ||
188 | |||
189 | dvb_usb_urb_kill(d); | ||
190 | |||
191 | if (d->state & DVB_USB_STATE_URB_LIST) { | ||
192 | for (i = 0; i < d->urbs_initialized; i++) { | ||
193 | if (d->urb_list[i] != NULL) { | ||
194 | deb_info("freeing URB no. %d.\n",i); | ||
195 | /* free the URBs */ | ||
196 | usb_free_urb(d->urb_list[i]); | ||
197 | } | ||
198 | } | ||
199 | d->urbs_initialized = 0; | ||
200 | /* free the urb array */ | ||
201 | kfree(d->urb_list); | ||
202 | d->state &= ~DVB_USB_STATE_URB_LIST; | ||
203 | } | ||
204 | |||
205 | if (d->state & DVB_USB_STATE_URB_BUF) | ||
206 | usb_buffer_free(d->udev, d->props.urb.u.bulk.buffersize * d->props.urb.count, | ||
207 | d->buffer, d->dma_handle); | ||
208 | |||
209 | d->state &= ~DVB_USB_STATE_URB_BUF; | ||
210 | return 0; | ||
211 | } | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h new file mode 100644 index 0000000000..abcee1943f --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h | |||
@@ -0,0 +1,315 @@ | |||
1 | /* dvb-usb.h is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * the headerfile, all dvb-usb-drivers have to include. | ||
7 | */ | ||
8 | #ifndef __DVB_USB_H__ | ||
9 | #define __DVB_USB_H__ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/input.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/usb.h> | ||
15 | |||
16 | #include "dvb_frontend.h" | ||
17 | #include "dvb_demux.h" | ||
18 | #include "dvb_net.h" | ||
19 | #include "dmxdev.h" | ||
20 | |||
21 | #include "dvb-pll.h" | ||
22 | |||
23 | #include "dvb-usb-ids.h" | ||
24 | |||
25 | /* debug */ | ||
26 | #ifdef CONFIG_DVB_USB_DEBUG | ||
27 | #define dprintk(var,level,args...) \ | ||
28 | do { if ((var & level)) { printk(args); } } while (0) | ||
29 | |||
30 | #define debug_dump(b,l,func) {\ | ||
31 | int loop_; \ | ||
32 | for (loop_ = 0; loop_ < l; loop_++) func("%02x ", b[loop_]); \ | ||
33 | func("\n");\ | ||
34 | } | ||
35 | #define DVB_USB_DEBUG_STATUS | ||
36 | #else | ||
37 | #define dprintk(args...) | ||
38 | #define debug_dump(b,l,func) | ||
39 | |||
40 | #define DVB_USB_DEBUG_STATUS " (debugging is not enabled)" | ||
41 | |||
42 | #endif | ||
43 | |||
44 | /* generic log methods - taken from usb.h */ | ||
45 | #ifndef DVB_USB_LOG_PREFIX | ||
46 | #define DVB_USB_LOG_PREFIX "dvb-usb (please define a log prefix)" | ||
47 | #endif | ||
48 | |||
49 | #undef err | ||
50 | #define err(format, arg...) printk(KERN_ERR DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
51 | #undef info | ||
52 | #define info(format, arg...) printk(KERN_INFO DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
53 | #undef warn | ||
54 | #define warn(format, arg...) printk(KERN_WARNING DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
55 | |||
56 | /** | ||
57 | * struct dvb_usb_device_description - name and its according USB IDs | ||
58 | * @name: real name of the box, regardless which DVB USB device class is in use | ||
59 | * @cold_ids: array of struct usb_device_id which describe the device in | ||
60 | * pre-firmware state | ||
61 | * @warm_ids: array of struct usb_device_id which describe the device in | ||
62 | * post-firmware state | ||
63 | * | ||
64 | * Each DVB USB device class can have one or more actual devices, this struct | ||
65 | * assigns a name to it. | ||
66 | */ | ||
67 | struct dvb_usb_device_description { | ||
68 | const char *name; | ||
69 | |||
70 | #define DVB_USB_ID_MAX_NUM 15 | ||
71 | struct usb_device_id *cold_ids[DVB_USB_ID_MAX_NUM]; | ||
72 | struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM]; | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * struct dvb_usb_rc_key - a remote control key and its input-event | ||
77 | * @custom: the vendor/custom part of the key | ||
78 | * @data: the actual key part | ||
79 | * @event: the input event assigned to key identified by custom and data | ||
80 | */ | ||
81 | struct dvb_usb_rc_key { | ||
82 | u8 custom,data; | ||
83 | u32 event; | ||
84 | }; | ||
85 | |||
86 | struct dvb_usb_device; | ||
87 | |||
88 | /** | ||
89 | * struct dvb_usb_properties - properties of a dvb-usb-device | ||
90 | * @caps: capabilites of the DVB USB device. | ||
91 | * @pid_filter_count: number of PID filter position in the optional hardware | ||
92 | * PID-filter. | ||
93 | * | ||
94 | * @usb_ctrl: which USB device-side controller is in use. Needed for firmware | ||
95 | * download. | ||
96 | * @firmware: name of the firmware file. | ||
97 | * | ||
98 | * @size_of_priv: how many bytes shall be allocated for the private field | ||
99 | * of struct dvb_usb_device. | ||
100 | * | ||
101 | * @power_ctrl: called to enable/disable power of the device. | ||
102 | * @streaming_crtl: called to start and stop the MPEG2-TS streaming of the | ||
103 | * device (not URB submitting/killing). | ||
104 | * @pid_filter_ctrl: called to en/disable the PID filter, if any. | ||
105 | * @pid_filter: called to set/unset a PID for filtering. | ||
106 | * | ||
107 | * @read_mac_address: called to read the MAC address of the device. | ||
108 | * | ||
109 | * @frontend_attach: called to attach the possible frontends (fill fe-field | ||
110 | * of struct dvb_usb_device). | ||
111 | * @tuner_attach: called to attach the correct tuner and to fill pll_addr, | ||
112 | * pll_desc and pll_init_buf of struct dvb_usb_device). | ||
113 | * @identify_state: called to determine the state (cold or warm), when it | ||
114 | * is not distinguishable by the USB IDs. | ||
115 | * | ||
116 | * @rc_key_map: a hard-wired array of struct dvb_usb_rc_key (NULL to disable | ||
117 | * remote control handling). | ||
118 | * @rc_key_map_size: number of items in @rc_key_map. | ||
119 | * @rc_query: called to query an event event. | ||
120 | * @rc_interval: time in ms between two queries. | ||
121 | * | ||
122 | * @i2c_algo: i2c_algorithm if the device has I2CoverUSB. | ||
123 | * | ||
124 | * @generic_bulk_ctrl_endpoint: most of the DVB USB devices have a generic | ||
125 | * endpoint which received control messages with bulk transfers. When this | ||
126 | * is non-zero, one can use dvb_usb_generic_rw and dvb_usb_generic_write- | ||
127 | * helper functions. | ||
128 | * | ||
129 | * @urb: describes the kind of USB transfer used for MPEG2-TS-streaming. | ||
130 | * Currently only BULK is implemented | ||
131 | * | ||
132 | * @num_device_descs: number of struct dvb_usb_device_description in @devices | ||
133 | * @devices: array of struct dvb_usb_device_description compatibles with these | ||
134 | * properties. | ||
135 | */ | ||
136 | struct dvb_usb_properties { | ||
137 | |||
138 | #define DVB_USB_HAS_PID_FILTER 0x01 | ||
139 | #define DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF 0x02 | ||
140 | #define DVB_USB_NEED_PID_FILTERING 0x04 | ||
141 | #define DVB_USB_IS_AN_I2C_ADAPTER 0x08 | ||
142 | int caps; | ||
143 | int pid_filter_count; | ||
144 | |||
145 | #define CYPRESS_AN2135 0 | ||
146 | #define CYPRESS_AN2235 1 | ||
147 | #define CYPRESS_FX2 2 | ||
148 | int usb_ctrl; | ||
149 | const char *firmware; | ||
150 | |||
151 | int size_of_priv; | ||
152 | |||
153 | int (*power_ctrl) (struct dvb_usb_device *, int); | ||
154 | int (*streaming_ctrl) (struct dvb_usb_device *, int); | ||
155 | int (*pid_filter_ctrl) (struct dvb_usb_device *, int); | ||
156 | int (*pid_filter) (struct dvb_usb_device *, int, u16, int); | ||
157 | |||
158 | int (*read_mac_address) (struct dvb_usb_device *, u8 []); | ||
159 | int (*frontend_attach) (struct dvb_usb_device *); | ||
160 | int (*tuner_attach) (struct dvb_usb_device *); | ||
161 | |||
162 | int (*identify_state) (struct usb_device *, struct dvb_usb_properties *, | ||
163 | struct dvb_usb_device_description **, int *); | ||
164 | |||
165 | /* remote control properties */ | ||
166 | #define REMOTE_NO_KEY_PRESSED 0x00 | ||
167 | #define REMOTE_KEY_PRESSED 0x01 | ||
168 | #define REMOTE_KEY_REPEAT 0x02 | ||
169 | struct dvb_usb_rc_key *rc_key_map; | ||
170 | int rc_key_map_size; | ||
171 | int (*rc_query) (struct dvb_usb_device *, u32 *, int *); | ||
172 | int rc_interval; | ||
173 | |||
174 | struct i2c_algorithm *i2c_algo; | ||
175 | |||
176 | int generic_bulk_ctrl_endpoint; | ||
177 | |||
178 | struct { | ||
179 | #define DVB_USB_BULK 1 | ||
180 | #define DVB_USB_ISOC 2 | ||
181 | int type; | ||
182 | int count; | ||
183 | int endpoint; | ||
184 | |||
185 | union { | ||
186 | struct { | ||
187 | int buffersize; /* per URB */ | ||
188 | } bulk; | ||
189 | struct { | ||
190 | int framesperurb; | ||
191 | int framesize; | ||
192 | } isoc; | ||
193 | } u; | ||
194 | } urb; | ||
195 | |||
196 | int num_device_descs; | ||
197 | struct dvb_usb_device_description devices[8]; | ||
198 | }; | ||
199 | |||
200 | |||
201 | /** | ||
202 | * struct dvb_usb_device - object of a DVB USB device | ||
203 | * @props: copy of the struct dvb_usb_properties this device belongs to. | ||
204 | * @desc: pointer to the device's struct dvb_usb_device_description. | ||
205 | * @state: initialization and runtime state of the device. | ||
206 | * | ||
207 | * @udev: pointer to the device's struct usb_device. | ||
208 | * @urb_list: array of dynamically allocated struct urb for the MPEG2-TS- | ||
209 | * streaming. | ||
210 | * @buffer: buffer used to streaming. | ||
211 | * @dma_handle: dma_addr_t for buffer. | ||
212 | * @urbs_initialized: number of URBs initialized. | ||
213 | * @urbs_submitted: number of URBs submitted. | ||
214 | * @feedcount: number of reqested feeds (used for streaming-activation) | ||
215 | * @pid_filtering: is hardware pid_filtering used or not. | ||
216 | * @usb_sem: semaphore of USB control messages (reading needs two messages) | ||
217 | * @i2c_sem: semaphore for i2c-transfers | ||
218 | * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB | ||
219 | * @pll_addr: I2C address of the tuner for programming | ||
220 | * @pll_init: array containing the initialization buffer | ||
221 | * @pll_desc: pointer to the appropriate struct dvb_pll_desc | ||
222 | * @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod | ||
223 | * @dvb_adap: device's dvb_adapter. | ||
224 | * @dmxdev: device's dmxdev. | ||
225 | * @demux: device's software demuxer. | ||
226 | * @dvb_net: device's dvb_net interfaces. | ||
227 | * @dvb_frontend: device's frontend. | ||
228 | * @max_feed_count: how many feeds can be handled simultaneously by this | ||
229 | * device | ||
230 | * @fe_sleep: rerouted frontend-sleep function. | ||
231 | * @fe_init: rerouted frontend-init (wakeup) function. | ||
232 | * @rc_input_dev: input device for the remote control. | ||
233 | * @rc_query_work: struct work_struct frequent rc queries | ||
234 | * @last_event: last triggered event | ||
235 | * @last_state: last state (no, pressed, repeat) | ||
236 | * @owner: owner of the dvb_adapter | ||
237 | * @priv: private data of the actual driver (allocate by dvb-usb, size defined | ||
238 | * in size_of_priv of dvb_usb_properties). | ||
239 | */ | ||
240 | struct dvb_usb_device { | ||
241 | struct dvb_usb_properties props; | ||
242 | struct dvb_usb_device_description *desc; | ||
243 | |||
244 | #define DVB_USB_STATE_INIT 0x000 | ||
245 | #define DVB_USB_STATE_URB_LIST 0x001 | ||
246 | #define DVB_USB_STATE_URB_BUF 0x002 | ||
247 | #define DVB_USB_STATE_DVB 0x004 | ||
248 | #define DVB_USB_STATE_I2C 0x008 | ||
249 | #define DVB_USB_STATE_REMOTE 0x010 | ||
250 | #define DVB_USB_STATE_URB_SUBMIT 0x020 | ||
251 | int state; | ||
252 | |||
253 | /* usb */ | ||
254 | struct usb_device *udev; | ||
255 | struct urb **urb_list; | ||
256 | u8 *buffer; | ||
257 | dma_addr_t dma_handle; | ||
258 | int urbs_initialized; | ||
259 | int urbs_submitted; | ||
260 | |||
261 | int feedcount; | ||
262 | int pid_filtering; | ||
263 | |||
264 | /* locking */ | ||
265 | struct semaphore usb_sem; | ||
266 | |||
267 | /* i2c */ | ||
268 | struct semaphore i2c_sem; | ||
269 | struct i2c_adapter i2c_adap; | ||
270 | |||
271 | /* tuner programming information */ | ||
272 | u8 pll_addr; | ||
273 | u8 pll_init[4]; | ||
274 | struct dvb_pll_desc *pll_desc; | ||
275 | int (*tuner_pass_ctrl)(struct dvb_frontend *, int, u8); | ||
276 | |||
277 | /* dvb */ | ||
278 | struct dvb_adapter dvb_adap; | ||
279 | struct dmxdev dmxdev; | ||
280 | struct dvb_demux demux; | ||
281 | struct dvb_net dvb_net; | ||
282 | struct dvb_frontend* fe; | ||
283 | int max_feed_count; | ||
284 | |||
285 | int (*fe_sleep) (struct dvb_frontend *); | ||
286 | int (*fe_init) (struct dvb_frontend *); | ||
287 | |||
288 | /* remote control */ | ||
289 | struct input_dev rc_input_dev; | ||
290 | struct work_struct rc_query_work; | ||
291 | u32 last_event; | ||
292 | int last_state; | ||
293 | |||
294 | struct module *owner; | ||
295 | |||
296 | void *priv; | ||
297 | }; | ||
298 | |||
299 | extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *); | ||
300 | extern void dvb_usb_device_exit(struct usb_interface *); | ||
301 | |||
302 | /* the generic read/write method for device control */ | ||
303 | extern int dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16,int); | ||
304 | extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16); | ||
305 | |||
306 | /* commonly used remote control parsing */ | ||
307 | extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *); | ||
308 | |||
309 | /* commonly used pll init and set functions */ | ||
310 | extern int dvb_usb_pll_init_i2c(struct dvb_frontend *); | ||
311 | extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]); | ||
312 | extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *); | ||
313 | |||
314 | |||
315 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c new file mode 100644 index 0000000000..9d83781aef --- /dev/null +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* DVB USB framework compliant Linux driver for the Hauppauge WinTV-NOVA-T usb2 | ||
2 | * DVB-T receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation, version 2. | ||
9 | * | ||
10 | * see Documentation/dvb/README.dvb-usb for more information | ||
11 | */ | ||
12 | #include "dibusb.h" | ||
13 | |||
14 | static int debug; | ||
15 | module_param(debug, int, 0644); | ||
16 | MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS); | ||
17 | |||
18 | #define deb_rc(args...) dprintk(debug,0x01,args) | ||
19 | #define deb_ee(args...) dprintk(debug,0x02,args) | ||
20 | |||
21 | /* Hauppauge NOVA-T USB2 keys */ | ||
22 | static struct dvb_usb_rc_key haupp_rc_keys [] = { | ||
23 | { 0x1e, 0x00, KEY_0 }, | ||
24 | { 0x1e, 0x01, KEY_1 }, | ||
25 | { 0x1e, 0x02, KEY_2 }, | ||
26 | { 0x1e, 0x03, KEY_3 }, | ||
27 | { 0x1e, 0x04, KEY_4 }, | ||
28 | { 0x1e, 0x05, KEY_5 }, | ||
29 | { 0x1e, 0x06, KEY_6 }, | ||
30 | { 0x1e, 0x07, KEY_7 }, | ||
31 | { 0x1e, 0x08, KEY_8 }, | ||
32 | { 0x1e, 0x09, KEY_9 }, | ||
33 | { 0x1e, 0x0a, KEY_KPASTERISK }, | ||
34 | { 0x1e, 0x0b, KEY_RED }, | ||
35 | { 0x1e, 0x0c, KEY_RADIO }, | ||
36 | { 0x1e, 0x0d, KEY_MENU }, | ||
37 | { 0x1e, 0x0e, KEY_GRAVE }, /* # */ | ||
38 | { 0x1e, 0x0f, KEY_MUTE }, | ||
39 | { 0x1e, 0x10, KEY_VOLUMEUP }, | ||
40 | { 0x1e, 0x11, KEY_VOLUMEDOWN }, | ||
41 | { 0x1e, 0x12, KEY_CHANNEL }, | ||
42 | { 0x1e, 0x14, KEY_UP }, | ||
43 | { 0x1e, 0x15, KEY_DOWN }, | ||
44 | { 0x1e, 0x16, KEY_LEFT }, | ||
45 | { 0x1e, 0x17, KEY_RIGHT }, | ||
46 | { 0x1e, 0x18, KEY_VIDEO }, | ||
47 | { 0x1e, 0x19, KEY_AUDIO }, | ||
48 | { 0x1e, 0x1a, KEY_MEDIA }, | ||
49 | { 0x1e, 0x1b, KEY_EPG }, | ||
50 | { 0x1e, 0x1c, KEY_TV }, | ||
51 | { 0x1e, 0x1e, KEY_NEXT }, | ||
52 | { 0x1e, 0x1f, KEY_BACK }, | ||
53 | { 0x1e, 0x20, KEY_CHANNELUP }, | ||
54 | { 0x1e, 0x21, KEY_CHANNELDOWN }, | ||
55 | { 0x1e, 0x24, KEY_LAST }, /* Skip backwards */ | ||
56 | { 0x1e, 0x25, KEY_OK }, | ||
57 | { 0x1e, 0x29, KEY_BLUE}, | ||
58 | { 0x1e, 0x2e, KEY_GREEN }, | ||
59 | { 0x1e, 0x30, KEY_PAUSE }, | ||
60 | { 0x1e, 0x32, KEY_REWIND }, | ||
61 | { 0x1e, 0x34, KEY_FASTFORWARD }, | ||
62 | { 0x1e, 0x35, KEY_PLAY }, | ||
63 | { 0x1e, 0x36, KEY_STOP }, | ||
64 | { 0x1e, 0x37, KEY_RECORD }, | ||
65 | { 0x1e, 0x38, KEY_YELLOW }, | ||
66 | { 0x1e, 0x3b, KEY_GOTO }, | ||
67 | { 0x1e, 0x3d, KEY_POWER }, | ||
68 | }; | ||
69 | |||
70 | /* Firmware bug? sometimes, when a new key is pressed, the previous pressed key | ||
71 | * is delivered. No workaround yet, maybe a new firmware. | ||
72 | */ | ||
73 | static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
74 | { | ||
75 | u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom; | ||
76 | u16 raw; | ||
77 | int i; | ||
78 | struct dibusb_state *st = d->priv; | ||
79 | |||
80 | dvb_usb_generic_rw(d,cmd,2,key,5,0); | ||
81 | |||
82 | *state = REMOTE_NO_KEY_PRESSED; | ||
83 | switch (key[0]) { | ||
84 | case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED: | ||
85 | raw = ((key[1] << 8) | key[2]) >> 3; | ||
86 | toggle = !!(raw & 0x800); | ||
87 | data = raw & 0x3f; | ||
88 | custom = (raw >> 6) & 0x1f; | ||
89 | |||
90 | deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle); | ||
91 | |||
92 | for (i = 0; i < ARRAY_SIZE(haupp_rc_keys); i++) { | ||
93 | deb_rc("c: %x, d: %x\n",haupp_rc_keys[i].data,haupp_rc_keys[i].custom); | ||
94 | if (haupp_rc_keys[i].data == data && | ||
95 | haupp_rc_keys[i].custom == custom) { | ||
96 | *event = haupp_rc_keys[i].event; | ||
97 | *state = REMOTE_KEY_PRESSED; | ||
98 | if (st->old_toggle == toggle) { | ||
99 | if (st->last_repeat_count++ < 2) | ||
100 | *state = REMOTE_NO_KEY_PRESSED; | ||
101 | } else { | ||
102 | st->last_repeat_count = 0; | ||
103 | st->old_toggle = toggle; | ||
104 | } | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | break; | ||
110 | case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY: | ||
111 | default: | ||
112 | break; | ||
113 | } | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6]) | ||
119 | { | ||
120 | int i; | ||
121 | u8 b; | ||
122 | |||
123 | mac[0] = 0x00; | ||
124 | mac[1] = 0x0d; | ||
125 | mac[2] = 0xfe; | ||
126 | |||
127 | /* this is a complete guess, but works for my box */ | ||
128 | for (i = 136; i < 139; i++) { | ||
129 | dibusb_read_eeprom_byte(d,i, &b); | ||
130 | |||
131 | mac[5 - (i - 136)] = b; | ||
132 | |||
133 | /* deb_ee("%02x ",b); | ||
134 | if ((i+1) % 16 == 0) | ||
135 | deb_ee("\n");*/ | ||
136 | } | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | /* USB Driver stuff */ | ||
142 | static struct dvb_usb_properties nova_t_properties; | ||
143 | |||
144 | static int nova_t_probe(struct usb_interface *intf, | ||
145 | const struct usb_device_id *id) | ||
146 | { | ||
147 | return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE); | ||
148 | } | ||
149 | |||
150 | /* do not change the order of the ID table */ | ||
151 | static struct usb_device_id nova_t_table [] = { | ||
152 | /* 00 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_COLD) }, | ||
153 | /* 01 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) }, | ||
154 | { } /* Terminating entry */ | ||
155 | }; | ||
156 | MODULE_DEVICE_TABLE (usb, nova_t_table); | ||
157 | |||
158 | static struct dvb_usb_properties nova_t_properties = { | ||
159 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
160 | .pid_filter_count = 32, | ||
161 | |||
162 | .usb_ctrl = CYPRESS_FX2, | ||
163 | .firmware = "dvb-usb-nova-t-usb2-01.fw", | ||
164 | |||
165 | .size_of_priv = sizeof(struct dibusb_state), | ||
166 | |||
167 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
168 | .pid_filter = dibusb_pid_filter, | ||
169 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
170 | .power_ctrl = dibusb2_0_power_ctrl, | ||
171 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | ||
172 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | ||
173 | .read_mac_address = nova_t_read_mac_address, | ||
174 | |||
175 | .rc_interval = 100, | ||
176 | .rc_key_map = haupp_rc_keys, | ||
177 | .rc_key_map_size = ARRAY_SIZE(haupp_rc_keys), | ||
178 | .rc_query = nova_t_rc_query, | ||
179 | |||
180 | .i2c_algo = &dibusb_i2c_algo, | ||
181 | |||
182 | .generic_bulk_ctrl_endpoint = 0x01, | ||
183 | /* parameter for the MPEG2-data transfer */ | ||
184 | .urb = { | ||
185 | .type = DVB_USB_BULK, | ||
186 | .count = 7, | ||
187 | .endpoint = 0x06, | ||
188 | .u = { | ||
189 | .bulk = { | ||
190 | .buffersize = 4096, | ||
191 | } | ||
192 | } | ||
193 | }, | ||
194 | |||
195 | .num_device_descs = 1, | ||
196 | .devices = { | ||
197 | { "Hauppauge WinTV-NOVA-T usb2", | ||
198 | { &nova_t_table[0], NULL }, | ||
199 | { &nova_t_table[1], NULL }, | ||
200 | }, | ||
201 | } | ||
202 | }; | ||
203 | |||
204 | static struct usb_driver nova_t_driver = { | ||
205 | .owner = THIS_MODULE, | ||
206 | .name = "Hauppauge WinTV-NOVA-T usb2", | ||
207 | .probe = nova_t_probe, | ||
208 | .disconnect = dvb_usb_device_exit, | ||
209 | .id_table = nova_t_table, | ||
210 | }; | ||
211 | |||
212 | /* module stuff */ | ||
213 | static int __init nova_t_module_init(void) | ||
214 | { | ||
215 | int result; | ||
216 | if ((result = usb_register(&nova_t_driver))) { | ||
217 | err("usb_register failed. Error number %d",result); | ||
218 | return result; | ||
219 | } | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static void __exit nova_t_module_exit(void) | ||
225 | { | ||
226 | /* deregister this driver from the USB subsystem */ | ||
227 | usb_deregister(&nova_t_driver); | ||
228 | } | ||
229 | |||
230 | module_init (nova_t_module_init); | ||
231 | module_exit (nova_t_module_exit); | ||
232 | |||
233 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
234 | MODULE_DESCRIPTION("Hauppauge WinTV-NOVA-T usb2"); | ||
235 | MODULE_VERSION("1.0"); | ||
236 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c new file mode 100644 index 0000000000..aa560422ce --- /dev/null +++ b/drivers/media/dvb/dvb-usb/umt-010.c | |||
@@ -0,0 +1,162 @@ | |||
1 | /* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0 | ||
2 | * DVB-T receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation, version 2. | ||
9 | * | ||
10 | * see Documentation/dvb/README.dvb-usb for more information | ||
11 | */ | ||
12 | #include "dibusb.h" | ||
13 | |||
14 | #include "mt352.h" | ||
15 | |||
16 | static int umt_mt352_demod_init(struct dvb_frontend *fe) | ||
17 | { | ||
18 | static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d }; | ||
19 | static u8 mt352_reset[] = { 0x50, 0x80 }; | ||
20 | static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 }; | ||
21 | static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 }; | ||
22 | static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 }; | ||
23 | |||
24 | static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff }; | ||
25 | static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff }; | ||
26 | static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 }; | ||
27 | static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 }; | ||
28 | static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f }; | ||
29 | |||
30 | static u8 mt352_acq_ctl[] = { 0x53, 0x50 }; | ||
31 | static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 }; | ||
32 | |||
33 | mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); | ||
34 | udelay(2000); | ||
35 | mt352_write(fe, mt352_reset, sizeof(mt352_reset)); | ||
36 | mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio)); | ||
37 | |||
38 | mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); | ||
39 | mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); | ||
40 | |||
41 | mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1)); | ||
42 | mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2)); | ||
43 | mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3)); | ||
44 | mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4)); | ||
45 | mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5)); | ||
46 | |||
47 | mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl)); | ||
48 | mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1)); | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static int umt_mt352_frontend_attach(struct dvb_usb_device *d) | ||
54 | { | ||
55 | struct mt352_config umt_config; | ||
56 | |||
57 | memset(&umt_config,0,sizeof(struct mt352_config)); | ||
58 | umt_config.demod_init = umt_mt352_demod_init; | ||
59 | umt_config.demod_address = 0xf; | ||
60 | umt_config.pll_set = dvb_usb_pll_set; | ||
61 | |||
62 | d->fe = mt352_attach(&umt_config, &d->i2c_adap); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int umt_tuner_attach (struct dvb_usb_device *d) | ||
68 | { | ||
69 | d->pll_addr = 0x61; | ||
70 | d->pll_desc = &dvb_pll_tua6034; | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | /* USB Driver stuff */ | ||
75 | static struct dvb_usb_properties umt_properties; | ||
76 | |||
77 | static int umt_probe(struct usb_interface *intf, | ||
78 | const struct usb_device_id *id) | ||
79 | { | ||
80 | if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE) == 0) | ||
81 | return 0; | ||
82 | return -EINVAL; | ||
83 | } | ||
84 | |||
85 | /* do not change the order of the ID table */ | ||
86 | static struct usb_device_id umt_table [] = { | ||
87 | /* 00 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) }, | ||
88 | /* 01 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) }, | ||
89 | { } /* Terminating entry */ | ||
90 | }; | ||
91 | MODULE_DEVICE_TABLE (usb, umt_table); | ||
92 | |||
93 | static struct dvb_usb_properties umt_properties = { | ||
94 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
95 | |||
96 | .usb_ctrl = CYPRESS_FX2, | ||
97 | .firmware = "dvb-usb-umt-010-02.fw", | ||
98 | |||
99 | .size_of_priv = sizeof(struct dibusb_state), | ||
100 | |||
101 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
102 | .power_ctrl = dibusb_power_ctrl, | ||
103 | .frontend_attach = umt_mt352_frontend_attach, | ||
104 | .tuner_attach = umt_tuner_attach, | ||
105 | |||
106 | .i2c_algo = &dibusb_i2c_algo, | ||
107 | |||
108 | .generic_bulk_ctrl_endpoint = 0x01, | ||
109 | /* parameter for the MPEG2-data transfer */ | ||
110 | .urb = { | ||
111 | .type = DVB_USB_BULK, | ||
112 | .count = 20, | ||
113 | .endpoint = 0x06, | ||
114 | .u = { | ||
115 | .bulk = { | ||
116 | .buffersize = 512, | ||
117 | } | ||
118 | } | ||
119 | }, | ||
120 | |||
121 | .num_device_descs = 1, | ||
122 | .devices = { | ||
123 | { "Hanftek UMT-010 DVB-T USB2.0", | ||
124 | { &umt_table[0], NULL }, | ||
125 | { &umt_table[1], NULL }, | ||
126 | }, | ||
127 | } | ||
128 | }; | ||
129 | |||
130 | static struct usb_driver umt_driver = { | ||
131 | .owner = THIS_MODULE, | ||
132 | .name = "HanfTek UMT-010 USB2.0 DVB-T devices", | ||
133 | .probe = umt_probe, | ||
134 | .disconnect = dvb_usb_device_exit, | ||
135 | .id_table = umt_table, | ||
136 | }; | ||
137 | |||
138 | /* module stuff */ | ||
139 | static int __init umt_module_init(void) | ||
140 | { | ||
141 | int result; | ||
142 | if ((result = usb_register(&umt_driver))) { | ||
143 | err("usb_register failed. Error number %d",result); | ||
144 | return result; | ||
145 | } | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static void __exit umt_module_exit(void) | ||
151 | { | ||
152 | /* deregister this driver from the USB subsystem */ | ||
153 | usb_deregister(&umt_driver); | ||
154 | } | ||
155 | |||
156 | module_init (umt_module_init); | ||
157 | module_exit (umt_module_exit); | ||
158 | |||
159 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
160 | MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device"); | ||
161 | MODULE_VERSION("1.0"); | ||
162 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c new file mode 100644 index 0000000000..2746edfecc --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0 | ||
2 | * DVB-T receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * Thanks to Twinhan who kindly provided hardware and information. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation, version 2. | ||
11 | * | ||
12 | * see Documentation/dvb/README.dvb-usb for more information | ||
13 | * | ||
14 | */ | ||
15 | #include "vp7045.h" | ||
16 | |||
17 | /* It is a Zarlink MT352 within a Samsung Tuner (DNOS404ZH102A) - 040929 - AAT | ||
18 | * | ||
19 | * Programming is hidden inside the firmware, so set_frontend is very easy. | ||
20 | * Even though there is a Firmware command that one can use to access the demod | ||
21 | * via its registers. This is used for status information. | ||
22 | */ | ||
23 | |||
24 | struct vp7045_fe_state { | ||
25 | struct dvb_frontend fe; | ||
26 | struct dvb_usb_device *d; | ||
27 | }; | ||
28 | |||
29 | |||
30 | static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) | ||
31 | { | ||
32 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
33 | u8 s0 = vp7045_read_reg(state->d,0x00), | ||
34 | s1 = vp7045_read_reg(state->d,0x01), | ||
35 | s3 = vp7045_read_reg(state->d,0x03); | ||
36 | |||
37 | *status = 0; | ||
38 | if (s0 & (1 << 4)) | ||
39 | *status |= FE_HAS_CARRIER; | ||
40 | if (s0 & (1 << 1)) | ||
41 | *status |= FE_HAS_VITERBI; | ||
42 | if (s0 & (1 << 5)) | ||
43 | *status |= FE_HAS_LOCK; | ||
44 | if (s1 & (1 << 1)) | ||
45 | *status |= FE_HAS_SYNC; | ||
46 | if (s3 & (1 << 6)) | ||
47 | *status |= FE_HAS_SIGNAL; | ||
48 | |||
49 | if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != | ||
50 | (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) | ||
51 | *status &= ~FE_HAS_LOCK; | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static int vp7045_fe_read_ber(struct dvb_frontend* fe, u32 *ber) | ||
57 | { | ||
58 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
59 | *ber = (vp7045_read_reg(state->d, 0x0D) << 16) | | ||
60 | (vp7045_read_reg(state->d, 0x0E) << 8) | | ||
61 | vp7045_read_reg(state->d, 0x0F); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int vp7045_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | ||
66 | { | ||
67 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
68 | *unc = (vp7045_read_reg(state->d, 0x10) << 8) | | ||
69 | vp7045_read_reg(state->d, 0x11); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int vp7045_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) | ||
74 | { | ||
75 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
76 | u16 signal = (vp7045_read_reg(state->d, 0x14) << 8) | | ||
77 | vp7045_read_reg(state->d, 0x15); | ||
78 | |||
79 | *strength = ~signal; | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int vp7045_fe_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
84 | { | ||
85 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
86 | u8 _snr = vp7045_read_reg(state->d, 0x09); | ||
87 | *snr = (_snr << 8) | _snr; | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int vp7045_fe_init(struct dvb_frontend* fe) | ||
92 | { | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int vp7045_fe_sleep(struct dvb_frontend* fe) | ||
97 | { | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | ||
102 | { | ||
103 | tune->min_delay_ms = 800; | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int vp7045_fe_set_frontend(struct dvb_frontend* fe, | ||
108 | struct dvb_frontend_parameters *fep) | ||
109 | { | ||
110 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
111 | u8 buf[5]; | ||
112 | u32 freq = fep->frequency / 1000; | ||
113 | |||
114 | buf[0] = (freq >> 16) & 0xff; | ||
115 | buf[1] = (freq >> 8) & 0xff; | ||
116 | buf[2] = freq & 0xff; | ||
117 | buf[3] = 0; | ||
118 | |||
119 | switch (fep->u.ofdm.bandwidth) { | ||
120 | case BANDWIDTH_8_MHZ: buf[4] = 8; break; | ||
121 | case BANDWIDTH_7_MHZ: buf[4] = 7; break; | ||
122 | case BANDWIDTH_6_MHZ: buf[4] = 6; break; | ||
123 | case BANDWIDTH_AUTO: return -EOPNOTSUPP; | ||
124 | default: | ||
125 | return -EINVAL; | ||
126 | } | ||
127 | |||
128 | vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int vp7045_fe_get_frontend(struct dvb_frontend* fe, | ||
133 | struct dvb_frontend_parameters *fep) | ||
134 | { | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static void vp7045_fe_release(struct dvb_frontend* fe) | ||
139 | { | ||
140 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
141 | kfree(state); | ||
142 | } | ||
143 | |||
144 | static struct dvb_frontend_ops vp7045_fe_ops; | ||
145 | |||
146 | struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d) | ||
147 | { | ||
148 | struct vp7045_fe_state *s = kmalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL); | ||
149 | if (s == NULL) | ||
150 | goto error; | ||
151 | memset(s,0,sizeof(struct vp7045_fe_state)); | ||
152 | |||
153 | s->d = d; | ||
154 | s->fe.ops = &vp7045_fe_ops; | ||
155 | s->fe.demodulator_priv = s; | ||
156 | |||
157 | goto success; | ||
158 | error: | ||
159 | return NULL; | ||
160 | success: | ||
161 | return &s->fe; | ||
162 | } | ||
163 | |||
164 | |||
165 | static struct dvb_frontend_ops vp7045_fe_ops = { | ||
166 | .info = { | ||
167 | .name = "Twinhan VP7045/46 USB DVB-T", | ||
168 | .type = FE_OFDM, | ||
169 | .frequency_min = 44250000, | ||
170 | .frequency_max = 867250000, | ||
171 | .frequency_stepsize = 1000, | ||
172 | .caps = FE_CAN_INVERSION_AUTO | | ||
173 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
174 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
175 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
176 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
177 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
178 | FE_CAN_RECOVER | | ||
179 | FE_CAN_HIERARCHY_AUTO, | ||
180 | }, | ||
181 | |||
182 | .release = vp7045_fe_release, | ||
183 | |||
184 | .init = vp7045_fe_init, | ||
185 | .sleep = vp7045_fe_sleep, | ||
186 | |||
187 | .set_frontend = vp7045_fe_set_frontend, | ||
188 | .get_frontend = vp7045_fe_get_frontend, | ||
189 | .get_tune_settings = vp7045_fe_get_tune_settings, | ||
190 | |||
191 | .read_status = vp7045_fe_read_status, | ||
192 | .read_ber = vp7045_fe_read_ber, | ||
193 | .read_signal_strength = vp7045_fe_read_signal_strength, | ||
194 | .read_snr = vp7045_fe_read_snr, | ||
195 | .read_ucblocks = vp7045_fe_read_unc_blocks, | ||
196 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c new file mode 100644 index 0000000000..02ecc9a8e3 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp7045.c | |||
@@ -0,0 +1,263 @@ | |||
1 | /* DVB USB compliant Linux driver for the | ||
2 | * - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver | ||
3 | * - DigitalNow TinyUSB2 DVB-t receiver | ||
4 | * | ||
5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
6 | * | ||
7 | * Thanks to Twinhan who kindly provided hardware and information. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation, version 2. | ||
12 | * | ||
13 | * see Documentation/dvb/README.dvb-usb for more information | ||
14 | */ | ||
15 | #include "vp7045.h" | ||
16 | |||
17 | /* debug */ | ||
18 | int dvb_usb_vp7045_debug; | ||
19 | module_param_named(debug,dvb_usb_vp7045_debug, int, 0644); | ||
20 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); | ||
21 | |||
22 | int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec) | ||
23 | { | ||
24 | int ret = 0; | ||
25 | u8 inbuf[12] = { 0 }, outbuf[20] = { 0 }; | ||
26 | |||
27 | outbuf[0] = cmd; | ||
28 | |||
29 | if (outlen > 19) | ||
30 | outlen = 19; | ||
31 | |||
32 | if (inlen > 11) | ||
33 | inlen = 11; | ||
34 | |||
35 | if (out != NULL && outlen > 0) | ||
36 | memcpy(&outbuf[1], out, outlen); | ||
37 | |||
38 | deb_xfer("out buffer: "); | ||
39 | debug_dump(outbuf,outlen+1,deb_xfer); | ||
40 | |||
41 | if ((ret = down_interruptible(&d->usb_sem))) | ||
42 | return ret; | ||
43 | |||
44 | if (usb_control_msg(d->udev, | ||
45 | usb_sndctrlpipe(d->udev,0), | ||
46 | TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, | ||
47 | outbuf, 20, 2*HZ) != 20) { | ||
48 | err("USB control message 'out' went wrong."); | ||
49 | ret = -EIO; | ||
50 | goto unlock; | ||
51 | } | ||
52 | |||
53 | msleep(msec); | ||
54 | |||
55 | if (usb_control_msg(d->udev, | ||
56 | usb_rcvctrlpipe(d->udev,0), | ||
57 | TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | ||
58 | inbuf, 12, 2*HZ) != 12) { | ||
59 | err("USB control message 'in' went wrong."); | ||
60 | ret = -EIO; | ||
61 | goto unlock; | ||
62 | } | ||
63 | |||
64 | deb_xfer("in buffer: "); | ||
65 | debug_dump(inbuf,12,deb_xfer); | ||
66 | |||
67 | if (in != NULL && inlen > 0) | ||
68 | memcpy(in,&inbuf[1],inlen); | ||
69 | |||
70 | unlock: | ||
71 | up(&d->usb_sem); | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg) | ||
77 | { | ||
78 | u8 obuf[2] = { 0 },v; | ||
79 | obuf[1] = reg; | ||
80 | |||
81 | vp7045_usb_op(d,TUNER_REG_READ,obuf,2,&v,1,30); | ||
82 | |||
83 | return v; | ||
84 | } | ||
85 | |||
86 | static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
87 | { | ||
88 | u8 v = onoff; | ||
89 | return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150); | ||
90 | } | ||
91 | |||
92 | /* remote control stuff */ | ||
93 | |||
94 | /* The keymapping struct. Somehow this should be loaded to the driver, but | ||
95 | * currently it is hardcoded. */ | ||
96 | static struct dvb_usb_rc_key vp7045_rc_keys[] = { | ||
97 | /* insert the keys like this. to make the raw keys visible, enable | ||
98 | * debug=0x04 when loading dvb-usb-vp7045. */ | ||
99 | |||
100 | /* these keys are probably wrong. I don't have a working IR-receiver on my | ||
101 | * vp7045, so I can't test it. Patches are welcome. */ | ||
102 | { 0x00, 0x01, KEY_1 }, | ||
103 | { 0x00, 0x02, KEY_2 }, | ||
104 | }; | ||
105 | |||
106 | static int vp7045_rc_query(struct dvb_usb_device *d, u32 *key_buf, int *state) | ||
107 | { | ||
108 | u8 key; | ||
109 | int i; | ||
110 | vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20); | ||
111 | |||
112 | deb_rc("remote query key: %x %d\n",key,key); | ||
113 | |||
114 | if (key == 0x44) { | ||
115 | *state = REMOTE_NO_KEY_PRESSED; | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | for (i = 0; i < sizeof(vp7045_rc_keys)/sizeof(struct dvb_usb_rc_key); i++) | ||
120 | if (vp7045_rc_keys[i].data == key) { | ||
121 | *state = REMOTE_KEY_PRESSED; | ||
122 | *key_buf = vp7045_rc_keys[i].event; | ||
123 | break; | ||
124 | } | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset) | ||
129 | { | ||
130 | int i = 0; | ||
131 | u8 v,br[2]; | ||
132 | for (i=0; i < len; i++) { | ||
133 | v = offset + i; | ||
134 | vp7045_usb_op(d,GET_EE_VALUE,&v,1,br,2,5); | ||
135 | buf[i] = br[1]; | ||
136 | } | ||
137 | deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ",offset, i); | ||
138 | debug_dump(buf,i,deb_info); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | |||
143 | static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) | ||
144 | { | ||
145 | return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR); | ||
146 | } | ||
147 | |||
148 | static int vp7045_frontend_attach(struct dvb_usb_device *d) | ||
149 | { | ||
150 | u8 buf[255] = { 0 }; | ||
151 | |||
152 | vp7045_usb_op(d,VENDOR_STRING_READ,NULL,0,buf,20,0); | ||
153 | buf[10] = '\0'; | ||
154 | deb_info("firmware says: %s ",buf); | ||
155 | |||
156 | vp7045_usb_op(d,PRODUCT_STRING_READ,NULL,0,buf,20,0); | ||
157 | buf[10] = '\0'; | ||
158 | deb_info("%s ",buf); | ||
159 | |||
160 | vp7045_usb_op(d,FW_VERSION_READ,NULL,0,buf,20,0); | ||
161 | buf[10] = '\0'; | ||
162 | deb_info("v%s\n",buf); | ||
163 | |||
164 | /* Dump the EEPROM */ | ||
165 | /* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */ | ||
166 | |||
167 | d->fe = vp7045_fe_attach(d); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static struct dvb_usb_properties vp7045_properties; | ||
173 | |||
174 | static int vp7045_usb_probe(struct usb_interface *intf, | ||
175 | const struct usb_device_id *id) | ||
176 | { | ||
177 | return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE); | ||
178 | } | ||
179 | |||
180 | static struct usb_device_id vp7045_usb_table [] = { | ||
181 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_COLD) }, | ||
182 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_WARM) }, | ||
183 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_COLD) }, | ||
184 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_WARM) }, | ||
185 | { 0 }, | ||
186 | }; | ||
187 | MODULE_DEVICE_TABLE(usb, vp7045_usb_table); | ||
188 | |||
189 | static struct dvb_usb_properties vp7045_properties = { | ||
190 | .caps = 0, | ||
191 | |||
192 | .usb_ctrl = CYPRESS_FX2, | ||
193 | .firmware = "dvb-usb-vp7045-01.fw", | ||
194 | |||
195 | .power_ctrl = vp7045_power_ctrl, | ||
196 | .frontend_attach = vp7045_frontend_attach, | ||
197 | .read_mac_address = vp7045_read_mac_addr, | ||
198 | |||
199 | .rc_interval = 400, | ||
200 | .rc_key_map = vp7045_rc_keys, | ||
201 | .rc_key_map_size = ARRAY_SIZE(vp7045_rc_keys), | ||
202 | .rc_query = vp7045_rc_query, | ||
203 | |||
204 | /* parameter for the MPEG2-data transfer */ | ||
205 | .urb = { | ||
206 | .type = DVB_USB_BULK, | ||
207 | .count = 7, | ||
208 | .endpoint = 0x02, | ||
209 | .u = { | ||
210 | .bulk = { | ||
211 | .buffersize = 4096, | ||
212 | } | ||
213 | } | ||
214 | }, | ||
215 | |||
216 | .num_device_descs = 2, | ||
217 | .devices = { | ||
218 | { .name = "Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II)", | ||
219 | .cold_ids = { &vp7045_usb_table[0], NULL }, | ||
220 | .warm_ids = { &vp7045_usb_table[1], NULL }, | ||
221 | }, | ||
222 | { .name = "DigitalNow TinyUSB 2 DVB-t Receiver", | ||
223 | .cold_ids = { &vp7045_usb_table[2], NULL }, | ||
224 | .warm_ids = { &vp7045_usb_table[3], NULL }, | ||
225 | }, | ||
226 | { 0 }, | ||
227 | } | ||
228 | }; | ||
229 | |||
230 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
231 | static struct usb_driver vp7045_usb_driver = { | ||
232 | .owner = THIS_MODULE, | ||
233 | .name = "dvb-usb-vp7045", | ||
234 | .probe = vp7045_usb_probe, | ||
235 | .disconnect = dvb_usb_device_exit, | ||
236 | .id_table = vp7045_usb_table, | ||
237 | }; | ||
238 | |||
239 | /* module stuff */ | ||
240 | static int __init vp7045_usb_module_init(void) | ||
241 | { | ||
242 | int result; | ||
243 | if ((result = usb_register(&vp7045_usb_driver))) { | ||
244 | err("usb_register failed. (%d)",result); | ||
245 | return result; | ||
246 | } | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static void __exit vp7045_usb_module_exit(void) | ||
252 | { | ||
253 | /* deregister this driver from the USB subsystem */ | ||
254 | usb_deregister(&vp7045_usb_driver); | ||
255 | } | ||
256 | |||
257 | module_init(vp7045_usb_module_init); | ||
258 | module_exit(vp7045_usb_module_exit); | ||
259 | |||
260 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
261 | MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0"); | ||
262 | MODULE_VERSION("1.0"); | ||
263 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/vp7045.h b/drivers/media/dvb/dvb-usb/vp7045.h new file mode 100644 index 0000000000..9ce21a20fa --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp7045.h | |||
@@ -0,0 +1,78 @@ | |||
1 | /* Common header-file of the Linux driver for the TwinhanDTV Alpha/MagicBoxII | ||
2 | * USB2.0 DVB-T receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * Thanks to Twinhan who kindly provided hardware and information. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation, version 2. | ||
11 | * | ||
12 | * see Documentation/dvb/README.dvb-usb for more information | ||
13 | */ | ||
14 | #ifndef _DVB_USB_VP7045_H_ | ||
15 | #define _DVB_USB_VP7045_H_ | ||
16 | |||
17 | #define DVB_USB_LOG_PREFIX "vp7045" | ||
18 | #include "dvb-usb.h" | ||
19 | |||
20 | extern int dvb_usb_vp7045_debug; | ||
21 | #define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args) | ||
22 | #define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args) | ||
23 | #define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args) | ||
24 | |||
25 | /* vp7045 commands */ | ||
26 | |||
27 | /* Twinhan Vendor requests */ | ||
28 | #define TH_COMMAND_IN 0xC0 | ||
29 | #define TH_COMMAND_OUT 0xC1 | ||
30 | |||
31 | /* command bytes */ | ||
32 | #define TUNER_REG_READ 0x03 | ||
33 | #define TUNER_REG_WRITE 0x04 | ||
34 | |||
35 | #define RC_VAL_READ 0x05 | ||
36 | #define RC_NO_KEY 0x44 | ||
37 | |||
38 | #define SET_TUNER_POWER 0x06 | ||
39 | #define CHECK_TUNER_POWER 0x12 | ||
40 | #define Tuner_Power_ON 1 | ||
41 | #define Tuner_Power_OFF 0 | ||
42 | |||
43 | #define GET_USB_SPEED 0x07 | ||
44 | #define USB_SPEED_LOW 0 | ||
45 | #define USB_SPEED_FULL 1 | ||
46 | #define USB_SPEED_HIGH 2 | ||
47 | |||
48 | #define LOCK_TUNER_COMMAND 0x09 | ||
49 | |||
50 | #define TUNER_SIGNAL_READ 0x0A | ||
51 | |||
52 | /* FX2 eeprom */ | ||
53 | #define SET_EE_VALUE 0x10 | ||
54 | #define GET_EE_VALUE 0x11 | ||
55 | #define FX2_ID_ADDR 0x00 | ||
56 | #define VID_MSB_ADDR 0x02 | ||
57 | #define VID_LSB_ADDR 0x01 | ||
58 | #define PID_MSB_ADDR 0x04 | ||
59 | #define PID_LSB_ADDR 0x03 | ||
60 | #define MAC_0_ADDR 0x07 | ||
61 | #define MAC_1_ADDR 0x08 | ||
62 | #define MAC_2_ADDR 0x09 | ||
63 | #define MAC_3_ADDR 0x0a | ||
64 | #define MAC_4_ADDR 0x0b | ||
65 | #define MAC_5_ADDR 0x0c | ||
66 | |||
67 | #define RESET_FX2 0x13 | ||
68 | |||
69 | #define FW_VERSION_READ 0x0B | ||
70 | #define VENDOR_STRING_READ 0x0C | ||
71 | #define PRODUCT_STRING_READ 0x0D | ||
72 | #define FW_BCD_VERSION_READ 0x14 | ||
73 | |||
74 | extern struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d); | ||
75 | extern int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen,int msec); | ||
76 | extern u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg); | ||
77 | |||
78 | #endif | ||
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 75fb556ec0..b4fddf513e 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -173,4 +173,12 @@ config DVB_OR51132 | |||
173 | An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want | 173 | An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want |
174 | to support this frontend. | 174 | to support this frontend. |
175 | 175 | ||
176 | config DVB_BCM3510 | ||
177 | tristate "Broadcom BCM3510" | ||
178 | depends on DVB_CORE | ||
179 | select FW_LOADER | ||
180 | help | ||
181 | An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to | ||
182 | support this frontend. | ||
183 | |||
176 | endmenu | 184 | endmenu |
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 7f8784870e..91d6d3576d 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -28,3 +28,4 @@ obj-$(CONFIG_DVB_STV0297) += stv0297.o | |||
28 | obj-$(CONFIG_DVB_NXT2002) += nxt2002.o | 28 | obj-$(CONFIG_DVB_NXT2002) += nxt2002.o |
29 | obj-$(CONFIG_DVB_OR51211) += or51211.o | 29 | obj-$(CONFIG_DVB_OR51211) += or51211.o |
30 | obj-$(CONFIG_DVB_OR51132) += or51132.o | 30 | obj-$(CONFIG_DVB_OR51132) += or51132.o |
31 | obj-$(CONFIG_DVB_BCM3510) += bcm3510.o | ||
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c new file mode 100644 index 0000000000..f5fdc5c3e6 --- /dev/null +++ b/drivers/media/dvb/frontends/bcm3510.c | |||
@@ -0,0 +1,853 @@ | |||
1 | /* | ||
2 | * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC) | ||
3 | * | ||
4 | * Copyright (C) 2001-5, B2C2 inc. | ||
5 | * | ||
6 | * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de> | ||
7 | * | ||
8 | * This driver is "hard-coded" to be used with the 1st generation of | ||
9 | * Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming | ||
10 | * (Panasonic CT10S) is located here, which is actually wrong. Unless there is | ||
11 | * another device with a BCM3510, this is no problem. | ||
12 | * | ||
13 | * The driver works also with QAM64 DVB-C, but had an unreasonable high | ||
14 | * UNC. (Tested with the Air2PC ATSC 1st generation) | ||
15 | * | ||
16 | * You'll need a firmware for this driver in order to get it running. It is | ||
17 | * called "dvb-fe-bcm3510-01.fw". | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify it | ||
20 | * under the terms of the GNU General Public License as published by the Free | ||
21 | * Software Foundation; either version 2 of the License, or (at your option) | ||
22 | * any later version. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
25 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
26 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
27 | * more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU General Public License along with | ||
30 | * this program; if not, write to the Free Software Foundation, Inc., 675 Mass | ||
31 | * Ave, Cambridge, MA 02139, USA. | ||
32 | */ | ||
33 | |||
34 | #include <linux/init.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/moduleparam.h> | ||
37 | #include <linux/device.h> | ||
38 | #include <linux/firmware.h> | ||
39 | |||
40 | #include "dvb_frontend.h" | ||
41 | #include "bcm3510.h" | ||
42 | #include "bcm3510_priv.h" | ||
43 | |||
44 | struct bcm3510_state { | ||
45 | |||
46 | struct i2c_adapter* i2c; | ||
47 | struct dvb_frontend_ops ops; | ||
48 | const struct bcm3510_config* config; | ||
49 | struct dvb_frontend frontend; | ||
50 | |||
51 | /* demodulator private data */ | ||
52 | struct semaphore hab_sem; | ||
53 | u8 firmware_loaded:1; | ||
54 | |||
55 | unsigned long next_status_check; | ||
56 | unsigned long status_check_interval; | ||
57 | struct bcm3510_hab_cmd_status1 status1; | ||
58 | struct bcm3510_hab_cmd_status2 status2; | ||
59 | }; | ||
60 | |||
61 | static int debug; | ||
62 | module_param(debug, int, 0644); | ||
63 | MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c (|-able))."); | ||
64 | |||
65 | #define dprintk(level,x...) if (level & debug) printk(x) | ||
66 | #define dbufout(b,l,m) {\ | ||
67 | int i; \ | ||
68 | for (i = 0; i < l; i++) \ | ||
69 | m("%02x ",b[i]); \ | ||
70 | } | ||
71 | #define deb_info(args...) dprintk(0x01,args) | ||
72 | #define deb_i2c(args...) dprintk(0x02,args) | ||
73 | #define deb_hab(args...) dprintk(0x04,args) | ||
74 | |||
75 | /* transfer functions */ | ||
76 | static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len) | ||
77 | { | ||
78 | u8 b[256]; | ||
79 | int err; | ||
80 | struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = len + 1 }; | ||
81 | |||
82 | b[0] = reg; | ||
83 | memcpy(&b[1],buf,len); | ||
84 | |||
85 | deb_i2c("i2c wr %02x: ",reg); | ||
86 | dbufout(buf,len,deb_i2c); | ||
87 | deb_i2c("\n"); | ||
88 | |||
89 | if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { | ||
90 | |||
91 | deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n", | ||
92 | __FUNCTION__, state->config->demod_address, reg, err); | ||
93 | return -EREMOTEIO; | ||
94 | } | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len) | ||
100 | { | ||
101 | struct i2c_msg msg[] = { | ||
102 | { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 }, | ||
103 | { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } | ||
104 | }; | ||
105 | int err; | ||
106 | |||
107 | memset(buf,0,len); | ||
108 | |||
109 | if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) { | ||
110 | deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n", | ||
111 | __FUNCTION__, state->config->demod_address, reg, err); | ||
112 | return -EREMOTEIO; | ||
113 | } | ||
114 | deb_i2c("i2c rd %02x: ",reg); | ||
115 | dbufout(buf,len,deb_i2c); | ||
116 | deb_i2c("\n"); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static int bcm3510_writeB(struct bcm3510_state *state, u8 reg, bcm3510_register_value v) | ||
122 | { | ||
123 | return bcm3510_writebytes(state,reg,&v.raw,1); | ||
124 | } | ||
125 | |||
126 | static int bcm3510_readB(struct bcm3510_state *state, u8 reg, bcm3510_register_value *v) | ||
127 | { | ||
128 | return bcm3510_readbytes(state,reg,&v->raw,1); | ||
129 | } | ||
130 | |||
131 | /* Host Access Buffer transfers */ | ||
132 | static int bcm3510_hab_get_response(struct bcm3510_state *st, u8 *buf, int len) | ||
133 | { | ||
134 | bcm3510_register_value v; | ||
135 | int ret,i; | ||
136 | |||
137 | v.HABADR_a6.HABADR = 0; | ||
138 | if ((ret = bcm3510_writeB(st,0xa6,v)) < 0) | ||
139 | return ret; | ||
140 | |||
141 | for (i = 0; i < len; i++) { | ||
142 | if ((ret = bcm3510_readB(st,0xa7,&v)) < 0) | ||
143 | return ret; | ||
144 | buf[i] = v.HABDATA_a7; | ||
145 | } | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int bcm3510_hab_send_request(struct bcm3510_state *st, u8 *buf, int len) | ||
150 | { | ||
151 | bcm3510_register_value v,hab; | ||
152 | int ret,i; | ||
153 | unsigned long t; | ||
154 | |||
155 | /* Check if any previous HAB request still needs to be serviced by the | ||
156 | * Aquisition Processor before sending new request */ | ||
157 | if ((ret = bcm3510_readB(st,0xa8,&v)) < 0) | ||
158 | return ret; | ||
159 | if (v.HABSTAT_a8.HABR) { | ||
160 | deb_info("HAB is running already - clearing it.\n"); | ||
161 | v.HABSTAT_a8.HABR = 0; | ||
162 | bcm3510_writeB(st,0xa8,v); | ||
163 | // return -EBUSY; | ||
164 | } | ||
165 | |||
166 | /* Send the start HAB Address (automatically incremented after write of | ||
167 | * HABDATA) and write the HAB Data */ | ||
168 | hab.HABADR_a6.HABADR = 0; | ||
169 | if ((ret = bcm3510_writeB(st,0xa6,hab)) < 0) | ||
170 | return ret; | ||
171 | |||
172 | for (i = 0; i < len; i++) { | ||
173 | hab.HABDATA_a7 = buf[i]; | ||
174 | if ((ret = bcm3510_writeB(st,0xa7,hab)) < 0) | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | /* Set the HABR bit to indicate AP request in progress (LBHABR allows HABR to | ||
179 | * be written) */ | ||
180 | v.raw = 0; v.HABSTAT_a8.HABR = 1; v.HABSTAT_a8.LDHABR = 1; | ||
181 | if ((ret = bcm3510_writeB(st,0xa8,v)) < 0) | ||
182 | return ret; | ||
183 | |||
184 | /* Polling method: Wait until the AP finishes processing the HAB request */ | ||
185 | t = jiffies + 1*HZ; | ||
186 | while (time_before(jiffies, t)) { | ||
187 | deb_info("waiting for HAB to complete\n"); | ||
188 | msleep(10); | ||
189 | if ((ret = bcm3510_readB(st,0xa8,&v)) < 0) | ||
190 | return ret; | ||
191 | |||
192 | if (!v.HABSTAT_a8.HABR) | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | deb_info("send_request execution timed out.\n"); | ||
197 | return -ETIMEDOUT; | ||
198 | } | ||
199 | |||
200 | static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *obuf, u8 olen, u8 *ibuf, u8 ilen) | ||
201 | { | ||
202 | u8 ob[olen+2],ib[ilen+2]; | ||
203 | int ret = 0; | ||
204 | |||
205 | ob[0] = cmd; | ||
206 | ob[1] = msgid; | ||
207 | memcpy(&ob[2],obuf,olen); | ||
208 | |||
209 | deb_hab("hab snd: "); | ||
210 | dbufout(ob,olen+2,deb_hab); | ||
211 | deb_hab("\n"); | ||
212 | |||
213 | if (down_interruptible(&st->hab_sem) < 0) | ||
214 | return -EAGAIN; | ||
215 | |||
216 | if ((ret = bcm3510_hab_send_request(st, ob, olen+2)) < 0 || | ||
217 | (ret = bcm3510_hab_get_response(st, ib, ilen+2)) < 0) | ||
218 | goto error; | ||
219 | |||
220 | deb_hab("hab get: "); | ||
221 | dbufout(ib,ilen+2,deb_hab); | ||
222 | deb_hab("\n"); | ||
223 | |||
224 | memcpy(ibuf,&ib[2],ilen); | ||
225 | error: | ||
226 | up(&st->hab_sem); | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | #if 0 | ||
231 | /* not needed, we use a semaphore to prevent HAB races */ | ||
232 | static int bcm3510_is_ap_ready(struct bcm3510_state *st) | ||
233 | { | ||
234 | bcm3510_register_value ap,hab; | ||
235 | int ret; | ||
236 | |||
237 | if ((ret = bcm3510_readB(st,0xa8,&hab)) < 0 || | ||
238 | (ret = bcm3510_readB(st,0xa2,&ap) < 0)) | ||
239 | return ret; | ||
240 | |||
241 | if (ap.APSTAT1_a2.RESET || ap.APSTAT1_a2.IDLE || ap.APSTAT1_a2.STOP || hab.HABSTAT_a8.HABR) { | ||
242 | deb_info("AP is busy\n"); | ||
243 | return -EBUSY; | ||
244 | } | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | #endif | ||
249 | |||
250 | static int bcm3510_bert_reset(struct bcm3510_state *st) | ||
251 | { | ||
252 | bcm3510_register_value b; | ||
253 | int ret; | ||
254 | |||
255 | if ((ret < bcm3510_readB(st,0xfa,&b)) < 0) | ||
256 | return ret; | ||
257 | |||
258 | b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b); | ||
259 | b.BERCTL_fa.RESYNC = 1; bcm3510_writeB(st,0xfa,b); | ||
260 | b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b); | ||
261 | b.BERCTL_fa.CNTCTL = 1; b.BERCTL_fa.BITCNT = 1; bcm3510_writeB(st,0xfa,b); | ||
262 | |||
263 | /* clear residual bit counter TODO */ | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static int bcm3510_refresh_state(struct bcm3510_state *st) | ||
268 | { | ||
269 | if (time_after(jiffies,st->next_status_check)) { | ||
270 | bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS1, NULL,0, (u8 *)&st->status1, sizeof(st->status1)); | ||
271 | bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS2, NULL,0, (u8 *)&st->status2, sizeof(st->status2)); | ||
272 | st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000; | ||
273 | } | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int bcm3510_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
278 | { | ||
279 | struct bcm3510_state* st = fe->demodulator_priv; | ||
280 | bcm3510_refresh_state(st); | ||
281 | |||
282 | *status = 0; | ||
283 | if (st->status1.STATUS1.RECEIVER_LOCK) | ||
284 | *status |= FE_HAS_LOCK | FE_HAS_SYNC; | ||
285 | |||
286 | if (st->status1.STATUS1.FEC_LOCK) | ||
287 | *status |= FE_HAS_VITERBI; | ||
288 | |||
289 | if (st->status1.STATUS1.OUT_PLL_LOCK) | ||
290 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||
291 | |||
292 | if (*status & FE_HAS_LOCK) | ||
293 | st->status_check_interval = 1500; | ||
294 | else /* more frequently checks if no lock has been achieved yet */ | ||
295 | st->status_check_interval = 500; | ||
296 | |||
297 | deb_info("real_status: %02x\n",*status); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int bcm3510_read_ber(struct dvb_frontend* fe, u32* ber) | ||
302 | { | ||
303 | struct bcm3510_state* st = fe->demodulator_priv; | ||
304 | bcm3510_refresh_state(st); | ||
305 | |||
306 | *ber = (st->status2.LDBER0 << 16) | (st->status2.LDBER1 << 8) | st->status2.LDBER2; | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int bcm3510_read_unc(struct dvb_frontend* fe, u32* unc) | ||
311 | { | ||
312 | struct bcm3510_state* st = fe->demodulator_priv; | ||
313 | bcm3510_refresh_state(st); | ||
314 | *unc = (st->status2.LDUERC0 << 8) | st->status2.LDUERC1; | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int bcm3510_read_signal_strength(struct dvb_frontend* fe, u16* strength) | ||
319 | { | ||
320 | struct bcm3510_state* st = fe->demodulator_priv; | ||
321 | s32 t; | ||
322 | |||
323 | bcm3510_refresh_state(st); | ||
324 | t = st->status2.SIGNAL; | ||
325 | |||
326 | if (t > 190) | ||
327 | t = 190; | ||
328 | if (t < 90) | ||
329 | t = 90; | ||
330 | |||
331 | t -= 90; | ||
332 | t = t * 0xff / 100; | ||
333 | /* normalize if necessary */ | ||
334 | *strength = (t << 8) | t; | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int bcm3510_read_snr(struct dvb_frontend* fe, u16* snr) | ||
339 | { | ||
340 | struct bcm3510_state* st = fe->demodulator_priv; | ||
341 | bcm3510_refresh_state(st); | ||
342 | |||
343 | *snr = st->status1.SNR_EST0*1000 + ((st->status1.SNR_EST1*1000) >> 8); | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | /* tuner frontend programming */ | ||
348 | static int bcm3510_tuner_cmd(struct bcm3510_state* st,u8 bc, u16 n, u8 a) | ||
349 | { | ||
350 | struct bcm3510_hab_cmd_tune c; | ||
351 | memset(&c,0,sizeof(struct bcm3510_hab_cmd_tune)); | ||
352 | |||
353 | /* I2C Mode disabled, set 16 control / Data pairs */ | ||
354 | c.length = 0x10; | ||
355 | c.clock_width = 0; | ||
356 | /* CS1, CS0, DATA, CLK bits control the tuner RF_AGC_SEL pin is set to | ||
357 | * logic high (as Configuration) */ | ||
358 | c.misc = 0x10; | ||
359 | /* Set duration of the initial state of TUNCTL = 3.34 micro Sec */ | ||
360 | c.TUNCTL_state = 0x40; | ||
361 | |||
362 | /* PRESCALER DEVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */ | ||
363 | c.ctl_dat[0].ctrl.size = BITS_8; | ||
364 | c.ctl_dat[0].data = 0x80 | bc; | ||
365 | |||
366 | /* Control DATA pin, 1stosc REFERENCE COUNTER REF_S10 to REF_S3 */ | ||
367 | c.ctl_dat[1].ctrl.size = BITS_8; | ||
368 | c.ctl_dat[1].data = 4; | ||
369 | |||
370 | /* set CONTROL BIT 1 to 1, 1stosc REFERENCE COUNTER REF_S2 to REF_S1 */ | ||
371 | c.ctl_dat[2].ctrl.size = BITS_3; | ||
372 | c.ctl_dat[2].data = 0x20; | ||
373 | |||
374 | /* control CS0 pin, pulse byte ? */ | ||
375 | c.ctl_dat[3].ctrl.size = BITS_3; | ||
376 | c.ctl_dat[3].ctrl.clk_off = 1; | ||
377 | c.ctl_dat[3].ctrl.cs0 = 1; | ||
378 | c.ctl_dat[3].data = 0x40; | ||
379 | |||
380 | /* PGM_S18 to PGM_S11 */ | ||
381 | c.ctl_dat[4].ctrl.size = BITS_8; | ||
382 | c.ctl_dat[4].data = n >> 3; | ||
383 | |||
384 | /* PGM_S10 to PGM_S8, SWL_S7 to SWL_S3 */ | ||
385 | c.ctl_dat[5].ctrl.size = BITS_8; | ||
386 | c.ctl_dat[5].data = ((n & 0x7) << 5) | (a >> 2); | ||
387 | |||
388 | /* SWL_S2 and SWL_S1, set CONTROL BIT 2 to 0 */ | ||
389 | c.ctl_dat[6].ctrl.size = BITS_3; | ||
390 | c.ctl_dat[6].data = (a << 6) & 0xdf; | ||
391 | |||
392 | /* control CS0 pin, pulse byte ? */ | ||
393 | c.ctl_dat[7].ctrl.size = BITS_3; | ||
394 | c.ctl_dat[7].ctrl.clk_off = 1; | ||
395 | c.ctl_dat[7].ctrl.cs0 = 1; | ||
396 | c.ctl_dat[7].data = 0x40; | ||
397 | |||
398 | /* PRESCALER DEVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */ | ||
399 | c.ctl_dat[8].ctrl.size = BITS_8; | ||
400 | c.ctl_dat[8].data = 0x80; | ||
401 | |||
402 | /* 2ndosc REFERENCE COUNTER REF_S10 to REF_S3 */ | ||
403 | c.ctl_dat[9].ctrl.size = BITS_8; | ||
404 | c.ctl_dat[9].data = 0x10; | ||
405 | |||
406 | /* set CONTROL BIT 1 to 1, 2ndosc REFERENCE COUNTER REF_S2 to REF_S1 */ | ||
407 | c.ctl_dat[10].ctrl.size = BITS_3; | ||
408 | c.ctl_dat[10].data = 0x20; | ||
409 | |||
410 | /* pulse byte */ | ||
411 | c.ctl_dat[11].ctrl.size = BITS_3; | ||
412 | c.ctl_dat[11].ctrl.clk_off = 1; | ||
413 | c.ctl_dat[11].ctrl.cs1 = 1; | ||
414 | c.ctl_dat[11].data = 0x40; | ||
415 | |||
416 | /* PGM_S18 to PGM_S11 */ | ||
417 | c.ctl_dat[12].ctrl.size = BITS_8; | ||
418 | c.ctl_dat[12].data = 0x2a; | ||
419 | |||
420 | /* PGM_S10 to PGM_S8 and SWL_S7 to SWL_S3 */ | ||
421 | c.ctl_dat[13].ctrl.size = BITS_8; | ||
422 | c.ctl_dat[13].data = 0x8e; | ||
423 | |||
424 | /* SWL_S2 and SWL_S1 and set CONTROL BIT 2 to 0 */ | ||
425 | c.ctl_dat[14].ctrl.size = BITS_3; | ||
426 | c.ctl_dat[14].data = 0; | ||
427 | |||
428 | /* Pulse Byte */ | ||
429 | c.ctl_dat[15].ctrl.size = BITS_3; | ||
430 | c.ctl_dat[15].ctrl.clk_off = 1; | ||
431 | c.ctl_dat[15].ctrl.cs1 = 1; | ||
432 | c.ctl_dat[15].data = 0x40; | ||
433 | |||
434 | return bcm3510_do_hab_cmd(st,CMD_TUNE, MSGID_TUNE,(u8 *) &c,sizeof(c), NULL, 0); | ||
435 | } | ||
436 | |||
437 | static int bcm3510_set_freq(struct bcm3510_state* st,u32 freq) | ||
438 | { | ||
439 | u8 bc,a; | ||
440 | u16 n; | ||
441 | s32 YIntercept,Tfvco1; | ||
442 | |||
443 | freq /= 1000; | ||
444 | |||
445 | deb_info("%dkHz:",freq); | ||
446 | /* set Band Switch */ | ||
447 | if (freq <= 168000) | ||
448 | bc = 0x1c; | ||
449 | else if (freq <= 378000) | ||
450 | bc = 0x2c; | ||
451 | else | ||
452 | bc = 0x30; | ||
453 | |||
454 | if (freq >= 470000) { | ||
455 | freq -= 470001; | ||
456 | YIntercept = 18805; | ||
457 | } else if (freq >= 90000) { | ||
458 | freq -= 90001; | ||
459 | YIntercept = 15005; | ||
460 | } else if (freq >= 76000){ | ||
461 | freq -= 76001; | ||
462 | YIntercept = 14865; | ||
463 | } else { | ||
464 | freq -= 54001; | ||
465 | YIntercept = 14645; | ||
466 | } | ||
467 | |||
468 | Tfvco1 = (((freq/6000)*60 + YIntercept)*4)/10; | ||
469 | |||
470 | n = Tfvco1 >> 6; | ||
471 | a = Tfvco1 & 0x3f; | ||
472 | |||
473 | deb_info(" BC1_2_3_4: %x, N: %x A: %x\n", bc, n, a); | ||
474 | if (n >= 16 && n <= 2047) | ||
475 | return bcm3510_tuner_cmd(st,bc,n,a); | ||
476 | |||
477 | return -EINVAL; | ||
478 | } | ||
479 | |||
480 | static int bcm3510_set_frontend(struct dvb_frontend* fe, | ||
481 | struct dvb_frontend_parameters *p) | ||
482 | { | ||
483 | struct bcm3510_state* st = fe->demodulator_priv; | ||
484 | struct bcm3510_hab_cmd_ext_acquire cmd; | ||
485 | struct bcm3510_hab_cmd_bert_control bert; | ||
486 | int ret; | ||
487 | |||
488 | memset(&cmd,0,sizeof(cmd)); | ||
489 | switch (p->u.vsb.modulation) { | ||
490 | case QAM_256: | ||
491 | cmd.ACQUIRE0.MODE = 0x1; | ||
492 | cmd.ACQUIRE1.SYM_RATE = 0x1; | ||
493 | cmd.ACQUIRE1.IF_FREQ = 0x1; | ||
494 | break; | ||
495 | case QAM_64: | ||
496 | cmd.ACQUIRE0.MODE = 0x2; | ||
497 | cmd.ACQUIRE1.SYM_RATE = 0x2; | ||
498 | cmd.ACQUIRE1.IF_FREQ = 0x1; | ||
499 | break; | ||
500 | /* case QAM_256: | ||
501 | cmd.ACQUIRE0.MODE = 0x3; | ||
502 | break; | ||
503 | case QAM_128: | ||
504 | cmd.ACQUIRE0.MODE = 0x4; | ||
505 | break; | ||
506 | case QAM_64: | ||
507 | cmd.ACQUIRE0.MODE = 0x5; | ||
508 | break; | ||
509 | case QAM_32: | ||
510 | cmd.ACQUIRE0.MODE = 0x6; | ||
511 | break; | ||
512 | case QAM_16: | ||
513 | cmd.ACQUIRE0.MODE = 0x7; | ||
514 | break;*/ | ||
515 | case VSB_8: | ||
516 | cmd.ACQUIRE0.MODE = 0x8; | ||
517 | cmd.ACQUIRE1.SYM_RATE = 0x0; | ||
518 | cmd.ACQUIRE1.IF_FREQ = 0x0; | ||
519 | break; | ||
520 | case VSB_16: | ||
521 | cmd.ACQUIRE0.MODE = 0x9; | ||
522 | cmd.ACQUIRE1.SYM_RATE = 0x0; | ||
523 | cmd.ACQUIRE1.IF_FREQ = 0x0; | ||
524 | default: | ||
525 | return -EINVAL; | ||
526 | }; | ||
527 | cmd.ACQUIRE0.OFFSET = 0; | ||
528 | cmd.ACQUIRE0.NTSCSWEEP = 1; | ||
529 | cmd.ACQUIRE0.FA = 1; | ||
530 | cmd.ACQUIRE0.BW = 0; | ||
531 | |||
532 | /* if (enableOffset) { | ||
533 | cmd.IF_OFFSET0 = xx; | ||
534 | cmd.IF_OFFSET1 = xx; | ||
535 | |||
536 | cmd.SYM_OFFSET0 = xx; | ||
537 | cmd.SYM_OFFSET1 = xx; | ||
538 | if (enableNtscSweep) { | ||
539 | cmd.NTSC_OFFSET0; | ||
540 | cmd.NTSC_OFFSET1; | ||
541 | } | ||
542 | } */ | ||
543 | bcm3510_do_hab_cmd(st, CMD_ACQUIRE, MSGID_EXT_TUNER_ACQUIRE, (u8 *) &cmd, sizeof(cmd), NULL, 0); | ||
544 | |||
545 | /* doing it with different MSGIDs, data book and source differs */ | ||
546 | bert.BE = 0; | ||
547 | bert.unused = 0; | ||
548 | bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_CONTROL, (u8 *) &bert, sizeof(bert), NULL, 0); | ||
549 | bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_SET, (u8 *) &bert, sizeof(bert), NULL, 0); | ||
550 | |||
551 | bcm3510_bert_reset(st); | ||
552 | |||
553 | if ((ret = bcm3510_set_freq(st,p->frequency)) < 0) | ||
554 | return ret; | ||
555 | |||
556 | memset(&st->status1,0,sizeof(st->status1)); | ||
557 | memset(&st->status2,0,sizeof(st->status2)); | ||
558 | st->status_check_interval = 500; | ||
559 | |||
560 | /* Give the AP some time */ | ||
561 | msleep(200); | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static int bcm3510_sleep(struct dvb_frontend* fe) | ||
567 | { | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static int bcm3510_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s) | ||
572 | { | ||
573 | s->min_delay_ms = 1000; | ||
574 | s->step_size = 0; | ||
575 | s->max_drift = 0; | ||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | static void bcm3510_release(struct dvb_frontend* fe) | ||
580 | { | ||
581 | struct bcm3510_state* state = fe->demodulator_priv; | ||
582 | kfree(state); | ||
583 | } | ||
584 | |||
585 | /* firmware download: | ||
586 | * firmware file is build up like this: | ||
587 | * 16bit addr, 16bit length, 8byte of length | ||
588 | */ | ||
589 | #define BCM3510_DEFAULT_FIRMWARE "dvb-fe-bcm3510-01.fw" | ||
590 | |||
591 | static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, u8 *b, u16 len) | ||
592 | { | ||
593 | int ret = 0,i; | ||
594 | bcm3510_register_value vH, vL,vD; | ||
595 | |||
596 | vH.MADRH_a9 = addr >> 8; | ||
597 | vL.MADRL_aa = addr; | ||
598 | if ((ret = bcm3510_writeB(st,0xa9,vH)) < 0) return ret; | ||
599 | if ((ret = bcm3510_writeB(st,0xaa,vL)) < 0) return ret; | ||
600 | |||
601 | for (i = 0; i < len; i++) { | ||
602 | vD.MDATA_ab = b[i]; | ||
603 | if ((ret = bcm3510_writeB(st,0xab,vD)) < 0) | ||
604 | return ret; | ||
605 | } | ||
606 | |||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static int bcm3510_download_firmware(struct dvb_frontend* fe) | ||
611 | { | ||
612 | struct bcm3510_state* st = fe->demodulator_priv; | ||
613 | const struct firmware *fw; | ||
614 | u16 addr,len; | ||
615 | u8 *b; | ||
616 | int ret,i; | ||
617 | |||
618 | deb_info("requesting firmware\n"); | ||
619 | if ((ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE)) < 0) { | ||
620 | err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret); | ||
621 | return ret; | ||
622 | } | ||
623 | deb_info("got firmware: %d\n",fw->size); | ||
624 | |||
625 | b = fw->data; | ||
626 | for (i = 0; i < fw->size;) { | ||
627 | addr = le16_to_cpu( *( (u16 *)&b[i] ) ); | ||
628 | len = le16_to_cpu( *( (u16 *)&b[i+2] ) ); | ||
629 | deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04x\n",addr,len,fw->size); | ||
630 | if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) { | ||
631 | err("firmware download failed: %d\n",ret); | ||
632 | return ret; | ||
633 | } | ||
634 | i += 4 + len; | ||
635 | } | ||
636 | release_firmware(fw); | ||
637 | deb_info("firmware download successfully completed\n"); | ||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | static int bcm3510_check_firmware_version(struct bcm3510_state *st) | ||
642 | { | ||
643 | struct bcm3510_hab_cmd_get_version_info ver; | ||
644 | bcm3510_do_hab_cmd(st,CMD_GET_VERSION_INFO,MSGID_GET_VERSION_INFO,NULL,0,(u8*)&ver,sizeof(ver)); | ||
645 | |||
646 | deb_info("Version information: 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
647 | ver.microcode_version, ver.script_version, ver.config_version, ver.demod_version); | ||
648 | |||
649 | if (ver.script_version == BCM3510_DEF_SCRIPT_VERSION && | ||
650 | ver.config_version == BCM3510_DEF_CONFIG_VERSION && | ||
651 | ver.demod_version == BCM3510_DEF_DEMOD_VERSION) | ||
652 | return 0; | ||
653 | |||
654 | deb_info("version check failed\n"); | ||
655 | return -ENODEV; | ||
656 | } | ||
657 | |||
658 | /* (un)resetting the AP */ | ||
659 | static int bcm3510_reset(struct bcm3510_state *st) | ||
660 | { | ||
661 | int ret; | ||
662 | unsigned long t; | ||
663 | bcm3510_register_value v; | ||
664 | |||
665 | bcm3510_readB(st,0xa0,&v); v.HCTL1_a0.RESET = 1; | ||
666 | if ((ret = bcm3510_writeB(st,0xa0,v)) < 0) | ||
667 | return ret; | ||
668 | |||
669 | t = jiffies + 3*HZ; | ||
670 | while (time_before(jiffies, t)) { | ||
671 | msleep(10); | ||
672 | if ((ret = bcm3510_readB(st,0xa2,&v)) < 0) | ||
673 | return ret; | ||
674 | |||
675 | if (v.APSTAT1_a2.RESET) | ||
676 | return 0; | ||
677 | } | ||
678 | deb_info("reset timed out\n"); | ||
679 | return -ETIMEDOUT; | ||
680 | } | ||
681 | |||
682 | static int bcm3510_clear_reset(struct bcm3510_state *st) | ||
683 | { | ||
684 | bcm3510_register_value v; | ||
685 | int ret; | ||
686 | unsigned long t; | ||
687 | |||
688 | v.raw = 0; | ||
689 | if ((ret = bcm3510_writeB(st,0xa0,v)) < 0) | ||
690 | return ret; | ||
691 | |||
692 | t = jiffies + 3*HZ; | ||
693 | while (time_before(jiffies, t)) { | ||
694 | msleep(10); | ||
695 | if ((ret = bcm3510_readB(st,0xa2,&v)) < 0) | ||
696 | return ret; | ||
697 | |||
698 | /* verify that reset is cleared */ | ||
699 | if (!v.APSTAT1_a2.RESET) | ||
700 | return 0; | ||
701 | } | ||
702 | deb_info("reset clear timed out\n"); | ||
703 | return -ETIMEDOUT; | ||
704 | } | ||
705 | |||
706 | static int bcm3510_init_cold(struct bcm3510_state *st) | ||
707 | { | ||
708 | int ret; | ||
709 | bcm3510_register_value v; | ||
710 | |||
711 | /* read Acquisation Processor status register and check it is not in RUN mode */ | ||
712 | if ((ret = bcm3510_readB(st,0xa2,&v)) < 0) | ||
713 | return ret; | ||
714 | if (v.APSTAT1_a2.RUN) { | ||
715 | deb_info("AP is already running - firmware already loaded.\n"); | ||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | deb_info("reset?\n"); | ||
720 | if ((ret = bcm3510_reset(st)) < 0) | ||
721 | return ret; | ||
722 | |||
723 | deb_info("tristate?\n"); | ||
724 | /* tri-state */ | ||
725 | v.TSTCTL_2e.CTL = 0; | ||
726 | if ((ret = bcm3510_writeB(st,0x2e,v)) < 0) | ||
727 | return ret; | ||
728 | |||
729 | deb_info("firmware?\n"); | ||
730 | if ((ret = bcm3510_download_firmware(&st->frontend)) < 0 || | ||
731 | (ret = bcm3510_clear_reset(st)) < 0) | ||
732 | return ret; | ||
733 | |||
734 | /* anything left here to Let the acquisition processor begin execution at program counter 0000 ??? */ | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static int bcm3510_init(struct dvb_frontend* fe) | ||
740 | { | ||
741 | struct bcm3510_state* st = fe->demodulator_priv; | ||
742 | bcm3510_register_value j; | ||
743 | struct bcm3510_hab_cmd_set_agc c; | ||
744 | int ret; | ||
745 | |||
746 | if ((ret = bcm3510_readB(st,0xca,&j)) < 0) | ||
747 | return ret; | ||
748 | |||
749 | deb_info("JDEC: %02x\n",j.raw); | ||
750 | |||
751 | switch (j.JDEC_ca.JDEC) { | ||
752 | case JDEC_WAIT_AT_RAM: | ||
753 | deb_info("attempting to download firmware\n"); | ||
754 | if ((ret = bcm3510_init_cold(st)) < 0) | ||
755 | return ret; | ||
756 | case JDEC_EEPROM_LOAD_WAIT: /* fall-through is wanted */ | ||
757 | deb_info("firmware is loaded\n"); | ||
758 | bcm3510_check_firmware_version(st); | ||
759 | break; | ||
760 | default: | ||
761 | return -ENODEV; | ||
762 | } | ||
763 | |||
764 | memset(&c,0,1); | ||
765 | c.SEL = 1; | ||
766 | bcm3510_do_hab_cmd(st,CMD_AUTO_PARAM,MSGID_SET_RF_AGC_SEL,(u8 *)&c,sizeof(c),NULL,0); | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | |||
772 | static struct dvb_frontend_ops bcm3510_ops; | ||
773 | |||
774 | struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config, | ||
775 | struct i2c_adapter *i2c) | ||
776 | { | ||
777 | struct bcm3510_state* state = NULL; | ||
778 | int ret; | ||
779 | bcm3510_register_value v; | ||
780 | |||
781 | /* allocate memory for the internal state */ | ||
782 | state = kmalloc(sizeof(struct bcm3510_state), GFP_KERNEL); | ||
783 | if (state == NULL) | ||
784 | goto error; | ||
785 | memset(state,0,sizeof(struct bcm3510_state)); | ||
786 | |||
787 | /* setup the state */ | ||
788 | |||
789 | state->config = config; | ||
790 | state->i2c = i2c; | ||
791 | memcpy(&state->ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops)); | ||
792 | |||
793 | /* create dvb_frontend */ | ||
794 | state->frontend.ops = &state->ops; | ||
795 | state->frontend.demodulator_priv = state; | ||
796 | |||
797 | sema_init(&state->hab_sem, 1); | ||
798 | |||
799 | if ((ret = bcm3510_readB(state,0xe0,&v)) < 0) | ||
800 | goto error; | ||
801 | |||
802 | deb_info("Revision: 0x%1x, Layer: 0x%1x.\n",v.REVID_e0.REV,v.REVID_e0.LAYER); | ||
803 | |||
804 | if ((v.REVID_e0.REV != 0x1 && v.REVID_e0.LAYER != 0xb) && /* cold */ | ||
805 | (v.REVID_e0.REV != 0x8 && v.REVID_e0.LAYER != 0x0)) /* warm */ | ||
806 | goto error; | ||
807 | |||
808 | info("Revision: 0x%1x, Layer: 0x%1x.",v.REVID_e0.REV,v.REVID_e0.LAYER); | ||
809 | |||
810 | bcm3510_reset(state); | ||
811 | |||
812 | return &state->frontend; | ||
813 | |||
814 | error: | ||
815 | kfree(state); | ||
816 | return NULL; | ||
817 | } | ||
818 | EXPORT_SYMBOL(bcm3510_attach); | ||
819 | |||
820 | static struct dvb_frontend_ops bcm3510_ops = { | ||
821 | |||
822 | .info = { | ||
823 | .name = "Broadcom BCM3510 VSB/QAM frontend", | ||
824 | .type = FE_ATSC, | ||
825 | .frequency_min = 54000000, | ||
826 | .frequency_max = 803000000, | ||
827 | /* stepsize is just a guess */ | ||
828 | .frequency_stepsize = 0, | ||
829 | .caps = | ||
830 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
831 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
832 | FE_CAN_8VSB | FE_CAN_16VSB | | ||
833 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | ||
834 | }, | ||
835 | |||
836 | .release = bcm3510_release, | ||
837 | |||
838 | .init = bcm3510_init, | ||
839 | .sleep = bcm3510_sleep, | ||
840 | |||
841 | .set_frontend = bcm3510_set_frontend, | ||
842 | .get_tune_settings = bcm3510_get_tune_settings, | ||
843 | |||
844 | .read_status = bcm3510_read_status, | ||
845 | .read_ber = bcm3510_read_ber, | ||
846 | .read_signal_strength = bcm3510_read_signal_strength, | ||
847 | .read_snr = bcm3510_read_snr, | ||
848 | .read_ucblocks = bcm3510_read_unc, | ||
849 | }; | ||
850 | |||
851 | MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver"); | ||
852 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
853 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h new file mode 100644 index 0000000000..80f5d0953d --- /dev/null +++ b/drivers/media/dvb/frontends/bcm3510.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC) | ||
3 | * | ||
4 | * Copyright (C) 2001-5, B2C2 inc. | ||
5 | * | ||
6 | * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | #ifndef BCM3510_H | ||
23 | #define BCM3510_H | ||
24 | |||
25 | #include <linux/dvb/frontend.h> | ||
26 | #include <linux/firmware.h> | ||
27 | |||
28 | struct bcm3510_config | ||
29 | { | ||
30 | /* the demodulator's i2c address */ | ||
31 | u8 demod_address; | ||
32 | |||
33 | /* request firmware for device */ | ||
34 | int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); | ||
35 | }; | ||
36 | |||
37 | extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config, | ||
38 | struct i2c_adapter* i2c); | ||
39 | |||
40 | #endif | ||
diff --git a/drivers/media/dvb/frontends/bcm3510_priv.h b/drivers/media/dvb/frontends/bcm3510_priv.h new file mode 100644 index 0000000000..3bb1bc2a04 --- /dev/null +++ b/drivers/media/dvb/frontends/bcm3510_priv.h | |||
@@ -0,0 +1,460 @@ | |||
1 | /* | ||
2 | * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC) | ||
3 | * | ||
4 | * Copyright (C) 2001-5, B2C2 inc. | ||
5 | * | ||
6 | * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | #ifndef __BCM3510_PRIV_H__ | ||
23 | #define __BCM3510_PRIV_H__ | ||
24 | |||
25 | #define PACKED __attribute__((packed)) | ||
26 | |||
27 | #undef err | ||
28 | #define err(format, arg...) printk(KERN_ERR "bcm3510: " format "\n" , ## arg) | ||
29 | #undef info | ||
30 | #define info(format, arg...) printk(KERN_INFO "bcm3510: " format "\n" , ## arg) | ||
31 | #undef warn | ||
32 | #define warn(format, arg...) printk(KERN_WARNING "bcm3510: " format "\n" , ## arg) | ||
33 | |||
34 | |||
35 | #define PANASONIC_FIRST_IF_BASE_IN_KHz 1407500 | ||
36 | #define BCM3510_SYMBOL_RATE 5381000 | ||
37 | |||
38 | typedef union { | ||
39 | u8 raw; | ||
40 | |||
41 | struct { | ||
42 | u8 CTL :8; | ||
43 | } TSTCTL_2e; | ||
44 | |||
45 | u8 LDCERC_4e; | ||
46 | u8 LDUERC_4f; | ||
47 | u8 LD_BER0_65; | ||
48 | u8 LD_BER1_66; | ||
49 | u8 LD_BER2_67; | ||
50 | u8 LD_BER3_68; | ||
51 | |||
52 | struct { | ||
53 | u8 RESET :1; | ||
54 | u8 IDLE :1; | ||
55 | u8 STOP :1; | ||
56 | u8 HIRQ0 :1; | ||
57 | u8 HIRQ1 :1; | ||
58 | u8 na0 :1; | ||
59 | u8 HABAV :1; | ||
60 | u8 na1 :1; | ||
61 | } HCTL1_a0; | ||
62 | |||
63 | struct { | ||
64 | u8 na0 :1; | ||
65 | u8 IDLMSK :1; | ||
66 | u8 STMSK :1; | ||
67 | u8 I0MSK :1; | ||
68 | u8 I1MSK :1; | ||
69 | u8 na1 :1; | ||
70 | u8 HABMSK :1; | ||
71 | u8 na2 :1; | ||
72 | } HCTLMSK_a1; | ||
73 | |||
74 | struct { | ||
75 | u8 RESET :1; | ||
76 | u8 IDLE :1; | ||
77 | u8 STOP :1; | ||
78 | u8 RUN :1; | ||
79 | u8 HABAV :1; | ||
80 | u8 MEMAV :1; | ||
81 | u8 ALDONE :1; | ||
82 | u8 REIRQ :1; | ||
83 | } APSTAT1_a2; | ||
84 | |||
85 | struct { | ||
86 | u8 RSTMSK :1; | ||
87 | u8 IMSK :1; | ||
88 | u8 SMSK :1; | ||
89 | u8 RMSK :1; | ||
90 | u8 HABMSK :1; | ||
91 | u8 MAVMSK :1; | ||
92 | u8 ALDMSK :1; | ||
93 | u8 REMSK :1; | ||
94 | } APMSK1_a3; | ||
95 | |||
96 | u8 APSTAT2_a4; | ||
97 | u8 APMSK2_a5; | ||
98 | |||
99 | struct { | ||
100 | u8 HABADR :7; | ||
101 | u8 na :1; | ||
102 | } HABADR_a6; | ||
103 | |||
104 | u8 HABDATA_a7; | ||
105 | |||
106 | struct { | ||
107 | u8 HABR :1; | ||
108 | u8 LDHABR :1; | ||
109 | u8 APMSK :1; | ||
110 | u8 HMSK :1; | ||
111 | u8 LDMSK :1; | ||
112 | u8 na :3; | ||
113 | } HABSTAT_a8; | ||
114 | |||
115 | u8 MADRH_a9; | ||
116 | u8 MADRL_aa; | ||
117 | u8 MDATA_ab; | ||
118 | |||
119 | struct { | ||
120 | #define JDEC_WAIT_AT_RAM 0x7 | ||
121 | #define JDEC_EEPROM_LOAD_WAIT 0x4 | ||
122 | u8 JDEC :3; | ||
123 | u8 na :5; | ||
124 | } JDEC_ca; | ||
125 | |||
126 | struct { | ||
127 | u8 REV :4; | ||
128 | u8 LAYER :4; | ||
129 | } REVID_e0; | ||
130 | |||
131 | struct { | ||
132 | u8 unk0 :1; | ||
133 | u8 CNTCTL :1; | ||
134 | u8 BITCNT :1; | ||
135 | u8 unk1 :1; | ||
136 | u8 RESYNC :1; | ||
137 | u8 unk2 :3; | ||
138 | } BERCTL_fa; | ||
139 | |||
140 | struct { | ||
141 | u8 CSEL0 :1; | ||
142 | u8 CLKED0 :1; | ||
143 | u8 CSEL1 :1; | ||
144 | u8 CLKED1 :1; | ||
145 | u8 CLKLEV :1; | ||
146 | u8 SPIVAR :1; | ||
147 | u8 na :2; | ||
148 | } TUNSET_fc; | ||
149 | |||
150 | struct { | ||
151 | u8 CLK :1; | ||
152 | u8 DATA :1; | ||
153 | u8 CS0 :1; | ||
154 | u8 CS1 :1; | ||
155 | u8 AGCSEL :1; | ||
156 | u8 na0 :1; | ||
157 | u8 TUNSEL :1; | ||
158 | u8 na1 :1; | ||
159 | } TUNCTL_fd; | ||
160 | |||
161 | u8 TUNSEL0_fe; | ||
162 | u8 TUNSEL1_ff; | ||
163 | |||
164 | } bcm3510_register_value; | ||
165 | |||
166 | /* HAB commands */ | ||
167 | |||
168 | /* version */ | ||
169 | #define CMD_GET_VERSION_INFO 0x3D | ||
170 | #define MSGID_GET_VERSION_INFO 0x15 | ||
171 | struct bcm3510_hab_cmd_get_version_info { | ||
172 | u8 microcode_version; | ||
173 | u8 script_version; | ||
174 | u8 config_version; | ||
175 | u8 demod_version; | ||
176 | } PACKED; | ||
177 | |||
178 | #define BCM3510_DEF_MICROCODE_VERSION 0x0E | ||
179 | #define BCM3510_DEF_SCRIPT_VERSION 0x06 | ||
180 | #define BCM3510_DEF_CONFIG_VERSION 0x01 | ||
181 | #define BCM3510_DEF_DEMOD_VERSION 0xB1 | ||
182 | |||
183 | /* acquire */ | ||
184 | #define CMD_ACQUIRE 0x38 | ||
185 | |||
186 | #define MSGID_EXT_TUNER_ACQUIRE 0x0A | ||
187 | struct bcm3510_hab_cmd_ext_acquire { | ||
188 | struct { | ||
189 | u8 MODE :4; | ||
190 | u8 BW :1; | ||
191 | u8 FA :1; | ||
192 | u8 NTSCSWEEP :1; | ||
193 | u8 OFFSET :1; | ||
194 | } PACKED ACQUIRE0; /* control_byte */ | ||
195 | |||
196 | struct { | ||
197 | u8 IF_FREQ :3; | ||
198 | u8 zero0 :1; | ||
199 | u8 SYM_RATE :3; | ||
200 | u8 zero1 :1; | ||
201 | } PACKED ACQUIRE1; /* sym_if */ | ||
202 | |||
203 | u8 IF_OFFSET0; /* IF_Offset_10hz */ | ||
204 | u8 IF_OFFSET1; | ||
205 | u8 SYM_OFFSET0; /* SymbolRateOffset */ | ||
206 | u8 SYM_OFFSET1; | ||
207 | u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */ | ||
208 | u8 NTSC_OFFSET1; | ||
209 | } PACKED; | ||
210 | |||
211 | #define MSGID_INT_TUNER_ACQUIRE 0x0B | ||
212 | struct bcm3510_hab_cmd_int_acquire { | ||
213 | struct { | ||
214 | u8 MODE :4; | ||
215 | u8 BW :1; | ||
216 | u8 FA :1; | ||
217 | u8 NTSCSWEEP :1; | ||
218 | u8 OFFSET :1; | ||
219 | } PACKED ACQUIRE0; /* control_byte */ | ||
220 | |||
221 | struct { | ||
222 | u8 IF_FREQ :3; | ||
223 | u8 zero0 :1; | ||
224 | u8 SYM_RATE :3; | ||
225 | u8 zero1 :1; | ||
226 | } PACKED ACQUIRE1; /* sym_if */ | ||
227 | |||
228 | u8 TUNER_FREQ0; | ||
229 | u8 TUNER_FREQ1; | ||
230 | u8 TUNER_FREQ2; | ||
231 | u8 TUNER_FREQ3; | ||
232 | u8 IF_OFFSET0; /* IF_Offset_10hz */ | ||
233 | u8 IF_OFFSET1; | ||
234 | u8 SYM_OFFSET0; /* SymbolRateOffset */ | ||
235 | u8 SYM_OFFSET1; | ||
236 | u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */ | ||
237 | u8 NTSC_OFFSET1; | ||
238 | } PACKED; | ||
239 | |||
240 | /* modes */ | ||
241 | #define BCM3510_QAM16 = 0x01 | ||
242 | #define BCM3510_QAM32 = 0x02 | ||
243 | #define BCM3510_QAM64 = 0x03 | ||
244 | #define BCM3510_QAM128 = 0x04 | ||
245 | #define BCM3510_QAM256 = 0x05 | ||
246 | #define BCM3510_8VSB = 0x0B | ||
247 | #define BCM3510_16VSB = 0x0D | ||
248 | |||
249 | /* IF_FREQS */ | ||
250 | #define BCM3510_IF_TERRESTRIAL 0x0 | ||
251 | #define BCM3510_IF_CABLE 0x1 | ||
252 | #define BCM3510_IF_USE_CMD 0x7 | ||
253 | |||
254 | /* SYM_RATE */ | ||
255 | #define BCM3510_SR_8VSB 0x0 /* 5381119 s/sec */ | ||
256 | #define BCM3510_SR_256QAM 0x1 /* 5360537 s/sec */ | ||
257 | #define BCM3510_SR_16QAM 0x2 /* 5056971 s/sec */ | ||
258 | #define BCM3510_SR_MISC 0x3 /* 5000000 s/sec */ | ||
259 | #define BCM3510_SR_USE_CMD 0x7 | ||
260 | |||
261 | /* special symbol rate */ | ||
262 | #define CMD_SET_VALUE_NOT_LISTED 0x2d | ||
263 | #define MSGID_SET_SYMBOL_RATE_NOT_LISTED 0x0c | ||
264 | struct bcm3510_hab_cmd_set_sr_not_listed { | ||
265 | u8 HOST_SYM_RATE0; | ||
266 | u8 HOST_SYM_RATE1; | ||
267 | u8 HOST_SYM_RATE2; | ||
268 | u8 HOST_SYM_RATE3; | ||
269 | } PACKED; | ||
270 | |||
271 | /* special IF */ | ||
272 | #define MSGID_SET_IF_FREQ_NOT_LISTED 0x0d | ||
273 | struct bcm3510_hab_cmd_set_if_freq_not_listed { | ||
274 | u8 HOST_IF_FREQ0; | ||
275 | u8 HOST_IF_FREQ1; | ||
276 | u8 HOST_IF_FREQ2; | ||
277 | u8 HOST_IF_FREQ3; | ||
278 | } PACKED; | ||
279 | |||
280 | /* auto reacquire */ | ||
281 | #define CMD_AUTO_PARAM 0x2a | ||
282 | #define MSGID_AUTO_REACQUIRE 0x0e | ||
283 | struct bcm3510_hab_cmd_auto_reacquire { | ||
284 | u8 ACQ :1; /* on/off*/ | ||
285 | u8 unused :7; | ||
286 | } PACKED; | ||
287 | |||
288 | #define MSGID_SET_RF_AGC_SEL 0x12 | ||
289 | struct bcm3510_hab_cmd_set_agc { | ||
290 | u8 LVL :1; | ||
291 | u8 unused :6; | ||
292 | u8 SEL :1; | ||
293 | } PACKED; | ||
294 | |||
295 | #define MSGID_SET_AUTO_INVERSION 0x14 | ||
296 | struct bcm3510_hab_cmd_auto_inversion { | ||
297 | u8 AI :1; | ||
298 | u8 unused :7; | ||
299 | } PACKED; | ||
300 | |||
301 | |||
302 | /* bert control */ | ||
303 | #define CMD_STATE_CONTROL 0x12 | ||
304 | #define MSGID_BERT_CONTROL 0x0e | ||
305 | #define MSGID_BERT_SET 0xfa | ||
306 | struct bcm3510_hab_cmd_bert_control { | ||
307 | u8 BE :1; | ||
308 | u8 unused :7; | ||
309 | } PACKED; | ||
310 | |||
311 | #define MSGID_TRI_STATE 0x2e | ||
312 | struct bcm3510_hab_cmd_tri_state { | ||
313 | u8 RE :1; /* a/d ram port pins */ | ||
314 | u8 PE :1; /* baud clock pin */ | ||
315 | u8 AC :1; /* a/d clock pin */ | ||
316 | u8 BE :1; /* baud clock pin */ | ||
317 | u8 unused :4; | ||
318 | } PACKED; | ||
319 | |||
320 | |||
321 | /* tune */ | ||
322 | #define CMD_TUNE 0x38 | ||
323 | #define MSGID_TUNE 0x16 | ||
324 | struct bcm3510_hab_cmd_tune_ctrl_data_pair { | ||
325 | struct { | ||
326 | #define BITS_8 0x07 | ||
327 | #define BITS_7 0x06 | ||
328 | #define BITS_6 0x05 | ||
329 | #define BITS_5 0x04 | ||
330 | #define BITS_4 0x03 | ||
331 | #define BITS_3 0x02 | ||
332 | #define BITS_2 0x01 | ||
333 | #define BITS_1 0x00 | ||
334 | u8 size :3; | ||
335 | u8 unk :2; | ||
336 | u8 clk_off :1; | ||
337 | u8 cs0 :1; | ||
338 | u8 cs1 :1; | ||
339 | |||
340 | } PACKED ctrl; | ||
341 | |||
342 | u8 data; | ||
343 | } PACKED; | ||
344 | |||
345 | struct bcm3510_hab_cmd_tune { | ||
346 | u8 length; | ||
347 | u8 clock_width; | ||
348 | u8 misc; | ||
349 | u8 TUNCTL_state; | ||
350 | |||
351 | struct bcm3510_hab_cmd_tune_ctrl_data_pair ctl_dat[16]; | ||
352 | } PACKED; | ||
353 | |||
354 | #define CMD_STATUS 0x38 | ||
355 | #define MSGID_STATUS1 0x08 | ||
356 | struct bcm3510_hab_cmd_status1 { | ||
357 | struct { | ||
358 | u8 EQ_MODE :4; | ||
359 | u8 reserved :2; | ||
360 | u8 QRE :1; /* if QSE and the spectrum is inversed */ | ||
361 | u8 QSE :1; /* automatic spectral inversion */ | ||
362 | } PACKED STATUS0; | ||
363 | |||
364 | struct { | ||
365 | u8 RECEIVER_LOCK :1; | ||
366 | u8 FEC_LOCK :1; | ||
367 | u8 OUT_PLL_LOCK :1; | ||
368 | u8 reserved :5; | ||
369 | } PACKED STATUS1; | ||
370 | |||
371 | struct { | ||
372 | u8 reserved :2; | ||
373 | u8 BW :1; | ||
374 | u8 NTE :1; /* NTSC filter sweep enabled */ | ||
375 | u8 AQI :1; /* currently acquiring */ | ||
376 | u8 FA :1; /* fast acquisition */ | ||
377 | u8 ARI :1; /* auto reacquire */ | ||
378 | u8 TI :1; /* programming the tuner */ | ||
379 | } PACKED STATUS2; | ||
380 | u8 STATUS3; | ||
381 | u8 SNR_EST0; | ||
382 | u8 SNR_EST1; | ||
383 | u8 TUNER_FREQ0; | ||
384 | u8 TUNER_FREQ1; | ||
385 | u8 TUNER_FREQ2; | ||
386 | u8 TUNER_FREQ3; | ||
387 | u8 SYM_RATE0; | ||
388 | u8 SYM_RATE1; | ||
389 | u8 SYM_RATE2; | ||
390 | u8 SYM_RATE3; | ||
391 | u8 SYM_OFFSET0; | ||
392 | u8 SYM_OFFSET1; | ||
393 | u8 SYM_ERROR0; | ||
394 | u8 SYM_ERROR1; | ||
395 | u8 IF_FREQ0; | ||
396 | u8 IF_FREQ1; | ||
397 | u8 IF_FREQ2; | ||
398 | u8 IF_FREQ3; | ||
399 | u8 IF_OFFSET0; | ||
400 | u8 IF_OFFSET1; | ||
401 | u8 IF_ERROR0; | ||
402 | u8 IF_ERROR1; | ||
403 | u8 NTSC_FILTER0; | ||
404 | u8 NTSC_FILTER1; | ||
405 | u8 NTSC_FILTER2; | ||
406 | u8 NTSC_FILTER3; | ||
407 | u8 NTSC_OFFSET0; | ||
408 | u8 NTSC_OFFSET1; | ||
409 | u8 NTSC_ERROR0; | ||
410 | u8 NTSC_ERROR1; | ||
411 | u8 INT_AGC_LEVEL0; | ||
412 | u8 INT_AGC_LEVEL1; | ||
413 | u8 EXT_AGC_LEVEL0; | ||
414 | u8 EXT_AGC_LEVEL1; | ||
415 | } PACKED; | ||
416 | |||
417 | #define MSGID_STATUS2 0x14 | ||
418 | struct bcm3510_hab_cmd_status2 { | ||
419 | struct { | ||
420 | u8 EQ_MODE :4; | ||
421 | u8 reserved :2; | ||
422 | u8 QRE :1; | ||
423 | u8 QSR :1; | ||
424 | } PACKED STATUS0; | ||
425 | struct { | ||
426 | u8 RL :1; | ||
427 | u8 FL :1; | ||
428 | u8 OL :1; | ||
429 | u8 reserved :5; | ||
430 | } PACKED STATUS1; | ||
431 | u8 SYMBOL_RATE0; | ||
432 | u8 SYMBOL_RATE1; | ||
433 | u8 SYMBOL_RATE2; | ||
434 | u8 SYMBOL_RATE3; | ||
435 | u8 LDCERC0; | ||
436 | u8 LDCERC1; | ||
437 | u8 LDCERC2; | ||
438 | u8 LDCERC3; | ||
439 | u8 LDUERC0; | ||
440 | u8 LDUERC1; | ||
441 | u8 LDUERC2; | ||
442 | u8 LDUERC3; | ||
443 | u8 LDBER0; | ||
444 | u8 LDBER1; | ||
445 | u8 LDBER2; | ||
446 | u8 LDBER3; | ||
447 | struct { | ||
448 | u8 MODE_TYPE :4; /* acquire mode 0 */ | ||
449 | u8 reservd :4; | ||
450 | } MODE_TYPE; | ||
451 | u8 SNR_EST0; | ||
452 | u8 SNR_EST1; | ||
453 | u8 SIGNAL; | ||
454 | } PACKED; | ||
455 | |||
456 | #define CMD_SET_RF_BW_NOT_LISTED 0x3f | ||
457 | #define MSGID_SET_RF_BW_NOT_LISTED 0x11 | ||
458 | /* TODO */ | ||
459 | |||
460 | #endif | ||
diff --git a/drivers/media/dvb/frontends/dib3000-common.c b/drivers/media/dvb/frontends/dib3000-common.c index 47ab02e133..1a4f1f7c22 100644 --- a/drivers/media/dvb/frontends/dib3000-common.c +++ b/drivers/media/dvb/frontends/dib3000-common.c | |||
@@ -73,7 +73,7 @@ u16 dib3000_seq[2][2][2] = /* fft,gua, inv */ | |||
73 | }; | 73 | }; |
74 | 74 | ||
75 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de"); | 75 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de"); |
76 | MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb-frontend drivers"); | 76 | MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers"); |
77 | MODULE_LICENSE("GPL"); | 77 | MODULE_LICENSE("GPL"); |
78 | 78 | ||
79 | EXPORT_SYMBOL(dib3000_seq); | 79 | EXPORT_SYMBOL(dib3000_seq); |
diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h index 80687c1308..2d5475b5c0 100644 --- a/drivers/media/dvb/frontends/dib3000.h +++ b/drivers/media/dvb/frontends/dib3000.h | |||
@@ -32,9 +32,8 @@ struct dib3000_config | |||
32 | u8 demod_address; | 32 | u8 demod_address; |
33 | 33 | ||
34 | /* PLL maintenance and the i2c address of the PLL */ | 34 | /* PLL maintenance and the i2c address of the PLL */ |
35 | u8 (*pll_addr)(struct dvb_frontend *fe); | 35 | int (*pll_init)(struct dvb_frontend *fe); |
36 | int (*pll_init)(struct dvb_frontend *fe, u8 pll_buf[5]); | 36 | int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params); |
37 | int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params, u8 pll_buf[5]); | ||
38 | }; | 37 | }; |
39 | 38 | ||
40 | struct dib_fe_xfer_ops | 39 | struct dib_fe_xfer_ops |
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c index 6f52d649e9..cd434b7cf9 100644 --- a/drivers/media/dvb/frontends/dib3000mb.c +++ b/drivers/media/dvb/frontends/dib3000mb.c | |||
@@ -48,8 +48,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a | |||
48 | #define deb_setf(args...) dprintk(0x04,args) | 48 | #define deb_setf(args...) dprintk(0x04,args) |
49 | #define deb_getf(args...) dprintk(0x08,args) | 49 | #define deb_getf(args...) dprintk(0x08,args) |
50 | 50 | ||
51 | static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr); | ||
52 | |||
53 | static int dib3000mb_get_frontend(struct dvb_frontend* fe, | 51 | static int dib3000mb_get_frontend(struct dvb_frontend* fe, |
54 | struct dvb_frontend_parameters *fep); | 52 | struct dvb_frontend_parameters *fep); |
55 | 53 | ||
@@ -61,10 +59,8 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe, | |||
61 | fe_code_rate_t fe_cr = FEC_NONE; | 59 | fe_code_rate_t fe_cr = FEC_NONE; |
62 | int search_state, seq; | 60 | int search_state, seq; |
63 | 61 | ||
64 | if (tuner && state->config.pll_addr && state->config.pll_set) { | 62 | if (tuner && state->config.pll_set) { |
65 | dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); | 63 | state->config.pll_set(fe, fep); |
66 | state->config.pll_set(fe, fep, NULL); | ||
67 | dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe)); | ||
68 | 64 | ||
69 | deb_setf("bandwidth: "); | 65 | deb_setf("bandwidth: "); |
70 | switch (ofdm->bandwidth) { | 66 | switch (ofdm->bandwidth) { |
@@ -389,11 +385,8 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode) | |||
389 | 385 | ||
390 | wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF); | 386 | wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF); |
391 | 387 | ||
392 | if (state->config.pll_init) { | 388 | if (state->config.pll_init) |
393 | dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); | 389 | state->config.pll_init(fe); |
394 | state->config.pll_init(fe,NULL); | ||
395 | dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe)); | ||
396 | } | ||
397 | 390 | ||
398 | return 0; | 391 | return 0; |
399 | } | 392 | } |
@@ -623,7 +616,7 @@ static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | |||
623 | { | 616 | { |
624 | struct dib3000_state* state = fe->demodulator_priv; | 617 | struct dib3000_state* state = fe->demodulator_priv; |
625 | 618 | ||
626 | *unc = rd(DIB3000MB_REG_UNC); | 619 | *unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE); |
627 | return 0; | 620 | return 0; |
628 | } | 621 | } |
629 | 622 | ||
@@ -638,9 +631,6 @@ static int dib3000mb_sleep(struct dvb_frontend* fe) | |||
638 | static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | 631 | static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) |
639 | { | 632 | { |
640 | tune->min_delay_ms = 800; | 633 | tune->min_delay_ms = 800; |
641 | tune->step_size = 166667; | ||
642 | tune->max_drift = 166667 * 2; | ||
643 | |||
644 | return 0; | 634 | return 0; |
645 | } | 635 | } |
646 | 636 | ||
diff --git a/drivers/media/dvb/frontends/dib3000mb_priv.h b/drivers/media/dvb/frontends/dib3000mb_priv.h index 57e61aa5b0..999b190478 100644 --- a/drivers/media/dvb/frontends/dib3000mb_priv.h +++ b/drivers/media/dvb/frontends/dib3000mb_priv.h | |||
@@ -294,7 +294,7 @@ static u16 dib3000mb_reg_filter_coeffs[] = { | |||
294 | 294 | ||
295 | static u16 dib3000mb_filter_coeffs[] = { | 295 | static u16 dib3000mb_filter_coeffs[] = { |
296 | 226, 160, 29, | 296 | 226, 160, 29, |
297 | 979, 998, 19, | 297 | 979, 998, 19, |
298 | 22, 1019, 1006, | 298 | 22, 1019, 1006, |
299 | 1022, 12, 6, | 299 | 1022, 12, 6, |
300 | 1017, 1017, 3, | 300 | 1017, 1017, 3, |
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c index 888f10a5e9..cd33705a43 100644 --- a/drivers/media/dvb/frontends/dib3000mc.c +++ b/drivers/media/dvb/frontends/dib3000mc.c | |||
@@ -48,8 +48,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe,16=s | |||
48 | #define deb_getf(args...) dprintk(0x08,args) | 48 | #define deb_getf(args...) dprintk(0x08,args) |
49 | #define deb_stat(args...) dprintk(0x10,args) | 49 | #define deb_stat(args...) dprintk(0x10,args) |
50 | 50 | ||
51 | static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr); | ||
52 | |||
53 | static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode, | 51 | static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode, |
54 | fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth) | 52 | fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth) |
55 | { | 53 | { |
@@ -463,10 +461,8 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe, | |||
463 | int search_state,auto_val; | 461 | int search_state,auto_val; |
464 | u16 val; | 462 | u16 val; |
465 | 463 | ||
466 | if (tuner && state->config.pll_addr && state->config.pll_set) { /* initial call from dvb */ | 464 | if (tuner && state->config.pll_set) { /* initial call from dvb */ |
467 | dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); | 465 | state->config.pll_set(fe,fep); |
468 | state->config.pll_set(fe,fep,NULL); | ||
469 | dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe)); | ||
470 | 466 | ||
471 | state->last_tuned_freq = fep->frequency; | 467 | state->last_tuned_freq = fep->frequency; |
472 | // if (!scanboost) { | 468 | // if (!scanboost) { |
@@ -554,19 +550,15 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe, | |||
554 | dib3000mc_set_adp_cfg(state,ofdm->constellation); | 550 | dib3000mc_set_adp_cfg(state,ofdm->constellation); |
555 | wr_foreach(dib3000mc_reg_offset, | 551 | wr_foreach(dib3000mc_reg_offset, |
556 | dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]); | 552 | dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]); |
557 | |||
558 | |||
559 | } | 553 | } |
560 | return 0; | 554 | return 0; |
561 | } | 555 | } |
562 | 556 | ||
563 | static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode) | 557 | static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode) |
564 | { | 558 | { |
565 | struct dib3000_state *state; | 559 | struct dib3000_state *state = fe->demodulator_priv; |
566 | |||
567 | deb_info("init start\n"); | 560 | deb_info("init start\n"); |
568 | 561 | ||
569 | state = fe->demodulator_priv; | ||
570 | state->timing_offset = 0; | 562 | state->timing_offset = 0; |
571 | state->timing_offset_comp_done = 0; | 563 | state->timing_offset_comp_done = 0; |
572 | 564 | ||
@@ -649,11 +641,9 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode) | |||
649 | 641 | ||
650 | set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF); | 642 | set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF); |
651 | 643 | ||
652 | /* if (state->config->pll_init) { | 644 | if (state->config.pll_init) |
653 | dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); | 645 | state->config.pll_init(fe); |
654 | state->config->pll_init(fe,NULL); | 646 | |
655 | dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe)); | ||
656 | }*/ | ||
657 | deb_info("init end\n"); | 647 | deb_info("init end\n"); |
658 | return 0; | 648 | return 0; |
659 | } | 649 | } |
@@ -688,7 +678,7 @@ static int dib3000mc_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | |||
688 | { | 678 | { |
689 | struct dib3000_state* state = fe->demodulator_priv; | 679 | struct dib3000_state* state = fe->demodulator_priv; |
690 | 680 | ||
691 | *unc = rd(DIB3000MC_REG_PACKET_ERROR_COUNT); | 681 | *unc = rd(DIB3000MC_REG_PACKET_ERRORS); |
692 | return 0; | 682 | return 0; |
693 | } | 683 | } |
694 | 684 | ||
@@ -737,10 +727,7 @@ static int dib3000mc_sleep(struct dvb_frontend* fe) | |||
737 | 727 | ||
738 | static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | 728 | static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) |
739 | { | 729 | { |
740 | tune->min_delay_ms = 2000; | 730 | tune->min_delay_ms = 1000; |
741 | tune->step_size = 166667; | ||
742 | tune->max_drift = 166667 * 2; | ||
743 | |||
744 | return 0; | 731 | return 0; |
745 | } | 732 | } |
746 | 733 | ||
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 2a3c2ce7b2..f73b5f48e2 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: dvb-pll.c,v 1.7 2005/02/10 11:52:02 kraxel Exp $ | ||
3 | * | ||
4 | * descriptions + helper functions for simple dvb plls. | 2 | * descriptions + helper functions for simple dvb plls. |
5 | * | 3 | * |
6 | * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | 4 | * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] |
@@ -114,6 +112,92 @@ struct dvb_pll_desc dvb_pll_unknown_1 = { | |||
114 | }; | 112 | }; |
115 | EXPORT_SYMBOL(dvb_pll_unknown_1); | 113 | EXPORT_SYMBOL(dvb_pll_unknown_1); |
116 | 114 | ||
115 | /* Infineon TUA6010XS | ||
116 | * used in Thomson Cable Tuner | ||
117 | */ | ||
118 | struct dvb_pll_desc dvb_pll_tua6010xs = { | ||
119 | .name = "Infineon TUA6010XS", | ||
120 | .min = 44250000, | ||
121 | .max = 858000000, | ||
122 | .count = 3, | ||
123 | .entries = { | ||
124 | { 115750000, 36125000, 62500, 0x8e, 0x03 }, | ||
125 | { 403250000, 36125000, 62500, 0x8e, 0x06 }, | ||
126 | { 999999999, 36125000, 62500, 0x8e, 0x85 }, | ||
127 | }, | ||
128 | }; | ||
129 | EXPORT_SYMBOL(dvb_pll_tua6010xs); | ||
130 | |||
131 | /* Panasonic env57h1xd5 (some Philips PLL ?) */ | ||
132 | struct dvb_pll_desc dvb_pll_env57h1xd5 = { | ||
133 | .name = "Panasonic ENV57H1XD5", | ||
134 | .min = 44250000, | ||
135 | .max = 858000000, | ||
136 | .count = 4, | ||
137 | .entries = { | ||
138 | { 153000000, 36291666, 166666, 0xc2, 0x41 }, | ||
139 | { 470000000, 36291666, 166666, 0xc2, 0x42 }, | ||
140 | { 526000000, 36291666, 166666, 0xc2, 0x84 }, | ||
141 | { 999999999, 36291666, 166666, 0xc2, 0xa4 }, | ||
142 | }, | ||
143 | }; | ||
144 | EXPORT_SYMBOL(dvb_pll_env57h1xd5); | ||
145 | |||
146 | /* Philips TDA6650/TDA6651 | ||
147 | * used in Panasonic ENV77H11D5 | ||
148 | */ | ||
149 | static void tda665x_bw(u8 *buf, int bandwidth) | ||
150 | { | ||
151 | if (bandwidth == BANDWIDTH_8_MHZ) | ||
152 | buf[3] |= 0x08; | ||
153 | } | ||
154 | |||
155 | struct dvb_pll_desc dvb_pll_tda665x = { | ||
156 | .name = "Philips TDA6650/TDA6651", | ||
157 | .min = 44250000, | ||
158 | .max = 858000000, | ||
159 | .setbw = tda665x_bw, | ||
160 | .count = 12, | ||
161 | .entries = { | ||
162 | { 93834000, 36249333, 166667, 0xca, 0x61 /* 011 0 0 0 01 */ }, | ||
163 | { 123834000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, | ||
164 | { 161000000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, | ||
165 | { 163834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, | ||
166 | { 253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ }, | ||
167 | { 383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ }, | ||
168 | { 443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, | ||
169 | { 444000000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ }, | ||
170 | { 583834000, 36249333, 166667, 0xca, 0x63 /* 011 0 0 0 11 */ }, | ||
171 | { 793834000, 36249333, 166667, 0xca, 0xa3 /* 101 0 0 0 11 */ }, | ||
172 | { 444834000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ }, | ||
173 | { 861000000, 36249333, 166667, 0xca, 0xe3 /* 111 0 0 0 11 */ }, | ||
174 | } | ||
175 | }; | ||
176 | EXPORT_SYMBOL(dvb_pll_tda665x); | ||
177 | |||
178 | /* Infineon TUA6034 | ||
179 | * used in LG TDTP E102P | ||
180 | */ | ||
181 | static void tua6034_bw(u8 *buf, int bandwidth) | ||
182 | { | ||
183 | if (BANDWIDTH_7_MHZ != bandwidth) | ||
184 | buf[3] |= 0x08; | ||
185 | } | ||
186 | |||
187 | struct dvb_pll_desc dvb_pll_tua6034 = { | ||
188 | .name = "Infineon TUA6034", | ||
189 | .min = 44250000, | ||
190 | .max = 858000000, | ||
191 | .count = 3, | ||
192 | .setbw = tua6034_bw, | ||
193 | .entries = { | ||
194 | { 174500000, 36166667, 62500, 0xce, 0x01 }, | ||
195 | { 230000000, 36166667, 62500, 0xce, 0x02 }, | ||
196 | { 999999999, 36166667, 62500, 0xce, 0x04 }, | ||
197 | }, | ||
198 | }; | ||
199 | EXPORT_SYMBOL(dvb_pll_tua6034); | ||
200 | |||
117 | /* ----------------------------------------------------------- */ | 201 | /* ----------------------------------------------------------- */ |
118 | /* code */ | 202 | /* code */ |
119 | 203 | ||
@@ -160,9 +244,3 @@ EXPORT_SYMBOL(dvb_pll_configure); | |||
160 | MODULE_DESCRIPTION("dvb pll library"); | 244 | MODULE_DESCRIPTION("dvb pll library"); |
161 | MODULE_AUTHOR("Gerd Knorr"); | 245 | MODULE_AUTHOR("Gerd Knorr"); |
162 | MODULE_LICENSE("GPL"); | 246 | MODULE_LICENSE("GPL"); |
163 | |||
164 | /* | ||
165 | * Local variables: | ||
166 | * c-basic-offset: 8 | ||
167 | * End: | ||
168 | */ | ||
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index c4c3c56c4a..b796778624 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: dvb-pll.h,v 1.2 2005/02/10 11:43:41 kraxel Exp $ | 2 | * descriptions + helper functions for simple dvb plls. |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #ifndef __DVB_PLL_H__ | 5 | #ifndef __DVB_PLL_H__ |
@@ -17,7 +17,7 @@ struct dvb_pll_desc { | |||
17 | u32 stepsize; | 17 | u32 stepsize; |
18 | u8 cb1; | 18 | u8 cb1; |
19 | u8 cb2; | 19 | u8 cb2; |
20 | } entries[9]; | 20 | } entries[12]; |
21 | }; | 21 | }; |
22 | 22 | ||
23 | extern struct dvb_pll_desc dvb_pll_thomson_dtt7579; | 23 | extern struct dvb_pll_desc dvb_pll_thomson_dtt7579; |
@@ -26,6 +26,11 @@ extern struct dvb_pll_desc dvb_pll_thomson_dtt7610; | |||
26 | extern struct dvb_pll_desc dvb_pll_lg_z201; | 26 | extern struct dvb_pll_desc dvb_pll_lg_z201; |
27 | extern struct dvb_pll_desc dvb_pll_unknown_1; | 27 | extern struct dvb_pll_desc dvb_pll_unknown_1; |
28 | 28 | ||
29 | extern struct dvb_pll_desc dvb_pll_tua6010xs; | ||
30 | extern struct dvb_pll_desc dvb_pll_env57h1xd5; | ||
31 | extern struct dvb_pll_desc dvb_pll_tua6034; | ||
32 | extern struct dvb_pll_desc dvb_pll_tda665x; | ||
33 | |||
29 | int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, | 34 | int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, |
30 | u32 freq, int bandwidth); | 35 | u32 freq, int bandwidth); |
31 | 36 | ||
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 6c05fddb69..f9383e7f34 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -7,6 +7,19 @@ menu "Video For Linux" | |||
7 | 7 | ||
8 | comment "Video Adapters" | 8 | comment "Video Adapters" |
9 | 9 | ||
10 | config CONFIG_TUNER_MULTI_I2C | ||
11 | bool "Enable support for multiple I2C devices on Video Adapters (EXPERIMENTAL)" | ||
12 | depends on VIDEO_DEV && EXPERIMENTAL | ||
13 | ---help--- | ||
14 | Some video adapters have more than one tuner inside. This patch | ||
15 | enables support for using more than one tuner. This is required | ||
16 | for some cards to allow tunning both video and radio. | ||
17 | It also improves I2C autodetection for these cards. | ||
18 | |||
19 | Only few tuners currently is supporting this. More to come. | ||
20 | |||
21 | It is safe to say 'Y' here even if your card has only one I2C tuner. | ||
22 | |||
10 | config VIDEO_BT848 | 23 | config VIDEO_BT848 |
11 | tristate "BT848 Video For Linux" | 24 | tristate "BT848 Video For Linux" |
12 | depends on VIDEO_DEV && PCI && I2C | 25 | depends on VIDEO_DEV && PCI && I2C |
@@ -330,6 +343,7 @@ config VIDEO_CX88_DVB | |||
330 | select VIDEO_BUF_DVB | 343 | select VIDEO_BUF_DVB |
331 | select DVB_MT352 | 344 | select DVB_MT352 |
332 | select DVB_OR51132 | 345 | select DVB_OR51132 |
346 | select DVB_CX22702 | ||
333 | ---help--- | 347 | ---help--- |
334 | This adds support for DVB/ATSC cards based on the | 348 | This adds support for DVB/ATSC cards based on the |
335 | Connexant 2388x chip. | 349 | Connexant 2388x chip. |
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c index 07f72f64c5..9a642c7de5 100644 --- a/drivers/media/video/bt832.c +++ b/drivers/media/video/bt832.c | |||
@@ -6,7 +6,7 @@ | |||
6 | It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly | 6 | It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly |
7 | connected to bt848/bt878 GPIO pins on this purpose. | 7 | connected to bt848/bt878 GPIO pins on this purpose. |
8 | (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets) | 8 | (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets) |
9 | 9 | ||
10 | Supported Cards: | 10 | Supported Cards: |
11 | - Pixelview Rev.4E: 0x8a | 11 | - Pixelview Rev.4E: 0x8a |
12 | GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 ! | 12 | GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 ! |
@@ -31,8 +31,8 @@ | |||
31 | #include <linux/errno.h> | 31 | #include <linux/errno.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | 33 | ||
34 | #include "id.h" | 34 | #include <media/audiochip.h> |
35 | #include "audiochip.h" | 35 | #include <media/id.h> |
36 | #include "bttv.h" | 36 | #include "bttv.h" |
37 | #include "bt832.h" | 37 | #include "bt832.h" |
38 | 38 | ||
@@ -95,7 +95,7 @@ int bt832_init(struct i2c_client *i2c_client_s) | |||
95 | 95 | ||
96 | buf=kmalloc(65,GFP_KERNEL); | 96 | buf=kmalloc(65,GFP_KERNEL); |
97 | bt832_hexdump(i2c_client_s,buf); | 97 | bt832_hexdump(i2c_client_s,buf); |
98 | 98 | ||
99 | if(buf[0x40] != 0x31) { | 99 | if(buf[0x40] != 0x31) { |
100 | printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]); | 100 | printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]); |
101 | kfree(buf); | 101 | kfree(buf); |
@@ -135,7 +135,7 @@ int bt832_init(struct i2c_client *i2c_client_s) | |||
135 | buf[1]= 0x27 & (~0x01); // Default | !skip | 135 | buf[1]= 0x27 & (~0x01); // Default | !skip |
136 | if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) | 136 | if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) |
137 | printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc); | 137 | printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc); |
138 | 138 | ||
139 | bt832_hexdump(i2c_client_s,buf); | 139 | bt832_hexdump(i2c_client_s,buf); |
140 | 140 | ||
141 | #if 0 | 141 | #if 0 |
@@ -168,8 +168,7 @@ int bt832_init(struct i2c_client *i2c_client_s) | |||
168 | 168 | ||
169 | 169 | ||
170 | 170 | ||
171 | static int bt832_attach(struct i2c_adapter *adap, int addr, | 171 | static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) |
172 | unsigned short flags, int kind) | ||
173 | { | 172 | { |
174 | struct bt832 *t; | 173 | struct bt832 *t; |
175 | 174 | ||
@@ -184,27 +183,32 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, | |||
184 | return -ENOMEM; | 183 | return -ENOMEM; |
185 | memset(t,0,sizeof(*t)); | 184 | memset(t,0,sizeof(*t)); |
186 | t->client = client_template; | 185 | t->client = client_template; |
187 | t->client.data = t; | 186 | i2c_set_clientdata(&t->client, t); |
188 | i2c_attach_client(&t->client); | 187 | i2c_attach_client(&t->client); |
189 | 188 | ||
190 | if(! bt832_init(&t->client)) { | 189 | if(! bt832_init(&t->client)) { |
191 | bt832_detach(&t->client); | 190 | bt832_detach(&t->client); |
192 | return -1; | 191 | return -1; |
193 | } | 192 | } |
194 | 193 | ||
195 | return 0; | 194 | return 0; |
196 | } | 195 | } |
197 | 196 | ||
198 | static int bt832_probe(struct i2c_adapter *adap) | 197 | static int bt832_probe(struct i2c_adapter *adap) |
199 | { | 198 | { |
199 | #ifdef I2C_CLASS_TV_ANALOG | ||
200 | if (adap->class & I2C_CLASS_TV_ANALOG) | 200 | if (adap->class & I2C_CLASS_TV_ANALOG) |
201 | return i2c_probe(adap, &addr_data, bt832_attach); | 201 | return i2c_probe(adap, &addr_data, bt832_attach); |
202 | #else | ||
203 | if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) | ||
204 | return i2c_probe(adap, &addr_data, bt832_attach); | ||
205 | #endif | ||
202 | return 0; | 206 | return 0; |
203 | } | 207 | } |
204 | 208 | ||
205 | static int bt832_detach(struct i2c_client *client) | 209 | static int bt832_detach(struct i2c_client *client) |
206 | { | 210 | { |
207 | struct bt832 *t = (struct bt832*)client->data; | 211 | struct bt832 *t = i2c_get_clientdata(client); |
208 | 212 | ||
209 | printk("bt832: detach.\n"); | 213 | printk("bt832: detach.\n"); |
210 | i2c_detach_client(client); | 214 | i2c_detach_client(client); |
@@ -215,7 +219,7 @@ static int bt832_detach(struct i2c_client *client) | |||
215 | static int | 219 | static int |
216 | bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) | 220 | bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) |
217 | { | 221 | { |
218 | struct bt832 *t = (struct bt832*)client->data; | 222 | struct bt832 *t = i2c_get_clientdata(client); |
219 | 223 | ||
220 | printk("bt832: command %x\n",cmd); | 224 | printk("bt832: command %x\n",cmd); |
221 | 225 | ||
@@ -249,19 +253,18 @@ static struct i2c_driver driver = { | |||
249 | }; | 253 | }; |
250 | static struct i2c_client client_template = | 254 | static struct i2c_client client_template = |
251 | { | 255 | { |
252 | .name = "bt832", | 256 | I2C_DEVNAME("bt832"), |
253 | .flags = I2C_CLIENT_ALLOW_USE, | 257 | .flags = I2C_CLIENT_ALLOW_USE, |
254 | .driver = &driver, | 258 | .driver = &driver, |
255 | }; | 259 | }; |
256 | 260 | ||
257 | 261 | ||
258 | int bt832_init_module(void) | 262 | static int __init bt832_init_module(void) |
259 | { | 263 | { |
260 | i2c_add_driver(&driver); | 264 | return i2c_add_driver(&driver); |
261 | return 0; | ||
262 | } | 265 | } |
263 | 266 | ||
264 | static void bt832_cleanup_module(void) | 267 | static void __exit bt832_cleanup_module(void) |
265 | { | 268 | { |
266 | i2c_del_driver(&driver); | 269 | i2c_del_driver(&driver); |
267 | } | 270 | } |
@@ -269,3 +272,10 @@ static void bt832_cleanup_module(void) | |||
269 | module_init(bt832_init_module); | 272 | module_init(bt832_init_module); |
270 | module_exit(bt832_cleanup_module); | 273 | module_exit(bt832_cleanup_module); |
271 | 274 | ||
275 | /* | ||
276 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
277 | * --------------------------------------------------------------------------- | ||
278 | * Local variables: | ||
279 | * c-basic-offset: 8 | ||
280 | * End: | ||
281 | */ | ||
diff --git a/drivers/media/video/bt832.h b/drivers/media/video/bt832.h index 7a98c06e0e..9b6a8d2c96 100644 --- a/drivers/media/video/bt832.h +++ b/drivers/media/video/bt832.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* Bt832 CMOS Camera Video Processor (VP) | 1 | /* Bt832 CMOS Camera Video Processor (VP) |
2 | 2 | ||
3 | The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS | 3 | The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS |
4 | color digital camera directly to video capture devices via an 8-bit, | 4 | color digital camera directly to video capture devices via an 8-bit, |
5 | 4:2:2 YUV or YCrCb video interface. | 5 | 4:2:2 YUV or YCrCb video interface. |
6 | 6 | ||
@@ -85,7 +85,7 @@ | |||
85 | #define BT832_DEVICE_ID 63 | 85 | #define BT832_DEVICE_ID 63 |
86 | # define BT832_DEVICE_ID__31 0x31 // Bt832 has ID 0x31 | 86 | # define BT832_DEVICE_ID__31 0x31 // Bt832 has ID 0x31 |
87 | 87 | ||
88 | /* STMicroelectronivcs VV5404 camera module | 88 | /* STMicroelectronivcs VV5404 camera module |
89 | i2c: 0x20: sensor address | 89 | i2c: 0x20: sensor address |
90 | i2c: 0xa0: eeprom for ccd defect map | 90 | i2c: 0xa0: eeprom for ccd defect map |
91 | */ | 91 | */ |
@@ -256,26 +256,26 @@ For the CCIR-601 standards, the sampling is based on a static orthogonal samplin | |||
256 | //=========================================================================== | 256 | //=========================================================================== |
257 | // Timing generator SRAM table values for CCIR601 720x480 NTSC | 257 | // Timing generator SRAM table values for CCIR601 720x480 NTSC |
258 | //=========================================================================== | 258 | //=========================================================================== |
259 | // For NTSC CCIR656 | 259 | // For NTSC CCIR656 |
260 | BYTE BtCard::SRAMTable_NTSC[] = | 260 | BYTE BtCard::SRAMTable_NTSC[] = |
261 | { | 261 | { |
262 | // SRAM Timing Table for NTSC | 262 | // SRAM Timing Table for NTSC |
263 | 0x0c, 0xc0, 0x00, | 263 | 0x0c, 0xc0, 0x00, |
264 | 0x00, 0x90, 0xc2, | 264 | 0x00, 0x90, 0xc2, |
265 | 0x03, 0x10, 0x03, | 265 | 0x03, 0x10, 0x03, |
266 | 0x06, 0x10, 0x34, | 266 | 0x06, 0x10, 0x34, |
267 | 0x12, 0x12, 0x65, | 267 | 0x12, 0x12, 0x65, |
268 | 0x02, 0x13, 0x24, | 268 | 0x02, 0x13, 0x24, |
269 | 0x19, 0x00, 0x24, | 269 | 0x19, 0x00, 0x24, |
270 | 0x39, 0x00, 0x96, | 270 | 0x39, 0x00, 0x96, |
271 | 0x59, 0x08, 0x93, | 271 | 0x59, 0x08, 0x93, |
272 | 0x83, 0x08, 0x97, | 272 | 0x83, 0x08, 0x97, |
273 | 0x03, 0x50, 0x30, | 273 | 0x03, 0x50, 0x30, |
274 | 0xc0, 0x40, 0x30, | 274 | 0xc0, 0x40, 0x30, |
275 | 0x86, 0x01, 0x01, | 275 | 0x86, 0x01, 0x01, |
276 | 0xa6, 0x0d, 0x62, | 276 | 0xa6, 0x0d, 0x62, |
277 | 0x03, 0x11, 0x61, | 277 | 0x03, 0x11, 0x61, |
278 | 0x05, 0x37, 0x30, | 278 | 0x05, 0x37, 0x30, |
279 | 0xac, 0x21, 0x50 | 279 | 0xac, 0x21, 0x50 |
280 | }; | 280 | }; |
281 | 281 | ||
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 6334122704..251092e7f1 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | $Id: bttv-cards.c,v 1.47 2005/02/22 14:06:32 kraxel Exp $ | 2 | $Id: bttv-cards.c,v 1.49 2005/06/10 17:20:24 mchehab Exp $ |
3 | 3 | ||
4 | bttv-cards.c | 4 | bttv-cards.c |
5 | 5 | ||
@@ -51,6 +51,7 @@ static void avermedia_eeprom(struct bttv *btv); | |||
51 | static void osprey_eeprom(struct bttv *btv); | 51 | static void osprey_eeprom(struct bttv *btv); |
52 | static void modtec_eeprom(struct bttv *btv); | 52 | static void modtec_eeprom(struct bttv *btv); |
53 | static void init_PXC200(struct bttv *btv); | 53 | static void init_PXC200(struct bttv *btv); |
54 | static void init_RTV24(struct bttv *btv); | ||
54 | 55 | ||
55 | static void winview_audio(struct bttv *btv, struct video_audio *v, int set); | 56 | static void winview_audio(struct bttv *btv, struct video_audio *v, int set); |
56 | static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set); | 57 | static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set); |
@@ -2251,6 +2252,20 @@ struct tvcard bttv_tvcards[] = { | |||
2251 | .no_tda7432 = 1, | 2252 | .no_tda7432 = 1, |
2252 | .no_tda9875 = 1, | 2253 | .no_tda9875 = 1, |
2253 | .muxsel_hook = kodicom4400r_muxsel, | 2254 | .muxsel_hook = kodicom4400r_muxsel, |
2255 | }, | ||
2256 | { | ||
2257 | /* ---- card 0x85---------------------------------- */ | ||
2258 | /* Michael Henson <mhenson@clarityvi.com> */ | ||
2259 | /* Adlink RTV24 with special unlock codes */ | ||
2260 | .name = "Adlink RTV24", | ||
2261 | .video_inputs = 4, | ||
2262 | .audio_inputs = 1, | ||
2263 | .tuner = 0, | ||
2264 | .svhs = 2, | ||
2265 | .muxsel = { 2, 3, 1, 0}, | ||
2266 | .tuner_type = -1, | ||
2267 | .pll = PLL_28, | ||
2268 | |||
2254 | }}; | 2269 | }}; |
2255 | 2270 | ||
2256 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); | 2271 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); |
@@ -2636,6 +2651,10 @@ void __devinit bttv_init_card1(struct bttv *btv) | |||
2636 | case BTTV_AVDVBT_771: | 2651 | case BTTV_AVDVBT_771: |
2637 | btv->use_i2c_hw = 1; | 2652 | btv->use_i2c_hw = 1; |
2638 | break; | 2653 | break; |
2654 | case BTTV_ADLINK_RTV24: | ||
2655 | init_RTV24( btv ); | ||
2656 | break; | ||
2657 | |||
2639 | } | 2658 | } |
2640 | if (!bttv_tvcards[btv->c.type].has_dvb) | 2659 | if (!bttv_tvcards[btv->c.type].has_dvb) |
2641 | bttv_reset_audio(btv); | 2660 | bttv_reset_audio(btv); |
@@ -2784,6 +2803,8 @@ void __devinit bttv_init_card2(struct bttv *btv) | |||
2784 | } | 2803 | } |
2785 | btv->pll.pll_current = -1; | 2804 | btv->pll.pll_current = -1; |
2786 | 2805 | ||
2806 | bttv_reset_audio(btv); | ||
2807 | |||
2787 | /* tuner configuration (from card list / autodetect / insmod option) */ | 2808 | /* tuner configuration (from card list / autodetect / insmod option) */ |
2788 | if (UNSET != bttv_tvcards[btv->c.type].tuner_type) | 2809 | if (UNSET != bttv_tvcards[btv->c.type].tuner_type) |
2789 | if(UNSET == btv->tuner_type) | 2810 | if(UNSET == btv->tuner_type) |
@@ -3304,6 +3325,83 @@ static void __devinit init_PXC200(struct bttv *btv) | |||
3304 | } | 3325 | } |
3305 | 3326 | ||
3306 | 3327 | ||
3328 | |||
3329 | /* ----------------------------------------------------------------------- */ | ||
3330 | /* | ||
3331 | * The Adlink RTV-24 (aka Angelo) has some special initialisation to unlock | ||
3332 | * it. This apparently involves the following procedure for each 878 chip: | ||
3333 | * | ||
3334 | * 1) write 0x00C3FEFF to the GPIO_OUT_EN register | ||
3335 | * | ||
3336 | * 2) write to GPIO_DATA | ||
3337 | * - 0x0E | ||
3338 | * - sleep 1ms | ||
3339 | * - 0x10 + 0x0E | ||
3340 | * - sleep 10ms | ||
3341 | * - 0x0E | ||
3342 | * read from GPIO_DATA into buf (uint_32) | ||
3343 | * - if ( data>>18 & 0x01 != 0) || ( buf>>19 & 0x01 != 1 ) | ||
3344 | * error. ERROR_CPLD_Check_Failed stop. | ||
3345 | * | ||
3346 | * 3) write to GPIO_DATA | ||
3347 | * - write 0x4400 + 0x0E | ||
3348 | * - sleep 10ms | ||
3349 | * - write 0x4410 + 0x0E | ||
3350 | * - sleep 1ms | ||
3351 | * - write 0x0E | ||
3352 | * read from GPIO_DATA into buf (uint_32) | ||
3353 | * - if ( buf>>18 & 0x01 ) || ( buf>>19 && 0x01 != 0 ) | ||
3354 | * error. ERROR_CPLD_Check_Failed. | ||
3355 | */ | ||
3356 | /* ----------------------------------------------------------------------- */ | ||
3357 | void | ||
3358 | init_RTV24 (struct bttv *btv) | ||
3359 | { | ||
3360 | uint32_t dataRead = 0; | ||
3361 | long watchdog_value = 0x0E; | ||
3362 | |||
3363 | printk (KERN_INFO | ||
3364 | "bttv%d: Adlink RTV-24 initialisation in progress ...\n", | ||
3365 | btv->c.nr); | ||
3366 | |||
3367 | btwrite (0x00c3feff, BT848_GPIO_OUT_EN); | ||
3368 | |||
3369 | btwrite (0 + watchdog_value, BT848_GPIO_DATA); | ||
3370 | msleep (1); | ||
3371 | btwrite (0x10 + watchdog_value, BT848_GPIO_DATA); | ||
3372 | msleep (10); | ||
3373 | btwrite (0 + watchdog_value, BT848_GPIO_DATA); | ||
3374 | |||
3375 | dataRead = btread (BT848_GPIO_DATA); | ||
3376 | |||
3377 | if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) { | ||
3378 | printk (KERN_INFO | ||
3379 | "bttv%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n", | ||
3380 | btv->c.nr, dataRead); | ||
3381 | } | ||
3382 | |||
3383 | btwrite (0x4400 + watchdog_value, BT848_GPIO_DATA); | ||
3384 | msleep (10); | ||
3385 | btwrite (0x4410 + watchdog_value, BT848_GPIO_DATA); | ||
3386 | msleep (1); | ||
3387 | btwrite (watchdog_value, BT848_GPIO_DATA); | ||
3388 | msleep (1); | ||
3389 | dataRead = btread (BT848_GPIO_DATA); | ||
3390 | |||
3391 | if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) { | ||
3392 | printk (KERN_INFO | ||
3393 | "bttv%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n", | ||
3394 | btv->c.nr, dataRead); | ||
3395 | |||
3396 | return; | ||
3397 | } | ||
3398 | |||
3399 | printk (KERN_INFO | ||
3400 | "bttv%d: Adlink RTV-24 initialisation complete.\n", btv->c.nr); | ||
3401 | } | ||
3402 | |||
3403 | |||
3404 | |||
3307 | /* ----------------------------------------------------------------------- */ | 3405 | /* ----------------------------------------------------------------------- */ |
3308 | /* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */ | 3406 | /* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */ |
3309 | /* | 3407 | /* |
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 033cc5498f..290289a997 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | $Id: bttv-driver.c,v 1.37 2005/02/21 13:57:59 kraxel Exp $ | 2 | $Id: bttv-driver.c,v 1.38 2005/06/10 17:20:24 mchehab Exp $ |
3 | 3 | ||
4 | bttv - Bt848 frame grabber driver | 4 | bttv - Bt848 frame grabber driver |
5 | 5 | ||
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index c2368bc832..da448a5f9e 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | $Id: bttv-i2c.c,v 1.18 2005/02/16 12:14:10 kraxel Exp $ | 2 | $Id: bttv-i2c.c,v 1.21 2005/06/10 17:20:24 mchehab Exp $ |
3 | 3 | ||
4 | bttv-i2c.c -- all the i2c code is here | 4 | bttv-i2c.c -- all the i2c code is here |
5 | 5 | ||
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 8322b66e09..191eaf1714 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: bttv.h,v 1.17 2005/02/22 14:06:32 kraxel Exp $ | 2 | * $Id: bttv.h,v 1.18 2005/05/24 23:41:42 nsh Exp $ |
3 | * | 3 | * |
4 | * bttv - Bt848 frame grabber driver | 4 | * bttv - Bt848 frame grabber driver |
5 | * | 5 | * |
@@ -135,6 +135,7 @@ | |||
135 | #define BTTV_DVICO_DVBT_LITE 0x80 | 135 | #define BTTV_DVICO_DVBT_LITE 0x80 |
136 | #define BTTV_TIBET_CS16 0x83 | 136 | #define BTTV_TIBET_CS16 0x83 |
137 | #define BTTV_KODICOM_4400R 0x84 | 137 | #define BTTV_KODICOM_4400R 0x84 |
138 | #define BTTV_ADLINK_RTV24 0x85 | ||
138 | 139 | ||
139 | /* i2c address list */ | 140 | /* i2c address list */ |
140 | #define I2C_TSA5522 0xc2 | 141 | #define I2C_TSA5522 0xc2 |
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index 1a9ba7e1cf..7b6f1e8560 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h | |||
@@ -226,10 +226,6 @@ extern int fini_bttv_i2c(struct bttv *btv); | |||
226 | #define dprintk if (bttv_debug >= 1) printk | 226 | #define dprintk if (bttv_debug >= 1) printk |
227 | #define d2printk if (bttv_debug >= 2) printk | 227 | #define d2printk if (bttv_debug >= 2) printk |
228 | 228 | ||
229 | /* our devices */ | ||
230 | #define BTTV_MAX 16 | ||
231 | extern unsigned int bttv_num; | ||
232 | |||
233 | #define BTTV_MAX_FBUF 0x208000 | 229 | #define BTTV_MAX_FBUF 0x208000 |
234 | #define VBIBUF_SIZE (2048*VBI_MAXLINES*2) | 230 | #define VBIBUF_SIZE (2048*VBI_MAXLINES*2) |
235 | #define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ | 231 | #define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ |
@@ -375,6 +371,10 @@ struct bttv { | |||
375 | unsigned int users; | 371 | unsigned int users; |
376 | struct bttv_fh init; | 372 | struct bttv_fh init; |
377 | }; | 373 | }; |
374 | |||
375 | /* our devices */ | ||
376 | #define BTTV_MAX 16 | ||
377 | extern unsigned int bttv_num; | ||
378 | extern struct bttv bttvs[BTTV_MAX]; | 378 | extern struct bttv bttvs[BTTV_MAX]; |
379 | 379 | ||
380 | /* private ioctls */ | 380 | /* private ioctls */ |
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 46d6778b86..91f8afeded 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: cx88-blackbird.c,v 1.26 2005/03/07 15:58:05 kraxel Exp $ | 2 | * $Id: cx88-blackbird.c,v 1.27 2005/06/03 13:31:50 mchehab Exp $ |
3 | * | 3 | * |
4 | * Support for a cx23416 mpeg encoder via cx2388x host port. | 4 | * Support for a cx23416 mpeg encoder via cx2388x host port. |
5 | * "blackbird" reference design. | 5 | * "blackbird" reference design. |
@@ -61,37 +61,304 @@ static LIST_HEAD(cx8802_devlist); | |||
61 | 61 | ||
62 | #define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF | 62 | #define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF |
63 | 63 | ||
64 | /*Firmware API commands*/ | 64 | /* Firmware API commands */ |
65 | #define IVTV_API_ENC_PING_FW 0x00000080 | 65 | /* #define IVTV_API_STD_TIMEOUT 0x00010000 // 65536, units?? */ |
66 | #define IVTV_API_ENC_GETVER 0x000000C4 | 66 | #define IVTV_API_STD_TIMEOUT 500 |
67 | #define IVTV_API_ENC_HALT_FW 0x000000C3 | 67 | |
68 | #define IVTV_API_STD_TIMEOUT 0x00010000 /*units??*/ | 68 | #define BLACKBIRD_API_PING 0x80 |
69 | //#define IVTV_API_ASSIGN_PGM_INDEX_INFO 0x000000c7 | 69 | #define BLACKBIRD_API_BEGIN_CAPTURE 0x81 |
70 | #define IVTV_API_ASSIGN_STREAM_TYPE 0x000000b9 | 70 | enum blackbird_capture_type { |
71 | #define IVTV_API_ASSIGN_OUTPUT_PORT 0x000000bb | 71 | BLACKBIRD_MPEG_CAPTURE, |
72 | #define IVTV_API_ASSIGN_FRAMERATE 0x0000008f | 72 | BLACKBIRD_RAW_CAPTURE, |
73 | #define IVTV_API_ASSIGN_FRAME_SIZE 0x00000091 | 73 | BLACKBIRD_RAW_PASSTHRU_CAPTURE |
74 | #define IVTV_API_ASSIGN_ASPECT_RATIO 0x00000099 | 74 | }; |
75 | #define IVTV_API_ASSIGN_BITRATES 0x00000095 | 75 | enum blackbird_capture_bits { |
76 | #define IVTV_API_ASSIGN_GOP_PROPERTIES 0x00000097 | 76 | BLACKBIRD_RAW_BITS_NONE = 0x00, |
77 | #define IVTV_API_ASSIGN_3_2_PULLDOWN 0x000000b1 | 77 | BLACKBIRD_RAW_BITS_YUV_CAPTURE = 0x01, |
78 | #define IVTV_API_ASSIGN_GOP_CLOSURE 0x000000c5 | 78 | BLACKBIRD_RAW_BITS_PCM_CAPTURE = 0x02, |
79 | #define IVTV_API_ASSIGN_AUDIO_PROPERTIES 0x000000bd | 79 | BLACKBIRD_RAW_BITS_VBI_CAPTURE = 0x04, |
80 | #define IVTV_API_ASSIGN_DNR_FILTER_MODE 0x0000009b | 80 | BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08, |
81 | #define IVTV_API_ASSIGN_DNR_FILTER_PROPS 0x0000009d | 81 | BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE = 0x10 |
82 | #define IVTV_API_ASSIGN_CORING_LEVELS 0x0000009f | 82 | }; |
83 | #define IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE 0x000000a1 | 83 | #define BLACKBIRD_API_END_CAPTURE 0x82 |
84 | #define IVTV_API_ASSIGN_FRAME_DROP_RATE 0x000000d0 | 84 | enum blackbird_capture_end { |
85 | #define IVTV_API_ASSIGN_PLACEHOLDER 0x000000d8 | 85 | BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */ |
86 | #define IVTV_API_MUTE_VIDEO 0x000000d9 | 86 | BLACKBIRD_END_NOW, /* stop immediately, no irq */ |
87 | #define IVTV_API_MUTE_AUDIO 0x000000da | 87 | }; |
88 | #define IVTV_API_INITIALIZE_INPUT 0x000000cd | 88 | #define BLACKBIRD_API_SET_AUDIO_ID 0x89 |
89 | #define IVTV_API_REFRESH_INPUT 0x000000d3 | 89 | #define BLACKBIRD_API_SET_VIDEO_ID 0x8B |
90 | #define IVTV_API_ASSIGN_NUM_VSYNC_LINES 0x000000d6 | 90 | #define BLACKBIRD_API_SET_PCR_ID 0x8D |
91 | #define IVTV_API_BEGIN_CAPTURE 0x00000081 | 91 | #define BLACKBIRD_API_SET_FRAMERATE 0x8F |
92 | //#define IVTV_API_PAUSE_ENCODER 0x000000d2 | 92 | enum blackbird_framerate { |
93 | //#define IVTV_API_EVENT_NOTIFICATION 0x000000d5 | 93 | BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */ |
94 | #define IVTV_API_END_CAPTURE 0x00000082 | 94 | BLACKBIRD_FRAMERATE_PAL_25 /* PAL: 25fps */ |
95 | }; | ||
96 | #define BLACKBIRD_API_SET_RESOLUTION 0x91 | ||
97 | #define BLACKBIRD_API_SET_VIDEO_BITRATE 0x95 | ||
98 | enum blackbird_video_bitrate_type { | ||
99 | BLACKBIRD_VIDEO_VBR, | ||
100 | BLACKBIRD_VIDEO_CBR | ||
101 | }; | ||
102 | #define BLACKBIRD_PEAK_RATE_DIVISOR 400 | ||
103 | enum blackbird_mux_rate { | ||
104 | BLACKBIRD_MUX_RATE_DEFAULT, | ||
105 | /* dvd mux rate: multiply by 400 to get the actual rate */ | ||
106 | BLACKBIRD_MUX_RATE_DVD = 25200 | ||
107 | }; | ||
108 | #define BLACKBIRD_API_SET_GOP_STRUCTURE 0x97 | ||
109 | #define BLACKBIRD_API_SET_ASPECT_RATIO 0x99 | ||
110 | enum blackbird_aspect_ratio { | ||
111 | BLACKBIRD_ASPECT_RATIO_FORBIDDEN, | ||
112 | BLACKBIRD_ASPECT_RATIO_1_1_SQUARE, | ||
113 | BLACKBIRD_ASPECT_RATIO_4_3, | ||
114 | BLACKBIRD_ASPECT_RATIO_16_9, | ||
115 | BLACKBIRD_ASPECT_RATIO_221_100, | ||
116 | BLACKBIRD_ASPECT_RATIO_RESERVED | ||
117 | }; | ||
118 | #define BLACKBIRD_API_SET_DNR_MODE 0x9B | ||
119 | enum blackbird_dnr_bits { | ||
120 | BLACKBIRD_DNR_BITS_MANUAL, | ||
121 | BLACKBIRD_DNR_BITS_AUTO_SPATIAL, | ||
122 | BLACKBIRD_DNR_BITS_AUTO_TEMPORAL, | ||
123 | BLACKBIRD_DNR_BITS_AUTO | ||
124 | }; | ||
125 | enum blackbird_median_filter { | ||
126 | BLACKBIRD_MEDIAN_FILTER_DISABLED, | ||
127 | BLACKBIRD_MEDIAN_FILTER_HORIZONTAL, | ||
128 | BLACKBIRD_MEDIAN_FILTER_VERTICAL, | ||
129 | BLACKBIRD_MEDIAN_FILTER_HV, | ||
130 | BLACKBIRD_MEDIAN_FILTER_DIAGONAL | ||
131 | }; | ||
132 | #define BLACKBIRD_API_SET_MANUAL_DNR 0x9D | ||
133 | #define BLACKBIRD_API_SET_DNR_MEDIAN 0x9F | ||
134 | #define BLACKBIRD_API_SET_SPATIAL_FILTER 0xA1 | ||
135 | enum blackbird_spatial_filter_luma { | ||
136 | BLACKBIRD_SPATIAL_FILTER_LUMA_DISABLED, | ||
137 | BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ, | ||
138 | BLACKBIRD_SPATIAL_FILTER_LUMA_1D_VERT, | ||
139 | BLACKBIRD_SPATIAL_FILTER_LUMA_2D_HV, /* separable, default */ | ||
140 | BLACKBIRD_SPATIAL_FILTER_LUMA_2D_SYMM /* symmetric non-separable */ | ||
141 | }; | ||
142 | enum blackbird_spatial_filter_chroma { | ||
143 | BLACKBIRD_SPATIAL_FILTER_CHROMA_DISABLED, | ||
144 | BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ /* default */ | ||
145 | }; | ||
146 | #define BLACKBIRD_API_SET_3_2_PULLDOWN 0xB1 | ||
147 | enum blackbird_pulldown { | ||
148 | BLACKBIRD_3_2_PULLDOWN_DISABLED, | ||
149 | BLACKBIRD_3_2_PULLDOWN_ENABLED | ||
150 | }; | ||
151 | #define BLACKBIRD_API_SET_VBI_LINE_NO 0xB7 | ||
152 | enum blackbird_vbi_line_bits { | ||
153 | BLACKBIRD_VBI_LINE_BITS_TOP_FIELD, | ||
154 | BLACKBIRD_VBI_LINE_BITS_BOT_FIELD = (1 << 31), | ||
155 | BLACKBIRD_VBI_LINE_BITS_ALL_LINES = 0xFFFFFFFF | ||
156 | }; | ||
157 | enum blackbird_vbi_line { | ||
158 | BLACKBIRD_VBI_LINE_DISABLED, | ||
159 | BLACKBIRD_VBI_LINE_ENABLED | ||
160 | }; | ||
161 | enum blackbird_vbi_slicing { | ||
162 | BLACKBIRD_VBI_SLICING_NONE, | ||
163 | BLACKBIRD_VBI_SLICING_CLOSED_CAPTION | ||
164 | }; | ||
165 | #define BLACKBIRD_API_SET_STREAM_TYPE 0xB9 | ||
166 | enum blackbird_stream_type { | ||
167 | BLACKBIRD_STREAM_PROGRAM, | ||
168 | BLACKBIRD_STREAM_TRANSPORT, | ||
169 | BLACKBIRD_STREAM_MPEG1, | ||
170 | BLACKBIRD_STREAM_PES_AV, | ||
171 | BLACKBIRD_STREAM_UNKNOWN4, | ||
172 | BLACKBIRD_STREAM_PES_VIDEO, | ||
173 | BLACKBIRD_STREAM_UNKNOWN6, | ||
174 | BLACKBIRD_STREAM_PES_AUDIO, | ||
175 | BLACKBIRD_STREAM_UNKNOWN8, | ||
176 | BLACKBIRD_STREAM_UNKNOWN9, /* audio/pcm ? */ | ||
177 | BLACKBIRD_STREAM_DVD, | ||
178 | BLACKBIRD_STREAM_VCD, | ||
179 | BLACKBIRD_STREAM_UNKNOWN12 /* svcd/xvcd ? */ | ||
180 | }; | ||
181 | #define BLACKBIRD_API_SET_OUTPUT_PORT 0xBB | ||
182 | enum blackbird_stream_port { | ||
183 | BLACKBIRD_OUTPUT_PORT_MEMORY, | ||
184 | BLACKBIRD_OUTPUT_PORT_STREAMING, | ||
185 | BLACKBIRD_OUTPUT_PORT_SERIAL | ||
186 | }; | ||
187 | #define BLACKBIRD_API_SET_AUDIO_PARAMS 0xBD | ||
188 | enum blackbird_audio_bits_sample_rate { | ||
189 | BLACKBIRD_AUDIO_BITS_44100HZ, | ||
190 | BLACKBIRD_AUDIO_BITS_48000HZ, | ||
191 | BLACKBIRD_AUDIO_BITS_32000HZ, | ||
192 | BLACKBIRD_AUDIO_BITS_RESERVED_HZ, | ||
193 | }; | ||
194 | enum blackbird_audio_bits_encoding { | ||
195 | BLACKBIRD_AUDIO_BITS_LAYER_1 = 0x1 << 2, | ||
196 | BLACKBIRD_AUDIO_BITS_LAYER_2 = 0x2 << 2, | ||
197 | }; | ||
198 | enum blackbird_audio_bits_bitrate_layer_1 { | ||
199 | BLACKBIRD_AUDIO_BITS_LAYER_1_FREE_FORMAT, | ||
200 | BLACKBIRD_AUDIO_BITS_LAYER_1_32 = 0x01 << 4, | ||
201 | BLACKBIRD_AUDIO_BITS_LAYER_1_64 = 0x02 << 4, | ||
202 | BLACKBIRD_AUDIO_BITS_LAYER_1_96 = 0x03 << 4, | ||
203 | BLACKBIRD_AUDIO_BITS_LAYER_1_128 = 0x04 << 4, | ||
204 | BLACKBIRD_AUDIO_BITS_LAYER_1_160 = 0x05 << 4, | ||
205 | BLACKBIRD_AUDIO_BITS_LAYER_1_192 = 0x06 << 4, | ||
206 | BLACKBIRD_AUDIO_BITS_LAYER_1_224 = 0x07 << 4, | ||
207 | BLACKBIRD_AUDIO_BITS_LAYER_1_256 = 0x08 << 4, | ||
208 | BLACKBIRD_AUDIO_BITS_LAYER_1_288 = 0x09 << 4, | ||
209 | BLACKBIRD_AUDIO_BITS_LAYER_1_320 = 0x0A << 4, | ||
210 | BLACKBIRD_AUDIO_BITS_LAYER_1_352 = 0x0B << 4, | ||
211 | BLACKBIRD_AUDIO_BITS_LAYER_1_384 = 0x0C << 4, | ||
212 | BLACKBIRD_AUDIO_BITS_LAYER_1_416 = 0x0D << 4, | ||
213 | BLACKBIRD_AUDIO_BITS_LAYER_1_448 = 0x0E << 4, | ||
214 | }; | ||
215 | enum blackbird_audio_bits_bitrate_layer_2 { | ||
216 | BLACKBIRD_AUDIO_BITS_LAYER_2_FREE_FORMAT, | ||
217 | BLACKBIRD_AUDIO_BITS_LAYER_2_32 = 0x01 << 4, | ||
218 | BLACKBIRD_AUDIO_BITS_LAYER_2_48 = 0x02 << 4, | ||
219 | BLACKBIRD_AUDIO_BITS_LAYER_2_56 = 0x03 << 4, | ||
220 | BLACKBIRD_AUDIO_BITS_LAYER_2_64 = 0x04 << 4, | ||
221 | BLACKBIRD_AUDIO_BITS_LAYER_2_80 = 0x05 << 4, | ||
222 | BLACKBIRD_AUDIO_BITS_LAYER_2_96 = 0x06 << 4, | ||
223 | BLACKBIRD_AUDIO_BITS_LAYER_2_112 = 0x07 << 4, | ||
224 | BLACKBIRD_AUDIO_BITS_LAYER_2_128 = 0x08 << 4, | ||
225 | BLACKBIRD_AUDIO_BITS_LAYER_2_160 = 0x09 << 4, | ||
226 | BLACKBIRD_AUDIO_BITS_LAYER_2_192 = 0x0A << 4, | ||
227 | BLACKBIRD_AUDIO_BITS_LAYER_2_224 = 0x0B << 4, | ||
228 | BLACKBIRD_AUDIO_BITS_LAYER_2_256 = 0x0C << 4, | ||
229 | BLACKBIRD_AUDIO_BITS_LAYER_2_320 = 0x0D << 4, | ||
230 | BLACKBIRD_AUDIO_BITS_LAYER_2_384 = 0x0E << 4, | ||
231 | }; | ||
232 | enum blackbird_audio_bits_mode { | ||
233 | BLACKBIRD_AUDIO_BITS_STEREO, | ||
234 | BLACKBIRD_AUDIO_BITS_JOINT_STEREO = 0x1 << 8, | ||
235 | BLACKBIRD_AUDIO_BITS_DUAL = 0x2 << 8, | ||
236 | BLACKBIRD_AUDIO_BITS_MONO = 0x3 << 8, | ||
237 | }; | ||
238 | enum blackbird_audio_bits_mode_extension { | ||
239 | BLACKBIRD_AUDIO_BITS_BOUND_4, | ||
240 | BLACKBIRD_AUDIO_BITS_BOUND_8 = 0x1 << 10, | ||
241 | BLACKBIRD_AUDIO_BITS_BOUND_12 = 0x2 << 10, | ||
242 | BLACKBIRD_AUDIO_BITS_BOUND_16 = 0x3 << 10, | ||
243 | }; | ||
244 | enum blackbird_audio_bits_emphasis { | ||
245 | BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE, | ||
246 | BLACKBIRD_AUDIO_BITS_EMPHASIS_50_15 = 0x1 << 12, | ||
247 | BLACKBIRD_AUDIO_BITS_EMPHASIS_RESERVED = 0x2 << 12, | ||
248 | BLACKBIRD_AUDIO_BITS_EMPHASIS_CCITT_J17 = 0x3 << 12, | ||
249 | }; | ||
250 | enum blackbird_audio_bits_crc { | ||
251 | BLACKBIRD_AUDIO_BITS_CRC_OFF, | ||
252 | BLACKBIRD_AUDIO_BITS_CRC_ON = 0x1 << 14, | ||
253 | }; | ||
254 | enum blackbird_audio_bits_copyright { | ||
255 | BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF, | ||
256 | BLACKBIRD_AUDIO_BITS_COPYRIGHT_ON = 0x1 << 15, | ||
257 | }; | ||
258 | enum blackbird_audio_bits_original { | ||
259 | BLACKBIRD_AUDIO_BITS_COPY, | ||
260 | BLACKBIRD_AUDIO_BITS_ORIGINAL = 0x1 << 16, | ||
261 | }; | ||
262 | #define BLACKBIRD_API_HALT 0xC3 | ||
263 | #define BLACKBIRD_API_GET_VERSION 0xC4 | ||
264 | #define BLACKBIRD_API_SET_GOP_CLOSURE 0xC5 | ||
265 | enum blackbird_gop_closure { | ||
266 | BLACKBIRD_GOP_CLOSURE_OFF, | ||
267 | BLACKBIRD_GOP_CLOSURE_ON, | ||
268 | }; | ||
269 | #define BLACKBIRD_API_DATA_XFER_STATUS 0xC6 | ||
270 | enum blackbird_data_xfer_status { | ||
271 | BLACKBIRD_MORE_BUFFERS_FOLLOW, | ||
272 | BLACKBIRD_LAST_BUFFER, | ||
273 | }; | ||
274 | #define BLACKBIRD_API_PROGRAM_INDEX_INFO 0xC7 | ||
275 | enum blackbird_picture_mask { | ||
276 | BLACKBIRD_PICTURE_MASK_NONE, | ||
277 | BLACKBIRD_PICTURE_MASK_I_FRAMES, | ||
278 | BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3, | ||
279 | BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7, | ||
280 | }; | ||
281 | #define BLACKBIRD_API_SET_VBI_PARAMS 0xC8 | ||
282 | enum blackbird_vbi_mode_bits { | ||
283 | BLACKBIRD_VBI_BITS_SLICED, | ||
284 | BLACKBIRD_VBI_BITS_RAW, | ||
285 | }; | ||
286 | enum blackbird_vbi_insertion_bits { | ||
287 | BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA, | ||
288 | BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1, | ||
289 | BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1, | ||
290 | BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1, | ||
291 | BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1, | ||
292 | }; | ||
293 | #define BLACKBIRD_API_SET_DMA_BLOCK_SIZE 0xC9 | ||
294 | enum blackbird_dma_unit { | ||
295 | BLACKBIRD_DMA_BYTES, | ||
296 | BLACKBIRD_DMA_FRAMES, | ||
297 | }; | ||
298 | #define BLACKBIRD_API_DMA_TRANSFER_INFO 0xCA | ||
299 | #define BLACKBIRD_API_DMA_TRANSFER_STAT 0xCB | ||
300 | enum blackbird_dma_transfer_status_bits { | ||
301 | BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01, | ||
302 | BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04, | ||
303 | BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10, | ||
304 | }; | ||
305 | #define BLACKBIRD_API_SET_DMA2HOST_ADDR 0xCC | ||
306 | #define BLACKBIRD_API_INIT_VIDEO_INPUT 0xCD | ||
307 | #define BLACKBIRD_API_SET_FRAMESKIP 0xD0 | ||
308 | #define BLACKBIRD_API_PAUSE 0xD2 | ||
309 | enum blackbird_pause { | ||
310 | BLACKBIRD_PAUSE_ENCODING, | ||
311 | BLACKBIRD_RESUME_ENCODING, | ||
312 | }; | ||
313 | #define BLACKBIRD_API_REFRESH_INPUT 0xD3 | ||
314 | #define BLACKBIRD_API_SET_COPYRIGHT 0xD4 | ||
315 | enum blackbird_copyright { | ||
316 | BLACKBIRD_COPYRIGHT_OFF, | ||
317 | BLACKBIRD_COPYRIGHT_ON, | ||
318 | }; | ||
319 | #define BLACKBIRD_API_SET_NOTIFICATION 0xD5 | ||
320 | enum blackbird_notification_type { | ||
321 | BLACKBIRD_NOTIFICATION_REFRESH, | ||
322 | }; | ||
323 | enum blackbird_notification_status { | ||
324 | BLACKBIRD_NOTIFICATION_OFF, | ||
325 | BLACKBIRD_NOTIFICATION_ON, | ||
326 | }; | ||
327 | enum blackbird_notification_mailbox { | ||
328 | BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1, | ||
329 | }; | ||
330 | #define BLACKBIRD_API_SET_CAPTURE_LINES 0xD6 | ||
331 | enum blackbird_field1_lines { | ||
332 | BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */ | ||
333 | BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */ | ||
334 | BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */ | ||
335 | }; | ||
336 | enum blackbird_field2_lines { | ||
337 | BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */ | ||
338 | BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */ | ||
339 | BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */ | ||
340 | }; | ||
341 | #define BLACKBIRD_API_SET_CUSTOM_DATA 0xD7 | ||
342 | enum blackbird_custom_data_type { | ||
343 | BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, | ||
344 | BLACKBIRD_CUSTOM_PRIVATE_PACKET, | ||
345 | }; | ||
346 | #define BLACKBIRD_API_MUTE_VIDEO 0xD9 | ||
347 | enum blackbird_mute { | ||
348 | BLACKBIRD_UNMUTE, | ||
349 | BLACKBIRD_MUTE, | ||
350 | }; | ||
351 | enum blackbird_mute_video_mask { | ||
352 | BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00, | ||
353 | BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000, | ||
354 | BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000, | ||
355 | }; | ||
356 | enum blackbird_mute_video_shift { | ||
357 | BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8, | ||
358 | BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16, | ||
359 | BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24, | ||
360 | }; | ||
361 | #define BLACKBIRD_API_MUTE_AUDIO 0xDA | ||
95 | 362 | ||
96 | /* Registers */ | 363 | /* Registers */ |
97 | #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/) | 364 | #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/) |
@@ -405,68 +672,100 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) | |||
405 | return 0; | 672 | return 0; |
406 | } | 673 | } |
407 | 674 | ||
675 | /** | ||
676 | Settings used by the windows tv app for PVR2000: | ||
677 | ================================================================================================================= | ||
678 | Profile | Codec | Resolution | CBR/VBR | Video Qlty | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode | ||
679 | ----------------------------------------------------------------------------------------------------------------- | ||
680 | MPEG-1 | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 2000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo | ||
681 | MPEG-2 | MPEG2 | 720x576PAL | VBR | 600 :Good | 4000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo | ||
682 | VCD | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 1150 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo | ||
683 | DVD | MPEG2 | 720x576PAL | VBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo | ||
684 | DB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo | ||
685 | ================================================================================================================= | ||
686 | *DB: "DirectBurn" | ||
687 | */ | ||
408 | static void blackbird_codec_settings(struct cx8802_dev *dev) | 688 | static void blackbird_codec_settings(struct cx8802_dev *dev) |
409 | { | 689 | { |
410 | int bitrate_mode = 1; | 690 | int bitrate_mode = 1; |
411 | int bitrate = 7500000; | 691 | int bitrate = 7500000; |
412 | int bitrate_peak = 7500000; | 692 | int bitrate_peak = 7500000; |
693 | #if 1 | ||
694 | bitrate_mode = BLACKBIRD_VIDEO_CBR; | ||
695 | bitrate = 4000*1024; | ||
696 | bitrate_peak = 4000*1024; | ||
697 | #endif | ||
413 | 698 | ||
414 | /* assign stream type */ | 699 | /* assign stream type */ |
415 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 0); /* program stream */ | 700 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_PROGRAM); |
416 | //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 2); /* MPEG1 stream */ | 701 | /* blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_TRANSPORT); */ |
417 | //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 3); /* PES A/V */ | ||
418 | //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 10); /* DVD stream */ | ||
419 | 702 | ||
420 | /* assign output port */ | 703 | /* assign output port */ |
421 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_OUTPUT_PORT, 1, 0, 1); /* 1 = Host */ | 704 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */ |
422 | 705 | ||
423 | /* assign framerate */ | 706 | /* assign framerate */ |
424 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAMERATE, 1, 0, 0); | 707 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25); |
425 | 708 | ||
426 | /* assign frame size */ | 709 | /* assign frame size */ |
427 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0, | 710 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_RESOLUTION, 2, 0, |
428 | dev->height, dev->width); | 711 | dev->height, dev->width); |
429 | 712 | ||
430 | /* assign aspect ratio */ | 713 | /* assign aspect ratio */ |
431 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_ASPECT_RATIO, 1, 0, 2); | 714 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, BLACKBIRD_ASPECT_RATIO_4_3); |
432 | 715 | ||
433 | /* assign bitrates */ | 716 | /* assign bitrates */ |
434 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_BITRATES, 5, 0, | 717 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 5, 0, |
435 | bitrate_mode, /* mode */ | 718 | bitrate_mode, /* mode */ |
436 | bitrate, /* bps */ | 719 | bitrate, /* bps */ |
437 | bitrate_peak / 400, /* peak/400 */ | 720 | bitrate_peak / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */ |
438 | 0, 0x70); /* encoding buffer, ckennedy */ | 721 | BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */ |
439 | 722 | ||
440 | /* assign gop properties */ | 723 | /* assign gop properties */ |
441 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 15, 3); | 724 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, 15, 3); |
442 | //blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 2, 1); | 725 | |
443 | 726 | /* assign 3 2 pulldown */ | |
444 | /* assign 3 2 pulldown */ | 727 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, BLACKBIRD_3_2_PULLDOWN_DISABLED); |
445 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_3_2_PULLDOWN, 1, 0, 0); | 728 | |
446 | 729 | /* assign audio properties */ | |
447 | /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ | 730 | /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ |
448 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4)); | 731 | /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4)); |
732 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4)); */ | ||
733 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, | ||
734 | BLACKBIRD_AUDIO_BITS_44100HZ | | ||
735 | BLACKBIRD_AUDIO_BITS_LAYER_2 | | ||
736 | BLACKBIRD_AUDIO_BITS_LAYER_2_224 | | ||
737 | BLACKBIRD_AUDIO_BITS_STEREO | | ||
738 | /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */ | ||
739 | BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE | | ||
740 | BLACKBIRD_AUDIO_BITS_CRC_OFF | | ||
741 | BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF | | ||
742 | BLACKBIRD_AUDIO_BITS_COPY | ||
743 | ); | ||
449 | 744 | ||
450 | /* assign gop closure */ | 745 | /* assign gop closure */ |
451 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_CLOSURE, 1, 0, 0); | 746 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, BLACKBIRD_GOP_CLOSURE_OFF); |
452 | 747 | ||
453 | /* assign audio properties */ | ||
454 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4)); | ||
455 | 748 | ||
456 | /* assign dnr filter mode */ | 749 | /* assign dnr filter mode */ |
457 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_MODE, 2, 0, 0, 0); | 750 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0, |
751 | BLACKBIRD_DNR_BITS_MANUAL, | ||
752 | BLACKBIRD_MEDIAN_FILTER_DISABLED | ||
753 | ); | ||
458 | 754 | ||
459 | /* assign dnr filter props*/ | 755 | /* assign dnr filter props*/ |
460 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_PROPS, 2, 0, 0, 0); | 756 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, 0, 0); |
461 | 757 | ||
462 | /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */ | 758 | /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */ |
463 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_CORING_LEVELS, 4, 0, 0, 255, 0, 255); | 759 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MEDIAN, 4, 0, 0, 255, 0, 255); |
464 | 760 | ||
465 | /* assign spatial filter type: luma_t: 1 = horiz_only, chroma_t: 1 = horiz_only */ | 761 | /* assign spatial filter type: luma_t: horiz_only, chroma_t: horiz_only */ |
466 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE, 2, 0, 1, 1); | 762 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_SPATIAL_FILTER, 2, 0, |
763 | BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ, | ||
764 | BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ | ||
765 | ); | ||
467 | 766 | ||
468 | /* assign frame drop rate */ | 767 | /* assign frame drop rate */ |
469 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); | 768 | /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); */ |
470 | } | 769 | } |
471 | 770 | ||
472 | static int blackbird_initialize_codec(struct cx8802_dev *dev) | 771 | static int blackbird_initialize_codec(struct cx8802_dev *dev) |
@@ -476,7 +775,7 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) | |||
476 | int retval; | 775 | int retval; |
477 | 776 | ||
478 | dprintk(1,"Initialize codec\n"); | 777 | dprintk(1,"Initialize codec\n"); |
479 | retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */ | 778 | retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */ |
480 | if (retval < 0) { | 779 | if (retval < 0) { |
481 | /* ping was not successful, reset and upload firmware */ | 780 | /* ping was not successful, reset and upload firmware */ |
482 | cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ | 781 | cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ |
@@ -491,13 +790,13 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) | |||
491 | if (dev->mailbox < 0) | 790 | if (dev->mailbox < 0) |
492 | return -1; | 791 | return -1; |
493 | 792 | ||
494 | retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */ | 793 | retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */ |
495 | if (retval < 0) { | 794 | if (retval < 0) { |
496 | dprintk(0, "ERROR: Firmware ping failed!\n"); | 795 | dprintk(0, "ERROR: Firmware ping failed!\n"); |
497 | return -1; | 796 | return -1; |
498 | } | 797 | } |
499 | 798 | ||
500 | retval = blackbird_api_cmd(dev, IVTV_API_ENC_GETVER, 0, 1, &version); | 799 | retval = blackbird_api_cmd(dev, BLACKBIRD_API_GET_VERSION, 0, 1, &version); |
501 | if (retval < 0) { | 800 | if (retval < 0) { |
502 | dprintk(0, "ERROR: Firmware get encoder version failed!\n"); | 801 | dprintk(0, "ERROR: Firmware get encoder version failed!\n"); |
503 | return -1; | 802 | return -1; |
@@ -517,25 +816,36 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) | |||
517 | blackbird_codec_settings(dev); | 816 | blackbird_codec_settings(dev); |
518 | msleep(1); | 817 | msleep(1); |
519 | 818 | ||
520 | //blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef); | 819 | /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef); |
521 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0); | 820 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0); |
522 | //blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); | 821 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */ |
523 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | 822 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_CAPTURE_LINES, 2, 0, |
823 | BLACKBIRD_FIELD1_SAA7115, | ||
824 | BLACKBIRD_FIELD1_SAA7115 | ||
825 | ); | ||
826 | |||
827 | /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */ | ||
828 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_CUSTOM_DATA, 12, 0, | ||
829 | BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, | ||
830 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | ||
524 | 831 | ||
525 | blackbird_api_cmd(dev, IVTV_API_INITIALIZE_INPUT, 0, 0); /* initialize the video input */ | 832 | blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0); /* initialize the video input */ |
526 | 833 | ||
527 | msleep(1); | 834 | msleep(1); |
528 | 835 | ||
529 | blackbird_api_cmd(dev, IVTV_API_MUTE_VIDEO, 1, 0, 0); | 836 | blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE); |
530 | msleep(1); | 837 | msleep(1); |
531 | blackbird_api_cmd(dev, IVTV_API_MUTE_AUDIO, 1, 0, 0); | 838 | blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE); |
532 | msleep(1); | 839 | msleep(1); |
533 | 840 | ||
534 | blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); /* start capturing to the host interface */ | 841 | /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); // start capturing to the host interface */ |
535 | //blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0); /* start capturing to the host interface */ | 842 | blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, |
536 | msleep(1); | 843 | BLACKBIRD_MPEG_CAPTURE, |
844 | BLACKBIRD_RAW_BITS_NONE | ||
845 | ); /* start capturing to the host interface */ | ||
846 | msleep(10); | ||
537 | 847 | ||
538 | blackbird_api_cmd(dev, IVTV_API_REFRESH_INPUT, 0,0); | 848 | blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0); |
539 | return 0; | 849 | return 0; |
540 | } | 850 | } |
541 | 851 | ||
@@ -709,7 +1019,12 @@ static int mpeg_release(struct inode *inode, struct file *file) | |||
709 | { | 1019 | { |
710 | struct cx8802_fh *fh = file->private_data; | 1020 | struct cx8802_fh *fh = file->private_data; |
711 | 1021 | ||
712 | blackbird_api_cmd(fh->dev, IVTV_API_END_CAPTURE, 3, 0, 1, 0, 0x13); | 1022 | /* blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ |
1023 | blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0, | ||
1024 | BLACKBIRD_END_NOW, | ||
1025 | BLACKBIRD_MPEG_CAPTURE, | ||
1026 | BLACKBIRD_RAW_BITS_NONE | ||
1027 | ); | ||
713 | 1028 | ||
714 | /* stop mpeg capture */ | 1029 | /* stop mpeg capture */ |
715 | if (fh->mpegq.streaming) | 1030 | if (fh->mpegq.streaming) |
@@ -908,4 +1223,5 @@ module_exit(blackbird_fini); | |||
908 | * Local variables: | 1223 | * Local variables: |
909 | * c-basic-offset: 8 | 1224 | * c-basic-offset: 8 |
910 | * End: | 1225 | * End: |
1226 | * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off | ||
911 | */ | 1227 | */ |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 367624822d..b3fb04356b 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: cx88-cards.c,v 1.66 2005/03/04 09:12:23 kraxel Exp $ | 2 | * $Id: cx88-cards.c,v 1.76 2005/06/08 01:28:09 mchehab Exp $ |
3 | * | 3 | * |
4 | * device driver for Conexant 2388x based TV cards | 4 | * device driver for Conexant 2388x based TV cards |
5 | * card-specific stuff. | 5 | * card-specific stuff. |
@@ -35,6 +35,9 @@ struct cx88_board cx88_boards[] = { | |||
35 | [CX88_BOARD_UNKNOWN] = { | 35 | [CX88_BOARD_UNKNOWN] = { |
36 | .name = "UNKNOWN/GENERIC", | 36 | .name = "UNKNOWN/GENERIC", |
37 | .tuner_type = UNSET, | 37 | .tuner_type = UNSET, |
38 | .radio_type = UNSET, | ||
39 | .tuner_addr = ADDR_UNSET, | ||
40 | .radio_addr = ADDR_UNSET, | ||
38 | .input = {{ | 41 | .input = {{ |
39 | .type = CX88_VMUX_COMPOSITE1, | 42 | .type = CX88_VMUX_COMPOSITE1, |
40 | .vmux = 0, | 43 | .vmux = 0, |
@@ -52,6 +55,9 @@ struct cx88_board cx88_boards[] = { | |||
52 | [CX88_BOARD_HAUPPAUGE] = { | 55 | [CX88_BOARD_HAUPPAUGE] = { |
53 | .name = "Hauppauge WinTV 34xxx models", | 56 | .name = "Hauppauge WinTV 34xxx models", |
54 | .tuner_type = UNSET, | 57 | .tuner_type = UNSET, |
58 | .radio_type = UNSET, | ||
59 | .tuner_addr = ADDR_UNSET, | ||
60 | .radio_addr = ADDR_UNSET, | ||
55 | .tda9887_conf = TDA9887_PRESENT, | 61 | .tda9887_conf = TDA9887_PRESENT, |
56 | .input = {{ | 62 | .input = {{ |
57 | .type = CX88_VMUX_TELEVISION, | 63 | .type = CX88_VMUX_TELEVISION, |
@@ -78,6 +84,9 @@ struct cx88_board cx88_boards[] = { | |||
78 | [CX88_BOARD_GDI] = { | 84 | [CX88_BOARD_GDI] = { |
79 | .name = "GDI Black Gold", | 85 | .name = "GDI Black Gold", |
80 | .tuner_type = UNSET, | 86 | .tuner_type = UNSET, |
87 | .radio_type = UNSET, | ||
88 | .tuner_addr = ADDR_UNSET, | ||
89 | .radio_addr = ADDR_UNSET, | ||
81 | .input = {{ | 90 | .input = {{ |
82 | .type = CX88_VMUX_TELEVISION, | 91 | .type = CX88_VMUX_TELEVISION, |
83 | .vmux = 0, | 92 | .vmux = 0, |
@@ -85,7 +94,10 @@ struct cx88_board cx88_boards[] = { | |||
85 | }, | 94 | }, |
86 | [CX88_BOARD_PIXELVIEW] = { | 95 | [CX88_BOARD_PIXELVIEW] = { |
87 | .name = "PixelView", | 96 | .name = "PixelView", |
88 | .tuner_type = 5, | 97 | .tuner_type = TUNER_PHILIPS_PAL, |
98 | .radio_type = UNSET, | ||
99 | .tuner_addr = ADDR_UNSET, | ||
100 | .radio_addr = ADDR_UNSET, | ||
89 | .input = {{ | 101 | .input = {{ |
90 | .type = CX88_VMUX_TELEVISION, | 102 | .type = CX88_VMUX_TELEVISION, |
91 | .vmux = 0, | 103 | .vmux = 0, |
@@ -104,7 +116,10 @@ struct cx88_board cx88_boards[] = { | |||
104 | }, | 116 | }, |
105 | [CX88_BOARD_ATI_WONDER_PRO] = { | 117 | [CX88_BOARD_ATI_WONDER_PRO] = { |
106 | .name = "ATI TV Wonder Pro", | 118 | .name = "ATI TV Wonder Pro", |
107 | .tuner_type = 44, | 119 | .tuner_type = TUNER_PHILIPS_4IN1, |
120 | .radio_type = UNSET, | ||
121 | .tuner_addr = ADDR_UNSET, | ||
122 | .radio_addr = ADDR_UNSET, | ||
108 | .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER, | 123 | .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER, |
109 | .input = {{ | 124 | .input = {{ |
110 | .type = CX88_VMUX_TELEVISION, | 125 | .type = CX88_VMUX_TELEVISION, |
@@ -122,7 +137,10 @@ struct cx88_board cx88_boards[] = { | |||
122 | }, | 137 | }, |
123 | [CX88_BOARD_WINFAST2000XP_EXPERT] = { | 138 | [CX88_BOARD_WINFAST2000XP_EXPERT] = { |
124 | .name = "Leadtek Winfast 2000XP Expert", | 139 | .name = "Leadtek Winfast 2000XP Expert", |
125 | .tuner_type = 44, | 140 | .tuner_type = TUNER_PHILIPS_4IN1, |
141 | .radio_type = UNSET, | ||
142 | .tuner_addr = ADDR_UNSET, | ||
143 | .radio_addr = ADDR_UNSET, | ||
126 | .tda9887_conf = TDA9887_PRESENT, | 144 | .tda9887_conf = TDA9887_PRESENT, |
127 | .input = {{ | 145 | .input = {{ |
128 | .type = CX88_VMUX_TELEVISION, | 146 | .type = CX88_VMUX_TELEVISION, |
@@ -156,7 +174,10 @@ struct cx88_board cx88_boards[] = { | |||
156 | }, | 174 | }, |
157 | [CX88_BOARD_AVERTV_303] = { | 175 | [CX88_BOARD_AVERTV_303] = { |
158 | .name = "AverTV Studio 303 (M126)", | 176 | .name = "AverTV Studio 303 (M126)", |
159 | .tuner_type = 38, | 177 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, |
178 | .radio_type = UNSET, | ||
179 | .tuner_addr = ADDR_UNSET, | ||
180 | .radio_addr = ADDR_UNSET, | ||
160 | .tda9887_conf = TDA9887_PRESENT, | 181 | .tda9887_conf = TDA9887_PRESENT, |
161 | .input = {{ | 182 | .input = {{ |
162 | .type = CX88_VMUX_TELEVISION, | 183 | .type = CX88_VMUX_TELEVISION, |
@@ -179,7 +200,10 @@ struct cx88_board cx88_boards[] = { | |||
179 | // added gpio values thanks to Michal | 200 | // added gpio values thanks to Michal |
180 | // values for PAL from DScaler | 201 | // values for PAL from DScaler |
181 | .name = "MSI TV-@nywhere Master", | 202 | .name = "MSI TV-@nywhere Master", |
182 | .tuner_type = 33, | 203 | .tuner_type = TUNER_MT2032, |
204 | .radio_type = UNSET, | ||
205 | .tuner_addr = ADDR_UNSET, | ||
206 | .radio_addr = ADDR_UNSET, | ||
183 | .tda9887_conf = TDA9887_PRESENT, | 207 | .tda9887_conf = TDA9887_PRESENT, |
184 | .input = {{ | 208 | .input = {{ |
185 | .type = CX88_VMUX_TELEVISION, | 209 | .type = CX88_VMUX_TELEVISION, |
@@ -206,7 +230,10 @@ struct cx88_board cx88_boards[] = { | |||
206 | }, | 230 | }, |
207 | [CX88_BOARD_WINFAST_DV2000] = { | 231 | [CX88_BOARD_WINFAST_DV2000] = { |
208 | .name = "Leadtek Winfast DV2000", | 232 | .name = "Leadtek Winfast DV2000", |
209 | .tuner_type = 38, | 233 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, |
234 | .radio_type = UNSET, | ||
235 | .tuner_addr = ADDR_UNSET, | ||
236 | .radio_addr = ADDR_UNSET, | ||
210 | .tda9887_conf = TDA9887_PRESENT, | 237 | .tda9887_conf = TDA9887_PRESENT, |
211 | .input = {{ | 238 | .input = {{ |
212 | .type = CX88_VMUX_TELEVISION, | 239 | .type = CX88_VMUX_TELEVISION, |
@@ -239,34 +266,40 @@ struct cx88_board cx88_boards[] = { | |||
239 | .gpio3 = 0x02000000, | 266 | .gpio3 = 0x02000000, |
240 | }, | 267 | }, |
241 | }, | 268 | }, |
242 | [CX88_BOARD_LEADTEK_PVR2000] = { | 269 | [CX88_BOARD_LEADTEK_PVR2000] = { |
243 | // gpio values for PAL version from regspy by DScaler | 270 | // gpio values for PAL version from regspy by DScaler |
244 | .name = "Leadtek PVR 2000", | 271 | .name = "Leadtek PVR 2000", |
245 | .tuner_type = 38, | 272 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, |
273 | .radio_type = UNSET, | ||
274 | .tuner_addr = ADDR_UNSET, | ||
275 | .radio_addr = ADDR_UNSET, | ||
246 | .tda9887_conf = TDA9887_PRESENT, | 276 | .tda9887_conf = TDA9887_PRESENT, |
247 | .input = {{ | 277 | .input = {{ |
248 | .type = CX88_VMUX_TELEVISION, | 278 | .type = CX88_VMUX_TELEVISION, |
249 | .vmux = 0, | 279 | .vmux = 0, |
250 | .gpio0 = 0x0000bde6, | 280 | .gpio0 = 0x0000bde2, |
251 | },{ | 281 | },{ |
252 | .type = CX88_VMUX_COMPOSITE1, | 282 | .type = CX88_VMUX_COMPOSITE1, |
253 | .vmux = 1, | 283 | .vmux = 1, |
254 | .gpio0 = 0x0000bde6, | 284 | .gpio0 = 0x0000bde6, |
255 | },{ | 285 | },{ |
256 | .type = CX88_VMUX_SVIDEO, | 286 | .type = CX88_VMUX_SVIDEO, |
257 | .vmux = 2, | 287 | .vmux = 2, |
258 | .gpio0 = 0x0000bde6, | 288 | .gpio0 = 0x0000bde6, |
259 | }}, | 289 | }}, |
260 | .radio = { | 290 | .radio = { |
261 | .type = CX88_RADIO, | 291 | .type = CX88_RADIO, |
262 | .gpio0 = 0x0000bd62, | 292 | .gpio0 = 0x0000bd62, |
263 | }, | 293 | }, |
264 | .blackbird = 1, | 294 | .blackbird = 1, |
265 | }, | 295 | }, |
266 | [CX88_BOARD_IODATA_GVVCP3PCI] = { | 296 | [CX88_BOARD_IODATA_GVVCP3PCI] = { |
267 | .name = "IODATA GV-VCP3/PCI", | 297 | .name = "IODATA GV-VCP3/PCI", |
268 | .tuner_type = TUNER_ABSENT, | 298 | .tuner_type = TUNER_ABSENT, |
269 | .input = {{ | 299 | .radio_type = UNSET, |
300 | .tuner_addr = ADDR_UNSET, | ||
301 | .radio_addr = ADDR_UNSET, | ||
302 | .input = {{ | ||
270 | .type = CX88_VMUX_COMPOSITE1, | 303 | .type = CX88_VMUX_COMPOSITE1, |
271 | .vmux = 0, | 304 | .vmux = 0, |
272 | },{ | 305 | },{ |
@@ -279,7 +312,10 @@ struct cx88_board cx88_boards[] = { | |||
279 | }, | 312 | }, |
280 | [CX88_BOARD_PROLINK_PLAYTVPVR] = { | 313 | [CX88_BOARD_PROLINK_PLAYTVPVR] = { |
281 | .name = "Prolink PlayTV PVR", | 314 | .name = "Prolink PlayTV PVR", |
282 | .tuner_type = 43, | 315 | .tuner_type = TUNER_PHILIPS_FM1236_MK3, |
316 | .radio_type = UNSET, | ||
317 | .tuner_addr = ADDR_UNSET, | ||
318 | .radio_addr = ADDR_UNSET, | ||
283 | .tda9887_conf = TDA9887_PRESENT, | 319 | .tda9887_conf = TDA9887_PRESENT, |
284 | .input = {{ | 320 | .input = {{ |
285 | .type = CX88_VMUX_TELEVISION, | 321 | .type = CX88_VMUX_TELEVISION, |
@@ -301,8 +337,11 @@ struct cx88_board cx88_boards[] = { | |||
301 | }, | 337 | }, |
302 | [CX88_BOARD_ASUS_PVR_416] = { | 338 | [CX88_BOARD_ASUS_PVR_416] = { |
303 | .name = "ASUS PVR-416", | 339 | .name = "ASUS PVR-416", |
304 | .tuner_type = 43, | 340 | .tuner_type = TUNER_PHILIPS_FM1236_MK3, |
305 | .tda9887_conf = TDA9887_PRESENT, | 341 | .radio_type = UNSET, |
342 | .tuner_addr = ADDR_UNSET, | ||
343 | .radio_addr = ADDR_UNSET, | ||
344 | .tda9887_conf = TDA9887_PRESENT, | ||
306 | .input = {{ | 345 | .input = {{ |
307 | .type = CX88_VMUX_TELEVISION, | 346 | .type = CX88_VMUX_TELEVISION, |
308 | .vmux = 0, | 347 | .vmux = 0, |
@@ -320,7 +359,10 @@ struct cx88_board cx88_boards[] = { | |||
320 | }, | 359 | }, |
321 | [CX88_BOARD_MSI_TVANYWHERE] = { | 360 | [CX88_BOARD_MSI_TVANYWHERE] = { |
322 | .name = "MSI TV-@nywhere", | 361 | .name = "MSI TV-@nywhere", |
323 | .tuner_type = 33, | 362 | .tuner_type = TUNER_MT2032, |
363 | .radio_type = UNSET, | ||
364 | .tuner_addr = ADDR_UNSET, | ||
365 | .radio_addr = ADDR_UNSET, | ||
324 | .tda9887_conf = TDA9887_PRESENT, | 366 | .tda9887_conf = TDA9887_PRESENT, |
325 | .input = {{ | 367 | .input = {{ |
326 | .type = CX88_VMUX_TELEVISION, | 368 | .type = CX88_VMUX_TELEVISION, |
@@ -342,6 +384,9 @@ struct cx88_board cx88_boards[] = { | |||
342 | [CX88_BOARD_KWORLD_DVB_T] = { | 384 | [CX88_BOARD_KWORLD_DVB_T] = { |
343 | .name = "KWorld/VStream XPert DVB-T", | 385 | .name = "KWorld/VStream XPert DVB-T", |
344 | .tuner_type = TUNER_ABSENT, | 386 | .tuner_type = TUNER_ABSENT, |
387 | .radio_type = UNSET, | ||
388 | .tuner_addr = ADDR_UNSET, | ||
389 | .radio_addr = ADDR_UNSET, | ||
345 | .input = {{ | 390 | .input = {{ |
346 | .type = CX88_VMUX_COMPOSITE1, | 391 | .type = CX88_VMUX_COMPOSITE1, |
347 | .vmux = 1, | 392 | .vmux = 1, |
@@ -358,6 +403,9 @@ struct cx88_board cx88_boards[] = { | |||
358 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = { | 403 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = { |
359 | .name = "DVICO FusionHDTV DVB-T1", | 404 | .name = "DVICO FusionHDTV DVB-T1", |
360 | .tuner_type = TUNER_ABSENT, /* No analog tuner */ | 405 | .tuner_type = TUNER_ABSENT, /* No analog tuner */ |
406 | .radio_type = UNSET, | ||
407 | .tuner_addr = ADDR_UNSET, | ||
408 | .radio_addr = ADDR_UNSET, | ||
361 | .input = {{ | 409 | .input = {{ |
362 | .type = CX88_VMUX_COMPOSITE1, | 410 | .type = CX88_VMUX_COMPOSITE1, |
363 | .vmux = 1, | 411 | .vmux = 1, |
@@ -371,7 +419,10 @@ struct cx88_board cx88_boards[] = { | |||
371 | }, | 419 | }, |
372 | [CX88_BOARD_KWORLD_LTV883] = { | 420 | [CX88_BOARD_KWORLD_LTV883] = { |
373 | .name = "KWorld LTV883RF", | 421 | .name = "KWorld LTV883RF", |
374 | .tuner_type = 48, | 422 | .tuner_type = TUNER_TNF_8831BGFF, |
423 | .radio_type = UNSET, | ||
424 | .tuner_addr = ADDR_UNSET, | ||
425 | .radio_addr = ADDR_UNSET, | ||
375 | .input = {{ | 426 | .input = {{ |
376 | .type = CX88_VMUX_TELEVISION, | 427 | .type = CX88_VMUX_TELEVISION, |
377 | .vmux = 0, | 428 | .vmux = 0, |
@@ -397,6 +448,9 @@ struct cx88_board cx88_boards[] = { | |||
397 | [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD] = { | 448 | [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD] = { |
398 | .name = "DViCO - FusionHDTV 3 Gold", | 449 | .name = "DViCO - FusionHDTV 3 Gold", |
399 | .tuner_type = TUNER_MICROTUNE_4042FI5, | 450 | .tuner_type = TUNER_MICROTUNE_4042FI5, |
451 | .radio_type = UNSET, | ||
452 | .tuner_addr = ADDR_UNSET, | ||
453 | .radio_addr = ADDR_UNSET, | ||
400 | /* | 454 | /* |
401 | GPIO[0] resets DT3302 DTV receiver | 455 | GPIO[0] resets DT3302 DTV receiver |
402 | 0 - reset asserted | 456 | 0 - reset asserted |
@@ -428,17 +482,14 @@ struct cx88_board cx88_boards[] = { | |||
428 | .vmux = 2, | 482 | .vmux = 2, |
429 | .gpio0 = 0x0f00, | 483 | .gpio0 = 0x0f00, |
430 | }}, | 484 | }}, |
431 | #if 0 | ||
432 | .ts = { | ||
433 | .type = CX88_TS, | ||
434 | .gpio0 = 0x00000f01, /* Hooked to tuner reset bit */ | ||
435 | } | ||
436 | #endif | ||
437 | }, | 485 | }, |
438 | [CX88_BOARD_HAUPPAUGE_DVB_T1] = { | 486 | [CX88_BOARD_HAUPPAUGE_DVB_T1] = { |
439 | .name = "Hauppauge Nova-T DVB-T", | 487 | .name = "Hauppauge Nova-T DVB-T", |
440 | .tuner_type = TUNER_ABSENT, | 488 | .tuner_type = TUNER_ABSENT, |
441 | .input = {{ | 489 | .radio_type = UNSET, |
490 | .tuner_addr = ADDR_UNSET, | ||
491 | .radio_addr = ADDR_UNSET, | ||
492 | .input = {{ | ||
442 | .type = CX88_VMUX_DVB, | 493 | .type = CX88_VMUX_DVB, |
443 | .vmux = 0, | 494 | .vmux = 0, |
444 | }}, | 495 | }}, |
@@ -447,6 +498,9 @@ struct cx88_board cx88_boards[] = { | |||
447 | [CX88_BOARD_CONEXANT_DVB_T1] = { | 498 | [CX88_BOARD_CONEXANT_DVB_T1] = { |
448 | .name = "Conexant DVB-T reference design", | 499 | .name = "Conexant DVB-T reference design", |
449 | .tuner_type = TUNER_ABSENT, | 500 | .tuner_type = TUNER_ABSENT, |
501 | .radio_type = UNSET, | ||
502 | .tuner_addr = ADDR_UNSET, | ||
503 | .radio_addr = ADDR_UNSET, | ||
450 | .input = {{ | 504 | .input = {{ |
451 | .type = CX88_VMUX_DVB, | 505 | .type = CX88_VMUX_DVB, |
452 | .vmux = 0, | 506 | .vmux = 0, |
@@ -456,6 +510,9 @@ struct cx88_board cx88_boards[] = { | |||
456 | [CX88_BOARD_PROVIDEO_PV259] = { | 510 | [CX88_BOARD_PROVIDEO_PV259] = { |
457 | .name = "Provideo PV259", | 511 | .name = "Provideo PV259", |
458 | .tuner_type = TUNER_PHILIPS_FQ1216ME, | 512 | .tuner_type = TUNER_PHILIPS_FQ1216ME, |
513 | .radio_type = UNSET, | ||
514 | .tuner_addr = ADDR_UNSET, | ||
515 | .radio_addr = ADDR_UNSET, | ||
459 | .input = {{ | 516 | .input = {{ |
460 | .type = CX88_VMUX_TELEVISION, | 517 | .type = CX88_VMUX_TELEVISION, |
461 | .vmux = 0, | 518 | .vmux = 0, |
@@ -465,6 +522,9 @@ struct cx88_board cx88_boards[] = { | |||
465 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = { | 522 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = { |
466 | .name = "DVICO FusionHDTV DVB-T Plus", | 523 | .name = "DVICO FusionHDTV DVB-T Plus", |
467 | .tuner_type = TUNER_ABSENT, /* No analog tuner */ | 524 | .tuner_type = TUNER_ABSENT, /* No analog tuner */ |
525 | .radio_type = UNSET, | ||
526 | .tuner_addr = ADDR_UNSET, | ||
527 | .radio_addr = ADDR_UNSET, | ||
468 | .input = {{ | 528 | .input = {{ |
469 | .type = CX88_VMUX_COMPOSITE1, | 529 | .type = CX88_VMUX_COMPOSITE1, |
470 | .vmux = 1, | 530 | .vmux = 1, |
@@ -479,6 +539,9 @@ struct cx88_board cx88_boards[] = { | |||
479 | [CX88_BOARD_DNTV_LIVE_DVB_T] = { | 539 | [CX88_BOARD_DNTV_LIVE_DVB_T] = { |
480 | .name = "digitalnow DNTV Live! DVB-T", | 540 | .name = "digitalnow DNTV Live! DVB-T", |
481 | .tuner_type = TUNER_ABSENT, | 541 | .tuner_type = TUNER_ABSENT, |
542 | .radio_type = UNSET, | ||
543 | .tuner_addr = ADDR_UNSET, | ||
544 | .radio_addr = ADDR_UNSET, | ||
482 | .input = {{ | 545 | .input = {{ |
483 | .type = CX88_VMUX_COMPOSITE1, | 546 | .type = CX88_VMUX_COMPOSITE1, |
484 | .vmux = 1, | 547 | .vmux = 1, |
@@ -495,6 +558,9 @@ struct cx88_board cx88_boards[] = { | |||
495 | [CX88_BOARD_PCHDTV_HD3000] = { | 558 | [CX88_BOARD_PCHDTV_HD3000] = { |
496 | .name = "pcHDTV HD3000 HDTV", | 559 | .name = "pcHDTV HD3000 HDTV", |
497 | .tuner_type = TUNER_THOMSON_DTT7610, | 560 | .tuner_type = TUNER_THOMSON_DTT7610, |
561 | .radio_type = UNSET, | ||
562 | .tuner_addr = ADDR_UNSET, | ||
563 | .radio_addr = ADDR_UNSET, | ||
498 | .input = {{ | 564 | .input = {{ |
499 | .type = CX88_VMUX_TELEVISION, | 565 | .type = CX88_VMUX_TELEVISION, |
500 | .vmux = 0, | 566 | .vmux = 0, |
@@ -530,8 +596,11 @@ struct cx88_board cx88_boards[] = { | |||
530 | [CX88_BOARD_HAUPPAUGE_ROSLYN] = { | 596 | [CX88_BOARD_HAUPPAUGE_ROSLYN] = { |
531 | // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu> | 597 | // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu> |
532 | // GPIO values obtained from regspy, courtesy Sean Covel | 598 | // GPIO values obtained from regspy, courtesy Sean Covel |
533 | .name = "Hauppauge WinTV 28xxx (Roslyn) models", | 599 | .name = "Hauppauge WinTV 28xxx (Roslyn) models", |
534 | .tuner_type = UNSET, | 600 | .tuner_type = UNSET, |
601 | .radio_type = UNSET, | ||
602 | .tuner_addr = ADDR_UNSET, | ||
603 | .radio_addr = ADDR_UNSET, | ||
535 | .input = {{ | 604 | .input = {{ |
536 | .type = CX88_VMUX_TELEVISION, | 605 | .type = CX88_VMUX_TELEVISION, |
537 | .vmux = 0, | 606 | .vmux = 0, |
@@ -559,33 +628,37 @@ struct cx88_board cx88_boards[] = { | |||
559 | .blackbird = 1, | 628 | .blackbird = 1, |
560 | }, | 629 | }, |
561 | [CX88_BOARD_DIGITALLOGIC_MEC] = { | 630 | [CX88_BOARD_DIGITALLOGIC_MEC] = { |
562 | /* params copied over from Leadtek PVR 2000 */ | ||
563 | .name = "Digital-Logic MICROSPACE Entertainment Center (MEC)", | 631 | .name = "Digital-Logic MICROSPACE Entertainment Center (MEC)", |
564 | /* not sure yet about the tuner type */ | 632 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, |
565 | .tuner_type = 38, | 633 | .radio_type = UNSET, |
634 | .tuner_addr = ADDR_UNSET, | ||
635 | .radio_addr = ADDR_UNSET, | ||
566 | .tda9887_conf = TDA9887_PRESENT, | 636 | .tda9887_conf = TDA9887_PRESENT, |
567 | .input = {{ | 637 | .input = {{ |
568 | .type = CX88_VMUX_TELEVISION, | 638 | .type = CX88_VMUX_TELEVISION, |
569 | .vmux = 0, | 639 | .vmux = 0, |
570 | .gpio0 = 0x0000bde6, | 640 | .gpio0 = 0x00009d80, |
571 | },{ | 641 | },{ |
572 | .type = CX88_VMUX_COMPOSITE1, | 642 | .type = CX88_VMUX_COMPOSITE1, |
573 | .vmux = 1, | 643 | .vmux = 1, |
574 | .gpio0 = 0x0000bde6, | 644 | .gpio0 = 0x00009d76, |
575 | },{ | 645 | },{ |
576 | .type = CX88_VMUX_SVIDEO, | 646 | .type = CX88_VMUX_SVIDEO, |
577 | .vmux = 2, | 647 | .vmux = 2, |
578 | .gpio0 = 0x0000bde6, | 648 | .gpio0 = 0x00009d76, |
579 | }}, | 649 | }}, |
580 | .radio = { | 650 | .radio = { |
581 | .type = CX88_RADIO, | 651 | .type = CX88_RADIO, |
582 | .gpio0 = 0x0000bd62, | 652 | .gpio0 = 0x00009d00, |
583 | }, | 653 | }, |
584 | .blackbird = 1, | 654 | .blackbird = 1, |
585 | }, | 655 | }, |
586 | [CX88_BOARD_IODATA_GVBCTV7E] = { | 656 | [CX88_BOARD_IODATA_GVBCTV7E] = { |
587 | .name = "IODATA GV/BCTV7E", | 657 | .name = "IODATA GV/BCTV7E", |
588 | .tuner_type = TUNER_PHILIPS_FQ1286, | 658 | .tuner_type = TUNER_PHILIPS_FQ1286, |
659 | .radio_type = UNSET, | ||
660 | .tuner_addr = ADDR_UNSET, | ||
661 | .radio_addr = ADDR_UNSET, | ||
589 | .tda9887_conf = TDA9887_PRESENT, | 662 | .tda9887_conf = TDA9887_PRESENT, |
590 | .input = {{ | 663 | .input = {{ |
591 | .type = CX88_VMUX_TELEVISION, | 664 | .type = CX88_VMUX_TELEVISION, |
@@ -601,6 +674,56 @@ struct cx88_board cx88_boards[] = { | |||
601 | .gpio1 = 0x0000e07f, | 674 | .gpio1 = 0x0000e07f, |
602 | }} | 675 | }} |
603 | }, | 676 | }, |
677 | [CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO] = { | ||
678 | .name = "PixelView PlayTV Ultra Pro (Stereo)", | ||
679 | /* May be also TUNER_YMEC_TVF_5533MF for NTSC/M or PAL/M */ | ||
680 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, | ||
681 | .radio_type = TUNER_TEA5767, | ||
682 | .tuner_addr = 0xc2>>1, | ||
683 | .radio_addr = 0xc0>>1, | ||
684 | .input = {{ | ||
685 | .type = CX88_VMUX_TELEVISION, | ||
686 | .vmux = 0, | ||
687 | .gpio0 = 0xbf61, /* internal decoder */ | ||
688 | },{ | ||
689 | .type = CX88_VMUX_COMPOSITE1, | ||
690 | .vmux = 1, | ||
691 | .gpio0 = 0xbf63, | ||
692 | },{ | ||
693 | .type = CX88_VMUX_SVIDEO, | ||
694 | .vmux = 2, | ||
695 | .gpio0 = 0xbf63, | ||
696 | }}, | ||
697 | .radio = { | ||
698 | .type = CX88_RADIO, | ||
699 | .gpio0 = 0xbf60, | ||
700 | }, | ||
701 | }, | ||
702 | [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = { | ||
703 | .name = "DViCO - FusionHDTV 3 Gold-T", | ||
704 | .tuner_type = TUNER_THOMSON_DTT7611, | ||
705 | .radio_type = UNSET, | ||
706 | .tuner_addr = ADDR_UNSET, | ||
707 | .radio_addr = ADDR_UNSET, | ||
708 | /* See DViCO FusionHDTV 3 Gold for GPIO documentation. */ | ||
709 | .input = {{ | ||
710 | .type = CX88_VMUX_TELEVISION, | ||
711 | .vmux = 0, | ||
712 | .gpio0 = 0x0f0d, | ||
713 | },{ | ||
714 | .type = CX88_VMUX_CABLE, | ||
715 | .vmux = 0, | ||
716 | .gpio0 = 0x0f05, | ||
717 | },{ | ||
718 | .type = CX88_VMUX_COMPOSITE1, | ||
719 | .vmux = 1, | ||
720 | .gpio0 = 0x0f00, | ||
721 | },{ | ||
722 | .type = CX88_VMUX_SVIDEO, | ||
723 | .vmux = 2, | ||
724 | .gpio0 = 0x0f00, | ||
725 | }}, | ||
726 | }, | ||
604 | }; | 727 | }; |
605 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); | 728 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); |
606 | 729 | ||
@@ -673,6 +796,10 @@ struct cx88_subid cx88_subids[] = { | |||
673 | .subdevice = 0xd810, | 796 | .subdevice = 0xd810, |
674 | .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD, | 797 | .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD, |
675 | },{ | 798 | },{ |
799 | .subvendor = 0x18ac, | ||
800 | .subdevice = 0xd820, | ||
801 | .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T, | ||
802 | },{ | ||
676 | .subvendor = 0x18AC, | 803 | .subvendor = 0x18AC, |
677 | .subdevice = 0xDB00, | 804 | .subdevice = 0xDB00, |
678 | .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1, | 805 | .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1, |
@@ -935,4 +1062,5 @@ EXPORT_SYMBOL(cx88_card_setup); | |||
935 | * Local variables: | 1062 | * Local variables: |
936 | * c-basic-offset: 8 | 1063 | * c-basic-offset: 8 |
937 | * End: | 1064 | * End: |
1065 | * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off | ||
938 | */ | 1066 | */ |
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 1ff79b5a88..c046a23537 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: cx88-core.c,v 1.24 2005/01/19 12:01:55 kraxel Exp $ | 2 | * $Id: cx88-core.c,v 1.28 2005/06/12 04:19:19 mchehab Exp $ |
3 | * | 3 | * |
4 | * device driver for Conexant 2388x based TV cards | 4 | * device driver for Conexant 2388x based TV cards |
5 | * driver core | 5 | * driver core |
@@ -51,12 +51,15 @@ module_param(latency,int,0444); | |||
51 | MODULE_PARM_DESC(latency,"pci latency timer"); | 51 | MODULE_PARM_DESC(latency,"pci latency timer"); |
52 | 52 | ||
53 | static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; | 53 | static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; |
54 | static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; | ||
54 | static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; | 55 | static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; |
55 | 56 | ||
56 | module_param_array(tuner, int, NULL, 0444); | 57 | module_param_array(tuner, int, NULL, 0444); |
58 | module_param_array(radio, int, NULL, 0444); | ||
57 | module_param_array(card, int, NULL, 0444); | 59 | module_param_array(card, int, NULL, 0444); |
58 | 60 | ||
59 | MODULE_PARM_DESC(tuner,"tuner type"); | 61 | MODULE_PARM_DESC(tuner,"tuner type"); |
62 | MODULE_PARM_DESC(radio,"radio tuner type"); | ||
60 | MODULE_PARM_DESC(card,"card type"); | 63 | MODULE_PARM_DESC(card,"card type"); |
61 | 64 | ||
62 | static unsigned int nicam = 0; | 65 | static unsigned int nicam = 0; |
@@ -429,7 +432,7 @@ int cx88_sram_channel_setup(struct cx88_core *core, | |||
429 | /* ------------------------------------------------------------------ */ | 432 | /* ------------------------------------------------------------------ */ |
430 | /* debug helper code */ | 433 | /* debug helper code */ |
431 | 434 | ||
432 | static int cx88_risc_decode(u32 risc) | 435 | int cx88_risc_decode(u32 risc) |
433 | { | 436 | { |
434 | static char *instr[16] = { | 437 | static char *instr[16] = { |
435 | [ RISC_SYNC >> 28 ] = "sync", | 438 | [ RISC_SYNC >> 28 ] = "sync", |
@@ -736,6 +739,10 @@ static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm) | |||
736 | { | 739 | { |
737 | static const unsigned int ntsc = 28636360; | 740 | static const unsigned int ntsc = 28636360; |
738 | static const unsigned int pal = 35468950; | 741 | static const unsigned int pal = 35468950; |
742 | static const unsigned int palm = 28604892; | ||
743 | |||
744 | if (norm->id & V4L2_STD_PAL_M) | ||
745 | return palm; | ||
739 | 746 | ||
740 | return (norm->id & V4L2_STD_625_50) ? pal : ntsc; | 747 | return (norm->id & V4L2_STD_625_50) ? pal : ntsc; |
741 | } | 748 | } |
@@ -749,6 +756,11 @@ static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm) | |||
749 | 756 | ||
750 | static unsigned int inline norm_htotal(struct cx88_tvnorm *norm) | 757 | static unsigned int inline norm_htotal(struct cx88_tvnorm *norm) |
751 | { | 758 | { |
759 | /* Should always be Line Draw Time / (4*FSC) */ | ||
760 | |||
761 | if (norm->id & V4L2_STD_PAL_M) | ||
762 | return 909; | ||
763 | |||
752 | return (norm->id & V4L2_STD_625_50) ? 1135 : 910; | 764 | return (norm->id & V4L2_STD_625_50) ? 1135 : 910; |
753 | } | 765 | } |
754 | 766 | ||
@@ -1164,8 +1176,20 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci) | |||
1164 | "insmod option" : "autodetected"); | 1176 | "insmod option" : "autodetected"); |
1165 | 1177 | ||
1166 | core->tuner_type = tuner[core->nr]; | 1178 | core->tuner_type = tuner[core->nr]; |
1179 | core->radio_type = radio[core->nr]; | ||
1167 | if (UNSET == core->tuner_type) | 1180 | if (UNSET == core->tuner_type) |
1168 | core->tuner_type = cx88_boards[core->board].tuner_type; | 1181 | core->tuner_type = cx88_boards[core->board].tuner_type; |
1182 | if (UNSET == core->radio_type) | ||
1183 | core->radio_type = cx88_boards[core->board].radio_type; | ||
1184 | if (!core->tuner_addr) | ||
1185 | core->tuner_addr = cx88_boards[core->board].tuner_addr; | ||
1186 | if (!core->radio_addr) | ||
1187 | core->radio_addr = cx88_boards[core->board].radio_addr; | ||
1188 | |||
1189 | printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n", | ||
1190 | core->tuner_type, core->tuner_addr<<1, | ||
1191 | core->radio_type, core->radio_addr<<1); | ||
1192 | |||
1169 | core->tda9887_conf = cx88_boards[core->board].tda9887_conf; | 1193 | core->tda9887_conf = cx88_boards[core->board].tda9887_conf; |
1170 | 1194 | ||
1171 | /* init hardware */ | 1195 | /* init hardware */ |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 9d15d3d5a2..1a259c3966 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: cx88-dvb.c,v 1.31 2005/03/07 15:58:05 kraxel Exp $ | 2 | * $Id: cx88-dvb.c,v 1.33 2005/06/12 04:19:19 mchehab Exp $ |
3 | * | 3 | * |
4 | * device driver for Conexant 2388x based TV cards | 4 | * device driver for Conexant 2388x based TV cards |
5 | * MPEG Transport Stream (DVB) routines | 5 | * MPEG Transport Stream (DVB) routines |
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 0725b1288f..e20adefcfc 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | $Id: cx88-i2c.c,v 1.20 2005/02/15 15:59:35 kraxel Exp $ | 2 | $Id: cx88-i2c.c,v 1.23 2005/06/12 04:19:19 mchehab Exp $ |
3 | 3 | ||
4 | cx88-i2c.c -- all the i2c code is here | 4 | cx88-i2c.c -- all the i2c code is here |
5 | 5 | ||
@@ -91,6 +91,7 @@ static int cx8800_bit_getsda(void *data) | |||
91 | 91 | ||
92 | static int attach_inform(struct i2c_client *client) | 92 | static int attach_inform(struct i2c_client *client) |
93 | { | 93 | { |
94 | struct tuner_addr tun_addr; | ||
94 | struct cx88_core *core = i2c_get_adapdata(client->adapter); | 95 | struct cx88_core *core = i2c_get_adapdata(client->adapter); |
95 | 96 | ||
96 | dprintk(1, "i2c attach [addr=0x%x,client=%s]\n", | 97 | dprintk(1, "i2c attach [addr=0x%x,client=%s]\n", |
@@ -98,8 +99,19 @@ static int attach_inform(struct i2c_client *client) | |||
98 | if (!client->driver->command) | 99 | if (!client->driver->command) |
99 | return 0; | 100 | return 0; |
100 | 101 | ||
101 | if (core->tuner_type != UNSET) | 102 | if (core->radio_type != UNSET) { |
102 | client->driver->command(client, TUNER_SET_TYPE, &core->tuner_type); | 103 | tun_addr.v4l2_tuner = V4L2_TUNER_RADIO; |
104 | tun_addr.type = core->radio_type; | ||
105 | tun_addr.addr = core->radio_addr; | ||
106 | client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr); | ||
107 | } | ||
108 | if (core->tuner_type != UNSET) { | ||
109 | tun_addr.v4l2_tuner = V4L2_TUNER_ANALOG_TV; | ||
110 | tun_addr.type = core->tuner_type; | ||
111 | tun_addr.addr = core->tuner_addr; | ||
112 | client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr); | ||
113 | } | ||
114 | |||
103 | if (core->tda9887_conf) | 115 | if (core->tda9887_conf) |
104 | client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf); | 116 | client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf); |
105 | return 0; | 117 | return 0; |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index af6ad8cdbd..dc0dcf249a 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: cx88-input.c,v 1.9 2005/03/04 09:12:23 kraxel Exp $ | 2 | * $Id: cx88-input.c,v 1.11 2005/05/22 20:57:56 nsh Exp $ |
3 | * | 3 | * |
4 | * Device driver for GPIO attached remote control interfaces | 4 | * Device driver for GPIO attached remote control interfaces |
5 | * on Conexant 2388x based TV/DVB cards. | 5 | * on Conexant 2388x based TV/DVB cards. |
@@ -235,6 +235,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
235 | /* detect & configure */ | 235 | /* detect & configure */ |
236 | switch (core->board) { | 236 | switch (core->board) { |
237 | case CX88_BOARD_DNTV_LIVE_DVB_T: | 237 | case CX88_BOARD_DNTV_LIVE_DVB_T: |
238 | case CX88_BOARD_KWORLD_DVB_T: | ||
238 | ir_codes = ir_codes_dntv_live_dvb_t; | 239 | ir_codes = ir_codes_dntv_live_dvb_t; |
239 | ir->gpio_addr = MO_GP1_IO; | 240 | ir->gpio_addr = MO_GP1_IO; |
240 | ir->mask_keycode = 0x1f; | 241 | ir->mask_keycode = 0x1f; |
@@ -261,7 +262,15 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
261 | ir->mask_keydown = 0x02; | 262 | ir->mask_keydown = 0x02; |
262 | ir->polling = 5; // ms | 263 | ir->polling = 5; // ms |
263 | break; | 264 | break; |
265 | case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: | ||
266 | ir_codes = ir_codes_pixelview; | ||
267 | ir->gpio_addr = MO_GP1_IO; | ||
268 | ir->mask_keycode = 0x1f; | ||
269 | ir->mask_keyup = 0x80; | ||
270 | ir->polling = 1; // ms | ||
271 | break; | ||
264 | } | 272 | } |
273 | |||
265 | if (NULL == ir_codes) { | 274 | if (NULL == ir_codes) { |
266 | kfree(ir); | 275 | kfree(ir); |
267 | return -ENODEV; | 276 | return -ENODEV; |
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 07aae1899e..9ade2ae91e 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: cx88-mpeg.c,v 1.25 2005/03/07 14:18:00 kraxel Exp $ | 2 | * $Id: cx88-mpeg.c,v 1.26 2005/06/03 13:31:51 mchehab Exp $ |
3 | * | 3 | * |
4 | * Support for the mpeg transport stream transfers | 4 | * Support for the mpeg transport stream transfers |
5 | * PCI function #2 of the cx2388x. | 5 | * PCI function #2 of the cx2388x. |
@@ -55,7 +55,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
55 | { | 55 | { |
56 | struct cx88_core *core = dev->core; | 56 | struct cx88_core *core = dev->core; |
57 | 57 | ||
58 | dprintk(1, "cx8802_start_mpegport_dma %d\n", buf->vb.width); | 58 | dprintk(0, "cx8802_start_dma %d\n", buf->vb.width); |
59 | 59 | ||
60 | /* setup fifo + format */ | 60 | /* setup fifo + format */ |
61 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], | 61 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], |
@@ -100,18 +100,21 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
100 | q->count = 1; | 100 | q->count = 1; |
101 | 101 | ||
102 | /* enable irqs */ | 102 | /* enable irqs */ |
103 | dprintk( 0, "setting the interrupt mask\n" ); | ||
103 | cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04); | 104 | cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04); |
104 | cx_write(MO_TS_INTMSK, 0x1f0011); | 105 | cx_set(MO_TS_INTMSK, 0x1f0011); |
106 | //cx_write(MO_TS_INTMSK, 0x0f0011); | ||
105 | 107 | ||
106 | /* start dma */ | 108 | /* start dma */ |
107 | cx_write(MO_DEV_CNTRL2, (1<<5)); /* FIXME: s/write/set/ ??? */ | 109 | cx_set(MO_DEV_CNTRL2, (1<<5)); |
108 | cx_write(MO_TS_DMACNTRL, 0x11); | 110 | cx_set(MO_TS_DMACNTRL, 0x11); |
109 | return 0; | 111 | return 0; |
110 | } | 112 | } |
111 | 113 | ||
112 | static int cx8802_stop_dma(struct cx8802_dev *dev) | 114 | static int cx8802_stop_dma(struct cx8802_dev *dev) |
113 | { | 115 | { |
114 | struct cx88_core *core = dev->core; | 116 | struct cx88_core *core = dev->core; |
117 | dprintk( 0, "cx8802_stop_dma\n" ); | ||
115 | 118 | ||
116 | /* stop dma */ | 119 | /* stop dma */ |
117 | cx_clear(MO_TS_DMACNTRL, 0x11); | 120 | cx_clear(MO_TS_DMACNTRL, 0x11); |
@@ -131,8 +134,12 @@ static int cx8802_restart_queue(struct cx8802_dev *dev, | |||
131 | struct cx88_buffer *buf; | 134 | struct cx88_buffer *buf; |
132 | struct list_head *item; | 135 | struct list_head *item; |
133 | 136 | ||
137 | dprintk( 0, "cx8802_restart_queue\n" ); | ||
134 | if (list_empty(&q->active)) | 138 | if (list_empty(&q->active)) |
139 | { | ||
140 | dprintk( 0, "cx8802_restart_queue: queue is empty\n" ); | ||
135 | return 0; | 141 | return 0; |
142 | } | ||
136 | 143 | ||
137 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); | 144 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); |
138 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", | 145 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", |
@@ -182,27 +189,32 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) | |||
182 | struct cx88_buffer *prev; | 189 | struct cx88_buffer *prev; |
183 | struct cx88_dmaqueue *q = &dev->mpegq; | 190 | struct cx88_dmaqueue *q = &dev->mpegq; |
184 | 191 | ||
192 | dprintk( 1, "cx8802_buf_queue\n" ); | ||
185 | /* add jump to stopper */ | 193 | /* add jump to stopper */ |
186 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | 194 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); |
187 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | 195 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); |
188 | 196 | ||
189 | if (list_empty(&q->active)) { | 197 | if (list_empty(&q->active)) { |
198 | dprintk( 0, "queue is empty - first active\n" ); | ||
190 | list_add_tail(&buf->vb.queue,&q->active); | 199 | list_add_tail(&buf->vb.queue,&q->active); |
191 | cx8802_start_dma(dev, q, buf); | 200 | cx8802_start_dma(dev, q, buf); |
192 | buf->vb.state = STATE_ACTIVE; | 201 | buf->vb.state = STATE_ACTIVE; |
193 | buf->count = q->count++; | 202 | buf->count = q->count++; |
194 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | 203 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); |
195 | dprintk(2,"[%p/%d] %s - first active\n", | 204 | dprintk(0,"[%p/%d] %s - first active\n", |
196 | buf, buf->vb.i, __FUNCTION__); | 205 | buf, buf->vb.i, __FUNCTION__); |
206 | //udelay(100); | ||
197 | 207 | ||
198 | } else { | 208 | } else { |
209 | dprintk( 1, "queue is not empty - append to active\n" ); | ||
199 | prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue); | 210 | prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue); |
200 | list_add_tail(&buf->vb.queue,&q->active); | 211 | list_add_tail(&buf->vb.queue,&q->active); |
201 | buf->vb.state = STATE_ACTIVE; | 212 | buf->vb.state = STATE_ACTIVE; |
202 | buf->count = q->count++; | 213 | buf->count = q->count++; |
203 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | 214 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); |
204 | dprintk(2,"[%p/%d] %s - append to active\n", | 215 | dprintk( 1, "[%p/%d] %s - append to active\n", |
205 | buf, buf->vb.i, __FUNCTION__); | 216 | buf, buf->vb.i, __FUNCTION__); |
217 | //udelay(100); | ||
206 | } | 218 | } |
207 | } | 219 | } |
208 | 220 | ||
@@ -224,7 +236,10 @@ static void do_cancel_buffers(struct cx8802_dev *dev, char *reason, int restart) | |||
224 | buf, buf->vb.i, reason, (unsigned long)buf->risc.dma); | 236 | buf, buf->vb.i, reason, (unsigned long)buf->risc.dma); |
225 | } | 237 | } |
226 | if (restart) | 238 | if (restart) |
239 | { | ||
240 | dprintk(0, "restarting queue\n" ); | ||
227 | cx8802_restart_queue(dev,q); | 241 | cx8802_restart_queue(dev,q); |
242 | } | ||
228 | spin_unlock_irqrestore(&dev->slock,flags); | 243 | spin_unlock_irqrestore(&dev->slock,flags); |
229 | } | 244 | } |
230 | 245 | ||
@@ -232,6 +247,7 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev) | |||
232 | { | 247 | { |
233 | struct cx88_dmaqueue *q = &dev->mpegq; | 248 | struct cx88_dmaqueue *q = &dev->mpegq; |
234 | 249 | ||
250 | dprintk( 1, "cx8802_cancel_buffers" ); | ||
235 | del_timer_sync(&q->timeout); | 251 | del_timer_sync(&q->timeout); |
236 | cx8802_stop_dma(dev); | 252 | cx8802_stop_dma(dev); |
237 | do_cancel_buffers(dev,"cancel",0); | 253 | do_cancel_buffers(dev,"cancel",0); |
@@ -241,7 +257,7 @@ static void cx8802_timeout(unsigned long data) | |||
241 | { | 257 | { |
242 | struct cx8802_dev *dev = (struct cx8802_dev*)data; | 258 | struct cx8802_dev *dev = (struct cx8802_dev*)data; |
243 | 259 | ||
244 | dprintk(1, "%s\n",__FUNCTION__); | 260 | dprintk(0, "%s\n",__FUNCTION__); |
245 | 261 | ||
246 | if (debug) | 262 | if (debug) |
247 | cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]); | 263 | cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]); |
@@ -254,12 +270,17 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev) | |||
254 | struct cx88_core *core = dev->core; | 270 | struct cx88_core *core = dev->core; |
255 | u32 status, mask, count; | 271 | u32 status, mask, count; |
256 | 272 | ||
273 | dprintk( 1, "cx8802_mpeg_irq\n" ); | ||
257 | status = cx_read(MO_TS_INTSTAT); | 274 | status = cx_read(MO_TS_INTSTAT); |
258 | mask = cx_read(MO_TS_INTMSK); | 275 | mask = cx_read(MO_TS_INTMSK); |
259 | if (0 == (status & mask)) | 276 | if (0 == (status & mask)) |
260 | return; | 277 | return; |
261 | 278 | ||
262 | cx_write(MO_TS_INTSTAT, status); | 279 | cx_write(MO_TS_INTSTAT, status); |
280 | #if 0 | ||
281 | cx88_print_irqbits(core->name, "irq mpeg ", | ||
282 | cx88_mpeg_irqs, status, mask); | ||
283 | #endif | ||
263 | if (debug || (status & mask & ~0xff)) | 284 | if (debug || (status & mask & ~0xff)) |
264 | cx88_print_irqbits(core->name, "irq mpeg ", | 285 | cx88_print_irqbits(core->name, "irq mpeg ", |
265 | cx88_mpeg_irqs, status, mask); | 286 | cx88_mpeg_irqs, status, mask); |
@@ -273,6 +294,7 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev) | |||
273 | 294 | ||
274 | /* risc1 y */ | 295 | /* risc1 y */ |
275 | if (status & 0x01) { | 296 | if (status & 0x01) { |
297 | dprintk( 1, "wake up\n" ); | ||
276 | spin_lock(&dev->slock); | 298 | spin_lock(&dev->slock); |
277 | count = cx_read(MO_TS_GPCNT); | 299 | count = cx_read(MO_TS_GPCNT); |
278 | cx88_wakeup(dev->core, &dev->mpegq, count); | 300 | cx88_wakeup(dev->core, &dev->mpegq, count); |
@@ -288,6 +310,7 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev) | |||
288 | 310 | ||
289 | /* other general errors */ | 311 | /* other general errors */ |
290 | if (status & 0x1f0100) { | 312 | if (status & 0x1f0100) { |
313 | dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 ); | ||
291 | spin_lock(&dev->slock); | 314 | spin_lock(&dev->slock); |
292 | cx8802_stop_dma(dev); | 315 | cx8802_stop_dma(dev); |
293 | cx8802_restart_queue(dev,&dev->mpegq); | 316 | cx8802_restart_queue(dev,&dev->mpegq); |
@@ -295,6 +318,8 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev) | |||
295 | } | 318 | } |
296 | } | 319 | } |
297 | 320 | ||
321 | #define MAX_IRQ_LOOP 10 | ||
322 | |||
298 | static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs) | 323 | static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs) |
299 | { | 324 | { |
300 | struct cx8802_dev *dev = dev_id; | 325 | struct cx8802_dev *dev = dev_id; |
@@ -302,10 +327,13 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
302 | u32 status; | 327 | u32 status; |
303 | int loop, handled = 0; | 328 | int loop, handled = 0; |
304 | 329 | ||
305 | for (loop = 0; loop < 10; loop++) { | 330 | for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { |
306 | status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04); | 331 | status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04); |
307 | if (0 == status) | 332 | if (0 == status) |
308 | goto out; | 333 | goto out; |
334 | dprintk( 1, "cx8802_irq\n" ); | ||
335 | dprintk( 1, " loop: %d/%d\n", loop, MAX_IRQ_LOOP ); | ||
336 | dprintk( 1, " status: %d\n", status ); | ||
309 | handled = 1; | 337 | handled = 1; |
310 | cx_write(MO_PCI_INTSTAT, status); | 338 | cx_write(MO_PCI_INTSTAT, status); |
311 | 339 | ||
@@ -314,7 +342,8 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
314 | if (status & 0x04) | 342 | if (status & 0x04) |
315 | cx8802_mpeg_irq(dev); | 343 | cx8802_mpeg_irq(dev); |
316 | }; | 344 | }; |
317 | if (10 == loop) { | 345 | if (MAX_IRQ_LOOP == loop) { |
346 | dprintk( 0, "clearing mask\n" ); | ||
318 | printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n", | 347 | printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n", |
319 | core->name); | 348 | core->name); |
320 | cx_write(MO_PCI_INTMSK,0); | 349 | cx_write(MO_PCI_INTMSK,0); |
@@ -378,6 +407,7 @@ int cx8802_init_common(struct cx8802_dev *dev) | |||
378 | 407 | ||
379 | void cx8802_fini_common(struct cx8802_dev *dev) | 408 | void cx8802_fini_common(struct cx8802_dev *dev) |
380 | { | 409 | { |
410 | dprintk( 2, "cx8802_fini_common\n" ); | ||
381 | cx8802_stop_dma(dev); | 411 | cx8802_stop_dma(dev); |
382 | pci_disable_device(dev->pci); | 412 | pci_disable_device(dev->pci); |
383 | 413 | ||
@@ -399,6 +429,7 @@ int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state) | |||
399 | /* stop mpeg dma */ | 429 | /* stop mpeg dma */ |
400 | spin_lock(&dev->slock); | 430 | spin_lock(&dev->slock); |
401 | if (!list_empty(&dev->mpegq.active)) { | 431 | if (!list_empty(&dev->mpegq.active)) { |
432 | dprintk( 2, "suspend\n" ); | ||
402 | printk("%s: suspend mpeg\n", core->name); | 433 | printk("%s: suspend mpeg\n", core->name); |
403 | cx8802_stop_dma(dev); | 434 | cx8802_stop_dma(dev); |
404 | del_timer(&dev->mpegq.timeout); | 435 | del_timer(&dev->mpegq.timeout); |
@@ -463,4 +494,5 @@ EXPORT_SYMBOL(cx8802_resume_common); | |||
463 | * Local variables: | 494 | * Local variables: |
464 | * c-basic-offset: 8 | 495 | * c-basic-offset: 8 |
465 | * End: | 496 | * End: |
497 | * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off | ||
466 | */ | 498 | */ |
diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h index 8638ce57d8..63ad33f581 100644 --- a/drivers/media/video/cx88/cx88-reg.h +++ b/drivers/media/video/cx88/cx88-reg.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | $Id: cx88-reg.h,v 1.6 2004/10/13 10:39:00 kraxel Exp $ | 2 | $Id: cx88-reg.h,v 1.7 2005/06/03 13:31:51 mchehab Exp $ |
3 | 3 | ||
4 | cx88x-hw.h - CX2388x register offsets | 4 | cx88x-hw.h - CX2388x register offsets |
5 | 5 | ||
@@ -397,6 +397,7 @@ | |||
397 | #define AUD_RATE_ADJ4 0x3205e4 | 397 | #define AUD_RATE_ADJ4 0x3205e4 |
398 | #define AUD_RATE_ADJ5 0x3205e8 | 398 | #define AUD_RATE_ADJ5 0x3205e8 |
399 | #define AUD_APB_IN_RATE_ADJ 0x3205ec | 399 | #define AUD_APB_IN_RATE_ADJ 0x3205ec |
400 | #define AUD_I2SCNTL 0x3205ec | ||
400 | #define AUD_PHASE_FIX_CTL 0x3205f0 | 401 | #define AUD_PHASE_FIX_CTL 0x3205f0 |
401 | #define AUD_PLL_PRESCALE 0x320600 | 402 | #define AUD_PLL_PRESCALE 0x320600 |
402 | #define AUD_PLL_DDS 0x320604 | 403 | #define AUD_PLL_DDS 0x320604 |
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index f2a9475a2f..46d78b1dc9 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | $Id: cx88-tvaudio.c,v 1.34 2005/03/07 16:10:51 kraxel Exp $ | 2 | $Id: cx88-tvaudio.c,v 1.36 2005/06/05 05:53:45 mchehab Exp $ |
3 | 3 | ||
4 | cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver | 4 | cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver |
5 | 5 | ||
@@ -127,7 +127,8 @@ static void set_audio_start(struct cx88_core *core, | |||
127 | cx_write(AUD_VOL_CTL, (1 << 6)); | 127 | cx_write(AUD_VOL_CTL, (1 << 6)); |
128 | 128 | ||
129 | // increase level of input by 12dB | 129 | // increase level of input by 12dB |
130 | cx_write(AUD_AFE_12DB_EN, 0x0001); | 130 | // cx_write(AUD_AFE_12DB_EN, 0x0001); |
131 | cx_write(AUD_AFE_12DB_EN, 0x0000); | ||
131 | 132 | ||
132 | // start programming | 133 | // start programming |
133 | cx_write(AUD_CTL, 0x0000); | 134 | cx_write(AUD_CTL, 0x0000); |
@@ -143,9 +144,15 @@ static void set_audio_finish(struct cx88_core *core) | |||
143 | u32 volume; | 144 | u32 volume; |
144 | 145 | ||
145 | if (cx88_boards[core->board].blackbird) { | 146 | if (cx88_boards[core->board].blackbird) { |
147 | // sets sound input from external adc | ||
148 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | ||
149 | //cx_write(AUD_I2SINPUTCNTL, 0); | ||
150 | cx_write(AUD_I2SINPUTCNTL, 4); | ||
151 | cx_write(AUD_BAUDRATE, 1); | ||
146 | // 'pass-thru mode': this enables the i2s output to the mpeg encoder | 152 | // 'pass-thru mode': this enables the i2s output to the mpeg encoder |
147 | cx_set(AUD_CTL, 0x2000); | 153 | cx_set(AUD_CTL, EN_I2SOUT_ENABLE); |
148 | cx_write(AUD_I2SOUTPUTCNTL, 1); | 154 | cx_write(AUD_I2SOUTPUTCNTL, 1); |
155 | cx_write(AUD_I2SCNTL, 0); | ||
149 | //cx_write(AUD_APB_IN_RATE_ADJ, 0); | 156 | //cx_write(AUD_APB_IN_RATE_ADJ, 0); |
150 | } | 157 | } |
151 | 158 | ||
@@ -707,50 +714,65 @@ static void set_audio_standard_EIAJ(struct cx88_core *core) | |||
707 | set_audio_finish(core); | 714 | set_audio_finish(core); |
708 | } | 715 | } |
709 | 716 | ||
710 | static void set_audio_standard_FM(struct cx88_core *core) | 717 | static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type deemph) |
711 | { | 718 | { |
712 | #if 0 /* FIXME */ | 719 | static const struct rlist fm_deemph_50[] = { |
713 | switch (dev->audio_properties.FM_deemphasis) | 720 | { AUD_DEEMPH0_G0, 0x0C45 }, |
714 | { | 721 | { AUD_DEEMPH0_A0, 0x6262 }, |
715 | case WW_FM_DEEMPH_50: | 722 | { AUD_DEEMPH0_B0, 0x1C29 }, |
716 | //Set De-emphasis filter coefficients for 50 usec | 723 | { AUD_DEEMPH0_A1, 0x3FC66}, |
717 | cx_write(AUD_DEEMPH0_G0, 0x0C45); | 724 | { AUD_DEEMPH0_B1, 0x399A }, |
718 | cx_write(AUD_DEEMPH0_A0, 0x6262); | 725 | |
719 | cx_write(AUD_DEEMPH0_B0, 0x1C29); | 726 | { AUD_DEEMPH1_G0, 0x0D80 }, |
720 | cx_write(AUD_DEEMPH0_A1, 0x3FC66); | 727 | { AUD_DEEMPH1_A0, 0x6262 }, |
721 | cx_write(AUD_DEEMPH0_B1, 0x399A); | 728 | { AUD_DEEMPH1_B0, 0x1C29 }, |
722 | 729 | { AUD_DEEMPH1_A1, 0x3FC66}, | |
723 | cx_write(AUD_DEEMPH1_G0, 0x0D80); | 730 | { AUD_DEEMPH1_B1, 0x399A}, |
724 | cx_write(AUD_DEEMPH1_A0, 0x6262); | 731 | |
725 | cx_write(AUD_DEEMPH1_B0, 0x1C29); | 732 | { AUD_POLYPH80SCALEFAC, 0x0003}, |
726 | cx_write(AUD_DEEMPH1_A1, 0x3FC66); | 733 | { /* end of list */ }, |
727 | cx_write(AUD_DEEMPH1_B1, 0x399A); | 734 | }; |
735 | static const struct rlist fm_deemph_75[] = { | ||
736 | { AUD_DEEMPH0_G0, 0x091B }, | ||
737 | { AUD_DEEMPH0_A0, 0x6B68 }, | ||
738 | { AUD_DEEMPH0_B0, 0x11EC }, | ||
739 | { AUD_DEEMPH0_A1, 0x3FC66}, | ||
740 | { AUD_DEEMPH0_B1, 0x399A }, | ||
741 | |||
742 | { AUD_DEEMPH1_G0, 0x0AA0 }, | ||
743 | { AUD_DEEMPH1_A0, 0x6B68 }, | ||
744 | { AUD_DEEMPH1_B0, 0x11EC }, | ||
745 | { AUD_DEEMPH1_A1, 0x3FC66}, | ||
746 | { AUD_DEEMPH1_B1, 0x399A}, | ||
747 | |||
748 | { AUD_POLYPH80SCALEFAC, 0x0003}, | ||
749 | { /* end of list */ }, | ||
750 | }; | ||
728 | 751 | ||
729 | break; | 752 | /* It is enough to leave default values? */ |
753 | static const struct rlist fm_no_deemph[] = { | ||
730 | 754 | ||
731 | case WW_FM_DEEMPH_75: | 755 | { AUD_POLYPH80SCALEFAC, 0x0003}, |
732 | //Set De-emphasis filter coefficients for 75 usec | 756 | { /* end of list */ }, |
733 | cx_write(AUD_DEEMPH0_G0, 0x91B ); | 757 | }; |
734 | cx_write(AUD_DEEMPH0_A0, 0x6B68); | ||
735 | cx_write(AUD_DEEMPH0_B0, 0x11EC); | ||
736 | cx_write(AUD_DEEMPH0_A1, 0x3FC66); | ||
737 | cx_write(AUD_DEEMPH0_B1, 0x399A); | ||
738 | 758 | ||
739 | cx_write(AUD_DEEMPH1_G0, 0xAA0 ); | 759 | dprintk("%s (status: unknown)\n",__FUNCTION__); |
740 | cx_write(AUD_DEEMPH1_A0, 0x6B68); | 760 | set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO); |
741 | cx_write(AUD_DEEMPH1_B0, 0x11EC); | ||
742 | cx_write(AUD_DEEMPH1_A1, 0x3FC66); | ||
743 | cx_write(AUD_DEEMPH1_B1, 0x399A); | ||
744 | 761 | ||
762 | switch (deemph) | ||
763 | { | ||
764 | case FM_NO_DEEMPH: | ||
765 | set_audio_registers(core, fm_no_deemph); | ||
745 | break; | 766 | break; |
746 | } | ||
747 | #endif | ||
748 | 767 | ||
749 | dprintk("%s (status: unknown)\n",__FUNCTION__); | 768 | case FM_DEEMPH_50: |
750 | set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO); | 769 | set_audio_registers(core, fm_deemph_50); |
770 | break; | ||
751 | 771 | ||
752 | // AB: 10/2/01: this register is not being reset appropriately on occasion. | 772 | case FM_DEEMPH_75: |
753 | cx_write(AUD_POLYPH80SCALEFAC,3); | 773 | set_audio_registers(core, fm_deemph_75); |
774 | break; | ||
775 | } | ||
754 | 776 | ||
755 | set_audio_finish(core); | 777 | set_audio_finish(core); |
756 | } | 778 | } |
@@ -778,7 +800,7 @@ void cx88_set_tvaudio(struct cx88_core *core) | |||
778 | set_audio_standard_EIAJ(core); | 800 | set_audio_standard_EIAJ(core); |
779 | break; | 801 | break; |
780 | case WW_FM: | 802 | case WW_FM: |
781 | set_audio_standard_FM(core); | 803 | set_audio_standard_FM(core,FM_NO_DEEMPH); |
782 | break; | 804 | break; |
783 | case WW_SYSTEM_L_AM: | 805 | case WW_SYSTEM_L_AM: |
784 | set_audio_standard_NICAM_L(core, 1); | 806 | set_audio_standard_NICAM_L(core, 1); |
@@ -1029,4 +1051,5 @@ EXPORT_SYMBOL(cx88_audio_thread); | |||
1029 | * Local variables: | 1051 | * Local variables: |
1030 | * c-basic-offset: 8 | 1052 | * c-basic-offset: 8 |
1031 | * End: | 1053 | * End: |
1054 | * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off | ||
1032 | */ | 1055 | */ |
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index 0584ff4763..320d57888b 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: cx88-vbi.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $ | 2 | * $Id: cx88-vbi.c,v 1.17 2005/06/12 04:19:19 mchehab Exp $ |
3 | */ | 3 | */ |
4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
@@ -47,8 +47,8 @@ void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f) | |||
47 | } | 47 | } |
48 | 48 | ||
49 | static int cx8800_start_vbi_dma(struct cx8800_dev *dev, | 49 | static int cx8800_start_vbi_dma(struct cx8800_dev *dev, |
50 | struct cx88_dmaqueue *q, | 50 | struct cx88_dmaqueue *q, |
51 | struct cx88_buffer *buf) | 51 | struct cx88_buffer *buf) |
52 | { | 52 | { |
53 | struct cx88_core *core = dev->core; | 53 | struct cx88_core *core = dev->core; |
54 | 54 | ||
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index d1f5c92f0c..e4ca7350df 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: cx88-video.c,v 1.58 2005/03/07 15:58:05 kraxel Exp $ | 2 | * $Id: cx88-video.c,v 1.63 2005/06/12 04:19:19 mchehab Exp $ |
3 | * | 3 | * |
4 | * device driver for Conexant 2388x based TV cards | 4 | * device driver for Conexant 2388x based TV cards |
5 | * video4linux video interface | 5 | * video4linux video interface |
@@ -1187,9 +1187,24 @@ static void init_controls(struct cx8800_dev *dev) | |||
1187 | .id = V4L2_CID_AUDIO_VOLUME, | 1187 | .id = V4L2_CID_AUDIO_VOLUME, |
1188 | .value = 0x3f, | 1188 | .value = 0x3f, |
1189 | }; | 1189 | }; |
1190 | static struct v4l2_control hue = { | ||
1191 | .id = V4L2_CID_HUE, | ||
1192 | .value = 0x80, | ||
1193 | }; | ||
1194 | static struct v4l2_control contrast = { | ||
1195 | .id = V4L2_CID_CONTRAST, | ||
1196 | .value = 0x80, | ||
1197 | }; | ||
1198 | static struct v4l2_control brightness = { | ||
1199 | .id = V4L2_CID_BRIGHTNESS, | ||
1200 | .value = 0x80, | ||
1201 | }; | ||
1190 | 1202 | ||
1191 | set_control(dev,&mute); | 1203 | set_control(dev,&mute); |
1192 | set_control(dev,&volume); | 1204 | set_control(dev,&volume); |
1205 | set_control(dev,&hue); | ||
1206 | set_control(dev,&contrast); | ||
1207 | set_control(dev,&brightness); | ||
1193 | } | 1208 | } |
1194 | 1209 | ||
1195 | /* ------------------------------------------------------------------ */ | 1210 | /* ------------------------------------------------------------------ */ |
@@ -1336,6 +1351,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file, | |||
1336 | V4L2_CAP_STREAMING | | 1351 | V4L2_CAP_STREAMING | |
1337 | V4L2_CAP_VBI_CAPTURE | | 1352 | V4L2_CAP_VBI_CAPTURE | |
1338 | #if 0 | 1353 | #if 0 |
1354 | V4L2_TUNER_CAP_LOW | | ||
1355 | #endif | ||
1356 | #if 0 | ||
1339 | V4L2_CAP_VIDEO_OVERLAY | | 1357 | V4L2_CAP_VIDEO_OVERLAY | |
1340 | #endif | 1358 | #endif |
1341 | 0; | 1359 | 0; |
@@ -1696,7 +1714,11 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, | |||
1696 | sizeof(cap->card)); | 1714 | sizeof(cap->card)); |
1697 | sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); | 1715 | sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); |
1698 | cap->version = CX88_VERSION_CODE; | 1716 | cap->version = CX88_VERSION_CODE; |
1699 | cap->capabilities = V4L2_CAP_TUNER; | 1717 | cap->capabilities = V4L2_CAP_TUNER |
1718 | #if 0 | ||
1719 | | V4L2_TUNER_CAP_LOW | ||
1720 | #endif | ||
1721 | ; | ||
1700 | return 0; | 1722 | return 0; |
1701 | } | 1723 | } |
1702 | case VIDIOC_G_TUNER: | 1724 | case VIDIOC_G_TUNER: |
@@ -1992,6 +2014,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1992 | { | 2014 | { |
1993 | struct cx8800_dev *dev; | 2015 | struct cx8800_dev *dev; |
1994 | struct cx88_core *core; | 2016 | struct cx88_core *core; |
2017 | struct tuner_addr tun_addr; | ||
1995 | int err; | 2018 | int err; |
1996 | 2019 | ||
1997 | dev = kmalloc(sizeof(*dev),GFP_KERNEL); | 2020 | dev = kmalloc(sizeof(*dev),GFP_KERNEL); |
@@ -2065,8 +2088,19 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
2065 | request_module("tuner"); | 2088 | request_module("tuner"); |
2066 | if (core->tda9887_conf) | 2089 | if (core->tda9887_conf) |
2067 | request_module("tda9887"); | 2090 | request_module("tda9887"); |
2068 | if (core->tuner_type != UNSET) | 2091 | if (core->radio_type != UNSET) { |
2069 | cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE,&core->tuner_type); | 2092 | tun_addr.v4l2_tuner = V4L2_TUNER_RADIO; |
2093 | tun_addr.type = core->radio_type; | ||
2094 | tun_addr.addr = core->radio_addr; | ||
2095 | cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE_ADDR, &tun_addr); | ||
2096 | } | ||
2097 | if (core->tuner_type != UNSET) { | ||
2098 | tun_addr.v4l2_tuner = V4L2_TUNER_ANALOG_TV; | ||
2099 | tun_addr.type = core->tuner_type; | ||
2100 | tun_addr.addr = core->tuner_addr; | ||
2101 | cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE_ADDR, &tun_addr); | ||
2102 | } | ||
2103 | |||
2070 | if (core->tda9887_conf) | 2104 | if (core->tda9887_conf) |
2071 | cx88_call_i2c_clients(dev->core,TDA9887_SET_CONFIG,&core->tda9887_conf); | 2105 | cx88_call_i2c_clients(dev->core,TDA9887_SET_CONFIG,&core->tda9887_conf); |
2072 | 2106 | ||
@@ -2162,7 +2196,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev) | |||
2162 | 2196 | ||
2163 | static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) | 2197 | static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) |
2164 | { | 2198 | { |
2165 | struct cx8800_dev *dev = pci_get_drvdata(pci_dev); | 2199 | struct cx8800_dev *dev = pci_get_drvdata(pci_dev); |
2166 | struct cx88_core *core = dev->core; | 2200 | struct cx88_core *core = dev->core; |
2167 | 2201 | ||
2168 | /* stop video+vbi capture */ | 2202 | /* stop video+vbi capture */ |
@@ -2194,7 +2228,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) | |||
2194 | 2228 | ||
2195 | static int cx8800_resume(struct pci_dev *pci_dev) | 2229 | static int cx8800_resume(struct pci_dev *pci_dev) |
2196 | { | 2230 | { |
2197 | struct cx8800_dev *dev = pci_get_drvdata(pci_dev); | 2231 | struct cx8800_dev *dev = pci_get_drvdata(pci_dev); |
2198 | struct cx88_core *core = dev->core; | 2232 | struct cx88_core *core = dev->core; |
2199 | 2233 | ||
2200 | if (dev->state.disabled) { | 2234 | if (dev->state.disabled) { |
@@ -2230,8 +2264,8 @@ static struct pci_device_id cx8800_pci_tbl[] = { | |||
2230 | { | 2264 | { |
2231 | .vendor = 0x14f1, | 2265 | .vendor = 0x14f1, |
2232 | .device = 0x8800, | 2266 | .device = 0x8800, |
2233 | .subvendor = PCI_ANY_ID, | 2267 | .subvendor = PCI_ANY_ID, |
2234 | .subdevice = PCI_ANY_ID, | 2268 | .subdevice = PCI_ANY_ID, |
2235 | },{ | 2269 | },{ |
2236 | /* --- end of list --- */ | 2270 | /* --- end of list --- */ |
2237 | } | 2271 | } |
@@ -2239,10 +2273,10 @@ static struct pci_device_id cx8800_pci_tbl[] = { | |||
2239 | MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl); | 2273 | MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl); |
2240 | 2274 | ||
2241 | static struct pci_driver cx8800_pci_driver = { | 2275 | static struct pci_driver cx8800_pci_driver = { |
2242 | .name = "cx8800", | 2276 | .name = "cx8800", |
2243 | .id_table = cx8800_pci_tbl, | 2277 | .id_table = cx8800_pci_tbl, |
2244 | .probe = cx8800_initdev, | 2278 | .probe = cx8800_initdev, |
2245 | .remove = __devexit_p(cx8800_finidev), | 2279 | .remove = __devexit_p(cx8800_finidev), |
2246 | 2280 | ||
2247 | .suspend = cx8800_suspend, | 2281 | .suspend = cx8800_suspend, |
2248 | .resume = cx8800_resume, | 2282 | .resume = cx8800_resume, |
@@ -2274,4 +2308,5 @@ module_exit(cx8800_fini); | |||
2274 | * Local variables: | 2308 | * Local variables: |
2275 | * c-basic-offset: 8 | 2309 | * c-basic-offset: 8 |
2276 | * End: | 2310 | * End: |
2311 | * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off | ||
2277 | */ | 2312 | */ |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 88eaaaba5a..ac0dc27bb3 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: cx88.h,v 1.56 2005/03/04 09:12:23 kraxel Exp $ | 2 | * $Id: cx88.h,v 1.62 2005/06/12 04:19:19 mchehab Exp $ |
3 | * | 3 | * |
4 | * v4l2 device driver for cx2388x based TV cards | 4 | * v4l2 device driver for cx2388x based TV cards |
5 | * | 5 | * |
@@ -64,6 +64,13 @@ | |||
64 | #define SHADOW_AUD_BAL_CTL 2 | 64 | #define SHADOW_AUD_BAL_CTL 2 |
65 | #define SHADOW_MAX 2 | 65 | #define SHADOW_MAX 2 |
66 | 66 | ||
67 | /* FM Radio deemphasis type */ | ||
68 | enum cx88_deemph_type { | ||
69 | FM_NO_DEEMPH = 0, | ||
70 | FM_DEEMPH_50, | ||
71 | FM_DEEMPH_75 | ||
72 | }; | ||
73 | |||
67 | /* ----------------------------------------------------------- */ | 74 | /* ----------------------------------------------------------- */ |
68 | /* tv norms */ | 75 | /* tv norms */ |
69 | 76 | ||
@@ -162,6 +169,8 @@ extern struct sram_channel cx88_sram_channels[]; | |||
162 | #define CX88_BOARD_HAUPPAUGE_ROSLYN 24 | 169 | #define CX88_BOARD_HAUPPAUGE_ROSLYN 24 |
163 | #define CX88_BOARD_DIGITALLOGIC_MEC 25 | 170 | #define CX88_BOARD_DIGITALLOGIC_MEC 25 |
164 | #define CX88_BOARD_IODATA_GVBCTV7E 26 | 171 | #define CX88_BOARD_IODATA_GVBCTV7E 26 |
172 | #define CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO 27 | ||
173 | #define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28 | ||
165 | 174 | ||
166 | enum cx88_itype { | 175 | enum cx88_itype { |
167 | CX88_VMUX_COMPOSITE1 = 1, | 176 | CX88_VMUX_COMPOSITE1 = 1, |
@@ -185,6 +194,9 @@ struct cx88_input { | |||
185 | struct cx88_board { | 194 | struct cx88_board { |
186 | char *name; | 195 | char *name; |
187 | unsigned int tuner_type; | 196 | unsigned int tuner_type; |
197 | unsigned int radio_type; | ||
198 | unsigned char tuner_addr; | ||
199 | unsigned char radio_addr; | ||
188 | int tda9887_conf; | 200 | int tda9887_conf; |
189 | struct cx88_input input[8]; | 201 | struct cx88_input input[8]; |
190 | struct cx88_input radio; | 202 | struct cx88_input radio; |
@@ -255,6 +267,9 @@ struct cx88_core { | |||
255 | /* config info -- analog */ | 267 | /* config info -- analog */ |
256 | unsigned int board; | 268 | unsigned int board; |
257 | unsigned int tuner_type; | 269 | unsigned int tuner_type; |
270 | unsigned int radio_type; | ||
271 | unsigned char tuner_addr; | ||
272 | unsigned char radio_addr; | ||
258 | unsigned int tda9887_conf; | 273 | unsigned int tda9887_conf; |
259 | unsigned int has_radio; | 274 | unsigned int has_radio; |
260 | 275 | ||
@@ -420,6 +435,7 @@ struct cx8802_dev { | |||
420 | /* ----------------------------------------------------------- */ | 435 | /* ----------------------------------------------------------- */ |
421 | /* cx88-core.c */ | 436 | /* cx88-core.c */ |
422 | 437 | ||
438 | extern char *cx88_pci_irqs[32]; | ||
423 | extern char *cx88_vid_irqs[32]; | 439 | extern char *cx88_vid_irqs[32]; |
424 | extern char *cx88_mpeg_irqs[32]; | 440 | extern char *cx88_mpeg_irqs[32]; |
425 | extern void cx88_print_irqbits(char *name, char *tag, char **strings, | 441 | extern void cx88_print_irqbits(char *name, char *tag, char **strings, |
@@ -471,6 +487,11 @@ extern void cx88_core_put(struct cx88_core *core, | |||
471 | /* cx88-vbi.c */ | 487 | /* cx88-vbi.c */ |
472 | 488 | ||
473 | void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f); | 489 | void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f); |
490 | /* | ||
491 | int cx8800_start_vbi_dma(struct cx8800_dev *dev, | ||
492 | struct cx88_dmaqueue *q, | ||
493 | struct cx88_buffer *buf); | ||
494 | */ | ||
474 | int cx8800_stop_vbi_dma(struct cx8800_dev *dev); | 495 | int cx8800_stop_vbi_dma(struct cx8800_dev *dev); |
475 | int cx8800_restart_vbi_queue(struct cx8800_dev *dev, | 496 | int cx8800_restart_vbi_queue(struct cx8800_dev *dev, |
476 | struct cx88_dmaqueue *q); | 497 | struct cx88_dmaqueue *q); |
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index ab6620de4b..a565823330 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: ir-kbd-gpio.c,v 1.12 2005/02/22 12:28:40 kraxel Exp $ | 2 | * $Id: ir-kbd-gpio.c,v 1.13 2005/05/15 19:01:26 mchehab Exp $ |
3 | * | 3 | * |
4 | * Copyright (c) 2003 Gerd Knorr | 4 | * Copyright (c) 2003 Gerd Knorr |
5 | * Copyright (c) 2003 Pavel Machek | 5 | * Copyright (c) 2003 Pavel Machek |
@@ -114,38 +114,6 @@ static IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = { | |||
114 | [ 0x3e ] = KEY_VOLUMEUP, // 'volume +' | 114 | [ 0x3e ] = KEY_VOLUMEUP, // 'volume +' |
115 | }; | 115 | }; |
116 | 116 | ||
117 | static IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { | ||
118 | [ 2 ] = KEY_KP0, | ||
119 | [ 1 ] = KEY_KP1, | ||
120 | [ 11 ] = KEY_KP2, | ||
121 | [ 27 ] = KEY_KP3, | ||
122 | [ 5 ] = KEY_KP4, | ||
123 | [ 9 ] = KEY_KP5, | ||
124 | [ 21 ] = KEY_KP6, | ||
125 | [ 6 ] = KEY_KP7, | ||
126 | [ 10 ] = KEY_KP8, | ||
127 | [ 18 ] = KEY_KP9, | ||
128 | |||
129 | [ 3 ] = KEY_TUNER, // TV/FM | ||
130 | [ 7 ] = KEY_SEARCH, // scan | ||
131 | [ 28 ] = KEY_ZOOM, // full screen | ||
132 | [ 30 ] = KEY_POWER, | ||
133 | [ 23 ] = KEY_VOLUMEDOWN, | ||
134 | [ 31 ] = KEY_VOLUMEUP, | ||
135 | [ 20 ] = KEY_CHANNELDOWN, | ||
136 | [ 22 ] = KEY_CHANNELUP, | ||
137 | [ 24 ] = KEY_MUTE, | ||
138 | |||
139 | [ 0 ] = KEY_LIST, // source | ||
140 | [ 19 ] = KEY_INFO, // loop | ||
141 | [ 16 ] = KEY_LAST, // +100 | ||
142 | [ 13 ] = KEY_CLEAR, // reset | ||
143 | [ 12 ] = BTN_RIGHT, // fun++ | ||
144 | [ 4 ] = BTN_LEFT, // fun-- | ||
145 | [ 14 ] = KEY_GOTO, // function | ||
146 | [ 15 ] = KEY_STOP, // freeze | ||
147 | }; | ||
148 | |||
149 | /* Attila Kondoros <attila.kondoros@chello.hu> */ | 117 | /* Attila Kondoros <attila.kondoros@chello.hu> */ |
150 | static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { | 118 | static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { |
151 | 119 | ||
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 09464d624a..1b7d38e96f 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c | |||
@@ -735,7 +735,6 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout) | |||
735 | { | 735 | { |
736 | DECLARE_WAITQUEUE(wait, current); | 736 | DECLARE_WAITQUEUE(wait, current); |
737 | 737 | ||
738 | again: | ||
739 | add_wait_queue(&msp->wq, &wait); | 738 | add_wait_queue(&msp->wq, &wait); |
740 | if (!kthread_should_stop()) { | 739 | if (!kthread_should_stop()) { |
741 | if (timeout < 0) { | 740 | if (timeout < 0) { |
@@ -751,12 +750,9 @@ again: | |||
751 | #endif | 750 | #endif |
752 | } | 751 | } |
753 | } | 752 | } |
754 | 753 | if (current->flags & PF_FREEZE) | |
754 | refrigerator(PF_FREEZE); | ||
755 | remove_wait_queue(&msp->wq, &wait); | 755 | remove_wait_queue(&msp->wq, &wait); |
756 | |||
757 | if (try_to_freeze(PF_FREEZE)) | ||
758 | goto again; | ||
759 | |||
760 | return msp->restart; | 756 | return msp->restart; |
761 | } | 757 | } |
762 | 758 | ||
@@ -1436,7 +1432,7 @@ static int msp_detach(struct i2c_client *client); | |||
1436 | static int msp_probe(struct i2c_adapter *adap); | 1432 | static int msp_probe(struct i2c_adapter *adap); |
1437 | static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg); | 1433 | static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg); |
1438 | 1434 | ||
1439 | static int msp_suspend(struct device * dev, pm_message_t state, u32 level); | 1435 | static int msp_suspend(struct device * dev, u32 state, u32 level); |
1440 | static int msp_resume(struct device * dev, u32 level); | 1436 | static int msp_resume(struct device * dev, u32 level); |
1441 | 1437 | ||
1442 | static void msp_wake_thread(struct i2c_client *client); | 1438 | static void msp_wake_thread(struct i2c_client *client); |
@@ -1841,7 +1837,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
1841 | return 0; | 1837 | return 0; |
1842 | } | 1838 | } |
1843 | 1839 | ||
1844 | static int msp_suspend(struct device * dev, pm_message_t state, u32 level) | 1840 | static int msp_suspend(struct device * dev, u32 state, u32 level) |
1845 | { | 1841 | { |
1846 | struct i2c_client *c = container_of(dev, struct i2c_client, dev); | 1842 | struct i2c_client *c = container_of(dev, struct i2c_client, dev); |
1847 | 1843 | ||
diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index d70a954e13..023f33056a 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h | |||
@@ -1,3 +1,7 @@ | |||
1 | /* | ||
2 | * $Id: msp3400.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $ | ||
3 | */ | ||
4 | |||
1 | #ifndef MSP3400_H | 5 | #ifndef MSP3400_H |
2 | #define MSP3400_H | 6 | #define MSP3400_H |
3 | 7 | ||
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 42c2b565c9..e6d0a18833 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c | |||
@@ -41,16 +41,16 @@ enum saa6752hs_videoformat { | |||
41 | 41 | ||
42 | static const struct v4l2_format v4l2_format_table[] = | 42 | static const struct v4l2_format v4l2_format_table[] = |
43 | { | 43 | { |
44 | [SAA6752HS_VF_D1] = { | 44 | [SAA6752HS_VF_D1] = |
45 | .fmt = { .pix = { .width = 720, .height = 576 }, }, }, | 45 | { .fmt = { .pix = { .width = 720, .height = 576 }}}, |
46 | [SAA6752HS_VF_2_3_D1] = { | 46 | [SAA6752HS_VF_2_3_D1] = |
47 | .fmt = { .pix = { .width = 480, .height = 576 }, }, }, | 47 | { .fmt = { .pix = { .width = 480, .height = 576 }}}, |
48 | [SAA6752HS_VF_1_2_D1] = { | 48 | [SAA6752HS_VF_1_2_D1] = |
49 | .fmt = { .pix = { .width = 352, .height = 576 }, }, }, | 49 | { .fmt = { .pix = { .width = 352, .height = 576 }}}, |
50 | [SAA6752HS_VF_SIF] = { | 50 | [SAA6752HS_VF_SIF] = |
51 | .fmt = { .pix = { .width = 352, .height = 288 }, }, }, | 51 | { .fmt = { .pix = { .width = 352, .height = 288 }}}, |
52 | [SAA6752HS_VF_UNKNOWN] = { | 52 | [SAA6752HS_VF_UNKNOWN] = |
53 | .fmt = { .pix = { .width = 0, .height = 0 }, }, }, | 53 | { .fmt = { .pix = { .width = 0, .height = 0}}}, |
54 | }; | 54 | }; |
55 | 55 | ||
56 | struct saa6752hs_state { | 56 | struct saa6752hs_state { |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index c51eb7f078..0c781e24c4 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -1,6 +1,6 @@ | |||
1 | 1 | ||
2 | /* | 2 | /* |
3 | * $Id: saa7134-cards.c,v 1.54 2005/03/07 12:01:51 kraxel Exp $ | 3 | * $Id: saa7134-cards.c,v 1.58 2005/06/07 18:05:00 nsh Exp $ |
4 | * | 4 | * |
5 | * device driver for philips saa7134 based TV cards | 5 | * device driver for philips saa7134 based TV cards |
6 | * card-specific stuff. | 6 | * card-specific stuff. |
@@ -165,7 +165,7 @@ struct saa7134_board saa7134_boards[] = { | |||
165 | .inputs = {{ | 165 | .inputs = {{ |
166 | .name = name_tv, | 166 | .name = name_tv, |
167 | .vmux = 1, | 167 | .vmux = 1, |
168 | .amux = LINE2, | 168 | .amux = TV, |
169 | .tv = 1, | 169 | .tv = 1, |
170 | },{ | 170 | },{ |
171 | .name = name_comp1, | 171 | .name = name_comp1, |
@@ -878,7 +878,7 @@ struct saa7134_board saa7134_boards[] = { | |||
878 | }, | 878 | }, |
879 | [SAA7134_BOARD_MANLI_MTV002] = { | 879 | [SAA7134_BOARD_MANLI_MTV002] = { |
880 | /* Ognjen Nastic <ognjen@logosoft.ba> */ | 880 | /* Ognjen Nastic <ognjen@logosoft.ba> */ |
881 | .name = "Manli MuchTV M-TV002", | 881 | .name = "Manli MuchTV M-TV002/Behold TV 403 FM", |
882 | .audio_clock = 0x00200000, | 882 | .audio_clock = 0x00200000, |
883 | .tuner_type = TUNER_PHILIPS_PAL, | 883 | .tuner_type = TUNER_PHILIPS_PAL, |
884 | .inputs = {{ | 884 | .inputs = {{ |
@@ -899,14 +899,10 @@ struct saa7134_board saa7134_boards[] = { | |||
899 | .name = name_radio, | 899 | .name = name_radio, |
900 | .amux = LINE2, | 900 | .amux = LINE2, |
901 | }, | 901 | }, |
902 | .mute = { | ||
903 | .name = name_mute, | ||
904 | .amux = LINE1, | ||
905 | }, | ||
906 | }, | 902 | }, |
907 | [SAA7134_BOARD_MANLI_MTV001] = { | 903 | [SAA7134_BOARD_MANLI_MTV001] = { |
908 | /* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */ | 904 | /* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */ |
909 | .name = "Manli MuchTV M-TV001", | 905 | .name = "Manli MuchTV M-TV001/Behold TV 401", |
910 | .audio_clock = 0x00200000, | 906 | .audio_clock = 0x00200000, |
911 | .tuner_type = TUNER_PHILIPS_PAL, | 907 | .tuner_type = TUNER_PHILIPS_PAL, |
912 | .inputs = {{ | 908 | .inputs = {{ |
@@ -923,6 +919,10 @@ struct saa7134_board saa7134_boards[] = { | |||
923 | .amux = LINE2, | 919 | .amux = LINE2, |
924 | .tv = 1, | 920 | .tv = 1, |
925 | }}, | 921 | }}, |
922 | .mute = { | ||
923 | .name = name_mute, | ||
924 | .amux = LINE1, | ||
925 | }, | ||
926 | }, | 926 | }, |
927 | [SAA7134_BOARD_TG3000TV] = { | 927 | [SAA7134_BOARD_TG3000TV] = { |
928 | /* TransGear 3000TV */ | 928 | /* TransGear 3000TV */ |
@@ -1078,7 +1078,6 @@ struct saa7134_board saa7134_boards[] = { | |||
1078 | .audio_clock = 0x00187de7, | 1078 | .audio_clock = 0x00187de7, |
1079 | .tuner_type = TUNER_PHILIPS_FM1256_IH3, | 1079 | .tuner_type = TUNER_PHILIPS_FM1256_IH3, |
1080 | .tda9887_conf = TDA9887_PRESENT, | 1080 | .tda9887_conf = TDA9887_PRESENT, |
1081 | .gpiomask = 0x3, | ||
1082 | .inputs = {{ | 1081 | .inputs = {{ |
1083 | .name = name_tv, | 1082 | .name = name_tv, |
1084 | .vmux = 1, | 1083 | .vmux = 1, |
@@ -1285,7 +1284,7 @@ struct saa7134_board saa7134_boards[] = { | |||
1285 | .gpio =0x8000, | 1284 | .gpio =0x8000, |
1286 | } | 1285 | } |
1287 | }, | 1286 | }, |
1288 | [SAA7134_BOARD_AVERMEDIA_307] = { | 1287 | [SAA7134_BOARD_AVERMEDIA_STUDIO_307] = { |
1289 | /* | 1288 | /* |
1290 | Nickolay V. Shmyrev <nshmyrev@yandex.ru> | 1289 | Nickolay V. Shmyrev <nshmyrev@yandex.ru> |
1291 | Lots of thanks to Andrey Zolotarev <zolotarev_andrey@mail.ru> | 1290 | Lots of thanks to Andrey Zolotarev <zolotarev_andrey@mail.ru> |
@@ -1323,6 +1322,35 @@ struct saa7134_board saa7134_boards[] = { | |||
1323 | .gpio = 0x01, | 1322 | .gpio = 0x01, |
1324 | }, | 1323 | }, |
1325 | }, | 1324 | }, |
1325 | [SAA7134_BOARD_AVERMEDIA_GO_007_FM] = { | ||
1326 | .name = "Avermedia AVerTV GO 007 FM", | ||
1327 | .audio_clock = 0x00187de7, | ||
1328 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
1329 | .gpiomask = 0x00300003, | ||
1330 | // .gpiomask = 0x8c240003, | ||
1331 | .inputs = {{ | ||
1332 | .name = name_tv, | ||
1333 | .vmux = 1, | ||
1334 | .amux = TV, | ||
1335 | .tv = 1, | ||
1336 | .gpio = 0x01, | ||
1337 | },{ | ||
1338 | .name = name_comp1, | ||
1339 | .vmux = 0, | ||
1340 | .amux = LINE2, | ||
1341 | .gpio = 0x02, | ||
1342 | },{ | ||
1343 | .name = name_svideo, | ||
1344 | .vmux = 6, | ||
1345 | .amux = LINE2, | ||
1346 | .gpio = 0x02, | ||
1347 | }}, | ||
1348 | .radio = { | ||
1349 | .name = name_radio, | ||
1350 | .amux = LINE1, | ||
1351 | .gpio = 0x00300001, | ||
1352 | }, | ||
1353 | }, | ||
1326 | [SAA7134_BOARD_AVERMEDIA_CARDBUS] = { | 1354 | [SAA7134_BOARD_AVERMEDIA_CARDBUS] = { |
1327 | /* Jon Westgate <oryn@oryn.fsck.tv> */ | 1355 | /* Jon Westgate <oryn@oryn.fsck.tv> */ |
1328 | .name = "AVerMedia Cardbus TV/Radio", | 1356 | .name = "AVerMedia Cardbus TV/Radio", |
@@ -1492,7 +1520,6 @@ struct saa7134_board saa7134_boards[] = { | |||
1492 | .audio_clock = 0x00187de7, | 1520 | .audio_clock = 0x00187de7, |
1493 | .tuner_type = TUNER_PHILIPS_FQ1216ME, | 1521 | .tuner_type = TUNER_PHILIPS_FQ1216ME, |
1494 | .tda9887_conf = TDA9887_PRESENT, | 1522 | .tda9887_conf = TDA9887_PRESENT, |
1495 | .gpiomask = 0x3, | ||
1496 | .inputs = {{ | 1523 | .inputs = {{ |
1497 | .name = name_tv, | 1524 | .name = name_tv, |
1498 | .vmux = 1, | 1525 | .vmux = 1, |
@@ -1546,7 +1573,82 @@ struct saa7134_board saa7134_boards[] = { | |||
1546 | // .gpio = 0x4000, | 1573 | // .gpio = 0x4000, |
1547 | }}, | 1574 | }}, |
1548 | }, | 1575 | }, |
1549 | }; | 1576 | [SAA7134_BOARD_AVERMEDIA_307] = { |
1577 | /* | ||
1578 | Davydov Vladimir <vladimir@iqmedia.com> | ||
1579 | */ | ||
1580 | .name = "Avermedia AVerTV 307", | ||
1581 | .audio_clock = 0x00187de7, | ||
1582 | .tuner_type = TUNER_PHILIPS_FQ1216ME, | ||
1583 | .tda9887_conf = TDA9887_PRESENT, | ||
1584 | .inputs = {{ | ||
1585 | .name = name_tv, | ||
1586 | .vmux = 1, | ||
1587 | .amux = TV, | ||
1588 | .tv = 1, | ||
1589 | },{ | ||
1590 | .name = name_comp1, | ||
1591 | .vmux = 0, | ||
1592 | .amux = LINE1, | ||
1593 | },{ | ||
1594 | .name = name_comp2, | ||
1595 | .vmux = 3, | ||
1596 | .amux = LINE1, | ||
1597 | },{ | ||
1598 | .name = name_svideo, | ||
1599 | .vmux = 8, | ||
1600 | .amux = LINE1, | ||
1601 | }}, | ||
1602 | }, | ||
1603 | [SAA7134_BOARD_ADS_INSTANT_TV] = { | ||
1604 | .name = "ADS Tech Instant TV (saa7135)", | ||
1605 | .audio_clock = 0x00187de7, | ||
1606 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
1607 | .inputs = {{ | ||
1608 | .name = name_tv, | ||
1609 | .vmux = 1, | ||
1610 | .amux = TV, | ||
1611 | .tv = 1, | ||
1612 | },{ | ||
1613 | .name = name_comp1, | ||
1614 | .vmux = 3, | ||
1615 | .amux = LINE2, | ||
1616 | },{ | ||
1617 | .name = name_svideo, | ||
1618 | .vmux = 8, | ||
1619 | .amux = LINE2, | ||
1620 | }}, | ||
1621 | }, | ||
1622 | [SAA7134_BOARD_KWORLD_VSTREAM_XPERT] = { | ||
1623 | .name = "Kworld/Tevion V-Stream Xpert TV PVR7134", | ||
1624 | .audio_clock = 0x00187de7, | ||
1625 | .tuner_type = TUNER_PHILIPS_PAL_I, | ||
1626 | .gpiomask = 0x0700, | ||
1627 | .inputs = {{ | ||
1628 | .name = name_tv, | ||
1629 | .vmux = 1, | ||
1630 | .amux = TV, | ||
1631 | .tv = 1, | ||
1632 | .gpio = 0x000, | ||
1633 | },{ | ||
1634 | .name = name_comp1, | ||
1635 | .vmux = 3, | ||
1636 | .amux = LINE1, | ||
1637 | .gpio = 0x200, //gpio by DScaler | ||
1638 | },{ | ||
1639 | .name = name_svideo, | ||
1640 | .vmux = 0, | ||
1641 | .amux = LINE1, | ||
1642 | .gpio = 0x200, | ||
1643 | }}, | ||
1644 | .radio = { | ||
1645 | .name = name_radio, | ||
1646 | .amux = LINE1, | ||
1647 | .gpio = 0x100, | ||
1648 | }, | ||
1649 | }, | ||
1650 | }; | ||
1651 | |||
1550 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 1652 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
1551 | 1653 | ||
1552 | /* ------------------------------------------------------------------ */ | 1654 | /* ------------------------------------------------------------------ */ |
@@ -1663,7 +1765,7 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
1663 | .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134, | 1765 | .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134, |
1664 | },{ | 1766 | },{ |
1665 | .vendor = PCI_VENDOR_ID_PHILIPS, | 1767 | .vendor = PCI_VENDOR_ID_PHILIPS, |
1666 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 1768 | .device = PCI_DEVICE_ID_PHILIPS_SAA7135, |
1667 | .subvendor = PCI_VENDOR_ID_ASUSTEK, | 1769 | .subvendor = PCI_VENDOR_ID_ASUSTEK, |
1668 | .subdevice = 0x4845, | 1770 | .subdevice = 0x4845, |
1669 | .driver_data = SAA7135_BOARD_ASUSTeK_TVFM7135, | 1771 | .driver_data = SAA7135_BOARD_ASUSTeK_TVFM7135, |
@@ -1824,6 +1926,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
1824 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 1926 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
1825 | .subvendor = 0x1461, /* Avermedia Technologies Inc */ | 1927 | .subvendor = 0x1461, /* Avermedia Technologies Inc */ |
1826 | .subdevice = 0x9715, | 1928 | .subdevice = 0x9715, |
1929 | .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_307, | ||
1930 | },{ | ||
1931 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
1932 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | ||
1933 | .subvendor = 0x1461, /* Avermedia Technologies Inc */ | ||
1934 | .subdevice = 0xa70a, | ||
1827 | .driver_data = SAA7134_BOARD_AVERMEDIA_307, | 1935 | .driver_data = SAA7134_BOARD_AVERMEDIA_307, |
1828 | },{ | 1936 | },{ |
1829 | .vendor = PCI_VENDOR_ID_PHILIPS, | 1937 | .vendor = PCI_VENDOR_ID_PHILIPS, |
@@ -1844,6 +1952,26 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
1844 | .subvendor = 0x5168, | 1952 | .subvendor = 0x5168, |
1845 | .subdevice = 0x0306, | 1953 | .subdevice = 0x0306, |
1846 | .driver_data = SAA7134_BOARD_FLYDVBTDUO, | 1954 | .driver_data = SAA7134_BOARD_FLYDVBTDUO, |
1955 | },{ | ||
1956 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
1957 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
1958 | .subvendor = 0x1461, /* Avermedia Technologies Inc */ | ||
1959 | .subdevice = 0xf31f, | ||
1960 | .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM, | ||
1961 | |||
1962 | },{ | ||
1963 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
1964 | .device = PCI_DEVICE_ID_PHILIPS_SAA7135, | ||
1965 | .subvendor = 0x1421, | ||
1966 | .subdevice = 0x0350, /* PCI version */ | ||
1967 | .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, | ||
1968 | |||
1969 | },{ | ||
1970 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
1971 | .device = PCI_DEVICE_ID_PHILIPS_SAA7135, | ||
1972 | .subvendor = 0x1421, | ||
1973 | .subdevice = 0x0370, /* cardbus version */ | ||
1974 | .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, | ||
1847 | 1975 | ||
1848 | },{ | 1976 | },{ |
1849 | /* --- boards without eeprom + subsystem ID --- */ | 1977 | /* --- boards without eeprom + subsystem ID --- */ |
@@ -1954,20 +2082,23 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
1954 | dev->has_remote = 1; | 2082 | dev->has_remote = 1; |
1955 | board_flyvideo(dev); | 2083 | board_flyvideo(dev); |
1956 | break; | 2084 | break; |
1957 | case SAA7134_BOARD_FLYTVPLATINUM_FM: | 2085 | case SAA7134_BOARD_FLYTVPLATINUM_FM: |
1958 | case SAA7134_BOARD_CINERGY400: | 2086 | case SAA7134_BOARD_CINERGY400: |
1959 | case SAA7134_BOARD_CINERGY600: | 2087 | case SAA7134_BOARD_CINERGY600: |
1960 | case SAA7134_BOARD_CINERGY600_MK3: | 2088 | case SAA7134_BOARD_CINERGY600_MK3: |
1961 | case SAA7134_BOARD_ECS_TVP3XP: | 2089 | case SAA7134_BOARD_ECS_TVP3XP: |
1962 | case SAA7134_BOARD_ECS_TVP3XP_4CB5: | 2090 | case SAA7134_BOARD_ECS_TVP3XP_4CB5: |
1963 | case SAA7134_BOARD_MD2819: | 2091 | case SAA7134_BOARD_MD2819: |
2092 | case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: | ||
1964 | case SAA7134_BOARD_AVERMEDIA_STUDIO_305: | 2093 | case SAA7134_BOARD_AVERMEDIA_STUDIO_305: |
1965 | case SAA7134_BOARD_AVERMEDIA_305: | 2094 | case SAA7134_BOARD_AVERMEDIA_305: |
2095 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: | ||
1966 | case SAA7134_BOARD_AVERMEDIA_307: | 2096 | case SAA7134_BOARD_AVERMEDIA_307: |
2097 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: | ||
1967 | // case SAA7134_BOARD_SABRENT_SBTTVFM: /* not finished yet */ | 2098 | // case SAA7134_BOARD_SABRENT_SBTTVFM: /* not finished yet */ |
1968 | case SAA7134_BOARD_VIDEOMATE_TV_PVR: | 2099 | case SAA7134_BOARD_VIDEOMATE_TV_PVR: |
1969 | dev->has_remote = 1; | 2100 | case SAA7134_BOARD_MANLI_MTV001: |
1970 | break; | 2101 | case SAA7134_BOARD_MANLI_MTV002: |
1971 | case SAA7134_BOARD_AVACSSMARTTV: | 2102 | case SAA7134_BOARD_AVACSSMARTTV: |
1972 | dev->has_remote = 1; | 2103 | dev->has_remote = 1; |
1973 | break; | 2104 | break; |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index d506cafba8..f61ed1849a 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: saa7134-core.c,v 1.28 2005/02/22 09:56:29 kraxel Exp $ | 2 | * $Id: saa7134-core.c,v 1.30 2005/05/22 19:23:39 nsh Exp $ |
3 | * | 3 | * |
4 | * device driver for philips saa7134 based TV cards | 4 | * device driver for philips saa7134 based TV cards |
5 | * driver core | 5 | * driver core |
@@ -316,7 +316,7 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf) | |||
316 | 316 | ||
317 | int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) | 317 | int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) |
318 | { | 318 | { |
319 | u32 *cpu; | 319 | __le32 *cpu; |
320 | dma_addr_t dma_addr; | 320 | dma_addr_t dma_addr; |
321 | 321 | ||
322 | cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); | 322 | cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); |
@@ -332,7 +332,7 @@ int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt, | |||
332 | struct scatterlist *list, unsigned int length, | 332 | struct scatterlist *list, unsigned int length, |
333 | unsigned int startpage) | 333 | unsigned int startpage) |
334 | { | 334 | { |
335 | u32 *ptr; | 335 | __le32 *ptr; |
336 | unsigned int i,p; | 336 | unsigned int i,p; |
337 | 337 | ||
338 | BUG_ON(NULL == pt || NULL == pt->cpu); | 338 | BUG_ON(NULL == pt || NULL == pt->cpu); |
@@ -340,7 +340,7 @@ int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt, | |||
340 | ptr = pt->cpu + startpage; | 340 | ptr = pt->cpu + startpage; |
341 | for (i = 0; i < length; i++, list++) | 341 | for (i = 0; i < length; i++, list++) |
342 | for (p = 0; p * 4096 < list->length; p++, ptr++) | 342 | for (p = 0; p * 4096 < list->length; p++, ptr++) |
343 | *ptr = sg_dma_address(list) - list->offset; | 343 | *ptr = cpu_to_le32(sg_dma_address(list) - list->offset); |
344 | return 0; | 344 | return 0; |
345 | } | 345 | } |
346 | 346 | ||
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index c2873ae029..aa8e2cf62d 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: saa7134-dvb.c,v 1.12 2005/02/18 12:28:29 kraxel Exp $ | 2 | * $Id: saa7134-dvb.c,v 1.13 2005/06/12 04:19:19 mchehab Exp $ |
3 | * | 3 | * |
4 | * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | 4 | * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] |
5 | * | 5 | * |
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index fa13573369..c85348d023 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: saa7134-empress.c,v 1.10 2005/02/03 10:24:33 kraxel Exp $ | 2 | * $Id: saa7134-empress.c,v 1.11 2005/05/22 19:23:39 nsh Exp $ |
3 | * | 3 | * |
4 | * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | 4 | * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] |
5 | * | 5 | * |
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 702bb63d98..b6f002e842 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: saa7134-i2c.c,v 1.10 2005/01/24 17:37:23 kraxel Exp $ | 2 | * $Id: saa7134-i2c.c,v 1.11 2005/06/12 01:36:14 mchehab Exp $ |
3 | * | 3 | * |
4 | * device driver for philips saa7134 based TV cards | 4 | * device driver for philips saa7134 based TV cards |
5 | * i2c interface support | 5 | * i2c interface support |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ca50cf531f..aba2b9de60 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: saa7134-input.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $ | 2 | * $Id: saa7134-input.c,v 1.19 2005/06/07 18:02:26 nsh Exp $ |
3 | * | 3 | * |
4 | * handle saa7134 IR remotes via linux kernel input layer. | 4 | * handle saa7134 IR remotes via linux kernel input layer. |
5 | * | 5 | * |
@@ -308,6 +308,102 @@ static IR_KEYTAB_TYPE videomate_tv_pvr_codes[IR_KEYTAB_SIZE] = { | |||
308 | [ 32 ] = KEY_LANGUAGE, | 308 | [ 32 ] = KEY_LANGUAGE, |
309 | [ 33 ] = KEY_SLEEP, | 309 | [ 33 ] = KEY_SLEEP, |
310 | }; | 310 | }; |
311 | |||
312 | /* Michael Tokarev <mjt@tls.msk.ru> | ||
313 | http://www.corpit.ru/mjt/beholdTV/remote_control.jpg | ||
314 | keytable is used by MANLI MTV00[12] and BeholdTV 40[13] at | ||
315 | least, and probably other cards too. | ||
316 | The "ascii-art picture" below (in comments, first row | ||
317 | is the keycode in hex, and subsequent row(s) shows | ||
318 | the button labels (several variants when appropriate) | ||
319 | helps to descide which keycodes to assign to the buttons. | ||
320 | */ | ||
321 | static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = { | ||
322 | |||
323 | /* 0x1c 0x12 * | ||
324 | * FUNCTION POWER * | ||
325 | * FM (|) * | ||
326 | * */ | ||
327 | [ 0x1c ] = KEY_RADIO, /*XXX*/ | ||
328 | [ 0x12 ] = KEY_POWER, | ||
329 | |||
330 | /* 0x01 0x02 0x03 * | ||
331 | * 1 2 3 * | ||
332 | * * | ||
333 | * 0x04 0x05 0x06 * | ||
334 | * 4 5 6 * | ||
335 | * * | ||
336 | * 0x07 0x08 0x09 * | ||
337 | * 7 8 9 * | ||
338 | * */ | ||
339 | [ 0x01 ] = KEY_KP1, | ||
340 | [ 0x02 ] = KEY_KP2, | ||
341 | [ 0x03 ] = KEY_KP3, | ||
342 | [ 0x04 ] = KEY_KP4, | ||
343 | [ 0x05 ] = KEY_KP5, | ||
344 | [ 0x06 ] = KEY_KP6, | ||
345 | [ 0x07 ] = KEY_KP7, | ||
346 | [ 0x08 ] = KEY_KP8, | ||
347 | [ 0x09 ] = KEY_KP9, | ||
348 | |||
349 | /* 0x0a 0x00 0x17 * | ||
350 | * RECALL 0 +100 * | ||
351 | * PLUS * | ||
352 | * */ | ||
353 | [ 0x0a ] = KEY_AGAIN, /*XXX KEY_REWIND? */ | ||
354 | [ 0x00 ] = KEY_KP0, | ||
355 | [ 0x17 ] = KEY_DIGITS, /*XXX*/ | ||
356 | |||
357 | /* 0x14 0x10 * | ||
358 | * MENU INFO * | ||
359 | * OSD */ | ||
360 | [ 0x14 ] = KEY_MENU, | ||
361 | [ 0x10 ] = KEY_INFO, | ||
362 | |||
363 | /* 0x0b * | ||
364 | * Up * | ||
365 | * * | ||
366 | * 0x18 0x16 0x0c * | ||
367 | * Left Ok Right * | ||
368 | * * | ||
369 | * 0x015 * | ||
370 | * Down * | ||
371 | * */ | ||
372 | [ 0x0b ] = KEY_UP, /*XXX KEY_SCROLLUP? */ | ||
373 | [ 0x18 ] = KEY_LEFT, /*XXX KEY_BACK? */ | ||
374 | [ 0x16 ] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ | ||
375 | [ 0x0c ] = KEY_RIGHT, /*XXX KEY_FORWARD? */ | ||
376 | [ 0x15 ] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */ | ||
377 | |||
378 | /* 0x11 0x0d * | ||
379 | * TV/AV MODE * | ||
380 | * SOURCE STEREO * | ||
381 | * */ | ||
382 | [ 0x11 ] = KEY_TV, /*XXX*/ | ||
383 | [ 0x0d ] = KEY_MODE, /*XXX there's no KEY_STEREO */ | ||
384 | |||
385 | /* 0x0f 0x1b 0x1a * | ||
386 | * AUDIO Vol+ Chan+ * | ||
387 | * TIMESHIFT??? * | ||
388 | * * | ||
389 | * 0x0e 0x1f 0x1e * | ||
390 | * SLEEP Vol- Chan- * | ||
391 | * */ | ||
392 | [ 0x0f ] = KEY_AUDIO, | ||
393 | [ 0x1b ] = KEY_VOLUMEUP, | ||
394 | [ 0x1a ] = KEY_CHANNELUP, | ||
395 | [ 0x0e ] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ | ||
396 | [ 0x1f ] = KEY_VOLUMEDOWN, | ||
397 | [ 0x1e ] = KEY_CHANNELDOWN, | ||
398 | |||
399 | /* 0x13 0x19 * | ||
400 | * MUTE SNAPSHOT* | ||
401 | * */ | ||
402 | [ 0x13 ] = KEY_MUTE, | ||
403 | [ 0x19 ] = KEY_RECORD, /*XXX*/ | ||
404 | |||
405 | // 0x1d unused ? | ||
406 | }; | ||
311 | /* ---------------------------------------------------------------------- */ | 407 | /* ---------------------------------------------------------------------- */ |
312 | 408 | ||
313 | static int build_key(struct saa7134_dev *dev) | 409 | static int build_key(struct saa7134_dev *dev) |
@@ -379,7 +475,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
379 | switch (dev->board) { | 475 | switch (dev->board) { |
380 | case SAA7134_BOARD_FLYVIDEO2000: | 476 | case SAA7134_BOARD_FLYVIDEO2000: |
381 | case SAA7134_BOARD_FLYVIDEO3000: | 477 | case SAA7134_BOARD_FLYVIDEO3000: |
382 | case SAA7134_BOARD_FLYTVPLATINUM_FM: | 478 | case SAA7134_BOARD_FLYTVPLATINUM_FM: |
383 | ir_codes = flyvideo_codes; | 479 | ir_codes = flyvideo_codes; |
384 | mask_keycode = 0xEC00000; | 480 | mask_keycode = 0xEC00000; |
385 | mask_keydown = 0x0040000; | 481 | mask_keydown = 0x0040000; |
@@ -405,8 +501,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
405 | polling = 50; // ms | 501 | polling = 50; // ms |
406 | break; | 502 | break; |
407 | case SAA7134_BOARD_MD2819: | 503 | case SAA7134_BOARD_MD2819: |
504 | case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: | ||
408 | case SAA7134_BOARD_AVERMEDIA_305: | 505 | case SAA7134_BOARD_AVERMEDIA_305: |
409 | case SAA7134_BOARD_AVERMEDIA_307: | 506 | case SAA7134_BOARD_AVERMEDIA_307: |
507 | case SAA7134_BOARD_AVERMEDIA_STUDIO_305: | ||
508 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: | ||
509 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: | ||
410 | ir_codes = md2819_codes; | 510 | ir_codes = md2819_codes; |
411 | mask_keycode = 0x0007C8; | 511 | mask_keycode = 0x0007C8; |
412 | mask_keydown = 0x000010; | 512 | mask_keydown = 0x000010; |
@@ -415,6 +515,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
415 | saa_setb(SAA7134_GPIO_GPMODE0, 0x4); | 515 | saa_setb(SAA7134_GPIO_GPMODE0, 0x4); |
416 | saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); | 516 | saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); |
417 | break; | 517 | break; |
518 | case SAA7134_BOARD_MANLI_MTV001: | ||
519 | case SAA7134_BOARD_MANLI_MTV002: | ||
520 | ir_codes = manli_codes; | ||
521 | mask_keycode = 0x001f00; | ||
522 | mask_keyup = 0x004000; | ||
523 | mask_keydown = 0x002000; | ||
524 | polling = 50; // ms | ||
525 | break; | ||
418 | case SAA7134_BOARD_VIDEOMATE_TV_PVR: | 526 | case SAA7134_BOARD_VIDEOMATE_TV_PVR: |
419 | ir_codes = videomate_tv_pvr_codes; | 527 | ir_codes = videomate_tv_pvr_codes; |
420 | mask_keycode = 0x00003F; | 528 | mask_keycode = 0x00003F; |
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index 6b6a643bf1..8173290462 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: saa7134-oss.c,v 1.13 2004/12/10 12:33:39 kraxel Exp $ | 2 | * $Id: saa7134-oss.c,v 1.14 2005/05/18 22:45:16 hhackmann Exp $ |
3 | * | 3 | * |
4 | * device driver for philips saa7134 based TV cards | 4 | * device driver for philips saa7134 based TV cards |
5 | * oss dsp interface | 5 | * oss dsp interface |
@@ -49,7 +49,6 @@ MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)"); | |||
49 | 49 | ||
50 | static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) | 50 | static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) |
51 | { | 51 | { |
52 | blksize &= ~0xff; | ||
53 | if (blksize < 0x100) | 52 | if (blksize < 0x100) |
54 | blksize = 0x100; | 53 | blksize = 0x100; |
55 | if (blksize > 0x10000) | 54 | if (blksize > 0x10000) |
@@ -57,8 +56,6 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) | |||
57 | 56 | ||
58 | if (blocks < 2) | 57 | if (blocks < 2) |
59 | blocks = 2; | 58 | blocks = 2; |
60 | while ((blksize * blocks) & ~PAGE_MASK) | ||
61 | blocks++; | ||
62 | if ((blksize * blocks) > 1024*1024) | 59 | if ((blksize * blocks) > 1024*1024) |
63 | blocks = 1024*1024 / blksize; | 60 | blocks = 1024*1024 / blksize; |
64 | 61 | ||
@@ -79,7 +76,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev) | |||
79 | BUG(); | 76 | BUG(); |
80 | videobuf_dma_init(&dev->oss.dma); | 77 | videobuf_dma_init(&dev->oss.dma); |
81 | err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, | 78 | err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, |
82 | dev->oss.bufsize >> PAGE_SHIFT); | 79 | (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); |
83 | if (0 != err) | 80 | if (0 != err) |
84 | return err; | 81 | return err; |
85 | return 0; | 82 | return 0; |
@@ -163,10 +160,11 @@ static int dsp_rec_start(struct saa7134_dev *dev) | |||
163 | fmt |= 0x04; | 160 | fmt |= 0x04; |
164 | fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80; | 161 | fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80; |
165 | 162 | ||
166 | saa_writeb(SAA7134_NUM_SAMPLES0, (dev->oss.blksize & 0x0000ff)); | 163 | saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff)); |
167 | saa_writeb(SAA7134_NUM_SAMPLES1, (dev->oss.blksize & 0x00ff00) >> 8); | 164 | saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8); |
168 | saa_writeb(SAA7134_NUM_SAMPLES2, (dev->oss.blksize & 0xff0000) >> 16); | 165 | saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16); |
169 | saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); | 166 | saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); |
167 | |||
170 | break; | 168 | break; |
171 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | 169 | case PCI_DEVICE_ID_PHILIPS_SAA7133: |
172 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | 170 | case PCI_DEVICE_ID_PHILIPS_SAA7135: |
@@ -817,7 +815,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) | |||
817 | reg = SAA7134_RS_BA1(6); | 815 | reg = SAA7134_RS_BA1(6); |
818 | } else { | 816 | } else { |
819 | /* even */ | 817 | /* even */ |
820 | if (0 == (dev->oss.dma_blk & 0x00)) | 818 | if (1 == (dev->oss.dma_blk & 0x01)) |
821 | reg = SAA7134_RS_BA2(6); | 819 | reg = SAA7134_RS_BA2(6); |
822 | } | 820 | } |
823 | if (0 == reg) { | 821 | if (0 == reg) { |
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index ecac13c006..3617e7f7a4 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: saa7134-tvaudio.c,v 1.22 2005/01/07 13:11:19 kraxel Exp $ | 2 | * $Id: saa7134-tvaudio.c,v 1.25 2005/06/07 19:00:38 nsh Exp $ |
3 | * | 3 | * |
4 | * device driver for philips saa7134 based TV cards | 4 | * device driver for philips saa7134 based TV cards |
5 | * tv audio decoder (fm stereo, nicam, ...) | 5 | * tv audio decoder (fm stereo, nicam, ...) |
@@ -181,7 +181,8 @@ static void tvaudio_init(struct saa7134_dev *dev) | |||
181 | saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff); | 181 | saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff); |
182 | saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff); | 182 | saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff); |
183 | saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff); | 183 | saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff); |
184 | saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x01); | 184 | // frame locked audio was reported not to be reliable |
185 | saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x02); | ||
185 | 186 | ||
186 | saa_writeb(SAA7134_NICAM_ERROR_LOW, 0x14); | 187 | saa_writeb(SAA7134_NICAM_ERROR_LOW, 0x14); |
187 | saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50); | 188 | saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50); |
@@ -250,6 +251,11 @@ static void mute_input_7134(struct saa7134_dev *dev) | |||
250 | saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel); | 251 | saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel); |
251 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics); | 252 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics); |
252 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, ocs); | 253 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, ocs); |
254 | // for oss, we need to change the clock configuration | ||
255 | if (in->amux == TV) | ||
256 | saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); | ||
257 | else | ||
258 | saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x01); | ||
253 | 259 | ||
254 | /* switch gpio-connected external audio mux */ | 260 | /* switch gpio-connected external audio mux */ |
255 | if (0 == card(dev).gpiomask) | 261 | if (0 == card(dev).gpiomask) |
@@ -439,16 +445,15 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au | |||
439 | nicam = saa_readb(SAA7134_NICAM_STATUS); | 445 | nicam = saa_readb(SAA7134_NICAM_STATUS); |
440 | dprintk("getstereo: nicam=0x%x\n",nicam); | 446 | dprintk("getstereo: nicam=0x%x\n",nicam); |
441 | switch (nicam & 0x0b) { | 447 | switch (nicam & 0x0b) { |
448 | case 0x08: | ||
449 | retval = V4L2_TUNER_SUB_MONO; | ||
450 | break; | ||
442 | case 0x09: | 451 | case 0x09: |
443 | retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | 452 | retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; |
444 | break; | 453 | break; |
445 | case 0x0a: | 454 | case 0x0a: |
446 | retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | 455 | retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; |
447 | break; | 456 | break; |
448 | case 0x08: | ||
449 | default: | ||
450 | retval = V4L2_TUNER_SUB_MONO; | ||
451 | break; | ||
452 | } | 457 | } |
453 | break; | 458 | break; |
454 | } | 459 | } |
@@ -572,14 +577,14 @@ static int tvaudio_thread(void *data) | |||
572 | } else if (0 != dev->last_carrier) { | 577 | } else if (0 != dev->last_carrier) { |
573 | /* no carrier -- try last detected one as fallback */ | 578 | /* no carrier -- try last detected one as fallback */ |
574 | carrier = dev->last_carrier; | 579 | carrier = dev->last_carrier; |
575 | printk(KERN_WARNING "%s/audio: audio carrier scan failed, " | 580 | dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, " |
576 | "using %d.%03d MHz [last detected]\n", | 581 | "using %d.%03d MHz [last detected]\n", |
577 | dev->name, carrier/1000, carrier%1000); | 582 | dev->name, carrier/1000, carrier%1000); |
578 | 583 | ||
579 | } else { | 584 | } else { |
580 | /* no carrier + no fallback -- use default */ | 585 | /* no carrier + no fallback -- use default */ |
581 | carrier = default_carrier; | 586 | carrier = default_carrier; |
582 | printk(KERN_WARNING "%s/audio: audio carrier scan failed, " | 587 | dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, " |
583 | "using %d.%03d MHz [default]\n", | 588 | "using %d.%03d MHz [default]\n", |
584 | dev->name, carrier/1000, carrier%1000); | 589 | dev->name, carrier/1000, carrier%1000); |
585 | } | 590 | } |
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c index 86954cc7c3..3c33c591cc 100644 --- a/drivers/media/video/saa7134/saa7134-vbi.c +++ b/drivers/media/video/saa7134/saa7134-vbi.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: saa7134-vbi.c,v 1.6 2004/12/10 12:33:39 kraxel Exp $ | 2 | * $Id: saa7134-vbi.c,v 1.7 2005/05/24 23:13:06 nsh Exp $ |
3 | * | 3 | * |
4 | * device driver for philips saa7134 based TV cards | 4 | * device driver for philips saa7134 based TV cards |
5 | * video4linux video interface | 5 | * video4linux video interface |
@@ -60,10 +60,10 @@ static void task_init(struct saa7134_dev *dev, struct saa7134_buf *buf, | |||
60 | saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start >> 8); | 60 | saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start >> 8); |
61 | saa_writeb(SAA7134_VBI_H_STOP1(task), norm->h_stop & 0xff); | 61 | saa_writeb(SAA7134_VBI_H_STOP1(task), norm->h_stop & 0xff); |
62 | saa_writeb(SAA7134_VBI_H_STOP2(task), norm->h_stop >> 8); | 62 | saa_writeb(SAA7134_VBI_H_STOP2(task), norm->h_stop >> 8); |
63 | saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start & 0xff); | 63 | saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start_0 & 0xff); |
64 | saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start >> 8); | 64 | saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start_0 >> 8); |
65 | saa_writeb(SAA7134_VBI_V_STOP1(task), norm->vbi_v_stop & 0xff); | 65 | saa_writeb(SAA7134_VBI_V_STOP1(task), norm->vbi_v_stop_0 & 0xff); |
66 | saa_writeb(SAA7134_VBI_V_STOP2(task), norm->vbi_v_stop >> 8); | 66 | saa_writeb(SAA7134_VBI_V_STOP2(task), norm->vbi_v_stop_0 >> 8); |
67 | 67 | ||
68 | saa_writeb(SAA7134_VBI_H_SCALE_INC1(task), VBI_SCALE & 0xff); | 68 | saa_writeb(SAA7134_VBI_H_SCALE_INC1(task), VBI_SCALE & 0xff); |
69 | saa_writeb(SAA7134_VBI_H_SCALE_INC2(task), VBI_SCALE >> 8); | 69 | saa_writeb(SAA7134_VBI_H_SCALE_INC2(task), VBI_SCALE >> 8); |
@@ -127,7 +127,7 @@ static int buffer_prepare(struct videobuf_queue *q, | |||
127 | unsigned int lines, llength, size; | 127 | unsigned int lines, llength, size; |
128 | int err; | 128 | int err; |
129 | 129 | ||
130 | lines = norm->vbi_v_stop - norm->vbi_v_start +1; | 130 | lines = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1; |
131 | if (lines > VBI_LINE_COUNT) | 131 | if (lines > VBI_LINE_COUNT) |
132 | lines = VBI_LINE_COUNT; | 132 | lines = VBI_LINE_COUNT; |
133 | #if 1 | 133 | #if 1 |
@@ -177,7 +177,7 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | |||
177 | struct saa7134_dev *dev = fh->dev; | 177 | struct saa7134_dev *dev = fh->dev; |
178 | int llength,lines; | 178 | int llength,lines; |
179 | 179 | ||
180 | lines = dev->tvnorm->vbi_v_stop - dev->tvnorm->vbi_v_start +1; | 180 | lines = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 +1; |
181 | #if 1 | 181 | #if 1 |
182 | llength = VBI_LINE_LENGTH; | 182 | llength = VBI_LINE_LENGTH; |
183 | #else | 183 | #else |
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 5d66060026..c0a2ee5205 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: saa7134-video.c,v 1.28 2005/02/15 15:59:35 kraxel Exp $ | 2 | * $Id: saa7134-video.c,v 1.30 2005/06/07 19:00:38 nsh Exp $ |
3 | * | 3 | * |
4 | * device driver for philips saa7134 based TV cards | 4 | * device driver for philips saa7134 based TV cards |
5 | * video4linux video interface | 5 | * video4linux video interface |
@@ -31,8 +31,6 @@ | |||
31 | #include "saa7134-reg.h" | 31 | #include "saa7134-reg.h" |
32 | #include "saa7134.h" | 32 | #include "saa7134.h" |
33 | 33 | ||
34 | #define V4L2_I2C_CLIENTS 1 | ||
35 | |||
36 | /* ------------------------------------------------------------------ */ | 34 | /* ------------------------------------------------------------------ */ |
37 | 35 | ||
38 | static unsigned int video_debug = 0; | 36 | static unsigned int video_debug = 0; |
@@ -158,18 +156,20 @@ static struct saa7134_format formats[] = { | |||
158 | .h_stop = 719, \ | 156 | .h_stop = 719, \ |
159 | .video_v_start = 24, \ | 157 | .video_v_start = 24, \ |
160 | .video_v_stop = 311, \ | 158 | .video_v_stop = 311, \ |
161 | .vbi_v_start = 7, \ | 159 | .vbi_v_start_0 = 7, \ |
162 | .vbi_v_stop = 22, \ | 160 | .vbi_v_stop_0 = 22, \ |
161 | .vbi_v_start_1 = 319, \ | ||
163 | .src_timing = 4 | 162 | .src_timing = 4 |
164 | 163 | ||
165 | #define NORM_525_60 \ | 164 | #define NORM_525_60 \ |
166 | .h_start = 0, \ | 165 | .h_start = 0, \ |
167 | .h_stop = 703, \ | 166 | .h_stop = 703, \ |
168 | .video_v_start = 22, \ | 167 | .video_v_start = 23, \ |
169 | .video_v_stop = 22+239, \ | 168 | .video_v_stop = 262, \ |
170 | .vbi_v_start = 10, /* FIXME */ \ | 169 | .vbi_v_start_0 = 10, \ |
171 | .vbi_v_stop = 21, /* FIXME */ \ | 170 | .vbi_v_stop_0 = 21, \ |
172 | .src_timing = 1 | 171 | .vbi_v_start_1 = 273, \ |
172 | .src_timing = 7 | ||
173 | 173 | ||
174 | static struct saa7134_tvnorm tvnorms[] = { | 174 | static struct saa7134_tvnorm tvnorms[] = { |
175 | { | 175 | { |
@@ -274,11 +274,12 @@ static struct saa7134_tvnorm tvnorms[] = { | |||
274 | 274 | ||
275 | .h_start = 0, | 275 | .h_start = 0, |
276 | .h_stop = 719, | 276 | .h_stop = 719, |
277 | .video_v_start = 22, | 277 | .video_v_start = 23, |
278 | .video_v_stop = 22+239, | 278 | .video_v_stop = 262, |
279 | .vbi_v_start = 10, /* FIXME */ | 279 | .vbi_v_start_0 = 10, |
280 | .vbi_v_stop = 21, /* FIXME */ | 280 | .vbi_v_stop_0 = 21, |
281 | .src_timing = 1, | 281 | .vbi_v_start_1 = 273, |
282 | .src_timing = 7, | ||
282 | 283 | ||
283 | .sync_control = 0x18, | 284 | .sync_control = 0x18, |
284 | .luma_control = 0x40, | 285 | .luma_control = 0x40, |
@@ -335,8 +336,8 @@ static const struct v4l2_queryctrl video_ctrls[] = { | |||
335 | .default_value = 0, | 336 | .default_value = 0, |
336 | .type = V4L2_CTRL_TYPE_INTEGER, | 337 | .type = V4L2_CTRL_TYPE_INTEGER, |
337 | },{ | 338 | },{ |
338 | .id = V4L2_CID_VFLIP, | 339 | .id = V4L2_CID_HFLIP, |
339 | .name = "vertical flip", | 340 | .name = "Mirror", |
340 | .minimum = 0, | 341 | .minimum = 0, |
341 | .maximum = 1, | 342 | .maximum = 1, |
342 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 343 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
@@ -482,7 +483,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) | |||
482 | dev->crop_bounds.width = norm->h_stop - norm->h_start +1; | 483 | dev->crop_bounds.width = norm->h_stop - norm->h_start +1; |
483 | dev->crop_defrect.width = norm->h_stop - norm->h_start +1; | 484 | dev->crop_defrect.width = norm->h_stop - norm->h_start +1; |
484 | 485 | ||
485 | dev->crop_bounds.top = (norm->vbi_v_stop+1)*2; | 486 | dev->crop_bounds.top = (norm->vbi_v_stop_0+1)*2; |
486 | dev->crop_defrect.top = norm->video_v_start*2; | 487 | dev->crop_defrect.top = norm->video_v_start*2; |
487 | dev->crop_bounds.height = ((norm->id & V4L2_STD_525_60) ? 524 : 624) | 488 | dev->crop_bounds.height = ((norm->id & V4L2_STD_525_60) ? 524 : 624) |
488 | - dev->crop_bounds.top; | 489 | - dev->crop_bounds.top; |
@@ -521,22 +522,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) | |||
521 | saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40); | 522 | saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40); |
522 | saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80); | 523 | saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80); |
523 | 524 | ||
524 | #ifdef V4L2_I2C_CLIENTS | ||
525 | saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id); | 525 | saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id); |
526 | #else | ||
527 | { | ||
528 | /* pass down info to the i2c chips (v4l1) */ | ||
529 | struct video_channel c; | ||
530 | memset(&c,0,sizeof(c)); | ||
531 | c.channel = dev->ctl_input; | ||
532 | c.norm = VIDEO_MODE_PAL; | ||
533 | if (norm->id & V4L2_STD_NTSC) | ||
534 | c.norm = VIDEO_MODE_NTSC; | ||
535 | if (norm->id & V4L2_STD_SECAM) | ||
536 | c.norm = VIDEO_MODE_SECAM; | ||
537 | saa7134_i2c_call_clients(dev,VIDIOCSCHAN,&c); | ||
538 | } | ||
539 | #endif | ||
540 | } | 526 | } |
541 | 527 | ||
542 | static void video_mux(struct saa7134_dev *dev, int input) | 528 | static void video_mux(struct saa7134_dev *dev, int input) |
@@ -1064,7 +1050,7 @@ static int get_control(struct saa7134_dev *dev, struct v4l2_control *c) | |||
1064 | case V4L2_CID_PRIVATE_INVERT: | 1050 | case V4L2_CID_PRIVATE_INVERT: |
1065 | c->value = dev->ctl_invert; | 1051 | c->value = dev->ctl_invert; |
1066 | break; | 1052 | break; |
1067 | case V4L2_CID_VFLIP: | 1053 | case V4L2_CID_HFLIP: |
1068 | c->value = dev->ctl_mirror; | 1054 | c->value = dev->ctl_mirror; |
1069 | break; | 1055 | break; |
1070 | case V4L2_CID_PRIVATE_Y_EVEN: | 1056 | case V4L2_CID_PRIVATE_Y_EVEN: |
@@ -1139,7 +1125,7 @@ static int set_control(struct saa7134_dev *dev, struct saa7134_fh *fh, | |||
1139 | saa_writeb(SAA7134_DEC_CHROMA_SATURATION, | 1125 | saa_writeb(SAA7134_DEC_CHROMA_SATURATION, |
1140 | dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation); | 1126 | dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation); |
1141 | break; | 1127 | break; |
1142 | case V4L2_CID_VFLIP: | 1128 | case V4L2_CID_HFLIP: |
1143 | dev->ctl_mirror = c->value; | 1129 | dev->ctl_mirror = c->value; |
1144 | restart_overlay = 1; | 1130 | restart_overlay = 1; |
1145 | break; | 1131 | break; |
@@ -1407,9 +1393,9 @@ static void saa7134_vbi_fmt(struct saa7134_dev *dev, struct v4l2_format *f) | |||
1407 | f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */; | 1393 | f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */; |
1408 | f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | 1394 | f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; |
1409 | f->fmt.vbi.offset = 64 * 4; | 1395 | f->fmt.vbi.offset = 64 * 4; |
1410 | f->fmt.vbi.start[0] = norm->vbi_v_start; | 1396 | f->fmt.vbi.start[0] = norm->vbi_v_start_0; |
1411 | f->fmt.vbi.count[0] = norm->vbi_v_stop - norm->vbi_v_start +1; | 1397 | f->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1; |
1412 | f->fmt.vbi.start[1] = norm->video_v_stop + norm->vbi_v_start +1; | 1398 | f->fmt.vbi.start[1] = norm->vbi_v_start_1; |
1413 | f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; | 1399 | f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; |
1414 | f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */ | 1400 | f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */ |
1415 | 1401 | ||
@@ -1880,11 +1866,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file, | |||
1880 | return -EINVAL; | 1866 | return -EINVAL; |
1881 | down(&dev->lock); | 1867 | down(&dev->lock); |
1882 | dev->ctl_freq = f->frequency; | 1868 | dev->ctl_freq = f->frequency; |
1883 | #ifdef V4L2_I2C_CLIENTS | 1869 | |
1884 | saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f); | 1870 | saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f); |
1885 | #else | 1871 | |
1886 | saa7134_i2c_call_clients(dev,VIDIOCSFREQ,&dev->ctl_freq); | ||
1887 | #endif | ||
1888 | saa7134_tvaudio_do_scan(dev); | 1872 | saa7134_tvaudio_do_scan(dev); |
1889 | up(&dev->lock); | 1873 | up(&dev->lock); |
1890 | return 0; | 1874 | return 0; |
@@ -2139,16 +2123,19 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, | |||
2139 | t->rangelow = (int)(65*16); | 2123 | t->rangelow = (int)(65*16); |
2140 | t->rangehigh = (int)(108*16); | 2124 | t->rangehigh = (int)(108*16); |
2141 | 2125 | ||
2142 | #ifdef V4L2_I2C_CLIENTS | 2126 | saa7134_i2c_call_clients(dev, VIDIOC_G_TUNER, t); |
2143 | saa7134_i2c_call_clients(dev,VIDIOC_G_TUNER,t); | 2127 | |
2144 | #else | 2128 | return 0; |
2145 | { | 2129 | } |
2146 | struct video_tuner vt; | 2130 | case VIDIOC_S_TUNER: |
2147 | memset(&vt,0,sizeof(vt)); | 2131 | { |
2148 | saa7134_i2c_call_clients(dev,VIDIOCGTUNER,&vt); | 2132 | struct v4l2_tuner *t = arg; |
2149 | t->signal = vt.signal; | 2133 | |
2150 | } | 2134 | if (0 != t->index) |
2151 | #endif | 2135 | return -EINVAL; |
2136 | |||
2137 | saa7134_i2c_call_clients(dev,VIDIOC_S_TUNER,t); | ||
2138 | |||
2152 | return 0; | 2139 | return 0; |
2153 | } | 2140 | } |
2154 | case VIDIOC_ENUMINPUT: | 2141 | case VIDIOC_ENUMINPUT: |
@@ -2182,7 +2169,6 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, | |||
2182 | return 0; | 2169 | return 0; |
2183 | } | 2170 | } |
2184 | case VIDIOC_S_AUDIO: | 2171 | case VIDIOC_S_AUDIO: |
2185 | case VIDIOC_S_TUNER: | ||
2186 | case VIDIOC_S_INPUT: | 2172 | case VIDIOC_S_INPUT: |
2187 | case VIDIOC_S_STD: | 2173 | case VIDIOC_S_STD: |
2188 | return 0; | 2174 | return 0; |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index ac90a98532..d6b1c0d4d0 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: saa7134.h,v 1.38 2005/03/07 12:01:51 kraxel Exp $ | 2 | * $Id: saa7134.h,v 1.41 2005/06/07 18:02:26 nsh Exp $ |
3 | * | 3 | * |
4 | * v4l2 device driver for philips saa7134 based TV cards | 4 | * v4l2 device driver for philips saa7134 based TV cards |
5 | * | 5 | * |
@@ -21,7 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/version.h> | 23 | #include <linux/version.h> |
24 | #define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,12) | 24 | #define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,13) |
25 | 25 | ||
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
@@ -91,9 +91,10 @@ struct saa7134_tvnorm { | |||
91 | unsigned int h_stop; | 91 | unsigned int h_stop; |
92 | unsigned int video_v_start; | 92 | unsigned int video_v_start; |
93 | unsigned int video_v_stop; | 93 | unsigned int video_v_stop; |
94 | unsigned int vbi_v_start; | 94 | unsigned int vbi_v_start_0; |
95 | unsigned int vbi_v_stop; | 95 | unsigned int vbi_v_stop_0; |
96 | unsigned int src_timing; | 96 | unsigned int src_timing; |
97 | unsigned int vbi_v_start_1; | ||
97 | }; | 98 | }; |
98 | 99 | ||
99 | struct saa7134_tvaudio { | 100 | struct saa7134_tvaudio { |
@@ -167,7 +168,7 @@ struct saa7134_format { | |||
167 | #define SAA7134_BOARD_SABRENT_SBTTVFM 42 | 168 | #define SAA7134_BOARD_SABRENT_SBTTVFM 42 |
168 | #define SAA7134_BOARD_ZOLID_XPERT_TV7134 43 | 169 | #define SAA7134_BOARD_ZOLID_XPERT_TV7134 43 |
169 | #define SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE 44 | 170 | #define SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE 44 |
170 | #define SAA7134_BOARD_AVERMEDIA_307 45 | 171 | #define SAA7134_BOARD_AVERMEDIA_STUDIO_307 45 |
171 | #define SAA7134_BOARD_AVERMEDIA_CARDBUS 46 | 172 | #define SAA7134_BOARD_AVERMEDIA_CARDBUS 46 |
172 | #define SAA7134_BOARD_CINERGY400_CARDBUS 47 | 173 | #define SAA7134_BOARD_CINERGY400_CARDBUS 47 |
173 | #define SAA7134_BOARD_CINERGY600_MK3 48 | 174 | #define SAA7134_BOARD_CINERGY600_MK3 48 |
@@ -178,6 +179,10 @@ struct saa7134_format { | |||
178 | #define SAA7135_BOARD_ASUSTeK_TVFM7135 53 | 179 | #define SAA7135_BOARD_ASUSTeK_TVFM7135 53 |
179 | #define SAA7134_BOARD_FLYTVPLATINUM_FM 54 | 180 | #define SAA7134_BOARD_FLYTVPLATINUM_FM 54 |
180 | #define SAA7134_BOARD_FLYDVBTDUO 55 | 181 | #define SAA7134_BOARD_FLYDVBTDUO 55 |
182 | #define SAA7134_BOARD_AVERMEDIA_307 56 | ||
183 | #define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57 | ||
184 | #define SAA7134_BOARD_ADS_INSTANT_TV 58 | ||
185 | #define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59 | ||
181 | 186 | ||
182 | #define SAA7134_MAXBOARDS 8 | 187 | #define SAA7134_MAXBOARDS 8 |
183 | #define SAA7134_INPUT_MAX 8 | 188 | #define SAA7134_INPUT_MAX 8 |
@@ -241,7 +246,7 @@ struct saa7134_dma; | |||
241 | /* saa7134 page table */ | 246 | /* saa7134 page table */ |
242 | struct saa7134_pgtable { | 247 | struct saa7134_pgtable { |
243 | unsigned int size; | 248 | unsigned int size; |
244 | u32 *cpu; | 249 | __le32 *cpu; |
245 | dma_addr_t dma; | 250 | dma_addr_t dma; |
246 | }; | 251 | }; |
247 | 252 | ||
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 7e6e6dd966..39773633cc 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c | |||
@@ -53,6 +53,7 @@ struct tda9887 { | |||
53 | unsigned int config; | 53 | unsigned int config; |
54 | unsigned int pinnacle_id; | 54 | unsigned int pinnacle_id; |
55 | unsigned int using_v4l2; | 55 | unsigned int using_v4l2; |
56 | unsigned int radio_mode; | ||
56 | }; | 57 | }; |
57 | 58 | ||
58 | struct tvnorm { | 59 | struct tvnorm { |
@@ -212,12 +213,22 @@ static struct tvnorm tvnorms[] = { | |||
212 | } | 213 | } |
213 | }; | 214 | }; |
214 | 215 | ||
215 | static struct tvnorm radio = { | 216 | static struct tvnorm radio_stereo = { |
216 | .name = "radio", | 217 | .name = "Radio Stereo", |
218 | .b = ( cFmRadio | | ||
219 | cQSS ), | ||
220 | .c = ( cDeemphasisOFF | | ||
221 | cAudioGain6 ), | ||
222 | .e = ( cAudioIF_5_5 | | ||
223 | cRadioIF_38_90 ), | ||
224 | }; | ||
225 | |||
226 | static struct tvnorm radio_mono = { | ||
227 | .name = "Radio Mono", | ||
217 | .b = ( cFmRadio | | 228 | .b = ( cFmRadio | |
218 | cQSS ), | 229 | cQSS ), |
219 | .c = ( cDeemphasisON | | 230 | .c = ( cDeemphasisON | |
220 | cDeemphasis50 ), | 231 | cDeemphasis50), |
221 | .e = ( cAudioIF_5_5 | | 232 | .e = ( cAudioIF_5_5 | |
222 | cRadioIF_38_90 ), | 233 | cRadioIF_38_90 ), |
223 | }; | 234 | }; |
@@ -354,7 +365,10 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf) | |||
354 | int i; | 365 | int i; |
355 | 366 | ||
356 | if (t->radio) { | 367 | if (t->radio) { |
357 | norm = &radio; | 368 | if (t->radio_mode == V4L2_TUNER_MODE_MONO) |
369 | norm = &radio_mono; | ||
370 | else | ||
371 | norm = &radio_stereo; | ||
358 | } else { | 372 | } else { |
359 | for (i = 0; i < ARRAY_SIZE(tvnorms); i++) { | 373 | for (i = 0; i < ARRAY_SIZE(tvnorms); i++) { |
360 | if (tvnorms[i].std & t->std) { | 374 | if (tvnorms[i].std & t->std) { |
@@ -545,11 +559,14 @@ static int tda9887_configure(struct tda9887 *t) | |||
545 | 559 | ||
546 | memset(buf,0,sizeof(buf)); | 560 | memset(buf,0,sizeof(buf)); |
547 | tda9887_set_tvnorm(t,buf); | 561 | tda9887_set_tvnorm(t,buf); |
562 | |||
548 | buf[1] |= cOutputPort1Inactive; | 563 | buf[1] |= cOutputPort1Inactive; |
549 | buf[1] |= cOutputPort2Inactive; | 564 | buf[1] |= cOutputPort2Inactive; |
565 | |||
550 | if (UNSET != t->pinnacle_id) { | 566 | if (UNSET != t->pinnacle_id) { |
551 | tda9887_set_pinnacle(t,buf); | 567 | tda9887_set_pinnacle(t,buf); |
552 | } | 568 | } |
569 | |||
553 | tda9887_set_config(t,buf); | 570 | tda9887_set_config(t,buf); |
554 | tda9887_set_insmod(t,buf); | 571 | tda9887_set_insmod(t,buf); |
555 | 572 | ||
@@ -592,9 +609,12 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) | |||
592 | if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) | 609 | if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) |
593 | return -ENOMEM; | 610 | return -ENOMEM; |
594 | memset(t,0,sizeof(*t)); | 611 | memset(t,0,sizeof(*t)); |
612 | |||
595 | t->client = client_template; | 613 | t->client = client_template; |
596 | t->std = 0; | 614 | t->std = 0; |
597 | t->pinnacle_id = UNSET; | 615 | t->pinnacle_id = UNSET; |
616 | t->radio_mode = V4L2_TUNER_MODE_STEREO; | ||
617 | |||
598 | i2c_set_clientdata(&t->client, t); | 618 | i2c_set_clientdata(&t->client, t); |
599 | i2c_attach_client(&t->client); | 619 | i2c_attach_client(&t->client); |
600 | 620 | ||
@@ -733,6 +753,16 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
733 | } | 753 | } |
734 | break; | 754 | break; |
735 | } | 755 | } |
756 | case VIDIOC_S_TUNER: | ||
757 | { | ||
758 | struct v4l2_tuner* tuner = arg; | ||
759 | |||
760 | if (t->radio) { | ||
761 | t->radio_mode = tuner->audmode; | ||
762 | tda9887_configure (t); | ||
763 | } | ||
764 | break; | ||
765 | } | ||
736 | default: | 766 | default: |
737 | /* nothing */ | 767 | /* nothing */ |
738 | break; | 768 | break; |
@@ -740,7 +770,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
740 | return 0; | 770 | return 0; |
741 | } | 771 | } |
742 | 772 | ||
743 | static int tda9887_suspend(struct device * dev, pm_message_t state, u32 level) | 773 | static int tda9887_suspend(struct device * dev, u32 state, u32 level) |
744 | { | 774 | { |
745 | dprintk("tda9887: suspend\n"); | 775 | dprintk("tda9887: suspend\n"); |
746 | return 0; | 776 | return 0; |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 81882ddab8..eaabfc8587 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: tuner-core.c,v 1.5 2005/02/15 15:59:35 kraxel Exp $ | 2 | * $Id: tuner-core.c,v 1.15 2005/06/12 01:36:14 mchehab Exp $ |
3 | * | 3 | * |
4 | * i2c tv tuner chip device driver | 4 | * i2c tv tuner chip device driver |
5 | * core core, i.e. kernel interfaces, registering and so on | 5 | * core core, i.e. kernel interfaces, registering and so on |
@@ -23,6 +23,11 @@ | |||
23 | #include <media/tuner.h> | 23 | #include <media/tuner.h> |
24 | #include <media/audiochip.h> | 24 | #include <media/audiochip.h> |
25 | 25 | ||
26 | /* | ||
27 | * comment line bellow to return to old behavor, where only one I2C device is supported | ||
28 | */ | ||
29 | #define CONFIG_TUNER_MULTI_I2C /**/ | ||
30 | |||
26 | #define UNSET (-1U) | 31 | #define UNSET (-1U) |
27 | 32 | ||
28 | /* standard i2c insmod options */ | 33 | /* standard i2c insmod options */ |
@@ -53,13 +58,16 @@ MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); | |||
53 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
54 | 59 | ||
55 | static int this_adap; | 60 | static int this_adap; |
61 | #ifdef CONFIG_TUNER_MULTI_I2C | ||
62 | static unsigned short first_tuner, tv_tuner, radio_tuner; | ||
63 | #endif | ||
56 | 64 | ||
57 | static struct i2c_driver driver; | 65 | static struct i2c_driver driver; |
58 | static struct i2c_client client_template; | 66 | static struct i2c_client client_template; |
59 | 67 | ||
60 | /* ---------------------------------------------------------------------- */ | 68 | /* ---------------------------------------------------------------------- */ |
61 | 69 | ||
62 | // Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz | 70 | /* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */ |
63 | static void set_tv_freq(struct i2c_client *c, unsigned int freq) | 71 | static void set_tv_freq(struct i2c_client *c, unsigned int freq) |
64 | { | 72 | { |
65 | struct tuner *t = i2c_get_clientdata(c); | 73 | struct tuner *t = i2c_get_clientdata(c); |
@@ -73,14 +81,26 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
73 | return; | 81 | return; |
74 | } | 82 | } |
75 | if (freq < tv_range[0]*16 || freq > tv_range[1]*16) { | 83 | if (freq < tv_range[0]*16 || freq > tv_range[1]*16) { |
76 | /* FIXME: better do that chip-specific, but | 84 | |
77 | right now we don't have that in the config | 85 | if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) { |
78 | struct and this way is still better than no | 86 | /* V4L2_TUNER_CAP_LOW frequency */ |
79 | check at all */ | 87 | |
80 | tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n", | 88 | tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for TV. Tuners yet doesn't support converting it to valid freq.\n"); |
81 | freq/16,freq%16*100/16,tv_range[0],tv_range[1]); | 89 | |
82 | return; | 90 | t->tv_freq(c,freq>>10); |
91 | |||
92 | return; | ||
93 | } else { | ||
94 | /* FIXME: better do that chip-specific, but | ||
95 | right now we don't have that in the config | ||
96 | struct and this way is still better than no | ||
97 | check at all */ | ||
98 | tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n", | ||
99 | freq/16,freq%16*100/16,tv_range[0],tv_range[1]); | ||
100 | return; | ||
101 | } | ||
83 | } | 102 | } |
103 | tuner_dbg("62.5 Khz freq step selected for TV.\n"); | ||
84 | t->tv_freq(c,freq); | 104 | t->tv_freq(c,freq); |
85 | } | 105 | } |
86 | 106 | ||
@@ -97,11 +117,29 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
97 | return; | 117 | return; |
98 | } | 118 | } |
99 | if (freq < radio_range[0]*16 || freq > radio_range[1]*16) { | 119 | if (freq < radio_range[0]*16 || freq > radio_range[1]*16) { |
100 | tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n", | 120 | if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) { |
121 | /* V4L2_TUNER_CAP_LOW frequency */ | ||
122 | if (t->type == TUNER_TEA5767) { | ||
123 | tuner_info("radio freq step 62.5Hz (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000); | ||
124 | t->radio_freq(c,freq>>10); | ||
125 | return; | ||
126 | } | ||
127 | |||
128 | tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for Radio. Tuners yet doesn't support converting it to valid freq.\n"); | ||
129 | |||
130 | tuner_info("radio freq (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000); | ||
131 | |||
132 | t->radio_freq(c,freq>>10); | ||
133 | return; | ||
134 | |||
135 | } else { | ||
136 | tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n", | ||
101 | freq/16,freq%16*100/16, | 137 | freq/16,freq%16*100/16, |
102 | radio_range[0],radio_range[1]); | 138 | radio_range[0],radio_range[1]); |
103 | return; | 139 | return; |
140 | } | ||
104 | } | 141 | } |
142 | tuner_dbg("62.5 Khz freq step selected for Radio.\n"); | ||
105 | t->radio_freq(c,freq); | 143 | t->radio_freq(c,freq); |
106 | } | 144 | } |
107 | 145 | ||
@@ -129,8 +167,9 @@ static void set_type(struct i2c_client *c, unsigned int type) | |||
129 | { | 167 | { |
130 | struct tuner *t = i2c_get_clientdata(c); | 168 | struct tuner *t = i2c_get_clientdata(c); |
131 | 169 | ||
170 | tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type); | ||
132 | /* sanity check */ | 171 | /* sanity check */ |
133 | if (type == UNSET || type == TUNER_ABSENT) | 172 | if (type == UNSET || type == TUNER_ABSENT) |
134 | return; | 173 | return; |
135 | if (type >= tuner_count) | 174 | if (type >= tuner_count) |
136 | return; | 175 | return; |
@@ -145,6 +184,7 @@ static void set_type(struct i2c_client *c, unsigned int type) | |||
145 | return; | 184 | return; |
146 | 185 | ||
147 | t->initialized = 1; | 186 | t->initialized = 1; |
187 | |||
148 | t->type = type; | 188 | t->type = type; |
149 | switch (t->type) { | 189 | switch (t->type) { |
150 | case TUNER_MT2032: | 190 | case TUNER_MT2032: |
@@ -159,6 +199,53 @@ static void set_type(struct i2c_client *c, unsigned int type) | |||
159 | } | 199 | } |
160 | } | 200 | } |
161 | 201 | ||
202 | #ifdef CONFIG_TUNER_MULTI_I2C | ||
203 | #define CHECK_ADDR(tp,cmd,tun) if (client->addr!=tp) { \ | ||
204 | return 0; } else \ | ||
205 | tuner_info ("Cmd %s accepted to "tun"\n",cmd); | ||
206 | #define CHECK_MODE(cmd) if (t->mode == V4L2_TUNER_RADIO) { \ | ||
207 | CHECK_ADDR(radio_tuner,cmd,"radio") } else \ | ||
208 | { CHECK_ADDR(tv_tuner,cmd,"TV"); } | ||
209 | #else | ||
210 | #define CHECK_ADDR(tp,cmd,tun) tuner_info ("Cmd %s accepted to "tun"\n",cmd); | ||
211 | #define CHECK_MODE(cmd) tuner_info ("Cmd %s accepted\n",cmd); | ||
212 | #endif | ||
213 | |||
214 | #ifdef CONFIG_TUNER_MULTI_I2C | ||
215 | |||
216 | static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr) | ||
217 | { | ||
218 | /* ADDR_UNSET defaults to first available tuner */ | ||
219 | if ( tun_addr->addr == ADDR_UNSET ) { | ||
220 | if (first_tuner != c->addr) | ||
221 | return; | ||
222 | switch (tun_addr->v4l2_tuner) { | ||
223 | case V4L2_TUNER_RADIO: | ||
224 | radio_tuner=c->addr; | ||
225 | break; | ||
226 | default: | ||
227 | tv_tuner=c->addr; | ||
228 | break; | ||
229 | } | ||
230 | } else { | ||
231 | /* Sets tuner to its configured value */ | ||
232 | switch (tun_addr->v4l2_tuner) { | ||
233 | case V4L2_TUNER_RADIO: | ||
234 | radio_tuner=tun_addr->addr; | ||
235 | if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type); | ||
236 | return; | ||
237 | default: | ||
238 | tv_tuner=tun_addr->addr; | ||
239 | if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type); | ||
240 | return; | ||
241 | } | ||
242 | } | ||
243 | set_type(c,tun_addr->type); | ||
244 | } | ||
245 | #else | ||
246 | #define set_addr(c,tun_addr) set_type(c,(tun_addr)->type) | ||
247 | #endif | ||
248 | |||
162 | static char pal[] = "-"; | 249 | static char pal[] = "-"; |
163 | module_param_string(pal, pal, sizeof(pal), 0644); | 250 | module_param_string(pal, pal, sizeof(pal), 0644); |
164 | 251 | ||
@@ -197,8 +284,17 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
197 | { | 284 | { |
198 | struct tuner *t; | 285 | struct tuner *t; |
199 | 286 | ||
287 | #ifndef CONFIG_TUNER_MULTI_I2C | ||
200 | if (this_adap > 0) | 288 | if (this_adap > 0) |
201 | return -1; | 289 | return -1; |
290 | #else | ||
291 | /* by default, first I2C card is both tv and radio tuner */ | ||
292 | if (this_adap == 0) { | ||
293 | first_tuner = addr; | ||
294 | tv_tuner = addr; | ||
295 | radio_tuner = addr; | ||
296 | } | ||
297 | #endif | ||
202 | this_adap++; | 298 | this_adap++; |
203 | 299 | ||
204 | client_template.adapter = adap; | 300 | client_template.adapter = adap; |
@@ -211,11 +307,12 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
211 | memcpy(&t->i2c,&client_template,sizeof(struct i2c_client)); | 307 | memcpy(&t->i2c,&client_template,sizeof(struct i2c_client)); |
212 | i2c_set_clientdata(&t->i2c, t); | 308 | i2c_set_clientdata(&t->i2c, t); |
213 | t->type = UNSET; | 309 | t->type = UNSET; |
214 | t->radio_if2 = 10700*1000; // 10.7MHz - FM radio | 310 | t->radio_if2 = 10700*1000; /* 10.7MHz - FM radio */ |
215 | 311 | ||
216 | i2c_attach_client(&t->i2c); | 312 | i2c_attach_client(&t->i2c); |
217 | tuner_info("chip found @ 0x%x (%s)\n", | 313 | tuner_info("chip found @ 0x%x (%s)\n", |
218 | addr << 1, adap->name); | 314 | addr << 1, adap->name); |
315 | |||
219 | set_type(&t->i2c, t->type); | 316 | set_type(&t->i2c, t->type); |
220 | return 0; | 317 | return 0; |
221 | } | 318 | } |
@@ -228,6 +325,12 @@ static int tuner_probe(struct i2c_adapter *adap) | |||
228 | } | 325 | } |
229 | this_adap = 0; | 326 | this_adap = 0; |
230 | 327 | ||
328 | #ifdef CONFIG_TUNER_MULTI_I2C | ||
329 | first_tuner = 0; | ||
330 | tv_tuner = 0; | ||
331 | radio_tuner = 0; | ||
332 | #endif | ||
333 | |||
231 | if (adap->class & I2C_CLASS_TV_ANALOG) | 334 | if (adap->class & I2C_CLASS_TV_ANALOG) |
232 | return i2c_probe(adap, &addr_data, tuner_attach); | 335 | return i2c_probe(adap, &addr_data, tuner_attach); |
233 | return 0; | 336 | return 0; |
@@ -236,8 +339,14 @@ static int tuner_probe(struct i2c_adapter *adap) | |||
236 | static int tuner_detach(struct i2c_client *client) | 339 | static int tuner_detach(struct i2c_client *client) |
237 | { | 340 | { |
238 | struct tuner *t = i2c_get_clientdata(client); | 341 | struct tuner *t = i2c_get_clientdata(client); |
342 | int err; | ||
343 | |||
344 | err=i2c_detach_client(&t->i2c); | ||
345 | if (err) { | ||
346 | tuner_warn ("Client deregistration failed, client not detached.\n"); | ||
347 | return err; | ||
348 | } | ||
239 | 349 | ||
240 | i2c_detach_client(&t->i2c); | ||
241 | kfree(t); | 350 | kfree(t); |
242 | return 0; | 351 | return 0; |
243 | } | 352 | } |
@@ -256,18 +365,23 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
256 | unsigned int *iarg = (int*)arg; | 365 | unsigned int *iarg = (int*)arg; |
257 | 366 | ||
258 | switch (cmd) { | 367 | switch (cmd) { |
259 | |||
260 | /* --- configuration --- */ | 368 | /* --- configuration --- */ |
261 | case TUNER_SET_TYPE: | 369 | case TUNER_SET_TYPE: |
262 | set_type(client,*iarg); | 370 | set_type(client,*iarg); |
263 | break; | 371 | break; |
372 | case TUNER_SET_TYPE_ADDR: | ||
373 | set_addr(client,(struct tuner_addr *)arg); | ||
374 | break; | ||
264 | case AUDC_SET_RADIO: | 375 | case AUDC_SET_RADIO: |
376 | t->mode = V4L2_TUNER_RADIO; | ||
377 | CHECK_ADDR(tv_tuner,"AUDC_SET_RADIO","TV"); | ||
378 | |||
265 | if (V4L2_TUNER_RADIO != t->mode) { | 379 | if (V4L2_TUNER_RADIO != t->mode) { |
266 | set_tv_freq(client,400 * 16); | 380 | set_tv_freq(client,400 * 16); |
267 | t->mode = V4L2_TUNER_RADIO; | ||
268 | } | 381 | } |
269 | break; | 382 | break; |
270 | case AUDC_CONFIG_PINNACLE: | 383 | case AUDC_CONFIG_PINNACLE: |
384 | CHECK_ADDR(tv_tuner,"AUDC_CONFIG_PINNACLE","TV"); | ||
271 | switch (*iarg) { | 385 | switch (*iarg) { |
272 | case 2: | 386 | case 2: |
273 | tuner_dbg("pinnacle pal\n"); | 387 | tuner_dbg("pinnacle pal\n"); |
@@ -297,6 +411,8 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
297 | 411 | ||
298 | CHECK_V4L2; | 412 | CHECK_V4L2; |
299 | t->mode = V4L2_TUNER_ANALOG_TV; | 413 | t->mode = V4L2_TUNER_ANALOG_TV; |
414 | CHECK_ADDR(tv_tuner,"VIDIOCSCHAN","TV"); | ||
415 | |||
300 | if (vc->norm < ARRAY_SIZE(map)) | 416 | if (vc->norm < ARRAY_SIZE(map)) |
301 | t->std = map[vc->norm]; | 417 | t->std = map[vc->norm]; |
302 | tuner_fixup_std(t); | 418 | tuner_fixup_std(t); |
@@ -308,6 +424,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
308 | { | 424 | { |
309 | unsigned long *v = arg; | 425 | unsigned long *v = arg; |
310 | 426 | ||
427 | CHECK_MODE("VIDIOCSFREQ"); | ||
311 | CHECK_V4L2; | 428 | CHECK_V4L2; |
312 | set_freq(client,*v); | 429 | set_freq(client,*v); |
313 | return 0; | 430 | return 0; |
@@ -316,15 +433,27 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
316 | { | 433 | { |
317 | struct video_tuner *vt = arg; | 434 | struct video_tuner *vt = arg; |
318 | 435 | ||
436 | CHECK_ADDR(radio_tuner,"VIDIOCGTUNER","radio"); | ||
319 | CHECK_V4L2; | 437 | CHECK_V4L2; |
320 | if (V4L2_TUNER_RADIO == t->mode && t->has_signal) | 438 | if (V4L2_TUNER_RADIO == t->mode) { |
321 | vt->signal = t->has_signal(client); | 439 | if (t->has_signal) |
440 | vt->signal = t->has_signal(client); | ||
441 | if (t->is_stereo) { | ||
442 | if (t->is_stereo(client)) | ||
443 | vt-> flags |= VIDEO_TUNER_STEREO_ON; | ||
444 | else | ||
445 | vt-> flags &= 0xffff ^ VIDEO_TUNER_STEREO_ON; | ||
446 | } | ||
447 | vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */ | ||
448 | } | ||
449 | |||
322 | return 0; | 450 | return 0; |
323 | } | 451 | } |
324 | case VIDIOCGAUDIO: | 452 | case VIDIOCGAUDIO: |
325 | { | 453 | { |
326 | struct video_audio *va = arg; | 454 | struct video_audio *va = arg; |
327 | 455 | ||
456 | CHECK_ADDR(radio_tuner,"VIDIOCGAUDIO","radio"); | ||
328 | CHECK_V4L2; | 457 | CHECK_V4L2; |
329 | if (V4L2_TUNER_RADIO == t->mode && t->is_stereo) | 458 | if (V4L2_TUNER_RADIO == t->mode && t->is_stereo) |
330 | va->mode = t->is_stereo(client) | 459 | va->mode = t->is_stereo(client) |
@@ -339,6 +468,8 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
339 | 468 | ||
340 | SWITCH_V4L2; | 469 | SWITCH_V4L2; |
341 | t->mode = V4L2_TUNER_ANALOG_TV; | 470 | t->mode = V4L2_TUNER_ANALOG_TV; |
471 | CHECK_ADDR(tv_tuner,"VIDIOC_S_STD","TV"); | ||
472 | |||
342 | t->std = *id; | 473 | t->std = *id; |
343 | tuner_fixup_std(t); | 474 | tuner_fixup_std(t); |
344 | if (t->freq) | 475 | if (t->freq) |
@@ -349,6 +480,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
349 | { | 480 | { |
350 | struct v4l2_frequency *f = arg; | 481 | struct v4l2_frequency *f = arg; |
351 | 482 | ||
483 | CHECK_MODE("VIDIOC_S_FREQUENCY"); | ||
352 | SWITCH_V4L2; | 484 | SWITCH_V4L2; |
353 | if (V4L2_TUNER_RADIO == f->type && | 485 | if (V4L2_TUNER_RADIO == f->type && |
354 | V4L2_TUNER_RADIO != t->mode) | 486 | V4L2_TUNER_RADIO != t->mode) |
@@ -361,6 +493,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
361 | { | 493 | { |
362 | struct v4l2_frequency *f = arg; | 494 | struct v4l2_frequency *f = arg; |
363 | 495 | ||
496 | CHECK_MODE("VIDIOC_G_FREQUENCY"); | ||
364 | SWITCH_V4L2; | 497 | SWITCH_V4L2; |
365 | f->type = t->mode; | 498 | f->type = t->mode; |
366 | f->frequency = t->freq; | 499 | f->frequency = t->freq; |
@@ -370,14 +503,29 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
370 | { | 503 | { |
371 | struct v4l2_tuner *tuner = arg; | 504 | struct v4l2_tuner *tuner = arg; |
372 | 505 | ||
506 | CHECK_MODE("VIDIOC_G_TUNER"); | ||
373 | SWITCH_V4L2; | 507 | SWITCH_V4L2; |
374 | if (V4L2_TUNER_RADIO == t->mode && t->has_signal) | 508 | if (V4L2_TUNER_RADIO == t->mode) { |
375 | tuner->signal = t->has_signal(client); | 509 | if (t->has_signal) |
510 | tuner -> signal = t->has_signal(client); | ||
511 | if (t->is_stereo) { | ||
512 | if (t->is_stereo(client)) { | ||
513 | tuner -> capability |= V4L2_TUNER_CAP_STEREO; | ||
514 | tuner -> rxsubchans |= V4L2_TUNER_SUB_STEREO; | ||
515 | } else { | ||
516 | tuner -> rxsubchans &= 0xffff ^ V4L2_TUNER_SUB_STEREO; | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | /* Wow to deal with V4L2_TUNER_CAP_LOW ? For now, it accepts from low at 62.5KHz step to high at 62.5 Hz */ | ||
376 | tuner->rangelow = tv_range[0] * 16; | 521 | tuner->rangelow = tv_range[0] * 16; |
377 | tuner->rangehigh = tv_range[1] * 16; | 522 | // tuner->rangehigh = tv_range[1] * 16; |
523 | // tuner->rangelow = tv_range[0] * 16384; | ||
524 | tuner->rangehigh = tv_range[1] * 16384; | ||
378 | break; | 525 | break; |
379 | } | 526 | } |
380 | default: | 527 | default: |
528 | tuner_dbg ("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd); | ||
381 | /* nothing */ | 529 | /* nothing */ |
382 | break; | 530 | break; |
383 | } | 531 | } |
@@ -385,7 +533,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
385 | return 0; | 533 | return 0; |
386 | } | 534 | } |
387 | 535 | ||
388 | static int tuner_suspend(struct device * dev, pm_message_t state, u32 level) | 536 | static int tuner_suspend(struct device * dev, u32 state, u32 level) |
389 | { | 537 | { |
390 | struct i2c_client *c = container_of(dev, struct i2c_client, dev); | 538 | struct i2c_client *c = container_of(dev, struct i2c_client, dev); |
391 | struct tuner *t = i2c_get_clientdata(c); | 539 | struct tuner *t = i2c_get_clientdata(c); |
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 48c6ceff1d..539f305573 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: tuner-simple.c,v 1.10 2005/03/08 08:38:00 kraxel Exp $ | 2 | * $Id: tuner-simple.c,v 1.21 2005/06/10 19:53:26 nsh Exp $ |
3 | * | 3 | * |
4 | * i2c tv tuner chip device driver | 4 | * i2c tv tuner chip device driver |
5 | * controls all those simple 4-control-bytes style tuners. | 5 | * controls all those simple 4-control-bytes style tuners. |
@@ -212,7 +212,25 @@ static struct tunertype tuners[] = { | |||
212 | { "Philips FQ1236A MK4", Philips, NTSC, | 212 | { "Philips FQ1236A MK4", Philips, NTSC, |
213 | 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, | 213 | 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, |
214 | 214 | ||
215 | /* Should work for TVF8531MF, TVF8831MF, TVF8731MF */ | ||
216 | { "Ymec TVision TVF-8531MF", Philips, NTSC, | ||
217 | 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732}, | ||
218 | { "Ymec TVision TVF-5533MF", Philips, NTSC, | ||
219 | 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, | ||
220 | |||
221 | { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, | ||
222 | 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, | ||
223 | { "Tena TNF9533-D/IF", LGINNOTEK, PAL, | ||
224 | 16*160.25, 16*464.25, 0x01,0x02,0x08,0x8e,623}, | ||
225 | |||
226 | /* | ||
227 | * This entry is for TEA5767 FM radio only chip used on several boards | ||
228 | * w/TV tuner | ||
229 | */ | ||
230 | { TEA5767_TUNER_NAME, Philips, RADIO, | ||
231 | -1, -1, 0, 0, 0, TEA5767_LOW_LO_32768,0}, | ||
215 | }; | 232 | }; |
233 | |||
216 | unsigned const int tuner_count = ARRAY_SIZE(tuners); | 234 | unsigned const int tuner_count = ARRAY_SIZE(tuners); |
217 | 235 | ||
218 | /* ---------------------------------------------------------------------- */ | 236 | /* ---------------------------------------------------------------------- */ |
@@ -223,6 +241,7 @@ static int tuner_getstatus(struct i2c_client *c) | |||
223 | 241 | ||
224 | if (1 != i2c_master_recv(c,&byte,1)) | 242 | if (1 != i2c_master_recv(c,&byte,1)) |
225 | return 0; | 243 | return 0; |
244 | |||
226 | return byte; | 245 | return byte; |
227 | } | 246 | } |
228 | 247 | ||
@@ -231,17 +250,33 @@ static int tuner_getstatus(struct i2c_client *c) | |||
231 | #define TUNER_MODE 0x38 | 250 | #define TUNER_MODE 0x38 |
232 | #define TUNER_AFC 0x07 | 251 | #define TUNER_AFC 0x07 |
233 | 252 | ||
234 | #define TUNER_STEREO 0x10 /* radio mode */ | 253 | #define TUNER_STEREO 0x10 /* radio mode */ |
235 | #define TUNER_SIGNAL 0x07 /* radio mode */ | 254 | #define TUNER_STEREO_MK3 0x04 /* radio mode */ |
255 | #define TUNER_SIGNAL 0x07 /* radio mode */ | ||
236 | 256 | ||
237 | static int tuner_signal(struct i2c_client *c) | 257 | static int tuner_signal(struct i2c_client *c) |
238 | { | 258 | { |
239 | return (tuner_getstatus(c) & TUNER_SIGNAL)<<13; | 259 | return (tuner_getstatus(c) & TUNER_SIGNAL) << 13; |
240 | } | 260 | } |
241 | 261 | ||
242 | static int tuner_stereo(struct i2c_client *c) | 262 | static int tuner_stereo(struct i2c_client *c) |
243 | { | 263 | { |
244 | return (tuner_getstatus (c) & TUNER_STEREO); | 264 | int stereo, status; |
265 | struct tuner *t = i2c_get_clientdata(c); | ||
266 | |||
267 | status = tuner_getstatus (c); | ||
268 | |||
269 | switch (t->type) { | ||
270 | case TUNER_PHILIPS_FM1216ME_MK3: | ||
271 | case TUNER_PHILIPS_FM1236_MK3: | ||
272 | case TUNER_PHILIPS_FM1256_IH3: | ||
273 | stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); | ||
274 | break; | ||
275 | default: | ||
276 | stereo = status & TUNER_STEREO; | ||
277 | } | ||
278 | |||
279 | return stereo; | ||
245 | } | 280 | } |
246 | 281 | ||
247 | #if 0 /* unused */ | 282 | #if 0 /* unused */ |
@@ -424,6 +459,14 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
424 | buffer[2] = tun->config; | 459 | buffer[2] = tun->config; |
425 | 460 | ||
426 | switch (t->type) { | 461 | switch (t->type) { |
462 | case TUNER_TENA_9533_DI: | ||
463 | case TUNER_YMEC_TVF_5533MF: | ||
464 | |||
465 | /*These values are empirically determinated */ | ||
466 | div = (freq*122)/16 - 20; | ||
467 | buffer[2] = 0x88; /* could be also 0x80 */ | ||
468 | buffer[3] = 0x19; /* could be also 0x10, 0x18, 0x99 */ | ||
469 | break; | ||
427 | case TUNER_PHILIPS_FM1216ME_MK3: | 470 | case TUNER_PHILIPS_FM1216ME_MK3: |
428 | case TUNER_PHILIPS_FM1236_MK3: | 471 | case TUNER_PHILIPS_FM1236_MK3: |
429 | buffer[3] = 0x19; | 472 | buffer[3] = 0x19; |
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 41b635e0d3..9a493bea76 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c | |||
@@ -285,7 +285,6 @@ static int chip_thread(void *data) | |||
285 | schedule(); | 285 | schedule(); |
286 | } | 286 | } |
287 | remove_wait_queue(&chip->wq, &wait); | 287 | remove_wait_queue(&chip->wq, &wait); |
288 | try_to_freeze(PF_FREEZE); | ||
289 | if (chip->done || signal_pending(current)) | 288 | if (chip->done || signal_pending(current)) |
290 | break; | 289 | break; |
291 | dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c)); | 290 | dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c)); |
@@ -1237,17 +1236,17 @@ static int ta8874z_checkit(struct CHIPSTATE *chip) | |||
1237 | /* audio chip descriptions - struct CHIPDESC */ | 1236 | /* audio chip descriptions - struct CHIPDESC */ |
1238 | 1237 | ||
1239 | /* insmod options to enable/disable individual audio chips */ | 1238 | /* insmod options to enable/disable individual audio chips */ |
1240 | int tda8425 = 1; | 1239 | static int tda8425 = 1; |
1241 | int tda9840 = 1; | 1240 | static int tda9840 = 1; |
1242 | int tda9850 = 1; | 1241 | static int tda9850 = 1; |
1243 | int tda9855 = 1; | 1242 | static int tda9855 = 1; |
1244 | int tda9873 = 1; | 1243 | static int tda9873 = 1; |
1245 | int tda9874a = 1; | 1244 | static int tda9874a = 1; |
1246 | int tea6300 = 0; // address clash with msp34xx | 1245 | static int tea6300 = 0; // address clash with msp34xx |
1247 | int tea6320 = 0; // address clash with msp34xx | 1246 | static int tea6320 = 0; // address clash with msp34xx |
1248 | int tea6420 = 1; | 1247 | static int tea6420 = 1; |
1249 | int pic16c54 = 1; | 1248 | static int pic16c54 = 1; |
1250 | int ta8874z = 0; // address clash with tda9840 | 1249 | static int ta8874z = 0; // address clash with tda9840 |
1251 | 1250 | ||
1252 | module_param(tda8425, int, 0444); | 1251 | module_param(tda8425, int, 0444); |
1253 | module_param(tda9840, int, 0444); | 1252 | module_param(tda9840, int, 0444); |
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 3d21697379..0f03c25489 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
@@ -75,7 +75,7 @@ hauppauge_tuner_fmt[] = | |||
75 | { 0x00000007, "PAL(B/G)" }, | 75 | { 0x00000007, "PAL(B/G)" }, |
76 | { 0x00001000, "NTSC(M)" }, | 76 | { 0x00001000, "NTSC(M)" }, |
77 | { 0x00000010, "PAL(I)" }, | 77 | { 0x00000010, "PAL(I)" }, |
78 | { 0x00400000, "SECAM(L/L�)" }, | 78 | { 0x00400000, "SECAM(L/L´)" }, |
79 | { 0x00000e00, "PAL(D/K)" }, | 79 | { 0x00000e00, "PAL(D/K)" }, |
80 | { 0x03000000, "ATSC Digital" }, | 80 | { 0x03000000, "ATSC Digital" }, |
81 | }; | 81 | }; |
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index eafd7061b3..51b99cdbf2 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c | |||
@@ -1,3 +1,7 @@ | |||
1 | /* | ||
2 | * $Id: tvmixer.c,v 1.8 2005/06/12 04:19:19 mchehab Exp $ | ||
3 | */ | ||
4 | |||
1 | #include <linux/module.h> | 5 | #include <linux/module.h> |
2 | #include <linux/moduleparam.h> | 6 | #include <linux/moduleparam.h> |
3 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index b0d4bcb027..70ecbdb802 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: v4l1-compat.c,v 1.9 2005/06/12 04:19:19 mchehab Exp $ | ||
3 | * | ||
2 | * Video for Linux Two | 4 | * Video for Linux Two |
3 | * Backward Compatibility Layer | 5 | * Backward Compatibility Layer |
4 | * | 6 | * |
@@ -15,14 +17,11 @@ | |||
15 | * | 17 | * |
16 | */ | 18 | */ |
17 | 19 | ||
18 | #ifndef __KERNEL__ | ||
19 | #define __KERNEL__ | ||
20 | #endif | ||
21 | |||
22 | #include <linux/config.h> | 20 | #include <linux/config.h> |
23 | 21 | ||
24 | #include <linux/init.h> | 22 | #include <linux/init.h> |
25 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | ||
26 | #include <linux/types.h> | 25 | #include <linux/types.h> |
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
28 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
@@ -787,12 +786,15 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
787 | !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) | 786 | !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) |
788 | aud->step = qctrl2.step; | 787 | aud->step = qctrl2.step; |
789 | aud->mode = 0; | 788 | aud->mode = 0; |
789 | |||
790 | memset(&tun2,0,sizeof(tun2)); | ||
790 | err = drv(inode, file, VIDIOC_G_TUNER, &tun2); | 791 | err = drv(inode, file, VIDIOC_G_TUNER, &tun2); |
791 | if (err < 0) { | 792 | if (err < 0) { |
792 | dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err); | 793 | dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err); |
793 | err = 0; | 794 | err = 0; |
794 | break; | 795 | break; |
795 | } | 796 | } |
797 | |||
796 | if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2) | 798 | if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2) |
797 | aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; | 799 | aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; |
798 | else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) | 800 | else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) |
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig index 8d132b0d6b..06e8eb19a0 100644 --- a/drivers/message/i2o/Kconfig +++ b/drivers/message/i2o/Kconfig | |||
@@ -24,10 +24,28 @@ config I2O | |||
24 | 24 | ||
25 | If unsure, say N. | 25 | If unsure, say N. |
26 | 26 | ||
27 | config I2O_EXT_ADAPTEC | ||
28 | bool "Enable Adaptec extensions" | ||
29 | depends on I2O | ||
30 | default y | ||
31 | ---help--- | ||
32 | Say Y for support of raidutils for Adaptec I2O controllers. You also | ||
33 | have to say Y to "I2O Configuration support", "I2O SCSI OSM" below | ||
34 | and to "SCSI generic support" under "SCSI device configuration". | ||
35 | |||
36 | config I2O_EXT_ADAPTEC_DMA64 | ||
37 | bool "Enable 64-bit DMA" | ||
38 | depends on I2O_EXT_ADAPTEC && ( 64BIT || HIGHMEM64G ) | ||
39 | default y | ||
40 | ---help--- | ||
41 | Say Y for support of 64-bit DMA transfer mode on Adaptec I2O | ||
42 | controllers. | ||
43 | Note: You need at least firmware version 3709. | ||
44 | |||
27 | config I2O_CONFIG | 45 | config I2O_CONFIG |
28 | tristate "I2O Configuration support" | 46 | tristate "I2O Configuration support" |
29 | depends on PCI && I2O | 47 | depends on I2O |
30 | help | 48 | ---help--- |
31 | Say Y for support of the configuration interface for the I2O adapters. | 49 | Say Y for support of the configuration interface for the I2O adapters. |
32 | If you have a RAID controller from Adaptec and you want to use the | 50 | If you have a RAID controller from Adaptec and you want to use the |
33 | raidutils to manage your RAID array, you have to say Y here. | 51 | raidutils to manage your RAID array, you have to say Y here. |
@@ -35,10 +53,28 @@ config I2O_CONFIG | |||
35 | To compile this support as a module, choose M here: the | 53 | To compile this support as a module, choose M here: the |
36 | module will be called i2o_config. | 54 | module will be called i2o_config. |
37 | 55 | ||
56 | config I2O_CONFIG_OLD_IOCTL | ||
57 | bool "Enable ioctls (OBSOLETE)" | ||
58 | depends on I2O_CONFIG | ||
59 | default y | ||
60 | ---help--- | ||
61 | Enables old ioctls. | ||
62 | |||
63 | config I2O_BUS | ||
64 | tristate "I2O Bus Adapter OSM" | ||
65 | depends on I2O | ||
66 | ---help--- | ||
67 | Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM | ||
68 | provides access to the busses on the I2O controller. The main purpose | ||
69 | is to rescan the bus to find new devices. | ||
70 | |||
71 | To compile this support as a module, choose M here: the | ||
72 | module will be called i2o_bus. | ||
73 | |||
38 | config I2O_BLOCK | 74 | config I2O_BLOCK |
39 | tristate "I2O Block OSM" | 75 | tristate "I2O Block OSM" |
40 | depends on I2O | 76 | depends on I2O |
41 | help | 77 | ---help--- |
42 | Include support for the I2O Block OSM. The Block OSM presents disk | 78 | Include support for the I2O Block OSM. The Block OSM presents disk |
43 | and other structured block devices to the operating system. If you | 79 | and other structured block devices to the operating system. If you |
44 | are using an RAID controller, you could access the array only by | 80 | are using an RAID controller, you could access the array only by |
@@ -51,7 +87,7 @@ config I2O_BLOCK | |||
51 | config I2O_SCSI | 87 | config I2O_SCSI |
52 | tristate "I2O SCSI OSM" | 88 | tristate "I2O SCSI OSM" |
53 | depends on I2O && SCSI | 89 | depends on I2O && SCSI |
54 | help | 90 | ---help--- |
55 | Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel | 91 | Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel |
56 | I2O controller. You can use both the SCSI and Block OSM together if | 92 | I2O controller. You can use both the SCSI and Block OSM together if |
57 | you wish. To access a RAID array, you must use the Block OSM driver. | 93 | you wish. To access a RAID array, you must use the Block OSM driver. |
@@ -63,7 +99,7 @@ config I2O_SCSI | |||
63 | config I2O_PROC | 99 | config I2O_PROC |
64 | tristate "I2O /proc support" | 100 | tristate "I2O /proc support" |
65 | depends on I2O | 101 | depends on I2O |
66 | help | 102 | ---help--- |
67 | If you say Y here and to "/proc file system support", you will be | 103 | If you say Y here and to "/proc file system support", you will be |
68 | able to read I2O related information from the virtual directory | 104 | able to read I2O related information from the virtual directory |
69 | /proc/i2o. | 105 | /proc/i2o. |
diff --git a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile index aabc6cdc3f..2c2e39aa1e 100644 --- a/drivers/message/i2o/Makefile +++ b/drivers/message/i2o/Makefile | |||
@@ -6,8 +6,11 @@ | |||
6 | # | 6 | # |
7 | 7 | ||
8 | i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o | 8 | i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o |
9 | i2o_bus-y += bus-osm.o | ||
10 | i2o_config-y += config-osm.o | ||
9 | obj-$(CONFIG_I2O) += i2o_core.o | 11 | obj-$(CONFIG_I2O) += i2o_core.o |
10 | obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o | 12 | obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o |
13 | obj-$(CONFIG_I2O_BUS) += i2o_bus.o | ||
11 | obj-$(CONFIG_I2O_BLOCK) += i2o_block.o | 14 | obj-$(CONFIG_I2O_BLOCK) += i2o_block.o |
12 | obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o | 15 | obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o |
13 | obj-$(CONFIG_I2O_PROC) += i2o_proc.o | 16 | obj-$(CONFIG_I2O_PROC) += i2o_proc.o |
diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c new file mode 100644 index 0000000000..151b228e1c --- /dev/null +++ b/drivers/message/i2o/bus-osm.c | |||
@@ -0,0 +1,164 @@ | |||
1 | /* | ||
2 | * Bus Adapter OSM | ||
3 | * | ||
4 | * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * Fixes/additions: | ||
12 | * Markus Lidel <Markus.Lidel@shadowconnect.com> | ||
13 | * initial version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/i2o.h> | ||
18 | |||
19 | #define OSM_NAME "bus-osm" | ||
20 | #define OSM_VERSION "$Rev$" | ||
21 | #define OSM_DESCRIPTION "I2O Bus Adapter OSM" | ||
22 | |||
23 | static struct i2o_driver i2o_bus_driver; | ||
24 | |||
25 | /* Bus OSM class handling definition */ | ||
26 | static struct i2o_class_id i2o_bus_class_id[] = { | ||
27 | {I2O_CLASS_BUS_ADAPTER}, | ||
28 | {I2O_CLASS_END} | ||
29 | }; | ||
30 | |||
31 | /** | ||
32 | * i2o_bus_scan - Scan the bus for new devices | ||
33 | * @dev: I2O device of the bus, which should be scanned | ||
34 | * | ||
35 | * Scans the bus dev for new / removed devices. After the scan a new LCT | ||
36 | * will be fetched automatically. | ||
37 | * | ||
38 | * Returns 0 on success or negative error code on failure. | ||
39 | */ | ||
40 | static int i2o_bus_scan(struct i2o_device *dev) | ||
41 | { | ||
42 | struct i2o_message __iomem *msg; | ||
43 | u32 m; | ||
44 | |||
45 | m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
46 | if (m == I2O_QUEUE_EMPTY) | ||
47 | return -ETIMEDOUT; | ||
48 | |||
49 | writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); | ||
50 | writel(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.tid, | ||
51 | &msg->u.head[1]); | ||
52 | |||
53 | return i2o_msg_post_wait(dev->iop, m, 60); | ||
54 | }; | ||
55 | |||
56 | /** | ||
57 | * i2o_bus_store_scan - Scan the I2O Bus Adapter | ||
58 | * @d: device which should be scanned | ||
59 | * | ||
60 | * Returns count. | ||
61 | */ | ||
62 | static ssize_t i2o_bus_store_scan(struct device *d, struct device_attribute *attr, const char *buf, | ||
63 | size_t count) | ||
64 | { | ||
65 | struct i2o_device *i2o_dev = to_i2o_device(d); | ||
66 | int rc; | ||
67 | |||
68 | if ((rc = i2o_bus_scan(i2o_dev))) | ||
69 | osm_warn("bus scan failed %d\n", rc); | ||
70 | |||
71 | return count; | ||
72 | } | ||
73 | |||
74 | /* Bus Adapter OSM device attributes */ | ||
75 | static DEVICE_ATTR(scan, S_IWUSR, NULL, i2o_bus_store_scan); | ||
76 | |||
77 | /** | ||
78 | * i2o_bus_probe - verify if dev is a I2O Bus Adapter device and install it | ||
79 | * @dev: device to verify if it is a I2O Bus Adapter device | ||
80 | * | ||
81 | * Because we want all Bus Adapters always return 0. | ||
82 | * | ||
83 | * Returns 0. | ||
84 | */ | ||
85 | static int i2o_bus_probe(struct device *dev) | ||
86 | { | ||
87 | struct i2o_device *i2o_dev = to_i2o_device(get_device(dev)); | ||
88 | |||
89 | device_create_file(dev, &dev_attr_scan); | ||
90 | |||
91 | osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid); | ||
92 | |||
93 | return 0; | ||
94 | }; | ||
95 | |||
96 | /** | ||
97 | * i2o_bus_remove - remove the I2O Bus Adapter device from the system again | ||
98 | * @dev: I2O Bus Adapter device which should be removed | ||
99 | * | ||
100 | * Always returns 0. | ||
101 | */ | ||
102 | static int i2o_bus_remove(struct device *dev) | ||
103 | { | ||
104 | struct i2o_device *i2o_dev = to_i2o_device(dev); | ||
105 | |||
106 | device_remove_file(dev, &dev_attr_scan); | ||
107 | |||
108 | put_device(dev); | ||
109 | |||
110 | osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid); | ||
111 | |||
112 | return 0; | ||
113 | }; | ||
114 | |||
115 | /* Bus Adapter OSM driver struct */ | ||
116 | static struct i2o_driver i2o_bus_driver = { | ||
117 | .name = OSM_NAME, | ||
118 | .classes = i2o_bus_class_id, | ||
119 | .driver = { | ||
120 | .probe = i2o_bus_probe, | ||
121 | .remove = i2o_bus_remove, | ||
122 | }, | ||
123 | }; | ||
124 | |||
125 | /** | ||
126 | * i2o_bus_init - Bus Adapter OSM initialization function | ||
127 | * | ||
128 | * Only register the Bus Adapter OSM in the I2O core. | ||
129 | * | ||
130 | * Returns 0 on success or negative error code on failure. | ||
131 | */ | ||
132 | static int __init i2o_bus_init(void) | ||
133 | { | ||
134 | int rc; | ||
135 | |||
136 | printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); | ||
137 | |||
138 | /* Register Bus Adapter OSM into I2O core */ | ||
139 | rc = i2o_driver_register(&i2o_bus_driver); | ||
140 | if (rc) { | ||
141 | osm_err("Could not register Bus Adapter OSM\n"); | ||
142 | return rc; | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | }; | ||
147 | |||
148 | /** | ||
149 | * i2o_bus_exit - Bus Adapter OSM exit function | ||
150 | * | ||
151 | * Unregisters Bus Adapter OSM from I2O core. | ||
152 | */ | ||
153 | static void __exit i2o_bus_exit(void) | ||
154 | { | ||
155 | i2o_driver_unregister(&i2o_bus_driver); | ||
156 | }; | ||
157 | |||
158 | MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>"); | ||
159 | MODULE_LICENSE("GPL"); | ||
160 | MODULE_DESCRIPTION(OSM_DESCRIPTION); | ||
161 | MODULE_VERSION(OSM_VERSION); | ||
162 | |||
163 | module_init(i2o_bus_init); | ||
164 | module_exit(i2o_bus_exit); | ||
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c new file mode 100644 index 0000000000..d0267609a9 --- /dev/null +++ b/drivers/message/i2o/config-osm.c | |||
@@ -0,0 +1,579 @@ | |||
1 | /* | ||
2 | * Configuration OSM | ||
3 | * | ||
4 | * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * Fixes/additions: | ||
12 | * Markus Lidel <Markus.Lidel@shadowconnect.com> | ||
13 | * initial version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/i2o.h> | ||
18 | #include <linux/namei.h> | ||
19 | |||
20 | #include <asm/uaccess.h> | ||
21 | |||
22 | #define OSM_NAME "config-osm" | ||
23 | #define OSM_VERSION "1.248" | ||
24 | #define OSM_DESCRIPTION "I2O Configuration OSM" | ||
25 | |||
26 | /* access mode user rw */ | ||
27 | #define S_IWRSR (S_IRUSR | S_IWUSR) | ||
28 | |||
29 | static struct i2o_driver i2o_config_driver; | ||
30 | |||
31 | /* Special file operations for sysfs */ | ||
32 | struct fops_attribute { | ||
33 | struct bin_attribute bin; | ||
34 | struct file_operations fops; | ||
35 | }; | ||
36 | |||
37 | /** | ||
38 | * sysfs_read_dummy | ||
39 | */ | ||
40 | static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset, | ||
41 | size_t count) | ||
42 | { | ||
43 | return 0; | ||
44 | }; | ||
45 | |||
46 | /** | ||
47 | * sysfs_write_dummy | ||
48 | */ | ||
49 | static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset, | ||
50 | size_t count) | ||
51 | { | ||
52 | return 0; | ||
53 | }; | ||
54 | |||
55 | /** | ||
56 | * sysfs_create_fops_file - Creates attribute with special file operations | ||
57 | * @kobj: kobject which should contains the attribute | ||
58 | * @attr: attributes which should be used to create file | ||
59 | * | ||
60 | * First creates attribute @attr in kobject @kobj. If it is the first time | ||
61 | * this function is called, merge old fops from sysfs with new one and | ||
62 | * write it back. Afterwords the new fops will be set for the created | ||
63 | * attribute. | ||
64 | * | ||
65 | * Returns 0 on success or negative error code on failure. | ||
66 | */ | ||
67 | static int sysfs_create_fops_file(struct kobject *kobj, | ||
68 | struct fops_attribute *attr) | ||
69 | { | ||
70 | struct file_operations tmp, *fops; | ||
71 | struct dentry *d; | ||
72 | struct qstr qstr; | ||
73 | int rc; | ||
74 | |||
75 | fops = &attr->fops; | ||
76 | |||
77 | if (fops->read) | ||
78 | attr->bin.read = sysfs_read_dummy; | ||
79 | |||
80 | if (fops->write) | ||
81 | attr->bin.write = sysfs_write_dummy; | ||
82 | |||
83 | if ((rc = sysfs_create_bin_file(kobj, &attr->bin))) | ||
84 | return rc; | ||
85 | |||
86 | qstr.name = attr->bin.attr.name; | ||
87 | qstr.len = strlen(qstr.name); | ||
88 | qstr.hash = full_name_hash(qstr.name, qstr.len); | ||
89 | |||
90 | if ((d = lookup_hash(&qstr, kobj->dentry))) { | ||
91 | if (!fops->owner) { | ||
92 | memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp)); | ||
93 | if (fops->read) | ||
94 | tmp.read = fops->read; | ||
95 | if (fops->write) | ||
96 | tmp.write = fops->write; | ||
97 | memcpy(fops, &tmp, sizeof(tmp)); | ||
98 | } | ||
99 | |||
100 | d->d_inode->i_fop = fops; | ||
101 | } else | ||
102 | sysfs_remove_bin_file(kobj, &attr->bin); | ||
103 | |||
104 | return -ENOENT; | ||
105 | }; | ||
106 | |||
107 | /** | ||
108 | * sysfs_remove_fops_file - Remove attribute with special file operations | ||
109 | * @kobj: kobject which contains the attribute | ||
110 | * @attr: attributes which are used to create file | ||
111 | * | ||
112 | * Only wrapper arround sysfs_remove_bin_file() | ||
113 | * | ||
114 | * Returns 0 on success or negative error code on failure. | ||
115 | */ | ||
116 | static inline int sysfs_remove_fops_file(struct kobject *kobj, | ||
117 | struct fops_attribute *attr) | ||
118 | { | ||
119 | return sysfs_remove_bin_file(kobj, &attr->bin); | ||
120 | }; | ||
121 | |||
122 | /** | ||
123 | * i2o_config_read_hrt - Returns the HRT of the controller | ||
124 | * @kob: kernel object handle | ||
125 | * @buf: buffer into which the HRT should be copied | ||
126 | * @off: file offset | ||
127 | * @count: number of bytes to read | ||
128 | * | ||
129 | * Put @count bytes starting at @off into @buf from the HRT of the I2O | ||
130 | * controller corresponding to @kobj. | ||
131 | * | ||
132 | * Returns number of bytes copied into buffer. | ||
133 | */ | ||
134 | static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf, | ||
135 | loff_t offset, size_t count) | ||
136 | { | ||
137 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
138 | i2o_hrt *hrt = c->hrt.virt; | ||
139 | |||
140 | u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4; | ||
141 | |||
142 | if (offset > size) | ||
143 | return 0; | ||
144 | |||
145 | if (offset + count > size) | ||
146 | count = size - offset; | ||
147 | |||
148 | memcpy(buf, (u8 *) hrt + offset, count); | ||
149 | |||
150 | return count; | ||
151 | }; | ||
152 | |||
153 | /** | ||
154 | * i2o_config_read_lct - Returns the LCT of the controller | ||
155 | * @kob: kernel object handle | ||
156 | * @buf: buffer into which the LCT should be copied | ||
157 | * @off: file offset | ||
158 | * @count: number of bytes to read | ||
159 | * | ||
160 | * Put @count bytes starting at @off into @buf from the LCT of the I2O | ||
161 | * controller corresponding to @kobj. | ||
162 | * | ||
163 | * Returns number of bytes copied into buffer. | ||
164 | */ | ||
165 | static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf, | ||
166 | loff_t offset, size_t count) | ||
167 | { | ||
168 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
169 | u32 size = c->lct->table_size * 4; | ||
170 | |||
171 | if (offset > size) | ||
172 | return 0; | ||
173 | |||
174 | if (offset + count > size) | ||
175 | count = size - offset; | ||
176 | |||
177 | memcpy(buf, (u8 *) c->lct + offset, count); | ||
178 | |||
179 | return count; | ||
180 | }; | ||
181 | |||
182 | #define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \ | ||
183 | static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \ | ||
184 | return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \ | ||
185 | };\ | ||
186 | \ | ||
187 | static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \ | ||
188 | return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \ | ||
189 | }; \ | ||
190 | \ | ||
191 | static struct fops_attribute i2o_config_attr_##_name = { \ | ||
192 | .bin = { .attr = { .name = __stringify(_name), .mode = _mode, \ | ||
193 | .owner = THIS_MODULE }, \ | ||
194 | .size = 0, }, \ | ||
195 | .fops = { .write = i2o_config_##_name##_write, \ | ||
196 | .read = i2o_config_##_name##_read} \ | ||
197 | }; | ||
198 | |||
199 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
200 | |||
201 | /** | ||
202 | * i2o_config_dpt_reagion - Converts type and id to flash region | ||
203 | * @swtype: type of software module reading | ||
204 | * @swid: id of software which should be read | ||
205 | * | ||
206 | * Converts type and id from I2O spec to the matching region for DPT / | ||
207 | * Adaptec controllers. | ||
208 | * | ||
209 | * Returns region which match type and id or -1 on error. | ||
210 | */ | ||
211 | static u32 i2o_config_dpt_region(u8 swtype, u8 swid) | ||
212 | { | ||
213 | switch (swtype) { | ||
214 | case I2O_SOFTWARE_MODULE_IRTOS: | ||
215 | /* | ||
216 | * content: operation firmware | ||
217 | * region size: | ||
218 | * 0xbc000 for 2554, 3754, 2564, 3757 | ||
219 | * 0x170000 for 2865 | ||
220 | * 0x17c000 for 3966 | ||
221 | */ | ||
222 | if (!swid) | ||
223 | return 0; | ||
224 | |||
225 | break; | ||
226 | |||
227 | case I2O_SOFTWARE_MODULE_IOP_PRIVATE: | ||
228 | /* | ||
229 | * content: BIOS and SMOR | ||
230 | * BIOS size: first 0x8000 bytes | ||
231 | * region size: | ||
232 | * 0x40000 for 2554, 3754, 2564, 3757 | ||
233 | * 0x80000 for 2865, 3966 | ||
234 | */ | ||
235 | if (!swid) | ||
236 | return 1; | ||
237 | |||
238 | break; | ||
239 | |||
240 | case I2O_SOFTWARE_MODULE_IOP_CONFIG: | ||
241 | switch (swid) { | ||
242 | case 0: | ||
243 | /* | ||
244 | * content: NVRAM defaults | ||
245 | * region size: 0x2000 bytes | ||
246 | */ | ||
247 | return 2; | ||
248 | case 1: | ||
249 | /* | ||
250 | * content: serial number | ||
251 | * region size: 0x2000 bytes | ||
252 | */ | ||
253 | return 3; | ||
254 | } | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | return -1; | ||
259 | }; | ||
260 | |||
261 | #endif | ||
262 | |||
263 | /** | ||
264 | * i2o_config_sw_read - Read a software module from controller | ||
265 | * @file: file pointer | ||
266 | * @buf: buffer into which the data should be copied | ||
267 | * @count: number of bytes to read | ||
268 | * @off: file offset | ||
269 | * @swtype: type of software module reading | ||
270 | * @swid: id of software which should be read | ||
271 | * | ||
272 | * Transfers @count bytes at offset @offset from IOP into buffer using | ||
273 | * type @swtype and id @swid as described in I2O spec. | ||
274 | * | ||
275 | * Returns number of bytes copied into buffer or error code on failure. | ||
276 | */ | ||
277 | static ssize_t i2o_config_sw_read(struct file *file, char __user * buf, | ||
278 | size_t count, loff_t * offset, u8 swtype, | ||
279 | u32 swid) | ||
280 | { | ||
281 | struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; | ||
282 | struct kobject *kobj = sd->s_element; | ||
283 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
284 | u32 m, function = I2O_CMD_SW_UPLOAD; | ||
285 | struct i2o_dma buffer; | ||
286 | struct i2o_message __iomem *msg; | ||
287 | u32 __iomem *mptr; | ||
288 | int rc, status; | ||
289 | |||
290 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
291 | if (m == I2O_QUEUE_EMPTY) | ||
292 | return -EBUSY; | ||
293 | |||
294 | mptr = &msg->body[3]; | ||
295 | |||
296 | if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) { | ||
297 | i2o_msg_nop(c, m); | ||
298 | return rc; | ||
299 | } | ||
300 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
301 | if (c->adaptec) { | ||
302 | mptr = &msg->body[4]; | ||
303 | function = I2O_CMD_PRIVATE; | ||
304 | |||
305 | writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); | ||
306 | |||
307 | writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ, | ||
308 | &msg->body[0]); | ||
309 | writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); | ||
310 | writel(*offset, &msg->body[2]); | ||
311 | writel(count, &msg->body[3]); | ||
312 | } else | ||
313 | #endif | ||
314 | writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); | ||
315 | |||
316 | writel(0xD0000000 | count, mptr++); | ||
317 | writel(buffer.phys, mptr); | ||
318 | |||
319 | writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); | ||
320 | writel(i2o_config_driver.context, &msg->u.head[2]); | ||
321 | writel(0, &msg->u.head[3]); | ||
322 | |||
323 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
324 | if (!c->adaptec) | ||
325 | #endif | ||
326 | { | ||
327 | writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); | ||
328 | writel(0, &msg->body[1]); | ||
329 | writel(swid, &msg->body[2]); | ||
330 | } | ||
331 | |||
332 | status = i2o_msg_post_wait_mem(c, m, 60, &buffer); | ||
333 | |||
334 | if (status == I2O_POST_WAIT_OK) { | ||
335 | if (!(rc = copy_to_user(buf, buffer.virt, count))) { | ||
336 | rc = count; | ||
337 | *offset += count; | ||
338 | } | ||
339 | } else | ||
340 | rc = -EIO; | ||
341 | |||
342 | if (status != -ETIMEDOUT) | ||
343 | i2o_dma_free(&c->pdev->dev, &buffer); | ||
344 | |||
345 | return rc; | ||
346 | }; | ||
347 | |||
348 | /** | ||
349 | * i2o_config_sw_write - Write a software module to controller | ||
350 | * @file: file pointer | ||
351 | * @buf: buffer into which the data should be copied | ||
352 | * @count: number of bytes to read | ||
353 | * @off: file offset | ||
354 | * @swtype: type of software module writing | ||
355 | * @swid: id of software which should be written | ||
356 | * | ||
357 | * Transfers @count bytes at offset @offset from buffer to IOP using | ||
358 | * type @swtype and id @swid as described in I2O spec. | ||
359 | * | ||
360 | * Returns number of bytes copied from buffer or error code on failure. | ||
361 | */ | ||
362 | static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf, | ||
363 | size_t count, loff_t * offset, u8 swtype, | ||
364 | u32 swid) | ||
365 | { | ||
366 | struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; | ||
367 | struct kobject *kobj = sd->s_element; | ||
368 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
369 | u32 m, function = I2O_CMD_SW_DOWNLOAD; | ||
370 | struct i2o_dma buffer; | ||
371 | struct i2o_message __iomem *msg; | ||
372 | u32 __iomem *mptr; | ||
373 | int rc, status; | ||
374 | |||
375 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
376 | if (m == I2O_QUEUE_EMPTY) | ||
377 | return -EBUSY; | ||
378 | |||
379 | mptr = &msg->body[3]; | ||
380 | |||
381 | if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) | ||
382 | goto nop_msg; | ||
383 | |||
384 | if ((rc = copy_from_user(buffer.virt, buf, count))) | ||
385 | goto free_buffer; | ||
386 | |||
387 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
388 | if (c->adaptec) { | ||
389 | mptr = &msg->body[4]; | ||
390 | function = I2O_CMD_PRIVATE; | ||
391 | |||
392 | writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); | ||
393 | |||
394 | writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE, | ||
395 | &msg->body[0]); | ||
396 | writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); | ||
397 | writel(*offset, &msg->body[2]); | ||
398 | writel(count, &msg->body[3]); | ||
399 | } else | ||
400 | #endif | ||
401 | writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); | ||
402 | |||
403 | writel(0xD4000000 | count, mptr++); | ||
404 | writel(buffer.phys, mptr); | ||
405 | |||
406 | writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); | ||
407 | writel(i2o_config_driver.context, &msg->u.head[2]); | ||
408 | writel(0, &msg->u.head[3]); | ||
409 | |||
410 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
411 | if (!c->adaptec) | ||
412 | #endif | ||
413 | { | ||
414 | writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); | ||
415 | writel(0, &msg->body[1]); | ||
416 | writel(swid, &msg->body[2]); | ||
417 | } | ||
418 | |||
419 | status = i2o_msg_post_wait_mem(c, m, 60, &buffer); | ||
420 | |||
421 | if (status != -ETIMEDOUT) | ||
422 | i2o_dma_free(&c->pdev->dev, &buffer); | ||
423 | |||
424 | if (status != I2O_POST_WAIT_OK) | ||
425 | return -EIO; | ||
426 | |||
427 | *offset += count; | ||
428 | |||
429 | return count; | ||
430 | |||
431 | free_buffer: | ||
432 | i2o_dma_free(&c->pdev->dev, &buffer); | ||
433 | |||
434 | nop_msg: | ||
435 | i2o_msg_nop(c, m); | ||
436 | |||
437 | return rc; | ||
438 | }; | ||
439 | |||
440 | /* attribute for HRT in sysfs */ | ||
441 | static struct bin_attribute i2o_config_hrt_attr = { | ||
442 | .attr = { | ||
443 | .name = "hrt", | ||
444 | .mode = S_IRUGO, | ||
445 | .owner = THIS_MODULE}, | ||
446 | .size = 0, | ||
447 | .read = i2o_config_read_hrt | ||
448 | }; | ||
449 | |||
450 | /* attribute for LCT in sysfs */ | ||
451 | static struct bin_attribute i2o_config_lct_attr = { | ||
452 | .attr = { | ||
453 | .name = "lct", | ||
454 | .mode = S_IRUGO, | ||
455 | .owner = THIS_MODULE}, | ||
456 | .size = 0, | ||
457 | .read = i2o_config_read_lct | ||
458 | }; | ||
459 | |||
460 | /* IRTOS firmware access */ | ||
461 | I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0); | ||
462 | |||
463 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
464 | |||
465 | /* | ||
466 | * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec | ||
467 | * controllers | ||
468 | */ | ||
469 | I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0); | ||
470 | I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0); | ||
471 | I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1); | ||
472 | |||
473 | #endif | ||
474 | |||
475 | /** | ||
476 | * i2o_config_notify_controller_add - Notify of added controller | ||
477 | * @c: the controller which was added | ||
478 | * | ||
479 | * If a I2O controller is added, we catch the notification to add sysfs | ||
480 | * entries. | ||
481 | */ | ||
482 | static void i2o_config_notify_controller_add(struct i2o_controller *c) | ||
483 | { | ||
484 | struct kobject *kobj = &c->exec->device.kobj; | ||
485 | |||
486 | sysfs_create_bin_file(kobj, &i2o_config_hrt_attr); | ||
487 | sysfs_create_bin_file(kobj, &i2o_config_lct_attr); | ||
488 | |||
489 | sysfs_create_fops_file(kobj, &i2o_config_attr_irtos); | ||
490 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
491 | if (c->adaptec) { | ||
492 | sysfs_create_fops_file(kobj, &i2o_config_attr_bios); | ||
493 | sysfs_create_fops_file(kobj, &i2o_config_attr_nvram); | ||
494 | sysfs_create_fops_file(kobj, &i2o_config_attr_serial); | ||
495 | } | ||
496 | #endif | ||
497 | }; | ||
498 | |||
499 | /** | ||
500 | * i2o_config_notify_controller_remove - Notify of removed controller | ||
501 | * @c: the controller which was removed | ||
502 | * | ||
503 | * If a I2O controller is removed, we catch the notification to remove the | ||
504 | * sysfs entries. | ||
505 | */ | ||
506 | static void i2o_config_notify_controller_remove(struct i2o_controller *c) | ||
507 | { | ||
508 | struct kobject *kobj = &c->exec->device.kobj; | ||
509 | |||
510 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
511 | if (c->adaptec) { | ||
512 | sysfs_remove_fops_file(kobj, &i2o_config_attr_serial); | ||
513 | sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram); | ||
514 | sysfs_remove_fops_file(kobj, &i2o_config_attr_bios); | ||
515 | } | ||
516 | #endif | ||
517 | sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos); | ||
518 | |||
519 | sysfs_remove_bin_file(kobj, &i2o_config_lct_attr); | ||
520 | sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr); | ||
521 | }; | ||
522 | |||
523 | /* Config OSM driver struct */ | ||
524 | static struct i2o_driver i2o_config_driver = { | ||
525 | .name = OSM_NAME, | ||
526 | .notify_controller_add = i2o_config_notify_controller_add, | ||
527 | .notify_controller_remove = i2o_config_notify_controller_remove | ||
528 | }; | ||
529 | |||
530 | #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL | ||
531 | #include "i2o_config.c" | ||
532 | #endif | ||
533 | |||
534 | /** | ||
535 | * i2o_config_init - Configuration OSM initialization function | ||
536 | * | ||
537 | * Registers Configuration OSM in the I2O core and if old ioctl's are | ||
538 | * compiled in initialize them. | ||
539 | * | ||
540 | * Returns 0 on success or negative error code on failure. | ||
541 | */ | ||
542 | static int __init i2o_config_init(void) | ||
543 | { | ||
544 | printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); | ||
545 | |||
546 | if (i2o_driver_register(&i2o_config_driver)) { | ||
547 | osm_err("handler register failed.\n"); | ||
548 | return -EBUSY; | ||
549 | } | ||
550 | #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL | ||
551 | if (i2o_config_old_init()) | ||
552 | i2o_driver_unregister(&i2o_config_driver); | ||
553 | #endif | ||
554 | |||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | /** | ||
559 | * i2o_config_exit - Configuration OSM exit function | ||
560 | * | ||
561 | * If old ioctl's are compiled in exit remove them and unregisters | ||
562 | * Configuration OSM from I2O core. | ||
563 | */ | ||
564 | static void i2o_config_exit(void) | ||
565 | { | ||
566 | #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL | ||
567 | i2o_config_old_exit(); | ||
568 | #endif | ||
569 | |||
570 | i2o_driver_unregister(&i2o_config_driver); | ||
571 | } | ||
572 | |||
573 | MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>"); | ||
574 | MODULE_LICENSE("GPL"); | ||
575 | MODULE_DESCRIPTION(OSM_DESCRIPTION); | ||
576 | MODULE_VERSION(OSM_VERSION); | ||
577 | |||
578 | module_init(i2o_config_init); | ||
579 | module_exit(i2o_config_exit); | ||
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h new file mode 100644 index 0000000000..c5bcfd70f7 --- /dev/null +++ b/drivers/message/i2o/core.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * I2O core internal declarations | ||
3 | * | ||
4 | * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * Fixes/additions: | ||
12 | * Markus Lidel <Markus.Lidel@shadowconnect.com> | ||
13 | * initial version. | ||
14 | */ | ||
15 | |||
16 | /* Exec-OSM */ | ||
17 | extern struct bus_type i2o_bus_type; | ||
18 | |||
19 | extern struct i2o_driver i2o_exec_driver; | ||
20 | extern int i2o_exec_lct_get(struct i2o_controller *); | ||
21 | |||
22 | extern int __init i2o_exec_init(void); | ||
23 | extern void __exit i2o_exec_exit(void); | ||
24 | |||
25 | /* driver */ | ||
26 | extern int i2o_driver_dispatch(struct i2o_controller *, u32); | ||
27 | |||
28 | extern int __init i2o_driver_init(void); | ||
29 | extern void __exit i2o_driver_exit(void); | ||
30 | |||
31 | /* PCI */ | ||
32 | extern int __init i2o_pci_init(void); | ||
33 | extern void __exit i2o_pci_exit(void); | ||
34 | |||
35 | /* device */ | ||
36 | extern void i2o_device_remove(struct i2o_device *); | ||
37 | extern int i2o_device_parse_lct(struct i2o_controller *); | ||
38 | |||
39 | extern int i2o_device_init(void); | ||
40 | extern void i2o_device_exit(void); | ||
41 | |||
42 | /* IOP */ | ||
43 | extern struct i2o_controller *i2o_iop_alloc(void); | ||
44 | extern void i2o_iop_free(struct i2o_controller *); | ||
45 | |||
46 | extern int i2o_iop_add(struct i2o_controller *); | ||
47 | extern void i2o_iop_remove(struct i2o_controller *); | ||
48 | |||
49 | /* config */ | ||
50 | extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); | ||
51 | |||
52 | /* control registers relative to c->base */ | ||
53 | #define I2O_IRQ_STATUS 0x30 | ||
54 | #define I2O_IRQ_MASK 0x34 | ||
55 | #define I2O_IN_PORT 0x40 | ||
56 | #define I2O_OUT_PORT 0x44 | ||
57 | |||
58 | #define I2O_IRQ_OUTBOUND_POST 0x00000008 | ||
diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c index 2a5d478fc6..018ca887ca 100644 --- a/drivers/message/i2o/debug.c +++ b/drivers/message/i2o/debug.c | |||
@@ -4,8 +4,6 @@ | |||
4 | #include <linux/pci.h> | 4 | #include <linux/pci.h> |
5 | #include <linux/i2o.h> | 5 | #include <linux/i2o.h> |
6 | 6 | ||
7 | extern struct i2o_driver **i2o_drivers; | ||
8 | extern unsigned int i2o_max_drivers; | ||
9 | static void i2o_report_util_cmd(u8 cmd); | 7 | static void i2o_report_util_cmd(u8 cmd); |
10 | static void i2o_report_exec_cmd(u8 cmd); | 8 | static void i2o_report_exec_cmd(u8 cmd); |
11 | static void i2o_report_fail_status(u8 req_status, u32 * msg); | 9 | static void i2o_report_fail_status(u8 req_status, u32 * msg); |
@@ -23,7 +21,6 @@ void i2o_report_status(const char *severity, const char *str, | |||
23 | u8 cmd = (msg[1] >> 24) & 0xFF; | 21 | u8 cmd = (msg[1] >> 24) & 0xFF; |
24 | u8 req_status = (msg[4] >> 24) & 0xFF; | 22 | u8 req_status = (msg[4] >> 24) & 0xFF; |
25 | u16 detailed_status = msg[4] & 0xFFFF; | 23 | u16 detailed_status = msg[4] & 0xFFFF; |
26 | //struct i2o_driver *h = i2o_drivers[msg[2] & (i2o_max_drivers-1)]; | ||
27 | 24 | ||
28 | if (cmd == I2O_CMD_UTIL_EVT_REGISTER) | 25 | if (cmd == I2O_CMD_UTIL_EVT_REGISTER) |
29 | return; // No status in this reply | 26 | return; // No status in this reply |
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index eb907e87bc..21f16ba3ac 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c | |||
@@ -16,9 +16,7 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/i2o.h> | 17 | #include <linux/i2o.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | 19 | #include "core.h" | |
20 | /* Exec OSM functions */ | ||
21 | extern struct bus_type i2o_bus_type; | ||
22 | 20 | ||
23 | /** | 21 | /** |
24 | * i2o_device_issue_claim - claim or release a device | 22 | * i2o_device_issue_claim - claim or release a device |
@@ -282,8 +280,7 @@ int i2o_device_parse_lct(struct i2o_controller *c) | |||
282 | 280 | ||
283 | down(&c->lct_lock); | 281 | down(&c->lct_lock); |
284 | 282 | ||
285 | if (c->lct) | 283 | kfree(c->lct); |
286 | kfree(c->lct); | ||
287 | 284 | ||
288 | lct = c->dlct.virt; | 285 | lct = c->dlct.virt; |
289 | 286 | ||
@@ -294,12 +291,12 @@ int i2o_device_parse_lct(struct i2o_controller *c) | |||
294 | } | 291 | } |
295 | 292 | ||
296 | if (lct->table_size * 4 > c->dlct.len) { | 293 | if (lct->table_size * 4 > c->dlct.len) { |
297 | memcpy_fromio(c->lct, c->dlct.virt, c->dlct.len); | 294 | memcpy(c->lct, c->dlct.virt, c->dlct.len); |
298 | up(&c->lct_lock); | 295 | up(&c->lct_lock); |
299 | return -EAGAIN; | 296 | return -EAGAIN; |
300 | } | 297 | } |
301 | 298 | ||
302 | memcpy_fromio(c->lct, c->dlct.virt, lct->table_size * 4); | 299 | memcpy(c->lct, c->dlct.virt, lct->table_size * 4); |
303 | 300 | ||
304 | lct = c->lct; | 301 | lct = c->lct; |
305 | 302 | ||
@@ -354,7 +351,7 @@ static ssize_t i2o_device_class_show_class_id(struct class_device *cd, | |||
354 | { | 351 | { |
355 | struct i2o_device *dev = to_i2o_device(cd->dev); | 352 | struct i2o_device *dev = to_i2o_device(cd->dev); |
356 | 353 | ||
357 | sprintf(buf, "%03x\n", dev->lct_data.class_id); | 354 | sprintf(buf, "0x%03x\n", dev->lct_data.class_id); |
358 | return strlen(buf) + 1; | 355 | return strlen(buf) + 1; |
359 | }; | 356 | }; |
360 | 357 | ||
@@ -369,7 +366,7 @@ static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf) | |||
369 | { | 366 | { |
370 | struct i2o_device *dev = to_i2o_device(cd->dev); | 367 | struct i2o_device *dev = to_i2o_device(cd->dev); |
371 | 368 | ||
372 | sprintf(buf, "%03x\n", dev->lct_data.tid); | 369 | sprintf(buf, "0x%03x\n", dev->lct_data.tid); |
373 | return strlen(buf) + 1; | 370 | return strlen(buf) + 1; |
374 | }; | 371 | }; |
375 | 372 | ||
@@ -401,25 +398,27 @@ static int i2o_device_class_add(struct class_device *cd) | |||
401 | 398 | ||
402 | /* create user entries for this device */ | 399 | /* create user entries for this device */ |
403 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); | 400 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); |
404 | if (tmp) | 401 | if (tmp && (tmp != i2o_dev)) |
405 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, | 402 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, |
406 | "user"); | 403 | "user"); |
407 | 404 | ||
408 | /* create user entries refering to this device */ | 405 | /* create user entries refering to this device */ |
409 | list_for_each_entry(tmp, &c->devices, list) | 406 | list_for_each_entry(tmp, &c->devices, list) |
410 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | 407 | if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) |
408 | && (tmp != i2o_dev)) | ||
411 | sysfs_create_link(&tmp->device.kobj, | 409 | sysfs_create_link(&tmp->device.kobj, |
412 | &i2o_dev->device.kobj, "user"); | 410 | &i2o_dev->device.kobj, "user"); |
413 | 411 | ||
414 | /* create parent entries for this device */ | 412 | /* create parent entries for this device */ |
415 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); | 413 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); |
416 | if (tmp) | 414 | if (tmp && (tmp != i2o_dev)) |
417 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, | 415 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, |
418 | "parent"); | 416 | "parent"); |
419 | 417 | ||
420 | /* create parent entries refering to this device */ | 418 | /* create parent entries refering to this device */ |
421 | list_for_each_entry(tmp, &c->devices, list) | 419 | list_for_each_entry(tmp, &c->devices, list) |
422 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | 420 | if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) |
421 | && (tmp != i2o_dev)) | ||
423 | sysfs_create_link(&tmp->device.kobj, | 422 | sysfs_create_link(&tmp->device.kobj, |
424 | &i2o_dev->device.kobj, "parent"); | 423 | &i2o_dev->device.kobj, "parent"); |
425 | 424 | ||
@@ -444,9 +443,8 @@ static struct class_interface i2o_device_class_interface = { | |||
444 | * Note that the minimum sized reslist is 8 bytes and contains | 443 | * Note that the minimum sized reslist is 8 bytes and contains |
445 | * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. | 444 | * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. |
446 | */ | 445 | */ |
447 | |||
448 | int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, | 446 | int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, |
449 | int oplen, void *reslist, int reslen) | 447 | int oplen, void *reslist, int reslen) |
450 | { | 448 | { |
451 | struct i2o_message __iomem *msg; | 449 | struct i2o_message __iomem *msg; |
452 | u32 m; | 450 | u32 m; |
@@ -489,7 +487,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, | |||
489 | if (rc == -ETIMEDOUT) | 487 | if (rc == -ETIMEDOUT) |
490 | return rc; | 488 | return rc; |
491 | 489 | ||
492 | memcpy_fromio(reslist, res.virt, res.len); | 490 | memcpy(reslist, res.virt, res.len); |
493 | i2o_dma_free(dev, &res); | 491 | i2o_dma_free(dev, &res); |
494 | 492 | ||
495 | /* Query failed */ | 493 | /* Query failed */ |
@@ -531,17 +529,23 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, | |||
531 | void *buf, int buflen) | 529 | void *buf, int buflen) |
532 | { | 530 | { |
533 | u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; | 531 | u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; |
534 | u8 resblk[8 + buflen]; /* 8 bytes for header */ | 532 | u8 *resblk; /* 8 bytes for header */ |
535 | int size; | 533 | int size; |
536 | 534 | ||
537 | if (field == -1) /* whole group */ | 535 | if (field == -1) /* whole group */ |
538 | opblk[4] = -1; | 536 | opblk[4] = -1; |
539 | 537 | ||
538 | resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC); | ||
539 | if (!resblk) | ||
540 | return -ENOMEM; | ||
541 | |||
540 | size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, | 542 | size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, |
541 | sizeof(opblk), resblk, sizeof(resblk)); | 543 | sizeof(opblk), resblk, buflen + 8); |
542 | 544 | ||
543 | memcpy(buf, resblk + 8, buflen); /* cut off header */ | 545 | memcpy(buf, resblk + 8, buflen); /* cut off header */ |
544 | 546 | ||
547 | kfree(resblk); | ||
548 | |||
545 | if (size > buflen) | 549 | if (size > buflen) |
546 | return buflen; | 550 | return buflen; |
547 | 551 | ||
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index 91f4edbb2a..739bfdef0c 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c | |||
@@ -17,9 +17,12 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/rwsem.h> | 18 | #include <linux/rwsem.h> |
19 | #include <linux/i2o.h> | 19 | #include <linux/i2o.h> |
20 | #include "core.h" | ||
21 | |||
22 | #define OSM_NAME "i2o" | ||
20 | 23 | ||
21 | /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ | 24 | /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ |
22 | unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; | 25 | static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; |
23 | module_param_named(max_drivers, i2o_max_drivers, uint, 0); | 26 | module_param_named(max_drivers, i2o_max_drivers, uint, 0); |
24 | MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); | 27 | MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); |
25 | 28 | ||
@@ -76,17 +79,16 @@ int i2o_driver_register(struct i2o_driver *drv) | |||
76 | int rc = 0; | 79 | int rc = 0; |
77 | unsigned long flags; | 80 | unsigned long flags; |
78 | 81 | ||
79 | pr_debug("i2o: Register driver %s\n", drv->name); | 82 | osm_debug("Register driver %s\n", drv->name); |
80 | 83 | ||
81 | if (drv->event) { | 84 | if (drv->event) { |
82 | drv->event_queue = create_workqueue(drv->name); | 85 | drv->event_queue = create_workqueue(drv->name); |
83 | if (!drv->event_queue) { | 86 | if (!drv->event_queue) { |
84 | printk(KERN_ERR "i2o: Could not initialize event queue " | 87 | osm_err("Could not initialize event queue for driver " |
85 | "for driver %s\n", drv->name); | 88 | "%s\n", drv->name); |
86 | return -EFAULT; | 89 | return -EFAULT; |
87 | } | 90 | } |
88 | pr_debug("i2o: Event queue initialized for driver %s\n", | 91 | osm_debug("Event queue initialized for driver %s\n", drv->name); |
89 | drv->name); | ||
90 | } else | 92 | } else |
91 | drv->event_queue = NULL; | 93 | drv->event_queue = NULL; |
92 | 94 | ||
@@ -97,8 +99,8 @@ int i2o_driver_register(struct i2o_driver *drv) | |||
97 | 99 | ||
98 | for (i = 0; i2o_drivers[i]; i++) | 100 | for (i = 0; i2o_drivers[i]; i++) |
99 | if (i >= i2o_max_drivers) { | 101 | if (i >= i2o_max_drivers) { |
100 | printk(KERN_ERR "i2o: too many drivers registered, " | 102 | osm_err("too many drivers registered, increase " |
101 | "increase max_drivers\n"); | 103 | "max_drivers\n"); |
102 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); | 104 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); |
103 | return -EFAULT; | 105 | return -EFAULT; |
104 | } | 106 | } |
@@ -108,18 +110,16 @@ int i2o_driver_register(struct i2o_driver *drv) | |||
108 | 110 | ||
109 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); | 111 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); |
110 | 112 | ||
111 | pr_debug("i2o: driver %s gets context id %d\n", drv->name, | 113 | osm_debug("driver %s gets context id %d\n", drv->name, drv->context); |
112 | drv->context); | ||
113 | 114 | ||
114 | list_for_each_entry(c, &i2o_controllers, list) { | 115 | list_for_each_entry(c, &i2o_controllers, list) { |
115 | struct i2o_device *i2o_dev; | 116 | struct i2o_device *i2o_dev; |
116 | 117 | ||
117 | i2o_driver_notify_controller_add(drv, c); | 118 | i2o_driver_notify_controller_add(drv, c); |
118 | list_for_each_entry(i2o_dev, &c->devices, list) | 119 | list_for_each_entry(i2o_dev, &c->devices, list) |
119 | i2o_driver_notify_device_add(drv, i2o_dev); | 120 | i2o_driver_notify_device_add(drv, i2o_dev); |
120 | } | 121 | } |
121 | 122 | ||
122 | |||
123 | rc = driver_register(&drv->driver); | 123 | rc = driver_register(&drv->driver); |
124 | if (rc) | 124 | if (rc) |
125 | destroy_workqueue(drv->event_queue); | 125 | destroy_workqueue(drv->event_queue); |
@@ -139,7 +139,7 @@ void i2o_driver_unregister(struct i2o_driver *drv) | |||
139 | struct i2o_controller *c; | 139 | struct i2o_controller *c; |
140 | unsigned long flags; | 140 | unsigned long flags; |
141 | 141 | ||
142 | pr_debug("i2o: unregister driver %s\n", drv->name); | 142 | osm_debug("unregister driver %s\n", drv->name); |
143 | 143 | ||
144 | driver_unregister(&drv->driver); | 144 | driver_unregister(&drv->driver); |
145 | 145 | ||
@@ -159,7 +159,7 @@ void i2o_driver_unregister(struct i2o_driver *drv) | |||
159 | if (drv->event_queue) { | 159 | if (drv->event_queue) { |
160 | destroy_workqueue(drv->event_queue); | 160 | destroy_workqueue(drv->event_queue); |
161 | drv->event_queue = NULL; | 161 | drv->event_queue = NULL; |
162 | pr_debug("i2o: event queue removed for %s\n", drv->name); | 162 | osm_debug("event queue removed for %s\n", drv->name); |
163 | } | 163 | } |
164 | }; | 164 | }; |
165 | 165 | ||
@@ -176,68 +176,70 @@ void i2o_driver_unregister(struct i2o_driver *drv) | |||
176 | * on success and if the message should be flushed afterwords. Returns | 176 | * on success and if the message should be flushed afterwords. Returns |
177 | * negative error code on failure (the message will be flushed too). | 177 | * negative error code on failure (the message will be flushed too). |
178 | */ | 178 | */ |
179 | int i2o_driver_dispatch(struct i2o_controller *c, u32 m, | 179 | int i2o_driver_dispatch(struct i2o_controller *c, u32 m) |
180 | struct i2o_message __iomem *msg) | ||
181 | { | 180 | { |
182 | struct i2o_driver *drv; | 181 | struct i2o_driver *drv; |
183 | u32 context = readl(&msg->u.s.icntxt); | 182 | struct i2o_message *msg = i2o_msg_out_to_virt(c, m); |
183 | u32 context = le32_to_cpu(msg->u.s.icntxt); | ||
184 | unsigned long flags; | ||
184 | 185 | ||
185 | if (likely(context < i2o_max_drivers)) { | 186 | if (unlikely(context >= i2o_max_drivers)) { |
186 | spin_lock(&i2o_drivers_lock); | 187 | osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, |
187 | drv = i2o_drivers[context]; | 188 | context); |
188 | spin_unlock(&i2o_drivers_lock); | 189 | return -EIO; |
190 | } | ||
189 | 191 | ||
190 | if (unlikely(!drv)) { | 192 | spin_lock_irqsave(&i2o_drivers_lock, flags); |
191 | printk(KERN_WARNING "%s: Spurious reply to unknown " | 193 | drv = i2o_drivers[context]; |
192 | "driver %d\n", c->name, context); | 194 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); |
193 | return -EIO; | ||
194 | } | ||
195 | 195 | ||
196 | if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { | 196 | if (unlikely(!drv)) { |
197 | struct i2o_device *dev, *tmp; | 197 | osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, |
198 | struct i2o_event *evt; | 198 | context); |
199 | u16 size; | 199 | return -EIO; |
200 | u16 tid; | 200 | } |
201 | 201 | ||
202 | tid = readl(&msg->u.head[1]) & 0x1fff; | 202 | if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { |
203 | struct i2o_device *dev, *tmp; | ||
204 | struct i2o_event *evt; | ||
205 | u16 size; | ||
206 | u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff; | ||
203 | 207 | ||
204 | pr_debug("%s: event received from device %d\n", c->name, | 208 | osm_debug("event received from device %d\n", tid); |
205 | tid); | ||
206 | 209 | ||
207 | /* cut of header from message size (in 32-bit words) */ | 210 | if (!drv->event) |
208 | size = (readl(&msg->u.head[0]) >> 16) - 5; | 211 | return -EIO; |
209 | 212 | ||
210 | evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); | 213 | /* cut of header from message size (in 32-bit words) */ |
211 | if (!evt) | 214 | size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5; |
212 | return -ENOMEM; | ||
213 | memset(evt, 0, size * 4 + sizeof(*evt)); | ||
214 | 215 | ||
215 | evt->size = size; | 216 | evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO); |
216 | memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, | 217 | if (!evt) |
217 | (size + 2) * 4); | 218 | return -ENOMEM; |
218 | 219 | ||
219 | list_for_each_entry_safe(dev, tmp, &c->devices, list) | 220 | evt->size = size; |
220 | if (dev->lct_data.tid == tid) { | 221 | evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt); |
221 | evt->i2o_dev = dev; | 222 | evt->event_indicator = le32_to_cpu(msg->body[0]); |
222 | break; | 223 | memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4); |
223 | } | ||
224 | 224 | ||
225 | INIT_WORK(&evt->work, (void (*)(void *))drv->event, | 225 | list_for_each_entry_safe(dev, tmp, &c->devices, list) |
226 | evt); | 226 | if (dev->lct_data.tid == tid) { |
227 | queue_work(drv->event_queue, &evt->work); | 227 | evt->i2o_dev = dev; |
228 | return 1; | 228 | break; |
229 | } | 229 | } |
230 | 230 | ||
231 | if (likely(drv->reply)) | 231 | INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt); |
232 | return drv->reply(c, m, msg); | 232 | queue_work(drv->event_queue, &evt->work); |
233 | else | 233 | return 1; |
234 | pr_debug("%s: Reply to driver %s, but no reply function" | 234 | } |
235 | " defined!\n", c->name, drv->name); | 235 | |
236 | if (unlikely(!drv->reply)) { | ||
237 | osm_debug("%s: Reply to driver %s, but no reply function" | ||
238 | " defined!\n", c->name, drv->name); | ||
236 | return -EIO; | 239 | return -EIO; |
237 | } else | 240 | } |
238 | printk(KERN_WARNING "%s: Spurious reply to unknown driver " | 241 | |
239 | "%d\n", c->name, readl(&msg->u.s.icntxt)); | 242 | return drv->reply(c, m, msg); |
240 | return -EIO; | ||
241 | } | 243 | } |
242 | 244 | ||
243 | /** | 245 | /** |
@@ -334,11 +336,11 @@ int __init i2o_driver_init(void) | |||
334 | if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) || | 336 | if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) || |
335 | ((i2o_max_drivers ^ (i2o_max_drivers - 1)) != | 337 | ((i2o_max_drivers ^ (i2o_max_drivers - 1)) != |
336 | (2 * i2o_max_drivers - 1))) { | 338 | (2 * i2o_max_drivers - 1))) { |
337 | printk(KERN_WARNING "i2o: max_drivers set to %d, but must be " | 339 | osm_warn("max_drivers set to %d, but must be >=2 and <= 64 and " |
338 | ">=2 and <= 64 and a power of 2\n", i2o_max_drivers); | 340 | "a power of 2\n", i2o_max_drivers); |
339 | i2o_max_drivers = I2O_MAX_DRIVERS; | 341 | i2o_max_drivers = I2O_MAX_DRIVERS; |
340 | } | 342 | } |
341 | printk(KERN_INFO "i2o: max drivers = %d\n", i2o_max_drivers); | 343 | osm_info("max drivers = %d\n", i2o_max_drivers); |
342 | 344 | ||
343 | i2o_drivers = | 345 | i2o_drivers = |
344 | kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL); | 346 | kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL); |
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 79c1cbfb8f..bda2c62648 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/i2o.h> | 31 | #include <linux/i2o.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include "core.h" | ||
33 | 34 | ||
34 | #define OSM_NAME "exec-osm" | 35 | #define OSM_NAME "exec-osm" |
35 | 36 | ||
@@ -37,9 +38,6 @@ struct i2o_driver i2o_exec_driver; | |||
37 | 38 | ||
38 | static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind); | 39 | static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind); |
39 | 40 | ||
40 | /* Module internal functions from other sources */ | ||
41 | extern int i2o_device_parse_lct(struct i2o_controller *); | ||
42 | |||
43 | /* global wait list for POST WAIT */ | 41 | /* global wait list for POST WAIT */ |
44 | static LIST_HEAD(i2o_exec_wait_list); | 42 | static LIST_HEAD(i2o_exec_wait_list); |
45 | 43 | ||
@@ -50,7 +48,7 @@ struct i2o_exec_wait { | |||
50 | u32 tcntxt; /* transaction context from reply */ | 48 | u32 tcntxt; /* transaction context from reply */ |
51 | int complete; /* 1 if reply received otherwise 0 */ | 49 | int complete; /* 1 if reply received otherwise 0 */ |
52 | u32 m; /* message id */ | 50 | u32 m; /* message id */ |
53 | struct i2o_message __iomem *msg; /* pointer to the reply message */ | 51 | struct i2o_message *msg; /* pointer to the reply message */ |
54 | struct list_head list; /* node in global wait list */ | 52 | struct list_head list; /* node in global wait list */ |
55 | }; | 53 | }; |
56 | 54 | ||
@@ -108,7 +106,8 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait) | |||
108 | * buffer must not be freed. Instead the event completion will free them | 106 | * buffer must not be freed. Instead the event completion will free them |
109 | * for you. In all other cases the buffer are your problem. | 107 | * for you. In all other cases the buffer are your problem. |
110 | * | 108 | * |
111 | * Returns 0 on success or negative error code on failure. | 109 | * Returns 0 on success, negative error code on timeout or positive error |
110 | * code from reply. | ||
112 | */ | 111 | */ |
113 | int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | 112 | int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long |
114 | timeout, struct i2o_dma *dma) | 113 | timeout, struct i2o_dma *dma) |
@@ -116,7 +115,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | |||
116 | DECLARE_WAIT_QUEUE_HEAD(wq); | 115 | DECLARE_WAIT_QUEUE_HEAD(wq); |
117 | struct i2o_exec_wait *wait; | 116 | struct i2o_exec_wait *wait; |
118 | static u32 tcntxt = 0x80000000; | 117 | static u32 tcntxt = 0x80000000; |
119 | struct i2o_message __iomem *msg = c->in_queue.virt + m; | 118 | struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m); |
120 | int rc = 0; | 119 | int rc = 0; |
121 | 120 | ||
122 | wait = i2o_exec_wait_alloc(); | 121 | wait = i2o_exec_wait_alloc(); |
@@ -153,7 +152,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | |||
153 | list_add(&wait->list, &i2o_exec_wait_list); | 152 | list_add(&wait->list, &i2o_exec_wait_list); |
154 | 153 | ||
155 | wait_event_interruptible_timeout(wq, wait->complete, | 154 | wait_event_interruptible_timeout(wq, wait->complete, |
156 | timeout * HZ); | 155 | timeout * HZ); |
157 | 156 | ||
158 | wait->wq = NULL; | 157 | wait->wq = NULL; |
159 | } | 158 | } |
@@ -161,8 +160,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | |||
161 | barrier(); | 160 | barrier(); |
162 | 161 | ||
163 | if (wait->complete) { | 162 | if (wait->complete) { |
164 | if (readl(&wait->msg->body[0]) >> 24) | 163 | rc = le32_to_cpu(wait->msg->body[0]) >> 24; |
165 | rc = readl(&wait->msg->body[0]) & 0xff; | ||
166 | i2o_flush_reply(c, wait->m); | 164 | i2o_flush_reply(c, wait->m); |
167 | i2o_exec_wait_free(wait); | 165 | i2o_exec_wait_free(wait); |
168 | } else { | 166 | } else { |
@@ -187,6 +185,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | |||
187 | * @c: I2O controller which answers | 185 | * @c: I2O controller which answers |
188 | * @m: message id | 186 | * @m: message id |
189 | * @msg: pointer to the I2O reply message | 187 | * @msg: pointer to the I2O reply message |
188 | * @context: transaction context of request | ||
190 | * | 189 | * |
191 | * This function is called in interrupt context only. If the reply reached | 190 | * This function is called in interrupt context only. If the reply reached |
192 | * before the timeout, the i2o_exec_wait struct is filled with the message | 191 | * before the timeout, the i2o_exec_wait struct is filled with the message |
@@ -201,16 +200,12 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | |||
201 | * message must also be given back to the controller. | 200 | * message must also be given back to the controller. |
202 | */ | 201 | */ |
203 | static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | 202 | static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, |
204 | struct i2o_message __iomem *msg) | 203 | struct i2o_message *msg, u32 context) |
205 | { | 204 | { |
206 | struct i2o_exec_wait *wait, *tmp; | 205 | struct i2o_exec_wait *wait, *tmp; |
207 | static spinlock_t lock; | 206 | unsigned long flags; |
207 | static spinlock_t lock = SPIN_LOCK_UNLOCKED; | ||
208 | int rc = 1; | 208 | int rc = 1; |
209 | u32 context; | ||
210 | |||
211 | spin_lock_init(&lock); | ||
212 | |||
213 | context = readl(&msg->u.s.tcntxt); | ||
214 | 209 | ||
215 | /* | 210 | /* |
216 | * We need to search through the i2o_exec_wait_list to see if the given | 211 | * We need to search through the i2o_exec_wait_list to see if the given |
@@ -219,11 +214,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | |||
219 | * already expired. Not much we can do about that except log it for | 214 | * already expired. Not much we can do about that except log it for |
220 | * debug purposes, increase timeout, and recompile. | 215 | * debug purposes, increase timeout, and recompile. |
221 | */ | 216 | */ |
222 | spin_lock(&lock); | 217 | spin_lock_irqsave(&lock, flags); |
223 | list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { | 218 | list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { |
224 | if (wait->tcntxt == context) { | 219 | if (wait->tcntxt == context) { |
225 | list_del(&wait->list); | 220 | list_del(&wait->list); |
226 | 221 | ||
222 | spin_unlock_irqrestore(&lock, flags); | ||
223 | |||
227 | wait->m = m; | 224 | wait->m = m; |
228 | wait->msg = msg; | 225 | wait->msg = msg; |
229 | wait->complete = 1; | 226 | wait->complete = 1; |
@@ -245,21 +242,63 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | |||
245 | rc = -1; | 242 | rc = -1; |
246 | } | 243 | } |
247 | 244 | ||
248 | spin_unlock(&lock); | ||
249 | |||
250 | return rc; | 245 | return rc; |
251 | } | 246 | } |
252 | } | 247 | } |
253 | 248 | ||
254 | spin_unlock(&lock); | 249 | spin_unlock_irqrestore(&lock, flags); |
255 | 250 | ||
256 | pr_debug("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, | 251 | osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, |
257 | context); | 252 | context); |
258 | 253 | ||
259 | return -1; | 254 | return -1; |
260 | }; | 255 | }; |
261 | 256 | ||
262 | /** | 257 | /** |
258 | * i2o_exec_show_vendor_id - Displays Vendor ID of controller | ||
259 | * @d: device of which the Vendor ID should be displayed | ||
260 | * @buf: buffer into which the Vendor ID should be printed | ||
261 | * | ||
262 | * Returns number of bytes printed into buffer. | ||
263 | */ | ||
264 | static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf) | ||
265 | { | ||
266 | struct i2o_device *dev = to_i2o_device(d); | ||
267 | u16 id; | ||
268 | |||
269 | if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) { | ||
270 | sprintf(buf, "0x%04x", id); | ||
271 | return strlen(buf) + 1; | ||
272 | } | ||
273 | |||
274 | return 0; | ||
275 | }; | ||
276 | |||
277 | /** | ||
278 | * i2o_exec_show_product_id - Displays Product ID of controller | ||
279 | * @d: device of which the Product ID should be displayed | ||
280 | * @buf: buffer into which the Product ID should be printed | ||
281 | * | ||
282 | * Returns number of bytes printed into buffer. | ||
283 | */ | ||
284 | static ssize_t i2o_exec_show_product_id(struct device *d, struct device_attribute *attr, char *buf) | ||
285 | { | ||
286 | struct i2o_device *dev = to_i2o_device(d); | ||
287 | u16 id; | ||
288 | |||
289 | if (i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) { | ||
290 | sprintf(buf, "0x%04x", id); | ||
291 | return strlen(buf) + 1; | ||
292 | } | ||
293 | |||
294 | return 0; | ||
295 | }; | ||
296 | |||
297 | /* Exec-OSM device attributes */ | ||
298 | static DEVICE_ATTR(vendor_id, S_IRUGO, i2o_exec_show_vendor_id, NULL); | ||
299 | static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL); | ||
300 | |||
301 | /** | ||
263 | * i2o_exec_probe - Called if a new I2O device (executive class) appears | 302 | * i2o_exec_probe - Called if a new I2O device (executive class) appears |
264 | * @dev: I2O device which should be probed | 303 | * @dev: I2O device which should be probed |
265 | * | 304 | * |
@@ -271,10 +310,16 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | |||
271 | static int i2o_exec_probe(struct device *dev) | 310 | static int i2o_exec_probe(struct device *dev) |
272 | { | 311 | { |
273 | struct i2o_device *i2o_dev = to_i2o_device(dev); | 312 | struct i2o_device *i2o_dev = to_i2o_device(dev); |
313 | struct i2o_controller *c = i2o_dev->iop; | ||
274 | 314 | ||
275 | i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); | 315 | i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); |
276 | 316 | ||
277 | i2o_dev->iop->exec = i2o_dev; | 317 | c->exec = i2o_dev; |
318 | |||
319 | i2o_exec_lct_notify(c, c->lct->change_ind + 1); | ||
320 | |||
321 | device_create_file(dev, &dev_attr_vendor_id); | ||
322 | device_create_file(dev, &dev_attr_product_id); | ||
278 | 323 | ||
279 | return 0; | 324 | return 0; |
280 | }; | 325 | }; |
@@ -289,6 +334,9 @@ static int i2o_exec_probe(struct device *dev) | |||
289 | */ | 334 | */ |
290 | static int i2o_exec_remove(struct device *dev) | 335 | static int i2o_exec_remove(struct device *dev) |
291 | { | 336 | { |
337 | device_remove_file(dev, &dev_attr_product_id); | ||
338 | device_remove_file(dev, &dev_attr_vendor_id); | ||
339 | |||
292 | i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); | 340 | i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); |
293 | 341 | ||
294 | return 0; | 342 | return 0; |
@@ -300,12 +348,16 @@ static int i2o_exec_remove(struct device *dev) | |||
300 | * | 348 | * |
301 | * This function handles asynchronus LCT NOTIFY replies. It parses the | 349 | * This function handles asynchronus LCT NOTIFY replies. It parses the |
302 | * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY | 350 | * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY |
303 | * again. | 351 | * again, otherwise send LCT NOTIFY to get informed on next LCT change. |
304 | */ | 352 | */ |
305 | static void i2o_exec_lct_modified(struct i2o_controller *c) | 353 | static void i2o_exec_lct_modified(struct i2o_controller *c) |
306 | { | 354 | { |
307 | if (i2o_device_parse_lct(c) == -EAGAIN) | 355 | u32 change_ind = 0; |
308 | i2o_exec_lct_notify(c, 0); | 356 | |
357 | if (i2o_device_parse_lct(c) != -EAGAIN) | ||
358 | change_ind = c->lct->change_ind + 1; | ||
359 | |||
360 | i2o_exec_lct_notify(c, change_ind); | ||
309 | }; | 361 | }; |
310 | 362 | ||
311 | /** | 363 | /** |
@@ -325,8 +377,14 @@ static void i2o_exec_lct_modified(struct i2o_controller *c) | |||
325 | static int i2o_exec_reply(struct i2o_controller *c, u32 m, | 377 | static int i2o_exec_reply(struct i2o_controller *c, u32 m, |
326 | struct i2o_message *msg) | 378 | struct i2o_message *msg) |
327 | { | 379 | { |
328 | if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { // Fail bit is set | 380 | u32 context; |
329 | struct i2o_message __iomem *pmsg; /* preserved message */ | 381 | |
382 | if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { | ||
383 | /* | ||
384 | * If Fail bit is set we must take the transaction context of | ||
385 | * the preserved message to find the right request again. | ||
386 | */ | ||
387 | struct i2o_message __iomem *pmsg; | ||
330 | u32 pm; | 388 | u32 pm; |
331 | 389 | ||
332 | pm = le32_to_cpu(msg->body[3]); | 390 | pm = le32_to_cpu(msg->body[3]); |
@@ -335,15 +393,15 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, | |||
335 | 393 | ||
336 | i2o_report_status(KERN_INFO, "i2o_core", msg); | 394 | i2o_report_status(KERN_INFO, "i2o_core", msg); |
337 | 395 | ||
338 | /* Release the preserved msg by resubmitting it as a NOP */ | 396 | context = readl(&pmsg->u.s.tcntxt); |
339 | i2o_msg_nop(c, pm); | ||
340 | 397 | ||
341 | /* If reply to i2o_post_wait failed, return causes a timeout */ | 398 | /* Release the preserved msg */ |
342 | return -1; | 399 | i2o_msg_nop(c, pm); |
343 | } | 400 | } else |
401 | context = le32_to_cpu(msg->u.s.tcntxt); | ||
344 | 402 | ||
345 | if (le32_to_cpu(msg->u.s.tcntxt) & 0x80000000) | 403 | if (context & 0x80000000) |
346 | return i2o_msg_post_wait_complete(c, m, msg); | 404 | return i2o_msg_post_wait_complete(c, m, msg, context); |
347 | 405 | ||
348 | if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { | 406 | if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { |
349 | struct work_struct *work; | 407 | struct work_struct *work; |
@@ -381,8 +439,9 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, | |||
381 | */ | 439 | */ |
382 | static void i2o_exec_event(struct i2o_event *evt) | 440 | static void i2o_exec_event(struct i2o_event *evt) |
383 | { | 441 | { |
384 | osm_info("Event received from device: %d\n", | 442 | if (likely(evt->i2o_dev)) |
385 | evt->i2o_dev->lct_data.tid); | 443 | osm_debug("Event received from device: %d\n", |
444 | evt->i2o_dev->lct_data.tid); | ||
386 | kfree(evt); | 445 | kfree(evt); |
387 | }; | 446 | }; |
388 | 447 | ||
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 4830b77590..f283b5bafd 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c | |||
@@ -62,7 +62,7 @@ | |||
62 | #include "i2o_block.h" | 62 | #include "i2o_block.h" |
63 | 63 | ||
64 | #define OSM_NAME "block-osm" | 64 | #define OSM_NAME "block-osm" |
65 | #define OSM_VERSION "$Rev$" | 65 | #define OSM_VERSION "1.287" |
66 | #define OSM_DESCRIPTION "I2O Block Device OSM" | 66 | #define OSM_DESCRIPTION "I2O Block Device OSM" |
67 | 67 | ||
68 | static struct i2o_driver i2o_block_driver; | 68 | static struct i2o_driver i2o_block_driver; |
@@ -104,7 +104,8 @@ static int i2o_block_remove(struct device *dev) | |||
104 | struct i2o_device *i2o_dev = to_i2o_device(dev); | 104 | struct i2o_device *i2o_dev = to_i2o_device(dev); |
105 | struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev); | 105 | struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev); |
106 | 106 | ||
107 | osm_info("Device removed %s\n", i2o_blk_dev->gd->disk_name); | 107 | osm_info("device removed (TID: %03x): %s\n", i2o_dev->lct_data.tid, |
108 | i2o_blk_dev->gd->disk_name); | ||
108 | 109 | ||
109 | i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0); | 110 | i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0); |
110 | 111 | ||
@@ -146,6 +147,29 @@ static int i2o_block_device_flush(struct i2o_device *dev) | |||
146 | }; | 147 | }; |
147 | 148 | ||
148 | /** | 149 | /** |
150 | * i2o_block_issue_flush - device-flush interface for block-layer | ||
151 | * @queue: the request queue of the device which should be flushed | ||
152 | * @disk: gendisk | ||
153 | * @error_sector: error offset | ||
154 | * | ||
155 | * Helper function to provide flush functionality to block-layer. | ||
156 | * | ||
157 | * Returns 0 on success or negative error code on failure. | ||
158 | */ | ||
159 | |||
160 | static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk, | ||
161 | sector_t * error_sector) | ||
162 | { | ||
163 | struct i2o_block_device *i2o_blk_dev = queue->queuedata; | ||
164 | int rc = -ENODEV; | ||
165 | |||
166 | if (likely(i2o_blk_dev)) | ||
167 | rc = i2o_block_device_flush(i2o_blk_dev->i2o_dev); | ||
168 | |||
169 | return rc; | ||
170 | } | ||
171 | |||
172 | /** | ||
149 | * i2o_block_device_mount - Mount (load) the media of device dev | 173 | * i2o_block_device_mount - Mount (load) the media of device dev |
150 | * @dev: I2O device which should receive the mount request | 174 | * @dev: I2O device which should receive the mount request |
151 | * @media_id: Media Identifier | 175 | * @media_id: Media Identifier |
@@ -298,28 +322,31 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq) | |||
298 | 322 | ||
299 | /** | 323 | /** |
300 | * i2o_block_sglist_alloc - Allocate the SG list and map it | 324 | * i2o_block_sglist_alloc - Allocate the SG list and map it |
325 | * @c: I2O controller to which the request belongs | ||
301 | * @ireq: I2O block request | 326 | * @ireq: I2O block request |
302 | * | 327 | * |
303 | * Builds the SG list and map it into to be accessable by the controller. | 328 | * Builds the SG list and map it to be accessable by the controller. |
304 | * | 329 | * |
305 | * Returns the number of elements in the SG list or 0 on failure. | 330 | * Returns 0 on failure or 1 on success. |
306 | */ | 331 | */ |
307 | static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq) | 332 | static inline int i2o_block_sglist_alloc(struct i2o_controller *c, |
333 | struct i2o_block_request *ireq, | ||
334 | u32 __iomem ** mptr) | ||
308 | { | 335 | { |
309 | struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev; | ||
310 | int nents; | 336 | int nents; |
337 | enum dma_data_direction direction; | ||
311 | 338 | ||
339 | ireq->dev = &c->pdev->dev; | ||
312 | nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table); | 340 | nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table); |
313 | 341 | ||
314 | if (rq_data_dir(ireq->req) == READ) | 342 | if (rq_data_dir(ireq->req) == READ) |
315 | ireq->sg_dma_direction = PCI_DMA_FROMDEVICE; | 343 | direction = PCI_DMA_FROMDEVICE; |
316 | else | 344 | else |
317 | ireq->sg_dma_direction = PCI_DMA_TODEVICE; | 345 | direction = PCI_DMA_TODEVICE; |
318 | 346 | ||
319 | ireq->sg_nents = dma_map_sg(dev, ireq->sg_table, nents, | 347 | ireq->sg_nents = nents; |
320 | ireq->sg_dma_direction); | ||
321 | 348 | ||
322 | return ireq->sg_nents; | 349 | return i2o_dma_map_sg(c, ireq->sg_table, nents, direction, mptr); |
323 | }; | 350 | }; |
324 | 351 | ||
325 | /** | 352 | /** |
@@ -330,10 +357,14 @@ static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq) | |||
330 | */ | 357 | */ |
331 | static inline void i2o_block_sglist_free(struct i2o_block_request *ireq) | 358 | static inline void i2o_block_sglist_free(struct i2o_block_request *ireq) |
332 | { | 359 | { |
333 | struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev; | 360 | enum dma_data_direction direction; |
334 | 361 | ||
335 | dma_unmap_sg(dev, ireq->sg_table, ireq->sg_nents, | 362 | if (rq_data_dir(ireq->req) == READ) |
336 | ireq->sg_dma_direction); | 363 | direction = PCI_DMA_FROMDEVICE; |
364 | else | ||
365 | direction = PCI_DMA_TODEVICE; | ||
366 | |||
367 | dma_unmap_sg(ireq->dev, ireq->sg_table, ireq->sg_nents, direction); | ||
337 | }; | 368 | }; |
338 | 369 | ||
339 | /** | 370 | /** |
@@ -351,6 +382,11 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) | |||
351 | struct i2o_block_device *i2o_blk_dev = q->queuedata; | 382 | struct i2o_block_device *i2o_blk_dev = q->queuedata; |
352 | struct i2o_block_request *ireq; | 383 | struct i2o_block_request *ireq; |
353 | 384 | ||
385 | if (unlikely(!i2o_blk_dev)) { | ||
386 | osm_err("block device already removed\n"); | ||
387 | return BLKPREP_KILL; | ||
388 | } | ||
389 | |||
354 | /* request is already processed by us, so return */ | 390 | /* request is already processed by us, so return */ |
355 | if (req->flags & REQ_SPECIAL) { | 391 | if (req->flags & REQ_SPECIAL) { |
356 | osm_debug("REQ_SPECIAL already set!\n"); | 392 | osm_debug("REQ_SPECIAL already set!\n"); |
@@ -400,71 +436,65 @@ static void i2o_block_delayed_request_fn(void *delayed_request) | |||
400 | }; | 436 | }; |
401 | 437 | ||
402 | /** | 438 | /** |
403 | * i2o_block_reply - Block OSM reply handler. | 439 | * i2o_block_end_request - Post-processing of completed commands |
404 | * @c: I2O controller from which the message arrives | 440 | * @req: request which should be completed |
405 | * @m: message id of reply | 441 | * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error |
406 | * qmsg: the actuall I2O message reply | 442 | * @nr_bytes: number of bytes to complete |
407 | * | 443 | * |
408 | * This function gets all the message replies. | 444 | * Mark the request as complete. The lock must not be held when entering. |
409 | * | 445 | * |
410 | */ | 446 | */ |
411 | static int i2o_block_reply(struct i2o_controller *c, u32 m, | 447 | static void i2o_block_end_request(struct request *req, int uptodate, |
412 | struct i2o_message *msg) | 448 | int nr_bytes) |
413 | { | 449 | { |
414 | struct i2o_block_request *ireq; | 450 | struct i2o_block_request *ireq = req->special; |
415 | struct request *req; | 451 | struct i2o_block_device *dev = ireq->i2o_blk_dev; |
416 | struct i2o_block_device *dev; | 452 | request_queue_t *q = req->q; |
417 | struct request_queue *q; | ||
418 | u8 st; | ||
419 | unsigned long flags; | 453 | unsigned long flags; |
420 | 454 | ||
421 | /* FAILed message */ | 455 | if (end_that_request_chunk(req, uptodate, nr_bytes)) { |
422 | if (unlikely(le32_to_cpu(msg->u.head[0]) & (1 << 13))) { | 456 | int leftover = (req->hard_nr_sectors << KERNEL_SECTOR_SHIFT); |
423 | struct i2o_message *pmsg; | ||
424 | u32 pm; | ||
425 | 457 | ||
426 | /* | 458 | if (blk_pc_request(req)) |
427 | * FAILed message from controller | 459 | leftover = req->data_len; |
428 | * We increment the error count and abort it | ||
429 | * | ||
430 | * In theory this will never happen. The I2O block class | ||
431 | * specification states that block devices never return | ||
432 | * FAILs but instead use the REQ status field...but | ||
433 | * better be on the safe side since no one really follows | ||
434 | * the spec to the book :) | ||
435 | */ | ||
436 | pm = le32_to_cpu(msg->body[3]); | ||
437 | pmsg = i2o_msg_in_to_virt(c, pm); | ||
438 | 460 | ||
439 | req = i2o_cntxt_list_get(c, le32_to_cpu(pmsg->u.s.tcntxt)); | 461 | if (end_io_error(uptodate)) |
440 | if (unlikely(!req)) { | 462 | end_that_request_chunk(req, 0, leftover); |
441 | osm_err("NULL reply received!\n"); | 463 | } |
442 | return -1; | ||
443 | } | ||
444 | 464 | ||
445 | ireq = req->special; | 465 | add_disk_randomness(req->rq_disk); |
446 | dev = ireq->i2o_blk_dev; | ||
447 | q = dev->gd->queue; | ||
448 | 466 | ||
449 | req->errors++; | 467 | spin_lock_irqsave(q->queue_lock, flags); |
450 | |||
451 | spin_lock_irqsave(q->queue_lock, flags); | ||
452 | 468 | ||
453 | while (end_that_request_chunk(req, !req->errors, | 469 | end_that_request_last(req); |
454 | le32_to_cpu(pmsg->body[1]))) ; | ||
455 | end_that_request_last(req); | ||
456 | 470 | ||
471 | if (likely(dev)) { | ||
457 | dev->open_queue_depth--; | 472 | dev->open_queue_depth--; |
458 | list_del(&ireq->queue); | 473 | list_del(&ireq->queue); |
459 | blk_start_queue(q); | 474 | } |
460 | 475 | ||
461 | spin_unlock_irqrestore(q->queue_lock, flags); | 476 | blk_start_queue(q); |
462 | 477 | ||
463 | /* Now flush the message by making it a NOP */ | 478 | spin_unlock_irqrestore(q->queue_lock, flags); |
464 | i2o_msg_nop(c, pm); | ||
465 | 479 | ||
466 | return -1; | 480 | i2o_block_sglist_free(ireq); |
467 | } | 481 | i2o_block_request_free(ireq); |
482 | }; | ||
483 | |||
484 | /** | ||
485 | * i2o_block_reply - Block OSM reply handler. | ||
486 | * @c: I2O controller from which the message arrives | ||
487 | * @m: message id of reply | ||
488 | * qmsg: the actuall I2O message reply | ||
489 | * | ||
490 | * This function gets all the message replies. | ||
491 | * | ||
492 | */ | ||
493 | static int i2o_block_reply(struct i2o_controller *c, u32 m, | ||
494 | struct i2o_message *msg) | ||
495 | { | ||
496 | struct request *req; | ||
497 | int uptodate = 1; | ||
468 | 498 | ||
469 | req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); | 499 | req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); |
470 | if (unlikely(!req)) { | 500 | if (unlikely(!req)) { |
@@ -472,61 +502,13 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, | |||
472 | return -1; | 502 | return -1; |
473 | } | 503 | } |
474 | 504 | ||
475 | ireq = req->special; | ||
476 | dev = ireq->i2o_blk_dev; | ||
477 | q = dev->gd->queue; | ||
478 | |||
479 | if (unlikely(!dev->i2o_dev)) { | ||
480 | /* | ||
481 | * This is HACK, but Intel Integrated RAID allows user | ||
482 | * to delete a volume that is claimed, locked, and in use | ||
483 | * by the OS. We have to check for a reply from a | ||
484 | * non-existent device and flag it as an error or the system | ||
485 | * goes kaput... | ||
486 | */ | ||
487 | req->errors++; | ||
488 | osm_warn("Data transfer to deleted device!\n"); | ||
489 | spin_lock_irqsave(q->queue_lock, flags); | ||
490 | while (end_that_request_chunk | ||
491 | (req, !req->errors, le32_to_cpu(msg->body[1]))) ; | ||
492 | end_that_request_last(req); | ||
493 | |||
494 | dev->open_queue_depth--; | ||
495 | list_del(&ireq->queue); | ||
496 | blk_start_queue(q); | ||
497 | |||
498 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
499 | return -1; | ||
500 | } | ||
501 | |||
502 | /* | 505 | /* |
503 | * Lets see what is cooking. We stuffed the | 506 | * Lets see what is cooking. We stuffed the |
504 | * request in the context. | 507 | * request in the context. |
505 | */ | 508 | */ |
506 | 509 | ||
507 | st = le32_to_cpu(msg->body[0]) >> 24; | 510 | if ((le32_to_cpu(msg->body[0]) >> 24) != 0) { |
508 | 511 | u32 status = le32_to_cpu(msg->body[0]); | |
509 | if (st != 0) { | ||
510 | int err; | ||
511 | char *bsa_errors[] = { | ||
512 | "Success", | ||
513 | "Media Error", | ||
514 | "Failure communicating to device", | ||
515 | "Device Failure", | ||
516 | "Device is not ready", | ||
517 | "Media not present", | ||
518 | "Media is locked by another user", | ||
519 | "Media has failed", | ||
520 | "Failure communicating to device", | ||
521 | "Device bus failure", | ||
522 | "Device is locked by another user", | ||
523 | "Device is write protected", | ||
524 | "Device has reset", | ||
525 | "Volume has changed, waiting for acknowledgement" | ||
526 | }; | ||
527 | |||
528 | err = le32_to_cpu(msg->body[0]) & 0xffff; | ||
529 | |||
530 | /* | 512 | /* |
531 | * Device not ready means two things. One is that the | 513 | * Device not ready means two things. One is that the |
532 | * the thing went offline (but not a removal media) | 514 | * the thing went offline (but not a removal media) |
@@ -539,40 +521,23 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, | |||
539 | * Don't stick a supertrak100 into cache aggressive modes | 521 | * Don't stick a supertrak100 into cache aggressive modes |
540 | */ | 522 | */ |
541 | 523 | ||
542 | osm_err("block-osm: /dev/%s error: %s", dev->gd->disk_name, | 524 | osm_err("TID %03x error status: 0x%02x, detailed status: " |
543 | bsa_errors[le32_to_cpu(msg->body[0]) & 0xffff]); | 525 | "0x%04x\n", (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff), |
544 | if (le32_to_cpu(msg->body[0]) & 0x00ff0000) | 526 | status >> 24, status & 0xffff); |
545 | printk(KERN_ERR " - DDM attempted %d retries", | ||
546 | (le32_to_cpu(msg->body[0]) >> 16) & 0x00ff); | ||
547 | printk(KERN_ERR ".\n"); | ||
548 | req->errors++; | ||
549 | } else | ||
550 | req->errors = 0; | ||
551 | 527 | ||
552 | if (!end_that_request_chunk | 528 | req->errors++; |
553 | (req, !req->errors, le32_to_cpu(msg->body[1]))) { | ||
554 | add_disk_randomness(req->rq_disk); | ||
555 | spin_lock_irqsave(q->queue_lock, flags); | ||
556 | |||
557 | end_that_request_last(req); | ||
558 | 529 | ||
559 | dev->open_queue_depth--; | 530 | uptodate = 0; |
560 | list_del(&ireq->queue); | 531 | } |
561 | blk_start_queue(q); | ||
562 | 532 | ||
563 | spin_unlock_irqrestore(q->queue_lock, flags); | 533 | i2o_block_end_request(req, uptodate, le32_to_cpu(msg->body[1])); |
564 | |||
565 | i2o_block_sglist_free(ireq); | ||
566 | i2o_block_request_free(ireq); | ||
567 | } else | ||
568 | osm_err("still remaining chunks\n"); | ||
569 | 534 | ||
570 | return 1; | 535 | return 1; |
571 | }; | 536 | }; |
572 | 537 | ||
573 | static void i2o_block_event(struct i2o_event *evt) | 538 | static void i2o_block_event(struct i2o_event *evt) |
574 | { | 539 | { |
575 | osm_info("block-osm: event received\n"); | 540 | osm_debug("event received\n"); |
576 | kfree(evt); | 541 | kfree(evt); |
577 | }; | 542 | }; |
578 | 543 | ||
@@ -778,18 +743,25 @@ static int i2o_block_media_changed(struct gendisk *disk) | |||
778 | static int i2o_block_transfer(struct request *req) | 743 | static int i2o_block_transfer(struct request *req) |
779 | { | 744 | { |
780 | struct i2o_block_device *dev = req->rq_disk->private_data; | 745 | struct i2o_block_device *dev = req->rq_disk->private_data; |
781 | struct i2o_controller *c = dev->i2o_dev->iop; | 746 | struct i2o_controller *c; |
782 | int tid = dev->i2o_dev->lct_data.tid; | 747 | int tid = dev->i2o_dev->lct_data.tid; |
783 | struct i2o_message __iomem *msg; | 748 | struct i2o_message __iomem *msg; |
784 | void __iomem *mptr; | 749 | u32 __iomem *mptr; |
785 | struct i2o_block_request *ireq = req->special; | 750 | struct i2o_block_request *ireq = req->special; |
786 | struct scatterlist *sg; | ||
787 | int sgnum; | ||
788 | int i; | ||
789 | u32 m; | 751 | u32 m; |
790 | u32 tcntxt; | 752 | u32 tcntxt; |
791 | u32 sg_flags; | 753 | u32 sgl_offset = SGL_OFFSET_8; |
754 | u32 ctl_flags = 0x00000000; | ||
792 | int rc; | 755 | int rc; |
756 | u32 cmd; | ||
757 | |||
758 | if (unlikely(!dev->i2o_dev)) { | ||
759 | osm_err("transfer to removed drive\n"); | ||
760 | rc = -ENODEV; | ||
761 | goto exit; | ||
762 | } | ||
763 | |||
764 | c = dev->i2o_dev->iop; | ||
793 | 765 | ||
794 | m = i2o_msg_get(c, &msg); | 766 | m = i2o_msg_get(c, &msg); |
795 | if (m == I2O_QUEUE_EMPTY) { | 767 | if (m == I2O_QUEUE_EMPTY) { |
@@ -803,82 +775,109 @@ static int i2o_block_transfer(struct request *req) | |||
803 | goto nop_msg; | 775 | goto nop_msg; |
804 | } | 776 | } |
805 | 777 | ||
806 | if ((sgnum = i2o_block_sglist_alloc(ireq)) <= 0) { | ||
807 | rc = -ENOMEM; | ||
808 | goto context_remove; | ||
809 | } | ||
810 | |||
811 | /* Build the message based on the request. */ | ||
812 | writel(i2o_block_driver.context, &msg->u.s.icntxt); | 778 | writel(i2o_block_driver.context, &msg->u.s.icntxt); |
813 | writel(tcntxt, &msg->u.s.tcntxt); | 779 | writel(tcntxt, &msg->u.s.tcntxt); |
814 | writel(req->nr_sectors << 9, &msg->body[1]); | ||
815 | |||
816 | writel((((u64) req->sector) << 9) & 0xffffffff, &msg->body[2]); | ||
817 | writel(req->sector >> 23, &msg->body[3]); | ||
818 | 780 | ||
819 | mptr = &msg->body[4]; | 781 | mptr = &msg->body[0]; |
820 | |||
821 | sg = ireq->sg_table; | ||
822 | 782 | ||
823 | if (rq_data_dir(req) == READ) { | 783 | if (rq_data_dir(req) == READ) { |
824 | writel(I2O_CMD_BLOCK_READ << 24 | HOST_TID << 12 | tid, | 784 | cmd = I2O_CMD_BLOCK_READ << 24; |
825 | &msg->u.head[1]); | 785 | |
826 | sg_flags = 0x10000000; | ||
827 | switch (dev->rcache) { | 786 | switch (dev->rcache) { |
828 | case CACHE_NULL: | ||
829 | writel(0, &msg->body[0]); | ||
830 | break; | ||
831 | case CACHE_PREFETCH: | 787 | case CACHE_PREFETCH: |
832 | writel(0x201F0008, &msg->body[0]); | 788 | ctl_flags = 0x201F0008; |
833 | break; | 789 | break; |
790 | |||
834 | case CACHE_SMARTFETCH: | 791 | case CACHE_SMARTFETCH: |
835 | if (req->nr_sectors > 16) | 792 | if (req->nr_sectors > 16) |
836 | writel(0x201F0008, &msg->body[0]); | 793 | ctl_flags = 0x201F0008; |
837 | else | 794 | else |
838 | writel(0x001F0000, &msg->body[0]); | 795 | ctl_flags = 0x001F0000; |
796 | break; | ||
797 | |||
798 | default: | ||
839 | break; | 799 | break; |
840 | } | 800 | } |
841 | } else { | 801 | } else { |
842 | writel(I2O_CMD_BLOCK_WRITE << 24 | HOST_TID << 12 | tid, | 802 | cmd = I2O_CMD_BLOCK_WRITE << 24; |
843 | &msg->u.head[1]); | 803 | |
844 | sg_flags = 0x14000000; | ||
845 | switch (dev->wcache) { | 804 | switch (dev->wcache) { |
846 | case CACHE_NULL: | ||
847 | writel(0, &msg->body[0]); | ||
848 | break; | ||
849 | case CACHE_WRITETHROUGH: | 805 | case CACHE_WRITETHROUGH: |
850 | writel(0x001F0008, &msg->body[0]); | 806 | ctl_flags = 0x001F0008; |
851 | break; | 807 | break; |
852 | case CACHE_WRITEBACK: | 808 | case CACHE_WRITEBACK: |
853 | writel(0x001F0010, &msg->body[0]); | 809 | ctl_flags = 0x001F0010; |
854 | break; | 810 | break; |
855 | case CACHE_SMARTBACK: | 811 | case CACHE_SMARTBACK: |
856 | if (req->nr_sectors > 16) | 812 | if (req->nr_sectors > 16) |
857 | writel(0x001F0004, &msg->body[0]); | 813 | ctl_flags = 0x001F0004; |
858 | else | 814 | else |
859 | writel(0x001F0010, &msg->body[0]); | 815 | ctl_flags = 0x001F0010; |
860 | break; | 816 | break; |
861 | case CACHE_SMARTTHROUGH: | 817 | case CACHE_SMARTTHROUGH: |
862 | if (req->nr_sectors > 16) | 818 | if (req->nr_sectors > 16) |
863 | writel(0x001F0004, &msg->body[0]); | 819 | ctl_flags = 0x001F0004; |
864 | else | 820 | else |
865 | writel(0x001F0010, &msg->body[0]); | 821 | ctl_flags = 0x001F0010; |
822 | default: | ||
823 | break; | ||
824 | } | ||
825 | } | ||
826 | |||
827 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
828 | if (c->adaptec) { | ||
829 | u8 cmd[10]; | ||
830 | u32 scsi_flags; | ||
831 | u16 hwsec = queue_hardsect_size(req->q) >> KERNEL_SECTOR_SHIFT; | ||
832 | |||
833 | memset(cmd, 0, 10); | ||
834 | |||
835 | sgl_offset = SGL_OFFSET_12; | ||
836 | |||
837 | writel(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid, | ||
838 | &msg->u.head[1]); | ||
839 | |||
840 | writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++); | ||
841 | writel(tid, mptr++); | ||
842 | |||
843 | /* | ||
844 | * ENABLE_DISCONNECT | ||
845 | * SIMPLE_TAG | ||
846 | * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME | ||
847 | */ | ||
848 | if (rq_data_dir(req) == READ) { | ||
849 | cmd[0] = 0x28; | ||
850 | scsi_flags = 0x60a0000a; | ||
851 | } else { | ||
852 | cmd[0] = 0x2A; | ||
853 | scsi_flags = 0xa0a0000a; | ||
866 | } | 854 | } |
855 | |||
856 | writel(scsi_flags, mptr++); | ||
857 | |||
858 | *((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec); | ||
859 | *((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec); | ||
860 | |||
861 | memcpy_toio(mptr, cmd, 10); | ||
862 | mptr += 4; | ||
863 | writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++); | ||
864 | } else | ||
865 | #endif | ||
866 | { | ||
867 | writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]); | ||
868 | writel(ctl_flags, mptr++); | ||
869 | writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++); | ||
870 | writel((u32) (req->sector << KERNEL_SECTOR_SHIFT), mptr++); | ||
871 | writel(req->sector >> (32 - KERNEL_SECTOR_SHIFT), mptr++); | ||
867 | } | 872 | } |
868 | 873 | ||
869 | for (i = sgnum; i > 0; i--) { | 874 | if (!i2o_block_sglist_alloc(c, ireq, &mptr)) { |
870 | if (i == 1) | 875 | rc = -ENOMEM; |
871 | sg_flags |= 0x80000000; | 876 | goto context_remove; |
872 | writel(sg_flags | sg_dma_len(sg), mptr); | ||
873 | writel(sg_dma_address(sg), mptr + 4); | ||
874 | mptr += 8; | ||
875 | sg++; | ||
876 | } | 877 | } |
877 | 878 | ||
878 | writel(I2O_MESSAGE_SIZE | 879 | writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | |
879 | (((unsigned long)mptr - | 880 | sgl_offset, &msg->u.head[0]); |
880 | (unsigned long)&msg->u.head[0]) >> 2) | SGL_OFFSET_8, | ||
881 | &msg->u.head[0]); | ||
882 | 881 | ||
883 | list_add_tail(&ireq->queue, &dev->open_queue); | 882 | list_add_tail(&ireq->queue, &dev->open_queue); |
884 | dev->open_queue_depth++; | 883 | dev->open_queue_depth++; |
@@ -921,11 +920,13 @@ static void i2o_block_request_fn(struct request_queue *q) | |||
921 | 920 | ||
922 | queue_depth = ireq->i2o_blk_dev->open_queue_depth; | 921 | queue_depth = ireq->i2o_blk_dev->open_queue_depth; |
923 | 922 | ||
924 | if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) | 923 | if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) { |
925 | if (!i2o_block_transfer(req)) { | 924 | if (!i2o_block_transfer(req)) { |
926 | blkdev_dequeue_request(req); | 925 | blkdev_dequeue_request(req); |
927 | continue; | 926 | continue; |
928 | } | 927 | } else |
928 | osm_info("transfer error\n"); | ||
929 | } | ||
929 | 930 | ||
930 | if (queue_depth) | 931 | if (queue_depth) |
931 | break; | 932 | break; |
@@ -939,7 +940,6 @@ static void i2o_block_request_fn(struct request_queue *q) | |||
939 | INIT_WORK(&dreq->work, i2o_block_delayed_request_fn, | 940 | INIT_WORK(&dreq->work, i2o_block_delayed_request_fn, |
940 | dreq); | 941 | dreq); |
941 | 942 | ||
942 | osm_info("transfer error\n"); | ||
943 | if (!queue_delayed_work(i2o_block_driver.event_queue, | 943 | if (!queue_delayed_work(i2o_block_driver.event_queue, |
944 | &dreq->work, | 944 | &dreq->work, |
945 | I2O_BLOCK_RETRY_TIME)) | 945 | I2O_BLOCK_RETRY_TIME)) |
@@ -1008,6 +1008,7 @@ static struct i2o_block_device *i2o_block_device_alloc(void) | |||
1008 | } | 1008 | } |
1009 | 1009 | ||
1010 | blk_queue_prep_rq(queue, i2o_block_prep_req_fn); | 1010 | blk_queue_prep_rq(queue, i2o_block_prep_req_fn); |
1011 | blk_queue_issue_flush_fn(queue, i2o_block_issue_flush); | ||
1011 | 1012 | ||
1012 | gd->major = I2O_MAJOR; | 1013 | gd->major = I2O_MAJOR; |
1013 | gd->queue = queue; | 1014 | gd->queue = queue; |
@@ -1040,17 +1041,27 @@ static struct i2o_block_device *i2o_block_device_alloc(void) | |||
1040 | static int i2o_block_probe(struct device *dev) | 1041 | static int i2o_block_probe(struct device *dev) |
1041 | { | 1042 | { |
1042 | struct i2o_device *i2o_dev = to_i2o_device(dev); | 1043 | struct i2o_device *i2o_dev = to_i2o_device(dev); |
1043 | struct i2o_block_device *i2o_blk_dev; | ||
1044 | struct i2o_controller *c = i2o_dev->iop; | 1044 | struct i2o_controller *c = i2o_dev->iop; |
1045 | struct i2o_block_device *i2o_blk_dev; | ||
1045 | struct gendisk *gd; | 1046 | struct gendisk *gd; |
1046 | struct request_queue *queue; | 1047 | struct request_queue *queue; |
1047 | static int unit = 0; | 1048 | static int unit = 0; |
1048 | int rc; | 1049 | int rc; |
1049 | u64 size; | 1050 | u64 size; |
1050 | u32 blocksize; | 1051 | u32 blocksize; |
1051 | u16 power; | ||
1052 | u32 flags, status; | 1052 | u32 flags, status; |
1053 | int segments; | 1053 | u16 body_size = 4; |
1054 | unsigned short max_sectors; | ||
1055 | |||
1056 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
1057 | if (c->adaptec) | ||
1058 | body_size = 8; | ||
1059 | #endif | ||
1060 | |||
1061 | if (c->limit_sectors) | ||
1062 | max_sectors = I2O_MAX_SECTORS_LIMITED; | ||
1063 | else | ||
1064 | max_sectors = I2O_MAX_SECTORS; | ||
1054 | 1065 | ||
1055 | /* skip devices which are used by IOP */ | 1066 | /* skip devices which are used by IOP */ |
1056 | if (i2o_dev->lct_data.user_tid != 0xfff) { | 1067 | if (i2o_dev->lct_data.user_tid != 0xfff) { |
@@ -1058,8 +1069,6 @@ static int i2o_block_probe(struct device *dev) | |||
1058 | return -ENODEV; | 1069 | return -ENODEV; |
1059 | } | 1070 | } |
1060 | 1071 | ||
1061 | osm_info("New device detected (TID: %03x)\n", i2o_dev->lct_data.tid); | ||
1062 | |||
1063 | if (i2o_device_claim(i2o_dev)) { | 1072 | if (i2o_device_claim(i2o_dev)) { |
1064 | osm_warn("Unable to claim device. Installation aborted\n"); | 1073 | osm_warn("Unable to claim device. Installation aborted\n"); |
1065 | rc = -EFAULT; | 1074 | rc = -EFAULT; |
@@ -1087,50 +1096,44 @@ static int i2o_block_probe(struct device *dev) | |||
1087 | queue = gd->queue; | 1096 | queue = gd->queue; |
1088 | queue->queuedata = i2o_blk_dev; | 1097 | queue->queuedata = i2o_blk_dev; |
1089 | 1098 | ||
1090 | blk_queue_max_phys_segments(queue, I2O_MAX_SEGMENTS); | 1099 | blk_queue_max_phys_segments(queue, I2O_MAX_PHYS_SEGMENTS); |
1091 | blk_queue_max_sectors(queue, I2O_MAX_SECTORS); | 1100 | blk_queue_max_sectors(queue, max_sectors); |
1092 | 1101 | blk_queue_max_hw_segments(queue, i2o_sg_tablesize(c, body_size)); | |
1093 | if (c->short_req) | ||
1094 | segments = 8; | ||
1095 | else { | ||
1096 | i2o_status_block *sb; | ||
1097 | 1102 | ||
1098 | sb = c->status_block.virt; | 1103 | osm_debug("max sectors = %d\n", queue->max_phys_segments); |
1099 | 1104 | osm_debug("phys segments = %d\n", queue->max_sectors); | |
1100 | segments = (sb->inbound_frame_size - | 1105 | osm_debug("max hw segments = %d\n", queue->max_hw_segments); |
1101 | sizeof(struct i2o_message) / 4 - 4) / 2; | ||
1102 | } | ||
1103 | |||
1104 | blk_queue_max_hw_segments(queue, segments); | ||
1105 | |||
1106 | osm_debug("max sectors = %d\n", I2O_MAX_SECTORS); | ||
1107 | osm_debug("phys segments = %d\n", I2O_MAX_SEGMENTS); | ||
1108 | osm_debug("hw segments = %d\n", segments); | ||
1109 | 1106 | ||
1110 | /* | 1107 | /* |
1111 | * Ask for the current media data. If that isn't supported | 1108 | * Ask for the current media data. If that isn't supported |
1112 | * then we ask for the device capacity data | 1109 | * then we ask for the device capacity data |
1113 | */ | 1110 | */ |
1114 | if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) != 0 | 1111 | if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || |
1115 | || i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) != 0) { | 1112 | i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { |
1116 | i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4); | 1113 | blk_queue_hardsect_size(queue, blocksize); |
1117 | i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8); | 1114 | } else |
1118 | } | 1115 | osm_warn("unable to get blocksize of %s\n", gd->disk_name); |
1119 | osm_debug("blocksize = %d\n", blocksize); | ||
1120 | 1116 | ||
1121 | if (i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2)) | 1117 | if (i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) || |
1122 | power = 0; | 1118 | i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) { |
1119 | set_capacity(gd, size >> KERNEL_SECTOR_SHIFT); | ||
1120 | } else | ||
1121 | osm_warn("could not get size of %s\n", gd->disk_name); | ||
1122 | |||
1123 | if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2)) | ||
1124 | i2o_blk_dev->power = 0; | ||
1123 | i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4); | 1125 | i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4); |
1124 | i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4); | 1126 | i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4); |
1125 | 1127 | ||
1126 | set_capacity(gd, size >> 9); | ||
1127 | |||
1128 | i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff); | 1128 | i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff); |
1129 | 1129 | ||
1130 | add_disk(gd); | 1130 | add_disk(gd); |
1131 | 1131 | ||
1132 | unit++; | 1132 | unit++; |
1133 | 1133 | ||
1134 | osm_info("device added (TID: %03x): %s\n", i2o_dev->lct_data.tid, | ||
1135 | i2o_blk_dev->gd->disk_name); | ||
1136 | |||
1134 | return 0; | 1137 | return 0; |
1135 | 1138 | ||
1136 | claim_release: | 1139 | claim_release: |
@@ -1178,7 +1181,7 @@ static int __init i2o_block_init(void) | |||
1178 | goto exit; | 1181 | goto exit; |
1179 | } | 1182 | } |
1180 | 1183 | ||
1181 | i2o_blk_req_pool.pool = mempool_create(I2O_REQ_MEMPOOL_SIZE, | 1184 | i2o_blk_req_pool.pool = mempool_create(I2O_BLOCK_REQ_MEMPOOL_SIZE, |
1182 | mempool_alloc_slab, | 1185 | mempool_alloc_slab, |
1183 | mempool_free_slab, | 1186 | mempool_free_slab, |
1184 | i2o_blk_req_pool.slab); | 1187 | i2o_blk_req_pool.slab); |
diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h index ddd9a15679..4fdaa5bda4 100644 --- a/drivers/message/i2o/i2o_block.h +++ b/drivers/message/i2o/i2o_block.h | |||
@@ -56,42 +56,46 @@ | |||
56 | #define I2O_BLOCK_RETRY_TIME HZ/4 | 56 | #define I2O_BLOCK_RETRY_TIME HZ/4 |
57 | #define I2O_BLOCK_MAX_OPEN_REQUESTS 50 | 57 | #define I2O_BLOCK_MAX_OPEN_REQUESTS 50 |
58 | 58 | ||
59 | /* request queue sizes */ | ||
60 | #define I2O_BLOCK_REQ_MEMPOOL_SIZE 32 | ||
61 | |||
62 | #define KERNEL_SECTOR_SHIFT 9 | ||
63 | #define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT) | ||
64 | |||
59 | /* I2O Block OSM mempool struct */ | 65 | /* I2O Block OSM mempool struct */ |
60 | struct i2o_block_mempool { | 66 | struct i2o_block_mempool { |
61 | kmem_cache_t *slab; | 67 | kmem_cache_t *slab; |
62 | mempool_t *pool; | 68 | mempool_t *pool; |
63 | }; | 69 | }; |
64 | 70 | ||
65 | /* I2O Block device descriptor */ | 71 | /* I2O Block device descriptor */ |
66 | struct i2o_block_device { | 72 | struct i2o_block_device { |
67 | struct i2o_device *i2o_dev; /* pointer to I2O device */ | 73 | struct i2o_device *i2o_dev; /* pointer to I2O device */ |
68 | struct gendisk *gd; | 74 | struct gendisk *gd; |
69 | spinlock_t lock; /* queue lock */ | 75 | spinlock_t lock; /* queue lock */ |
70 | struct list_head open_queue; /* list of transfered, but unfinished | 76 | struct list_head open_queue; /* list of transfered, but unfinished |
71 | requests */ | 77 | requests */ |
72 | unsigned int open_queue_depth; /* number of requests in the queue */ | 78 | unsigned int open_queue_depth; /* number of requests in the queue */ |
73 | 79 | ||
74 | int rcache; /* read cache flags */ | 80 | int rcache; /* read cache flags */ |
75 | int wcache; /* write cache flags */ | 81 | int wcache; /* write cache flags */ |
76 | int flags; | 82 | int flags; |
77 | int power; /* power state */ | 83 | u16 power; /* power state */ |
78 | int media_change_flag; /* media changed flag */ | 84 | int media_change_flag; /* media changed flag */ |
79 | }; | 85 | }; |
80 | 86 | ||
81 | /* I2O Block device request */ | 87 | /* I2O Block device request */ |
82 | struct i2o_block_request | 88 | struct i2o_block_request { |
83 | { | ||
84 | struct list_head queue; | 89 | struct list_head queue; |
85 | struct request *req; /* corresponding request */ | 90 | struct request *req; /* corresponding request */ |
86 | struct i2o_block_device *i2o_blk_dev; /* I2O block device */ | 91 | struct i2o_block_device *i2o_blk_dev; /* I2O block device */ |
87 | int sg_dma_direction; /* direction of DMA buffer read/write */ | 92 | struct device *dev; /* device used for DMA */ |
88 | int sg_nents; /* number of SG elements */ | 93 | int sg_nents; /* number of SG elements */ |
89 | struct scatterlist sg_table[I2O_MAX_SEGMENTS]; /* SG table */ | 94 | struct scatterlist sg_table[I2O_MAX_PHYS_SEGMENTS]; /* SG table */ |
90 | }; | 95 | }; |
91 | 96 | ||
92 | /* I2O Block device delayed request */ | 97 | /* I2O Block device delayed request */ |
93 | struct i2o_block_delayed_request | 98 | struct i2o_block_delayed_request { |
94 | { | ||
95 | struct work_struct work; | 99 | struct work_struct work; |
96 | struct request_queue *queue; | 100 | struct request_queue *queue; |
97 | }; | 101 | }; |
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 1fb5cdf67f..3c3a7abebb 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c | |||
@@ -30,29 +30,15 @@ | |||
30 | * 2 of the License, or (at your option) any later version. | 30 | * 2 of the License, or (at your option) any later version. |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/pci.h> | ||
36 | #include <linux/i2o.h> | ||
37 | #include <linux/errno.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/slab.h> | ||
40 | #include <linux/miscdevice.h> | 33 | #include <linux/miscdevice.h> |
41 | #include <linux/mm.h> | ||
42 | #include <linux/spinlock.h> | ||
43 | #include <linux/smp_lock.h> | 34 | #include <linux/smp_lock.h> |
44 | #include <linux/ioctl32.h> | ||
45 | #include <linux/compat.h> | 35 | #include <linux/compat.h> |
46 | #include <linux/syscalls.h> | ||
47 | 36 | ||
48 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
49 | #include <asm/io.h> | ||
50 | 38 | ||
51 | #define OSM_NAME "config-osm" | 39 | #include "core.h" |
52 | #define OSM_VERSION "$Rev$" | ||
53 | #define OSM_DESCRIPTION "I2O Configuration OSM" | ||
54 | 40 | ||
55 | extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); | 41 | #define SG_TABLESIZE 30 |
56 | 42 | ||
57 | static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, | 43 | static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, |
58 | unsigned long arg); | 44 | unsigned long arg); |
@@ -80,15 +66,6 @@ struct i2o_cfg_info { | |||
80 | static struct i2o_cfg_info *open_files = NULL; | 66 | static struct i2o_cfg_info *open_files = NULL; |
81 | static ulong i2o_cfg_info_id = 0; | 67 | static ulong i2o_cfg_info_id = 0; |
82 | 68 | ||
83 | /* | ||
84 | * Each of these describes an i2o message handler. They are | ||
85 | * multiplexed by the i2o_core code | ||
86 | */ | ||
87 | |||
88 | static struct i2o_driver i2o_config_driver = { | ||
89 | .name = OSM_NAME | ||
90 | }; | ||
91 | |||
92 | static int i2o_cfg_getiops(unsigned long arg) | 69 | static int i2o_cfg_getiops(unsigned long arg) |
93 | { | 70 | { |
94 | struct i2o_controller *c; | 71 | struct i2o_controller *c; |
@@ -391,9 +368,9 @@ static int i2o_cfg_swul(unsigned long arg) | |||
391 | 368 | ||
392 | i2o_dma_free(&c->pdev->dev, &buffer); | 369 | i2o_dma_free(&c->pdev->dev, &buffer); |
393 | 370 | ||
394 | return_ret: | 371 | return_ret: |
395 | return ret; | 372 | return ret; |
396 | return_fault: | 373 | return_fault: |
397 | ret = -EFAULT; | 374 | ret = -EFAULT; |
398 | goto return_ret; | 375 | goto return_ret; |
399 | }; | 376 | }; |
@@ -540,8 +517,10 @@ static int i2o_cfg_evt_get(unsigned long arg, struct file *fp) | |||
540 | return 0; | 517 | return 0; |
541 | } | 518 | } |
542 | 519 | ||
520 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
543 | #ifdef CONFIG_COMPAT | 521 | #ifdef CONFIG_COMPAT |
544 | static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long arg) | 522 | static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, |
523 | unsigned long arg) | ||
545 | { | 524 | { |
546 | struct i2o_cmd_passthru32 __user *cmd; | 525 | struct i2o_cmd_passthru32 __user *cmd; |
547 | struct i2o_controller *c; | 526 | struct i2o_controller *c; |
@@ -555,6 +534,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
555 | u32 sg_offset = 0; | 534 | u32 sg_offset = 0; |
556 | u32 sg_count = 0; | 535 | u32 sg_count = 0; |
557 | u32 i = 0; | 536 | u32 i = 0; |
537 | u32 sg_index = 0; | ||
558 | i2o_status_block *sb; | 538 | i2o_status_block *sb; |
559 | struct i2o_message *msg; | 539 | struct i2o_message *msg; |
560 | u32 m; | 540 | u32 m; |
@@ -634,8 +614,8 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
634 | if (sg_count > SG_TABLESIZE) { | 614 | if (sg_count > SG_TABLESIZE) { |
635 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", | 615 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", |
636 | c->name, sg_count); | 616 | c->name, sg_count); |
637 | kfree(reply); | 617 | rcode = -EINVAL; |
638 | return -EINVAL; | 618 | goto cleanup; |
639 | } | 619 | } |
640 | 620 | ||
641 | for (i = 0; i < sg_count; i++) { | 621 | for (i = 0; i < sg_count; i++) { |
@@ -651,7 +631,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
651 | goto cleanup; | 631 | goto cleanup; |
652 | } | 632 | } |
653 | sg_size = sg[i].flag_count & 0xffffff; | 633 | sg_size = sg[i].flag_count & 0xffffff; |
654 | p = &(sg_list[i]); | 634 | p = &(sg_list[sg_index++]); |
655 | /* Allocate memory for the transfer */ | 635 | /* Allocate memory for the transfer */ |
656 | if (i2o_dma_alloc | 636 | if (i2o_dma_alloc |
657 | (&c->pdev->dev, p, sg_size, | 637 | (&c->pdev->dev, p, sg_size, |
@@ -660,20 +640,21 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
660 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", | 640 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
661 | c->name, sg_size, i, sg_count); | 641 | c->name, sg_size, i, sg_count); |
662 | rcode = -ENOMEM; | 642 | rcode = -ENOMEM; |
663 | goto cleanup; | 643 | goto sg_list_cleanup; |
664 | } | 644 | } |
665 | /* Copy in the user's SG buffer if necessary */ | 645 | /* Copy in the user's SG buffer if necessary */ |
666 | if (sg[i]. | 646 | if (sg[i]. |
667 | flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { | 647 | flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { |
668 | // TODO 64bit fix | 648 | // TODO 64bit fix |
669 | if (copy_from_user | 649 | if (copy_from_user |
670 | (p->virt, (void __user *)(unsigned long)sg[i].addr_bus, | 650 | (p->virt, |
671 | sg_size)) { | 651 | (void __user *)(unsigned long)sg[i]. |
652 | addr_bus, sg_size)) { | ||
672 | printk(KERN_DEBUG | 653 | printk(KERN_DEBUG |
673 | "%s: Could not copy SG buf %d FROM user\n", | 654 | "%s: Could not copy SG buf %d FROM user\n", |
674 | c->name, i); | 655 | c->name, i); |
675 | rcode = -EFAULT; | 656 | rcode = -EFAULT; |
676 | goto cleanup; | 657 | goto sg_list_cleanup; |
677 | } | 658 | } |
678 | } | 659 | } |
679 | //TODO 64bit fix | 660 | //TODO 64bit fix |
@@ -683,10 +664,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
683 | 664 | ||
684 | rcode = i2o_msg_post_wait(c, m, 60); | 665 | rcode = i2o_msg_post_wait(c, m, 60); |
685 | if (rcode) | 666 | if (rcode) |
686 | goto cleanup; | 667 | goto sg_list_cleanup; |
687 | 668 | ||
688 | if (sg_offset) { | 669 | if (sg_offset) { |
689 | u32 msg[128]; | 670 | u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE]; |
690 | /* Copy back the Scatter Gather buffers back to user space */ | 671 | /* Copy back the Scatter Gather buffers back to user space */ |
691 | u32 j; | 672 | u32 j; |
692 | // TODO 64bit fix | 673 | // TODO 64bit fix |
@@ -694,18 +675,18 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
694 | int sg_size; | 675 | int sg_size; |
695 | 676 | ||
696 | // re-acquire the original message to handle correctly the sg copy operation | 677 | // re-acquire the original message to handle correctly the sg copy operation |
697 | memset(&msg, 0, MSG_FRAME_SIZE * 4); | 678 | memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); |
698 | // get user msg size in u32s | 679 | // get user msg size in u32s |
699 | if (get_user(size, &user_msg[0])) { | 680 | if (get_user(size, &user_msg[0])) { |
700 | rcode = -EFAULT; | 681 | rcode = -EFAULT; |
701 | goto cleanup; | 682 | goto sg_list_cleanup; |
702 | } | 683 | } |
703 | size = size >> 16; | 684 | size = size >> 16; |
704 | size *= 4; | 685 | size *= 4; |
705 | /* Copy in the user's I2O command */ | 686 | /* Copy in the user's I2O command */ |
706 | if (copy_from_user(msg, user_msg, size)) { | 687 | if (copy_from_user(msg, user_msg, size)) { |
707 | rcode = -EFAULT; | 688 | rcode = -EFAULT; |
708 | goto cleanup; | 689 | goto sg_list_cleanup; |
709 | } | 690 | } |
710 | sg_count = | 691 | sg_count = |
711 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); | 692 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); |
@@ -727,7 +708,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
727 | c->name, sg_list[j].virt, | 708 | c->name, sg_list[j].virt, |
728 | sg[j].addr_bus); | 709 | sg[j].addr_bus); |
729 | rcode = -EFAULT; | 710 | rcode = -EFAULT; |
730 | goto cleanup; | 711 | goto sg_list_cleanup; |
731 | } | 712 | } |
732 | } | 713 | } |
733 | } | 714 | } |
@@ -741,6 +722,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
741 | "%s: Could not copy message context FROM user\n", | 722 | "%s: Could not copy message context FROM user\n", |
742 | c->name); | 723 | c->name); |
743 | rcode = -EFAULT; | 724 | rcode = -EFAULT; |
725 | goto sg_list_cleanup; | ||
744 | } | 726 | } |
745 | if (copy_to_user(user_reply, reply, reply_size)) { | 727 | if (copy_to_user(user_reply, reply, reply_size)) { |
746 | printk(KERN_WARNING | 728 | printk(KERN_WARNING |
@@ -749,16 +731,21 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
749 | } | 731 | } |
750 | } | 732 | } |
751 | 733 | ||
734 | sg_list_cleanup: | ||
735 | for (i = 0; i < sg_index; i++) | ||
736 | i2o_dma_free(&c->pdev->dev, &sg_list[i]); | ||
737 | |||
752 | cleanup: | 738 | cleanup: |
753 | kfree(reply); | 739 | kfree(reply); |
754 | return rcode; | 740 | return rcode; |
755 | } | 741 | } |
756 | 742 | ||
757 | static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) | 743 | static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, |
744 | unsigned long arg) | ||
758 | { | 745 | { |
759 | int ret; | 746 | int ret; |
760 | lock_kernel(); | 747 | lock_kernel(); |
761 | switch (cmd) { | 748 | switch (cmd) { |
762 | case I2OGETIOPS: | 749 | case I2OGETIOPS: |
763 | ret = i2o_cfg_ioctl(NULL, file, cmd, arg); | 750 | ret = i2o_cfg_ioctl(NULL, file, cmd, arg); |
764 | break; | 751 | break; |
@@ -862,8 +849,8 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
862 | if (sg_count > SG_TABLESIZE) { | 849 | if (sg_count > SG_TABLESIZE) { |
863 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", | 850 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", |
864 | c->name, sg_count); | 851 | c->name, sg_count); |
865 | kfree(reply); | 852 | rcode = -EINVAL; |
866 | return -EINVAL; | 853 | goto cleanup; |
867 | } | 854 | } |
868 | 855 | ||
869 | for (i = 0; i < sg_count; i++) { | 856 | for (i = 0; i < sg_count; i++) { |
@@ -875,7 +862,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
875 | "%s:Bad SG element %d - not simple (%x)\n", | 862 | "%s:Bad SG element %d - not simple (%x)\n", |
876 | c->name, i, sg[i].flag_count); | 863 | c->name, i, sg[i].flag_count); |
877 | rcode = -EINVAL; | 864 | rcode = -EINVAL; |
878 | goto cleanup; | 865 | goto sg_list_cleanup; |
879 | } | 866 | } |
880 | sg_size = sg[i].flag_count & 0xffffff; | 867 | sg_size = sg[i].flag_count & 0xffffff; |
881 | /* Allocate memory for the transfer */ | 868 | /* Allocate memory for the transfer */ |
@@ -885,7 +872,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
885 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", | 872 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
886 | c->name, sg_size, i, sg_count); | 873 | c->name, sg_size, i, sg_count); |
887 | rcode = -ENOMEM; | 874 | rcode = -ENOMEM; |
888 | goto cleanup; | 875 | goto sg_list_cleanup; |
889 | } | 876 | } |
890 | sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. | 877 | sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. |
891 | /* Copy in the user's SG buffer if necessary */ | 878 | /* Copy in the user's SG buffer if necessary */ |
@@ -899,7 +886,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
899 | "%s: Could not copy SG buf %d FROM user\n", | 886 | "%s: Could not copy SG buf %d FROM user\n", |
900 | c->name, i); | 887 | c->name, i); |
901 | rcode = -EFAULT; | 888 | rcode = -EFAULT; |
902 | goto cleanup; | 889 | goto sg_list_cleanup; |
903 | } | 890 | } |
904 | } | 891 | } |
905 | //TODO 64bit fix | 892 | //TODO 64bit fix |
@@ -909,7 +896,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
909 | 896 | ||
910 | rcode = i2o_msg_post_wait(c, m, 60); | 897 | rcode = i2o_msg_post_wait(c, m, 60); |
911 | if (rcode) | 898 | if (rcode) |
912 | goto cleanup; | 899 | goto sg_list_cleanup; |
913 | 900 | ||
914 | if (sg_offset) { | 901 | if (sg_offset) { |
915 | u32 msg[128]; | 902 | u32 msg[128]; |
@@ -920,18 +907,18 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
920 | int sg_size; | 907 | int sg_size; |
921 | 908 | ||
922 | // re-acquire the original message to handle correctly the sg copy operation | 909 | // re-acquire the original message to handle correctly the sg copy operation |
923 | memset(&msg, 0, MSG_FRAME_SIZE * 4); | 910 | memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); |
924 | // get user msg size in u32s | 911 | // get user msg size in u32s |
925 | if (get_user(size, &user_msg[0])) { | 912 | if (get_user(size, &user_msg[0])) { |
926 | rcode = -EFAULT; | 913 | rcode = -EFAULT; |
927 | goto cleanup; | 914 | goto sg_list_cleanup; |
928 | } | 915 | } |
929 | size = size >> 16; | 916 | size = size >> 16; |
930 | size *= 4; | 917 | size *= 4; |
931 | /* Copy in the user's I2O command */ | 918 | /* Copy in the user's I2O command */ |
932 | if (copy_from_user(msg, user_msg, size)) { | 919 | if (copy_from_user(msg, user_msg, size)) { |
933 | rcode = -EFAULT; | 920 | rcode = -EFAULT; |
934 | goto cleanup; | 921 | goto sg_list_cleanup; |
935 | } | 922 | } |
936 | sg_count = | 923 | sg_count = |
937 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); | 924 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); |
@@ -953,7 +940,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
953 | c->name, sg_list[j], | 940 | c->name, sg_list[j], |
954 | sg[j].addr_bus); | 941 | sg[j].addr_bus); |
955 | rcode = -EFAULT; | 942 | rcode = -EFAULT; |
956 | goto cleanup; | 943 | goto sg_list_cleanup; |
957 | } | 944 | } |
958 | } | 945 | } |
959 | } | 946 | } |
@@ -975,10 +962,15 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
975 | } | 962 | } |
976 | } | 963 | } |
977 | 964 | ||
965 | sg_list_cleanup: | ||
966 | for (i = 0; i < sg_index; i++) | ||
967 | kfree(sg_list[i]); | ||
968 | |||
978 | cleanup: | 969 | cleanup: |
979 | kfree(reply); | 970 | kfree(reply); |
980 | return rcode; | 971 | return rcode; |
981 | } | 972 | } |
973 | #endif | ||
982 | 974 | ||
983 | /* | 975 | /* |
984 | * IOCTL Handler | 976 | * IOCTL Handler |
@@ -1033,9 +1025,11 @@ static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, | |||
1033 | ret = i2o_cfg_evt_get(arg, fp); | 1025 | ret = i2o_cfg_evt_get(arg, fp); |
1034 | break; | 1026 | break; |
1035 | 1027 | ||
1028 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
1036 | case I2OPASSTHRU: | 1029 | case I2OPASSTHRU: |
1037 | ret = i2o_cfg_passthru(arg); | 1030 | ret = i2o_cfg_passthru(arg); |
1038 | break; | 1031 | break; |
1032 | #endif | ||
1039 | 1033 | ||
1040 | default: | 1034 | default: |
1041 | osm_debug("unknown ioctl called!\n"); | 1035 | osm_debug("unknown ioctl called!\n"); |
@@ -1137,37 +1131,21 @@ static struct miscdevice i2o_miscdev = { | |||
1137 | &config_fops | 1131 | &config_fops |
1138 | }; | 1132 | }; |
1139 | 1133 | ||
1140 | static int __init i2o_config_init(void) | 1134 | static int __init i2o_config_old_init(void) |
1141 | { | 1135 | { |
1142 | printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); | ||
1143 | |||
1144 | spin_lock_init(&i2o_config_lock); | 1136 | spin_lock_init(&i2o_config_lock); |
1145 | 1137 | ||
1146 | if (misc_register(&i2o_miscdev) < 0) { | 1138 | if (misc_register(&i2o_miscdev) < 0) { |
1147 | osm_err("can't register device.\n"); | 1139 | osm_err("can't register device.\n"); |
1148 | return -EBUSY; | 1140 | return -EBUSY; |
1149 | } | 1141 | } |
1150 | /* | 1142 | |
1151 | * Install our handler | ||
1152 | */ | ||
1153 | if (i2o_driver_register(&i2o_config_driver)) { | ||
1154 | osm_err("handler register failed.\n"); | ||
1155 | misc_deregister(&i2o_miscdev); | ||
1156 | return -EBUSY; | ||
1157 | } | ||
1158 | return 0; | 1143 | return 0; |
1159 | } | 1144 | } |
1160 | 1145 | ||
1161 | static void i2o_config_exit(void) | 1146 | static void i2o_config_old_exit(void) |
1162 | { | 1147 | { |
1163 | misc_deregister(&i2o_miscdev); | 1148 | misc_deregister(&i2o_miscdev); |
1164 | i2o_driver_unregister(&i2o_config_driver); | ||
1165 | } | 1149 | } |
1166 | 1150 | ||
1167 | MODULE_AUTHOR("Red Hat Software"); | 1151 | MODULE_AUTHOR("Red Hat Software"); |
1168 | MODULE_LICENSE("GPL"); | ||
1169 | MODULE_DESCRIPTION(OSM_DESCRIPTION); | ||
1170 | MODULE_VERSION(OSM_VERSION); | ||
1171 | |||
1172 | module_init(i2o_config_init); | ||
1173 | module_exit(i2o_config_exit); | ||
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index b176d0eeff..d559a17583 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c | |||
@@ -28,7 +28,7 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #define OSM_NAME "proc-osm" | 30 | #define OSM_NAME "proc-osm" |
31 | #define OSM_VERSION "$Rev$" | 31 | #define OSM_VERSION "1.145" |
32 | #define OSM_DESCRIPTION "I2O ProcFS OSM" | 32 | #define OSM_DESCRIPTION "I2O ProcFS OSM" |
33 | 33 | ||
34 | #define I2O_MAX_MODULES 4 | 34 | #define I2O_MAX_MODULES 4 |
@@ -228,7 +228,7 @@ static const char *i2o_get_class_name(int class) | |||
228 | case I2O_CLASS_FLOPPY_DEVICE: | 228 | case I2O_CLASS_FLOPPY_DEVICE: |
229 | idx = 12; | 229 | idx = 12; |
230 | break; | 230 | break; |
231 | case I2O_CLASS_BUS_ADAPTER_PORT: | 231 | case I2O_CLASS_BUS_ADAPTER: |
232 | idx = 13; | 232 | idx = 13; |
233 | break; | 233 | break; |
234 | case I2O_CLASS_PEER_TRANSPORT_AGENT: | 234 | case I2O_CLASS_PEER_TRANSPORT_AGENT: |
@@ -490,7 +490,7 @@ static int i2o_seq_show_lct(struct seq_file *seq, void *v) | |||
490 | seq_printf(seq, ", Unknown Device Type"); | 490 | seq_printf(seq, ", Unknown Device Type"); |
491 | break; | 491 | break; |
492 | 492 | ||
493 | case I2O_CLASS_BUS_ADAPTER_PORT: | 493 | case I2O_CLASS_BUS_ADAPTER: |
494 | if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) | 494 | if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) |
495 | seq_printf(seq, ", %s", | 495 | seq_printf(seq, ", %s", |
496 | bus_ports[lct->lct_entry[i]. | 496 | bus_ports[lct->lct_entry[i]. |
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index 43f5875e0b..9f1744c393 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include <linux/pci.h> | 54 | #include <linux/pci.h> |
55 | #include <linux/blkdev.h> | 55 | #include <linux/blkdev.h> |
56 | #include <linux/i2o.h> | 56 | #include <linux/i2o.h> |
57 | #include <linux/scatterlist.h> | ||
57 | 58 | ||
58 | #include <asm/dma.h> | 59 | #include <asm/dma.h> |
59 | #include <asm/system.h> | 60 | #include <asm/system.h> |
@@ -64,19 +65,23 @@ | |||
64 | #include <scsi/scsi_host.h> | 65 | #include <scsi/scsi_host.h> |
65 | #include <scsi/scsi_device.h> | 66 | #include <scsi/scsi_device.h> |
66 | #include <scsi/scsi_cmnd.h> | 67 | #include <scsi/scsi_cmnd.h> |
68 | #include <scsi/scsi_request.h> | ||
69 | #include <scsi/sg.h> | ||
70 | #include <scsi/sg_request.h> | ||
67 | 71 | ||
68 | #define OSM_NAME "scsi-osm" | 72 | #define OSM_NAME "scsi-osm" |
69 | #define OSM_VERSION "$Rev$" | 73 | #define OSM_VERSION "1.282" |
70 | #define OSM_DESCRIPTION "I2O SCSI Peripheral OSM" | 74 | #define OSM_DESCRIPTION "I2O SCSI Peripheral OSM" |
71 | 75 | ||
72 | static struct i2o_driver i2o_scsi_driver; | 76 | static struct i2o_driver i2o_scsi_driver; |
73 | 77 | ||
74 | static int i2o_scsi_max_id = 16; | 78 | static unsigned int i2o_scsi_max_id = 16; |
75 | static int i2o_scsi_max_lun = 8; | 79 | static unsigned int i2o_scsi_max_lun = 255; |
76 | 80 | ||
77 | struct i2o_scsi_host { | 81 | struct i2o_scsi_host { |
78 | struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ | 82 | struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ |
79 | struct i2o_controller *iop; /* pointer to the I2O controller */ | 83 | struct i2o_controller *iop; /* pointer to the I2O controller */ |
84 | unsigned int lun; /* lun's used for block devices */ | ||
80 | struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ | 85 | struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ |
81 | }; | 86 | }; |
82 | 87 | ||
@@ -99,11 +104,17 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) | |||
99 | u8 type; | 104 | u8 type; |
100 | int i; | 105 | int i; |
101 | size_t size; | 106 | size_t size; |
102 | i2o_status_block *sb; | 107 | u16 body_size = 6; |
108 | |||
109 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
110 | if (c->adaptec) | ||
111 | body_size = 8; | ||
112 | #endif | ||
103 | 113 | ||
104 | list_for_each_entry(i2o_dev, &c->devices, list) | 114 | list_for_each_entry(i2o_dev, &c->devices, list) |
105 | if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) { | 115 | if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { |
106 | if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* SCSI bus */ | 116 | if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) |
117 | && (type == 0x01)) /* SCSI bus */ | ||
107 | max_channel++; | 118 | max_channel++; |
108 | } | 119 | } |
109 | 120 | ||
@@ -125,20 +136,18 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) | |||
125 | scsi_host->max_id = i2o_scsi_max_id; | 136 | scsi_host->max_id = i2o_scsi_max_id; |
126 | scsi_host->max_lun = i2o_scsi_max_lun; | 137 | scsi_host->max_lun = i2o_scsi_max_lun; |
127 | scsi_host->this_id = c->unit; | 138 | scsi_host->this_id = c->unit; |
128 | 139 | scsi_host->sg_tablesize = i2o_sg_tablesize(c, body_size); | |
129 | sb = c->status_block.virt; | ||
130 | |||
131 | scsi_host->sg_tablesize = (sb->inbound_frame_size - | ||
132 | sizeof(struct i2o_message) / 4 - 6) / 2; | ||
133 | 140 | ||
134 | i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata; | 141 | i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata; |
135 | i2o_shost->scsi_host = scsi_host; | 142 | i2o_shost->scsi_host = scsi_host; |
136 | i2o_shost->iop = c; | 143 | i2o_shost->iop = c; |
144 | i2o_shost->lun = 1; | ||
137 | 145 | ||
138 | i = 0; | 146 | i = 0; |
139 | list_for_each_entry(i2o_dev, &c->devices, list) | 147 | list_for_each_entry(i2o_dev, &c->devices, list) |
140 | if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) { | 148 | if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { |
141 | if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* only SCSI bus */ | 149 | if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) |
150 | && (type == 0x01)) /* only SCSI bus */ | ||
142 | i2o_shost->channel[i++] = i2o_dev; | 151 | i2o_shost->channel[i++] = i2o_dev; |
143 | 152 | ||
144 | if (i >= max_channel) | 153 | if (i >= max_channel) |
@@ -178,10 +187,13 @@ static int i2o_scsi_remove(struct device *dev) | |||
178 | struct i2o_scsi_host *i2o_shost; | 187 | struct i2o_scsi_host *i2o_shost; |
179 | struct scsi_device *scsi_dev; | 188 | struct scsi_device *scsi_dev; |
180 | 189 | ||
190 | osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid); | ||
191 | |||
181 | i2o_shost = i2o_scsi_get_host(c); | 192 | i2o_shost = i2o_scsi_get_host(c); |
182 | 193 | ||
183 | shost_for_each_device(scsi_dev, i2o_shost->scsi_host) | 194 | shost_for_each_device(scsi_dev, i2o_shost->scsi_host) |
184 | if (scsi_dev->hostdata == i2o_dev) { | 195 | if (scsi_dev->hostdata == i2o_dev) { |
196 | sysfs_remove_link(&i2o_dev->device.kobj, "scsi"); | ||
185 | scsi_remove_device(scsi_dev); | 197 | scsi_remove_device(scsi_dev); |
186 | scsi_device_put(scsi_dev); | 198 | scsi_device_put(scsi_dev); |
187 | break; | 199 | break; |
@@ -207,8 +219,8 @@ static int i2o_scsi_probe(struct device *dev) | |||
207 | struct Scsi_Host *scsi_host; | 219 | struct Scsi_Host *scsi_host; |
208 | struct i2o_device *parent; | 220 | struct i2o_device *parent; |
209 | struct scsi_device *scsi_dev; | 221 | struct scsi_device *scsi_dev; |
210 | u32 id; | 222 | u32 id = -1; |
211 | u64 lun; | 223 | u64 lun = -1; |
212 | int channel = -1; | 224 | int channel = -1; |
213 | int i; | 225 | int i; |
214 | 226 | ||
@@ -218,8 +230,56 @@ static int i2o_scsi_probe(struct device *dev) | |||
218 | 230 | ||
219 | scsi_host = i2o_shost->scsi_host; | 231 | scsi_host = i2o_shost->scsi_host; |
220 | 232 | ||
221 | if (i2o_parm_field_get(i2o_dev, 0, 3, &id, 4) < 0) | 233 | switch (i2o_dev->lct_data.class_id) { |
234 | case I2O_CLASS_RANDOM_BLOCK_STORAGE: | ||
235 | case I2O_CLASS_EXECUTIVE: | ||
236 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
237 | if (c->adaptec) { | ||
238 | u8 type; | ||
239 | struct i2o_device *d = i2o_shost->channel[0]; | ||
240 | |||
241 | if (i2o_parm_field_get(d, 0x0000, 0, &type, 1) | ||
242 | && (type == 0x01)) /* SCSI bus */ | ||
243 | if (i2o_parm_field_get(d, 0x0200, 4, &id, 4)) { | ||
244 | channel = 0; | ||
245 | if (i2o_dev->lct_data.class_id == | ||
246 | I2O_CLASS_RANDOM_BLOCK_STORAGE) | ||
247 | lun = i2o_shost->lun++; | ||
248 | else | ||
249 | lun = 0; | ||
250 | } | ||
251 | } | ||
252 | #endif | ||
253 | break; | ||
254 | |||
255 | case I2O_CLASS_SCSI_PERIPHERAL: | ||
256 | if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4) < 0) | ||
257 | return -EFAULT; | ||
258 | |||
259 | if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8) < 0) | ||
260 | return -EFAULT; | ||
261 | |||
262 | parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); | ||
263 | if (!parent) { | ||
264 | osm_warn("can not find parent of device %03x\n", | ||
265 | i2o_dev->lct_data.tid); | ||
266 | return -EFAULT; | ||
267 | } | ||
268 | |||
269 | for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++) | ||
270 | if (i2o_shost->channel[i] == parent) | ||
271 | channel = i; | ||
272 | break; | ||
273 | |||
274 | default: | ||
222 | return -EFAULT; | 275 | return -EFAULT; |
276 | } | ||
277 | |||
278 | if (channel == -1) { | ||
279 | osm_warn("can not find channel of device %03x\n", | ||
280 | i2o_dev->lct_data.tid); | ||
281 | return -EFAULT; | ||
282 | } | ||
223 | 283 | ||
224 | if (id >= scsi_host->max_id) { | 284 | if (id >= scsi_host->max_id) { |
225 | osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id, | 285 | osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id, |
@@ -227,42 +287,26 @@ static int i2o_scsi_probe(struct device *dev) | |||
227 | return -EFAULT; | 287 | return -EFAULT; |
228 | } | 288 | } |
229 | 289 | ||
230 | if (i2o_parm_field_get(i2o_dev, 0, 4, &lun, 8) < 0) | ||
231 | return -EFAULT; | ||
232 | if (lun >= scsi_host->max_lun) { | 290 | if (lun >= scsi_host->max_lun) { |
233 | osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)", | 291 | osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)", |
234 | (unsigned int)lun, scsi_host->max_lun); | 292 | (unsigned int)lun, scsi_host->max_lun); |
235 | return -EFAULT; | 293 | return -EFAULT; |
236 | } | 294 | } |
237 | 295 | ||
238 | parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); | ||
239 | if (!parent) { | ||
240 | osm_warn("can not find parent of device %03x\n", | ||
241 | i2o_dev->lct_data.tid); | ||
242 | return -EFAULT; | ||
243 | } | ||
244 | |||
245 | for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++) | ||
246 | if (i2o_shost->channel[i] == parent) | ||
247 | channel = i; | ||
248 | |||
249 | if (channel == -1) { | ||
250 | osm_warn("can not find channel of device %03x\n", | ||
251 | i2o_dev->lct_data.tid); | ||
252 | return -EFAULT; | ||
253 | } | ||
254 | |||
255 | scsi_dev = | 296 | scsi_dev = |
256 | __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev); | 297 | __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev); |
257 | 298 | ||
258 | if (!scsi_dev) { | 299 | if (IS_ERR(scsi_dev)) { |
259 | osm_warn("can not add SCSI device %03x\n", | 300 | osm_warn("can not add SCSI device %03x\n", |
260 | i2o_dev->lct_data.tid); | 301 | i2o_dev->lct_data.tid); |
261 | return -EFAULT; | 302 | return PTR_ERR(scsi_dev); |
262 | } | 303 | } |
263 | 304 | ||
264 | osm_debug("added new SCSI device %03x (cannel: %d, id: %d, lun: %d)\n", | 305 | sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj, |
265 | i2o_dev->lct_data.tid, channel, id, (unsigned int)lun); | 306 | "scsi"); |
307 | |||
308 | osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n", | ||
309 | i2o_dev->lct_data.tid, channel, id, (unsigned int)lun); | ||
266 | 310 | ||
267 | return 0; | 311 | return 0; |
268 | }; | 312 | }; |
@@ -293,162 +337,89 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m, | |||
293 | struct i2o_message *msg) | 337 | struct i2o_message *msg) |
294 | { | 338 | { |
295 | struct scsi_cmnd *cmd; | 339 | struct scsi_cmnd *cmd; |
340 | u32 error; | ||
296 | struct device *dev; | 341 | struct device *dev; |
297 | u8 as, ds, st; | ||
298 | 342 | ||
299 | cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); | 343 | cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); |
300 | 344 | if (unlikely(!cmd)) { | |
301 | if (msg->u.head[0] & (1 << 13)) { | 345 | osm_err("NULL reply received!\n"); |
302 | struct i2o_message __iomem *pmsg; /* preserved message */ | 346 | return -1; |
303 | u32 pm; | ||
304 | int err = DID_ERROR; | ||
305 | |||
306 | pm = le32_to_cpu(msg->body[3]); | ||
307 | |||
308 | pmsg = i2o_msg_in_to_virt(c, pm); | ||
309 | |||
310 | osm_err("IOP fail.\n"); | ||
311 | osm_err("From %d To %d Cmd %d.\n", | ||
312 | (msg->u.head[1] >> 12) & 0xFFF, | ||
313 | msg->u.head[1] & 0xFFF, msg->u.head[1] >> 24); | ||
314 | osm_err("Failure Code %d.\n", msg->body[0] >> 24); | ||
315 | if (msg->body[0] & (1 << 16)) | ||
316 | osm_err("Format error.\n"); | ||
317 | if (msg->body[0] & (1 << 17)) | ||
318 | osm_err("Path error.\n"); | ||
319 | if (msg->body[0] & (1 << 18)) | ||
320 | osm_err("Path State.\n"); | ||
321 | if (msg->body[0] & (1 << 18)) | ||
322 | { | ||
323 | osm_err("Congestion.\n"); | ||
324 | err = DID_BUS_BUSY; | ||
325 | } | ||
326 | |||
327 | osm_debug("Failing message is %p.\n", pmsg); | ||
328 | |||
329 | cmd = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt)); | ||
330 | if (!cmd) | ||
331 | return 1; | ||
332 | |||
333 | cmd->result = err << 16; | ||
334 | cmd->scsi_done(cmd); | ||
335 | |||
336 | /* Now flush the message by making it a NOP */ | ||
337 | i2o_msg_nop(c, pm); | ||
338 | |||
339 | return 1; | ||
340 | } | 347 | } |
341 | 348 | ||
342 | /* | 349 | /* |
343 | * Low byte is device status, next is adapter status, | 350 | * Low byte is device status, next is adapter status, |
344 | * (then one byte reserved), then request status. | 351 | * (then one byte reserved), then request status. |
345 | */ | 352 | */ |
346 | ds = (u8) le32_to_cpu(msg->body[0]); | 353 | error = le32_to_cpu(msg->body[0]); |
347 | as = (u8) (le32_to_cpu(msg->body[0]) >> 8); | 354 | |
348 | st = (u8) (le32_to_cpu(msg->body[0]) >> 24); | 355 | osm_debug("Completed %ld\n", cmd->serial_number); |
349 | 356 | ||
357 | cmd->result = error & 0xff; | ||
350 | /* | 358 | /* |
351 | * Is this a control request coming back - eg an abort ? | 359 | * if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let |
360 | * the SCSI layer handle the error | ||
352 | */ | 361 | */ |
362 | if (cmd->result) | ||
363 | memcpy(cmd->sense_buffer, &msg->body[3], | ||
364 | min(sizeof(cmd->sense_buffer), (size_t) 40)); | ||
353 | 365 | ||
354 | if (!cmd) { | 366 | /* only output error code if AdapterStatus is not HBA_SUCCESS */ |
355 | if (st) | 367 | if ((error >> 8) & 0xff) |
356 | osm_warn("SCSI abort: %08X", le32_to_cpu(msg->body[0])); | 368 | osm_err("SCSI error %08x\n", error); |
357 | osm_info("SCSI abort completed.\n"); | ||
358 | return -EFAULT; | ||
359 | } | ||
360 | 369 | ||
361 | osm_debug("Completed %ld\n", cmd->serial_number); | 370 | dev = &c->pdev->dev; |
371 | if (cmd->use_sg) | ||
372 | dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg, | ||
373 | cmd->sc_data_direction); | ||
374 | else if (cmd->SCp.dma_handle) | ||
375 | dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen, | ||
376 | cmd->sc_data_direction); | ||
362 | 377 | ||
363 | if (st) { | 378 | cmd->scsi_done(cmd); |
364 | u32 count, error; | ||
365 | /* An error has occurred */ | ||
366 | |||
367 | switch (st) { | ||
368 | case 0x06: | ||
369 | count = le32_to_cpu(msg->body[1]); | ||
370 | if (count < cmd->underflow) { | ||
371 | int i; | ||
372 | |||
373 | osm_err("SCSI underflow 0x%08X 0x%08X\n", count, | ||
374 | cmd->underflow); | ||
375 | osm_debug("Cmd: "); | ||
376 | for (i = 0; i < 15; i++) | ||
377 | pr_debug("%02X ", cmd->cmnd[i]); | ||
378 | pr_debug(".\n"); | ||
379 | cmd->result = (DID_ERROR << 16); | ||
380 | } | ||
381 | break; | ||
382 | 379 | ||
383 | default: | 380 | return 1; |
384 | error = le32_to_cpu(msg->body[0]); | 381 | }; |
385 | |||
386 | osm_err("SCSI error %08x\n", error); | ||
387 | |||
388 | if ((error & 0xff) == 0x02 /*CHECK_CONDITION */ ) { | ||
389 | int i; | ||
390 | u32 len = sizeof(cmd->sense_buffer); | ||
391 | len = (len > 40) ? 40 : len; | ||
392 | // Copy over the sense data | ||
393 | memcpy(cmd->sense_buffer, (void *)&msg->body[3], | ||
394 | len); | ||
395 | for (i = 0; i <= len; i++) | ||
396 | osm_info("%02x\n", | ||
397 | cmd->sense_buffer[i]); | ||
398 | if (cmd->sense_buffer[0] == 0x70 | ||
399 | && cmd->sense_buffer[2] == DATA_PROTECT) { | ||
400 | /* This is to handle an array failed */ | ||
401 | cmd->result = (DID_TIME_OUT << 16); | ||
402 | printk(KERN_WARNING "%s: SCSI Data " | ||
403 | "Protect-Device (%d,%d,%d) " | ||
404 | "hba_status=0x%x, dev_status=" | ||
405 | "0x%x, cmd=0x%x\n", c->name, | ||
406 | (u32) cmd->device->channel, | ||
407 | (u32) cmd->device->id, | ||
408 | (u32) cmd->device->lun, | ||
409 | (error >> 8) & 0xff, | ||
410 | error & 0xff, cmd->cmnd[0]); | ||
411 | } else | ||
412 | cmd->result = (DID_ERROR << 16); | ||
413 | |||
414 | break; | ||
415 | } | ||
416 | |||
417 | switch (as) { | ||
418 | case 0x0E: | ||
419 | /* SCSI Reset */ | ||
420 | cmd->result = DID_RESET << 16; | ||
421 | break; | ||
422 | |||
423 | case 0x0F: | ||
424 | cmd->result = DID_PARITY << 16; | ||
425 | break; | ||
426 | |||
427 | default: | ||
428 | cmd->result = DID_ERROR << 16; | ||
429 | break; | ||
430 | } | ||
431 | 382 | ||
432 | break; | 383 | /** |
433 | } | 384 | * i2o_scsi_notify_device_add - Retrieve notifications of added devices |
385 | * @i2o_dev: the I2O device which was added | ||
386 | * | ||
387 | * If a I2O device is added we catch the notification, because I2O classes | ||
388 | * other then SCSI peripheral will not be received through | ||
389 | * i2o_scsi_probe(). | ||
390 | */ | ||
391 | static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev) | ||
392 | { | ||
393 | switch (i2o_dev->lct_data.class_id) { | ||
394 | case I2O_CLASS_EXECUTIVE: | ||
395 | case I2O_CLASS_RANDOM_BLOCK_STORAGE: | ||
396 | i2o_scsi_probe(&i2o_dev->device); | ||
397 | break; | ||
434 | 398 | ||
435 | cmd->scsi_done(cmd); | 399 | default: |
436 | return 1; | 400 | break; |
437 | } | 401 | } |
402 | }; | ||
438 | 403 | ||
439 | cmd->result = DID_OK << 16 | ds; | 404 | /** |
440 | 405 | * i2o_scsi_notify_device_remove - Retrieve notifications of removed | |
441 | cmd->scsi_done(cmd); | 406 | * devices |
442 | 407 | * @i2o_dev: the I2O device which was removed | |
443 | dev = &c->pdev->dev; | 408 | * |
444 | if (cmd->use_sg) | 409 | * If a I2O device is removed, we catch the notification to remove the |
445 | dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer, | 410 | * corresponding SCSI device. |
446 | cmd->use_sg, cmd->sc_data_direction); | 411 | */ |
447 | else if (cmd->request_bufflen) | 412 | static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev) |
448 | dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr), | 413 | { |
449 | cmd->request_bufflen, cmd->sc_data_direction); | 414 | switch (i2o_dev->lct_data.class_id) { |
415 | case I2O_CLASS_EXECUTIVE: | ||
416 | case I2O_CLASS_RANDOM_BLOCK_STORAGE: | ||
417 | i2o_scsi_remove(&i2o_dev->device); | ||
418 | break; | ||
450 | 419 | ||
451 | return 1; | 420 | default: |
421 | break; | ||
422 | } | ||
452 | }; | 423 | }; |
453 | 424 | ||
454 | /** | 425 | /** |
@@ -501,7 +472,7 @@ static void i2o_scsi_notify_controller_remove(struct i2o_controller *c) | |||
501 | 472 | ||
502 | scsi_remove_host(i2o_shost->scsi_host); | 473 | scsi_remove_host(i2o_shost->scsi_host); |
503 | scsi_host_put(i2o_shost->scsi_host); | 474 | scsi_host_put(i2o_shost->scsi_host); |
504 | pr_info("I2O SCSI host removed\n"); | 475 | osm_debug("I2O SCSI host removed\n"); |
505 | }; | 476 | }; |
506 | 477 | ||
507 | /* SCSI OSM driver struct */ | 478 | /* SCSI OSM driver struct */ |
@@ -509,6 +480,8 @@ static struct i2o_driver i2o_scsi_driver = { | |||
509 | .name = OSM_NAME, | 480 | .name = OSM_NAME, |
510 | .reply = i2o_scsi_reply, | 481 | .reply = i2o_scsi_reply, |
511 | .classes = i2o_scsi_class_id, | 482 | .classes = i2o_scsi_class_id, |
483 | .notify_device_add = i2o_scsi_notify_device_add, | ||
484 | .notify_device_remove = i2o_scsi_notify_device_remove, | ||
512 | .notify_controller_add = i2o_scsi_notify_controller_add, | 485 | .notify_controller_add = i2o_scsi_notify_controller_add, |
513 | .notify_controller_remove = i2o_scsi_notify_controller_remove, | 486 | .notify_controller_remove = i2o_scsi_notify_controller_remove, |
514 | .driver = { | 487 | .driver = { |
@@ -535,26 +508,26 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
535 | void (*done) (struct scsi_cmnd *)) | 508 | void (*done) (struct scsi_cmnd *)) |
536 | { | 509 | { |
537 | struct i2o_controller *c; | 510 | struct i2o_controller *c; |
538 | struct Scsi_Host *host; | ||
539 | struct i2o_device *i2o_dev; | 511 | struct i2o_device *i2o_dev; |
540 | struct device *dev; | ||
541 | int tid; | 512 | int tid; |
542 | struct i2o_message __iomem *msg; | 513 | struct i2o_message __iomem *msg; |
543 | u32 m; | 514 | u32 m; |
544 | u32 scsi_flags, sg_flags; | 515 | /* |
516 | * ENABLE_DISCONNECT | ||
517 | * SIMPLE_TAG | ||
518 | * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME | ||
519 | */ | ||
520 | u32 scsi_flags = 0x20a00000; | ||
521 | u32 sgl_offset; | ||
545 | u32 __iomem *mptr; | 522 | u32 __iomem *mptr; |
546 | u32 __iomem *lenptr; | 523 | u32 cmd = I2O_CMD_SCSI_EXEC << 24; |
547 | u32 len, reqlen; | 524 | int rc = 0; |
548 | int i; | ||
549 | 525 | ||
550 | /* | 526 | /* |
551 | * Do the incoming paperwork | 527 | * Do the incoming paperwork |
552 | */ | 528 | */ |
553 | |||
554 | i2o_dev = SCpnt->device->hostdata; | 529 | i2o_dev = SCpnt->device->hostdata; |
555 | host = SCpnt->device->host; | ||
556 | c = i2o_dev->iop; | 530 | c = i2o_dev->iop; |
557 | dev = &c->pdev->dev; | ||
558 | 531 | ||
559 | SCpnt->scsi_done = done; | 532 | SCpnt->scsi_done = done; |
560 | 533 | ||
@@ -562,7 +535,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
562 | osm_warn("no I2O device in request\n"); | 535 | osm_warn("no I2O device in request\n"); |
563 | SCpnt->result = DID_NO_CONNECT << 16; | 536 | SCpnt->result = DID_NO_CONNECT << 16; |
564 | done(SCpnt); | 537 | done(SCpnt); |
565 | return 0; | 538 | goto exit; |
566 | } | 539 | } |
567 | 540 | ||
568 | tid = i2o_dev->lct_data.tid; | 541 | tid = i2o_dev->lct_data.tid; |
@@ -571,44 +544,85 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
571 | osm_debug("Real scsi messages.\n"); | 544 | osm_debug("Real scsi messages.\n"); |
572 | 545 | ||
573 | /* | 546 | /* |
574 | * Obtain an I2O message. If there are none free then | ||
575 | * throw it back to the scsi layer | ||
576 | */ | ||
577 | |||
578 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
579 | if (m == I2O_QUEUE_EMPTY) | ||
580 | return SCSI_MLQUEUE_HOST_BUSY; | ||
581 | |||
582 | /* | ||
583 | * Put together a scsi execscb message | 547 | * Put together a scsi execscb message |
584 | */ | 548 | */ |
585 | |||
586 | len = SCpnt->request_bufflen; | ||
587 | |||
588 | switch (SCpnt->sc_data_direction) { | 549 | switch (SCpnt->sc_data_direction) { |
589 | case PCI_DMA_NONE: | 550 | case PCI_DMA_NONE: |
590 | scsi_flags = 0x00000000; // DATA NO XFER | 551 | /* DATA NO XFER */ |
591 | sg_flags = 0x00000000; | 552 | sgl_offset = SGL_OFFSET_0; |
592 | break; | 553 | break; |
593 | 554 | ||
594 | case PCI_DMA_TODEVICE: | 555 | case PCI_DMA_TODEVICE: |
595 | scsi_flags = 0x80000000; // DATA OUT (iop-->dev) | 556 | /* DATA OUT (iop-->dev) */ |
596 | sg_flags = 0x14000000; | 557 | scsi_flags |= 0x80000000; |
558 | sgl_offset = SGL_OFFSET_10; | ||
597 | break; | 559 | break; |
598 | 560 | ||
599 | case PCI_DMA_FROMDEVICE: | 561 | case PCI_DMA_FROMDEVICE: |
600 | scsi_flags = 0x40000000; // DATA IN (iop<--dev) | 562 | /* DATA IN (iop<--dev) */ |
601 | sg_flags = 0x10000000; | 563 | scsi_flags |= 0x40000000; |
564 | sgl_offset = SGL_OFFSET_10; | ||
602 | break; | 565 | break; |
603 | 566 | ||
604 | default: | 567 | default: |
605 | /* Unknown - kill the command */ | 568 | /* Unknown - kill the command */ |
606 | SCpnt->result = DID_NO_CONNECT << 16; | 569 | SCpnt->result = DID_NO_CONNECT << 16; |
607 | done(SCpnt); | 570 | done(SCpnt); |
608 | return 0; | 571 | goto exit; |
609 | } | 572 | } |
610 | 573 | ||
611 | writel(I2O_CMD_SCSI_EXEC << 24 | HOST_TID << 12 | tid, &msg->u.head[1]); | 574 | /* |
575 | * Obtain an I2O message. If there are none free then | ||
576 | * throw it back to the scsi layer | ||
577 | */ | ||
578 | |||
579 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
580 | if (m == I2O_QUEUE_EMPTY) { | ||
581 | rc = SCSI_MLQUEUE_HOST_BUSY; | ||
582 | goto exit; | ||
583 | } | ||
584 | |||
585 | mptr = &msg->body[0]; | ||
586 | |||
587 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
588 | if (c->adaptec) { | ||
589 | u32 adpt_flags = 0; | ||
590 | |||
591 | if (SCpnt->sc_request && SCpnt->sc_request->upper_private_data) { | ||
592 | i2o_sg_io_hdr_t __user *usr_ptr = | ||
593 | ((Sg_request *) (SCpnt->sc_request-> | ||
594 | upper_private_data))->header. | ||
595 | usr_ptr; | ||
596 | |||
597 | if (usr_ptr) | ||
598 | get_user(adpt_flags, &usr_ptr->flags); | ||
599 | } | ||
600 | |||
601 | switch (i2o_dev->lct_data.class_id) { | ||
602 | case I2O_CLASS_EXECUTIVE: | ||
603 | case I2O_CLASS_RANDOM_BLOCK_STORAGE: | ||
604 | /* interpret flag has to be set for executive */ | ||
605 | adpt_flags ^= I2O_DPT_SG_FLAG_INTERPRET; | ||
606 | break; | ||
607 | |||
608 | default: | ||
609 | break; | ||
610 | } | ||
611 | |||
612 | /* | ||
613 | * for Adaptec controllers we use the PRIVATE command, because | ||
614 | * the normal SCSI EXEC doesn't support all SCSI commands on | ||
615 | * all controllers (for example READ CAPACITY). | ||
616 | */ | ||
617 | if (sgl_offset == SGL_OFFSET_10) | ||
618 | sgl_offset = SGL_OFFSET_12; | ||
619 | cmd = I2O_CMD_PRIVATE << 24; | ||
620 | writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++); | ||
621 | writel(adpt_flags | tid, mptr++); | ||
622 | } | ||
623 | #endif | ||
624 | |||
625 | writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]); | ||
612 | writel(i2o_scsi_driver.context, &msg->u.s.icntxt); | 626 | writel(i2o_scsi_driver.context, &msg->u.s.icntxt); |
613 | 627 | ||
614 | /* We want the SCSI control block back */ | 628 | /* We want the SCSI control block back */ |
@@ -626,7 +640,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
626 | */ | 640 | */ |
627 | 641 | ||
628 | /* Attach tags to the devices */ | 642 | /* Attach tags to the devices */ |
629 | /* | 643 | /* FIXME: implement |
630 | if(SCpnt->device->tagged_supported) { | 644 | if(SCpnt->device->tagged_supported) { |
631 | if(SCpnt->tag == HEAD_OF_QUEUE_TAG) | 645 | if(SCpnt->tag == HEAD_OF_QUEUE_TAG) |
632 | scsi_flags |= 0x01000000; | 646 | scsi_flags |= 0x01000000; |
@@ -635,67 +649,35 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
635 | } | 649 | } |
636 | */ | 650 | */ |
637 | 651 | ||
638 | /* Direction, disconnect ok, tag, CDBLen */ | 652 | writel(scsi_flags | SCpnt->cmd_len, mptr++); |
639 | writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, &msg->body[0]); | ||
640 | |||
641 | mptr = &msg->body[1]; | ||
642 | 653 | ||
643 | /* Write SCSI command into the message - always 16 byte block */ | 654 | /* Write SCSI command into the message - always 16 byte block */ |
644 | memcpy_toio(mptr, SCpnt->cmnd, 16); | 655 | memcpy_toio(mptr, SCpnt->cmnd, 16); |
645 | mptr += 4; | 656 | mptr += 4; |
646 | lenptr = mptr++; /* Remember me - fill in when we know */ | ||
647 | |||
648 | reqlen = 12; // SINGLE SGE | ||
649 | |||
650 | /* Now fill in the SGList and command */ | ||
651 | if (SCpnt->use_sg) { | ||
652 | struct scatterlist *sg; | ||
653 | int sg_count; | ||
654 | |||
655 | sg = SCpnt->request_buffer; | ||
656 | len = 0; | ||
657 | |||
658 | sg_count = dma_map_sg(dev, sg, SCpnt->use_sg, | ||
659 | SCpnt->sc_data_direction); | ||
660 | 657 | ||
661 | if (unlikely(sg_count <= 0)) | 658 | if (sgl_offset != SGL_OFFSET_0) { |
662 | return -ENOMEM; | 659 | /* write size of data addressed by SGL */ |
663 | 660 | writel(SCpnt->request_bufflen, mptr++); | |
664 | for (i = SCpnt->use_sg; i > 0; i--) { | 661 | |
665 | if (i == 1) | 662 | /* Now fill in the SGList and command */ |
666 | sg_flags |= 0xC0000000; | 663 | if (SCpnt->use_sg) { |
667 | writel(sg_flags | sg_dma_len(sg), mptr++); | 664 | if (!i2o_dma_map_sg(c, SCpnt->request_buffer, |
668 | writel(sg_dma_address(sg), mptr++); | 665 | SCpnt->use_sg, |
669 | len += sg_dma_len(sg); | 666 | SCpnt->sc_data_direction, &mptr)) |
670 | sg++; | 667 | goto nomem; |
668 | } else { | ||
669 | SCpnt->SCp.dma_handle = | ||
670 | i2o_dma_map_single(c, SCpnt->request_buffer, | ||
671 | SCpnt->request_bufflen, | ||
672 | SCpnt->sc_data_direction, &mptr); | ||
673 | if (dma_mapping_error(SCpnt->SCp.dma_handle)) | ||
674 | goto nomem; | ||
671 | } | 675 | } |
672 | |||
673 | reqlen = mptr - &msg->u.head[0]; | ||
674 | writel(len, lenptr); | ||
675 | } else { | ||
676 | len = SCpnt->request_bufflen; | ||
677 | |||
678 | writel(len, lenptr); | ||
679 | |||
680 | if (len > 0) { | ||
681 | dma_addr_t dma_addr; | ||
682 | |||
683 | dma_addr = dma_map_single(dev, SCpnt->request_buffer, | ||
684 | SCpnt->request_bufflen, | ||
685 | SCpnt->sc_data_direction); | ||
686 | if (!dma_addr) | ||
687 | return -ENOMEM; | ||
688 | |||
689 | SCpnt->SCp.ptr = (void *)(unsigned long)dma_addr; | ||
690 | sg_flags |= 0xC0000000; | ||
691 | writel(sg_flags | SCpnt->request_bufflen, mptr++); | ||
692 | writel(dma_addr, mptr++); | ||
693 | } else | ||
694 | reqlen = 9; | ||
695 | } | 676 | } |
696 | 677 | ||
697 | /* Stick the headers on */ | 678 | /* Stick the headers on */ |
698 | writel(reqlen << 16 | SGL_OFFSET_10, &msg->u.head[0]); | 679 | writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset, |
680 | &msg->u.head[0]); | ||
699 | 681 | ||
700 | /* Queue the message */ | 682 | /* Queue the message */ |
701 | i2o_msg_post(c, m); | 683 | i2o_msg_post(c, m); |
@@ -703,6 +685,13 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
703 | osm_debug("Issued %ld\n", SCpnt->serial_number); | 685 | osm_debug("Issued %ld\n", SCpnt->serial_number); |
704 | 686 | ||
705 | return 0; | 687 | return 0; |
688 | |||
689 | nomem: | ||
690 | rc = -ENOMEM; | ||
691 | i2o_msg_nop(c, m); | ||
692 | |||
693 | exit: | ||
694 | return rc; | ||
706 | }; | 695 | }; |
707 | 696 | ||
708 | /** | 697 | /** |
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 50c8cedf7a..42f8b810d6 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c | |||
@@ -28,8 +28,10 @@ | |||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/i2o.h> | 29 | #include <linux/i2o.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include "core.h" | ||
31 | 32 | ||
32 | #define OSM_VERSION "$Rev$" | 33 | #define OSM_NAME "i2o" |
34 | #define OSM_VERSION "1.288" | ||
33 | #define OSM_DESCRIPTION "I2O subsystem" | 35 | #define OSM_DESCRIPTION "I2O subsystem" |
34 | 36 | ||
35 | /* global I2O controller list */ | 37 | /* global I2O controller list */ |
@@ -43,20 +45,6 @@ static struct i2o_dma i2o_systab; | |||
43 | 45 | ||
44 | static int i2o_hrt_get(struct i2o_controller *c); | 46 | static int i2o_hrt_get(struct i2o_controller *c); |
45 | 47 | ||
46 | /* Module internal functions from other sources */ | ||
47 | extern struct i2o_driver i2o_exec_driver; | ||
48 | extern int i2o_exec_lct_get(struct i2o_controller *); | ||
49 | extern void i2o_device_remove(struct i2o_device *); | ||
50 | |||
51 | extern int __init i2o_driver_init(void); | ||
52 | extern void __exit i2o_driver_exit(void); | ||
53 | extern int __init i2o_exec_init(void); | ||
54 | extern void __exit i2o_exec_exit(void); | ||
55 | extern int __init i2o_pci_init(void); | ||
56 | extern void __exit i2o_pci_exit(void); | ||
57 | extern int i2o_device_init(void); | ||
58 | extern void i2o_device_exit(void); | ||
59 | |||
60 | /** | 48 | /** |
61 | * i2o_msg_nop - Returns a message which is not used | 49 | * i2o_msg_nop - Returns a message which is not used |
62 | * @c: I2O controller from which the message was created | 50 | * @c: I2O controller from which the message was created |
@@ -68,7 +56,7 @@ extern void i2o_device_exit(void); | |||
68 | */ | 56 | */ |
69 | void i2o_msg_nop(struct i2o_controller *c, u32 m) | 57 | void i2o_msg_nop(struct i2o_controller *c, u32 m) |
70 | { | 58 | { |
71 | struct i2o_message __iomem *msg = c->in_queue.virt + m; | 59 | struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m); |
72 | 60 | ||
73 | writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); | 61 | writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); |
74 | writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, | 62 | writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, |
@@ -92,16 +80,16 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m) | |||
92 | * address from the read port (see the i2o spec). If no message is | 80 | * address from the read port (see the i2o spec). If no message is |
93 | * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. | 81 | * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. |
94 | */ | 82 | */ |
95 | u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message __iomem **msg, | 83 | u32 i2o_msg_get_wait(struct i2o_controller *c, |
96 | int wait) | 84 | struct i2o_message __iomem ** msg, int wait) |
97 | { | 85 | { |
98 | unsigned long timeout = jiffies + wait * HZ; | 86 | unsigned long timeout = jiffies + wait * HZ; |
99 | u32 m; | 87 | u32 m; |
100 | 88 | ||
101 | while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) { | 89 | while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) { |
102 | if (time_after(jiffies, timeout)) { | 90 | if (time_after(jiffies, timeout)) { |
103 | pr_debug("%s: Timeout waiting for message frame.\n", | 91 | osm_debug("%s: Timeout waiting for message frame.\n", |
104 | c->name); | 92 | c->name); |
105 | return I2O_QUEUE_EMPTY; | 93 | return I2O_QUEUE_EMPTY; |
106 | } | 94 | } |
107 | set_current_state(TASK_UNINTERRUPTIBLE); | 95 | set_current_state(TASK_UNINTERRUPTIBLE); |
@@ -129,13 +117,13 @@ u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) | |||
129 | unsigned long flags; | 117 | unsigned long flags; |
130 | 118 | ||
131 | if (!ptr) | 119 | if (!ptr) |
132 | printk(KERN_ERR "%s: couldn't add NULL pointer to context list!" | 120 | osm_err("%s: couldn't add NULL pointer to context list!\n", |
133 | "\n", c->name); | 121 | c->name); |
134 | 122 | ||
135 | entry = kmalloc(sizeof(*entry), GFP_ATOMIC); | 123 | entry = kmalloc(sizeof(*entry), GFP_ATOMIC); |
136 | if (!entry) { | 124 | if (!entry) { |
137 | printk(KERN_ERR "%s: Could not allocate memory for context " | 125 | osm_err("%s: Could not allocate memory for context list element" |
138 | "list element\n", c->name); | 126 | "\n", c->name); |
139 | return 0; | 127 | return 0; |
140 | } | 128 | } |
141 | 129 | ||
@@ -154,7 +142,7 @@ u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) | |||
154 | 142 | ||
155 | spin_unlock_irqrestore(&c->context_list_lock, flags); | 143 | spin_unlock_irqrestore(&c->context_list_lock, flags); |
156 | 144 | ||
157 | pr_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context); | 145 | osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context); |
158 | 146 | ||
159 | return entry->context; | 147 | return entry->context; |
160 | }; | 148 | }; |
@@ -186,11 +174,11 @@ u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr) | |||
186 | spin_unlock_irqrestore(&c->context_list_lock, flags); | 174 | spin_unlock_irqrestore(&c->context_list_lock, flags); |
187 | 175 | ||
188 | if (!context) | 176 | if (!context) |
189 | printk(KERN_WARNING "%s: Could not remove nonexistent ptr " | 177 | osm_warn("%s: Could not remove nonexistent ptr %p\n", c->name, |
190 | "%p\n", c->name, ptr); | 178 | ptr); |
191 | 179 | ||
192 | pr_debug("%s: remove ptr from context list %d -> %p\n", c->name, | 180 | osm_debug("%s: remove ptr from context list %d -> %p\n", c->name, |
193 | context, ptr); | 181 | context, ptr); |
194 | 182 | ||
195 | return context; | 183 | return context; |
196 | }; | 184 | }; |
@@ -220,11 +208,10 @@ void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) | |||
220 | spin_unlock_irqrestore(&c->context_list_lock, flags); | 208 | spin_unlock_irqrestore(&c->context_list_lock, flags); |
221 | 209 | ||
222 | if (!ptr) | 210 | if (!ptr) |
223 | printk(KERN_WARNING "%s: context id %d not found\n", c->name, | 211 | osm_warn("%s: context id %d not found\n", c->name, context); |
224 | context); | ||
225 | 212 | ||
226 | pr_debug("%s: get ptr from context list %d -> %p\n", c->name, context, | 213 | osm_debug("%s: get ptr from context list %d -> %p\n", c->name, context, |
227 | ptr); | 214 | ptr); |
228 | 215 | ||
229 | return ptr; | 216 | return ptr; |
230 | }; | 217 | }; |
@@ -252,11 +239,11 @@ u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr) | |||
252 | spin_unlock_irqrestore(&c->context_list_lock, flags); | 239 | spin_unlock_irqrestore(&c->context_list_lock, flags); |
253 | 240 | ||
254 | if (!context) | 241 | if (!context) |
255 | printk(KERN_WARNING "%s: Could not find nonexistent ptr " | 242 | osm_warn("%s: Could not find nonexistent ptr %p\n", c->name, |
256 | "%p\n", c->name, ptr); | 243 | ptr); |
257 | 244 | ||
258 | pr_debug("%s: get context id from context list %p -> %d\n", c->name, | 245 | osm_debug("%s: get context id from context list %p -> %d\n", c->name, |
259 | ptr, context); | 246 | ptr, context); |
260 | 247 | ||
261 | return context; | 248 | return context; |
262 | }; | 249 | }; |
@@ -336,10 +323,9 @@ static int i2o_iop_quiesce(struct i2o_controller *c) | |||
336 | 323 | ||
337 | /* Long timeout needed for quiesce if lots of devices */ | 324 | /* Long timeout needed for quiesce if lots of devices */ |
338 | if ((rc = i2o_msg_post_wait(c, m, 240))) | 325 | if ((rc = i2o_msg_post_wait(c, m, 240))) |
339 | printk(KERN_INFO "%s: Unable to quiesce (status=%#x).\n", | 326 | osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc); |
340 | c->name, -rc); | ||
341 | else | 327 | else |
342 | pr_debug("%s: Quiesced.\n", c->name); | 328 | osm_debug("%s: Quiesced.\n", c->name); |
343 | 329 | ||
344 | i2o_status_get(c); // Entered READY state | 330 | i2o_status_get(c); // Entered READY state |
345 | 331 | ||
@@ -377,10 +363,9 @@ static int i2o_iop_enable(struct i2o_controller *c) | |||
377 | 363 | ||
378 | /* How long of a timeout do we need? */ | 364 | /* How long of a timeout do we need? */ |
379 | if ((rc = i2o_msg_post_wait(c, m, 240))) | 365 | if ((rc = i2o_msg_post_wait(c, m, 240))) |
380 | printk(KERN_ERR "%s: Could not enable (status=%#x).\n", | 366 | osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc); |
381 | c->name, -rc); | ||
382 | else | 367 | else |
383 | pr_debug("%s: Enabled.\n", c->name); | 368 | osm_debug("%s: Enabled.\n", c->name); |
384 | 369 | ||
385 | i2o_status_get(c); // entered OPERATIONAL state | 370 | i2o_status_get(c); // entered OPERATIONAL state |
386 | 371 | ||
@@ -444,20 +429,78 @@ static int i2o_iop_clear(struct i2o_controller *c) | |||
444 | &msg->u.head[1]); | 429 | &msg->u.head[1]); |
445 | 430 | ||
446 | if ((rc = i2o_msg_post_wait(c, m, 30))) | 431 | if ((rc = i2o_msg_post_wait(c, m, 30))) |
447 | printk(KERN_INFO "%s: Unable to clear (status=%#x).\n", | 432 | osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc); |
448 | c->name, -rc); | ||
449 | else | 433 | else |
450 | pr_debug("%s: Cleared.\n", c->name); | 434 | osm_debug("%s: Cleared.\n", c->name); |
451 | 435 | ||
452 | /* Enable all IOPs */ | 436 | /* Enable all IOPs */ |
453 | i2o_iop_enable_all(); | 437 | i2o_iop_enable_all(); |
454 | 438 | ||
455 | i2o_status_get(c); | ||
456 | |||
457 | return rc; | 439 | return rc; |
458 | } | 440 | } |
459 | 441 | ||
460 | /** | 442 | /** |
443 | * i2o_iop_init_outbound_queue - setup the outbound message queue | ||
444 | * @c: I2O controller | ||
445 | * | ||
446 | * Clear and (re)initialize IOP's outbound queue and post the message | ||
447 | * frames to the IOP. | ||
448 | * | ||
449 | * Returns 0 on success or a negative errno code on failure. | ||
450 | */ | ||
451 | static int i2o_iop_init_outbound_queue(struct i2o_controller *c) | ||
452 | { | ||
453 | volatile u8 *status = c->status.virt; | ||
454 | u32 m; | ||
455 | struct i2o_message __iomem *msg; | ||
456 | ulong timeout; | ||
457 | int i; | ||
458 | |||
459 | osm_debug("%s: Initializing Outbound Queue...\n", c->name); | ||
460 | |||
461 | memset(c->status.virt, 0, 4); | ||
462 | |||
463 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
464 | if (m == I2O_QUEUE_EMPTY) | ||
465 | return -ETIMEDOUT; | ||
466 | |||
467 | writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]); | ||
468 | writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID, | ||
469 | &msg->u.head[1]); | ||
470 | writel(i2o_exec_driver.context, &msg->u.s.icntxt); | ||
471 | writel(0x00000000, &msg->u.s.tcntxt); | ||
472 | writel(PAGE_SIZE, &msg->body[0]); | ||
473 | /* Outbound msg frame size in words and Initcode */ | ||
474 | writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); | ||
475 | writel(0xd0000004, &msg->body[2]); | ||
476 | writel(i2o_dma_low(c->status.phys), &msg->body[3]); | ||
477 | writel(i2o_dma_high(c->status.phys), &msg->body[4]); | ||
478 | |||
479 | i2o_msg_post(c, m); | ||
480 | |||
481 | timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ; | ||
482 | while (*status <= I2O_CMD_IN_PROGRESS) { | ||
483 | if (time_after(jiffies, timeout)) { | ||
484 | osm_warn("%s: Timeout Initializing\n", c->name); | ||
485 | return -ETIMEDOUT; | ||
486 | } | ||
487 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
488 | schedule_timeout(1); | ||
489 | } | ||
490 | |||
491 | m = c->out_queue.phys; | ||
492 | |||
493 | /* Post frames */ | ||
494 | for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) { | ||
495 | i2o_flush_reply(c, m); | ||
496 | udelay(1); /* Promise */ | ||
497 | m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32); | ||
498 | } | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | /** | ||
461 | * i2o_iop_reset - reset an I2O controller | 504 | * i2o_iop_reset - reset an I2O controller |
462 | * @c: controller to reset | 505 | * @c: controller to reset |
463 | * | 506 | * |
@@ -468,20 +511,20 @@ static int i2o_iop_clear(struct i2o_controller *c) | |||
468 | */ | 511 | */ |
469 | static int i2o_iop_reset(struct i2o_controller *c) | 512 | static int i2o_iop_reset(struct i2o_controller *c) |
470 | { | 513 | { |
471 | u8 *status = c->status.virt; | 514 | volatile u8 *status = c->status.virt; |
472 | struct i2o_message __iomem *msg; | 515 | struct i2o_message __iomem *msg; |
473 | u32 m; | 516 | u32 m; |
474 | unsigned long timeout; | 517 | unsigned long timeout; |
475 | i2o_status_block *sb = c->status_block.virt; | 518 | i2o_status_block *sb = c->status_block.virt; |
476 | int rc = 0; | 519 | int rc = 0; |
477 | 520 | ||
478 | pr_debug("%s: Resetting controller\n", c->name); | 521 | osm_debug("%s: Resetting controller\n", c->name); |
479 | 522 | ||
480 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | 523 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); |
481 | if (m == I2O_QUEUE_EMPTY) | 524 | if (m == I2O_QUEUE_EMPTY) |
482 | return -ETIMEDOUT; | 525 | return -ETIMEDOUT; |
483 | 526 | ||
484 | memset(status, 0, 8); | 527 | memset(c->status_block.virt, 0, 8); |
485 | 528 | ||
486 | /* Quiesce all IOPs first */ | 529 | /* Quiesce all IOPs first */ |
487 | i2o_iop_quiesce_all(); | 530 | i2o_iop_quiesce_all(); |
@@ -493,49 +536,43 @@ static int i2o_iop_reset(struct i2o_controller *c) | |||
493 | writel(0, &msg->u.s.tcntxt); //FIXME: use reasonable transaction context | 536 | writel(0, &msg->u.s.tcntxt); //FIXME: use reasonable transaction context |
494 | writel(0, &msg->body[0]); | 537 | writel(0, &msg->body[0]); |
495 | writel(0, &msg->body[1]); | 538 | writel(0, &msg->body[1]); |
496 | writel(i2o_ptr_low((void *)c->status.phys), &msg->body[2]); | 539 | writel(i2o_dma_low(c->status.phys), &msg->body[2]); |
497 | writel(i2o_ptr_high((void *)c->status.phys), &msg->body[3]); | 540 | writel(i2o_dma_high(c->status.phys), &msg->body[3]); |
498 | 541 | ||
499 | i2o_msg_post(c, m); | 542 | i2o_msg_post(c, m); |
500 | 543 | ||
501 | /* Wait for a reply */ | 544 | /* Wait for a reply */ |
502 | timeout = jiffies + I2O_TIMEOUT_RESET * HZ; | 545 | timeout = jiffies + I2O_TIMEOUT_RESET * HZ; |
503 | while (!*status) { | 546 | while (!*status) { |
504 | if (time_after(jiffies, timeout)) { | 547 | if (time_after(jiffies, timeout)) |
505 | printk(KERN_ERR "%s: IOP reset timeout.\n", c->name); | ||
506 | rc = -ETIMEDOUT; | ||
507 | goto exit; | ||
508 | } | ||
509 | |||
510 | /* Promise bug */ | ||
511 | if (status[1] || status[4]) { | ||
512 | *status = 0; | ||
513 | break; | 548 | break; |
514 | } | ||
515 | 549 | ||
516 | set_current_state(TASK_UNINTERRUPTIBLE); | 550 | set_current_state(TASK_UNINTERRUPTIBLE); |
517 | schedule_timeout(1); | 551 | schedule_timeout(1); |
518 | |||
519 | rmb(); | ||
520 | } | 552 | } |
521 | 553 | ||
522 | if (*status == I2O_CMD_IN_PROGRESS) { | 554 | switch (*status) { |
555 | case I2O_CMD_REJECTED: | ||
556 | osm_warn("%s: IOP reset rejected\n", c->name); | ||
557 | rc = -EPERM; | ||
558 | break; | ||
559 | |||
560 | case I2O_CMD_IN_PROGRESS: | ||
523 | /* | 561 | /* |
524 | * Once the reset is sent, the IOP goes into the INIT state | 562 | * Once the reset is sent, the IOP goes into the INIT state |
525 | * which is indeterminate. We need to wait until the IOP | 563 | * which is indeterminate. We need to wait until the IOP has |
526 | * has rebooted before we can let the system talk to | 564 | * rebooted before we can let the system talk to it. We read |
527 | * it. We read the inbound Free_List until a message is | 565 | * the inbound Free_List until a message is available. If we |
528 | * available. If we can't read one in the given ammount of | 566 | * can't read one in the given ammount of time, we assume the |
529 | * time, we assume the IOP could not reboot properly. | 567 | * IOP could not reboot properly. |
530 | */ | 568 | */ |
531 | pr_debug("%s: Reset in progress, waiting for reboot...\n", | 569 | osm_debug("%s: Reset in progress, waiting for reboot...\n", |
532 | c->name); | 570 | c->name); |
533 | 571 | ||
534 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); | 572 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); |
535 | while (m == I2O_QUEUE_EMPTY) { | 573 | while (m == I2O_QUEUE_EMPTY) { |
536 | if (time_after(jiffies, timeout)) { | 574 | if (time_after(jiffies, timeout)) { |
537 | printk(KERN_ERR "%s: IOP reset timeout.\n", | 575 | osm_err("%s: IOP reset timeout.\n", c->name); |
538 | c->name); | ||
539 | rc = -ETIMEDOUT; | 576 | rc = -ETIMEDOUT; |
540 | goto exit; | 577 | goto exit; |
541 | } | 578 | } |
@@ -545,19 +582,26 @@ static int i2o_iop_reset(struct i2o_controller *c) | |||
545 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); | 582 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); |
546 | } | 583 | } |
547 | i2o_msg_nop(c, m); | 584 | i2o_msg_nop(c, m); |
548 | } | ||
549 | 585 | ||
550 | /* from here all quiesce commands are safe */ | 586 | /* from here all quiesce commands are safe */ |
551 | c->no_quiesce = 0; | 587 | c->no_quiesce = 0; |
552 | 588 | ||
553 | /* If IopReset was rejected or didn't perform reset, try IopClear */ | 589 | /* verify if controller is in state RESET */ |
554 | i2o_status_get(c); | 590 | i2o_status_get(c); |
555 | if (*status == I2O_CMD_REJECTED || sb->iop_state != ADAPTER_STATE_RESET) { | 591 | |
556 | printk(KERN_WARNING "%s: Reset rejected, trying to clear\n", | 592 | if (!c->promise && (sb->iop_state != ADAPTER_STATE_RESET)) |
557 | c->name); | 593 | osm_warn("%s: reset completed, but adapter not in RESET" |
558 | i2o_iop_clear(c); | 594 | " state.\n", c->name); |
559 | } else | 595 | else |
560 | pr_debug("%s: Reset completed.\n", c->name); | 596 | osm_debug("%s: reset completed.\n", c->name); |
597 | |||
598 | break; | ||
599 | |||
600 | default: | ||
601 | osm_err("%s: IOP reset timeout.\n", c->name); | ||
602 | rc = -ETIMEDOUT; | ||
603 | break; | ||
604 | } | ||
561 | 605 | ||
562 | exit: | 606 | exit: |
563 | /* Enable all IOPs */ | 607 | /* Enable all IOPs */ |
@@ -567,88 +611,6 @@ static int i2o_iop_reset(struct i2o_controller *c) | |||
567 | }; | 611 | }; |
568 | 612 | ||
569 | /** | 613 | /** |
570 | * i2o_iop_init_outbound_queue - setup the outbound message queue | ||
571 | * @c: I2O controller | ||
572 | * | ||
573 | * Clear and (re)initialize IOP's outbound queue and post the message | ||
574 | * frames to the IOP. | ||
575 | * | ||
576 | * Returns 0 on success or a negative errno code on failure. | ||
577 | */ | ||
578 | static int i2o_iop_init_outbound_queue(struct i2o_controller *c) | ||
579 | { | ||
580 | u8 *status = c->status.virt; | ||
581 | u32 m; | ||
582 | struct i2o_message __iomem *msg; | ||
583 | ulong timeout; | ||
584 | int i; | ||
585 | |||
586 | pr_debug("%s: Initializing Outbound Queue...\n", c->name); | ||
587 | |||
588 | memset(status, 0, 4); | ||
589 | |||
590 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
591 | if (m == I2O_QUEUE_EMPTY) | ||
592 | return -ETIMEDOUT; | ||
593 | |||
594 | writel(EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6, &msg->u.head[0]); | ||
595 | writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID, | ||
596 | &msg->u.head[1]); | ||
597 | writel(i2o_exec_driver.context, &msg->u.s.icntxt); | ||
598 | writel(0x0106, &msg->u.s.tcntxt); /* FIXME: why 0x0106, maybe in | ||
599 | Spec? */ | ||
600 | writel(PAGE_SIZE, &msg->body[0]); | ||
601 | writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); /* Outbound msg frame | ||
602 | size in words and Initcode */ | ||
603 | writel(0xd0000004, &msg->body[2]); | ||
604 | writel(i2o_ptr_low((void *)c->status.phys), &msg->body[3]); | ||
605 | writel(i2o_ptr_high((void *)c->status.phys), &msg->body[4]); | ||
606 | |||
607 | i2o_msg_post(c, m); | ||
608 | |||
609 | timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ; | ||
610 | while (*status <= I2O_CMD_IN_PROGRESS) { | ||
611 | if (time_after(jiffies, timeout)) { | ||
612 | printk(KERN_WARNING "%s: Timeout Initializing\n", | ||
613 | c->name); | ||
614 | return -ETIMEDOUT; | ||
615 | } | ||
616 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
617 | schedule_timeout(1); | ||
618 | |||
619 | rmb(); | ||
620 | } | ||
621 | |||
622 | m = c->out_queue.phys; | ||
623 | |||
624 | /* Post frames */ | ||
625 | for (i = 0; i < NMBR_MSG_FRAMES; i++) { | ||
626 | i2o_flush_reply(c, m); | ||
627 | udelay(1); /* Promise */ | ||
628 | m += MSG_FRAME_SIZE * 4; | ||
629 | } | ||
630 | |||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | /** | ||
635 | * i2o_iop_send_nop - send a core NOP message | ||
636 | * @c: controller | ||
637 | * | ||
638 | * Send a no-operation message with a reply set to cause no | ||
639 | * action either. Needed for bringing up promise controllers. | ||
640 | */ | ||
641 | static int i2o_iop_send_nop(struct i2o_controller *c) | ||
642 | { | ||
643 | struct i2o_message __iomem *msg; | ||
644 | u32 m = i2o_msg_get_wait(c, &msg, HZ); | ||
645 | if (m == I2O_QUEUE_EMPTY) | ||
646 | return -ETIMEDOUT; | ||
647 | i2o_msg_nop(c, m); | ||
648 | return 0; | ||
649 | } | ||
650 | |||
651 | /** | ||
652 | * i2o_iop_activate - Bring controller up to HOLD | 614 | * i2o_iop_activate - Bring controller up to HOLD |
653 | * @c: controller | 615 | * @c: controller |
654 | * | 616 | * |
@@ -659,78 +621,62 @@ static int i2o_iop_send_nop(struct i2o_controller *c) | |||
659 | */ | 621 | */ |
660 | static int i2o_iop_activate(struct i2o_controller *c) | 622 | static int i2o_iop_activate(struct i2o_controller *c) |
661 | { | 623 | { |
662 | struct pci_dev *i960 = NULL; | ||
663 | i2o_status_block *sb = c->status_block.virt; | 624 | i2o_status_block *sb = c->status_block.virt; |
664 | int rc; | 625 | int rc; |
665 | 626 | int state; | |
666 | if (c->promise) { | ||
667 | /* Beat up the hardware first of all */ | ||
668 | i960 = | ||
669 | pci_find_slot(c->pdev->bus->number, | ||
670 | PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0)); | ||
671 | if (i960) | ||
672 | pci_write_config_word(i960, 0x42, 0); | ||
673 | |||
674 | /* Follow this sequence precisely or the controller | ||
675 | ceases to perform useful functions until reboot */ | ||
676 | if ((rc = i2o_iop_send_nop(c))) | ||
677 | return rc; | ||
678 | |||
679 | if ((rc = i2o_iop_reset(c))) | ||
680 | return rc; | ||
681 | } | ||
682 | 627 | ||
683 | /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */ | 628 | /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */ |
684 | /* In READY state, Get status */ | 629 | /* In READY state, Get status */ |
685 | 630 | ||
686 | rc = i2o_status_get(c); | 631 | rc = i2o_status_get(c); |
687 | if (rc) { | 632 | if (rc) { |
688 | printk(KERN_INFO "%s: Unable to obtain status, " | 633 | osm_info("%s: Unable to obtain status, attempting a reset.\n", |
689 | "attempting a reset.\n", c->name); | 634 | c->name); |
690 | if (i2o_iop_reset(c)) | 635 | rc = i2o_iop_reset(c); |
636 | if (rc) | ||
691 | return rc; | 637 | return rc; |
692 | } | 638 | } |
693 | 639 | ||
694 | if (sb->i2o_version > I2OVER15) { | 640 | if (sb->i2o_version > I2OVER15) { |
695 | printk(KERN_ERR "%s: Not running version 1.5 of the I2O " | 641 | osm_err("%s: Not running version 1.5 of the I2O Specification." |
696 | "Specification.\n", c->name); | 642 | "\n", c->name); |
697 | return -ENODEV; | 643 | return -ENODEV; |
698 | } | 644 | } |
699 | 645 | ||
700 | switch (sb->iop_state) { | 646 | switch (sb->iop_state) { |
701 | case ADAPTER_STATE_FAULTED: | 647 | case ADAPTER_STATE_FAULTED: |
702 | printk(KERN_CRIT "%s: hardware fault\n", c->name); | 648 | osm_err("%s: hardware fault\n", c->name); |
703 | return -ENODEV; | 649 | return -EFAULT; |
704 | 650 | ||
705 | case ADAPTER_STATE_READY: | 651 | case ADAPTER_STATE_READY: |
706 | case ADAPTER_STATE_OPERATIONAL: | 652 | case ADAPTER_STATE_OPERATIONAL: |
707 | case ADAPTER_STATE_HOLD: | 653 | case ADAPTER_STATE_HOLD: |
708 | case ADAPTER_STATE_FAILED: | 654 | case ADAPTER_STATE_FAILED: |
709 | pr_debug("%s: already running, trying to reset...\n", c->name); | 655 | osm_debug("%s: already running, trying to reset...\n", c->name); |
710 | if (i2o_iop_reset(c)) | 656 | rc = i2o_iop_reset(c); |
711 | return -ENODEV; | 657 | if (rc) |
658 | return rc; | ||
712 | } | 659 | } |
713 | 660 | ||
661 | /* preserve state */ | ||
662 | state = sb->iop_state; | ||
663 | |||
714 | rc = i2o_iop_init_outbound_queue(c); | 664 | rc = i2o_iop_init_outbound_queue(c); |
715 | if (rc) | 665 | if (rc) |
716 | return rc; | 666 | return rc; |
717 | 667 | ||
718 | if (c->promise) { | 668 | /* if adapter was not in RESET state clear now */ |
719 | if ((rc = i2o_iop_send_nop(c))) | 669 | if (state != ADAPTER_STATE_RESET) |
720 | return rc; | 670 | i2o_iop_clear(c); |
721 | 671 | ||
722 | if ((rc = i2o_status_get(c))) | 672 | i2o_status_get(c); |
723 | return rc; | ||
724 | 673 | ||
725 | if (i960) | 674 | if (sb->iop_state != ADAPTER_STATE_HOLD) { |
726 | pci_write_config_word(i960, 0x42, 0x3FF); | 675 | osm_err("%s: failed to bring IOP into HOLD state\n", c->name); |
676 | return -EIO; | ||
727 | } | 677 | } |
728 | 678 | ||
729 | /* In HOLD state */ | 679 | return i2o_hrt_get(c); |
730 | |||
731 | rc = i2o_hrt_get(c); | ||
732 | |||
733 | return rc; | ||
734 | }; | 680 | }; |
735 | 681 | ||
736 | /** | 682 | /** |
@@ -756,20 +702,18 @@ static int i2o_iop_systab_set(struct i2o_controller *c) | |||
756 | res->flags = IORESOURCE_MEM; | 702 | res->flags = IORESOURCE_MEM; |
757 | res->start = 0; | 703 | res->start = 0; |
758 | res->end = 0; | 704 | res->end = 0; |
759 | printk(KERN_INFO "%s: requires private memory resources.\n", | 705 | osm_info("%s: requires private memory resources.\n", c->name); |
760 | c->name); | ||
761 | root = pci_find_parent_resource(c->pdev, res); | 706 | root = pci_find_parent_resource(c->pdev, res); |
762 | if (root == NULL) | 707 | if (root == NULL) |
763 | printk(KERN_WARNING "%s: Can't find parent resource!\n", | 708 | osm_warn("%s: Can't find parent resource!\n", c->name); |
764 | c->name); | ||
765 | if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ | 709 | if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ |
766 | NULL, NULL) >= 0) { | 710 | NULL, NULL) >= 0) { |
767 | c->mem_alloc = 1; | 711 | c->mem_alloc = 1; |
768 | sb->current_mem_size = 1 + res->end - res->start; | 712 | sb->current_mem_size = 1 + res->end - res->start; |
769 | sb->current_mem_base = res->start; | 713 | sb->current_mem_base = res->start; |
770 | printk(KERN_INFO "%s: allocated %ld bytes of PCI memory" | 714 | osm_info("%s: allocated %ld bytes of PCI memory at " |
771 | " at 0x%08lX.\n", c->name, | 715 | "0x%08lX.\n", c->name, |
772 | 1 + res->end - res->start, res->start); | 716 | 1 + res->end - res->start, res->start); |
773 | } | 717 | } |
774 | } | 718 | } |
775 | 719 | ||
@@ -779,20 +723,18 @@ static int i2o_iop_systab_set(struct i2o_controller *c) | |||
779 | res->flags = IORESOURCE_IO; | 723 | res->flags = IORESOURCE_IO; |
780 | res->start = 0; | 724 | res->start = 0; |
781 | res->end = 0; | 725 | res->end = 0; |
782 | printk(KERN_INFO "%s: requires private memory resources.\n", | 726 | osm_info("%s: requires private memory resources.\n", c->name); |
783 | c->name); | ||
784 | root = pci_find_parent_resource(c->pdev, res); | 727 | root = pci_find_parent_resource(c->pdev, res); |
785 | if (root == NULL) | 728 | if (root == NULL) |
786 | printk(KERN_WARNING "%s: Can't find parent resource!\n", | 729 | osm_warn("%s: Can't find parent resource!\n", c->name); |
787 | c->name); | ||
788 | if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ | 730 | if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ |
789 | NULL, NULL) >= 0) { | 731 | NULL, NULL) >= 0) { |
790 | c->io_alloc = 1; | 732 | c->io_alloc = 1; |
791 | sb->current_io_size = 1 + res->end - res->start; | 733 | sb->current_io_size = 1 + res->end - res->start; |
792 | sb->current_mem_base = res->start; | 734 | sb->current_mem_base = res->start; |
793 | printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at" | 735 | osm_info("%s: allocated %ld bytes of PCI I/O at 0x%08lX" |
794 | " 0x%08lX.\n", c->name, | 736 | ".\n", c->name, 1 + res->end - res->start, |
795 | 1 + res->end - res->start, res->start); | 737 | res->start); |
796 | } | 738 | } |
797 | } | 739 | } |
798 | 740 | ||
@@ -836,10 +778,10 @@ static int i2o_iop_systab_set(struct i2o_controller *c) | |||
836 | PCI_DMA_TODEVICE); | 778 | PCI_DMA_TODEVICE); |
837 | 779 | ||
838 | if (rc < 0) | 780 | if (rc < 0) |
839 | printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n", | 781 | osm_err("%s: Unable to set SysTab (status=%#x).\n", c->name, |
840 | c->name, -rc); | 782 | -rc); |
841 | else | 783 | else |
842 | pr_debug("%s: SysTab set.\n", c->name); | 784 | osm_debug("%s: SysTab set.\n", c->name); |
843 | 785 | ||
844 | i2o_status_get(c); // Entered READY state | 786 | i2o_status_get(c); // Entered READY state |
845 | 787 | ||
@@ -863,7 +805,7 @@ static int i2o_iop_online(struct i2o_controller *c) | |||
863 | return rc; | 805 | return rc; |
864 | 806 | ||
865 | /* In READY state */ | 807 | /* In READY state */ |
866 | pr_debug("%s: Attempting to enable...\n", c->name); | 808 | osm_debug("%s: Attempting to enable...\n", c->name); |
867 | rc = i2o_iop_enable(c); | 809 | rc = i2o_iop_enable(c); |
868 | if (rc) | 810 | if (rc) |
869 | return rc; | 811 | return rc; |
@@ -882,7 +824,7 @@ void i2o_iop_remove(struct i2o_controller *c) | |||
882 | { | 824 | { |
883 | struct i2o_device *dev, *tmp; | 825 | struct i2o_device *dev, *tmp; |
884 | 826 | ||
885 | pr_debug("%s: deleting controller\n", c->name); | 827 | osm_debug("%s: deleting controller\n", c->name); |
886 | 828 | ||
887 | i2o_driver_notify_controller_remove_all(c); | 829 | i2o_driver_notify_controller_remove_all(c); |
888 | 830 | ||
@@ -891,8 +833,12 @@ void i2o_iop_remove(struct i2o_controller *c) | |||
891 | list_for_each_entry_safe(dev, tmp, &c->devices, list) | 833 | list_for_each_entry_safe(dev, tmp, &c->devices, list) |
892 | i2o_device_remove(dev); | 834 | i2o_device_remove(dev); |
893 | 835 | ||
836 | device_del(&c->device); | ||
837 | |||
894 | /* Ask the IOP to switch to RESET state */ | 838 | /* Ask the IOP to switch to RESET state */ |
895 | i2o_iop_reset(c); | 839 | i2o_iop_reset(c); |
840 | |||
841 | put_device(&c->device); | ||
896 | } | 842 | } |
897 | 843 | ||
898 | /** | 844 | /** |
@@ -927,8 +873,7 @@ static int i2o_systab_build(void) | |||
927 | 873 | ||
928 | systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL); | 874 | systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL); |
929 | if (!systab) { | 875 | if (!systab) { |
930 | printk(KERN_ERR "i2o: unable to allocate memory for System " | 876 | osm_err("unable to allocate memory for System Table\n"); |
931 | "Table\n"); | ||
932 | return -ENOMEM; | 877 | return -ENOMEM; |
933 | } | 878 | } |
934 | memset(systab, 0, i2o_systab.len); | 879 | memset(systab, 0, i2o_systab.len); |
@@ -940,8 +885,8 @@ static int i2o_systab_build(void) | |||
940 | i2o_status_block *sb; | 885 | i2o_status_block *sb; |
941 | 886 | ||
942 | if (count >= num_controllers) { | 887 | if (count >= num_controllers) { |
943 | printk(KERN_ERR "i2o: controller added while building " | 888 | osm_err("controller added while building system table" |
944 | "system table\n"); | 889 | "\n"); |
945 | break; | 890 | break; |
946 | } | 891 | } |
947 | 892 | ||
@@ -955,9 +900,8 @@ static int i2o_systab_build(void) | |||
955 | * it is techninically not part of the I2O subsystem... | 900 | * it is techninically not part of the I2O subsystem... |
956 | */ | 901 | */ |
957 | if (unlikely(i2o_status_get(c))) { | 902 | if (unlikely(i2o_status_get(c))) { |
958 | printk(KERN_ERR "%s: Deleting b/c could not get status" | 903 | osm_err("%s: Deleting b/c could not get status while " |
959 | " while attempting to build system table\n", | 904 | "attempting to build system table\n", c->name); |
960 | c->name); | ||
961 | i2o_iop_remove(c); | 905 | i2o_iop_remove(c); |
962 | continue; // try the next one | 906 | continue; // try the next one |
963 | } | 907 | } |
@@ -971,8 +915,10 @@ static int i2o_systab_build(void) | |||
971 | systab->iops[count].frame_size = sb->inbound_frame_size; | 915 | systab->iops[count].frame_size = sb->inbound_frame_size; |
972 | systab->iops[count].last_changed = change_ind; | 916 | systab->iops[count].last_changed = change_ind; |
973 | systab->iops[count].iop_capabilities = sb->iop_capabilities; | 917 | systab->iops[count].iop_capabilities = sb->iop_capabilities; |
974 | systab->iops[count].inbound_low = i2o_ptr_low(c->post_port); | 918 | systab->iops[count].inbound_low = |
975 | systab->iops[count].inbound_high = i2o_ptr_high(c->post_port); | 919 | i2o_dma_low(c->base.phys + I2O_IN_PORT); |
920 | systab->iops[count].inbound_high = | ||
921 | i2o_dma_high(c->base.phys + I2O_IN_PORT); | ||
976 | 922 | ||
977 | count++; | 923 | count++; |
978 | } | 924 | } |
@@ -1010,11 +956,11 @@ int i2o_status_get(struct i2o_controller *c) | |||
1010 | { | 956 | { |
1011 | struct i2o_message __iomem *msg; | 957 | struct i2o_message __iomem *msg; |
1012 | u32 m; | 958 | u32 m; |
1013 | u8 *status_block; | 959 | volatile u8 *status_block; |
1014 | unsigned long timeout; | 960 | unsigned long timeout; |
1015 | 961 | ||
1016 | status_block = (u8 *) c->status_block.virt; | 962 | status_block = (u8 *) c->status_block.virt; |
1017 | memset(status_block, 0, sizeof(i2o_status_block)); | 963 | memset(c->status_block.virt, 0, sizeof(i2o_status_block)); |
1018 | 964 | ||
1019 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | 965 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); |
1020 | if (m == I2O_QUEUE_EMPTY) | 966 | if (m == I2O_QUEUE_EMPTY) |
@@ -1027,8 +973,8 @@ int i2o_status_get(struct i2o_controller *c) | |||
1027 | writel(0, &msg->u.s.tcntxt); // FIXME: use resonable transaction context | 973 | writel(0, &msg->u.s.tcntxt); // FIXME: use resonable transaction context |
1028 | writel(0, &msg->body[0]); | 974 | writel(0, &msg->body[0]); |
1029 | writel(0, &msg->body[1]); | 975 | writel(0, &msg->body[1]); |
1030 | writel(i2o_ptr_low((void *)c->status_block.phys), &msg->body[2]); | 976 | writel(i2o_dma_low(c->status_block.phys), &msg->body[2]); |
1031 | writel(i2o_ptr_high((void *)c->status_block.phys), &msg->body[3]); | 977 | writel(i2o_dma_high(c->status_block.phys), &msg->body[3]); |
1032 | writel(sizeof(i2o_status_block), &msg->body[4]); /* always 88 bytes */ | 978 | writel(sizeof(i2o_status_block), &msg->body[4]); /* always 88 bytes */ |
1033 | 979 | ||
1034 | i2o_msg_post(c, m); | 980 | i2o_msg_post(c, m); |
@@ -1037,14 +983,12 @@ int i2o_status_get(struct i2o_controller *c) | |||
1037 | timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ; | 983 | timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ; |
1038 | while (status_block[87] != 0xFF) { | 984 | while (status_block[87] != 0xFF) { |
1039 | if (time_after(jiffies, timeout)) { | 985 | if (time_after(jiffies, timeout)) { |
1040 | printk(KERN_ERR "%s: Get status timeout.\n", c->name); | 986 | osm_err("%s: Get status timeout.\n", c->name); |
1041 | return -ETIMEDOUT; | 987 | return -ETIMEDOUT; |
1042 | } | 988 | } |
1043 | 989 | ||
1044 | set_current_state(TASK_UNINTERRUPTIBLE); | 990 | set_current_state(TASK_UNINTERRUPTIBLE); |
1045 | schedule_timeout(1); | 991 | schedule_timeout(1); |
1046 | |||
1047 | rmb(); | ||
1048 | } | 992 | } |
1049 | 993 | ||
1050 | #ifdef DEBUG | 994 | #ifdef DEBUG |
@@ -1088,8 +1032,8 @@ static int i2o_hrt_get(struct i2o_controller *c) | |||
1088 | rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt); | 1032 | rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt); |
1089 | 1033 | ||
1090 | if (rc < 0) { | 1034 | if (rc < 0) { |
1091 | printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n", | 1035 | osm_err("%s: Unable to get HRT (status=%#x)\n", c->name, |
1092 | c->name, -rc); | 1036 | -rc); |
1093 | return rc; | 1037 | return rc; |
1094 | } | 1038 | } |
1095 | 1039 | ||
@@ -1103,13 +1047,41 @@ static int i2o_hrt_get(struct i2o_controller *c) | |||
1103 | return i2o_parse_hrt(c); | 1047 | return i2o_parse_hrt(c); |
1104 | } | 1048 | } |
1105 | 1049 | ||
1106 | printk(KERN_ERR "%s: Unable to get HRT after %d tries, giving up\n", | 1050 | osm_err("%s: Unable to get HRT after %d tries, giving up\n", c->name, |
1107 | c->name, I2O_HRT_GET_TRIES); | 1051 | I2O_HRT_GET_TRIES); |
1108 | 1052 | ||
1109 | return -EBUSY; | 1053 | return -EBUSY; |
1110 | } | 1054 | } |
1111 | 1055 | ||
1112 | /** | 1056 | /** |
1057 | * i2o_iop_free - Free the i2o_controller struct | ||
1058 | * @c: I2O controller to free | ||
1059 | */ | ||
1060 | void i2o_iop_free(struct i2o_controller *c) | ||
1061 | { | ||
1062 | kfree(c); | ||
1063 | }; | ||
1064 | |||
1065 | /** | ||
1066 | * i2o_iop_release - release the memory for a I2O controller | ||
1067 | * @dev: I2O controller which should be released | ||
1068 | * | ||
1069 | * Release the allocated memory. This function is called if refcount of | ||
1070 | * device reaches 0 automatically. | ||
1071 | */ | ||
1072 | static void i2o_iop_release(struct device *dev) | ||
1073 | { | ||
1074 | struct i2o_controller *c = to_i2o_controller(dev); | ||
1075 | |||
1076 | i2o_iop_free(c); | ||
1077 | }; | ||
1078 | |||
1079 | /* I2O controller class */ | ||
1080 | static struct class i2o_controller_class = { | ||
1081 | .name = "i2o_controller", | ||
1082 | }; | ||
1083 | |||
1084 | /** | ||
1113 | * i2o_iop_alloc - Allocate and initialize a i2o_controller struct | 1085 | * i2o_iop_alloc - Allocate and initialize a i2o_controller struct |
1114 | * | 1086 | * |
1115 | * Allocate the necessary memory for a i2o_controller struct and | 1087 | * Allocate the necessary memory for a i2o_controller struct and |
@@ -1125,8 +1097,8 @@ struct i2o_controller *i2o_iop_alloc(void) | |||
1125 | 1097 | ||
1126 | c = kmalloc(sizeof(*c), GFP_KERNEL); | 1098 | c = kmalloc(sizeof(*c), GFP_KERNEL); |
1127 | if (!c) { | 1099 | if (!c) { |
1128 | printk(KERN_ERR "i2o: Insufficient memory to allocate a I2O " | 1100 | osm_err("i2o: Insufficient memory to allocate a I2O controller." |
1129 | "controller.\n"); | 1101 | "\n"); |
1130 | return ERR_PTR(-ENOMEM); | 1102 | return ERR_PTR(-ENOMEM); |
1131 | } | 1103 | } |
1132 | memset(c, 0, sizeof(*c)); | 1104 | memset(c, 0, sizeof(*c)); |
@@ -1137,6 +1109,16 @@ struct i2o_controller *i2o_iop_alloc(void) | |||
1137 | c->unit = unit++; | 1109 | c->unit = unit++; |
1138 | sprintf(c->name, "iop%d", c->unit); | 1110 | sprintf(c->name, "iop%d", c->unit); |
1139 | 1111 | ||
1112 | device_initialize(&c->device); | ||
1113 | class_device_initialize(&c->classdev); | ||
1114 | |||
1115 | c->device.release = &i2o_iop_release; | ||
1116 | c->classdev.class = &i2o_controller_class; | ||
1117 | c->classdev.dev = &c->device; | ||
1118 | |||
1119 | snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit); | ||
1120 | snprintf(c->classdev.class_id, BUS_ID_SIZE, "iop%d", c->unit); | ||
1121 | |||
1140 | #if BITS_PER_LONG == 64 | 1122 | #if BITS_PER_LONG == 64 |
1141 | spin_lock_init(&c->context_list_lock); | 1123 | spin_lock_init(&c->context_list_lock); |
1142 | atomic_set(&c->context_list_counter, 0); | 1124 | atomic_set(&c->context_list_counter, 0); |
@@ -1147,15 +1129,6 @@ struct i2o_controller *i2o_iop_alloc(void) | |||
1147 | }; | 1129 | }; |
1148 | 1130 | ||
1149 | /** | 1131 | /** |
1150 | * i2o_iop_free - Free the i2o_controller struct | ||
1151 | * @c: I2O controller to free | ||
1152 | */ | ||
1153 | void i2o_iop_free(struct i2o_controller *c) | ||
1154 | { | ||
1155 | kfree(c); | ||
1156 | }; | ||
1157 | |||
1158 | /** | ||
1159 | * i2o_iop_add - Initialize the I2O controller and add him to the I2O core | 1132 | * i2o_iop_add - Initialize the I2O controller and add him to the I2O core |
1160 | * @c: controller | 1133 | * @c: controller |
1161 | * | 1134 | * |
@@ -1168,45 +1141,58 @@ int i2o_iop_add(struct i2o_controller *c) | |||
1168 | { | 1141 | { |
1169 | int rc; | 1142 | int rc; |
1170 | 1143 | ||
1171 | printk(KERN_INFO "%s: Activating I2O controller...\n", c->name); | 1144 | if ((rc = device_add(&c->device))) { |
1172 | printk(KERN_INFO "%s: This may take a few minutes if there are many " | 1145 | osm_err("%s: could not add controller\n", c->name); |
1173 | "devices\n", c->name); | 1146 | goto iop_reset; |
1147 | } | ||
1174 | 1148 | ||
1175 | if ((rc = i2o_iop_activate(c))) { | 1149 | if ((rc = class_device_add(&c->classdev))) { |
1176 | printk(KERN_ERR "%s: could not activate controller\n", | 1150 | osm_err("%s: could not add controller class\n", c->name); |
1177 | c->name); | 1151 | goto device_del; |
1178 | i2o_iop_reset(c); | ||
1179 | return rc; | ||
1180 | } | 1152 | } |
1181 | 1153 | ||
1182 | pr_debug("%s: building sys table...\n", c->name); | 1154 | osm_info("%s: Activating I2O controller...\n", c->name); |
1155 | osm_info("%s: This may take a few minutes if there are many devices\n", | ||
1156 | c->name); | ||
1183 | 1157 | ||
1184 | if ((rc = i2o_systab_build())) { | 1158 | if ((rc = i2o_iop_activate(c))) { |
1185 | i2o_iop_reset(c); | 1159 | osm_err("%s: could not activate controller\n", c->name); |
1186 | return rc; | 1160 | goto class_del; |
1187 | } | 1161 | } |
1188 | 1162 | ||
1189 | pr_debug("%s: online controller...\n", c->name); | 1163 | osm_debug("%s: building sys table...\n", c->name); |
1190 | 1164 | ||
1191 | if ((rc = i2o_iop_online(c))) { | 1165 | if ((rc = i2o_systab_build())) |
1192 | i2o_iop_reset(c); | 1166 | goto class_del; |
1193 | return rc; | ||
1194 | } | ||
1195 | 1167 | ||
1196 | pr_debug("%s: getting LCT...\n", c->name); | 1168 | osm_debug("%s: online controller...\n", c->name); |
1197 | 1169 | ||
1198 | if ((rc = i2o_exec_lct_get(c))) { | 1170 | if ((rc = i2o_iop_online(c))) |
1199 | i2o_iop_reset(c); | 1171 | goto class_del; |
1200 | return rc; | 1172 | |
1201 | } | 1173 | osm_debug("%s: getting LCT...\n", c->name); |
1174 | |||
1175 | if ((rc = i2o_exec_lct_get(c))) | ||
1176 | goto class_del; | ||
1202 | 1177 | ||
1203 | list_add(&c->list, &i2o_controllers); | 1178 | list_add(&c->list, &i2o_controllers); |
1204 | 1179 | ||
1205 | i2o_driver_notify_controller_add_all(c); | 1180 | i2o_driver_notify_controller_add_all(c); |
1206 | 1181 | ||
1207 | printk(KERN_INFO "%s: Controller added\n", c->name); | 1182 | osm_info("%s: Controller added\n", c->name); |
1208 | 1183 | ||
1209 | return 0; | 1184 | return 0; |
1185 | |||
1186 | class_del: | ||
1187 | class_device_del(&c->classdev); | ||
1188 | |||
1189 | device_del: | ||
1190 | device_del(&c->device); | ||
1191 | |||
1192 | iop_reset: | ||
1193 | i2o_iop_reset(c); | ||
1194 | |||
1195 | return rc; | ||
1210 | }; | 1196 | }; |
1211 | 1197 | ||
1212 | /** | 1198 | /** |
@@ -1264,16 +1250,18 @@ static int __init i2o_iop_init(void) | |||
1264 | if (rc) | 1250 | if (rc) |
1265 | goto exit; | 1251 | goto exit; |
1266 | 1252 | ||
1267 | rc = i2o_driver_init(); | 1253 | if ((rc = class_register(&i2o_controller_class))) { |
1268 | if (rc) | 1254 | osm_err("can't register class i2o_controller\n"); |
1269 | goto device_exit; | 1255 | goto device_exit; |
1256 | } | ||
1270 | 1257 | ||
1271 | rc = i2o_exec_init(); | 1258 | if ((rc = i2o_driver_init())) |
1272 | if (rc) | 1259 | goto class_exit; |
1260 | |||
1261 | if ((rc = i2o_exec_init())) | ||
1273 | goto driver_exit; | 1262 | goto driver_exit; |
1274 | 1263 | ||
1275 | rc = i2o_pci_init(); | 1264 | if ((rc = i2o_pci_init())) |
1276 | if (rc < 0) | ||
1277 | goto exec_exit; | 1265 | goto exec_exit; |
1278 | 1266 | ||
1279 | return 0; | 1267 | return 0; |
@@ -1284,6 +1272,9 @@ static int __init i2o_iop_init(void) | |||
1284 | driver_exit: | 1272 | driver_exit: |
1285 | i2o_driver_exit(); | 1273 | i2o_driver_exit(); |
1286 | 1274 | ||
1275 | class_exit: | ||
1276 | class_unregister(&i2o_controller_class); | ||
1277 | |||
1287 | device_exit: | 1278 | device_exit: |
1288 | i2o_device_exit(); | 1279 | i2o_device_exit(); |
1289 | 1280 | ||
@@ -1301,6 +1292,7 @@ static void __exit i2o_iop_exit(void) | |||
1301 | i2o_pci_exit(); | 1292 | i2o_pci_exit(); |
1302 | i2o_exec_exit(); | 1293 | i2o_exec_exit(); |
1303 | i2o_driver_exit(); | 1294 | i2o_driver_exit(); |
1295 | class_unregister(&i2o_controller_class); | ||
1304 | i2o_device_exit(); | 1296 | i2o_device_exit(); |
1305 | }; | 1297 | }; |
1306 | 1298 | ||
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index e772752f05..7a60fd7be8 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c | |||
@@ -30,53 +30,18 @@ | |||
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/i2o.h> | 32 | #include <linux/i2o.h> |
33 | 33 | #include "core.h" | |
34 | #ifdef CONFIG_MTRR | ||
35 | #include <asm/mtrr.h> | ||
36 | #endif // CONFIG_MTRR | ||
37 | |||
38 | /* Module internal functions from other sources */ | ||
39 | extern struct i2o_controller *i2o_iop_alloc(void); | ||
40 | extern void i2o_iop_free(struct i2o_controller *); | ||
41 | |||
42 | extern int i2o_iop_add(struct i2o_controller *); | ||
43 | extern void i2o_iop_remove(struct i2o_controller *); | ||
44 | |||
45 | extern int i2o_driver_dispatch(struct i2o_controller *, u32, | ||
46 | struct i2o_message *); | ||
47 | 34 | ||
48 | /* PCI device id table for all I2O controllers */ | 35 | /* PCI device id table for all I2O controllers */ |
49 | static struct pci_device_id __devinitdata i2o_pci_ids[] = { | 36 | static struct pci_device_id __devinitdata i2o_pci_ids[] = { |
50 | {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, | 37 | {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, |
51 | {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)}, | 38 | {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)}, |
39 | {.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962, | ||
40 | .subvendor = PCI_VENDOR_ID_PROMISE,.subdevice = PCI_ANY_ID}, | ||
52 | {0} | 41 | {0} |
53 | }; | 42 | }; |
54 | 43 | ||
55 | /** | 44 | /** |
56 | * i2o_dma_realloc - Realloc DMA memory | ||
57 | * @dev: struct device pointer to the PCI device of the I2O controller | ||
58 | * @addr: pointer to a i2o_dma struct DMA buffer | ||
59 | * @len: new length of memory | ||
60 | * @gfp_mask: GFP mask | ||
61 | * | ||
62 | * If there was something allocated in the addr, free it first. If len > 0 | ||
63 | * than try to allocate it and write the addresses back to the addr | ||
64 | * structure. If len == 0 set the virtual address to NULL. | ||
65 | * | ||
66 | * Returns the 0 on success or negative error code on failure. | ||
67 | */ | ||
68 | int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len, | ||
69 | unsigned int gfp_mask) | ||
70 | { | ||
71 | i2o_dma_free(dev, addr); | ||
72 | |||
73 | if (len) | ||
74 | return i2o_dma_alloc(dev, addr, len, gfp_mask); | ||
75 | |||
76 | return 0; | ||
77 | }; | ||
78 | |||
79 | /** | ||
80 | * i2o_pci_free - Frees the DMA memory for the I2O controller | 45 | * i2o_pci_free - Frees the DMA memory for the I2O controller |
81 | * @c: I2O controller to free | 46 | * @c: I2O controller to free |
82 | * | 47 | * |
@@ -91,19 +56,11 @@ static void i2o_pci_free(struct i2o_controller *c) | |||
91 | 56 | ||
92 | i2o_dma_free(dev, &c->out_queue); | 57 | i2o_dma_free(dev, &c->out_queue); |
93 | i2o_dma_free(dev, &c->status_block); | 58 | i2o_dma_free(dev, &c->status_block); |
94 | if (c->lct) | 59 | kfree(c->lct); |
95 | kfree(c->lct); | ||
96 | i2o_dma_free(dev, &c->dlct); | 60 | i2o_dma_free(dev, &c->dlct); |
97 | i2o_dma_free(dev, &c->hrt); | 61 | i2o_dma_free(dev, &c->hrt); |
98 | i2o_dma_free(dev, &c->status); | 62 | i2o_dma_free(dev, &c->status); |
99 | 63 | ||
100 | #ifdef CONFIG_MTRR | ||
101 | if (c->mtrr_reg0 >= 0) | ||
102 | mtrr_del(c->mtrr_reg0, 0, 0); | ||
103 | if (c->mtrr_reg1 >= 0) | ||
104 | mtrr_del(c->mtrr_reg1, 0, 0); | ||
105 | #endif | ||
106 | |||
107 | if (c->raptor && c->in_queue.virt) | 64 | if (c->raptor && c->in_queue.virt) |
108 | iounmap(c->in_queue.virt); | 65 | iounmap(c->in_queue.virt); |
109 | 66 | ||
@@ -178,14 +135,15 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
178 | c->name, (unsigned long)c->base.phys, | 135 | c->name, (unsigned long)c->base.phys, |
179 | (unsigned long)c->base.len); | 136 | (unsigned long)c->base.len); |
180 | 137 | ||
181 | c->base.virt = ioremap(c->base.phys, c->base.len); | 138 | c->base.virt = ioremap_nocache(c->base.phys, c->base.len); |
182 | if (!c->base.virt) { | 139 | if (!c->base.virt) { |
183 | printk(KERN_ERR "%s: Unable to map controller.\n", c->name); | 140 | printk(KERN_ERR "%s: Unable to map controller.\n", c->name); |
184 | return -ENOMEM; | 141 | return -ENOMEM; |
185 | } | 142 | } |
186 | 143 | ||
187 | if (c->raptor) { | 144 | if (c->raptor) { |
188 | c->in_queue.virt = ioremap(c->in_queue.phys, c->in_queue.len); | 145 | c->in_queue.virt = |
146 | ioremap_nocache(c->in_queue.phys, c->in_queue.len); | ||
189 | if (!c->in_queue.virt) { | 147 | if (!c->in_queue.virt) { |
190 | printk(KERN_ERR "%s: Unable to map controller.\n", | 148 | printk(KERN_ERR "%s: Unable to map controller.\n", |
191 | c->name); | 149 | c->name); |
@@ -195,43 +153,10 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
195 | } else | 153 | } else |
196 | c->in_queue = c->base; | 154 | c->in_queue = c->base; |
197 | 155 | ||
198 | c->irq_mask = c->base.virt + 0x34; | 156 | c->irq_status = c->base.virt + I2O_IRQ_STATUS; |
199 | c->post_port = c->base.virt + 0x40; | 157 | c->irq_mask = c->base.virt + I2O_IRQ_MASK; |
200 | c->reply_port = c->base.virt + 0x44; | 158 | c->in_port = c->base.virt + I2O_IN_PORT; |
201 | 159 | c->out_port = c->base.virt + I2O_OUT_PORT; | |
202 | #ifdef CONFIG_MTRR | ||
203 | /* Enable Write Combining MTRR for IOP's memory region */ | ||
204 | c->mtrr_reg0 = mtrr_add(c->in_queue.phys, c->in_queue.len, | ||
205 | MTRR_TYPE_WRCOMB, 1); | ||
206 | c->mtrr_reg1 = -1; | ||
207 | |||
208 | if (c->mtrr_reg0 < 0) | ||
209 | printk(KERN_WARNING "%s: could not enable write combining " | ||
210 | "MTRR\n", c->name); | ||
211 | else | ||
212 | printk(KERN_INFO "%s: using write combining MTRR\n", c->name); | ||
213 | |||
214 | /* | ||
215 | * If it is an INTEL i960 I/O processor then set the first 64K to | ||
216 | * Uncacheable since the region contains the messaging unit which | ||
217 | * shouldn't be cached. | ||
218 | */ | ||
219 | if ((pdev->vendor == PCI_VENDOR_ID_INTEL || | ||
220 | pdev->vendor == PCI_VENDOR_ID_DPT) && !c->raptor) { | ||
221 | printk(KERN_INFO "%s: MTRR workaround for Intel i960 processor" | ||
222 | "\n", c->name); | ||
223 | c->mtrr_reg1 = mtrr_add(c->base.phys, 0x10000, | ||
224 | MTRR_TYPE_UNCACHABLE, 1); | ||
225 | |||
226 | if (c->mtrr_reg1 < 0) { | ||
227 | printk(KERN_WARNING "%s: Error in setting " | ||
228 | "MTRR_TYPE_UNCACHABLE\n", c->name); | ||
229 | mtrr_del(c->mtrr_reg0, c->in_queue.phys, | ||
230 | c->in_queue.len); | ||
231 | c->mtrr_reg0 = -1; | ||
232 | } | ||
233 | } | ||
234 | #endif | ||
235 | 160 | ||
236 | if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { | 161 | if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { |
237 | i2o_pci_free(c); | 162 | i2o_pci_free(c); |
@@ -254,7 +179,10 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
254 | return -ENOMEM; | 179 | return -ENOMEM; |
255 | } | 180 | } |
256 | 181 | ||
257 | if (i2o_dma_alloc(dev, &c->out_queue, MSG_POOL_SIZE, GFP_KERNEL)) { | 182 | if (i2o_dma_alloc |
183 | (dev, &c->out_queue, | ||
184 | I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE * | ||
185 | sizeof(u32), GFP_KERNEL)) { | ||
258 | i2o_pci_free(c); | 186 | i2o_pci_free(c); |
259 | return -ENOMEM; | 187 | return -ENOMEM; |
260 | } | 188 | } |
@@ -276,51 +204,30 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
276 | static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) | 204 | static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) |
277 | { | 205 | { |
278 | struct i2o_controller *c = dev_id; | 206 | struct i2o_controller *c = dev_id; |
279 | struct device *dev = &c->pdev->dev; | 207 | u32 m; |
280 | struct i2o_message *m; | 208 | irqreturn_t rc = IRQ_NONE; |
281 | u32 mv; | 209 | |
282 | 210 | while (readl(c->irq_status) & I2O_IRQ_OUTBOUND_POST) { | |
283 | /* | 211 | m = readl(c->out_port); |
284 | * Old 960 steppings had a bug in the I2O unit that caused | 212 | if (m == I2O_QUEUE_EMPTY) { |
285 | * the queue to appear empty when it wasn't. | 213 | /* |
286 | */ | 214 | * Old 960 steppings had a bug in the I2O unit that |
287 | mv = I2O_REPLY_READ32(c); | 215 | * caused the queue to appear empty when it wasn't. |
288 | if (mv == I2O_QUEUE_EMPTY) { | 216 | */ |
289 | mv = I2O_REPLY_READ32(c); | 217 | m = readl(c->out_port); |
290 | if (unlikely(mv == I2O_QUEUE_EMPTY)) { | 218 | if (unlikely(m == I2O_QUEUE_EMPTY)) |
291 | return IRQ_NONE; | 219 | break; |
292 | } else | 220 | } |
293 | pr_debug("%s: 960 bug detected\n", c->name); | ||
294 | } | ||
295 | |||
296 | while (mv != I2O_QUEUE_EMPTY) { | ||
297 | /* | ||
298 | * Map the message from the page frame map to kernel virtual. | ||
299 | * Because bus_to_virt is deprecated, we have calculate the | ||
300 | * location by ourself! | ||
301 | */ | ||
302 | m = i2o_msg_out_to_virt(c, mv); | ||
303 | |||
304 | /* | ||
305 | * Ensure this message is seen coherently but cachably by | ||
306 | * the processor | ||
307 | */ | ||
308 | dma_sync_single_for_cpu(dev, mv, MSG_FRAME_SIZE * 4, | ||
309 | PCI_DMA_FROMDEVICE); | ||
310 | 221 | ||
311 | /* dispatch it */ | 222 | /* dispatch it */ |
312 | if (i2o_driver_dispatch(c, mv, m)) | 223 | if (i2o_driver_dispatch(c, m)) |
313 | /* flush it if result != 0 */ | 224 | /* flush it if result != 0 */ |
314 | i2o_flush_reply(c, mv); | 225 | i2o_flush_reply(c, m); |
315 | 226 | ||
316 | /* | 227 | rc = IRQ_HANDLED; |
317 | * That 960 bug again... | ||
318 | */ | ||
319 | mv = I2O_REPLY_READ32(c); | ||
320 | if (mv == I2O_QUEUE_EMPTY) | ||
321 | mv = I2O_REPLY_READ32(c); | ||
322 | } | 228 | } |
323 | return IRQ_HANDLED; | 229 | |
230 | return rc; | ||
324 | } | 231 | } |
325 | 232 | ||
326 | /** | 233 | /** |
@@ -336,7 +243,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) | |||
336 | struct pci_dev *pdev = c->pdev; | 243 | struct pci_dev *pdev = c->pdev; |
337 | int rc; | 244 | int rc; |
338 | 245 | ||
339 | I2O_IRQ_WRITE32(c, 0xffffffff); | 246 | writel(0xffffffff, c->irq_mask); |
340 | 247 | ||
341 | if (pdev->irq) { | 248 | if (pdev->irq) { |
342 | rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ, | 249 | rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ, |
@@ -348,7 +255,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) | |||
348 | } | 255 | } |
349 | } | 256 | } |
350 | 257 | ||
351 | I2O_IRQ_WRITE32(c, 0x00000000); | 258 | writel(0x00000000, c->irq_mask); |
352 | 259 | ||
353 | printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq); | 260 | printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq); |
354 | 261 | ||
@@ -363,7 +270,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) | |||
363 | */ | 270 | */ |
364 | static void i2o_pci_irq_disable(struct i2o_controller *c) | 271 | static void i2o_pci_irq_disable(struct i2o_controller *c) |
365 | { | 272 | { |
366 | I2O_IRQ_WRITE32(c, 0xffffffff); | 273 | writel(0xffffffff, c->irq_mask); |
367 | 274 | ||
368 | if (c->pdev->irq > 0) | 275 | if (c->pdev->irq > 0) |
369 | free_irq(c->pdev->irq, c); | 276 | free_irq(c->pdev->irq, c); |
@@ -385,28 +292,25 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
385 | { | 292 | { |
386 | struct i2o_controller *c; | 293 | struct i2o_controller *c; |
387 | int rc; | 294 | int rc; |
295 | struct pci_dev *i960 = NULL; | ||
388 | 296 | ||
389 | printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); | 297 | printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); |
390 | 298 | ||
391 | if ((pdev->class & 0xff) > 1) { | 299 | if ((pdev->class & 0xff) > 1) { |
392 | printk(KERN_WARNING "i2o: I2O controller found but does not " | 300 | printk(KERN_WARNING "i2o: %s does not support I2O 1.5 " |
393 | "support I2O 1.5 (skipping).\n"); | 301 | "(skipping).\n", pci_name(pdev)); |
394 | return -ENODEV; | 302 | return -ENODEV; |
395 | } | 303 | } |
396 | 304 | ||
397 | if ((rc = pci_enable_device(pdev))) { | 305 | if ((rc = pci_enable_device(pdev))) { |
398 | printk(KERN_WARNING "i2o: I2O controller found but could not be" | 306 | printk(KERN_WARNING "i2o: couldn't enable device %s\n", |
399 | " enabled.\n"); | 307 | pci_name(pdev)); |
400 | return rc; | 308 | return rc; |
401 | } | 309 | } |
402 | 310 | ||
403 | printk(KERN_INFO "i2o: I2O controller found on bus %d at %d.\n", | ||
404 | pdev->bus->number, pdev->devfn); | ||
405 | |||
406 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { | 311 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { |
407 | printk(KERN_WARNING "i2o: I2O controller on bus %d at %d: No " | 312 | printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", |
408 | "suitable DMA available!\n", pdev->bus->number, | 313 | pci_name(pdev)); |
409 | pdev->devfn); | ||
410 | rc = -ENODEV; | 314 | rc = -ENODEV; |
411 | goto disable; | 315 | goto disable; |
412 | } | 316 | } |
@@ -415,14 +319,16 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
415 | 319 | ||
416 | c = i2o_iop_alloc(); | 320 | c = i2o_iop_alloc(); |
417 | if (IS_ERR(c)) { | 321 | if (IS_ERR(c)) { |
418 | printk(KERN_ERR "i2o: memory for I2O controller could not be " | 322 | printk(KERN_ERR "i2o: couldn't allocate memory for %s\n", |
419 | "allocated\n"); | 323 | pci_name(pdev)); |
420 | rc = PTR_ERR(c); | 324 | rc = PTR_ERR(c); |
421 | goto disable; | 325 | goto disable; |
422 | } | 326 | } else |
327 | printk(KERN_INFO "%s: controller found (%s)\n", c->name, | ||
328 | pci_name(pdev)); | ||
423 | 329 | ||
424 | c->pdev = pdev; | 330 | c->pdev = pdev; |
425 | c->device = pdev->dev; | 331 | c->device.parent = get_device(&pdev->dev); |
426 | 332 | ||
427 | /* Cards that fall apart if you hit them with large I/O loads... */ | 333 | /* Cards that fall apart if you hit them with large I/O loads... */ |
428 | if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) { | 334 | if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) { |
@@ -432,16 +338,48 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
432 | } | 338 | } |
433 | 339 | ||
434 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) { | 340 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) { |
341 | /* | ||
342 | * Expose the ship behind i960 for initialization, or it will | ||
343 | * failed | ||
344 | */ | ||
345 | i960 = | ||
346 | pci_find_slot(c->pdev->bus->number, | ||
347 | PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0)); | ||
348 | |||
349 | if (i960) | ||
350 | pci_write_config_word(i960, 0x42, 0); | ||
351 | |||
435 | c->promise = 1; | 352 | c->promise = 1; |
436 | printk(KERN_INFO "%s: Promise workarounds activated.\n", | 353 | c->limit_sectors = 1; |
437 | c->name); | ||
438 | } | 354 | } |
439 | 355 | ||
356 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_DPT) | ||
357 | c->adaptec = 1; | ||
358 | |||
440 | /* Cards that go bananas if you quiesce them before you reset them. */ | 359 | /* Cards that go bananas if you quiesce them before you reset them. */ |
441 | if (pdev->vendor == PCI_VENDOR_ID_DPT) { | 360 | if (pdev->vendor == PCI_VENDOR_ID_DPT) { |
442 | c->no_quiesce = 1; | 361 | c->no_quiesce = 1; |
443 | if (pdev->device == 0xa511) | 362 | if (pdev->device == 0xa511) |
444 | c->raptor = 1; | 363 | c->raptor = 1; |
364 | |||
365 | if (pdev->subsystem_device == 0xc05a) { | ||
366 | c->limit_sectors = 1; | ||
367 | printk(KERN_INFO | ||
368 | "%s: limit sectors per request to %d\n", c->name, | ||
369 | I2O_MAX_SECTORS_LIMITED); | ||
370 | } | ||
371 | #ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 | ||
372 | if (sizeof(dma_addr_t) > 4) { | ||
373 | if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)) | ||
374 | printk(KERN_INFO "%s: 64-bit DMA unavailable\n", | ||
375 | c->name); | ||
376 | else { | ||
377 | c->pae_support = 1; | ||
378 | printk(KERN_INFO "%s: using 64-bit DMA\n", | ||
379 | c->name); | ||
380 | } | ||
381 | } | ||
382 | #endif | ||
445 | } | 383 | } |
446 | 384 | ||
447 | if ((rc = i2o_pci_alloc(c))) { | 385 | if ((rc = i2o_pci_alloc(c))) { |
@@ -459,6 +397,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
459 | if ((rc = i2o_iop_add(c))) | 397 | if ((rc = i2o_iop_add(c))) |
460 | goto uninstall; | 398 | goto uninstall; |
461 | 399 | ||
400 | get_device(&c->device); | ||
401 | |||
402 | if (i960) | ||
403 | pci_write_config_word(i960, 0x42, 0x03ff); | ||
404 | |||
462 | return 0; | 405 | return 0; |
463 | 406 | ||
464 | uninstall: | 407 | uninstall: |
@@ -469,6 +412,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
469 | 412 | ||
470 | free_controller: | 413 | free_controller: |
471 | i2o_iop_free(c); | 414 | i2o_iop_free(c); |
415 | put_device(c->device.parent); | ||
472 | 416 | ||
473 | disable: | 417 | disable: |
474 | pci_disable_device(pdev); | 418 | pci_disable_device(pdev); |
@@ -492,15 +436,17 @@ static void __devexit i2o_pci_remove(struct pci_dev *pdev) | |||
492 | i2o_pci_irq_disable(c); | 436 | i2o_pci_irq_disable(c); |
493 | i2o_pci_free(c); | 437 | i2o_pci_free(c); |
494 | 438 | ||
439 | pci_disable_device(pdev); | ||
440 | |||
495 | printk(KERN_INFO "%s: Controller removed.\n", c->name); | 441 | printk(KERN_INFO "%s: Controller removed.\n", c->name); |
496 | 442 | ||
497 | i2o_iop_free(c); | 443 | put_device(c->device.parent); |
498 | pci_disable_device(pdev); | 444 | put_device(&c->device); |
499 | }; | 445 | }; |
500 | 446 | ||
501 | /* PCI driver for I2O controller */ | 447 | /* PCI driver for I2O controller */ |
502 | static struct pci_driver i2o_pci_driver = { | 448 | static struct pci_driver i2o_pci_driver = { |
503 | .name = "I2O controller", | 449 | .name = "PCI_I2O", |
504 | .id_table = i2o_pci_ids, | 450 | .id_table = i2o_pci_ids, |
505 | .probe = i2o_pci_probe, | 451 | .probe = i2o_pci_probe, |
506 | .remove = __devexit_p(i2o_pci_remove), | 452 | .remove = __devexit_p(i2o_pci_remove), |
@@ -523,6 +469,4 @@ void __exit i2o_pci_exit(void) | |||
523 | { | 469 | { |
524 | pci_unregister_driver(&i2o_pci_driver); | 470 | pci_unregister_driver(&i2o_pci_driver); |
525 | }; | 471 | }; |
526 | |||
527 | EXPORT_SYMBOL(i2o_dma_realloc); | ||
528 | MODULE_DEVICE_TABLE(pci, i2o_pci_ids); | 472 | MODULE_DEVICE_TABLE(pci, i2o_pci_ids); |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 325495b8b6..137226d98d 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -2307,6 +2307,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
2307 | tso = e1000_tso(adapter, skb); | 2307 | tso = e1000_tso(adapter, skb); |
2308 | if (tso < 0) { | 2308 | if (tso < 0) { |
2309 | dev_kfree_skb_any(skb); | 2309 | dev_kfree_skb_any(skb); |
2310 | spin_unlock_irqrestore(&adapter->tx_lock, flags); | ||
2310 | return NETDEV_TX_OK; | 2311 | return NETDEV_TX_OK; |
2311 | } | 2312 | } |
2312 | 2313 | ||
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 89454915b8..e44f8e9055 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c | |||
@@ -848,7 +848,7 @@ static void __exit sixpack_exit_driver(void) | |||
848 | { | 848 | { |
849 | int ret; | 849 | int ret; |
850 | 850 | ||
851 | if ((ret = tty_register_ldisc(N_6PACK, NULL))) | 851 | if ((ret = tty_unregister_ldisc(N_6PACK))) |
852 | printk(msg_unregfail, ret); | 852 | printk(msg_unregfail, ret); |
853 | } | 853 | } |
854 | 854 | ||
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 6279051109..3035422f5a 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c | |||
@@ -934,7 +934,7 @@ static void __exit mkiss_exit_driver(void) | |||
934 | kfree(ax25_ctrls); | 934 | kfree(ax25_ctrls); |
935 | ax25_ctrls = NULL; | 935 | ax25_ctrls = NULL; |
936 | 936 | ||
937 | if ((i = tty_register_ldisc(N_AX25, NULL))) | 937 | if ((i = tty_unregister_ldisc(N_AX25))) |
938 | printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i); | 938 | printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i); |
939 | } | 939 | } |
940 | 940 | ||
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 7d23aa3759..b8d112348b 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c | |||
@@ -626,7 +626,7 @@ static void __exit irtty_sir_cleanup(void) | |||
626 | { | 626 | { |
627 | int err; | 627 | int err; |
628 | 628 | ||
629 | if ((err = tty_register_ldisc(N_IRDA, NULL))) { | 629 | if ((err = tty_unregister_ldisc(N_IRDA))) { |
630 | IRDA_ERROR("%s(), can't unregister line discipline (err = %d)\n", | 630 | IRDA_ERROR("%s(), can't unregister line discipline (err = %d)\n", |
631 | __FUNCTION__, err); | 631 | __FUNCTION__, err); |
632 | } | 632 | } |
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 33b9d79b1a..5e48b9ab30 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c | |||
@@ -1025,7 +1025,7 @@ static void async_lcp_peek(struct asyncppp *ap, unsigned char *data, | |||
1025 | 1025 | ||
1026 | static void __exit ppp_async_cleanup(void) | 1026 | static void __exit ppp_async_cleanup(void) |
1027 | { | 1027 | { |
1028 | if (tty_register_ldisc(N_PPP, NULL) != 0) | 1028 | if (tty_unregister_ldisc(N_PPP) != 0) |
1029 | printk(KERN_ERR "failed to unregister PPP line discipline\n"); | 1029 | printk(KERN_ERR "failed to unregister PPP line discipline\n"); |
1030 | } | 1030 | } |
1031 | 1031 | ||
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 7d0150b4c6..fd9f501803 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c | |||
@@ -793,7 +793,7 @@ err: | |||
793 | static void __exit | 793 | static void __exit |
794 | ppp_sync_cleanup(void) | 794 | ppp_sync_cleanup(void) |
795 | { | 795 | { |
796 | if (tty_register_ldisc(N_SYNC_PPP, NULL) != 0) | 796 | if (tty_unregister_ldisc(N_SYNC_PPP) != 0) |
797 | printk(KERN_ERR "failed to unregister Sync PPP line discipline\n"); | 797 | printk(KERN_ERR "failed to unregister Sync PPP line discipline\n"); |
798 | } | 798 | } |
799 | 799 | ||
diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 8f7841c037..c79e0ad4ba 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c | |||
@@ -198,18 +198,12 @@ err_exit: | |||
198 | static void | 198 | static void |
199 | sl_free_bufs(struct slip *sl) | 199 | sl_free_bufs(struct slip *sl) |
200 | { | 200 | { |
201 | void * tmp; | ||
202 | |||
203 | /* Free all SLIP frame buffers. */ | 201 | /* Free all SLIP frame buffers. */ |
204 | tmp = xchg(&sl->rbuff, NULL); | 202 | kfree(xchg(&sl->rbuff, NULL)); |
205 | kfree(tmp); | 203 | kfree(xchg(&sl->xbuff, NULL)); |
206 | tmp = xchg(&sl->xbuff, NULL); | ||
207 | kfree(tmp); | ||
208 | #ifdef SL_INCLUDE_CSLIP | 204 | #ifdef SL_INCLUDE_CSLIP |
209 | tmp = xchg(&sl->cbuff, NULL); | 205 | kfree(xchg(&sl->cbuff, NULL)); |
210 | kfree(tmp); | 206 | slhc_free(xchg(&sl->slcomp, NULL)); |
211 | if ((tmp = xchg(&sl->slcomp, NULL)) != NULL) | ||
212 | slhc_free(tmp); | ||
213 | #endif | 207 | #endif |
214 | } | 208 | } |
215 | 209 | ||
@@ -1430,7 +1424,7 @@ static void __exit slip_exit(void) | |||
1430 | kfree(slip_devs); | 1424 | kfree(slip_devs); |
1431 | slip_devs = NULL; | 1425 | slip_devs = NULL; |
1432 | 1426 | ||
1433 | if ((i = tty_register_ldisc(N_SLIP, NULL))) | 1427 | if ((i = tty_unregister_ldisc(N_SLIP))) |
1434 | { | 1428 | { |
1435 | printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i); | 1429 | printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i); |
1436 | } | 1430 | } |
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 1c540d8255..bdf672c481 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c | |||
@@ -829,7 +829,7 @@ static void __exit exit_x25_asy(void) | |||
829 | } | 829 | } |
830 | 830 | ||
831 | kfree(x25_asy_devs); | 831 | kfree(x25_asy_devs); |
832 | tty_register_ldisc(N_X25, NULL); | 832 | tty_unregister_ldisc(N_X25); |
833 | } | 833 | } |
834 | 834 | ||
835 | module_init(init_x25_asy); | 835 | module_init(init_x25_asy); |
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index ec8cf29ffc..6c42b573a9 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c | |||
@@ -2828,7 +2828,7 @@ static void __exit strip_exit_driver(void) | |||
2828 | /* Unregister with the /proc/net file here. */ | 2828 | /* Unregister with the /proc/net file here. */ |
2829 | proc_net_remove("strip"); | 2829 | proc_net_remove("strip"); |
2830 | 2830 | ||
2831 | if ((i = tty_register_ldisc(N_STRIP, NULL))) | 2831 | if ((i = tty_unregister_ldisc(N_STRIP))) |
2832 | printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i); | 2832 | printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i); |
2833 | 2833 | ||
2834 | printk(signoff); | 2834 | printk(signoff); |
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 745a141836..531b073131 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c | |||
@@ -206,7 +206,7 @@ static inline unsigned long fast_get_dcookie(struct dentry * dentry, | |||
206 | */ | 206 | */ |
207 | static unsigned long get_exec_dcookie(struct mm_struct * mm) | 207 | static unsigned long get_exec_dcookie(struct mm_struct * mm) |
208 | { | 208 | { |
209 | unsigned long cookie = 0; | 209 | unsigned long cookie = NO_COOKIE; |
210 | struct vm_area_struct * vma; | 210 | struct vm_area_struct * vma; |
211 | 211 | ||
212 | if (!mm) | 212 | if (!mm) |
@@ -234,35 +234,42 @@ out: | |||
234 | */ | 234 | */ |
235 | static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, off_t * offset) | 235 | static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, off_t * offset) |
236 | { | 236 | { |
237 | unsigned long cookie = 0; | 237 | unsigned long cookie = NO_COOKIE; |
238 | struct vm_area_struct * vma; | 238 | struct vm_area_struct * vma; |
239 | 239 | ||
240 | for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) { | 240 | for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) { |
241 | 241 | ||
242 | if (!vma->vm_file) | ||
243 | continue; | ||
244 | |||
245 | if (addr < vma->vm_start || addr >= vma->vm_end) | 242 | if (addr < vma->vm_start || addr >= vma->vm_end) |
246 | continue; | 243 | continue; |
247 | 244 | ||
248 | cookie = fast_get_dcookie(vma->vm_file->f_dentry, | 245 | if (vma->vm_file) { |
249 | vma->vm_file->f_vfsmnt); | 246 | cookie = fast_get_dcookie(vma->vm_file->f_dentry, |
250 | *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; | 247 | vma->vm_file->f_vfsmnt); |
248 | *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - | ||
249 | vma->vm_start; | ||
250 | } else { | ||
251 | /* must be an anonymous map */ | ||
252 | *offset = addr; | ||
253 | } | ||
254 | |||
251 | break; | 255 | break; |
252 | } | 256 | } |
253 | 257 | ||
258 | if (!vma) | ||
259 | cookie = INVALID_COOKIE; | ||
260 | |||
254 | return cookie; | 261 | return cookie; |
255 | } | 262 | } |
256 | 263 | ||
257 | 264 | ||
258 | static unsigned long last_cookie = ~0UL; | 265 | static unsigned long last_cookie = INVALID_COOKIE; |
259 | 266 | ||
260 | static void add_cpu_switch(int i) | 267 | static void add_cpu_switch(int i) |
261 | { | 268 | { |
262 | add_event_entry(ESCAPE_CODE); | 269 | add_event_entry(ESCAPE_CODE); |
263 | add_event_entry(CPU_SWITCH_CODE); | 270 | add_event_entry(CPU_SWITCH_CODE); |
264 | add_event_entry(i); | 271 | add_event_entry(i); |
265 | last_cookie = ~0UL; | 272 | last_cookie = INVALID_COOKIE; |
266 | } | 273 | } |
267 | 274 | ||
268 | static void add_kernel_ctx_switch(unsigned int in_kernel) | 275 | static void add_kernel_ctx_switch(unsigned int in_kernel) |
@@ -317,7 +324,7 @@ static int add_us_sample(struct mm_struct * mm, struct op_sample * s) | |||
317 | 324 | ||
318 | cookie = lookup_dcookie(mm, s->eip, &offset); | 325 | cookie = lookup_dcookie(mm, s->eip, &offset); |
319 | 326 | ||
320 | if (!cookie) { | 327 | if (cookie == INVALID_COOKIE) { |
321 | atomic_inc(&oprofile_stats.sample_lost_no_mapping); | 328 | atomic_inc(&oprofile_stats.sample_lost_no_mapping); |
322 | return 0; | 329 | return 0; |
323 | } | 330 | } |
diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h index 442aaad391..0180236305 100644 --- a/drivers/oprofile/event_buffer.h +++ b/drivers/oprofile/event_buffer.h | |||
@@ -35,6 +35,9 @@ void wake_up_buffer_waiter(void); | |||
35 | #define TRACE_BEGIN_CODE 8 | 35 | #define TRACE_BEGIN_CODE 8 |
36 | #define TRACE_END_CODE 9 | 36 | #define TRACE_END_CODE 9 |
37 | 37 | ||
38 | #define INVALID_COOKIE ~0UL | ||
39 | #define NO_COOKIE 0UL | ||
40 | |||
38 | /* add data to the event buffer */ | 41 | /* add data to the event buffer */ |
39 | void add_event_entry(unsigned long data); | 42 | void add_event_entry(unsigned long data); |
40 | 43 | ||
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index e7f3bcb790..80edfa3abd 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
@@ -2751,7 +2751,6 @@ enum parport_pc_pci_cards { | |||
2751 | netmos_9755, | 2751 | netmos_9755, |
2752 | netmos_9805, | 2752 | netmos_9805, |
2753 | netmos_9815, | 2753 | netmos_9815, |
2754 | netmos_9855, | ||
2755 | }; | 2754 | }; |
2756 | 2755 | ||
2757 | 2756 | ||
@@ -2826,7 +2825,6 @@ static struct parport_pc_pci { | |||
2826 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */ | 2825 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */ |
2827 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, /* untested */ | 2826 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, /* untested */ |
2828 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */ | 2827 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */ |
2829 | /* netmos_9855 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */ | ||
2830 | }; | 2828 | }; |
2831 | 2829 | ||
2832 | static struct pci_device_id parport_pc_pci_tbl[] = { | 2830 | static struct pci_device_id parport_pc_pci_tbl[] = { |
@@ -2907,8 +2905,6 @@ static struct pci_device_id parport_pc_pci_tbl[] = { | |||
2907 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 }, | 2905 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 }, |
2908 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815, | 2906 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815, |
2909 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, | 2907 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, |
2910 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855, | ||
2911 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 }, | ||
2912 | { 0, } /* terminate list */ | 2908 | { 0, } /* terminate list */ |
2913 | }; | 2909 | }; |
2914 | MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl); | 2910 | MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl); |
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index 6715a17b5d..00498e2f12 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c | |||
@@ -34,6 +34,7 @@ enum parport_pc_pci_cards { | |||
34 | titan_110l = 0, | 34 | titan_110l = 0, |
35 | titan_210l, | 35 | titan_210l, |
36 | netmos_9xx5_combo, | 36 | netmos_9xx5_combo, |
37 | netmos_9855, | ||
37 | avlab_1s1p, | 38 | avlab_1s1p, |
38 | avlab_1s1p_650, | 39 | avlab_1s1p_650, |
39 | avlab_1s1p_850, | 40 | avlab_1s1p_850, |
@@ -87,6 +88,7 @@ static struct parport_pc_pci cards[] __devinitdata = { | |||
87 | /* titan_110l */ { 1, { { 3, -1 }, } }, | 88 | /* titan_110l */ { 1, { { 3, -1 }, } }, |
88 | /* titan_210l */ { 1, { { 3, -1 }, } }, | 89 | /* titan_210l */ { 1, { { 3, -1 }, } }, |
89 | /* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init }, | 90 | /* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init }, |
91 | /* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init }, | ||
90 | /* avlab_1s1p */ { 1, { { 1, 2}, } }, | 92 | /* avlab_1s1p */ { 1, { { 1, 2}, } }, |
91 | /* avlab_1s1p_650 */ { 1, { { 1, 2}, } }, | 93 | /* avlab_1s1p_650 */ { 1, { { 1, 2}, } }, |
92 | /* avlab_1s1p_850 */ { 1, { { 1, 2}, } }, | 94 | /* avlab_1s1p_850 */ { 1, { { 1, 2}, } }, |
@@ -120,7 +122,7 @@ static struct pci_device_id parport_serial_pci_tbl[] = { | |||
120 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845, | 122 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845, |
121 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo }, | 123 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo }, |
122 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855, | 124 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855, |
123 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo }, | 125 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 }, |
124 | /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ | 126 | /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ |
125 | { 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p}, | 127 | { 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p}, |
126 | { 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650}, | 128 | { 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650}, |
@@ -207,6 +209,7 @@ static struct pci_board_no_ids pci_boards[] __devinitdata = { | |||
207 | /* titan_110l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 }, | 209 | /* titan_110l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 }, |
208 | /* titan_210l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 }, | 210 | /* titan_210l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 }, |
209 | /* netmos_9xx5_combo */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init }, | 211 | /* netmos_9xx5_combo */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init }, |
212 | /* netmos_9855 */ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init }, | ||
210 | /* avlab_1s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, | 213 | /* avlab_1s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, |
211 | /* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, | 214 | /* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, |
212 | /* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, | 215 | /* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, |
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c index c94963145e..6e6f42d01e 100644 --- a/drivers/parport/probe.c +++ b/drivers/parport/probe.c | |||
@@ -48,14 +48,6 @@ static void pretty_print(struct parport *port, int device) | |||
48 | printk("\n"); | 48 | printk("\n"); |
49 | } | 49 | } |
50 | 50 | ||
51 | static char *strdup(char *str) | ||
52 | { | ||
53 | int n = strlen(str)+1; | ||
54 | char *s = kmalloc(n, GFP_KERNEL); | ||
55 | if (!s) return NULL; | ||
56 | return strcpy(s, str); | ||
57 | } | ||
58 | |||
59 | static void parse_data(struct parport *port, int device, char *str) | 51 | static void parse_data(struct parport *port, int device, char *str) |
60 | { | 52 | { |
61 | char *txt = kmalloc(strlen(str)+1, GFP_KERNEL); | 53 | char *txt = kmalloc(strlen(str)+1, GFP_KERNEL); |
@@ -88,16 +80,16 @@ static void parse_data(struct parport *port, int device, char *str) | |||
88 | if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) { | 80 | if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) { |
89 | if (info->mfr) | 81 | if (info->mfr) |
90 | kfree (info->mfr); | 82 | kfree (info->mfr); |
91 | info->mfr = strdup(sep); | 83 | info->mfr = kstrdup(sep, GFP_KERNEL); |
92 | } else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) { | 84 | } else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) { |
93 | if (info->model) | 85 | if (info->model) |
94 | kfree (info->model); | 86 | kfree (info->model); |
95 | info->model = strdup(sep); | 87 | info->model = kstrdup(sep, GFP_KERNEL); |
96 | } else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) { | 88 | } else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) { |
97 | int i; | 89 | int i; |
98 | if (info->class_name) | 90 | if (info->class_name) |
99 | kfree (info->class_name); | 91 | kfree (info->class_name); |
100 | info->class_name = strdup(sep); | 92 | info->class_name = kstrdup(sep, GFP_KERNEL); |
101 | for (u = sep; *u; u++) | 93 | for (u = sep; *u; u++) |
102 | *u = toupper(*u); | 94 | *u = toupper(*u); |
103 | for (i = 0; classes[i].token; i++) { | 95 | for (i = 0; classes[i].token; i++) { |
@@ -112,7 +104,7 @@ static void parse_data(struct parport *port, int device, char *str) | |||
112 | !strcmp(p, "COMMAND SET")) { | 104 | !strcmp(p, "COMMAND SET")) { |
113 | if (info->cmdset) | 105 | if (info->cmdset) |
114 | kfree (info->cmdset); | 106 | kfree (info->cmdset); |
115 | info->cmdset = strdup(sep); | 107 | info->cmdset = kstrdup(sep, GFP_KERNEL); |
116 | /* if it speaks printer language, it's | 108 | /* if it speaks printer language, it's |
117 | probably a printer */ | 109 | probably a printer */ |
118 | if (strstr(sep, "PJL") || strstr(sep, "PCL")) | 110 | if (strstr(sep, "PJL") || strstr(sep, "PCL")) |
@@ -120,7 +112,7 @@ static void parse_data(struct parport *port, int device, char *str) | |||
120 | } else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) { | 112 | } else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) { |
121 | if (info->description) | 113 | if (info->description) |
122 | kfree (info->description); | 114 | kfree (info->description); |
123 | info->description = strdup(sep); | 115 | info->description = kstrdup(sep, GFP_KERNEL); |
124 | } | 116 | } |
125 | } | 117 | } |
126 | rock_on: | 118 | rock_on: |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 03fc885db1..d136b3c8fa 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -508,6 +508,10 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay) | |||
508 | cs_err(skt, "unsupported voltage key.\n"); | 508 | cs_err(skt, "unsupported voltage key.\n"); |
509 | return CS_BAD_TYPE; | 509 | return CS_BAD_TYPE; |
510 | } | 510 | } |
511 | |||
512 | if (skt->power_hook) | ||
513 | skt->power_hook(skt, HOOK_POWER_PRE); | ||
514 | |||
511 | skt->socket.flags = 0; | 515 | skt->socket.flags = 0; |
512 | skt->ops->set_socket(skt, &skt->socket); | 516 | skt->ops->set_socket(skt, &skt->socket); |
513 | 517 | ||
@@ -522,7 +526,12 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay) | |||
522 | return CS_BAD_TYPE; | 526 | return CS_BAD_TYPE; |
523 | } | 527 | } |
524 | 528 | ||
525 | return socket_reset(skt); | 529 | status = socket_reset(skt); |
530 | |||
531 | if (skt->power_hook) | ||
532 | skt->power_hook(skt, HOOK_POWER_POST); | ||
533 | |||
534 | return status; | ||
526 | } | 535 | } |
527 | 536 | ||
528 | /* | 537 | /* |
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index a8a1d10452..c7ba99871a 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h | |||
@@ -611,6 +611,170 @@ out: | |||
611 | } | 611 | } |
612 | } | 612 | } |
613 | 613 | ||
614 | |||
615 | /* Returns true value if the second slot of a two-slot controller is empty */ | ||
616 | static int ti12xx_2nd_slot_empty(struct yenta_socket *socket) | ||
617 | { | ||
618 | struct pci_dev *func; | ||
619 | struct yenta_socket *slot2; | ||
620 | int devfn; | ||
621 | unsigned int state; | ||
622 | int ret = 1; | ||
623 | |||
624 | /* catch the two-slot controllers */ | ||
625 | switch (socket->dev->device) { | ||
626 | case PCI_DEVICE_ID_TI_1220: | ||
627 | case PCI_DEVICE_ID_TI_1221: | ||
628 | case PCI_DEVICE_ID_TI_1225: | ||
629 | case PCI_DEVICE_ID_TI_1251A: | ||
630 | case PCI_DEVICE_ID_TI_1251B: | ||
631 | case PCI_DEVICE_ID_TI_1420: | ||
632 | case PCI_DEVICE_ID_TI_1450: | ||
633 | case PCI_DEVICE_ID_TI_1451A: | ||
634 | case PCI_DEVICE_ID_TI_1520: | ||
635 | case PCI_DEVICE_ID_TI_1620: | ||
636 | case PCI_DEVICE_ID_TI_4520: | ||
637 | case PCI_DEVICE_ID_TI_4450: | ||
638 | case PCI_DEVICE_ID_TI_4451: | ||
639 | /* | ||
640 | * there are way more, but they need to be added in yenta_socket.c | ||
641 | * and pci_ids.h first anyway. | ||
642 | */ | ||
643 | break; | ||
644 | |||
645 | /* single-slot controllers have the 2nd slot empty always :) */ | ||
646 | default: | ||
647 | return 1; | ||
648 | } | ||
649 | |||
650 | /* get other slot */ | ||
651 | devfn = socket->dev->devfn & ~0x07; | ||
652 | func = pci_get_slot(socket->dev->bus, | ||
653 | (socket->dev->devfn & 0x07) ? devfn : devfn | 0x01); | ||
654 | if (!func) | ||
655 | return 1; | ||
656 | |||
657 | slot2 = pci_get_drvdata(func); | ||
658 | if (!slot2) | ||
659 | goto out; | ||
660 | |||
661 | /* check state */ | ||
662 | yenta_get_status(&socket->socket, &state); | ||
663 | if (state & SS_DETECT) { | ||
664 | ret = 0; | ||
665 | goto out; | ||
666 | } | ||
667 | |||
668 | out: | ||
669 | pci_dev_put(func); | ||
670 | return ret; | ||
671 | } | ||
672 | |||
673 | /* | ||
674 | * TI specifiy parts for the power hook. | ||
675 | * | ||
676 | * some TI's with some CB's produces interrupt storm on power on. it has been | ||
677 | * seen with atheros wlan cards on TI1225 and TI1410. solution is simply to | ||
678 | * disable any CB interrupts during this time. | ||
679 | */ | ||
680 | static int ti12xx_power_hook(struct pcmcia_socket *sock, int operation) | ||
681 | { | ||
682 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); | ||
683 | u32 mfunc, devctl, sysctl; | ||
684 | u8 gpio3; | ||
685 | |||
686 | /* only POWER_PRE and POWER_POST are interesting */ | ||
687 | if ((operation != HOOK_POWER_PRE) && (operation != HOOK_POWER_POST)) | ||
688 | return 0; | ||
689 | |||
690 | devctl = config_readb(socket, TI113X_DEVICE_CONTROL); | ||
691 | sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL); | ||
692 | mfunc = config_readl(socket, TI122X_MFUNC); | ||
693 | |||
694 | /* | ||
695 | * all serial/tied: only disable when modparm set. always doing it | ||
696 | * would mean a regression for working setups 'cos it disables the | ||
697 | * interrupts for both both slots on 2-slot controllers | ||
698 | * (and users of single slot controllers where it's save have to | ||
699 | * live with setting the modparm, most don't have to anyway) | ||
700 | */ | ||
701 | if (((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) && | ||
702 | (pwr_irqs_off || ti12xx_2nd_slot_empty(socket))) { | ||
703 | switch (socket->dev->device) { | ||
704 | case PCI_DEVICE_ID_TI_1250: | ||
705 | case PCI_DEVICE_ID_TI_1251A: | ||
706 | case PCI_DEVICE_ID_TI_1251B: | ||
707 | case PCI_DEVICE_ID_TI_1450: | ||
708 | case PCI_DEVICE_ID_TI_1451A: | ||
709 | case PCI_DEVICE_ID_TI_4450: | ||
710 | case PCI_DEVICE_ID_TI_4451: | ||
711 | /* these chips have no IRQSER setting in MFUNC3 */ | ||
712 | break; | ||
713 | |||
714 | default: | ||
715 | if (operation == HOOK_POWER_PRE) | ||
716 | mfunc = (mfunc & ~TI122X_MFUNC3_MASK); | ||
717 | else | ||
718 | mfunc = (mfunc & ~TI122X_MFUNC3_MASK) | TI122X_MFUNC3_IRQSER; | ||
719 | } | ||
720 | |||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | /* do the job differently for func0/1 */ | ||
725 | if ((PCI_FUNC(socket->dev->devfn) == 0) || | ||
726 | ((sysctl & TI122X_SCR_INTRTIE) && | ||
727 | (pwr_irqs_off || ti12xx_2nd_slot_empty(socket)))) { | ||
728 | /* some bridges are different */ | ||
729 | switch (socket->dev->device) { | ||
730 | case PCI_DEVICE_ID_TI_1250: | ||
731 | case PCI_DEVICE_ID_TI_1251A: | ||
732 | case PCI_DEVICE_ID_TI_1251B: | ||
733 | case PCI_DEVICE_ID_TI_1450: | ||
734 | /* those oldies use gpio3 for INTA */ | ||
735 | gpio3 = config_readb(socket, TI1250_GPIO3_CONTROL); | ||
736 | if (operation == HOOK_POWER_PRE) | ||
737 | gpio3 = (gpio3 & ~TI1250_GPIO_MODE_MASK) | 0x40; | ||
738 | else | ||
739 | gpio3 &= ~TI1250_GPIO_MODE_MASK; | ||
740 | config_writeb(socket, TI1250_GPIO3_CONTROL, gpio3); | ||
741 | break; | ||
742 | |||
743 | default: | ||
744 | /* all new bridges are the same */ | ||
745 | if (operation == HOOK_POWER_PRE) | ||
746 | mfunc &= ~TI122X_MFUNC0_MASK; | ||
747 | else | ||
748 | mfunc |= TI122X_MFUNC0_INTA; | ||
749 | config_writel(socket, TI122X_MFUNC, mfunc); | ||
750 | } | ||
751 | } else { | ||
752 | switch (socket->dev->device) { | ||
753 | case PCI_DEVICE_ID_TI_1251A: | ||
754 | case PCI_DEVICE_ID_TI_1251B: | ||
755 | case PCI_DEVICE_ID_TI_1450: | ||
756 | /* those have INTA elsewhere and INTB in MFUNC0 */ | ||
757 | if (operation == HOOK_POWER_PRE) | ||
758 | mfunc &= ~TI122X_MFUNC0_MASK; | ||
759 | else | ||
760 | mfunc |= TI125X_MFUNC0_INTB; | ||
761 | config_writel(socket, TI122X_MFUNC, mfunc); | ||
762 | |||
763 | break; | ||
764 | |||
765 | default: | ||
766 | /* all new bridges are the same */ | ||
767 | if (operation == HOOK_POWER_PRE) | ||
768 | mfunc &= ~TI122X_MFUNC1_MASK; | ||
769 | else | ||
770 | mfunc |= TI122X_MFUNC1_INTB; | ||
771 | config_writel(socket, TI122X_MFUNC, mfunc); | ||
772 | } | ||
773 | } | ||
774 | |||
775 | return 0; | ||
776 | } | ||
777 | |||
614 | static int ti12xx_override(struct yenta_socket *socket) | 778 | static int ti12xx_override(struct yenta_socket *socket) |
615 | { | 779 | { |
616 | u32 val, val_orig; | 780 | u32 val, val_orig; |
@@ -654,6 +818,9 @@ static int ti12xx_override(struct yenta_socket *socket) | |||
654 | else | 818 | else |
655 | ti12xx_irqroute_func1(socket); | 819 | ti12xx_irqroute_func1(socket); |
656 | 820 | ||
821 | /* install power hook */ | ||
822 | socket->socket.power_hook = ti12xx_power_hook; | ||
823 | |||
657 | return ti_override(socket); | 824 | return ti_override(socket); |
658 | } | 825 | } |
659 | 826 | ||
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 6404d97a12..bee05362fd 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -32,6 +32,14 @@ static int disable_clkrun; | |||
32 | module_param(disable_clkrun, bool, 0444); | 32 | module_param(disable_clkrun, bool, 0444); |
33 | MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option"); | 33 | MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option"); |
34 | 34 | ||
35 | static int isa_probe = 1; | ||
36 | module_param(isa_probe, bool, 0444); | ||
37 | MODULE_PARM_DESC(isa_probe, "If set ISA interrupts are probed (default). Set to N to disable probing"); | ||
38 | |||
39 | static int pwr_irqs_off; | ||
40 | module_param(pwr_irqs_off, bool, 0644); | ||
41 | MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!"); | ||
42 | |||
35 | #if 0 | 43 | #if 0 |
36 | #define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args) | 44 | #define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args) |
37 | #else | 45 | #else |
@@ -150,15 +158,16 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value) | |||
150 | 158 | ||
151 | val = (state & CB_3VCARD) ? SS_3VCARD : 0; | 159 | val = (state & CB_3VCARD) ? SS_3VCARD : 0; |
152 | val |= (state & CB_XVCARD) ? SS_XVCARD : 0; | 160 | val |= (state & CB_XVCARD) ? SS_XVCARD : 0; |
153 | val |= (state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | CB_3VCARD | 161 | val |= (state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING; |
154 | | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING; | 162 | val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? SS_PENDING : 0; |
163 | |||
155 | 164 | ||
156 | if (state & CB_CBCARD) { | 165 | if (state & CB_CBCARD) { |
157 | val |= SS_CARDBUS; | 166 | val |= SS_CARDBUS; |
158 | val |= (state & CB_CARDSTS) ? SS_STSCHG : 0; | 167 | val |= (state & CB_CARDSTS) ? SS_STSCHG : 0; |
159 | val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT; | 168 | val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT; |
160 | val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0; | 169 | val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0; |
161 | } else { | 170 | } else if (state & CB_16BITCARD) { |
162 | u8 status = exca_readb(socket, I365_STATUS); | 171 | u8 status = exca_readb(socket, I365_STATUS); |
163 | val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; | 172 | val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; |
164 | if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { | 173 | if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { |
@@ -405,11 +414,13 @@ static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map * | |||
405 | } | 414 | } |
406 | 415 | ||
407 | 416 | ||
408 | static unsigned int yenta_events(struct yenta_socket *socket) | 417 | |
418 | static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
409 | { | 419 | { |
420 | unsigned int events; | ||
421 | struct yenta_socket *socket = (struct yenta_socket *) dev_id; | ||
410 | u8 csc; | 422 | u8 csc; |
411 | u32 cb_event; | 423 | u32 cb_event; |
412 | unsigned int events; | ||
413 | 424 | ||
414 | /* Clear interrupt status for the event */ | 425 | /* Clear interrupt status for the event */ |
415 | cb_event = cb_readl(socket, CB_SOCKET_EVENT); | 426 | cb_event = cb_readl(socket, CB_SOCKET_EVENT); |
@@ -426,20 +437,13 @@ static unsigned int yenta_events(struct yenta_socket *socket) | |||
426 | events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; | 437 | events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; |
427 | events |= (csc & I365_CSC_READY) ? SS_READY : 0; | 438 | events |= (csc & I365_CSC_READY) ? SS_READY : 0; |
428 | } | 439 | } |
429 | return events; | ||
430 | } | ||
431 | |||
432 | |||
433 | static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
434 | { | ||
435 | unsigned int events; | ||
436 | struct yenta_socket *socket = (struct yenta_socket *) dev_id; | ||
437 | 440 | ||
438 | events = yenta_events(socket); | 441 | if (events) |
439 | if (events) { | ||
440 | pcmcia_parse_events(&socket->socket, events); | 442 | pcmcia_parse_events(&socket->socket, events); |
443 | |||
444 | if (cb_event || csc) | ||
441 | return IRQ_HANDLED; | 445 | return IRQ_HANDLED; |
442 | } | 446 | |
443 | return IRQ_NONE; | 447 | return IRQ_NONE; |
444 | } | 448 | } |
445 | 449 | ||
@@ -470,11 +474,22 @@ static void yenta_clear_maps(struct yenta_socket *socket) | |||
470 | } | 474 | } |
471 | } | 475 | } |
472 | 476 | ||
477 | /* redoes voltage interrogation if required */ | ||
478 | static void yenta_interrogate(struct yenta_socket *socket) | ||
479 | { | ||
480 | u32 state; | ||
481 | |||
482 | state = cb_readl(socket, CB_SOCKET_STATE); | ||
483 | if (!(state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) || | ||
484 | (state & (CB_CDETECT1 | CB_CDETECT2 | CB_NOTACARD | CB_BADVCCREQ)) || | ||
485 | ((state & (CB_16BITCARD | CB_CBCARD)) == (CB_16BITCARD | CB_CBCARD))) | ||
486 | cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); | ||
487 | } | ||
488 | |||
473 | /* Called at resume and initialization events */ | 489 | /* Called at resume and initialization events */ |
474 | static int yenta_sock_init(struct pcmcia_socket *sock) | 490 | static int yenta_sock_init(struct pcmcia_socket *sock) |
475 | { | 491 | { |
476 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); | 492 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); |
477 | u32 state; | ||
478 | u16 bridge; | 493 | u16 bridge; |
479 | 494 | ||
480 | bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR; | 495 | bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR; |
@@ -486,10 +501,7 @@ static int yenta_sock_init(struct pcmcia_socket *sock) | |||
486 | exca_writeb(socket, I365_GENCTL, 0x00); | 501 | exca_writeb(socket, I365_GENCTL, 0x00); |
487 | 502 | ||
488 | /* Redo card voltage interrogation */ | 503 | /* Redo card voltage interrogation */ |
489 | state = cb_readl(socket, CB_SOCKET_STATE); | 504 | yenta_interrogate(socket); |
490 | if (!(state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | | ||
491 | CB_3VCARD | CB_XVCARD | CB_YVCARD))) | ||
492 | cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); | ||
493 | 505 | ||
494 | yenta_clear_maps(socket); | 506 | yenta_clear_maps(socket); |
495 | 507 | ||
@@ -856,7 +868,10 @@ static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_i | |||
856 | socket->socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS; | 868 | socket->socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS; |
857 | socket->socket.map_size = 0x1000; | 869 | socket->socket.map_size = 0x1000; |
858 | socket->socket.pci_irq = socket->cb_irq; | 870 | socket->socket.pci_irq = socket->cb_irq; |
859 | socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask); | 871 | if (isa_probe) |
872 | socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask); | ||
873 | else | ||
874 | socket->socket.irq_mask = 0; | ||
860 | socket->socket.cb_dev = socket->dev; | 875 | socket->socket.cb_dev = socket->dev; |
861 | 876 | ||
862 | printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n", | 877 | printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n", |
@@ -996,6 +1011,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i | |||
996 | } | 1011 | } |
997 | 1012 | ||
998 | /* Figure out what the dang thing can do for the PCMCIA layer... */ | 1013 | /* Figure out what the dang thing can do for the PCMCIA layer... */ |
1014 | yenta_interrogate(socket); | ||
999 | yenta_get_socket_capabilities(socket, isa_interrupts); | 1015 | yenta_get_socket_capabilities(socket, isa_interrupts); |
1000 | printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); | 1016 | printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); |
1001 | 1017 | ||
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index 3252662958..add12f7c48 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c | |||
@@ -259,7 +259,6 @@ int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev) | |||
259 | 259 | ||
260 | /** | 260 | /** |
261 | * pnp_remove_card_device- removes a device from the specified card | 261 | * pnp_remove_card_device- removes a device from the specified card |
262 | * @card: pointer to the card to remove from | ||
263 | * @dev: pointer to the device to remove | 262 | * @dev: pointer to the device to remove |
264 | */ | 263 | */ |
265 | 264 | ||
@@ -274,7 +273,7 @@ void pnp_remove_card_device(struct pnp_dev * dev) | |||
274 | 273 | ||
275 | /** | 274 | /** |
276 | * pnp_request_card_device - Searches for a PnP device under the specified card | 275 | * pnp_request_card_device - Searches for a PnP device under the specified card |
277 | * @lcard: pointer to the card link, cannot be NULL | 276 | * @clink: pointer to the card link, cannot be NULL |
278 | * @id: pointer to a PnP ID structure that explains the rules for finding the device | 277 | * @id: pointer to a PnP ID structure that explains the rules for finding the device |
279 | * @from: Starting place to search from. If NULL it will start from the begining. | 278 | * @from: Starting place to search from. If NULL it will start from the begining. |
280 | */ | 279 | */ |
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 65ecef7385..6c510c19ad 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c | |||
@@ -390,6 +390,7 @@ fail: | |||
390 | * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table | 390 | * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table |
391 | * @dev: pointer to the desired device | 391 | * @dev: pointer to the desired device |
392 | * @res: pointer to the new resource config | 392 | * @res: pointer to the new resource config |
393 | * @mode: 0 or PNP_CONFIG_FORCE | ||
393 | * | 394 | * |
394 | * This function can be used by drivers that want to manually set thier resources. | 395 | * This function can be used by drivers that want to manually set thier resources. |
395 | */ | 396 | */ |
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 16ab8d363a..6bc27d5232 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
@@ -35,14 +35,17 @@ | |||
35 | static int dcssblk_open(struct inode *inode, struct file *filp); | 35 | static int dcssblk_open(struct inode *inode, struct file *filp); |
36 | static int dcssblk_release(struct inode *inode, struct file *filp); | 36 | static int dcssblk_release(struct inode *inode, struct file *filp); |
37 | static int dcssblk_make_request(struct request_queue *q, struct bio *bio); | 37 | static int dcssblk_make_request(struct request_queue *q, struct bio *bio); |
38 | static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum, | ||
39 | unsigned long *data); | ||
38 | 40 | ||
39 | static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0"; | 41 | static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0"; |
40 | 42 | ||
41 | static int dcssblk_major; | 43 | static int dcssblk_major; |
42 | static struct block_device_operations dcssblk_devops = { | 44 | static struct block_device_operations dcssblk_devops = { |
43 | .owner = THIS_MODULE, | 45 | .owner = THIS_MODULE, |
44 | .open = dcssblk_open, | 46 | .open = dcssblk_open, |
45 | .release = dcssblk_release, | 47 | .release = dcssblk_release, |
48 | .direct_access = dcssblk_direct_access, | ||
46 | }; | 49 | }; |
47 | 50 | ||
48 | static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf, | 51 | static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf, |
@@ -641,6 +644,20 @@ dcssblk_make_request(request_queue_t *q, struct bio *bio) | |||
641 | /* Request beyond end of DCSS segment. */ | 644 | /* Request beyond end of DCSS segment. */ |
642 | goto fail; | 645 | goto fail; |
643 | } | 646 | } |
647 | /* verify data transfer direction */ | ||
648 | if (dev_info->is_shared) { | ||
649 | switch (dev_info->segment_type) { | ||
650 | case SEG_TYPE_SR: | ||
651 | case SEG_TYPE_ER: | ||
652 | case SEG_TYPE_SC: | ||
653 | /* cannot write to these segments */ | ||
654 | if (bio_data_dir(bio) == WRITE) { | ||
655 | PRINT_WARN("rejecting write to ro segment %s\n", dev_info->dev.bus_id); | ||
656 | goto fail; | ||
657 | } | ||
658 | } | ||
659 | } | ||
660 | |||
644 | index = (bio->bi_sector >> 3); | 661 | index = (bio->bi_sector >> 3); |
645 | bio_for_each_segment(bvec, bio, i) { | 662 | bio_for_each_segment(bvec, bio, i) { |
646 | page_addr = (unsigned long) | 663 | page_addr = (unsigned long) |
@@ -661,7 +678,26 @@ dcssblk_make_request(request_queue_t *q, struct bio *bio) | |||
661 | bio_endio(bio, bytes_done, 0); | 678 | bio_endio(bio, bytes_done, 0); |
662 | return 0; | 679 | return 0; |
663 | fail: | 680 | fail: |
664 | bio_io_error(bio, bytes_done); | 681 | bio_io_error(bio, bio->bi_size); |
682 | return 0; | ||
683 | } | ||
684 | |||
685 | static int | ||
686 | dcssblk_direct_access (struct block_device *bdev, sector_t secnum, | ||
687 | unsigned long *data) | ||
688 | { | ||
689 | struct dcssblk_dev_info *dev_info; | ||
690 | unsigned long pgoff; | ||
691 | |||
692 | dev_info = bdev->bd_disk->private_data; | ||
693 | if (!dev_info) | ||
694 | return -ENODEV; | ||
695 | if (secnum % (PAGE_SIZE/512)) | ||
696 | return -EINVAL; | ||
697 | pgoff = secnum / (PAGE_SIZE / 512); | ||
698 | if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start) | ||
699 | return -ERANGE; | ||
700 | *data = (unsigned long) (dev_info->start+pgoff*PAGE_SIZE); | ||
665 | return 0; | 701 | return 0; |
666 | } | 702 | } |
667 | 703 | ||
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 9cc0015b71..a699c30b26 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c | |||
@@ -1126,11 +1126,11 @@ static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout) | |||
1126 | struct adpt_i2o_post_wait_data *p1, *p2; | 1126 | struct adpt_i2o_post_wait_data *p1, *p2; |
1127 | struct adpt_i2o_post_wait_data *wait_data = | 1127 | struct adpt_i2o_post_wait_data *wait_data = |
1128 | kmalloc(sizeof(struct adpt_i2o_post_wait_data),GFP_KERNEL); | 1128 | kmalloc(sizeof(struct adpt_i2o_post_wait_data),GFP_KERNEL); |
1129 | adpt_wait_queue_t wait; | 1129 | DECLARE_WAITQUEUE(wait, current); |
1130 | 1130 | ||
1131 | if(!wait_data){ | 1131 | if (!wait_data) |
1132 | return -ENOMEM; | 1132 | return -ENOMEM; |
1133 | } | 1133 | |
1134 | /* | 1134 | /* |
1135 | * The spin locking is needed to keep anyone from playing | 1135 | * The spin locking is needed to keep anyone from playing |
1136 | * with the queue pointers and id while we do the same | 1136 | * with the queue pointers and id while we do the same |
@@ -1148,12 +1148,7 @@ static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout) | |||
1148 | wait_data->wq = &adpt_wq_i2o_post; | 1148 | wait_data->wq = &adpt_wq_i2o_post; |
1149 | wait_data->status = -ETIMEDOUT; | 1149 | wait_data->status = -ETIMEDOUT; |
1150 | 1150 | ||
1151 | // this code is taken from kernel/sched.c:interruptible_sleep_on_timeout | 1151 | add_wait_queue(&adpt_wq_i2o_post, &wait); |
1152 | wait.task = current; | ||
1153 | init_waitqueue_entry(&wait, current); | ||
1154 | spin_lock_irqsave(&adpt_wq_i2o_post.lock, flags); | ||
1155 | __add_wait_queue(&adpt_wq_i2o_post, &wait); | ||
1156 | spin_unlock(&adpt_wq_i2o_post.lock); | ||
1157 | 1152 | ||
1158 | msg[2] |= 0x80000000 | ((u32)wait_data->id); | 1153 | msg[2] |= 0x80000000 | ((u32)wait_data->id); |
1159 | timeout *= HZ; | 1154 | timeout *= HZ; |
@@ -1175,9 +1170,7 @@ static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout) | |||
1175 | if(pHba->host) | 1170 | if(pHba->host) |
1176 | spin_lock_irq(pHba->host->host_lock); | 1171 | spin_lock_irq(pHba->host->host_lock); |
1177 | } | 1172 | } |
1178 | spin_lock_irq(&adpt_wq_i2o_post.lock); | 1173 | remove_wait_queue(&adpt_wq_i2o_post, &wait); |
1179 | __remove_wait_queue(&adpt_wq_i2o_post, &wait); | ||
1180 | spin_unlock_irqrestore(&adpt_wq_i2o_post.lock, flags); | ||
1181 | 1174 | ||
1182 | if(status == -ETIMEDOUT){ | 1175 | if(status == -ETIMEDOUT){ |
1183 | printk(KERN_INFO"dpti%d: POST WAIT TIMEOUT\n",pHba->unit); | 1176 | printk(KERN_INFO"dpti%d: POST WAIT TIMEOUT\n",pHba->unit); |
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index ba347576d9..d7a38b6713 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -56,7 +56,7 @@ static struct class shost_class = { | |||
56 | * @shost: pointer to struct Scsi_Host | 56 | * @shost: pointer to struct Scsi_Host |
57 | * recovery: recovery requested to run. | 57 | * recovery: recovery requested to run. |
58 | **/ | 58 | **/ |
59 | void scsi_host_cancel(struct Scsi_Host *shost, int recovery) | 59 | static void scsi_host_cancel(struct Scsi_Host *shost, int recovery) |
60 | { | 60 | { |
61 | struct scsi_device *sdev; | 61 | struct scsi_device *sdev; |
62 | 62 | ||
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 5578ae9a9e..1cb5f7d4f2 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -68,6 +68,8 @@ | |||
68 | #include "scsi_priv.h" | 68 | #include "scsi_priv.h" |
69 | #include "scsi_logging.h" | 69 | #include "scsi_logging.h" |
70 | 70 | ||
71 | static void scsi_done(struct scsi_cmnd *cmd); | ||
72 | static int scsi_retry_command(struct scsi_cmnd *cmd); | ||
71 | 73 | ||
72 | /* | 74 | /* |
73 | * Definitions and constants. | 75 | * Definitions and constants. |
@@ -741,7 +743,7 @@ static DEFINE_PER_CPU(struct list_head, scsi_done_q); | |||
741 | * | 743 | * |
742 | * This function is interrupt context safe. | 744 | * This function is interrupt context safe. |
743 | */ | 745 | */ |
744 | void scsi_done(struct scsi_cmnd *cmd) | 746 | static void scsi_done(struct scsi_cmnd *cmd) |
745 | { | 747 | { |
746 | /* | 748 | /* |
747 | * We don't have to worry about this one timing out any more. | 749 | * We don't have to worry about this one timing out any more. |
@@ -836,7 +838,7 @@ static void scsi_softirq(struct softirq_action *h) | |||
836 | * level drivers should not become re-entrant as a result of | 838 | * level drivers should not become re-entrant as a result of |
837 | * this. | 839 | * this. |
838 | */ | 840 | */ |
839 | int scsi_retry_command(struct scsi_cmnd *cmd) | 841 | static int scsi_retry_command(struct scsi_cmnd *cmd) |
840 | { | 842 | { |
841 | /* | 843 | /* |
842 | * Restore the SCSI command state. | 844 | * Restore the SCSI command state. |
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index e0208886b4..322b5a41a3 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -1783,7 +1783,7 @@ static void __exit scsi_debug_exit(void) | |||
1783 | device_initcall(scsi_debug_init); | 1783 | device_initcall(scsi_debug_init); |
1784 | module_exit(scsi_debug_exit); | 1784 | module_exit(scsi_debug_exit); |
1785 | 1785 | ||
1786 | void pseudo_0_release(struct device * dev) | 1786 | static void pseudo_0_release(struct device * dev) |
1787 | { | 1787 | { |
1788 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 1788 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
1789 | printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n"); | 1789 | printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n"); |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9f996499fa..621dee8b8c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -44,7 +44,7 @@ struct scsi_host_sg_pool { | |||
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | #define SP(x) { x, "sgpool-" #x } | 46 | #define SP(x) { x, "sgpool-" #x } |
47 | struct scsi_host_sg_pool scsi_sg_pools[] = { | 47 | static struct scsi_host_sg_pool scsi_sg_pools[] = { |
48 | SP(8), | 48 | SP(8), |
49 | SP(16), | 49 | SP(16), |
50 | SP(32), | 50 | SP(32), |
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index c01580df44..96d4f74597 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h | |||
@@ -61,8 +61,6 @@ extern void scsi_exit_hosts(void); | |||
61 | extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); | 61 | extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); |
62 | extern int scsi_setup_command_freelist(struct Scsi_Host *shost); | 62 | extern int scsi_setup_command_freelist(struct Scsi_Host *shost); |
63 | extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); | 63 | extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); |
64 | extern void scsi_done(struct scsi_cmnd *cmd); | ||
65 | extern int scsi_retry_command(struct scsi_cmnd *cmd); | ||
66 | extern int scsi_insert_special_req(struct scsi_request *sreq, int); | 64 | extern int scsi_insert_special_req(struct scsi_request *sreq, int); |
67 | extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, | 65 | extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, |
68 | struct scsi_request *sreq); | 66 | struct scsi_request *sreq); |
@@ -136,7 +134,6 @@ extern void scsi_exit_sysctl(void); | |||
136 | #endif /* CONFIG_SYSCTL */ | 134 | #endif /* CONFIG_SYSCTL */ |
137 | 135 | ||
138 | /* scsi_sysfs.c */ | 136 | /* scsi_sysfs.c */ |
139 | extern void scsi_device_dev_release(struct device *); | ||
140 | extern int scsi_sysfs_add_sdev(struct scsi_device *); | 137 | extern int scsi_sysfs_add_sdev(struct scsi_device *); |
141 | extern int scsi_sysfs_add_host(struct Scsi_Host *); | 138 | extern int scsi_sysfs_add_host(struct Scsi_Host *); |
142 | extern int scsi_sysfs_register(void); | 139 | extern int scsi_sysfs_register(void); |
@@ -145,7 +142,6 @@ extern void scsi_sysfs_device_initialize(struct scsi_device *); | |||
145 | extern int scsi_sysfs_target_initialize(struct scsi_device *); | 142 | extern int scsi_sysfs_target_initialize(struct scsi_device *); |
146 | extern struct scsi_transport_template blank_transport_template; | 143 | extern struct scsi_transport_template blank_transport_template; |
147 | 144 | ||
148 | extern struct class sdev_class; | ||
149 | extern struct bus_type scsi_bus_type; | 145 | extern struct bus_type scsi_bus_type; |
150 | 146 | ||
151 | /* | 147 | /* |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 93b41100a6..beed7fbe1c 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -150,7 +150,7 @@ static void scsi_device_cls_release(struct class_device *class_dev) | |||
150 | put_device(&sdev->sdev_gendev); | 150 | put_device(&sdev->sdev_gendev); |
151 | } | 151 | } |
152 | 152 | ||
153 | void scsi_device_dev_release(struct device *dev) | 153 | static void scsi_device_dev_release(struct device *dev) |
154 | { | 154 | { |
155 | struct scsi_device *sdev; | 155 | struct scsi_device *sdev; |
156 | struct device *parent; | 156 | struct device *parent; |
@@ -185,7 +185,7 @@ void scsi_device_dev_release(struct device *dev) | |||
185 | put_device(parent); | 185 | put_device(parent); |
186 | } | 186 | } |
187 | 187 | ||
188 | struct class sdev_class = { | 188 | static struct class sdev_class = { |
189 | .name = "scsi_device", | 189 | .name = "scsi_device", |
190 | .release = scsi_device_cls_release, | 190 | .release = scsi_device_cls_release, |
191 | }; | 191 | }; |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 30e8beb714..d8b9d2b8c2 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -132,9 +132,9 @@ struct uart_8250_port { | |||
132 | struct uart_port port; | 132 | struct uart_port port; |
133 | struct timer_list timer; /* "no irq" timer */ | 133 | struct timer_list timer; /* "no irq" timer */ |
134 | struct list_head list; /* ports on this IRQ */ | 134 | struct list_head list; /* ports on this IRQ */ |
135 | unsigned int capabilities; /* port capabilities */ | 135 | unsigned short capabilities; /* port capabilities */ |
136 | unsigned short bugs; /* port bugs */ | ||
136 | unsigned int tx_loadsz; /* transmit fifo load size */ | 137 | unsigned int tx_loadsz; /* transmit fifo load size */ |
137 | unsigned short rev; | ||
138 | unsigned char acr; | 138 | unsigned char acr; |
139 | unsigned char ier; | 139 | unsigned char ier; |
140 | unsigned char lcr; | 140 | unsigned char lcr; |
@@ -560,7 +560,14 @@ static void autoconfig_has_efr(struct uart_8250_port *up) | |||
560 | if (id1 == 0x16 && id2 == 0xC9 && | 560 | if (id1 == 0x16 && id2 == 0xC9 && |
561 | (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) { | 561 | (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) { |
562 | up->port.type = PORT_16C950; | 562 | up->port.type = PORT_16C950; |
563 | up->rev = rev | (id3 << 8); | 563 | |
564 | /* | ||
565 | * Enable work around for the Oxford Semiconductor 952 rev B | ||
566 | * chip which causes it to seriously miscalculate baud rates | ||
567 | * when DLL is 0. | ||
568 | */ | ||
569 | if (id3 == 0x52 && rev == 0x01) | ||
570 | up->bugs |= UART_BUG_QUOT; | ||
564 | return; | 571 | return; |
565 | } | 572 | } |
566 | 573 | ||
@@ -577,8 +584,6 @@ static void autoconfig_has_efr(struct uart_8250_port *up) | |||
577 | 584 | ||
578 | id2 = id1 >> 8; | 585 | id2 = id1 >> 8; |
579 | if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) { | 586 | if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) { |
580 | if (id2 == 0x10) | ||
581 | up->rev = id1 & 255; | ||
582 | up->port.type = PORT_16850; | 587 | up->port.type = PORT_16850; |
583 | return; | 588 | return; |
584 | } | 589 | } |
@@ -809,6 +814,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | |||
809 | // save_flags(flags); cli(); | 814 | // save_flags(flags); cli(); |
810 | 815 | ||
811 | up->capabilities = 0; | 816 | up->capabilities = 0; |
817 | up->bugs = 0; | ||
812 | 818 | ||
813 | if (!(up->port.flags & UPF_BUGGY_UART)) { | 819 | if (!(up->port.flags & UPF_BUGGY_UART)) { |
814 | /* | 820 | /* |
@@ -1021,6 +1027,8 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
1021 | } | 1027 | } |
1022 | } | 1028 | } |
1023 | 1029 | ||
1030 | static void transmit_chars(struct uart_8250_port *up); | ||
1031 | |||
1024 | static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start) | 1032 | static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start) |
1025 | { | 1033 | { |
1026 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 1034 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
@@ -1028,6 +1036,14 @@ static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start) | |||
1028 | if (!(up->ier & UART_IER_THRI)) { | 1036 | if (!(up->ier & UART_IER_THRI)) { |
1029 | up->ier |= UART_IER_THRI; | 1037 | up->ier |= UART_IER_THRI; |
1030 | serial_out(up, UART_IER, up->ier); | 1038 | serial_out(up, UART_IER, up->ier); |
1039 | |||
1040 | if (up->bugs & UART_BUG_TXEN) { | ||
1041 | unsigned char lsr, iir; | ||
1042 | lsr = serial_in(up, UART_LSR); | ||
1043 | iir = serial_in(up, UART_IIR); | ||
1044 | if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) | ||
1045 | transmit_chars(up); | ||
1046 | } | ||
1031 | } | 1047 | } |
1032 | /* | 1048 | /* |
1033 | * We only do this from uart_start | 1049 | * We only do this from uart_start |
@@ -1433,6 +1449,7 @@ static int serial8250_startup(struct uart_port *port) | |||
1433 | { | 1449 | { |
1434 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 1450 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
1435 | unsigned long flags; | 1451 | unsigned long flags; |
1452 | unsigned char lsr, iir; | ||
1436 | int retval; | 1453 | int retval; |
1437 | 1454 | ||
1438 | up->capabilities = uart_config[up->port.type].flags; | 1455 | up->capabilities = uart_config[up->port.type].flags; |
@@ -1536,6 +1553,26 @@ static int serial8250_startup(struct uart_port *port) | |||
1536 | up->port.mctrl |= TIOCM_OUT2; | 1553 | up->port.mctrl |= TIOCM_OUT2; |
1537 | 1554 | ||
1538 | serial8250_set_mctrl(&up->port, up->port.mctrl); | 1555 | serial8250_set_mctrl(&up->port, up->port.mctrl); |
1556 | |||
1557 | /* | ||
1558 | * Do a quick test to see if we receive an | ||
1559 | * interrupt when we enable the TX irq. | ||
1560 | */ | ||
1561 | serial_outp(up, UART_IER, UART_IER_THRI); | ||
1562 | lsr = serial_in(up, UART_LSR); | ||
1563 | iir = serial_in(up, UART_IIR); | ||
1564 | serial_outp(up, UART_IER, 0); | ||
1565 | |||
1566 | if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { | ||
1567 | if (!(up->bugs & UART_BUG_TXEN)) { | ||
1568 | up->bugs |= UART_BUG_TXEN; | ||
1569 | pr_debug("ttyS%d - enabling bad tx status workarounds\n", | ||
1570 | port->line); | ||
1571 | } | ||
1572 | } else { | ||
1573 | up->bugs &= ~UART_BUG_TXEN; | ||
1574 | } | ||
1575 | |||
1539 | spin_unlock_irqrestore(&up->port.lock, flags); | 1576 | spin_unlock_irqrestore(&up->port.lock, flags); |
1540 | 1577 | ||
1541 | /* | 1578 | /* |
@@ -1645,22 +1682,22 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, | |||
1645 | 1682 | ||
1646 | switch (termios->c_cflag & CSIZE) { | 1683 | switch (termios->c_cflag & CSIZE) { |
1647 | case CS5: | 1684 | case CS5: |
1648 | cval = 0x00; | 1685 | cval = UART_LCR_WLEN5; |
1649 | break; | 1686 | break; |
1650 | case CS6: | 1687 | case CS6: |
1651 | cval = 0x01; | 1688 | cval = UART_LCR_WLEN6; |
1652 | break; | 1689 | break; |
1653 | case CS7: | 1690 | case CS7: |
1654 | cval = 0x02; | 1691 | cval = UART_LCR_WLEN7; |
1655 | break; | 1692 | break; |
1656 | default: | 1693 | default: |
1657 | case CS8: | 1694 | case CS8: |
1658 | cval = 0x03; | 1695 | cval = UART_LCR_WLEN8; |
1659 | break; | 1696 | break; |
1660 | } | 1697 | } |
1661 | 1698 | ||
1662 | if (termios->c_cflag & CSTOPB) | 1699 | if (termios->c_cflag & CSTOPB) |
1663 | cval |= 0x04; | 1700 | cval |= UART_LCR_STOP; |
1664 | if (termios->c_cflag & PARENB) | 1701 | if (termios->c_cflag & PARENB) |
1665 | cval |= UART_LCR_PARITY; | 1702 | cval |= UART_LCR_PARITY; |
1666 | if (!(termios->c_cflag & PARODD)) | 1703 | if (!(termios->c_cflag & PARODD)) |
@@ -1677,12 +1714,9 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, | |||
1677 | quot = serial8250_get_divisor(port, baud); | 1714 | quot = serial8250_get_divisor(port, baud); |
1678 | 1715 | ||
1679 | /* | 1716 | /* |
1680 | * Work around a bug in the Oxford Semiconductor 952 rev B | 1717 | * Oxford Semi 952 rev B workaround |
1681 | * chip which causes it to seriously miscalculate baud rates | ||
1682 | * when DLL is 0. | ||
1683 | */ | 1718 | */ |
1684 | if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 && | 1719 | if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0) |
1685 | up->rev == 0x5201) | ||
1686 | quot ++; | 1720 | quot ++; |
1687 | 1721 | ||
1688 | if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) { | 1722 | if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) { |
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index 4f3d62f222..9225c82fae 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h | |||
@@ -51,6 +51,9 @@ struct serial8250_config { | |||
51 | #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ | 51 | #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ |
52 | #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ | 52 | #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ |
53 | 53 | ||
54 | #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ | ||
55 | #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ | ||
56 | |||
54 | #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) | 57 | #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) |
55 | #define _INLINE_ inline | 58 | #define _INLINE_ inline |
56 | #else | 59 | #else |
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index b6d3d50349..5400dc2c08 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c | |||
@@ -773,22 +773,22 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, | |||
773 | 773 | ||
774 | switch (termios->c_cflag & CSIZE) { | 774 | switch (termios->c_cflag & CSIZE) { |
775 | case CS5: | 775 | case CS5: |
776 | cval = 0x00; | 776 | cval = UART_LCR_WLEN5; |
777 | break; | 777 | break; |
778 | case CS6: | 778 | case CS6: |
779 | cval = 0x01; | 779 | cval = UART_LCR_WLEN6; |
780 | break; | 780 | break; |
781 | case CS7: | 781 | case CS7: |
782 | cval = 0x02; | 782 | cval = UART_LCR_WLEN7; |
783 | break; | 783 | break; |
784 | default: | 784 | default: |
785 | case CS8: | 785 | case CS8: |
786 | cval = 0x03; | 786 | cval = UART_LCR_WLEN8; |
787 | break; | 787 | break; |
788 | } | 788 | } |
789 | 789 | ||
790 | if (termios->c_cflag & CSTOPB) | 790 | if (termios->c_cflag & CSTOPB) |
791 | cval |= 0x04; | 791 | cval |= UART_LCR_STOP; |
792 | if (termios->c_cflag & PARENB) | 792 | if (termios->c_cflag & PARENB) |
793 | cval |= UART_LCR_PARITY; | 793 | cval |= UART_LCR_PARITY; |
794 | if (!(termios->c_cflag & PARODD)) | 794 | if (!(termios->c_cflag & PARODD)) |
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 08d61f13ed..0301feacbd 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c | |||
@@ -724,22 +724,22 @@ static void m32r_sio_set_termios(struct uart_port *port, | |||
724 | 724 | ||
725 | switch (termios->c_cflag & CSIZE) { | 725 | switch (termios->c_cflag & CSIZE) { |
726 | case CS5: | 726 | case CS5: |
727 | cval = 0x00; | 727 | cval = UART_LCR_WLEN5; |
728 | break; | 728 | break; |
729 | case CS6: | 729 | case CS6: |
730 | cval = 0x01; | 730 | cval = UART_LCR_WLEN6; |
731 | break; | 731 | break; |
732 | case CS7: | 732 | case CS7: |
733 | cval = 0x02; | 733 | cval = UART_LCR_WLEN7; |
734 | break; | 734 | break; |
735 | default: | 735 | default: |
736 | case CS8: | 736 | case CS8: |
737 | cval = 0x03; | 737 | cval = UART_LCR_WLEN8; |
738 | break; | 738 | break; |
739 | } | 739 | } |
740 | 740 | ||
741 | if (termios->c_cflag & CSTOPB) | 741 | if (termios->c_cflag & CSTOPB) |
742 | cval |= 0x04; | 742 | cval |= UART_LCR_STOP; |
743 | if (termios->c_cflag & PARENB) | 743 | if (termios->c_cflag & PARENB) |
744 | cval |= UART_LCR_PARITY; | 744 | cval |= UART_LCR_PARITY; |
745 | if (!(termios->c_cflag & PARODD)) | 745 | if (!(termios->c_cflag & PARODD)) |
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 9dc151d8fa..08b08d6ae9 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c | |||
@@ -455,22 +455,22 @@ serial_pxa_set_termios(struct uart_port *port, struct termios *termios, | |||
455 | 455 | ||
456 | switch (termios->c_cflag & CSIZE) { | 456 | switch (termios->c_cflag & CSIZE) { |
457 | case CS5: | 457 | case CS5: |
458 | cval = 0x00; | 458 | cval = UART_LCR_WLEN5; |
459 | break; | 459 | break; |
460 | case CS6: | 460 | case CS6: |
461 | cval = 0x01; | 461 | cval = UART_LCR_WLEN6; |
462 | break; | 462 | break; |
463 | case CS7: | 463 | case CS7: |
464 | cval = 0x02; | 464 | cval = UART_LCR_WLEN7; |
465 | break; | 465 | break; |
466 | default: | 466 | default: |
467 | case CS8: | 467 | case CS8: |
468 | cval = 0x03; | 468 | cval = UART_LCR_WLEN8; |
469 | break; | 469 | break; |
470 | } | 470 | } |
471 | 471 | ||
472 | if (termios->c_cflag & CSTOPB) | 472 | if (termios->c_cflag & CSTOPB) |
473 | cval |= 0x04; | 473 | cval |= UART_LCR_STOP; |
474 | if (termios->c_cflag & PARENB) | 474 | if (termios->c_cflag & PARENB) |
475 | cval |= UART_LCR_PARITY; | 475 | cval |= UART_LCR_PARITY; |
476 | if (!(termios->c_cflag & PARODD)) | 476 | if (!(termios->c_cflag & PARODD)) |
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 2a9f7ade2c..5c4678478b 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c | |||
@@ -198,7 +198,7 @@ static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port) | |||
198 | 198 | ||
199 | /* translate a port to the device name */ | 199 | /* translate a port to the device name */ |
200 | 200 | ||
201 | static inline char *s3c24xx_serial_portname(struct uart_port *port) | 201 | static inline const char *s3c24xx_serial_portname(struct uart_port *port) |
202 | { | 202 | { |
203 | return to_platform_device(port->dev)->name; | 203 | return to_platform_device(port->dev)->name; |
204 | } | 204 | } |
@@ -903,7 +903,7 @@ static void s3c24xx_serial_release_port(struct uart_port *port) | |||
903 | 903 | ||
904 | static int s3c24xx_serial_request_port(struct uart_port *port) | 904 | static int s3c24xx_serial_request_port(struct uart_port *port) |
905 | { | 905 | { |
906 | char *name = s3c24xx_serial_portname(port); | 906 | const char *name = s3c24xx_serial_portname(port); |
907 | return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY; | 907 | return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY; |
908 | } | 908 | } |
909 | 909 | ||
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index fee6418e84..840815fde4 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c | |||
@@ -572,6 +572,7 @@ static void sn_transmit_chars(struct sn_cons_port *port, int raw) | |||
572 | 572 | ||
573 | if (uart_circ_empty(xmit) || uart_tx_stopped(&port->sc_port)) { | 573 | if (uart_circ_empty(xmit) || uart_tx_stopped(&port->sc_port)) { |
574 | /* Nothing to do. */ | 574 | /* Nothing to do. */ |
575 | ia64_sn_console_intr_disable(SAL_CONSOLE_INTR_XMIT); | ||
575 | return; | 576 | return; |
576 | } | 577 | } |
577 | 578 | ||
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d041782e0c..0da23732e8 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -1794,7 +1794,7 @@ EXPORT_SYMBOL (usb_remove_hcd); | |||
1794 | 1794 | ||
1795 | /*-------------------------------------------------------------------------*/ | 1795 | /*-------------------------------------------------------------------------*/ |
1796 | 1796 | ||
1797 | #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) | 1797 | #if defined(CONFIG_USB_MON) |
1798 | 1798 | ||
1799 | struct usb_mon_operations *mon_ops; | 1799 | struct usb_mon_operations *mon_ops; |
1800 | 1800 | ||
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index f67cf1e634..325a51656c 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -399,7 +399,7 @@ static inline void usbfs_cleanup(void) { } | |||
399 | 399 | ||
400 | /*-------------------------------------------------------------------------*/ | 400 | /*-------------------------------------------------------------------------*/ |
401 | 401 | ||
402 | #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) | 402 | #if defined(CONFIG_USB_MON) |
403 | 403 | ||
404 | struct usb_mon_operations { | 404 | struct usb_mon_operations { |
405 | void (*urb_submit)(struct usb_bus *bus, struct urb *urb); | 405 | void (*urb_submit)(struct usb_bus *bus, struct urb *urb); |
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index f9f9561c6b..c3e3a95d38 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
@@ -453,17 +453,6 @@ static int usbfs_fill_super(struct super_block *sb, void *data, int silent) | |||
453 | return 0; | 453 | return 0; |
454 | } | 454 | } |
455 | 455 | ||
456 | static struct dentry * get_dentry(struct dentry *parent, const char *name) | ||
457 | { | ||
458 | struct qstr qstr; | ||
459 | |||
460 | qstr.name = name; | ||
461 | qstr.len = strlen(name); | ||
462 | qstr.hash = full_name_hash(name,qstr.len); | ||
463 | return lookup_hash(&qstr,parent); | ||
464 | } | ||
465 | |||
466 | |||
467 | /* | 456 | /* |
468 | * fs_create_by_name - create a file, given a name | 457 | * fs_create_by_name - create a file, given a name |
469 | * @name: name of file | 458 | * @name: name of file |
@@ -496,7 +485,7 @@ static int fs_create_by_name (const char *name, mode_t mode, | |||
496 | 485 | ||
497 | *dentry = NULL; | 486 | *dentry = NULL; |
498 | down(&parent->d_inode->i_sem); | 487 | down(&parent->d_inode->i_sem); |
499 | *dentry = get_dentry (parent, name); | 488 | *dentry = lookup_one_len(name, parent, strlen(name)); |
500 | if (!IS_ERR(dentry)) { | 489 | if (!IS_ERR(dentry)) { |
501 | if ((mode & S_IFMT) == S_IFDIR) | 490 | if ((mode & S_IFMT) == S_IFDIR) |
502 | error = usbfs_mkdir (parent->d_inode, *dentry, mode); | 491 | error = usbfs_mkdir (parent->d_inode, *dentry, mode); |
diff --git a/drivers/usb/media/pwc/pwc-uncompress.c b/drivers/usb/media/pwc/pwc-uncompress.c index bc3b1635ea..ef4204eab6 100644 --- a/drivers/usb/media/pwc/pwc-uncompress.c +++ b/drivers/usb/media/pwc/pwc-uncompress.c | |||
@@ -118,9 +118,9 @@ int pwc_decompress(struct pwc_device *pdev) | |||
118 | return -ENXIO; /* No such device or address: missing decompressor */ | 118 | return -ENXIO; /* No such device or address: missing decompressor */ |
119 | } | 119 | } |
120 | 120 | ||
121 | #if 0 | ||
121 | switch (pdev->type) | 122 | switch (pdev->type) |
122 | { | 123 | { |
123 | #if 0 | ||
124 | case 675: | 124 | case 675: |
125 | case 680: | 125 | case 680: |
126 | case 690: | 126 | case 690: |
@@ -128,18 +128,17 @@ int pwc_decompress(struct pwc_device *pdev) | |||
128 | case 730: | 128 | case 730: |
129 | case 740: | 129 | case 740: |
130 | case 750: | 130 | case 750: |
131 | pwc_dec23_decompress(&pdev->image, &pdev->view, &pdev->offset, | 131 | pwc_dec23_decompress(&pdev->image, &pdev->view, |
132 | yuv, image, | 132 | &pdev->offset, yuv, image, flags, |
133 | flags, | ||
134 | pdev->decompress_data, pdev->vbandlength); | 133 | pdev->decompress_data, pdev->vbandlength); |
135 | break; | 134 | break; |
136 | case 645: | 135 | case 645: |
137 | case 646: | 136 | case 646: |
138 | /* TODO & FIXME */ | 137 | /* TODO & FIXME */ |
139 | #endif | 138 | return -ENXIO; /* Missing decompressor */ |
140 | return -ENXIO; /* No such device or address: missing decompressor */ | ||
141 | break; | 139 | break; |
142 | } | 140 | } |
141 | #endif | ||
143 | } | 142 | } |
144 | return 0; | 143 | return 0; |
145 | } | 144 | } |
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig index 4e6152aa5f..777642e26b 100644 --- a/drivers/usb/mon/Kconfig +++ b/drivers/usb/mon/Kconfig | |||
@@ -2,13 +2,9 @@ | |||
2 | # USB Monitor configuration | 2 | # USB Monitor configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | # In normal life, it makes little sense to have usbmon as a module, and in fact | ||
6 | # it is harmful, because there is no way to autoload the module. | ||
7 | # The 'm' option is allowed for hackers who debug the usbmon itself, | ||
8 | # and for those who have usbcore as a module. | ||
9 | config USB_MON | 5 | config USB_MON |
10 | tristate "USB Monitor" | 6 | bool "USB Monitor" |
11 | depends on USB | 7 | depends on USB!=n |
12 | default y | 8 | default y |
13 | help | 9 | help |
14 | If you say Y here, a component which captures the USB traffic | 10 | If you say Y here, a component which captures the USB traffic |
@@ -17,6 +13,5 @@ config USB_MON | |||
17 | Harding's USBMon. | 13 | Harding's USBMon. |
18 | 14 | ||
19 | This is somewhat experimental at this time, but it should be safe, | 15 | This is somewhat experimental at this time, but it should be safe, |
20 | as long as you aren't building this as a module and then removing it. | 16 | as long as you aren't using modular USB and try to remove this |
21 | 17 | module. | |
22 | If unsure, say Y. Do not say M. | ||
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile index 3cff8d444b..f18d10ce91 100644 --- a/drivers/usb/mon/Makefile +++ b/drivers/usb/mon/Makefile | |||
@@ -4,4 +4,4 @@ | |||
4 | 4 | ||
5 | usbmon-objs := mon_main.o mon_stat.o mon_text.o | 5 | usbmon-objs := mon_main.o mon_stat.o mon_text.o |
6 | 6 | ||
7 | obj-$(CONFIG_USB_MON) += usbmon.o | 7 | obj-$(CONFIG_USB) += usbmon.o |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 815fbc8317..16e37a535d 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <asm/io.h> | 43 | #include <asm/io.h> |
44 | #include <asm/irq.h> | 44 | #include <asm/irq.h> |
45 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
46 | #include <asm/div64.h> | ||
46 | #include <asm/arch/pxa-regs.h> | 47 | #include <asm/arch/pxa-regs.h> |
47 | #include <asm/arch/bitfield.h> | 48 | #include <asm/arch/bitfield.h> |
48 | #include <asm/arch/pxafb.h> | 49 | #include <asm/arch/pxafb.h> |
@@ -460,7 +461,7 @@ static inline unsigned int get_pcd(unsigned int pixclock) | |||
460 | * speeds */ | 461 | * speeds */ |
461 | 462 | ||
462 | pcd = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock; | 463 | pcd = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock; |
463 | pcd /= 100000000 * 2; | 464 | do_div(pcd, 100000000 * 2); |
464 | /* no need for this, since we should subtract 1 anyway. they cancel */ | 465 | /* no need for this, since we should subtract 1 anyway. they cancel */ |
465 | /* pcd += 1; */ /* make up for integer math truncations */ | 466 | /* pcd += 1; */ /* make up for integer math truncations */ |
466 | return (unsigned int)pcd; | 467 | return (unsigned int)pcd; |