Commit 55490050df0f5d82ce070be11351c65f7696101c

Authored by Geert Uytterhoeven
1 parent 3c776a0791

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