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()
This commit is contained in:
Коммит
dc113c1f1d
|
@ -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
|
||||
|
@ -242,6 +240,37 @@ 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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -33,10 +33,6 @@ void __init amiga_chip_init(void)
|
|||
if (!AMIGAHW_PRESENT(CHIP_RAM))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Remove the first 4 pages where PPC exception handlers will be located
|
||||
*/
|
||||
amiga_chip_size -= 0x4000;
|
||||
chipram_res.end = amiga_chip_size-1;
|
||||
request_resource(&iomem_resource, &chipram_res);
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# Makefile for Linux arch/m68k/emu source directory
|
||||
#
|
||||
|
||||
obj-y += natfeat.o
|
||||
|
||||
obj-$(CONFIG_NFBLOCK) += nfblock.o
|
||||
obj-$(CONFIG_NFCON) += nfcon.o
|
||||
obj-$(CONFIG_NFETH) += nfeth.o
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* natfeat.c - ARAnyM hardware support via Native Features (natfeats)
|
||||
*
|
||||
* Copyright (c) 2005 Petr Stehlik of ARAnyM dev team
|
||||
*
|
||||
* Reworked for Linux by Roman Zippel <zippel@linux-m68k.org>
|
||||
*
|
||||
* This software may be used and distributed according to the terms of
|
||||
* the GNU General Public License (GPL), incorporated herein by reference.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/natfeat.h>
|
||||
|
||||
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);
|
||||
|
||||
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 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;
|
||||
}
|
|
@ -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 <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/genhd.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/natfeat.h>
|
||||
|
||||
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");
|
|
@ -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 <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/natfeat.h>
|
||||
|
||||
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");
|
|
@ -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 <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/natfeat.h>
|
||||
#include <asm/virtconvert.h>
|
||||
|
||||
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);
|
|
@ -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 */
|
|
@ -113,6 +113,8 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
|
|||
wrusp(usp);
|
||||
}
|
||||
|
||||
extern int handle_kernel_fault(struct pt_regs *regs);
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#ifdef CONFIG_SUN3X
|
||||
#include <asm/dvma.h>
|
||||
#endif
|
||||
#include <asm/natfeat.h>
|
||||
|
||||
#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
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <linux/personality.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
@ -51,7 +52,7 @@
|
|||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
const int frame_extra_sizes[16] = {
|
||||
static const int frame_extra_sizes[16] = {
|
||||
[1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
|
||||
[2] = sizeof(((struct frame *)0)->un.fmt2),
|
||||
[3] = sizeof(((struct frame *)0)->un.fmt3),
|
||||
|
@ -69,6 +70,27 @@ const int frame_extra_sizes[16] = {
|
|||
[15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */
|
||||
};
|
||||
|
||||
int handle_kernel_fault(struct pt_regs *regs)
|
||||
{
|
||||
const struct exception_table_entry *fixup;
|
||||
struct pt_regs *tregs;
|
||||
|
||||
/* Are we prepared to handle this kernel fault? */
|
||||
fixup = search_exception_tables(regs->pc);
|
||||
if (!fixup)
|
||||
return 0;
|
||||
|
||||
/* Create a new four word stack frame, discarding the old one. */
|
||||
regs->stkadj = frame_extra_sizes[regs->format];
|
||||
tregs = (struct pt_regs *)((long)regs + regs->stkadj);
|
||||
tregs->vector = regs->vector;
|
||||
tregs->format = 0;
|
||||
tregs->pc = fixup->fixup;
|
||||
tregs->sr = regs->sr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomically swap in the new signal mask, and wait for a signal.
|
||||
*/
|
||||
|
|
|
@ -48,10 +48,7 @@ asmlinkage void nmihandler(void);
|
|||
asmlinkage void fpu_emu(void);
|
||||
#endif
|
||||
|
||||
e_vector vectors[256] = {
|
||||
[VEC_BUSERR] = buserr,
|
||||
[VEC_SYS] = system_call,
|
||||
};
|
||||
e_vector vectors[256];
|
||||
|
||||
/* nmi handler for the Amiga */
|
||||
asm(".text\n"
|
||||
|
@ -61,10 +58,11 @@ asm(".text\n"
|
|||
/*
|
||||
* this must be called very early as the kernel might
|
||||
* use some instruction that are emulated on the 060
|
||||
* and so we're prepared for early probe attempts (e.g. nf_init).
|
||||
*/
|
||||
void __init base_trap_init(void)
|
||||
{
|
||||
if(MACH_IS_SUN3X) {
|
||||
if (MACH_IS_SUN3X) {
|
||||
extern e_vector *sun3x_prom_vbr;
|
||||
|
||||
__asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
|
||||
|
@ -79,6 +77,10 @@ void __init base_trap_init(void)
|
|||
|
||||
vectors[VEC_UNIMPII] = unimp_vec;
|
||||
}
|
||||
|
||||
vectors[VEC_BUSERR] = buserr;
|
||||
vectors[VEC_ILLEGAL] = trap;
|
||||
vectors[VEC_SYS] = system_call;
|
||||
}
|
||||
|
||||
void __init trap_init (void)
|
||||
|
@ -1055,9 +1057,11 @@ asmlinkage void trap_c(struct frame *fp)
|
|||
siginfo_t info;
|
||||
|
||||
if (fp->ptregs.sr & PS_S) {
|
||||
if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
|
||||
/* traced a trapping instruction */
|
||||
} else
|
||||
if (fp->ptregs.vector == VEC_TRACE << 2) {
|
||||
/* traced a trapping instruction on a 68020/30,
|
||||
* real exception will be executed afterwards.
|
||||
*/
|
||||
} else if (!handle_kernel_fault(&fp->ptregs))
|
||||
bad_super_trap(fp);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
#EXTRA_AFLAGS += -DFPU_EMU_DEBUG
|
||||
#EXTRA_CFLAGS += -DFPU_EMU_DEBUG
|
||||
#asflags-y := -DFPU_EMU_DEBUG
|
||||
#ccflags-y := -DFPU_EMU_DEBUG
|
||||
|
||||
obj-y := fp_entry.o fp_scan.o fp_util.o fp_move.o fp_movem.o \
|
||||
fp_cond.o fp_arith.o fp_log.o fp_trig.o
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <asm/pgalloc.h>
|
||||
|
||||
extern void die_if_kernel(char *, struct pt_regs *, long);
|
||||
extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */
|
||||
|
||||
int send_fault_sig(struct pt_regs *regs)
|
||||
{
|
||||
|
@ -35,21 +34,8 @@ int send_fault_sig(struct pt_regs *regs)
|
|||
force_sig_info(siginfo.si_signo,
|
||||
&siginfo, current);
|
||||
} else {
|
||||
const struct exception_table_entry *fixup;
|
||||
|
||||
/* Are we prepared to handle this kernel fault? */
|
||||
if ((fixup = search_exception_tables(regs->pc))) {
|
||||
struct pt_regs *tregs;
|
||||
/* Create a new four word stack frame, discarding the old
|
||||
one. */
|
||||
regs->stkadj = frame_extra_sizes[regs->format];
|
||||
tregs = (struct pt_regs *)((ulong)regs + regs->stkadj);
|
||||
tregs->vector = regs->vector;
|
||||
tregs->format = 0;
|
||||
tregs->pc = fixup->fixup;
|
||||
tregs->sr = regs->sr;
|
||||
if (handle_kernel_fault(regs))
|
||||
return -1;
|
||||
}
|
||||
|
||||
//if (siginfo.si_signo == SIGBUS)
|
||||
// force_sig_info(siginfo.si_signo,
|
||||
|
|
|
@ -1768,8 +1768,8 @@ static int __init amiga_floppy_probe(struct platform_device *pdev)
|
|||
return -EBUSY;
|
||||
|
||||
ret = -ENOMEM;
|
||||
if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) ==
|
||||
NULL) {
|
||||
raw_buf = amiga_chip_alloc(RAW_BUF_SIZE, "Floppy");
|
||||
if (!raw_buf) {
|
||||
printk("fd: cannot get chip mem buffer\n");
|
||||
goto out_blkdev;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче