Hi,

starting the Atari patch bomb on a light note: attached is the (minimal)
patch required to get Falcon IDE working. Tested under ARAnyM, may require
a slightly different solution once I get to testing SCSI properly (this
patch lets the IDE interrupt register on top of stdma_int which really
handles dispatching the appropriate interrupt handler; a different
approach would be to allow interrupt registration to fail, either
explicitly in ide-probe.c or by passing a SA_MAYFAIL flag :-), this would
help to prevent entering the handler twice for each interrupt which may
currently be the case).

The patch (and the rest of my patches) is relative to m68k CVS. Geert's
patch queue already has this one.

Signed-Off-By: /me, who else :-)

        Michael
--- linux-2.6.19-m68k-cvs/arch/m68k/atari/config.c      2006-12-02 
00:16:50.000000000 +0100
+++ linux-2.6.19-m68k/arch/m68k/atari/config.c  2006-12-08 18:49:02.000000000 
+0100
@@ -32,6 +32,10 @@
 #include <linux/ioport.h>
 #include <linux/vt_kern.h>
 
+#ifdef CONFIG_NATFEAT
+#include "natfeat.h"
+#endif
+
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
 #include <asm/atarihw.h>
@@ -207,6 +211,12 @@
     }
 }
 
+void atari_poweroff(void)
+{
+#ifdef CONFIG_NATFEAT
+    nf_shutdown();
+#endif
+}
 
     /*
      *  Setup the Atari configuration info
@@ -218,6 +228,10 @@
 
     memset(&atari_hw_present, 0, sizeof(atari_hw_present));
 
+#ifdef CONFIG_NATFEAT
+    nf_init();
+#endif
+
     atari_debug_init();
 
     ioport_resource.end  = 0xFFFFFFFF;  /* Change size of I/O space from 64KB
@@ -229,6 +243,8 @@
     mach_get_hardware_list = atari_get_hardware_list;
     mach_gettimeoffset   = atari_gettimeoffset;
     mach_reset           = atari_reset;
+    mach_halt            = atari_poweroff;
+    mach_power_off       = atari_poweroff;
     mach_max_dma_address = 0xffffff;
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
     mach_beep          = atari_mksound;
@@ -614,6 +630,11 @@
 
 static void atari_get_model(char *model)
 {
+#ifdef CONFIG_NATFEAT
+    if (nf_name1(model, 80)) { // char model[80] defined in kernel/setup.c
+       return;
+    }
+#endif
     strcpy(model, "Atari ");
     switch (atari_mch_cookie >> 16) {
        case ATARI_MCH_ST:
--- linux-2.6.19-m68k-cvs/arch/m68k/atari/Makefile      2003-02-10 
20:34:25.000000000 +0100
+++ linux-2.6.19-m68k/arch/m68k/atari/Makefile  2006-12-08 18:49:02.000000000 
+0100
@@ -3,8 +3,12 @@
 #
 
 obj-y          := config.o time.o debug.o ataints.o stdma.o \
-                       atasound.o stram.o atari_ksyms.o
+                       atakeyb.o atasound.o stram.o atari_ksyms.o
 
 ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_HADES)    += hades-pci.o
 endif
+
+ifeq ($(CONFIG_NATFEAT),y)
+obj-$(CONFIG_NATFEAT)  += natfeat.o
+endif
--- linux-2.6.19-m68k-cvs/arch/m68k/atari/natfeat.h     2006-12-08 
18:49:02.000000000 +0100
+++ linux-2.6.19-m68k/arch/m68k/atari/natfeat.h 2006-12-08 18:49:02.000000000 
+0100
@@ -0,0 +1,35 @@
+/*
+ * 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
+
+struct nf_ops
+{
+       long (*get_id)(const char *);
+       long (*call)(long id, ...);
+       long res[3];
+};
+
+struct nf_ops *nf_init(void);
+
+int nf_name(char *buf, int bufsize);
+int nf_debug(const char *msg);
+int nf_shutdown(void);
+
+int nf_ethernet_check_version(char *errmsg, int errmsglen);
+int nf_ethernet_get_irq(void);
+int nf_ethernet_get_hw_addr(int ethX, char *buffer, int bufsize);
+int nf_ethernet_interrupt(int bit);
+int nf_ethernet_read_packet_len(int ethX);
+void nf_ethernet_read_block(int ethX, char *buffer, int len);
+void nf_ethernet_write_block(int ethX, char *buffer, int len);
+void nf_ethernet_xif_start(int ethX);
+void nf_ethernet_xif_stop(int ethX);
+# endif /* _natfeat_h */
--- linux-2.6.19-m68k-cvs/arch/m68k/atari/ethernet_nfapi.h      2006-12-08 
18:49:02.000000000 +0100
+++ linux-2.6.19-m68k/arch/m68k/atari/ethernet_nfapi.h  2006-12-08 
18:49:02.000000000 +0100
@@ -0,0 +1,56 @@
+/*
+ * ARAnyM ethernet driver - header file.
+ *
+ * Copyright (c) 2002-2004 Standa and Petr of ARAnyM dev team (see AUTHORS)
+ * 
+ * This file is part of the ARAnyM project which builds a new and powerful
+ * TOS/FreeMiNT compatible virtual machine running on almost any hardware.
+ *
+ * ARAnyM is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * ARAnyM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ARAnyM; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _ARAETHER_NFAPI_H
+#define _ARAETHER_NFAPI_H
+
+/*
+   The code for the FreeMiNT driver was moved to the FreeMiNT CVS:
+   freemint/sys/sockets/xif/nfeth.
+
+   If you edit this file then you would need to synchronize it with the
+   driver in the freemint CVS (nfeth_nfapi.h).
+
+   if you change anything in the enum {} below you have to increase 
+   this ARAETHER_NFAPI_VERSION!
+*/
+#define ARAETHER_NFAPI_VERSION 0x00000005
+
+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 ETH(a) (nfEtherID + a)
+
+#endif /* _ARAETHER_NFAPI_H */
--- linux-2.6.19-m68k-cvs/arch/m68k/atari/natfeat.c     2006-12-08 
18:49:02.000000000 +0100
+++ linux-2.6.19-m68k/arch/m68k/atari/natfeat.c 2006-12-08 18:49:02.000000000 
+0100
@@ -0,0 +1,231 @@
+/*
+ * natfeat.c - 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.
+ */
+
+// #include <linux/config.h>
+#include <linux/types.h>
+#include <linux/string.h> // strncpy()
+#include <linux/kernel.h> // snprintf()
+#include <asm/io.h> // virt_to_phys()
+
+#include "natfeat.h"
+
+#ifdef CONFIG_ATARI_NFETH
+#include "natfeat_ethernet_nfapi.h"
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+static unsigned long nf_get_id_instr = 0x73004e75UL;
+static unsigned long nf_call_instr = 0x73014e75UL;
+
+static struct nf_ops _nf_ops = { &nf_get_id_instr, &nf_call_instr }; 
+static struct nf_ops *nf_ops = NULL; 
+
+#define NF_GETID(a)            nf_ops->get_id(virt_to_phys(a))
+
+int detect_native_features(void)
+{
+    int                ret;
+    long       save_sp, save_vbr;
+    static long tmp_vectors[5];
+    static char *nf_version = "NF_VERSION";
+       
+    __asm__ __volatile__
+       (       "movec  %/vbr,%2\n\t"   /* save vbr value            */
+               "movel  #Liierr,%3@(0x10)\n\t" /* set Illegal Insn vec */
+               "movec  %3,%/vbr\n\t"   /* set up temporary vectors  */
+               "movel  %/sp,%1\n\t"    /* save sp                   */
+               "moveq  #0,%0\n\t"              /* assume no NatFeats        */
+               "clrl   %/d0\n\t"               /* clear ID value register   */
+               "movel  %4,%/[EMAIL PROTECTED]"
+               "subql  #4,%/sp\n\t"
+               "dc     0x7300\n\t"                     /* call NatFeat GetID   
     */
+               "tstl   %/d0\n\t"               /* check ID value register   */
+               "sne    %0\n\t"                 /* if non-zero NatFeats work */
+               "Liierr:\n\t"
+               "movel  %1,%/sp\n\t"    /* restore sp                */
+               "movec  %2,%/vbr"               /* restore vbr               */
+               : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
+               : "a" (tmp_vectors), "a" (virt_to_phys(nf_version))
+               : "d0"                                  /* reg d0 used by 
NatFeats   */
+        );
+
+    return( ret );
+}
+
+struct nf_ops * nf_init(void)
+{
+       if (detect_native_features()) {
+               nf_ops = &_nf_ops;
+               nf_debug("NatFeats found\n");
+               return nf_ops;
+       }
+       
+       return NULL;
+}
+
+/****************/
+/* NF Basic Set */
+int nf_name1(char *buf, int bufsize)
+{
+       if (nf_ops) {
+               static long nfid_name = 0;
+               if (nfid_name == 0) {
+                       nfid_name = NF_GETID("NF_NAME");
+               }
+
+               if (nfid_name) {
+                       nf_ops->call(nfid_name+1, virt_to_phys(buf), bufsize); 
// TODO: lock buf to prevent swap out
+                       return TRUE;
+               }
+       }
+        
+       return FALSE;
+}
+
+int nf_debug(const char *msg)
+{
+       if (nf_ops) {
+               static long nfid_stderr = 0;
+               if (nfid_stderr == 0) {
+                       nfid_stderr = NF_GETID("NF_STDERR");
+               }
+               
+               if (nfid_stderr) {
+                       nf_ops->call(nfid_stderr, virt_to_phys(msg)); // TODO: 
lock msg to prevent swap out
+                       return TRUE;
+               }
+       }
+       
+       return FALSE;
+}
+
+int nf_shutdown(void)
+{
+       if (nf_ops) {
+               long shutdown_id = NF_GETID("NF_SHUTDOWN");
+               
+               if (shutdown_id) {
+                       nf_ops->call(shutdown_id);
+                       return TRUE; /* never returns actually */
+               }
+       }
+
+       return FALSE;
+}
+
+#ifdef CONFIG_ATARI_NFETH
+
+/****************************/
+/* NatFeat Ethernet support */
+static long nfEtherID = 0;
+
+static int is_nf_eth(void)
+{
+       if (nf_ops) {
+               if (nfEtherID == 0) {
+                       nfEtherID = NF_GETID("ETHERNET");
+               }
+       }
+       return (nfEtherID != 0);
+}
+
+int nf_ethernet_check_version(char *errmsg, int errmsglen)
+{
+       if (is_nf_eth()) {
+               static unsigned long host_ver = 0;
+               if (host_ver == 0) {
+                       host_ver = nf_ops->call(ETH(GET_VERSION));
+               }
+               if (host_ver == ARAETHER_NFAPI_VERSION) {
+                       return TRUE;
+               }
+               else {
+                       // API version mismatch
+                       if (errmsg != NULL) {
+                               snprintf(errmsg, errmsglen,
+                                       "NatFeat Ethernet API: expected %d, got 
%ld",
+                                       ARAETHER_NFAPI_VERSION, host_ver);
+                       }
+                       return FALSE;
+               }
+       }
+       if (errmsg != NULL) {
+               strncpy(errmsg, "NatFeat Ethernet support not found", 
errmsglen);
+       }
+       return FALSE;
+}
+
+int nf_ethernet_get_irq(void)
+{
+       return is_nf_eth() ? nf_ops->call(ETH(XIF_INTLEVEL)) : 0;
+}
+
+int nf_ethernet_get_hw_addr(int ethX, char *buffer, int bufsize)
+{
+       if (is_nf_eth()) {
+               return nf_ops->call(ETH(XIF_GET_MAC), (unsigned long)ethX, 
virt_to_phys(buffer), (unsigned long)bufsize); // TODO: lock buffer to prevent 
swap out
+       }
+       return FALSE;
+}
+
+int nf_ethernet_interrupt(int bit)
+{
+       if (is_nf_eth()) {
+               return nf_ops->call(ETH(XIF_IRQ), (unsigned long)bit);
+       }
+       return 0;
+}
+
+int nf_ethernet_read_packet_len(int ethX)
+{
+       if (is_nf_eth()) {
+               return nf_ops->call(ETH(XIF_READLENGTH), (unsigned long)ethX);
+       }
+       return 0;
+}
+
+void nf_ethernet_read_block(int ethX, char *buffer, int len)
+{
+       if (is_nf_eth()) {
+               nf_ops->call(ETH(XIF_READBLOCK), (unsigned long)ethX, 
virt_to_phys(buffer), (unsigned long)len); // TODO: lock buffer to prevent swap 
out
+       }
+}
+
+void nf_ethernet_write_block(int ethX, char *buffer, int len)
+{
+       if (is_nf_eth()) {
+               nf_ops->call(ETH(XIF_WRITEBLOCK), (unsigned long)ethX, 
virt_to_phys(buffer), (unsigned long)len); // TODO: lock buffer to prevent swap 
out
+       }
+}
+
+void nf_ethernet_xif_start(int ethX)
+{
+       if (is_nf_eth()) {
+               nf_ops->call(ETH(XIF_START), (unsigned long)ethX);
+       }
+}
+
+void nf_ethernet_xif_stop(int ethX)
+{
+       if (is_nf_eth()) {
+               nf_ops->call(ETH(XIF_STOP), (unsigned long)ethX);
+       }
+}
+#endif // CONFIG_ATARI_NFETH
+
+/*
+vim:ts=4:sw=4:
+*/
--- linux-2.6.19-m68k-cvs/arch/m68k/atari/natfeat_ethernet_nfapi.h      
2006-12-08 18:49:02.000000000 +0100
+++ linux-2.6.19-m68k/arch/m68k/atari/natfeat_ethernet_nfapi.h  2006-12-08 
18:49:02.000000000 +0100
@@ -0,0 +1,56 @@
+/*
+ * ARAnyM ethernet driver - header file.
+ *
+ * Copyright (c) 2002-2004 Standa and Petr of ARAnyM dev team (see AUTHORS)
+ * 
+ * This file is part of the ARAnyM project which builds a new and powerful
+ * TOS/FreeMiNT compatible virtual machine running on almost any hardware.
+ *
+ * ARAnyM is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * ARAnyM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ARAnyM; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _ARAETHER_NFAPI_H
+#define _ARAETHER_NFAPI_H
+
+/*
+   The code for the FreeMiNT driver was moved to the FreeMiNT CVS:
+   freemint/sys/sockets/xif/nfeth.
+
+   If you edit this file then you would need to synchronize it with the
+   driver in the freemint CVS (nfeth_nfapi.h).
+
+   if you change anything in the enum {} below you have to increase 
+   this ARAETHER_NFAPI_VERSION!
+*/
+#define ARAETHER_NFAPI_VERSION 0x00000005
+
+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 ETH(a) (nfEtherID + a)
+
+#endif /* _ARAETHER_NFAPI_H */
--- linux-2.6.19-m68k-cvs/arch/m68k/Kconfig     2006-09-03 17:54:52.000000000 
+0200
+++ linux-2.6.19-m68k/arch/m68k/Kconfig 2006-12-09 17:12:36.000000000 +0100
@@ -132,6 +132,31 @@
          information about which PCI hardware does work under Linux and which
          doesn't.
 
