aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 22:08:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 22:08:03 -0400
commitdc113c1f1d4b47af1b1ca701c5a39e24d296c2ac (patch)
tree0bb5ce21bcd41a9443708567edbdca80d9a72397 /arch/m68k
parent63a93699c6a58795b854ff573542a08367684dae (diff)
parent059718d572e8ad388313b863aff717623bb2552f (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k: m68k/block: amiflop - Remove superfluous amiga_chip_alloc() cast m68k/atari: ARAnyM - Add support for network access m68k/atari: ARAnyM - Add support for console access m68k/atari: ARAnyM - Add support for block access m68k/atari: Initial ARAnyM support m68k: Kconfig - Remove unneeded "default n" m68k: Makefiles - Change to new flags variables m68k/amiga: Reclaim Chip RAM for PPC exception handlers m68k: Allow all kernel traps to be handled via exception fixups m68k: Use base_trap_init() to initialize vectors m68k: Add helper function handle_kernel_fault()
Diffstat (limited to 'arch/m68k')
-rw-r--r--arch/m68k/Kconfig33
-rw-r--r--arch/m68k/Makefile1
-rw-r--r--arch/m68k/amiga/chipram.c4
-rw-r--r--arch/m68k/emu/Makefile9
-rw-r--r--arch/m68k/emu/natfeat.c78
-rw-r--r--arch/m68k/emu/nfblock.c195
-rw-r--r--arch/m68k/emu/nfcon.c162
-rw-r--r--arch/m68k/emu/nfeth.c270
-rw-r--r--arch/m68k/include/asm/natfeat.h22
-rw-r--r--arch/m68k/include/asm/processor.h2
-rw-r--r--arch/m68k/kernel/setup.c5
-rw-r--r--arch/m68k/kernel/signal.c24
-rw-r--r--arch/m68k/kernel/traps.c20
-rw-r--r--arch/m68k/math-emu/Makefile4
-rw-r--r--arch/m68k/mm/fault.c16
15 files changed, 813 insertions, 32 deletions
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index a85e251c411f..525174d41679 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -18,11 +18,9 @@ config RWSEM_XCHGADD_ALGORITHM
18 18
19config ARCH_HAS_ILOG2_U32 19config ARCH_HAS_ILOG2_U32
20 bool 20 bool
21 default n
22 21
23config ARCH_HAS_ILOG2_U64 22config ARCH_HAS_ILOG2_U64
24 bool 23 bool
25 default n
26 24
27config GENERIC_HWEIGHT 25config GENERIC_HWEIGHT
28 bool 26 bool
@@ -242,6 +240,37 @@ config SUN3
242 240
243 If you don't want to compile a kernel exclusively for a Sun 3, say N. 241 If you don't want to compile a kernel exclusively for a Sun 3, say N.
244 242
243config NATFEAT
244 bool "ARAnyM emulator support"
245 depends on ATARI
246 help
247 This option enables support for ARAnyM native features, such as
248 access to a disk image as /dev/hda.
249
250config NFBLOCK
251 tristate "NatFeat block device support"
252 depends on BLOCK && NATFEAT
253 help
254 Say Y to include support for the ARAnyM NatFeat block device
255 which allows direct access to the hard drives without using
256 the hardware emulation.
257
258config NFCON
259 tristate "NatFeat console driver"
260 depends on NATFEAT
261 help
262 Say Y to include support for the ARAnyM NatFeat console driver
263 which allows the console output to be redirected to the stderr
264 output of ARAnyM.
265
266config NFETH
267 tristate "NatFeat Ethernet support"
268 depends on NET_ETHERNET && NATFEAT
269 help
270 Say Y to include support for the ARAnyM NatFeat network device
271 which will emulate a regular ethernet device while presenting an
272 ethertap device to the host system.
273
245comment "Processor type" 274comment "Processor type"
246 275
247config M68020 276config M68020
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index b06a7e3cbcd6..b793163abc61 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -76,6 +76,7 @@ core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/
76core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/ 76core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/
77core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/ 77core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/
78core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/ 78core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/
79core-$(CONFIG_NATFEAT) += arch/m68k/emu/
79core-$(CONFIG_M68040) += arch/m68k/fpsp040/ 80core-$(CONFIG_M68040) += arch/m68k/fpsp040/
80core-$(CONFIG_M68060) += arch/m68k/ifpsp060/ 81core-$(CONFIG_M68060) += arch/m68k/ifpsp060/
81core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/ 82core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index 61df1d33c050..dd0447db1c90 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -33,10 +33,6 @@ void __init amiga_chip_init(void)
33 if (!AMIGAHW_PRESENT(CHIP_RAM)) 33 if (!AMIGAHW_PRESENT(CHIP_RAM))
34 return; 34 return;
35 35
36 /*
37 * Remove the first 4 pages where PPC exception handlers will be located
38 */
39 amiga_chip_size -= 0x4000;
40 chipram_res.end = amiga_chip_size-1; 36 chipram_res.end = amiga_chip_size-1;
41 request_resource(&iomem_resource, &chipram_res); 37 request_resource(&iomem_resource, &chipram_res);
42 38
diff --git a/arch/m68k/emu/Makefile b/arch/m68k/emu/Makefile
new file mode 100644
index 000000000000..7dc201080308
--- /dev/null
+++ b/arch/m68k/emu/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for Linux arch/m68k/emu source directory
3#
4
5obj-y += natfeat.o
6
7obj-$(CONFIG_NFBLOCK) += nfblock.o
8obj-$(CONFIG_NFCON) += nfcon.o
9obj-$(CONFIG_NFETH) += nfeth.o
diff --git a/arch/m68k/emu/natfeat.c b/arch/m68k/emu/natfeat.c
new file mode 100644
index 000000000000..2291a7d69d49
--- /dev/null
+++ b/arch/m68k/emu/natfeat.c
@@ -0,0 +1,78 @@
1/*
2 * natfeat.c - ARAnyM hardware support via Native Features (natfeats)
3 *
4 * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team
5 *
6 * Reworked for Linux by Roman Zippel <zippel@linux-m68k.org>
7 *
8 * This software may be used and distributed according to the terms of
9 * the GNU General Public License (GPL), incorporated herein by reference.
10 */
11
12#include <linux/types.h>
13#include <linux/console.h>
14#include <linux/string.h>
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/io.h>
18#include <asm/machdep.h>
19#include <asm/natfeat.h>
20
21asm("\n"
22" .global nf_get_id,nf_call\n"
23"nf_get_id:\n"
24" .short 0x7300\n"
25" rts\n"
26"nf_call:\n"
27" .short 0x7301\n"
28" rts\n"
29"1: moveq.l #0,%d0\n"
30" rts\n"
31" .section __ex_table,\"a\"\n"
32" .long nf_get_id,1b\n"
33" .long nf_call,1b\n"
34" .previous");
35EXPORT_SYMBOL_GPL(nf_get_id);
36EXPORT_SYMBOL_GPL(nf_call);
37
38void nfprint(const char *fmt, ...)
39{
40 static char buf[256];
41 va_list ap;
42 int n;
43
44 va_start(ap, fmt);
45 n = vsnprintf(buf, 256, fmt, ap);
46 nf_call(nf_get_id("NF_STDERR"), buf);
47 va_end(ap);
48}
49
50static void nf_poweroff(void)
51{
52 long id = nf_get_id("NF_SHUTDOWN");
53
54 if (id)
55 nf_call(id);
56}
57
58void nf_init(void)
59{
60 unsigned long id, version;
61 char buf[256];
62
63 id = nf_get_id("NF_VERSION");
64 if (!id)
65 return;
66 version = nf_call(id);
67
68 id = nf_get_id("NF_NAME");
69 if (!id)
70 return;
71 nf_call(id, buf, 256);
72 buf[255] = 0;
73
74 pr_info("NatFeats found (%s, %lu.%lu)\n", buf, version >> 16,
75 version & 0xffff);
76
77 mach_power_off = nf_poweroff;
78}
diff --git a/arch/m68k/emu/nfblock.c b/arch/m68k/emu/nfblock.c
new file mode 100644
index 000000000000..48e50f8c1c7e
--- /dev/null
+++ b/arch/m68k/emu/nfblock.c
@@ -0,0 +1,195 @@
1/*
2 * ARAnyM block device driver
3 *
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
6 * for more details.
7 */
8
9#include <linux/module.h>
10#include <linux/moduleparam.h>
11#include <linux/init.h>
12
13#include <linux/kernel.h>
14#include <linux/errno.h>
15#include <linux/types.h>
16#include <linux/genhd.h>
17#include <linux/blkdev.h>
18#include <linux/hdreg.h>
19#include <linux/slab.h>
20
21#include <asm/natfeat.h>
22
23static long nfhd_id;
24
25enum {
26 /* emulation entry points */
27 NFHD_READ_WRITE = 10,
28 NFHD_GET_CAPACITY = 14,
29
30 /* skip ACSI devices */
31 NFHD_DEV_OFFSET = 8,
32};
33
34static inline s32 nfhd_read_write(u32 major, u32 minor, u32 rwflag, u32 recno,
35 u32 count, u32 buf)
36{
37 return nf_call(nfhd_id + NFHD_READ_WRITE, major, minor, rwflag, recno,
38 count, buf);
39}
40
41static inline s32 nfhd_get_capacity(u32 major, u32 minor, u32 *blocks,
42 u32 *blocksize)
43{
44 return nf_call(nfhd_id + NFHD_GET_CAPACITY, major, minor, blocks,
45 blocksize);
46}
47
48static LIST_HEAD(nfhd_list);
49
50static int major_num;
51module_param(major_num, int, 0);
52
53struct nfhd_device {
54 struct list_head list;
55 int id;
56 u32 blocks, bsize;
57 int bshift;
58 struct request_queue *queue;
59 struct gendisk *disk;
60};
61
62static int nfhd_make_request(struct request_queue *queue, struct bio *bio)
63{
64 struct nfhd_device *dev = queue->queuedata;
65 struct bio_vec *bvec;
66 int i, dir, len, shift;
67 sector_t sec = bio->bi_sector;
68
69 dir = bio_data_dir(bio);
70 shift = dev->bshift;
71 bio_for_each_segment(bvec, bio, i) {
72 len = bvec->bv_len;
73 len >>= 9;
74 nfhd_read_write(dev->id, 0, dir, sec >> shift, len >> shift,
75 bvec_to_phys(bvec));
76 sec += len;
77 }
78 bio_endio(bio, 0);
79 return 0;
80}
81
82static int nfhd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
83{
84 struct nfhd_device *dev = bdev->bd_disk->private_data;
85
86 geo->cylinders = dev->blocks >> (6 - dev->bshift);
87 geo->heads = 4;
88 geo->sectors = 16;
89
90 return 0;
91}
92
93static const struct block_device_operations nfhd_ops = {
94 .owner = THIS_MODULE,
95 .getgeo = nfhd_getgeo,
96};
97
98static int __init nfhd_init_one(int id, u32 blocks, u32 bsize)
99{
100 struct nfhd_device *dev;
101 int dev_id = id - NFHD_DEV_OFFSET;
102
103 pr_info("nfhd%u: found device with %u blocks (%u bytes)\n", dev_id,
104 blocks, bsize);
105
106 if (bsize < 512 || (bsize & (bsize - 1))) {
107 pr_warn("nfhd%u: invalid block size\n", dev_id);
108 return -EINVAL;
109 }
110
111 dev = kmalloc(sizeof(struct nfhd_device), GFP_KERNEL);
112 if (!dev)
113 goto out;
114
115 dev->id = id;
116 dev->blocks = blocks;
117 dev->bsize = bsize;
118 dev->bshift = ffs(bsize) - 10;
119
120 dev->queue = blk_alloc_queue(GFP_KERNEL);
121 if (dev->queue == NULL)
122 goto free_dev;
123
124 dev->queue->queuedata = dev;
125 blk_queue_make_request(dev->queue, nfhd_make_request);
126 blk_queue_logical_block_size(dev->queue, bsize);
127
128 dev->disk = alloc_disk(16);
129 if (!dev->disk)
130 goto free_queue;
131
132 dev->disk->major = major_num;
133 dev->disk->first_minor = dev_id * 16;
134 dev->disk->fops = &nfhd_ops;
135 dev->disk->private_data = dev;
136 sprintf(dev->disk->disk_name, "nfhd%u", dev_id);
137 set_capacity(dev->disk, (sector_t)blocks * (bsize / 512));
138 dev->disk->queue = dev->queue;
139
140 add_disk(dev->disk);
141
142 list_add_tail(&dev->list, &nfhd_list);
143
144 return 0;
145
146free_queue:
147 blk_cleanup_queue(dev->queue);
148free_dev:
149 kfree(dev);
150out:
151 return -ENOMEM;
152}
153
154static int __init nfhd_init(void)
155{
156 u32 blocks, bsize;
157 int i;
158
159 nfhd_id = nf_get_id("XHDI");
160 if (!nfhd_id)
161 return -ENODEV;
162
163 major_num = register_blkdev(major_num, "nfhd");
164 if (major_num <= 0) {
165 pr_warn("nfhd: unable to get major number\n");
166 return major_num;
167 }
168
169 for (i = NFHD_DEV_OFFSET; i < 24; i++) {
170 if (nfhd_get_capacity(i, 0, &blocks, &bsize))
171 continue;
172 nfhd_init_one(i, blocks, bsize);
173 }
174
175 return 0;
176}
177
178static void __exit nfhd_exit(void)
179{
180 struct nfhd_device *dev, *next;
181
182 list_for_each_entry_safe(dev, next, &nfhd_list, list) {
183 list_del(&dev->list);
184 del_gendisk(dev->disk);
185 put_disk(dev->disk);
186 blk_cleanup_queue(dev->queue);
187 kfree(dev);
188 }
189 unregister_blkdev(major_num, "nfhd");
190}
191
192module_init(nfhd_init);
193module_exit(nfhd_exit);
194
195MODULE_LICENSE("GPL");
diff --git a/arch/m68k/emu/nfcon.c b/arch/m68k/emu/nfcon.c
new file mode 100644
index 000000000000..ab20dc0ff63b
--- /dev/null
+++ b/arch/m68k/emu/nfcon.c
@@ -0,0 +1,162 @@
1/*
2 * ARAnyM console driver
3 *
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
6 * for more details.
7 */
8
9#include <linux/module.h>
10#include <linux/init.h>
11#include <linux/console.h>
12#include <linux/tty.h>
13#include <linux/tty_driver.h>
14#include <linux/tty_flip.h>
15#include <linux/slab.h>
16#include <linux/err.h>
17#include <linux/uaccess.h>
18
19#include <asm/natfeat.h>
20
21static int stderr_id;
22static struct tty_driver *nfcon_tty_driver;
23
24static void nfputs(const char *str, unsigned int count)
25{
26 char buf[68];
27
28 buf[64] = 0;
29 while (count > 64) {
30 memcpy(buf, str, 64);
31 nf_call(stderr_id, buf);
32 str += 64;
33 count -= 64;
34 }
35 memcpy(buf, str, count);
36 buf[count] = 0;
37 nf_call(stderr_id, buf);
38}
39
40static void nfcon_write(struct console *con, const char *str,
41 unsigned int count)
42{
43 nfputs(str, count);
44}
45
46static struct tty_driver *nfcon_device(struct console *con, int *index)
47{
48 *index = 0;
49 return (con->flags & CON_ENABLED) ? nfcon_tty_driver : NULL;
50}
51
52static struct console nf_console = {
53 .name = "nfcon",
54 .write = nfcon_write,
55 .device = nfcon_device,
56 .flags = CON_PRINTBUFFER,
57 .index = -1,
58};
59
60
61static int nfcon_tty_open(struct tty_struct *tty, struct file *filp)
62{
63 return 0;
64}
65
66static void nfcon_tty_close(struct tty_struct *tty, struct file *filp)
67{
68}
69
70static int nfcon_tty_write(struct tty_struct *tty, const unsigned char *buf,
71 int count)
72{
73 nfputs(buf, count);
74 return count;
75}
76
77static int nfcon_tty_put_char(struct tty_struct *tty, unsigned char ch)
78{
79 char temp[2] = { ch, 0 };
80
81 nf_call(stderr_id, temp);
82 return 1;
83}
84
85static int nfcon_tty_write_room(struct tty_struct *tty)
86{
87 return 64;
88}
89
90static const struct tty_operations nfcon_tty_ops = {
91 .open = nfcon_tty_open,
92 .close = nfcon_tty_close,
93 .write = nfcon_tty_write,
94 .put_char = nfcon_tty_put_char,
95 .write_room = nfcon_tty_write_room,
96};
97
98#ifndef MODULE
99
100static int __init nf_debug_setup(char *arg)
101{
102 if (strcmp(arg, "nfcon"))
103 return 0;
104
105 stderr_id = nf_get_id("NF_STDERR");
106 if (stderr_id) {
107 nf_console.flags |= CON_ENABLED;
108 register_console(&nf_console);
109 }
110
111 return 0;
112}
113
114early_param("debug", nf_debug_setup);
115
116#endif /* !MODULE */
117
118static int __init nfcon_init(void)
119{
120 int res;
121
122 stderr_id = nf_get_id("NF_STDERR");
123 if (!stderr_id)
124 return -ENODEV;
125
126 nfcon_tty_driver = alloc_tty_driver(1);
127 if (!nfcon_tty_driver)
128 return -ENOMEM;
129
130 nfcon_tty_driver->owner = THIS_MODULE;
131 nfcon_tty_driver->driver_name = "nfcon";
132 nfcon_tty_driver->name = "nfcon";
133 nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
134 nfcon_tty_driver->subtype = SYSTEM_TYPE_TTY;
135 nfcon_tty_driver->init_termios = tty_std_termios;
136 nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
137
138 tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops);
139 res = tty_register_driver(nfcon_tty_driver);
140 if (res) {
141 pr_err("failed to register nfcon tty driver\n");
142 put_tty_driver(nfcon_tty_driver);
143 return res;
144 }
145
146 if (!(nf_console.flags & CON_ENABLED))
147 register_console(&nf_console);
148
149 return 0;
150}
151
152static void __exit nfcon_exit(void)
153{
154 unregister_console(&nf_console);
155 tty_unregister_driver(nfcon_tty_driver);
156 put_tty_driver(nfcon_tty_driver);
157}
158
159module_init(nfcon_init);
160module_exit(nfcon_exit);
161
162MODULE_LICENSE("GPL");
diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c
new file mode 100644
index 000000000000..8b6e201b2c20
--- /dev/null
+++ b/arch/m68k/emu/nfeth.c
@@ -0,0 +1,270 @@
1/*
2 * atari_nfeth.c - ARAnyM ethernet card driver for GNU/Linux
3 *
4 * Copyright (c) 2005 Milan Jurik, Petr Stehlik of ARAnyM dev team
5 *
6 * Based on ARAnyM driver for FreeMiNT written by Standa Opichal
7 *
8 * This software may be used and distributed according to the terms of
9 * the GNU General Public License (GPL), incorporated herein by reference.
10 */
11
12#define DRV_VERSION "0.3"
13#define DRV_RELDATE "10/12/2005"
14
15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16
17#include <linux/netdevice.h>
18#include <linux/etherdevice.h>
19#include <linux/module.h>
20#include <asm/natfeat.h>
21#include <asm/virtconvert.h>
22
23enum {
24 GET_VERSION = 0,/* no parameters, return NFAPI_VERSION in d0 */
25 XIF_INTLEVEL, /* no parameters, return Interrupt Level in d0 */
26 XIF_IRQ, /* acknowledge interrupt from host */
27 XIF_START, /* (ethX), called on 'ifup', start receiver thread */
28 XIF_STOP, /* (ethX), called on 'ifdown', stop the thread */
29 XIF_READLENGTH, /* (ethX), return size of network data block to read */
30 XIF_READBLOCK, /* (ethX, buffer, size), read block of network data */
31 XIF_WRITEBLOCK, /* (ethX, buffer, size), write block of network data */
32 XIF_GET_MAC, /* (ethX, buffer, size), return MAC HW addr in buffer */
33 XIF_GET_IPHOST, /* (ethX, buffer, size), return IP address of host */
34 XIF_GET_IPATARI,/* (ethX, buffer, size), return IP address of atari */
35 XIF_GET_NETMASK /* (ethX, buffer, size), return IP netmask */
36};
37
38#define MAX_UNIT 8
39
40/* These identify the driver base version and may not be removed. */
41static const char version[] __devinitdata =
42 KERN_INFO KBUILD_MODNAME ".c:v" DRV_VERSION " " DRV_RELDATE
43 " S.Opichal, M.Jurik, P.Stehlik\n"
44 KERN_INFO " http://aranym.org/\n";
45
46MODULE_AUTHOR("Milan Jurik");
47MODULE_DESCRIPTION("Atari NFeth driver");
48MODULE_LICENSE("GPL");
49/*
50MODULE_PARM(nfeth_debug, "i");
51MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)");
52*/
53
54
55static long nfEtherID;
56static int nfEtherIRQ;
57
58struct nfeth_private {
59 int ethX;
60};
61
62static struct net_device *nfeth_dev[MAX_UNIT];
63
64static int nfeth_open(struct net_device *dev)
65{
66 struct nfeth_private *priv = netdev_priv(dev);
67 int res;
68
69 res = nf_call(nfEtherID + XIF_START, priv->ethX);
70 netdev_dbg(dev, "%s: %d\n", __func__, res);
71
72 /* Ready for data */
73 netif_start_queue(dev);
74
75 return 0;
76}
77
78static int nfeth_stop(struct net_device *dev)
79{
80 struct nfeth_private *priv = netdev_priv(dev);
81
82 /* No more data */
83 netif_stop_queue(dev);
84
85 nf_call(nfEtherID + XIF_STOP, priv->ethX);
86
87 return 0;
88}
89
90/*
91 * Read a packet out of the adapter and pass it to the upper layers
92 */
93static inline void recv_packet(struct net_device *dev)
94{
95 struct nfeth_private *priv = netdev_priv(dev);
96 unsigned short pktlen;
97 struct sk_buff *skb;
98
99 /* read packet length (excluding 32 bit crc) */
100 pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX);
101
102 netdev_dbg(dev, "%s: %u\n", __func__, pktlen);
103
104 if (!pktlen) {
105 netdev_dbg(dev, "%s: pktlen == 0\n", __func__);
106 dev->stats.rx_errors++;
107 return;
108 }
109
110 skb = dev_alloc_skb(pktlen + 2);
111 if (!skb) {
112 netdev_dbg(dev, "%s: out of mem (buf_alloc failed)\n",
113 __func__);
114 dev->stats.rx_dropped++;
115 return;
116 }
117
118 skb->dev = dev;
119 skb_reserve(skb, 2); /* 16 Byte align */
120 skb_put(skb, pktlen); /* make room */
121 nf_call(nfEtherID + XIF_READBLOCK, priv->ethX, virt_to_phys(skb->data),
122 pktlen);
123
124 skb->protocol = eth_type_trans(skb, dev);
125 netif_rx(skb);
126 dev->last_rx = jiffies;
127 dev->stats.rx_packets++;
128 dev->stats.rx_bytes += pktlen;
129
130 /* and enqueue packet */
131 return;
132}
133
134static irqreturn_t nfeth_interrupt(int irq, void *dev_id)
135{
136 int i, m, mask;
137
138 mask = nf_call(nfEtherID + XIF_IRQ, 0);
139 for (i = 0, m = 1; i < MAX_UNIT; m <<= 1, i++) {
140 if (mask & m && nfeth_dev[i]) {
141 recv_packet(nfeth_dev[i]);
142 nf_call(nfEtherID + XIF_IRQ, m);
143 }
144 }
145 return IRQ_HANDLED;
146}
147
148static int nfeth_xmit(struct sk_buff *skb, struct net_device *dev)
149{
150 unsigned int len;
151 char *data, shortpkt[ETH_ZLEN];
152 struct nfeth_private *priv = netdev_priv(dev);
153
154 data = skb->data;
155 len = skb->len;
156 if (len < ETH_ZLEN) {
157 memset(shortpkt, 0, ETH_ZLEN);
158 memcpy(shortpkt, data, len);
159 data = shortpkt;
160 len = ETH_ZLEN;
161 }
162
163 netdev_dbg(dev, "%s: send %u bytes\n", __func__, len);
164 nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data),
165 len);
166
167 dev->stats.tx_packets++;
168 dev->stats.tx_bytes += len;
169
170 dev_kfree_skb(skb);
171 return 0;
172}
173
174static void nfeth_tx_timeout(struct net_device *dev)
175{
176 dev->stats.tx_errors++;
177 netif_wake_queue(dev);
178}
179
180static const struct net_device_ops nfeth_netdev_ops = {
181 .ndo_open = nfeth_open,
182 .ndo_stop = nfeth_stop,
183 .ndo_start_xmit = nfeth_xmit,
184 .ndo_tx_timeout = nfeth_tx_timeout,
185 .ndo_validate_addr = eth_validate_addr,
186 .ndo_change_mtu = eth_change_mtu,
187 .ndo_set_mac_address = eth_mac_addr,
188};
189
190static struct net_device * __init nfeth_probe(int unit)
191{
192 struct net_device *dev;
193 struct nfeth_private *priv;
194 char mac[ETH_ALEN], host_ip[32], local_ip[32];
195 int err;
196
197 if (!nf_call(nfEtherID + XIF_GET_MAC, unit, mac, ETH_ALEN))
198 return NULL;
199
200 dev = alloc_etherdev(sizeof(struct nfeth_private));
201 if (!dev)
202 return NULL;
203
204 dev->irq = nfEtherIRQ;
205 dev->netdev_ops = &nfeth_netdev_ops;
206
207 dev->flags |= NETIF_F_NO_CSUM;
208 memcpy(dev->dev_addr, mac, ETH_ALEN);
209
210 priv = netdev_priv(dev);
211 priv->ethX = unit;
212
213 err = register_netdev(dev);
214 if (err) {
215 free_netdev(dev);
216 return NULL;
217 }
218
219 nf_call(nfEtherID + XIF_GET_IPHOST, unit,
220 host_ip, sizeof(host_ip));
221 nf_call(nfEtherID + XIF_GET_IPATARI, unit,
222 local_ip, sizeof(local_ip));
223
224 netdev_info(dev, KBUILD_MODNAME " addr:%s (%s) HWaddr:%pM\n", host_ip,
225 local_ip, mac);
226
227 return dev;
228}
229
230static int __init nfeth_init(void)
231{
232 long ver;
233 int error, i;
234
235 nfEtherID = nf_get_id("ETHERNET");
236 if (!nfEtherID)
237 return -ENODEV;
238
239 ver = nf_call(nfEtherID + GET_VERSION);
240 pr_info("API %lu\n", ver);
241
242 nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL);
243 error = request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED,
244 "eth emu", nfeth_interrupt);
245 if (error) {
246 pr_err("request for irq %d failed %d", nfEtherIRQ, error);
247 return error;
248 }
249
250 for (i = 0; i < MAX_UNIT; i++)
251 nfeth_dev[i] = nfeth_probe(i);
252
253 return 0;
254}
255
256static void __exit nfeth_cleanup(void)
257{
258 int i;
259
260 for (i = 0; i < MAX_UNIT; i++) {
261 if (nfeth_dev[i]) {
262 unregister_netdev(nfeth_dev[0]);
263 free_netdev(nfeth_dev[0]);
264 }
265 }
266 free_irq(nfEtherIRQ, nfeth_interrupt);
267}
268
269module_init(nfeth_init);
270module_exit(nfeth_cleanup);
diff --git a/arch/m68k/include/asm/natfeat.h b/arch/m68k/include/asm/natfeat.h
new file mode 100644
index 000000000000..a3521b80c3b9
--- /dev/null
+++ b/arch/m68k/include/asm/natfeat.h
@@ -0,0 +1,22 @@
1/*
2 * ARAnyM hardware support via Native Features (natfeats)
3 *
4 * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team
5 *
6 * This software may be used and distributed according to the terms of
7 * the GNU General Public License (GPL), incorporated herein by reference.
8 */
9
10#ifndef _NATFEAT_H
11#define _NATFEAT_H
12
13long nf_get_id(const char *feature_name);
14long nf_call(long id, ...);
15
16void nf_init(void);
17void nf_shutdown(void);
18
19void nfprint(const char *fmt, ...)
20 __attribute__ ((format (printf, 1, 2)));
21
22# endif /* _NATFEAT_H */
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index 278c69bad57a..f111b02b704f 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -113,6 +113,8 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
113 wrusp(usp); 113 wrusp(usp);
114} 114}
115 115
116extern int handle_kernel_fault(struct pt_regs *regs);
117
116#else 118#else
117 119
118/* 120/*
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index b3963ab3d149..334d83640376 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -42,6 +42,7 @@
42#ifdef CONFIG_SUN3X 42#ifdef CONFIG_SUN3X
43#include <asm/dvma.h> 43#include <asm/dvma.h>
44#endif 44#endif
45#include <asm/natfeat.h>
45 46
46#if !FPSTATESIZE || !NR_IRQS 47#if !FPSTATESIZE || !NR_IRQS
47#warning No CPU/platform type selected, your kernel will not work! 48#warning No CPU/platform type selected, your kernel will not work!
@@ -324,6 +325,10 @@ void __init setup_arch(char **cmdline_p)
324 panic("No configuration setup"); 325 panic("No configuration setup");
325 } 326 }
326 327
328#ifdef CONFIG_NATFEAT
329 nf_init();
330#endif
331
327 paging_init(); 332 paging_init();
328 333
329#ifndef CONFIG_SUN3 334#ifndef CONFIG_SUN3
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index d12c3b0d9e4f..a0afc239304e 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -42,6 +42,7 @@
42#include <linux/personality.h> 42#include <linux/personality.h>
43#include <linux/tty.h> 43#include <linux/tty.h>
44#include <linux/binfmts.h> 44#include <linux/binfmts.h>
45#include <linux/module.h>
45 46
46#include <asm/setup.h> 47#include <asm/setup.h>
47#include <asm/uaccess.h> 48#include <asm/uaccess.h>
@@ -51,7 +52,7 @@
51 52
52#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 53#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
53 54
54const int frame_extra_sizes[16] = { 55static const int frame_extra_sizes[16] = {
55 [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ 56 [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
56 [2] = sizeof(((struct frame *)0)->un.fmt2), 57 [2] = sizeof(((struct frame *)0)->un.fmt2),
57 [3] = sizeof(((struct frame *)0)->un.fmt3), 58 [3] = sizeof(((struct frame *)0)->un.fmt3),
@@ -69,6 +70,27 @@ const int frame_extra_sizes[16] = {
69 [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */ 70 [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */
70}; 71};
71 72
73int handle_kernel_fault(struct pt_regs *regs)
74{
75 const struct exception_table_entry *fixup;
76 struct pt_regs *tregs;
77
78 /* Are we prepared to handle this kernel fault? */
79 fixup = search_exception_tables(regs->pc);
80 if (!fixup)
81 return 0;
82
83 /* Create a new four word stack frame, discarding the old one. */
84 regs->stkadj = frame_extra_sizes[regs->format];
85 tregs = (struct pt_regs *)((long)regs + regs->stkadj);
86 tregs->vector = regs->vector;
87 tregs->format = 0;
88 tregs->pc = fixup->fixup;
89 tregs->sr = regs->sr;
90
91 return 1;
92}
93
72/* 94/*
73 * Atomically swap in the new signal mask, and wait for a signal. 95 * Atomically swap in the new signal mask, and wait for a signal.
74 */ 96 */
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index ada4f4cca811..4022bbc28878 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -48,10 +48,7 @@ asmlinkage void nmihandler(void);
48asmlinkage void fpu_emu(void); 48asmlinkage void fpu_emu(void);
49#endif 49#endif
50 50
51e_vector vectors[256] = { 51e_vector vectors[256];
52 [VEC_BUSERR] = buserr,
53 [VEC_SYS] = system_call,
54};
55 52
56/* nmi handler for the Amiga */ 53/* nmi handler for the Amiga */
57asm(".text\n" 54asm(".text\n"
@@ -61,10 +58,11 @@ asm(".text\n"
61/* 58/*
62 * this must be called very early as the kernel might 59 * this must be called very early as the kernel might
63 * use some instruction that are emulated on the 060 60 * use some instruction that are emulated on the 060
61 * and so we're prepared for early probe attempts (e.g. nf_init).
64 */ 62 */
65void __init base_trap_init(void) 63void __init base_trap_init(void)
66{ 64{
67 if(MACH_IS_SUN3X) { 65 if (MACH_IS_SUN3X) {
68 extern e_vector *sun3x_prom_vbr; 66 extern e_vector *sun3x_prom_vbr;
69 67
70 __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr)); 68 __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
@@ -79,6 +77,10 @@ void __init base_trap_init(void)
79 77
80 vectors[VEC_UNIMPII] = unimp_vec; 78 vectors[VEC_UNIMPII] = unimp_vec;
81 } 79 }
80
81 vectors[VEC_BUSERR] = buserr;
82 vectors[VEC_ILLEGAL] = trap;
83 vectors[VEC_SYS] = system_call;
82} 84}
83 85
84void __init trap_init (void) 86void __init trap_init (void)
@@ -1055,9 +1057,11 @@ asmlinkage void trap_c(struct frame *fp)
1055 siginfo_t info; 1057 siginfo_t info;
1056 1058
1057 if (fp->ptregs.sr & PS_S) { 1059 if (fp->ptregs.sr & PS_S) {
1058 if ((fp->ptregs.vector >> 2) == VEC_TRACE) { 1060 if (fp->ptregs.vector == VEC_TRACE << 2) {
1059 /* traced a trapping instruction */ 1061 /* traced a trapping instruction on a 68020/30,
1060 } else 1062 * real exception will be executed afterwards.
1063 */
1064 } else if (!handle_kernel_fault(&fp->ptregs))
1061 bad_super_trap(fp); 1065 bad_super_trap(fp);
1062 return; 1066 return;
1063 } 1067 }
diff --git a/arch/m68k/math-emu/Makefile b/arch/m68k/math-emu/Makefile
index a0935bf98362..547c23c6e40e 100644
--- a/arch/m68k/math-emu/Makefile
+++ b/arch/m68k/math-emu/Makefile
@@ -2,8 +2,8 @@
2# Makefile for the linux kernel. 2# Makefile for the linux kernel.
3# 3#
4 4
5#EXTRA_AFLAGS += -DFPU_EMU_DEBUG 5#asflags-y := -DFPU_EMU_DEBUG
6#EXTRA_CFLAGS += -DFPU_EMU_DEBUG 6#ccflags-y := -DFPU_EMU_DEBUG
7 7
8obj-y := fp_entry.o fp_scan.o fp_util.o fp_move.o fp_movem.o \ 8obj-y := fp_entry.o fp_scan.o fp_util.o fp_move.o fp_movem.o \
9 fp_cond.o fp_arith.o fp_log.o fp_trig.o 9 fp_cond.o fp_arith.o fp_log.o fp_trig.o
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index a96394a0333d..2db6099784ba 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -18,7 +18,6 @@
18#include <asm/pgalloc.h> 18#include <asm/pgalloc.h>
19 19
20extern void die_if_kernel(char *, struct pt_regs *, long); 20extern void die_if_kernel(char *, struct pt_regs *, long);
21extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */
22 21
23int send_fault_sig(struct pt_regs *regs) 22int send_fault_sig(struct pt_regs *regs)
24{ 23{
@@ -35,21 +34,8 @@ int send_fault_sig(struct pt_regs *regs)
35 force_sig_info(siginfo.si_signo, 34 force_sig_info(siginfo.si_signo,
36 &siginfo, current); 35 &siginfo, current);
37 } else { 36 } else {
38 const struct exception_table_entry *fixup; 37 if (handle_kernel_fault(regs))
39
40 /* Are we prepared to handle this kernel fault? */
41 if ((fixup = search_exception_tables(regs->pc))) {
42 struct pt_regs *tregs;
43 /* Create a new four word stack frame, discarding the old
44 one. */
45 regs->stkadj = frame_extra_sizes[regs->format];
46 tregs = (struct pt_regs *)((ulong)regs + regs->stkadj);
47 tregs->vector = regs->vector;
48 tregs->format = 0;
49 tregs->pc = fixup->fixup;
50 tregs->sr = regs->sr;
51 return -1; 38 return -1;
52 }
53 39
54 //if (siginfo.si_signo == SIGBUS) 40 //if (siginfo.si_signo == SIGBUS)
55 // force_sig_info(siginfo.si_signo, 41 // force_sig_info(siginfo.si_signo,