From 93ff9542462ba5074fb6b6cd9e27c4fb04d452ec Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 16 Jan 2011 19:54:14 +0100 Subject: m68k: Kconfig - Remove unneeded "default n" Reported-by: Phillip Lougher Signed-off-by: Geert Uytterhoeven --- arch/m68k/Kconfig | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/m68k/Kconfig') diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index bc9271b85759..cbe8b18e808b 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -18,11 +18,9 @@ config RWSEM_XCHGADD_ALGORITHM config ARCH_HAS_ILOG2_U32 bool - default n config ARCH_HAS_ILOG2_U64 bool - default n config GENERIC_HWEIGHT bool -- cgit v1.2.3-58-ga151 From 65cd577d5e61043d1c1aec5812dea8a5c834652d Mon Sep 17 00:00:00 2001 From: Petr Stehlik Date: Tue, 18 Nov 2008 21:02:18 +0100 Subject: m68k/atari: Initial ARAnyM support Add improved support for running under the ARAnyM emulator (Atari Running on Any Machine - http://aranym.org/). [michael, geert: Cleanups and updates] Signed-off-by: Petr Stehlik Signed-off-by: Michael Schmitz Signed-off-by: Geert Uytterhoeven --- arch/m68k/Kconfig | 7 +++ arch/m68k/Makefile | 1 + arch/m68k/emu/Makefile | 5 ++ arch/m68k/emu/natfeat.c | 116 ++++++++++++++++++++++++++++++++++++++++ arch/m68k/include/asm/natfeat.h | 22 ++++++++ arch/m68k/kernel/setup.c | 5 ++ 6 files changed, 156 insertions(+) create mode 100644 arch/m68k/emu/Makefile create mode 100644 arch/m68k/emu/natfeat.c create mode 100644 arch/m68k/include/asm/natfeat.h (limited to 'arch/m68k/Kconfig') diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index cbe8b18e808b..f668a5802a4a 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -240,6 +240,13 @@ config SUN3 If you don't want to compile a kernel exclusively for a Sun 3, say N. +config NATFEAT + bool "ARAnyM emulator support" + depends on ATARI + help + This option enables support for ARAnyM native features, such as + access to a disk image as /dev/hda. + comment "Processor type" config 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/ core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/ core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/ core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/ +core-$(CONFIG_NATFEAT) += arch/m68k/emu/ core-$(CONFIG_M68040) += arch/m68k/fpsp040/ core-$(CONFIG_M68060) += arch/m68k/ifpsp060/ core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/ diff --git a/arch/m68k/emu/Makefile b/arch/m68k/emu/Makefile new file mode 100644 index 000000000000..34cfa348ca2b --- /dev/null +++ b/arch/m68k/emu/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for Linux arch/m68k/emu source directory +# + +obj-y += natfeat.o diff --git a/arch/m68k/emu/natfeat.c b/arch/m68k/emu/natfeat.c new file mode 100644 index 000000000000..987d77322178 --- /dev/null +++ b/arch/m68k/emu/natfeat.c @@ -0,0 +1,116 @@ +/* + * natfeat.c - ARAnyM hardware support via Native Features (natfeats) + * + * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team + * + * Reworked for Linux by Roman Zippel + * + * This software may be used and distributed according to the terms of + * the GNU General Public License (GPL), incorporated herein by reference. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +asm("\n" +" .global nf_get_id,nf_call\n" +"nf_get_id:\n" +" .short 0x7300\n" +" rts\n" +"nf_call:\n" +" .short 0x7301\n" +" rts\n" +"1: moveq.l #0,%d0\n" +" rts\n" +" .section __ex_table,\"a\"\n" +" .long nf_get_id,1b\n" +" .long nf_call,1b\n" +" .previous"); +EXPORT_SYMBOL_GPL(nf_get_id); +EXPORT_SYMBOL_GPL(nf_call); + +static int stderr_id; + +static void nf_write(struct console *co, const char *str, unsigned int count) +{ + char buf[68]; + + buf[64] = 0; + while (count > 64) { + memcpy(buf, str, 64); + nf_call(stderr_id, buf); + str += 64; + count -= 64; + } + memcpy(buf, str, count); + buf[count] = 0; + nf_call(stderr_id, buf); +} + +void nfprint(const char *fmt, ...) +{ + static char buf[256]; + va_list ap; + int n; + + va_start(ap, fmt); + n = vsnprintf(buf, 256, fmt, ap); + nf_call(nf_get_id("NF_STDERR"), buf); + va_end(ap); +} + +static struct console nf_console_driver = { + .name = "debug", + .write = nf_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +static int __init nf_debug_setup(char *arg) +{ + if (strcmp(arg, "emu")) + return 0; + + stderr_id = nf_get_id("NF_STDERR"); + if (stderr_id) + register_console(&nf_console_driver); + return 0; +} + +early_param("debug", nf_debug_setup); + +static void nf_poweroff(void) +{ + long id = nf_get_id("NF_SHUTDOWN"); + + if (id) + nf_call(id); +} + +void nf_init(void) +{ + unsigned long id, version; + char buf[256]; + + id = nf_get_id("NF_VERSION"); + if (!id) + return; + version = nf_call(id); + + id = nf_get_id("NF_NAME"); + if (!id) + return; + nf_call(id, buf, 256); + buf[255] = 0; + + pr_info("NatFeats found (%s, %lu.%lu)\n", buf, version >> 16, + version & 0xffff); + + mach_power_off = nf_poweroff; +} 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 @@ +/* + * ARAnyM hardware support via Native Features (natfeats) + * + * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team + * + * This software may be used and distributed according to the terms of + * the GNU General Public License (GPL), incorporated herein by reference. + */ + +#ifndef _NATFEAT_H +#define _NATFEAT_H + +long nf_get_id(const char *feature_name); +long nf_call(long id, ...); + +void nf_init(void); +void nf_shutdown(void); + +void nfprint(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +# endif /* _NATFEAT_H */ 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 @@ #ifdef CONFIG_SUN3X #include #endif +#include #if !FPSTATESIZE || !NR_IRQS #warning No CPU/platform type selected, your kernel will not work! @@ -324,6 +325,10 @@ void __init setup_arch(char **cmdline_p) panic("No configuration setup"); } +#ifdef CONFIG_NATFEAT + nf_init(); +#endif + paging_init(); #ifndef CONFIG_SUN3 -- cgit v1.2.3-58-ga151 From b2edd2fd9b10c0cfc5a305eaf91587e6142b08f9 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 18 Nov 2008 21:02:19 +0100 Subject: m68k/atari: ARAnyM - Add support for block access [geert: Cleanups and updates] Signed-off-by: Roman Zippel Signed-off-by: Geert Uytterhoeven Acked-by: Petr Stehlik --- arch/m68k/Kconfig | 8 ++ arch/m68k/emu/Makefile | 2 + arch/m68k/emu/nfblock.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 arch/m68k/emu/nfblock.c (limited to 'arch/m68k/Kconfig') diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index f668a5802a4a..2c890b56c96e 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -247,6 +247,14 @@ config NATFEAT This option enables support for ARAnyM native features, such as access to a disk image as /dev/hda. +config NFBLOCK + tristate "NatFeat block device support" + depends on BLOCK && NATFEAT + help + Say Y to include support for the ARAnyM NatFeat block device + which allows direct access to the hard drives without using + the hardware emulation. + comment "Processor type" config M68020 diff --git a/arch/m68k/emu/Makefile b/arch/m68k/emu/Makefile index 34cfa348ca2b..fc4f77a3d35c 100644 --- a/arch/m68k/emu/Makefile +++ b/arch/m68k/emu/Makefile @@ -3,3 +3,5 @@ # obj-y += natfeat.o + +obj-$(CONFIG_NFBLOCK) += nfblock.o 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 @@ +/* + * ARAnyM block device driver + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +static long nfhd_id; + +enum { + /* emulation entry points */ + NFHD_READ_WRITE = 10, + NFHD_GET_CAPACITY = 14, + + /* skip ACSI devices */ + NFHD_DEV_OFFSET = 8, +}; + +static inline s32 nfhd_read_write(u32 major, u32 minor, u32 rwflag, u32 recno, + u32 count, u32 buf) +{ + return nf_call(nfhd_id + NFHD_READ_WRITE, major, minor, rwflag, recno, + count, buf); +} + +static inline s32 nfhd_get_capacity(u32 major, u32 minor, u32 *blocks, + u32 *blocksize) +{ + return nf_call(nfhd_id + NFHD_GET_CAPACITY, major, minor, blocks, + blocksize); +} + +static LIST_HEAD(nfhd_list); + +static int major_num; +module_param(major_num, int, 0); + +struct nfhd_device { + struct list_head list; + int id; + u32 blocks, bsize; + int bshift; + struct request_queue *queue; + struct gendisk *disk; +}; + +static int nfhd_make_request(struct request_queue *queue, struct bio *bio) +{ + struct nfhd_device *dev = queue->queuedata; + struct bio_vec *bvec; + int i, dir, len, shift; + sector_t sec = bio->bi_sector; + + dir = bio_data_dir(bio); + shift = dev->bshift; + bio_for_each_segment(bvec, bio, i) { + len = bvec->bv_len; + len >>= 9; + nfhd_read_write(dev->id, 0, dir, sec >> shift, len >> shift, + bvec_to_phys(bvec)); + sec += len; + } + bio_endio(bio, 0); + return 0; +} + +static int nfhd_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + struct nfhd_device *dev = bdev->bd_disk->private_data; + + geo->cylinders = dev->blocks >> (6 - dev->bshift); + geo->heads = 4; + geo->sectors = 16; + + return 0; +} + +static const struct block_device_operations nfhd_ops = { + .owner = THIS_MODULE, + .getgeo = nfhd_getgeo, +}; + +static int __init nfhd_init_one(int id, u32 blocks, u32 bsize) +{ + struct nfhd_device *dev; + int dev_id = id - NFHD_DEV_OFFSET; + + pr_info("nfhd%u: found device with %u blocks (%u bytes)\n", dev_id, + blocks, bsize); + + if (bsize < 512 || (bsize & (bsize - 1))) { + pr_warn("nfhd%u: invalid block size\n", dev_id); + return -EINVAL; + } + + dev = kmalloc(sizeof(struct nfhd_device), GFP_KERNEL); + if (!dev) + goto out; + + dev->id = id; + dev->blocks = blocks; + dev->bsize = bsize; + dev->bshift = ffs(bsize) - 10; + + dev->queue = blk_alloc_queue(GFP_KERNEL); + if (dev->queue == NULL) + goto free_dev; + + dev->queue->queuedata = dev; + blk_queue_make_request(dev->queue, nfhd_make_request); + blk_queue_logical_block_size(dev->queue, bsize); + + dev->disk = alloc_disk(16); + if (!dev->disk) + goto free_queue; + + dev->disk->major = major_num; + dev->disk->first_minor = dev_id * 16; + dev->disk->fops = &nfhd_ops; + dev->disk->private_data = dev; + sprintf(dev->disk->disk_name, "nfhd%u", dev_id); + set_capacity(dev->disk, (sector_t)blocks * (bsize / 512)); + dev->disk->queue = dev->queue; + + add_disk(dev->disk); + + list_add_tail(&dev->list, &nfhd_list); + + return 0; + +free_queue: + blk_cleanup_queue(dev->queue); +free_dev: + kfree(dev); +out: + return -ENOMEM; +} + +static int __init nfhd_init(void) +{ + u32 blocks, bsize; + int i; + + nfhd_id = nf_get_id("XHDI"); + if (!nfhd_id) + return -ENODEV; + + major_num = register_blkdev(major_num, "nfhd"); + if (major_num <= 0) { + pr_warn("nfhd: unable to get major number\n"); + return major_num; + } + + for (i = NFHD_DEV_OFFSET; i < 24; i++) { + if (nfhd_get_capacity(i, 0, &blocks, &bsize)) + continue; + nfhd_init_one(i, blocks, bsize); + } + + return 0; +} + +static void __exit nfhd_exit(void) +{ + struct nfhd_device *dev, *next; + + list_for_each_entry_safe(dev, next, &nfhd_list, list) { + list_del(&dev->list); + del_gendisk(dev->disk); + put_disk(dev->disk); + blk_cleanup_queue(dev->queue); + kfree(dev); + } + unregister_blkdev(major_num, "nfhd"); +} + +module_init(nfhd_init); +module_exit(nfhd_exit); + +MODULE_LICENSE("GPL"); -- cgit v1.2.3-58-ga151 From 37b0b65f6362269a4cb86ed8be1c0ac8caa497f8 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 18 Nov 2008 21:02:19 +0100 Subject: m68k/atari: ARAnyM - Add support for console access [geert: Cleanups and updates] Signed-off-by: Roman Zippel Signed-off-by: Geert Uytterhoeven Acked-by: Petr Stehlik --- arch/m68k/Kconfig | 8 +++ arch/m68k/emu/Makefile | 1 + arch/m68k/emu/natfeat.c | 38 ------------ arch/m68k/emu/nfcon.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 171 insertions(+), 38 deletions(-) create mode 100644 arch/m68k/emu/nfcon.c (limited to 'arch/m68k/Kconfig') diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 2c890b56c96e..6719c5629c5d 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -255,6 +255,14 @@ config NFBLOCK which allows direct access to the hard drives without using the hardware emulation. +config NFCON + tristate "NatFeat console driver" + depends on NATFEAT + help + Say Y to include support for the ARAnyM NatFeat console driver + which allows the console output to be redirected to the stderr + output of ARAnyM. + comment "Processor type" config M68020 diff --git a/arch/m68k/emu/Makefile b/arch/m68k/emu/Makefile index fc4f77a3d35c..a83ef1e497b3 100644 --- a/arch/m68k/emu/Makefile +++ b/arch/m68k/emu/Makefile @@ -5,3 +5,4 @@ obj-y += natfeat.o obj-$(CONFIG_NFBLOCK) += nfblock.o +obj-$(CONFIG_NFCON) += nfcon.o diff --git a/arch/m68k/emu/natfeat.c b/arch/m68k/emu/natfeat.c index 987d77322178..2291a7d69d49 100644 --- a/arch/m68k/emu/natfeat.c +++ b/arch/m68k/emu/natfeat.c @@ -35,24 +35,6 @@ asm("\n" EXPORT_SYMBOL_GPL(nf_get_id); EXPORT_SYMBOL_GPL(nf_call); -static int stderr_id; - -static void nf_write(struct console *co, const char *str, unsigned int count) -{ - char buf[68]; - - buf[64] = 0; - while (count > 64) { - memcpy(buf, str, 64); - nf_call(stderr_id, buf); - str += 64; - count -= 64; - } - memcpy(buf, str, count); - buf[count] = 0; - nf_call(stderr_id, buf); -} - void nfprint(const char *fmt, ...) { static char buf[256]; @@ -65,26 +47,6 @@ void nfprint(const char *fmt, ...) va_end(ap); } -static struct console nf_console_driver = { - .name = "debug", - .write = nf_write, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -static int __init nf_debug_setup(char *arg) -{ - if (strcmp(arg, "emu")) - return 0; - - stderr_id = nf_get_id("NF_STDERR"); - if (stderr_id) - register_console(&nf_console_driver); - return 0; -} - -early_param("debug", nf_debug_setup); - static void nf_poweroff(void) { long id = nf_get_id("NF_SHUTDOWN"); 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 @@ +/* + * ARAnyM console driver + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static int stderr_id; +static struct tty_driver *nfcon_tty_driver; + +static void nfputs(const char *str, unsigned int count) +{ + char buf[68]; + + buf[64] = 0; + while (count > 64) { + memcpy(buf, str, 64); + nf_call(stderr_id, buf); + str += 64; + count -= 64; + } + memcpy(buf, str, count); + buf[count] = 0; + nf_call(stderr_id, buf); +} + +static void nfcon_write(struct console *con, const char *str, + unsigned int count) +{ + nfputs(str, count); +} + +static struct tty_driver *nfcon_device(struct console *con, int *index) +{ + *index = 0; + return (con->flags & CON_ENABLED) ? nfcon_tty_driver : NULL; +} + +static struct console nf_console = { + .name = "nfcon", + .write = nfcon_write, + .device = nfcon_device, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + + +static int nfcon_tty_open(struct tty_struct *tty, struct file *filp) +{ + return 0; +} + +static void nfcon_tty_close(struct tty_struct *tty, struct file *filp) +{ +} + +static int nfcon_tty_write(struct tty_struct *tty, const unsigned char *buf, + int count) +{ + nfputs(buf, count); + return count; +} + +static int nfcon_tty_put_char(struct tty_struct *tty, unsigned char ch) +{ + char temp[2] = { ch, 0 }; + + nf_call(stderr_id, temp); + return 1; +} + +static int nfcon_tty_write_room(struct tty_struct *tty) +{ + return 64; +} + +static const struct tty_operations nfcon_tty_ops = { + .open = nfcon_tty_open, + .close = nfcon_tty_close, + .write = nfcon_tty_write, + .put_char = nfcon_tty_put_char, + .write_room = nfcon_tty_write_room, +}; + +#ifndef MODULE + +static int __init nf_debug_setup(char *arg) +{ + if (strcmp(arg, "nfcon")) + return 0; + + stderr_id = nf_get_id("NF_STDERR"); + if (stderr_id) { + nf_console.flags |= CON_ENABLED; + register_console(&nf_console); + } + + return 0; +} + +early_param("debug", nf_debug_setup); + +#endif /* !MODULE */ + +static int __init nfcon_init(void) +{ + int res; + + stderr_id = nf_get_id("NF_STDERR"); + if (!stderr_id) + return -ENODEV; + + nfcon_tty_driver = alloc_tty_driver(1); + if (!nfcon_tty_driver) + return -ENOMEM; + + nfcon_tty_driver->owner = THIS_MODULE; + nfcon_tty_driver->driver_name = "nfcon"; + nfcon_tty_driver->name = "nfcon"; + nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM; + nfcon_tty_driver->subtype = SYSTEM_TYPE_TTY; + nfcon_tty_driver->init_termios = tty_std_termios; + nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW; + + tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops); + res = tty_register_driver(nfcon_tty_driver); + if (res) { + pr_err("failed to register nfcon tty driver\n"); + put_tty_driver(nfcon_tty_driver); + return res; + } + + if (!(nf_console.flags & CON_ENABLED)) + register_console(&nf_console); + + return 0; +} + +static void __exit nfcon_exit(void) +{ + unregister_console(&nf_console); + tty_unregister_driver(nfcon_tty_driver); + put_tty_driver(nfcon_tty_driver); +} + +module_init(nfcon_init); +module_exit(nfcon_exit); + +MODULE_LICENSE("GPL"); -- cgit v1.2.3-58-ga151 From 9cd7b148312f6971f37cfac6a490688286bd1522 Mon Sep 17 00:00:00 2001 From: Milan Jurik Date: Tue, 18 Nov 2008 21:02:18 +0100 Subject: m68k/atari: ARAnyM - Add support for network access [petr: Second author] [michael, geert: Cleanups and updates] Signed-off-by: Milan Jurik Signed-off-by: Petr Stehlik Signed-off-by: Michael Schmitz Signed-off-by: Geert Uytterhoeven Cc: netdev@vger.kernel.org --- arch/m68k/Kconfig | 8 ++ arch/m68k/emu/Makefile | 1 + arch/m68k/emu/nfeth.c | 270 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 279 insertions(+) create mode 100644 arch/m68k/emu/nfeth.c (limited to 'arch/m68k/Kconfig') diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 6719c5629c5d..80df6ee7cac8 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -263,6 +263,14 @@ config NFCON which allows the console output to be redirected to the stderr output of ARAnyM. +config NFETH + tristate "NatFeat Ethernet support" + depends on NET_ETHERNET && NATFEAT + help + Say Y to include support for the ARAnyM NatFeat network device + which will emulate a regular ethernet device while presenting an + ethertap device to the host system. + comment "Processor type" config M68020 diff --git a/arch/m68k/emu/Makefile b/arch/m68k/emu/Makefile index a83ef1e497b3..7dc201080308 100644 --- a/arch/m68k/emu/Makefile +++ b/arch/m68k/emu/Makefile @@ -6,3 +6,4 @@ obj-y += natfeat.o obj-$(CONFIG_NFBLOCK) += nfblock.o obj-$(CONFIG_NFCON) += nfcon.o +obj-$(CONFIG_NFETH) += nfeth.o 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 @@ +/* + * atari_nfeth.c - ARAnyM ethernet card driver for GNU/Linux + * + * Copyright (c) 2005 Milan Jurik, Petr Stehlik of ARAnyM dev team + * + * Based on ARAnyM driver for FreeMiNT written by Standa Opichal + * + * This software may be used and distributed according to the terms of + * the GNU General Public License (GPL), incorporated herein by reference. + */ + +#define DRV_VERSION "0.3" +#define DRV_RELDATE "10/12/2005" + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +enum { + GET_VERSION = 0,/* no parameters, return NFAPI_VERSION in d0 */ + XIF_INTLEVEL, /* no parameters, return Interrupt Level in d0 */ + XIF_IRQ, /* acknowledge interrupt from host */ + XIF_START, /* (ethX), called on 'ifup', start receiver thread */ + XIF_STOP, /* (ethX), called on 'ifdown', stop the thread */ + XIF_READLENGTH, /* (ethX), return size of network data block to read */ + XIF_READBLOCK, /* (ethX, buffer, size), read block of network data */ + XIF_WRITEBLOCK, /* (ethX, buffer, size), write block of network data */ + XIF_GET_MAC, /* (ethX, buffer, size), return MAC HW addr in buffer */ + XIF_GET_IPHOST, /* (ethX, buffer, size), return IP address of host */ + XIF_GET_IPATARI,/* (ethX, buffer, size), return IP address of atari */ + XIF_GET_NETMASK /* (ethX, buffer, size), return IP netmask */ +}; + +#define MAX_UNIT 8 + +/* These identify the driver base version and may not be removed. */ +static const char version[] __devinitdata = + KERN_INFO KBUILD_MODNAME ".c:v" DRV_VERSION " " DRV_RELDATE + " S.Opichal, M.Jurik, P.Stehlik\n" + KERN_INFO " http://aranym.org/\n"; + +MODULE_AUTHOR("Milan Jurik"); +MODULE_DESCRIPTION("Atari NFeth driver"); +MODULE_LICENSE("GPL"); +/* +MODULE_PARM(nfeth_debug, "i"); +MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)"); +*/ + + +static long nfEtherID; +static int nfEtherIRQ; + +struct nfeth_private { + int ethX; +}; + +static struct net_device *nfeth_dev[MAX_UNIT]; + +static int nfeth_open(struct net_device *dev) +{ + struct nfeth_private *priv = netdev_priv(dev); + int res; + + res = nf_call(nfEtherID + XIF_START, priv->ethX); + netdev_dbg(dev, "%s: %d\n", __func__, res); + + /* Ready for data */ + netif_start_queue(dev); + + return 0; +} + +static int nfeth_stop(struct net_device *dev) +{ + struct nfeth_private *priv = netdev_priv(dev); + + /* No more data */ + netif_stop_queue(dev); + + nf_call(nfEtherID + XIF_STOP, priv->ethX); + + return 0; +} + +/* + * Read a packet out of the adapter and pass it to the upper layers + */ +static inline void recv_packet(struct net_device *dev) +{ + struct nfeth_private *priv = netdev_priv(dev); + unsigned short pktlen; + struct sk_buff *skb; + + /* read packet length (excluding 32 bit crc) */ + pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX); + + netdev_dbg(dev, "%s: %u\n", __func__, pktlen); + + if (!pktlen) { + netdev_dbg(dev, "%s: pktlen == 0\n", __func__); + dev->stats.rx_errors++; + return; + } + + skb = dev_alloc_skb(pktlen + 2); + if (!skb) { + netdev_dbg(dev, "%s: out of mem (buf_alloc failed)\n", + __func__); + dev->stats.rx_dropped++; + return; + } + + skb->dev = dev; + skb_reserve(skb, 2); /* 16 Byte align */ + skb_put(skb, pktlen); /* make room */ + nf_call(nfEtherID + XIF_READBLOCK, priv->ethX, virt_to_phys(skb->data), + pktlen); + + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->last_rx = jiffies; + dev->stats.rx_packets++; + dev->stats.rx_bytes += pktlen; + + /* and enqueue packet */ + return; +} + +static irqreturn_t nfeth_interrupt(int irq, void *dev_id) +{ + int i, m, mask; + + mask = nf_call(nfEtherID + XIF_IRQ, 0); + for (i = 0, m = 1; i < MAX_UNIT; m <<= 1, i++) { + if (mask & m && nfeth_dev[i]) { + recv_packet(nfeth_dev[i]); + nf_call(nfEtherID + XIF_IRQ, m); + } + } + return IRQ_HANDLED; +} + +static int nfeth_xmit(struct sk_buff *skb, struct net_device *dev) +{ + unsigned int len; + char *data, shortpkt[ETH_ZLEN]; + struct nfeth_private *priv = netdev_priv(dev); + + data = skb->data; + len = skb->len; + if (len < ETH_ZLEN) { + memset(shortpkt, 0, ETH_ZLEN); + memcpy(shortpkt, data, len); + data = shortpkt; + len = ETH_ZLEN; + } + + netdev_dbg(dev, "%s: send %u bytes\n", __func__, len); + nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data), + len); + + dev->stats.tx_packets++; + dev->stats.tx_bytes += len; + + dev_kfree_skb(skb); + return 0; +} + +static void nfeth_tx_timeout(struct net_device *dev) +{ + dev->stats.tx_errors++; + netif_wake_queue(dev); +} + +static const struct net_device_ops nfeth_netdev_ops = { + .ndo_open = nfeth_open, + .ndo_stop = nfeth_stop, + .ndo_start_xmit = nfeth_xmit, + .ndo_tx_timeout = nfeth_tx_timeout, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, +}; + +static struct net_device * __init nfeth_probe(int unit) +{ + struct net_device *dev; + struct nfeth_private *priv; + char mac[ETH_ALEN], host_ip[32], local_ip[32]; + int err; + + if (!nf_call(nfEtherID + XIF_GET_MAC, unit, mac, ETH_ALEN)) + return NULL; + + dev = alloc_etherdev(sizeof(struct nfeth_private)); + if (!dev) + return NULL; + + dev->irq = nfEtherIRQ; + dev->netdev_ops = &nfeth_netdev_ops; + + dev->flags |= NETIF_F_NO_CSUM; + memcpy(dev->dev_addr, mac, ETH_ALEN); + + priv = netdev_priv(dev); + priv->ethX = unit; + + err = register_netdev(dev); + if (err) { + free_netdev(dev); + return NULL; + } + + nf_call(nfEtherID + XIF_GET_IPHOST, unit, + host_ip, sizeof(host_ip)); + nf_call(nfEtherID + XIF_GET_IPATARI, unit, + local_ip, sizeof(local_ip)); + + netdev_info(dev, KBUILD_MODNAME " addr:%s (%s) HWaddr:%pM\n", host_ip, + local_ip, mac); + + return dev; +} + +static int __init nfeth_init(void) +{ + long ver; + int error, i; + + nfEtherID = nf_get_id("ETHERNET"); + if (!nfEtherID) + return -ENODEV; + + ver = nf_call(nfEtherID + GET_VERSION); + pr_info("API %lu\n", ver); + + nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL); + error = request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED, + "eth emu", nfeth_interrupt); + if (error) { + pr_err("request for irq %d failed %d", nfEtherIRQ, error); + return error; + } + + for (i = 0; i < MAX_UNIT; i++) + nfeth_dev[i] = nfeth_probe(i); + + return 0; +} + +static void __exit nfeth_cleanup(void) +{ + int i; + + for (i = 0; i < MAX_UNIT; i++) { + if (nfeth_dev[i]) { + unregister_netdev(nfeth_dev[0]); + free_netdev(nfeth_dev[0]); + } + } + free_irq(nfEtherIRQ, nfeth_interrupt); +} + +module_init(nfeth_init); +module_exit(nfeth_cleanup); -- cgit v1.2.3-58-ga151