+config ATARI_ROM_ISA
+       bool "Atari ROM port ISA adapter support"
+       depends on ATARI
+       help
+         This option enables support for the ROM port ISA adapter used to 
+         operate ISA cards on Atari. Only 8  bit cards are supported, and
+         no interrupt lines are connected. 
+         The only driver currently using this adapter is the EtherNEC
+         driver for RTL8019AS based NE2000 compatible network cards.
+
+config ARANYM
+       bool "ARAnyM emulator support "
+       depends on ATARI
+       help
+         This option enables support for the ARAnyM emulator support
+         features. To use this kernel on ARAnyM, say Y here; otherwise say N.
+
+config NATFEAT
+       bool
+       depends on ARANYM
+       default y
+       help
+         This option enables support for ARAnyM native features, such as 
+         access to a disk image as /dev/hda. Useful with the ARANYM option.
+
 config MAC
        bool "Macintosh support"
        depends on !MMU_SUN3
--- linux-2.6.19-m68k-cvs/drivers/net/Makefile  2006-12-02 01:02:10.000000000 
+0100
+++ linux-2.6.19-m68k/drivers/net/Makefile      2006-12-09 17:13:01.000000000 
+0100
@@ -177,6 +177,8 @@
 obj-$(CONFIG_ATARILANCE) += atarilance.o
 obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o
 obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o
