Commit 55490050df0f5d82ce070be11351c65f7696101c
1 parent
3c776a0791
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
m68k/atari: ARAnyM - Always use physical addresses in NatFeat calls
Pointers passed to ARAnyM NatFeat calls should be physical addresses, not virtual addresses. This worked before because on Atari, physical and virtual kernel addresses are the same, as long as normal kernel memory is concerned. Correct the few remaining places where virtual addresses were used. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Showing 4 changed files with 18 additions and 15 deletions Inline Diff
arch/m68k/emu/natfeat.c
1 | /* | 1 | /* |
2 | * natfeat.c - ARAnyM hardware support via Native Features (natfeats) | 2 | * natfeat.c - ARAnyM hardware support via Native Features (natfeats) |
3 | * | 3 | * |
4 | * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team | 4 | * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team |
5 | * | 5 | * |
6 | * Reworked for Linux by Roman Zippel <zippel@linux-m68k.org> | 6 | * Reworked for Linux by Roman Zippel <zippel@linux-m68k.org> |
7 | * | 7 | * |
8 | * This software may be used and distributed according to the terms of | 8 | * This software may be used and distributed according to the terms of |
9 | * the GNU General Public License (GPL), incorporated herein by reference. | 9 | * the GNU General Public License (GPL), incorporated herein by reference. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/console.h> | 13 | #include <linux/console.h> |
14 | #include <linux/string.h> | 14 | #include <linux/string.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <asm/machdep.h> | 18 | #include <asm/machdep.h> |
19 | #include <asm/natfeat.h> | 19 | #include <asm/natfeat.h> |
20 | 20 | ||
21 | extern long nf_get_id2(const char *feature_name); | 21 | extern long nf_get_id_phys(unsigned long feature_name); |
22 | 22 | ||
23 | asm("\n" | 23 | asm("\n" |
24 | " .global nf_get_id2,nf_call\n" | 24 | " .global nf_get_id_phys,nf_call\n" |
25 | "nf_get_id2:\n" | 25 | "nf_get_id_phys:\n" |
26 | " .short 0x7300\n" | 26 | " .short 0x7300\n" |
27 | " rts\n" | 27 | " rts\n" |
28 | "nf_call:\n" | 28 | "nf_call:\n" |
29 | " .short 0x7301\n" | 29 | " .short 0x7301\n" |
30 | " rts\n" | 30 | " rts\n" |
31 | "1: moveq.l #0,%d0\n" | 31 | "1: moveq.l #0,%d0\n" |
32 | " rts\n" | 32 | " rts\n" |
33 | " .section __ex_table,\"a\"\n" | 33 | " .section __ex_table,\"a\"\n" |
34 | " .long nf_get_id2,1b\n" | 34 | " .long nf_get_id_phys,1b\n" |
35 | " .long nf_call,1b\n" | 35 | " .long nf_call,1b\n" |
36 | " .previous"); | 36 | " .previous"); |
37 | EXPORT_SYMBOL_GPL(nf_call); | 37 | EXPORT_SYMBOL_GPL(nf_call); |
38 | 38 | ||
39 | long nf_get_id(const char *feature_name) | 39 | long nf_get_id(const char *feature_name) |
40 | { | 40 | { |
41 | /* feature_name may be in vmalloc()ed memory, so make a copy */ | 41 | /* feature_name may be in vmalloc()ed memory, so make a copy */ |
42 | char name_copy[32]; | 42 | char name_copy[32]; |
43 | size_t n; | 43 | size_t n; |
44 | 44 | ||
45 | n = strlcpy(name_copy, feature_name, sizeof(name_copy)); | 45 | n = strlcpy(name_copy, feature_name, sizeof(name_copy)); |
46 | if (n >= sizeof(name_copy)) | 46 | if (n >= sizeof(name_copy)) |
47 | return 0; | 47 | return 0; |
48 | 48 | ||
49 | return nf_get_id2(name_copy); | 49 | return nf_get_id_phys(virt_to_phys(name_copy)); |
50 | } | 50 | } |
51 | EXPORT_SYMBOL_GPL(nf_get_id); | 51 | EXPORT_SYMBOL_GPL(nf_get_id); |
52 | 52 | ||
53 | void nfprint(const char *fmt, ...) | 53 | void nfprint(const char *fmt, ...) |
54 | { | 54 | { |
55 | static char buf[256]; | 55 | static char buf[256]; |
56 | va_list ap; | 56 | va_list ap; |
57 | int n; | 57 | int n; |
58 | 58 | ||
59 | va_start(ap, fmt); | 59 | va_start(ap, fmt); |
60 | n = vsnprintf(buf, 256, fmt, ap); | 60 | n = vsnprintf(buf, 256, fmt, ap); |
61 | nf_call(nf_get_id("NF_STDERR"), buf); | 61 | nf_call(nf_get_id("NF_STDERR"), virt_to_phys(buf)); |
62 | va_end(ap); | 62 | va_end(ap); |
63 | } | 63 | } |
64 | 64 | ||
65 | static void nf_poweroff(void) | 65 | static void nf_poweroff(void) |
66 | { | 66 | { |
67 | long id = nf_get_id("NF_SHUTDOWN"); | 67 | long id = nf_get_id("NF_SHUTDOWN"); |
68 | 68 | ||
69 | if (id) | 69 | if (id) |
70 | nf_call(id); | 70 | nf_call(id); |
71 | } | 71 | } |
72 | 72 | ||
73 | void nf_init(void) | 73 | void nf_init(void) |
74 | { | 74 | { |
75 | unsigned long id, version; | 75 | unsigned long id, version; |
76 | char buf[256]; | 76 | char buf[256]; |
77 | 77 | ||
78 | id = nf_get_id("NF_VERSION"); | 78 | id = nf_get_id("NF_VERSION"); |
79 | if (!id) | 79 | if (!id) |
80 | return; | 80 | return; |
81 | version = nf_call(id); | 81 | version = nf_call(id); |
82 | 82 | ||
83 | id = nf_get_id("NF_NAME"); | 83 | id = nf_get_id("NF_NAME"); |
84 | if (!id) | 84 | if (!id) |
85 | return; | 85 | return; |
86 | nf_call(id, buf, 256); | 86 | nf_call(id, virt_to_phys(buf), 256); |
87 | buf[255] = 0; | 87 | buf[255] = 0; |
88 | 88 | ||
89 | pr_info("NatFeats found (%s, %lu.%lu)\n", buf, version >> 16, | 89 | pr_info("NatFeats found (%s, %lu.%lu)\n", buf, version >> 16, |
90 | version & 0xffff); | 90 | version & 0xffff); |
91 | 91 | ||
92 | mach_power_off = nf_poweroff; | 92 | mach_power_off = nf_poweroff; |
93 | } | 93 | } |
94 | 94 |
arch/m68k/emu/nfblock.c
1 | /* | 1 | /* |
2 | * ARAnyM block device driver | 2 | * ARAnyM block device driver |
3 | * | 3 | * |
4 | * This file is subject to the terms and conditions of the GNU General Public | 4 | * This file is subject to the terms and conditions of the GNU General Public |
5 | * License. See the file COPYING in the main directory of this archive | 5 | * License. See the file COPYING in the main directory of this archive |
6 | * for more details. | 6 | * for more details. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/moduleparam.h> | 10 | #include <linux/moduleparam.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | 12 | ||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/genhd.h> | 16 | #include <linux/genhd.h> |
17 | #include <linux/blkdev.h> | 17 | #include <linux/blkdev.h> |
18 | #include <linux/hdreg.h> | 18 | #include <linux/hdreg.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | 20 | ||
21 | #include <asm/natfeat.h> | 21 | #include <asm/natfeat.h> |
22 | 22 | ||
23 | static long nfhd_id; | 23 | static long nfhd_id; |
24 | 24 | ||
25 | enum { | 25 | enum { |
26 | /* emulation entry points */ | 26 | /* emulation entry points */ |
27 | NFHD_READ_WRITE = 10, | 27 | NFHD_READ_WRITE = 10, |
28 | NFHD_GET_CAPACITY = 14, | 28 | NFHD_GET_CAPACITY = 14, |
29 | 29 | ||
30 | /* skip ACSI devices */ | 30 | /* skip ACSI devices */ |
31 | NFHD_DEV_OFFSET = 8, | 31 | NFHD_DEV_OFFSET = 8, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | static inline s32 nfhd_read_write(u32 major, u32 minor, u32 rwflag, u32 recno, | 34 | static inline s32 nfhd_read_write(u32 major, u32 minor, u32 rwflag, u32 recno, |
35 | u32 count, u32 buf) | 35 | u32 count, u32 buf) |
36 | { | 36 | { |
37 | return nf_call(nfhd_id + NFHD_READ_WRITE, major, minor, rwflag, recno, | 37 | return nf_call(nfhd_id + NFHD_READ_WRITE, major, minor, rwflag, recno, |
38 | count, buf); | 38 | count, buf); |
39 | } | 39 | } |
40 | 40 | ||
41 | static inline s32 nfhd_get_capacity(u32 major, u32 minor, u32 *blocks, | 41 | static inline s32 nfhd_get_capacity(u32 major, u32 minor, u32 *blocks, |
42 | u32 *blocksize) | 42 | u32 *blocksize) |
43 | { | 43 | { |
44 | return nf_call(nfhd_id + NFHD_GET_CAPACITY, major, minor, blocks, | 44 | return nf_call(nfhd_id + NFHD_GET_CAPACITY, major, minor, |
45 | blocksize); | 45 | virt_to_phys(blocks), virt_to_phys(blocksize)); |
46 | } | 46 | } |
47 | 47 | ||
48 | static LIST_HEAD(nfhd_list); | 48 | static LIST_HEAD(nfhd_list); |
49 | 49 | ||
50 | static int major_num; | 50 | static int major_num; |
51 | module_param(major_num, int, 0); | 51 | module_param(major_num, int, 0); |
52 | 52 | ||
53 | struct nfhd_device { | 53 | struct nfhd_device { |
54 | struct list_head list; | 54 | struct list_head list; |
55 | int id; | 55 | int id; |
56 | u32 blocks, bsize; | 56 | u32 blocks, bsize; |
57 | int bshift; | 57 | int bshift; |
58 | struct request_queue *queue; | 58 | struct request_queue *queue; |
59 | struct gendisk *disk; | 59 | struct gendisk *disk; |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static void nfhd_make_request(struct request_queue *queue, struct bio *bio) | 62 | static void nfhd_make_request(struct request_queue *queue, struct bio *bio) |
63 | { | 63 | { |
64 | struct nfhd_device *dev = queue->queuedata; | 64 | struct nfhd_device *dev = queue->queuedata; |
65 | struct bio_vec *bvec; | 65 | struct bio_vec *bvec; |
66 | int i, dir, len, shift; | 66 | int i, dir, len, shift; |
67 | sector_t sec = bio->bi_sector; | 67 | sector_t sec = bio->bi_sector; |
68 | 68 | ||
69 | dir = bio_data_dir(bio); | 69 | dir = bio_data_dir(bio); |
70 | shift = dev->bshift; | 70 | shift = dev->bshift; |
71 | bio_for_each_segment(bvec, bio, i) { | 71 | bio_for_each_segment(bvec, bio, i) { |
72 | len = bvec->bv_len; | 72 | len = bvec->bv_len; |
73 | len >>= 9; | 73 | len >>= 9; |
74 | nfhd_read_write(dev->id, 0, dir, sec >> shift, len >> shift, | 74 | nfhd_read_write(dev->id, 0, dir, sec >> shift, len >> shift, |
75 | bvec_to_phys(bvec)); | 75 | bvec_to_phys(bvec)); |
76 | sec += len; | 76 | sec += len; |
77 | } | 77 | } |
78 | bio_endio(bio, 0); | 78 | bio_endio(bio, 0); |
79 | } | 79 | } |
80 | 80 | ||
81 | static int nfhd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | 81 | static int nfhd_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
82 | { | 82 | { |
83 | struct nfhd_device *dev = bdev->bd_disk->private_data; | 83 | struct nfhd_device *dev = bdev->bd_disk->private_data; |
84 | 84 | ||
85 | geo->cylinders = dev->blocks >> (6 - dev->bshift); | 85 | geo->cylinders = dev->blocks >> (6 - dev->bshift); |
86 | geo->heads = 4; | 86 | geo->heads = 4; |
87 | geo->sectors = 16; | 87 | geo->sectors = 16; |
88 | 88 | ||
89 | return 0; | 89 | return 0; |
90 | } | 90 | } |
91 | 91 | ||
92 | static const struct block_device_operations nfhd_ops = { | 92 | static const struct block_device_operations nfhd_ops = { |
93 | .owner = THIS_MODULE, | 93 | .owner = THIS_MODULE, |
94 | .getgeo = nfhd_getgeo, | 94 | .getgeo = nfhd_getgeo, |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static int __init nfhd_init_one(int id, u32 blocks, u32 bsize) | 97 | static int __init nfhd_init_one(int id, u32 blocks, u32 bsize) |
98 | { | 98 | { |
99 | struct nfhd_device *dev; | 99 | struct nfhd_device *dev; |
100 | int dev_id = id - NFHD_DEV_OFFSET; | 100 | int dev_id = id - NFHD_DEV_OFFSET; |
101 | 101 | ||
102 | pr_info("nfhd%u: found device with %u blocks (%u bytes)\n", dev_id, | 102 | pr_info("nfhd%u: found device with %u blocks (%u bytes)\n", dev_id, |
103 | blocks, bsize); | 103 | blocks, bsize); |
104 | 104 | ||
105 | if (bsize < 512 || (bsize & (bsize - 1))) { | 105 | if (bsize < 512 || (bsize & (bsize - 1))) { |
106 | pr_warn("nfhd%u: invalid block size\n", dev_id); | 106 | pr_warn("nfhd%u: invalid block size\n", dev_id); |
107 | return -EINVAL; | 107 | return -EINVAL; |
108 | } | 108 | } |
109 | 109 | ||
110 | dev = kmalloc(sizeof(struct nfhd_device), GFP_KERNEL); | 110 | dev = kmalloc(sizeof(struct nfhd_device), GFP_KERNEL); |
111 | if (!dev) | 111 | if (!dev) |
112 | goto out; | 112 | goto out; |
113 | 113 | ||
114 | dev->id = id; | 114 | dev->id = id; |
115 | dev->blocks = blocks; | 115 | dev->blocks = blocks; |
116 | dev->bsize = bsize; | 116 | dev->bsize = bsize; |
117 | dev->bshift = ffs(bsize) - 10; | 117 | dev->bshift = ffs(bsize) - 10; |
118 | 118 | ||
119 | dev->queue = blk_alloc_queue(GFP_KERNEL); | 119 | dev->queue = blk_alloc_queue(GFP_KERNEL); |
120 | if (dev->queue == NULL) | 120 | if (dev->queue == NULL) |
121 | goto free_dev; | 121 | goto free_dev; |
122 | 122 | ||
123 | dev->queue->queuedata = dev; | 123 | dev->queue->queuedata = dev; |
124 | blk_queue_make_request(dev->queue, nfhd_make_request); | 124 | blk_queue_make_request(dev->queue, nfhd_make_request); |
125 | blk_queue_logical_block_size(dev->queue, bsize); | 125 | blk_queue_logical_block_size(dev->queue, bsize); |
126 | 126 | ||
127 | dev->disk = alloc_disk(16); | 127 | dev->disk = alloc_disk(16); |
128 | if (!dev->disk) | 128 | if (!dev->disk) |
129 | goto free_queue; | 129 | goto free_queue; |
130 | 130 | ||
131 | dev->disk->major = major_num; | 131 | dev->disk->major = major_num; |
132 | dev->disk->first_minor = dev_id * 16; | 132 | dev->disk->first_minor = dev_id * 16; |
133 | dev->disk->fops = &nfhd_ops; | 133 | dev->disk->fops = &nfhd_ops; |
134 | dev->disk->private_data = dev; | 134 | dev->disk->private_data = dev; |
135 | sprintf(dev->disk->disk_name, "nfhd%u", dev_id); | 135 | sprintf(dev->disk->disk_name, "nfhd%u", dev_id); |
136 | set_capacity(dev->disk, (sector_t)blocks * (bsize / 512)); | 136 | set_capacity(dev->disk, (sector_t)blocks * (bsize / 512)); |
137 | dev->disk->queue = dev->queue; | 137 | dev->disk->queue = dev->queue; |
138 | 138 | ||
139 | add_disk(dev->disk); | 139 | add_disk(dev->disk); |
140 | 140 | ||
141 | list_add_tail(&dev->list, &nfhd_list); | 141 | list_add_tail(&dev->list, &nfhd_list); |
142 | 142 | ||
143 | return 0; | 143 | return 0; |
144 | 144 | ||
145 | free_queue: | 145 | free_queue: |
146 | blk_cleanup_queue(dev->queue); | 146 | blk_cleanup_queue(dev->queue); |
147 | free_dev: | 147 | free_dev: |
148 | kfree(dev); | 148 | kfree(dev); |
149 | out: | 149 | out: |
150 | return -ENOMEM; | 150 | return -ENOMEM; |
151 | } | 151 | } |
152 | 152 | ||
153 | static int __init nfhd_init(void) | 153 | static int __init nfhd_init(void) |
154 | { | 154 | { |
155 | u32 blocks, bsize; | 155 | u32 blocks, bsize; |
156 | int i; | 156 | int i; |
157 | 157 | ||
158 | nfhd_id = nf_get_id("XHDI"); | 158 | nfhd_id = nf_get_id("XHDI"); |
159 | if (!nfhd_id) | 159 | if (!nfhd_id) |
160 | return -ENODEV; | 160 | return -ENODEV; |
161 | 161 | ||
162 | major_num = register_blkdev(major_num, "nfhd"); | 162 | major_num = register_blkdev(major_num, "nfhd"); |
163 | if (major_num <= 0) { | 163 | if (major_num <= 0) { |
164 | pr_warn("nfhd: unable to get major number\n"); | 164 | pr_warn("nfhd: unable to get major number\n"); |
165 | return major_num; | 165 | return major_num; |
166 | } | 166 | } |
167 | 167 | ||
168 | for (i = NFHD_DEV_OFFSET; i < 24; i++) { | 168 | for (i = NFHD_DEV_OFFSET; i < 24; i++) { |
169 | if (nfhd_get_capacity(i, 0, &blocks, &bsize)) | 169 | if (nfhd_get_capacity(i, 0, &blocks, &bsize)) |
170 | continue; | 170 | continue; |
171 | nfhd_init_one(i, blocks, bsize); | 171 | nfhd_init_one(i, blocks, bsize); |
172 | } | 172 | } |
173 | 173 | ||
174 | return 0; | 174 | return 0; |
175 | } | 175 | } |
176 | 176 | ||
177 | static void __exit nfhd_exit(void) | 177 | static void __exit nfhd_exit(void) |
178 | { | 178 | { |
179 | struct nfhd_device *dev, *next; | 179 | struct nfhd_device *dev, *next; |
180 | 180 | ||
181 | list_for_each_entry_safe(dev, next, &nfhd_list, list) { | 181 | list_for_each_entry_safe(dev, next, &nfhd_list, list) { |
182 | list_del(&dev->list); | 182 | list_del(&dev->list); |
183 | del_gendisk(dev->disk); | 183 | del_gendisk(dev->disk); |
184 | put_disk(dev->disk); | 184 | put_disk(dev->disk); |
185 | blk_cleanup_queue(dev->queue); | 185 | blk_cleanup_queue(dev->queue); |
186 | kfree(dev); | 186 | kfree(dev); |
187 | } | 187 | } |
188 | unregister_blkdev(major_num, "nfhd"); | 188 | unregister_blkdev(major_num, "nfhd"); |
189 | } | 189 | } |
190 | 190 | ||
191 | module_init(nfhd_init); | 191 | module_init(nfhd_init); |
192 | module_exit(nfhd_exit); | 192 | module_exit(nfhd_exit); |
193 | 193 | ||
194 | MODULE_LICENSE("GPL"); | 194 | MODULE_LICENSE("GPL"); |
195 | 195 |
arch/m68k/emu/nfcon.c
1 | /* | 1 | /* |
2 | * ARAnyM console driver | 2 | * ARAnyM console driver |
3 | * | 3 | * |
4 | * This file is subject to the terms and conditions of the GNU General Public | 4 | * This file is subject to the terms and conditions of the GNU General Public |
5 | * License. See the file COPYING in the main directory of this archive | 5 | * License. See the file COPYING in the main directory of this archive |
6 | * for more details. | 6 | * for more details. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/console.h> | 11 | #include <linux/console.h> |
12 | #include <linux/tty.h> | 12 | #include <linux/tty.h> |
13 | #include <linux/tty_driver.h> | 13 | #include <linux/tty_driver.h> |
14 | #include <linux/tty_flip.h> | 14 | #include <linux/tty_flip.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/uaccess.h> | 17 | #include <linux/uaccess.h> |
18 | #include <linux/io.h> | ||
18 | 19 | ||
19 | #include <asm/natfeat.h> | 20 | #include <asm/natfeat.h> |
20 | 21 | ||
21 | static int stderr_id; | 22 | static int stderr_id; |
22 | static struct tty_port nfcon_tty_port; | 23 | static struct tty_port nfcon_tty_port; |
23 | static struct tty_driver *nfcon_tty_driver; | 24 | static struct tty_driver *nfcon_tty_driver; |
24 | 25 | ||
25 | static void nfputs(const char *str, unsigned int count) | 26 | static void nfputs(const char *str, unsigned int count) |
26 | { | 27 | { |
27 | char buf[68]; | 28 | char buf[68]; |
29 | unsigned long phys = virt_to_phys(buf); | ||
28 | 30 | ||
29 | buf[64] = 0; | 31 | buf[64] = 0; |
30 | while (count > 64) { | 32 | while (count > 64) { |
31 | memcpy(buf, str, 64); | 33 | memcpy(buf, str, 64); |
32 | nf_call(stderr_id, buf); | 34 | nf_call(stderr_id, phys); |
33 | str += 64; | 35 | str += 64; |
34 | count -= 64; | 36 | count -= 64; |
35 | } | 37 | } |
36 | memcpy(buf, str, count); | 38 | memcpy(buf, str, count); |
37 | buf[count] = 0; | 39 | buf[count] = 0; |
38 | nf_call(stderr_id, buf); | 40 | nf_call(stderr_id, phys); |
39 | } | 41 | } |
40 | 42 | ||
41 | static void nfcon_write(struct console *con, const char *str, | 43 | static void nfcon_write(struct console *con, const char *str, |
42 | unsigned int count) | 44 | unsigned int count) |
43 | { | 45 | { |
44 | nfputs(str, count); | 46 | nfputs(str, count); |
45 | } | 47 | } |
46 | 48 | ||
47 | static struct tty_driver *nfcon_device(struct console *con, int *index) | 49 | static struct tty_driver *nfcon_device(struct console *con, int *index) |
48 | { | 50 | { |
49 | *index = 0; | 51 | *index = 0; |
50 | return (con->flags & CON_ENABLED) ? nfcon_tty_driver : NULL; | 52 | return (con->flags & CON_ENABLED) ? nfcon_tty_driver : NULL; |
51 | } | 53 | } |
52 | 54 | ||
53 | static struct console nf_console = { | 55 | static struct console nf_console = { |
54 | .name = "nfcon", | 56 | .name = "nfcon", |
55 | .write = nfcon_write, | 57 | .write = nfcon_write, |
56 | .device = nfcon_device, | 58 | .device = nfcon_device, |
57 | .flags = CON_PRINTBUFFER, | 59 | .flags = CON_PRINTBUFFER, |
58 | .index = -1, | 60 | .index = -1, |
59 | }; | 61 | }; |
60 | 62 | ||
61 | 63 | ||
62 | static int nfcon_tty_open(struct tty_struct *tty, struct file *filp) | 64 | static int nfcon_tty_open(struct tty_struct *tty, struct file *filp) |
63 | { | 65 | { |
64 | return 0; | 66 | return 0; |
65 | } | 67 | } |
66 | 68 | ||
67 | static void nfcon_tty_close(struct tty_struct *tty, struct file *filp) | 69 | static void nfcon_tty_close(struct tty_struct *tty, struct file *filp) |
68 | { | 70 | { |
69 | } | 71 | } |
70 | 72 | ||
71 | static int nfcon_tty_write(struct tty_struct *tty, const unsigned char *buf, | 73 | static int nfcon_tty_write(struct tty_struct *tty, const unsigned char *buf, |
72 | int count) | 74 | int count) |
73 | { | 75 | { |
74 | nfputs(buf, count); | 76 | nfputs(buf, count); |
75 | return count; | 77 | return count; |
76 | } | 78 | } |
77 | 79 | ||
78 | static int nfcon_tty_put_char(struct tty_struct *tty, unsigned char ch) | 80 | static int nfcon_tty_put_char(struct tty_struct *tty, unsigned char ch) |
79 | { | 81 | { |
80 | char temp[2] = { ch, 0 }; | 82 | char temp[2] = { ch, 0 }; |
81 | 83 | ||
82 | nf_call(stderr_id, temp); | 84 | nf_call(stderr_id, virt_to_phys(temp)); |
83 | return 1; | 85 | return 1; |
84 | } | 86 | } |
85 | 87 | ||
86 | static int nfcon_tty_write_room(struct tty_struct *tty) | 88 | static int nfcon_tty_write_room(struct tty_struct *tty) |
87 | { | 89 | { |
88 | return 64; | 90 | return 64; |
89 | } | 91 | } |
90 | 92 | ||
91 | static const struct tty_operations nfcon_tty_ops = { | 93 | static const struct tty_operations nfcon_tty_ops = { |
92 | .open = nfcon_tty_open, | 94 | .open = nfcon_tty_open, |
93 | .close = nfcon_tty_close, | 95 | .close = nfcon_tty_close, |
94 | .write = nfcon_tty_write, | 96 | .write = nfcon_tty_write, |
95 | .put_char = nfcon_tty_put_char, | 97 | .put_char = nfcon_tty_put_char, |
96 | .write_room = nfcon_tty_write_room, | 98 | .write_room = nfcon_tty_write_room, |
97 | }; | 99 | }; |
98 | 100 | ||
99 | #ifndef MODULE | 101 | #ifndef MODULE |
100 | 102 | ||
101 | static int __init nf_debug_setup(char *arg) | 103 | static int __init nf_debug_setup(char *arg) |
102 | { | 104 | { |
103 | if (strcmp(arg, "nfcon")) | 105 | if (strcmp(arg, "nfcon")) |
104 | return 0; | 106 | return 0; |
105 | 107 | ||
106 | stderr_id = nf_get_id("NF_STDERR"); | 108 | stderr_id = nf_get_id("NF_STDERR"); |
107 | if (stderr_id) { | 109 | if (stderr_id) { |
108 | nf_console.flags |= CON_ENABLED; | 110 | nf_console.flags |= CON_ENABLED; |
109 | register_console(&nf_console); | 111 | register_console(&nf_console); |
110 | } | 112 | } |
111 | 113 | ||
112 | return 0; | 114 | return 0; |
113 | } | 115 | } |
114 | 116 | ||
115 | early_param("debug", nf_debug_setup); | 117 | early_param("debug", nf_debug_setup); |
116 | 118 | ||
117 | #endif /* !MODULE */ | 119 | #endif /* !MODULE */ |
118 | 120 | ||
119 | static int __init nfcon_init(void) | 121 | static int __init nfcon_init(void) |
120 | { | 122 | { |
121 | int res; | 123 | int res; |
122 | 124 | ||
123 | stderr_id = nf_get_id("NF_STDERR"); | 125 | stderr_id = nf_get_id("NF_STDERR"); |
124 | if (!stderr_id) | 126 | if (!stderr_id) |
125 | return -ENODEV; | 127 | return -ENODEV; |
126 | 128 | ||
127 | nfcon_tty_driver = alloc_tty_driver(1); | 129 | nfcon_tty_driver = alloc_tty_driver(1); |
128 | if (!nfcon_tty_driver) | 130 | if (!nfcon_tty_driver) |
129 | return -ENOMEM; | 131 | return -ENOMEM; |
130 | 132 | ||
131 | tty_port_init(&nfcon_tty_port); | 133 | tty_port_init(&nfcon_tty_port); |
132 | 134 | ||
133 | nfcon_tty_driver->driver_name = "nfcon"; | 135 | nfcon_tty_driver->driver_name = "nfcon"; |
134 | nfcon_tty_driver->name = "nfcon"; | 136 | nfcon_tty_driver->name = "nfcon"; |
135 | nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM; | 137 | nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM; |
136 | nfcon_tty_driver->subtype = SYSTEM_TYPE_TTY; | 138 | nfcon_tty_driver->subtype = SYSTEM_TYPE_TTY; |
137 | nfcon_tty_driver->init_termios = tty_std_termios; | 139 | nfcon_tty_driver->init_termios = tty_std_termios; |
138 | nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW; | 140 | nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW; |
139 | 141 | ||
140 | tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops); | 142 | tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops); |
141 | tty_port_link_device(&nfcon_tty_port, nfcon_tty_driver, 0); | 143 | tty_port_link_device(&nfcon_tty_port, nfcon_tty_driver, 0); |
142 | res = tty_register_driver(nfcon_tty_driver); | 144 | res = tty_register_driver(nfcon_tty_driver); |
143 | if (res) { | 145 | if (res) { |
144 | pr_err("failed to register nfcon tty driver\n"); | 146 | pr_err("failed to register nfcon tty driver\n"); |
145 | put_tty_driver(nfcon_tty_driver); | 147 | put_tty_driver(nfcon_tty_driver); |
146 | tty_port_destroy(&nfcon_tty_port); | 148 | tty_port_destroy(&nfcon_tty_port); |
147 | return res; | 149 | return res; |
148 | } | 150 | } |
149 | 151 | ||
150 | if (!(nf_console.flags & CON_ENABLED)) | 152 | if (!(nf_console.flags & CON_ENABLED)) |
151 | register_console(&nf_console); | 153 | register_console(&nf_console); |
152 | 154 | ||
153 | return 0; | 155 | return 0; |
154 | } | 156 | } |
155 | 157 | ||
156 | static void __exit nfcon_exit(void) | 158 | static void __exit nfcon_exit(void) |
157 | { | 159 | { |
158 | unregister_console(&nf_console); | 160 | unregister_console(&nf_console); |
159 | tty_unregister_driver(nfcon_tty_driver); | 161 | tty_unregister_driver(nfcon_tty_driver); |
160 | put_tty_driver(nfcon_tty_driver); | 162 | put_tty_driver(nfcon_tty_driver); |
161 | tty_port_destroy(&nfcon_tty_port); | 163 | tty_port_destroy(&nfcon_tty_port); |
162 | } | 164 | } |
163 | 165 | ||
164 | module_init(nfcon_init); | 166 | module_init(nfcon_init); |
165 | module_exit(nfcon_exit); | 167 | module_exit(nfcon_exit); |
166 | 168 | ||
167 | MODULE_LICENSE("GPL"); | 169 | MODULE_LICENSE("GPL"); |
168 | 170 |
arch/m68k/emu/nfeth.c
1 | /* | 1 | /* |
2 | * atari_nfeth.c - ARAnyM ethernet card driver for GNU/Linux | 2 | * atari_nfeth.c - ARAnyM ethernet card driver for GNU/Linux |
3 | * | 3 | * |
4 | * Copyright (c) 2005 Milan Jurik, Petr Stehlik of ARAnyM dev team | 4 | * Copyright (c) 2005 Milan Jurik, Petr Stehlik of ARAnyM dev team |
5 | * | 5 | * |
6 | * Based on ARAnyM driver for FreeMiNT written by Standa Opichal | 6 | * Based on ARAnyM driver for FreeMiNT written by Standa Opichal |
7 | * | 7 | * |
8 | * This software may be used and distributed according to the terms of | 8 | * This software may be used and distributed according to the terms of |
9 | * the GNU General Public License (GPL), incorporated herein by reference. | 9 | * the GNU General Public License (GPL), incorporated herein by reference. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #define DRV_VERSION "0.3" | 12 | #define DRV_VERSION "0.3" |
13 | #define DRV_RELDATE "10/12/2005" | 13 | #define DRV_RELDATE "10/12/2005" |
14 | 14 | ||
15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
16 | 16 | ||
17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
18 | #include <linux/etherdevice.h> | 18 | #include <linux/etherdevice.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <asm/natfeat.h> | 21 | #include <asm/natfeat.h> |
22 | #include <asm/virtconvert.h> | 22 | #include <asm/virtconvert.h> |
23 | 23 | ||
24 | enum { | 24 | enum { |
25 | GET_VERSION = 0,/* no parameters, return NFAPI_VERSION in d0 */ | 25 | GET_VERSION = 0,/* no parameters, return NFAPI_VERSION in d0 */ |
26 | XIF_INTLEVEL, /* no parameters, return Interrupt Level in d0 */ | 26 | XIF_INTLEVEL, /* no parameters, return Interrupt Level in d0 */ |
27 | XIF_IRQ, /* acknowledge interrupt from host */ | 27 | XIF_IRQ, /* acknowledge interrupt from host */ |
28 | XIF_START, /* (ethX), called on 'ifup', start receiver thread */ | 28 | XIF_START, /* (ethX), called on 'ifup', start receiver thread */ |
29 | XIF_STOP, /* (ethX), called on 'ifdown', stop the thread */ | 29 | XIF_STOP, /* (ethX), called on 'ifdown', stop the thread */ |
30 | XIF_READLENGTH, /* (ethX), return size of network data block to read */ | 30 | XIF_READLENGTH, /* (ethX), return size of network data block to read */ |
31 | XIF_READBLOCK, /* (ethX, buffer, size), read block of network data */ | 31 | XIF_READBLOCK, /* (ethX, buffer, size), read block of network data */ |
32 | XIF_WRITEBLOCK, /* (ethX, buffer, size), write block of network data */ | 32 | XIF_WRITEBLOCK, /* (ethX, buffer, size), write block of network data */ |
33 | XIF_GET_MAC, /* (ethX, buffer, size), return MAC HW addr in buffer */ | 33 | XIF_GET_MAC, /* (ethX, buffer, size), return MAC HW addr in buffer */ |
34 | XIF_GET_IPHOST, /* (ethX, buffer, size), return IP address of host */ | 34 | XIF_GET_IPHOST, /* (ethX, buffer, size), return IP address of host */ |
35 | XIF_GET_IPATARI,/* (ethX, buffer, size), return IP address of atari */ | 35 | XIF_GET_IPATARI,/* (ethX, buffer, size), return IP address of atari */ |
36 | XIF_GET_NETMASK /* (ethX, buffer, size), return IP netmask */ | 36 | XIF_GET_NETMASK /* (ethX, buffer, size), return IP netmask */ |
37 | }; | 37 | }; |
38 | 38 | ||
39 | #define MAX_UNIT 8 | 39 | #define MAX_UNIT 8 |
40 | 40 | ||
41 | /* These identify the driver base version and may not be removed. */ | 41 | /* These identify the driver base version and may not be removed. */ |
42 | static const char version[] = | 42 | static const char version[] = |
43 | KERN_INFO KBUILD_MODNAME ".c:v" DRV_VERSION " " DRV_RELDATE | 43 | KERN_INFO KBUILD_MODNAME ".c:v" DRV_VERSION " " DRV_RELDATE |
44 | " S.Opichal, M.Jurik, P.Stehlik\n" | 44 | " S.Opichal, M.Jurik, P.Stehlik\n" |
45 | KERN_INFO " http://aranym.org/\n"; | 45 | KERN_INFO " http://aranym.org/\n"; |
46 | 46 | ||
47 | MODULE_AUTHOR("Milan Jurik"); | 47 | MODULE_AUTHOR("Milan Jurik"); |
48 | MODULE_DESCRIPTION("Atari NFeth driver"); | 48 | MODULE_DESCRIPTION("Atari NFeth driver"); |
49 | MODULE_LICENSE("GPL"); | 49 | MODULE_LICENSE("GPL"); |
50 | /* | 50 | /* |
51 | MODULE_PARM(nfeth_debug, "i"); | 51 | MODULE_PARM(nfeth_debug, "i"); |
52 | MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)"); | 52 | MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)"); |
53 | */ | 53 | */ |
54 | 54 | ||
55 | 55 | ||
56 | static long nfEtherID; | 56 | static long nfEtherID; |
57 | static int nfEtherIRQ; | 57 | static int nfEtherIRQ; |
58 | 58 | ||
59 | struct nfeth_private { | 59 | struct nfeth_private { |
60 | int ethX; | 60 | int ethX; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | static struct net_device *nfeth_dev[MAX_UNIT]; | 63 | static struct net_device *nfeth_dev[MAX_UNIT]; |
64 | 64 | ||
65 | static int nfeth_open(struct net_device *dev) | 65 | static int nfeth_open(struct net_device *dev) |
66 | { | 66 | { |
67 | struct nfeth_private *priv = netdev_priv(dev); | 67 | struct nfeth_private *priv = netdev_priv(dev); |
68 | int res; | 68 | int res; |
69 | 69 | ||
70 | res = nf_call(nfEtherID + XIF_START, priv->ethX); | 70 | res = nf_call(nfEtherID + XIF_START, priv->ethX); |
71 | netdev_dbg(dev, "%s: %d\n", __func__, res); | 71 | netdev_dbg(dev, "%s: %d\n", __func__, res); |
72 | 72 | ||
73 | /* Ready for data */ | 73 | /* Ready for data */ |
74 | netif_start_queue(dev); | 74 | netif_start_queue(dev); |
75 | 75 | ||
76 | return 0; | 76 | return 0; |
77 | } | 77 | } |
78 | 78 | ||
79 | static int nfeth_stop(struct net_device *dev) | 79 | static int nfeth_stop(struct net_device *dev) |
80 | { | 80 | { |
81 | struct nfeth_private *priv = netdev_priv(dev); | 81 | struct nfeth_private *priv = netdev_priv(dev); |
82 | 82 | ||
83 | /* No more data */ | 83 | /* No more data */ |
84 | netif_stop_queue(dev); | 84 | netif_stop_queue(dev); |
85 | 85 | ||
86 | nf_call(nfEtherID + XIF_STOP, priv->ethX); | 86 | nf_call(nfEtherID + XIF_STOP, priv->ethX); |
87 | 87 | ||
88 | return 0; | 88 | return 0; |
89 | } | 89 | } |
90 | 90 | ||
91 | /* | 91 | /* |
92 | * Read a packet out of the adapter and pass it to the upper layers | 92 | * Read a packet out of the adapter and pass it to the upper layers |
93 | */ | 93 | */ |
94 | static inline void recv_packet(struct net_device *dev) | 94 | static inline void recv_packet(struct net_device *dev) |
95 | { | 95 | { |
96 | struct nfeth_private *priv = netdev_priv(dev); | 96 | struct nfeth_private *priv = netdev_priv(dev); |
97 | unsigned short pktlen; | 97 | unsigned short pktlen; |
98 | struct sk_buff *skb; | 98 | struct sk_buff *skb; |
99 | 99 | ||
100 | /* read packet length (excluding 32 bit crc) */ | 100 | /* read packet length (excluding 32 bit crc) */ |
101 | pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX); | 101 | pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX); |
102 | 102 | ||
103 | netdev_dbg(dev, "%s: %u\n", __func__, pktlen); | 103 | netdev_dbg(dev, "%s: %u\n", __func__, pktlen); |
104 | 104 | ||
105 | if (!pktlen) { | 105 | if (!pktlen) { |
106 | netdev_dbg(dev, "%s: pktlen == 0\n", __func__); | 106 | netdev_dbg(dev, "%s: pktlen == 0\n", __func__); |
107 | dev->stats.rx_errors++; | 107 | dev->stats.rx_errors++; |
108 | return; | 108 | return; |
109 | } | 109 | } |
110 | 110 | ||
111 | skb = dev_alloc_skb(pktlen + 2); | 111 | skb = dev_alloc_skb(pktlen + 2); |
112 | if (!skb) { | 112 | if (!skb) { |
113 | netdev_dbg(dev, "%s: out of mem (buf_alloc failed)\n", | 113 | netdev_dbg(dev, "%s: out of mem (buf_alloc failed)\n", |
114 | __func__); | 114 | __func__); |
115 | dev->stats.rx_dropped++; | 115 | dev->stats.rx_dropped++; |
116 | return; | 116 | return; |
117 | } | 117 | } |
118 | 118 | ||
119 | skb->dev = dev; | 119 | skb->dev = dev; |
120 | skb_reserve(skb, 2); /* 16 Byte align */ | 120 | skb_reserve(skb, 2); /* 16 Byte align */ |
121 | skb_put(skb, pktlen); /* make room */ | 121 | skb_put(skb, pktlen); /* make room */ |
122 | nf_call(nfEtherID + XIF_READBLOCK, priv->ethX, virt_to_phys(skb->data), | 122 | nf_call(nfEtherID + XIF_READBLOCK, priv->ethX, virt_to_phys(skb->data), |
123 | pktlen); | 123 | pktlen); |
124 | 124 | ||
125 | skb->protocol = eth_type_trans(skb, dev); | 125 | skb->protocol = eth_type_trans(skb, dev); |
126 | netif_rx(skb); | 126 | netif_rx(skb); |
127 | dev->last_rx = jiffies; | 127 | dev->last_rx = jiffies; |
128 | dev->stats.rx_packets++; | 128 | dev->stats.rx_packets++; |
129 | dev->stats.rx_bytes += pktlen; | 129 | dev->stats.rx_bytes += pktlen; |
130 | 130 | ||
131 | /* and enqueue packet */ | 131 | /* and enqueue packet */ |
132 | return; | 132 | return; |
133 | } | 133 | } |
134 | 134 | ||
135 | static irqreturn_t nfeth_interrupt(int irq, void *dev_id) | 135 | static irqreturn_t nfeth_interrupt(int irq, void *dev_id) |
136 | { | 136 | { |
137 | int i, m, mask; | 137 | int i, m, mask; |
138 | 138 | ||
139 | mask = nf_call(nfEtherID + XIF_IRQ, 0); | 139 | mask = nf_call(nfEtherID + XIF_IRQ, 0); |
140 | for (i = 0, m = 1; i < MAX_UNIT; m <<= 1, i++) { | 140 | for (i = 0, m = 1; i < MAX_UNIT; m <<= 1, i++) { |
141 | if (mask & m && nfeth_dev[i]) { | 141 | if (mask & m && nfeth_dev[i]) { |
142 | recv_packet(nfeth_dev[i]); | 142 | recv_packet(nfeth_dev[i]); |
143 | nf_call(nfEtherID + XIF_IRQ, m); | 143 | nf_call(nfEtherID + XIF_IRQ, m); |
144 | } | 144 | } |
145 | } | 145 | } |
146 | return IRQ_HANDLED; | 146 | return IRQ_HANDLED; |
147 | } | 147 | } |
148 | 148 | ||
149 | static int nfeth_xmit(struct sk_buff *skb, struct net_device *dev) | 149 | static int nfeth_xmit(struct sk_buff *skb, struct net_device *dev) |
150 | { | 150 | { |
151 | unsigned int len; | 151 | unsigned int len; |
152 | char *data, shortpkt[ETH_ZLEN]; | 152 | char *data, shortpkt[ETH_ZLEN]; |
153 | struct nfeth_private *priv = netdev_priv(dev); | 153 | struct nfeth_private *priv = netdev_priv(dev); |
154 | 154 | ||
155 | data = skb->data; | 155 | data = skb->data; |
156 | len = skb->len; | 156 | len = skb->len; |
157 | if (len < ETH_ZLEN) { | 157 | if (len < ETH_ZLEN) { |
158 | memset(shortpkt, 0, ETH_ZLEN); | 158 | memset(shortpkt, 0, ETH_ZLEN); |
159 | memcpy(shortpkt, data, len); | 159 | memcpy(shortpkt, data, len); |
160 | data = shortpkt; | 160 | data = shortpkt; |
161 | len = ETH_ZLEN; | 161 | len = ETH_ZLEN; |
162 | } | 162 | } |
163 | 163 | ||
164 | netdev_dbg(dev, "%s: send %u bytes\n", __func__, len); | 164 | netdev_dbg(dev, "%s: send %u bytes\n", __func__, len); |
165 | nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data), | 165 | nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data), |
166 | len); | 166 | len); |
167 | 167 | ||
168 | dev->stats.tx_packets++; | 168 | dev->stats.tx_packets++; |
169 | dev->stats.tx_bytes += len; | 169 | dev->stats.tx_bytes += len; |
170 | 170 | ||
171 | dev_kfree_skb(skb); | 171 | dev_kfree_skb(skb); |
172 | return 0; | 172 | return 0; |
173 | } | 173 | } |
174 | 174 | ||
175 | static void nfeth_tx_timeout(struct net_device *dev) | 175 | static void nfeth_tx_timeout(struct net_device *dev) |
176 | { | 176 | { |
177 | dev->stats.tx_errors++; | 177 | dev->stats.tx_errors++; |
178 | netif_wake_queue(dev); | 178 | netif_wake_queue(dev); |
179 | } | 179 | } |
180 | 180 | ||
181 | static const struct net_device_ops nfeth_netdev_ops = { | 181 | static const struct net_device_ops nfeth_netdev_ops = { |
182 | .ndo_open = nfeth_open, | 182 | .ndo_open = nfeth_open, |
183 | .ndo_stop = nfeth_stop, | 183 | .ndo_stop = nfeth_stop, |
184 | .ndo_start_xmit = nfeth_xmit, | 184 | .ndo_start_xmit = nfeth_xmit, |
185 | .ndo_tx_timeout = nfeth_tx_timeout, | 185 | .ndo_tx_timeout = nfeth_tx_timeout, |
186 | .ndo_validate_addr = eth_validate_addr, | 186 | .ndo_validate_addr = eth_validate_addr, |
187 | .ndo_change_mtu = eth_change_mtu, | 187 | .ndo_change_mtu = eth_change_mtu, |
188 | .ndo_set_mac_address = eth_mac_addr, | 188 | .ndo_set_mac_address = eth_mac_addr, |
189 | }; | 189 | }; |
190 | 190 | ||
191 | static struct net_device * __init nfeth_probe(int unit) | 191 | static struct net_device * __init nfeth_probe(int unit) |
192 | { | 192 | { |
193 | struct net_device *dev; | 193 | struct net_device *dev; |
194 | struct nfeth_private *priv; | 194 | struct nfeth_private *priv; |
195 | char mac[ETH_ALEN], host_ip[32], local_ip[32]; | 195 | char mac[ETH_ALEN], host_ip[32], local_ip[32]; |
196 | int err; | 196 | int err; |
197 | 197 | ||
198 | if (!nf_call(nfEtherID + XIF_GET_MAC, unit, mac, ETH_ALEN)) | 198 | if (!nf_call(nfEtherID + XIF_GET_MAC, unit, virt_to_phys(mac), |
199 | ETH_ALEN)) | ||
199 | return NULL; | 200 | return NULL; |
200 | 201 | ||
201 | dev = alloc_etherdev(sizeof(struct nfeth_private)); | 202 | dev = alloc_etherdev(sizeof(struct nfeth_private)); |
202 | if (!dev) | 203 | if (!dev) |
203 | return NULL; | 204 | return NULL; |
204 | 205 | ||
205 | dev->irq = nfEtherIRQ; | 206 | dev->irq = nfEtherIRQ; |
206 | dev->netdev_ops = &nfeth_netdev_ops; | 207 | dev->netdev_ops = &nfeth_netdev_ops; |
207 | 208 | ||
208 | memcpy(dev->dev_addr, mac, ETH_ALEN); | 209 | memcpy(dev->dev_addr, mac, ETH_ALEN); |
209 | 210 | ||
210 | priv = netdev_priv(dev); | 211 | priv = netdev_priv(dev); |
211 | priv->ethX = unit; | 212 | priv->ethX = unit; |
212 | 213 | ||
213 | err = register_netdev(dev); | 214 | err = register_netdev(dev); |
214 | if (err) { | 215 | if (err) { |
215 | free_netdev(dev); | 216 | free_netdev(dev); |
216 | return NULL; | 217 | return NULL; |
217 | } | 218 | } |
218 | 219 | ||
219 | nf_call(nfEtherID + XIF_GET_IPHOST, unit, | 220 | nf_call(nfEtherID + XIF_GET_IPHOST, unit, |
220 | host_ip, sizeof(host_ip)); | 221 | virt_to_phys(host_ip), sizeof(host_ip)); |
221 | nf_call(nfEtherID + XIF_GET_IPATARI, unit, | 222 | nf_call(nfEtherID + XIF_GET_IPATARI, unit, |
222 | local_ip, sizeof(local_ip)); | 223 | virt_to_phys(local_ip), sizeof(local_ip)); |
223 | 224 | ||
224 | netdev_info(dev, KBUILD_MODNAME " addr:%s (%s) HWaddr:%pM\n", host_ip, | 225 | netdev_info(dev, KBUILD_MODNAME " addr:%s (%s) HWaddr:%pM\n", host_ip, |
225 | local_ip, mac); | 226 | local_ip, mac); |
226 | 227 | ||
227 | return dev; | 228 | return dev; |
228 | } | 229 | } |
229 | 230 | ||
230 | static int __init nfeth_init(void) | 231 | static int __init nfeth_init(void) |
231 | { | 232 | { |
232 | long ver; | 233 | long ver; |
233 | int error, i; | 234 | int error, i; |
234 | 235 | ||
235 | nfEtherID = nf_get_id("ETHERNET"); | 236 | nfEtherID = nf_get_id("ETHERNET"); |
236 | if (!nfEtherID) | 237 | if (!nfEtherID) |
237 | return -ENODEV; | 238 | return -ENODEV; |
238 | 239 | ||
239 | ver = nf_call(nfEtherID + GET_VERSION); | 240 | ver = nf_call(nfEtherID + GET_VERSION); |
240 | pr_info("API %lu\n", ver); | 241 | pr_info("API %lu\n", ver); |
241 | 242 | ||
242 | nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL); | 243 | nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL); |
243 | error = request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED, | 244 | error = request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED, |
244 | "eth emu", nfeth_interrupt); | 245 | "eth emu", nfeth_interrupt); |
245 | if (error) { | 246 | if (error) { |
246 | pr_err("request for irq %d failed %d", nfEtherIRQ, error); | 247 | pr_err("request for irq %d failed %d", nfEtherIRQ, error); |
247 | return error; | 248 | return error; |
248 | } | 249 | } |
249 | 250 | ||
250 | for (i = 0; i < MAX_UNIT; i++) | 251 | for (i = 0; i < MAX_UNIT; i++) |
251 | nfeth_dev[i] = nfeth_probe(i); | 252 | nfeth_dev[i] = nfeth_probe(i); |
252 | 253 | ||
253 | return 0; | 254 | return 0; |
254 | } | 255 | } |
255 | 256 | ||
256 | static void __exit nfeth_cleanup(void) | 257 | static void __exit nfeth_cleanup(void) |
257 | { | 258 | { |
258 | int i; | 259 | int i; |
259 | 260 | ||
260 | for (i = 0; i < MAX_UNIT; i++) { | 261 | for (i = 0; i < MAX_UNIT; i++) { |
261 | if (nfeth_dev[i]) { | 262 | if (nfeth_dev[i]) { |
262 | unregister_netdev(nfeth_dev[0]); | 263 | unregister_netdev(nfeth_dev[0]); |
263 | free_netdev(nfeth_dev[0]); | 264 | free_netdev(nfeth_dev[0]); |
264 | } | 265 | } |
265 | } | 266 | } |
266 | free_irq(nfEtherIRQ, nfeth_interrupt); | 267 | free_irq(nfEtherIRQ, nfeth_interrupt); |
267 | } | 268 | } |
268 | 269 | ||
269 | module_init(nfeth_init); | 270 | module_init(nfeth_init); |
270 | module_exit(nfeth_cleanup); | 271 | module_exit(nfeth_cleanup); |
271 | 272 |