+obj-$(CONFIG_ATARI_NFETH) += atari_nfeth.o
+obj-$(CONFIG_ATARI_ETHERNEC) += atari_ethernec.o 8390.o
 obj-$(CONFIG_A2065) += a2065.o
 obj-$(CONFIG_HYDRA) += hydra.o 8390.o
 obj-$(CONFIG_ARIADNE) += ariadne.o
--- linux-2.6.19-m68k-cvs/drivers/net/Kconfig   2006-12-02 03:51:45.000000000 
+0100
+++ linux-2.6.19-m68k/drivers/net/Kconfig       2006-12-09 17:13:01.000000000 
+0100
@@ -397,6 +397,22 @@
          ACSI port ("ACSI node"). The driver works (has to work...) with a
          polled I/O scheme, so it's rather slow :-(
 
+config ATARI_NFETH
+       tristate "Atari NatFeat Ethernet support"
+       depends on NET_ETHERNET && ATARI && 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.
+
+config ATARI_ETHERNEC
+       tristate "Atari EtherNEC Ethernet support"
+       depends on NET_ETHERNET && ATARI && ATARI_ROM_ISA
+       help
+         Say Y to include support for the EtherNEC network adapter for the
+         ROM port. The driver works by polling instead of interrupts, so it
+         is quite slow.
+
 config SUN3LANCE
        tristate "Sun3/Sun3x on-board LANCE support"
        depends on NET_ETHERNET && (SUN3 || SUN3X)
--- linux-2.6.19-m68k-cvs/drivers/net/Space.c   2006-12-02 01:02:11.000000000 
+0100
+++ linux-2.6.19-m68k/drivers/net/Space.c       2006-12-09 17:13:01.000000000 
+0100
@@ -74,6 +74,8 @@
 extern struct net_device *seeq8005_probe(int unit);
 extern struct net_device *smc_init(int unit);
 extern struct net_device *atarilance_probe(int unit);
+extern struct net_device *atari_ethernec_probe(int unit);
+extern struct net_device *atari_nfeth_probe(struct net_device *);
 extern struct net_device *sun3lance_probe(int unit);
 extern struct net_device *sun3_82586_probe(int unit);
 extern struct net_device *apne_probe(int unit);
@@ -261,6 +263,12 @@
 #ifdef CONFIG_ATARILANCE       /* Lance-based Atari ethernet boards */
        {atarilance_probe, 0},
 #endif
+#ifdef CONFIG_ATARI_NFETH      /* ARAnyM tun/tap device */
+       {atari_nfeth_probe, 0},
+#endif
+#ifdef CONFIG_ATARI_ETHERNEC   /* NE2000 based ROM port ethernet cards */
+       {atari_ethernec_probe, 0},
+#endif
 #ifdef CONFIG_SUN3LANCE         /* sun3 onboard Lance chip */
        {sun3lance_probe, 0},
 #endif
--- linux-2.6.19-m68k-cvs/drivers/net/atari_nfeth.c     2006-12-08 
18:49:02.000000000 +0100
+++ linux-2.6.19-m68k/drivers/net/atari_nfeth.c 2006-12-08 18:49:02.000000000 
+0100
@@ -0,0 +1,327 @@
+/*
+ * 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.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <asm/atariints.h>
+
+#include "../../arch/m68k/atari/natfeat.h"
+
+#define DRV_NAME        "atari_nfeth"
+#define DRV_VERSION     "0.3"
+#define DRV_RELDATE     "10/12/2005"
+
+/* These identify the driver base version and may not be removed. */
+static char version[] __devinitdata =
+KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " S.Opichal, M.Jurik, 
P.Stehlik\n"
+KERN_INFO "  http://aranym.atari.org/\n";;
+
+MODULE_AUTHOR("Milan Jurik");
+MODULE_DESCRIPTION("Atari NFeth driver");
+MODULE_LICENSE("GPL");
+/*
+MODULE_PARM(atari_nfeth_debug, "i");
+MODULE_PARM_DESC(atari_nfeth_debug, "atari_nfeth_debug level (1-2)");
+*/
+
+#undef DEBUG
+
+struct atari_nfeth_private {
+       int ethX;
+       struct net_device_stats stats;
+       spinlock_t lock;
+};
+
+static inline int getEthX(struct net_device *dev)
+{
+       return ((struct atari_nfeth_private *)netdev_priv(dev))->ethX;
+}
+
+int atari_nfeth_open(struct net_device *dev);
+int atari_nfeth_stop(struct net_device *dev);
+irqreturn_t atari_nfeth_interrupt(int irq, void *dev_id, struct pt_regs *fp);
+int atari_nfeth_xmit(struct sk_buff *skb, struct net_device *dev);
+
+int atari_nfeth_open(struct net_device *dev)
+{
+       nf_ethernet_xif_start(getEthX(dev));
+
+       /* Set IRQ */
+       dev->irq = nf_ethernet_get_irq();
+       if (request_irq(dev->irq, atari_nfeth_interrupt, IRQ_TYPE_PRIO, 
dev->name, dev)) {
+               printk( DRV_NAME ": request for irq %d failed\n", dev->irq);
+               return( 0 );
+       }
+
+       /* Clean statistics */
+       memset(&(((struct atari_nfeth_private *)netdev_priv(dev))->stats), 0, 
sizeof(((struct atari_nfeth_private *)(dev->priv))->stats));
+
+       spin_lock_init(&(((struct atari_nfeth_private 
*)netdev_priv(dev))->lock));
+
+#ifdef DEBUG
+       printk( DRV_NAME ": open");
+#endif
+
+       /* Ready for data */
+       netif_start_queue(dev);
+
+       return 0;
+}
+
+int atari_nfeth_stop(struct net_device *dev)
+{
+       /* No more data */
+       netif_stop_queue(dev);
+
+       /* Release IRQ */
+       free_irq(dev->irq, dev);
+
+       nf_ethernet_xif_stop(getEthX(dev));
+
+       return 0;
+}
+
+/*
+ * Read a packet out of the adapter and pass it to the upper layers
+ */
+static irqreturn_t inline recv_packet (struct net_device *dev)
+{
+       int handled = 0;
+       unsigned short pktlen;
+       struct sk_buff *skb;
+       struct atari_nfeth_private *anp = (struct atari_nfeth_private 
*)netdev_priv(dev);
+
+       if (dev == NULL) {
+               printk(DRV_NAME " recv_packet(): interrupt for unknown 
device.\n");
+               return IRQ_NONE;
+       }
+
+       /* read packet length (excluding 32 bit crc) */
+       pktlen = nf_ethernet_read_packet_len(getEthX(dev));
+
+#ifdef DEBUG
+       printk(DRV_NAME ": recv_packet: %i", pktlen);
+#endif
+
+       //if (pktlen < 32)
+       if (!pktlen)
+       {
+#ifdef DEBUG
+               printk(DRV_NAME ": recv_packet: pktlen == 0");
+#endif
+               anp->stats.rx_errors++;
+               return IRQ_RETVAL(handled);
+       }
+
+       skb = dev_alloc_skb(pktlen + 2);
+       if (skb == NULL)
+       {
+#ifdef DEBUG
+               printk(DRV_NAME ": recv_packet: out of mem (buf_alloc failed)");
+#endif
+               anp->stats.rx_dropped++;
+               return IRQ_RETVAL(handled);
+       }
+
+       skb->dev = dev;
+       skb_reserve( skb, 2 );          /* 16 Byte align  */
+       skb_put( skb, pktlen ); /* make room */
+       nf_ethernet_read_block(getEthX(dev), skb->data, pktlen);
+
+       skb->protocol = eth_type_trans(skb, dev);
+       netif_rx(skb);
+       dev->last_rx = jiffies;
+       anp->stats.rx_packets++;
+       anp->stats.rx_bytes += pktlen;
+
+       /* and enqueue packet */
+       handled = 1;
+       return IRQ_RETVAL(handled);
+}
+
+irqreturn_t atari_nfeth_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+{
+       struct net_device *dev = dev_id;
+       struct atari_nfeth_private *anp = (struct atari_nfeth_private 
*)netdev_priv(dev);
+       int this_dev_irq_bit;
+       int irq_for_eth_bitmask;
+       if (dev == NULL) {
+#ifdef DEBUG
+               printk(DRV_NAME " atari_nfeth_interrupt(): interrupt for 
unknown device.\n");
+#endif
+               return IRQ_NONE;
+       }
+       spin_lock(&anp->lock);
+       irq_for_eth_bitmask = nf_ethernet_interrupt(0);
+       this_dev_irq_bit = 1 << (anp->ethX);
+       if (this_dev_irq_bit & irq_for_eth_bitmask) {
+               recv_packet(dev);
+               nf_ethernet_interrupt(this_dev_irq_bit);
+       }
+#ifdef DEBUG
+       else {
+               printk(DRV_NAME " atari_nfeth_interrupt(%d): not for me\n", 
anp->ethX);
+       }
+#endif
+       spin_unlock(&anp->lock);
+}
+
+int atari_nfeth_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       int len;
+       char *data, shortpkt[ETH_ZLEN];
+       struct atari_nfeth_private *anp = 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;
+       }
+
+       dev->trans_start = jiffies;
+       
+#ifdef DEBUG
+       printk( DRV_NAME ": send %d bytes", len);
+#endif
+       nf_ethernet_write_block(getEthX(dev), data, len);
+
+       anp->stats.tx_packets++;
+       anp->stats.tx_bytes += len;
+
+       dev_kfree_skb(skb);
+       return 0;
+}
+
+static void atari_nfeth_tx_timeout(struct net_device *dev)
+{
+       struct atari_nfeth_private *anp = netdev_priv(dev);
+       anp->stats.tx_errors++;
+       netif_wake_queue(dev);
+}
+
+static struct net_device_stats *atari_nfeth_get_stats(struct net_device *dev)
+{
+       struct atari_nfeth_private *anp = netdev_priv(dev);
+       return &(anp->stats);
+}
+
+// probe1() - HW detection
+// probe() - set module owner, found == 1, probe1()
+// init() - probe()
+
+static int __init atari_nfeth_probe1(struct net_device *dev, int ethX)
+{
+       static int did_version = 0;
+       static int did_notinstall = 0;
+       char errmsg[60];
+
+       if ( ! nf_ethernet_check_version(errmsg, sizeof(errmsg)-1) ) {
+               if (did_notinstall++ == 0)
+                       printk (DRV_NAME " not installed - %s\n", errmsg);
+                return -ENODEV;
+        }
+
+       /* Get MAC address */
+       if (! nf_ethernet_get_hw_addr(ethX, (unsigned char *)&(dev->dev_addr), 
ETH_ALEN)) {
+#ifdef DEBUG
+               printk(DRV_NAME " eth%d not installed - not defined\n", ethX);
+#endif
+               return -ENODEV;
+       }
+
+       ether_setup(dev);
+
+       dev->open = &atari_nfeth_open;
+       dev->stop = &atari_nfeth_stop;
+       dev->hard_start_xmit = &atari_nfeth_xmit;
+       dev->tx_timeout = &atari_nfeth_tx_timeout;
+       dev->get_stats = &atari_nfeth_get_stats;
+       dev->flags |= NETIF_F_NO_CSUM;
+
+       //if ((dev->priv = kmalloc(sizeof(struct atari_nfeth_private), 
GFP_KERNEL)) == NULL)
+       //      return -ENOMEM;
+       ((struct atari_nfeth_private *)(dev->priv))->ethX = ethX; /* index of 
NF NIC */
+
+       if (did_version++ == 0)
+               printk(version);
+
+       return 0;
+}
+
+struct net_device * __init atari_nfeth_probe(int unit)
+{
+        int err;
+       static int found = 0;
+       struct net_device *dev;
+
+       dev = alloc_etherdev(sizeof(struct atari_nfeth_private));
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+       if (unit >= 0) {
+               sprintf(dev->name, "eth%d", unit);
+               netdev_boot_setup_check(dev);
+       }
+       SET_MODULE_OWNER(dev);
+
+       if (!atari_nfeth_probe1(dev, found++)) {
+               err = register_netdev(dev);
+               if (err == -EIO)  {
+                       printk(DRV_NAME ": NatFeat Ethernet not found. Module 
not loaded.\n");
+               }
+               if (!err)
+                       return dev;
+       }
+
+       return ERR_PTR(-ENODEV);
+}
+
+#ifdef MODULE
+static struct net_device * atari_nfeth_dev;
+
+int atari_nfeth_init(void)
+{
+       // int err;
+
+       if (IS_ERR(atari_nfeth_dev = atari_nfeth_probe(0))) {
+               return PTR_ERR((atarilance_dev);
+       }
+
+       // ? atari_nfeth_dev.init = atari_nfeth_probe;
+#if 0
+       if ((err = register_netdev(&atari_nfeth_dev))) {
+               if (err == -EIO)  {
+                       printk(DRV_NAME ": NatFeat Ethernet not found. Module 
not loaded.\n");
+               }
+               return err;
+       }
+#endif
+
+        return 0;
+}
+
+void atari_nfeth_cleanup(void)
+{
+        unregister_netdev(&atari_nfeth_dev);
+        free_netdev(atari_nfeth_dev); // ?
+}
+
+module_init(atari_nfeth_init);
+module_exit(atari_nfeth_cleanup);
+
+#endif /* MODULE */
+
+/*
+vim:ts=4:sw=4:
+*/

Reply via email to