[kernel] r12963 - in dists/sid/linux-2.6/debian/patches: bugfix/m68k/2.6.28 series
Stephen Marenka
smarenka at alioth.debian.org
Mon Mar 2 21:29:21 UTC 2009
Author: smarenka
Date: Mon Mar 2 21:29:17 2009
New Revision: 12963
Log:
m68k: add 2.6.28 patches
Added:
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/amiga-debug=mem.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/amiga-platform-device.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-c2p.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-cfb16.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-line_length.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-panning.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-block-and-console-access.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-export-nf-api.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-nf-wrappers.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-nfcon-no-early_param-if-modular.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernat-fixes.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernat-warning-fix.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernat.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernec-fixes.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernec.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-io-fixes.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-platform-device.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-rom-isa.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-break_ctl.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-checkpatch.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-gs-fix.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-no-serial-console-if-modular.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-readd-CONFIG_ATARI_SCC.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-readd-atari_SCC_init_done.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/falconide-fix-ide_release_lock-imbalance.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/fbcon-protect-free-irq-by-MACH_IS_ATARI-check.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/fbcon-remove-broken-mac-vbl-handler.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-PRIVATE-m68k-changes.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-add-install-target.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-allow-all-kernel-traps-to-be-handled-via-exception-fixups-all.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-fpsp040-fix-trigraph-ignored-warning.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-noswap-linux-swap-h-needs-linux-pagemap-h.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-replace-linux-68k-by-linux-m68k.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-scsi-HOST_C-cleanup.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-update-defconfig-latest.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-use-the-new-byteorder-headers.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-add-SWIM-floppy-support.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-add-floppy-model-entry.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-baboon-interrupt-enable-disable.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-esp-fix-for-quadras-with-two-esp-chips.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-mac_esp-asm-fix.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-macfb-annotations-and-compiler-warning-fix.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-macfb-do-not-overflow-fix-id.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-machw_h_cleanup.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-platform-device.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-reinstate-rtc.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-via-cleanup-and-commentry.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/parisc-__kernel_time_t-is-always-long.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/revert-7557bc66be629d19a402e752673708bfbb8b5e86.diff
dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/zorro-module-device-table.diff
Modified:
dists/sid/linux-2.6/debian/patches/series/2
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/amiga-debug=mem.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/amiga-debug=mem.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,94 @@
+Subject: [PATCH] m68k: Fix debug=mem on Amiga
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+`debug=mem' on Amiga has been broken for a while.
+early_param() processing is done very/too early, i.e. before
+amiga_hw_present.CHIP_RAM has been set in amiga_identify(), causing
+amiga_savekmsg_setup() not to find any Chip RAM.
+
+The quick hack below makes it work again by introducing an additional
+intermediate flag, but I don't like it.
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+
+TODO: Suggestion from Roman Zippel <zippel at linux-m68k.org>:
+
+The alternative to pull some of the setup ahead of the early_param() call.
+It shouldn't be a big problem to move the call after the config calls, as
+these should only do a very basic setup, everything else should be done
+via init calls (e.g. amiga_init_sound() might be such a candidate).
+---
+ arch/m68k/amiga/config.c | 30 +++++++++++++++++++++---------
+ 1 file changed, 21 insertions(+), 9 deletions(-)
+
+--- a/arch/m68k/amiga/config.c
++++ b/arch/m68k/amiga/config.c
+@@ -106,6 +106,7 @@ static void amiga_reset(void);
+ extern void amiga_init_sound(void);
+ static void amiga_mem_console_write(struct console *co, const char *b,
+ unsigned int count);
++static void __init amiga_savekmsg_init(void);
+ #ifdef CONFIG_HEARTBEAT
+ static void amiga_heartbeat(int on);
+ #endif
+@@ -116,6 +117,8 @@ static struct console amiga_console_driv
+ .index = -1,
+ };
+
++static int __initdata amiga_enable_debug_mem;
++
+
+ /*
+ * Motherboard Resources present in all Amiga models
+@@ -461,6 +464,9 @@ void __init config_amiga(void)
+ /* initialize chipram allocator */
+ amiga_chip_init();
+
++ if (amiga_enable_debug_mem && AMIGAHW_PRESENT(CHIP_RAM))
++ amiga_savekmsg_init();
++
+ /* our beloved beeper */
+ if (AMIGAHW_PRESENT(AMI_AUDIO))
+ amiga_init_sound();
+@@ -779,18 +785,10 @@ static void amiga_mem_console_write(stru
+ }
+ }
+
+-static int __init amiga_savekmsg_setup(char *arg)
++static void __init amiga_savekmsg_init(void)
+ {
+ static struct resource debug_res = { .name = "Debug" };
+
+- if (!MACH_IS_AMIGA || strcmp(arg, "mem"))
+- goto done;
+-
+- if (!AMIGAHW_PRESENT(CHIP_RAM)) {
+- printk("Warning: no chipram present for debugging\n");
+- goto done;
+- }
+-
+ savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
+ savekmsg->magic1 = SAVEKMSG_MAGIC1;
+ savekmsg->magic2 = SAVEKMSG_MAGIC2;
+@@ -799,6 +797,20 @@ static int __init amiga_savekmsg_setup(c
+
+ amiga_console_driver.write = amiga_mem_console_write;
+ register_console(&amiga_console_driver);
++}
++
++static int __init amiga_savekmsg_setup(char *arg)
++{
++ if (!MACH_IS_AMIGA || strcmp(arg, "mem"))
++ goto done;
++
++ if (!AMIGAHW_PRESENT(CHIP_RAM)) {
++ printk("Warning: no chipram present for debugging\n");
++ amiga_enable_debug_mem = 1;
++ goto done;
++ }
++
++ amiga_savekmsg_init();
+
+ done:
+ return 0;
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/amiga-platform-device.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/amiga-platform-device.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,208 @@
+Subject: [PATCH] m68k: Initial Amiga platform device handling
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+static int __init xxx_probe(struct platform_device *pdev)
+{
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID);
+ fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID);
+ if (!regs || !fifo)
+ return -ENXIO;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+
+
+
+
+ platform_set_drvdata(pdev, xxx);
+
+
+
+
+
+
+
+
+}
+
+static int __exit xxx_remove(struct platform_device *pdev)
+{
+ xxx = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+
+ return 0;
+}
+
+static struct platform_driver xxx_driver = {
+ .remove = __exit_p(xxx_remove),
+ .driver = {
+ .name = "xxx",
+ },
+};
+
+static int __init xxx_init(void)
+{
+ return platform_driver_probe(&xxx_driver, xxx_probe);
+}
+module_init(xxx_init);
+
+static void __exit xxx_exit(void)
+{
+ platform_driver_unregister(&xxx_driver);
+}
+module_exit(xxx_exit);
+
+arch/m68k/amiga/amiints.c: if (AMIGAHW_PRESENT(PCMCIA))
+arch/m68k/amiga/chipram.c: if (!AMIGAHW_PRESENT(CHIP_RAM))
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(name)) \
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(ZORRO))
+arch/m68k/amiga/config.c: printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(A3000_CLK)) {
+arch/m68k/amiga/config.c: } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(ZORRO3)) {
+arch/m68k/amiga/config.c: if (amiga_enable_debug_mem && AMIGAHW_PRESENT(CHIP_RAM))
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(AMI_AUDIO))
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(MAGIC_REKICK))
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(A3000_CLK)) {
+arch/m68k/amiga/config.c: } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(A3000_CLK)) {
+arch/m68k/amiga/config.c: } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
+arch/m68k/amiga/config.c: if (!AMIGAHW_PRESENT(CHIP_RAM)) {
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(CHIP_RAM))
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(AMI_VIDEO)) {
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(name)) \
+arch/m68k/amiga/config.c: if (AMIGAHW_PRESENT(ZORRO))
+arch/m68k/amiga/config.c: AMIGAHW_PRESENT(ZORRO3) ? "I" : "",
+arch/m68k/kernel/setup.c: if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)) {
+arch/m68k/kernel/setup.c: if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
+drivers/block/amiflop.c: if (!AMIGAHW_PRESENT(AMI_FLOPPY))
+drivers/char/amiserial.c: if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_SERIAL))
+drivers/ide/gayle.c: if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
+drivers/input/keyboard/amikbd.c: if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
+drivers/input/mouse/amimouse.c: if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
+drivers/net/apne.c: if ( !(AMIGAHW_PRESENT(PCMCIA)) )
+drivers/parport/parport_amiga.c: if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_PARALLEL))
+drivers/scsi/a3000.c: if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI))
+drivers/scsi/a4000t.c: if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI)))
+drivers/video/amifb.c: if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))
+drivers/video/amifb.c: if (AMIGAHW_PRESENT(AMBER_FF))
+drivers/video/amifb.c: } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
+drivers/video/amifb.c: AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
+drivers/video/amifb.c: } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
+drivers/video/amifb.c: AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
+drivers/zorro/proc.c: if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) {
+drivers/zorro/zorro.c: if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
+drivers/zorro/zorro.c: if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
+drivers/zorro/zorro.c: zorro_bus.num_resources = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2;
+include/asm-m68k/amigahw.h:#define AMIGAHW_PRESENT(name) (amiga_hw_present.name)
+sound/oss/dmasound/dmasound_paula.c: if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_AUDIO)) {
+---
+ arch/m68k/amiga/Makefile | 2 -
+ arch/m68k/amiga/platform.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 88 insertions(+), 1 deletion(-)
+
+--- a/arch/m68k/amiga/Makefile
++++ b/arch/m68k/amiga/Makefile
+@@ -2,6 +2,6 @@
+ # Makefile for Linux arch/m68k/amiga source directory
+ #
+
+-obj-y := config.o amiints.o cia.o chipram.o amisound.o
++obj-y := config.o amiints.o cia.o chipram.o amisound.o platform.o
+
+ obj-$(CONFIG_AMIGA_PCMCIA) += pcmcia.o
+--- /dev/null
++++ b/arch/m68k/amiga/platform.c
+@@ -0,0 +1,87 @@
++/*
++ * Copyright (C) 2007 Geert Uytterhoeven
++ *
++ * 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/platform_device.h>
++#include <linux/mm.h> // FIXME show_mem()
++
++#include <asm/amigahw.h>
++
++
++static struct resource amiga_serial_resources[] = {
++ {
++ /*
++ * We request SERDAT and SERPER only, because the serial
++ * registers are too spread over the custom register space
++ */
++ .start = CUSTOM_PHYSADDR+0x30,
++ .end = CUSTOM_PHYSADDR+0x33,
++ .flags = IORESOURCE_MEM,
++ }
++};
++
++static struct platform_device amiga_serial = {
++ .name = "amiga-serial",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(amiga_serial_resources),
++ .resource = amiga_serial_resources,
++};
++
++static int __init amiga_init_devices(void)
++{
++ if (AMIGAHW_PRESENT(AMI_FLOPPY))
++ platform_device_register_simple("amiga-floppy", -1, NULL, 0);
++
++ if (AMIGAHW_PRESENT(AMI_SERIAL))
++ platform_device_register(&amiga_serial);
++
++#if 0
++ /* video hardware */
++[ ] AMIGAHW_PRESENT(AMI_VIDEO); /* Amiga Video */
++[ ] AMIGAHW_PRESENT(AMI_BLITTER); /* Amiga Blitter */
++[ ] AMIGAHW_PRESENT(AMBER_FF); /* Amber Flicker Fixer */
++ /* sound hardware */
++[ ] AMIGAHW_PRESENT(AMI_AUDIO); /* Amiga Audio */
++ /* disk storage interfaces */
++[ ] AMIGAHW_PRESENT(AMI_FLOPPY); /* Amiga Floppy */
++[ ] AMIGAHW_PRESENT(A3000_SCSI); /* SCSI (wd33c93, A3000 alike) */
++[ ] AMIGAHW_PRESENT(A4000_SCSI); /* SCSI (ncr53c710, A4000T alike) */
++[ ] AMIGAHW_PRESENT(A1200_IDE); /* IDE (A1200 alike) */
++[ ] AMIGAHW_PRESENT(A4000_IDE); /* IDE (A4000 alike) */
++[ ] AMIGAHW_PRESENT(CD_ROM); /* CD ROM drive */
++ /* other I/O hardware */
++[ ] AMIGAHW_PRESENT(AMI_KEYBOARD); /* Amiga Keyboard */
++[ ] AMIGAHW_PRESENT(AMI_MOUSE); /* Amiga Mouse */
++[ ] AMIGAHW_PRESENT(AMI_SERIAL); /* Amiga Serial */
++[ ] AMIGAHW_PRESENT(AMI_PARALLEL); /* Amiga Parallel */
++ /* real time clocks */
++[ ] AMIGAHW_PRESENT(A2000_CLK); /* Hardware Clock (A2000 alike) */
++[ ] AMIGAHW_PRESENT(A3000_CLK); /* Hardware Clock (A3000 alike) */
++ /* supporting hardware */
++[ ] AMIGAHW_PRESENT(CHIP_RAM); /* Chip RAM */
++[ ] AMIGAHW_PRESENT(PAULA); /* Paula (8364) */
++[ ] AMIGAHW_PRESENT(DENISE); /* Denise (8362) */
++[ ] AMIGAHW_PRESENT(DENISE_HR); /* Denise (8373) */
++[ ] AMIGAHW_PRESENT(LISA); /* Lisa (8375) */
++[ ] AMIGAHW_PRESENT(AGNUS_PAL); /* Normal/Fat PAL Agnus (8367/8371) */
++[ ] AMIGAHW_PRESENT(AGNUS_NTSC); /* Normal/Fat NTSC Agnus (8361/8370) */
++[ ] AMIGAHW_PRESENT(AGNUS_HR_PAL); /* Fat Hires PAL Agnus (8372) */
++[ ] AMIGAHW_PRESENT(AGNUS_HR_NTSC); /* Fat Hires NTSC Agnus (8372) */
++[ ] AMIGAHW_PRESENT(ALICE_PAL); /* PAL Alice (8374) */
++[ ] AMIGAHW_PRESENT(ALICE_NTSC); /* NTSC Alice (8374) */
++[ ] AMIGAHW_PRESENT(MAGIC_REKICK); /* A3000 Magic Hard Rekick */
++[ ] AMIGAHW_PRESENT(PCMCIA); /* PCMCIA Slot */
++[ ] AMIGAHW_PRESENT(GG2_ISA); /* GG2 Zorro2ISA Bridge */
++[ ] AMIGAHW_PRESENT(ZORRO); /* Zorro AutoConfig */
++[ ] AMIGAHW_PRESENT(ZORRO3); /* Zorro III */
++#endif
++
++ return 0;
++}
++
++device_initcall(amiga_init_devices);
++
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-c2p.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-c2p.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,477 @@
+Subject: [PATCH] fbdev: Add c2p support for Atari interleaved bitplanes
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Add c2p (Chunky-to-Planar) support for Atari interleaved bitplanes.
+This fixes the garbled penguin logo.
+
+TODO:
+ - checkpatch original c2p.c
+ - Extract common code
+ - Separate c2p_planar() and c2p_iplan2()
+ - Optimize? (for bpp < 8, we can skip steps that just swap zeroes)
+---
+ drivers/video/amifb.c | 6 -
+ drivers/video/atafb.c | 15 ---
+ drivers/video/c2p.c | 247 +++++++++++++++++++++++++++++++++++++++++---------
+ drivers/video/c2p.h | 11 +-
+ 4 files changed, 218 insertions(+), 61 deletions(-)
+
+--- a/drivers/video/amifb.c
++++ b/drivers/video/amifb.c
+@@ -2159,9 +2159,9 @@ static void amifb_imageblit(struct fb_in
+ src += pitch;
+ }
+ } else {
+- c2p(info->screen_base, image->data, dx, dy, width, height,
+- par->next_line, par->next_plane, image->width,
+- info->var.bits_per_pixel);
++ c2p_planar(info->screen_base, image->data, dx, dy, width,
++ height, par->next_line, par->next_plane,
++ image->width, info->var.bits_per_pixel);
+ }
+ }
+
+--- a/drivers/video/atafb.c
++++ b/drivers/video/atafb.c
+@@ -122,7 +122,6 @@ static struct atafb_par {
+ void *screen_base;
+ int yres_virtual;
+ u_long next_line;
+- u_long next_plane;
+ #if defined ATAFB_TT || defined ATAFB_STE
+ union {
+ struct {
+@@ -1394,14 +1393,7 @@ set_screen_base:
+ par->screen_base = screen_base + var->yoffset * linelen;
+ par->hw.falcon.xoffset = 0;
+
+- // FIXME!!! sort of works, no crash
+- //par->next_line = linelen;
+- //par->next_plane = yres_virtual * linelen;
+ par->next_line = linelen;
+- par->next_plane = 2;
+- // crashes
+- //par->next_plane = linelen;
+- //par->next_line = yres_virtual * linelen;
+
+ return 0;
+ }
+@@ -2676,10 +2668,9 @@ static void atafb_imageblit(struct fb_in
+ src += pitch;
+ }
+ } else {
+- // only used for logo; broken
+- c2p(info->screen_base, image->data, dx, dy, width, height,
+- par->next_line, par->next_plane, image->width,
+- info->var.bits_per_pixel);
++ c2p_iplan2(info->screen_base, image->data, dx, dy, width,
++ height, par->next_line, image->width,
++ info->var.bits_per_pixel);
+ }
+ }
+
+--- a/drivers/video/c2p.c
++++ b/drivers/video/c2p.c
+@@ -1,7 +1,7 @@
+ /*
+ * Fast C2P (Chunky-to-Planar) Conversion
+ *
+- * Copyright (C) 2003 Geert Uytterhoeven
++ * Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ * NOTES:
+ * - This code was inspired by Scout's C2P tutorial
+@@ -14,6 +14,7 @@
+
+ #include <linux/module.h>
+ #include <linux/string.h>
++
+ #include "c2p.h"
+
+
+@@ -54,7 +55,7 @@ static inline u32 get_mask(int n)
+ return 0;
+ }
+
+-#define transp_nx1(d, n) \
++#define transp8_nx1(d, n) \
+ do { \
+ u32 mask = get_mask(n); \
+ /* First block */ \
+@@ -67,7 +68,7 @@ static inline u32 get_mask(int n)
+ _transp(d, 6, 7, n, mask); \
+ } while (0)
+
+-#define transp_nx2(d, n) \
++#define transp8_nx2(d, n) \
+ do { \
+ u32 mask = get_mask(n); \
+ /* First block */ \
+@@ -78,40 +79,90 @@ static inline u32 get_mask(int n)
+ _transp(d, 5, 7, n, mask); \
+ } while (0)
+
+-#define transp_nx4(d, n) \
++#define transp8_nx4(d, n) \
+ do { \
+ u32 mask = get_mask(n); \
++ /* Single block */ \
+ _transp(d, 0, 4, n, mask); \
+ _transp(d, 1, 5, n, mask); \
+ _transp(d, 2, 6, n, mask); \
+ _transp(d, 3, 7, n, mask); \
+ } while (0)
+
+-#define transp(d, n, m) transp_nx ## m(d, n)
++#define transp8(d, n, m) transp8_nx ## m(d, n)
++
++
++#define transp4_nx1(d, n) \
++ do { \
++ u32 mask = get_mask(n); \
++ /* First block */ \
++ _transp(d, 0, 1, n, mask); \
++ /* Second block */ \
++ _transp(d, 2, 3, n, mask); \
++ } while (0)
++
++#define transp4_nx2(d, n) \
++ do { \
++ u32 mask = get_mask(n); \
++ /* Single block */ \
++ _transp(d, 0, 2, n, mask); \
++ _transp(d, 1, 3, n, mask); \
++ } while (0)
++
++#define transp4(d, n, m) transp4_nx ## m(d, n)
++
++
++#define transp4x_nx2(d, n) \
++ do { \
++ u32 mask = get_mask(n); \
++ /* Single block */ \
++ _transp(d, 2, 0, n, mask); \
++ _transp(d, 3, 1, n, mask); \
++ } while (0)
++
++#define transp4x(d, n, m) transp4x_nx ## m(d, n)
+
+
+ /*
+ * Perform a full C2P step on 32 8-bit pixels, stored in 8 32-bit words
+ * containing
+ * - 32 8-bit chunky pixels on input
+- * - permuted planar data on output
++ * - permutated planar data (1 plane per 32-bit word) on output
+ */
+
+-static void c2p_8bpp(u32 d[8])
++static void c2p_32x8(u32 d[8])
+ {
+- transp(d, 16, 4);
+- transp(d, 8, 2);
+- transp(d, 4, 1);
+- transp(d, 2, 4);
+- transp(d, 1, 2);
++ transp8(d, 16, 4);
++ transp8(d, 8, 2);
++ transp8(d, 4, 1);
++ transp8(d, 2, 4);
++ transp8(d, 1, 2);
+ }
+
+
+ /*
+- * Array containing the permution indices of the planar data after c2p
++ * Perform a full C2P step on 16 8-bit pixels, stored in 4 32-bit words
++ * containing
++ * - 16 8-bit chunky pixels on input
++ * - permutated planar data (2 planes per 32-bit word) on output
+ */
+
+-static const int perm_c2p_8bpp[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
++static void c2p_16x8(u32 d[4])
++{
++ transp4(d, 8, 2);
++ transp4(d, 1, 2);
++ transp4x(d, 16, 2);
++ transp4x(d, 2, 2);
++ transp4(d, 4, 1);
++}
++
++
++ /*
++ * Array containing the permutation indices of the planar data after c2p
++ */
++
++static const int perm_c2p_32x8[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
++static const int perm_c2p_16x8[4] = { 1, 3, 0, 2 };
+
+
+ /*
+@@ -130,12 +181,12 @@ static inline unsigned long comp(unsigne
+ * Store a full block of planar data after c2p conversion
+ */
+
+-static inline void store_planar(char *dst, u32 dst_inc, u32 bpp, u32 d[8])
++static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
+ {
+ int i;
+
+ for (i = 0; i < bpp; i++, dst += dst_inc)
+- *(u32 *)dst = d[perm_c2p_8bpp[i]];
++ *(u32 *)dst = d[perm_c2p_32x8[i]];
+ }
+
+
+@@ -143,18 +194,44 @@ static inline void store_planar(char *ds
+ * Store a partial block of planar data after c2p conversion
+ */
+
+-static inline void store_planar_masked(char *dst, u32 dst_inc, u32 bpp,
++static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
+ u32 d[8], u32 mask)
+ {
+ int i;
+
+ for (i = 0; i < bpp; i++, dst += dst_inc)
+- *(u32 *)dst = comp(d[perm_c2p_8bpp[i]], *(u32 *)dst, mask);
++ *(u32 *)dst = comp(d[perm_c2p_32x8[i]], *(u32 *)dst, mask);
++}
++
++
++ /*
++ * Store a full block of iplan2 data after c2p conversion
++ */
++
++static inline void store_iplan2(void *dst, u32 bpp, u32 d[4])
++{
++ int i;
++
++ for (i = 0; i < bpp/2; i++, dst += 4)
++ *(u32 *)dst = d[perm_c2p_16x8[i]];
+ }
+
+
+ /*
+- * c2p - Copy 8-bit chunky image data to a planar frame buffer
++ * Store a partial block of iplan2 data after c2p conversion
++ */
++
++static inline void store_iplan2_masked(void *dst, u32 bpp, u32 d[4], u32 mask)
++{
++ int i;
++
++ for (i = 0; i < bpp/2; i++, dst += 4)
++ *(u32 *)dst = comp(d[perm_c2p_16x8[i]], *(u32 *)dst, mask);
++}
++
++
++ /*
++ * c2p_planar - Copy 8-bit chunky image data to a planar frame buffer
+ * @dst: Starting address of the planar frame buffer
+ * @dx: Horizontal destination offset (in pixels)
+ * @dy: Vertical destination offset (in pixels)
+@@ -166,18 +243,22 @@ static inline void store_planar_masked(c
+ * @bpp: Bits per pixel of the planar frame buffer (1-8)
+ */
+
+-void c2p(u8 *dst, const u8 *src, u32 dx, u32 dy, u32 width, u32 height,
+- u32 dst_nextline, u32 dst_nextplane, u32 src_nextline, u32 bpp)
++void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
++ u32 height, u32 dst_nextline, u32 dst_nextplane,
++ u32 src_nextline, u32 bpp)
+ {
+- int dst_idx;
+- u32 d[8], first, last, w;
++ union {
++ u8 pixels[32];
++ u32 words[8];
++ } d;
++ u32 dst_idx, first, last, w;
+ const u8 *c;
+- u8 *p;
++ void *p;
+
+ dst += dy*dst_nextline+(dx & ~31);
+ dst_idx = dx % 32;
+- first = ~0UL >> dst_idx;
+- last = ~(~0UL >> ((dst_idx+width) % 32));
++ first = 0xffffffffU >> dst_idx;
++ last = ~(0xffffffffU >> ((dst_idx+width) % 32));
+ while (height--) {
+ c = src;
+ p = dst;
+@@ -185,11 +266,11 @@ void c2p(u8 *dst, const u8 *src, u32 dx,
+ if (dst_idx+width <= 32) {
+ /* Single destination word */
+ first &= last;
+- memset(d, 0, sizeof(d));
+- memcpy((u8 *)d+dst_idx, c, width);
++ memset(d.pixels, 0, sizeof(d));
++ memcpy(d.pixels+dst_idx, c, width);
+ c += width;
+- c2p_8bpp(d);
+- store_planar_masked(p, dst_nextplane, bpp, d, first);
++ c2p_32x8(d.words);
++ store_planar_masked(p, dst_nextplane, bpp, d.words, first);
+ p += 4;
+ } else {
+ /* Multiple destination words */
+@@ -197,36 +278,118 @@ void c2p(u8 *dst, const u8 *src, u32 dx,
+ /* Leading bits */
+ if (dst_idx) {
+ w = 32 - dst_idx;
+- memset(d, 0, dst_idx);
+- memcpy((u8 *)d+dst_idx, c, w);
++ memset(d.pixels, 0, dst_idx);
++ memcpy(d.pixels+dst_idx, c, w);
+ c += w;
+- c2p_8bpp(d);
+- store_planar_masked(p, dst_nextplane, bpp, d, first);
++ c2p_32x8(d.words);
++ store_planar_masked(p, dst_nextplane, bpp, d.words, first);
+ p += 4;
+ w = width-w;
+ }
+ /* Main chunk */
+ while (w >= 32) {
+- memcpy(d, c, 32);
++ memcpy(d.pixels, c, 32);
+ c += 32;
+- c2p_8bpp(d);
+- store_planar(p, dst_nextplane, bpp, d);
++ c2p_32x8(d.words);
++ store_planar(p, dst_nextplane, bpp, d.words);
+ p += 4;
+ w -= 32;
+ }
+ /* Trailing bits */
+ w %= 32;
+ if (w > 0) {
+- memcpy(d, c, w);
+- memset((u8 *)d+w, 0, 32-w);
+- c2p_8bpp(d);
+- store_planar_masked(p, dst_nextplane, bpp, d, last);
++ memcpy(d.pixels, c, w);
++ memset(d.pixels+w, 0, 32-w);
++ c2p_32x8(d.words);
++ store_planar_masked(p, dst_nextplane, bpp, d.words, last);
++ }
++ }
++ src += src_nextline;
++ dst += dst_nextline;
++ }
++}
++EXPORT_SYMBOL_GPL(c2p_planar);
++
++
++ /*
++ * c2p_iplan2 - Copy 8-bit chunky image data to an interleaved planar
++ * frame buffer with 2 bytes of interleave
++ * @dst: Starting address of the planar frame buffer
++ * @dx: Horizontal destination offset (in pixels)
++ * @dy: Vertical destination offset (in pixels)
++ * @width: Image width (in pixels)
++ * @height: Image height (in pixels)
++ * @dst_nextline: Frame buffer offset to the next line (in bytes)
++ * @src_nextline: Image offset to the next line (in bytes)
++ * @bpp: Bits per pixel of the planar frame buffer (2, 4, or 8)
++ */
++
++void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
++ u32 height, u32 dst_nextline, u32 src_nextline, u32 bpp)
++{
++ union {
++ u8 pixels[16];
++ u32 words[4];
++ } d;
++ u32 dst_idx, first, last, w;
++ const u8 *c;
++ void *p;
++
++ dst += dy*dst_nextline+(dx & ~15)*bpp;
++ dst_idx = dx % 16;
++ first = 0xffffU >> dst_idx;
++ first |= first << 16;
++ last = 0xffffU ^ (0xffffU >> ((dst_idx+width) % 16));
++ last |= last << 16;
++ while (height--) {
++ c = src;
++ p = dst;
++ w = width;
++ if (dst_idx+width <= 16) {
++ /* Single destination word */
++ first &= last;
++ memset(d.pixels, 0, sizeof(d));
++ memcpy(d.pixels+dst_idx, c, width);
++ c += width;
++ c2p_16x8(d.words);
++ store_iplan2_masked(p, bpp, d.words, first);
++ p += bpp*2;
++ } else {
++ /* Multiple destination words */
++ w = width;
++ /* Leading bits */
++ if (dst_idx) {
++ w = 16 - dst_idx;
++ memset(d.pixels, 0, dst_idx);
++ memcpy(d.pixels+dst_idx, c, w);
++ c += w;
++ c2p_16x8(d.words);
++ store_iplan2_masked(p, bpp, d.words, first);
++ p += bpp*2;
++ w = width-w;
++ }
++ /* Main chunk */
++ while (w >= 16) {
++ memcpy(d.pixels, c, 16);
++ c += 16;
++ c2p_16x8(d.words);
++ store_iplan2(p, bpp, d.words);
++ p += bpp*2;
++ w -= 16;
++ }
++ /* Trailing bits */
++ w %= 16;
++ if (w > 0) {
++ memcpy(d.pixels, c, w);
++ memset(d.pixels+w, 0, 16-w);
++ c2p_16x8(d.words);
++ store_iplan2_masked(p, bpp, d.words, last);
+ }
+ }
+ src += src_nextline;
+ dst += dst_nextline;
+ }
+ }
+-EXPORT_SYMBOL_GPL(c2p);
++EXPORT_SYMBOL_GPL(c2p_iplan2);
+
+ MODULE_LICENSE("GPL");
+--- a/drivers/video/c2p.h
++++ b/drivers/video/c2p.h
+@@ -1,7 +1,7 @@
+ /*
+ * Fast C2P (Chunky-to-Planar) Conversion
+ *
+- * Copyright (C) 2003 Geert Uytterhoeven
++ * Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ * 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
+@@ -10,7 +10,10 @@
+
+ #include <linux/types.h>
+
+-extern void c2p(u8 *dst, const u8 *src, u32 dx, u32 dy, u32 width, u32 height,
+- u32 dst_nextline, u32 dst_nextplane, u32 src_nextline,
+- u32 bpp);
++extern void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
++ u32 height, u32 dst_nextline, u32 dst_nextplane,
++ u32 src_nextline, u32 bpp);
+
++extern void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
++ u32 height, u32 dst_nextline, u32 src_nextline,
++ u32 bpp);
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-cfb16.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-cfb16.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,150 @@
+Subject: [PATCH] fbdev: Fix 16 bpp console in atafb
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Fix console on 16 bpp (tested on ARAnyM):
+ o 16 bpp must use the cfb_*() ops
+ o 16 bpp needs to set up info->pseudo_palette[] (was fbcon_cfb16_cmap[] on
+ 2.4.x)
+
+TODO:
+ - Kill atafb_get_fix(), atafb_get_var(), atafb_set_disp()
+ - Kill FBCMD_GET_CURRENTPAR, FBCMD_SET_CURRENTPAR
+ - Use info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
+ (also in amifb)
+---
+ drivers/video/atafb.c | 74 ++++++++++++++++++++------------------------------
+ 1 file changed, 30 insertions(+), 44 deletions(-)
+
+--- a/drivers/video/atafb.c
++++ b/drivers/video/atafb.c
+@@ -148,6 +148,7 @@ static struct atafb_par {
+ short mono;
+ short ste_mode;
+ short bpp;
++ u32 pseudo_palette[16];
+ } falcon;
+ #endif
+ /* Nothing needed for external mode */
+@@ -883,10 +884,6 @@ static int vdl_prescale[4][3] = {
+ /* Default hsync timing [mon_type] in picoseconds */
+ static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
+
+-#ifdef FBCON_HAS_CFB16
+-static u16 fbcon_cfb16_cmap[16];
+-#endif
+-
+ static inline int hxx_prescale(struct falcon_hw *hw)
+ {
+ return hw->ste_mode ? 16
+@@ -1728,10 +1725,10 @@ static int falcon_setcolreg(unsigned int
+ (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
+ (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
+ ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
+-#ifdef FBCON_HAS_CFB16
+- fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
+- ((green & 0xfc00) >> 5) |
+- ((blue & 0xf800) >> 11));
++#ifdef ATAFB_FALCON
++ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
++ ((green & 0xfc00) >> 5) |
++ ((blue & 0xf800) >> 11));
+ #endif
+ }
+ return 0;
+@@ -2436,42 +2433,6 @@ static void atafb_set_disp(struct fb_inf
+ atafb_get_fix(&info->fix, info);
+
+ info->screen_base = (void *)info->fix.smem_start;
+-
+- switch (info->fix.type) {
+- case FB_TYPE_INTERLEAVED_PLANES:
+- switch (info->var.bits_per_pixel) {
+- case 2:
+- // display->dispsw = &fbcon_iplan2p2;
+- break;
+- case 4:
+- // display->dispsw = &fbcon_iplan2p4;
+- break;
+- case 8:
+- // display->dispsw = &fbcon_iplan2p8;
+- break;
+- }
+- break;
+- case FB_TYPE_PACKED_PIXELS:
+- switch (info->var.bits_per_pixel) {
+-#ifdef FBCON_HAS_MFB
+- case 1:
+- // display->dispsw = &fbcon_mfb;
+- break;
+-#endif
+-#ifdef FBCON_HAS_CFB8
+- case 8:
+- // display->dispsw = &fbcon_cfb8;
+- break;
+-#endif
+-#ifdef FBCON_HAS_CFB16
+- case 16:
+- // display->dispsw = &fbcon_cfb16;
+- // display->dispsw_data = fbcon_cfb16_cmap;
+- break;
+-#endif
+- }
+- break;
+- }
+ }
+
+ static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+@@ -2542,6 +2503,13 @@ static void atafb_fillrect(struct fb_inf
+ if (!rect->width || !rect->height)
+ return;
+
++#ifdef ATAFB_FALCON
++ if (info->var.bits_per_pixel == 16) {
++ cfb_fillrect(info, rect);
++ return;
++ }
++#endif
++
+ /*
+ * We could use hardware clipping but on many cards you get around
+ * hardware clipping by writing to framebuffer directly.
+@@ -2576,6 +2544,13 @@ static void atafb_copyarea(struct fb_inf
+ u32 dx, dy, sx, sy, width, height;
+ int rev_copy = 0;
+
++#ifdef ATAFB_FALCON
++ if (info->var.bits_per_pixel == 16) {
++ cfb_copyarea(info, area);
++ return;
++ }
++#endif
++
+ /* clip the destination */
+ x2 = area->dx + area->width;
+ y2 = area->dy + area->height;
+@@ -2625,6 +2600,13 @@ static void atafb_imageblit(struct fb_in
+ const char *src;
+ u32 dx, dy, width, height, pitch;
+
++#ifdef ATAFB_FALCON
++ if (info->var.bits_per_pixel == 16) {
++ cfb_imageblit(info, image);
++ return;
++ }
++#endif
++
+ /*
+ * We could use hardware clipping but on many cards you get around
+ * hardware clipping by writing to framebuffer directly like we are
+@@ -3217,6 +3199,10 @@ int __init atafb_init(void)
+ // tries to read from HW which may not be initialized yet
+ // so set sane var first, then call atafb_set_par
+ atafb_get_var(&fb_info.var, &fb_info);
++
++#ifdef ATAFB_FALCON
++ fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
++#endif
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+ if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-line_length.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-line_length.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,52 @@
+Subject: [PATCH] fbdev: make sure fix->line_length is always set in atafb
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Make sure fix->line_length is always set, as some applications need it because
+they don't have fallback code if line_length is zero.
+
+Works on ARAnyM (Falcon emulation), but par->next_line is not set on any other
+Atari variant?
+---
+ drivers/video/atafb.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/video/atafb.c
++++ b/drivers/video/atafb.c
+@@ -613,7 +613,7 @@ static int tt_encode_fix(struct fb_fix_s
+ fix->xpanstep = 0;
+ fix->ypanstep = 1;
+ fix->ywrapstep = 0;
+- fix->line_length = 0;
++ fix->line_length = par->next_line;
+ fix->accel = FB_ACCEL_ATARIBLITT;
+ return 0;
+ }
+@@ -917,7 +917,8 @@ static int falcon_encode_fix(struct fb_f
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->xpanstep = 2;
+ }
+- fix->line_length = 0;
++ fix->line_length =
++ (par->hw.falcon.line_width + par->hw.falcon.line_offset) * 2;
+ fix->accel = FB_ACCEL_ATARIBLITT;
+ return 0;
+ }
+@@ -1844,7 +1845,7 @@ static int stste_encode_fix(struct fb_fi
+ fix->ypanstep = 0;
+ }
+ fix->ywrapstep = 0;
+- fix->line_length = 0;
++ fix->line_length = par->next_line;
+ fix->accel = FB_ACCEL_ATARIBLITT;
+ return 0;
+ }
+@@ -2161,7 +2162,7 @@ static int ext_encode_fix(struct fb_fix_
+ fix->xpanstep = 0;
+ fix->ypanstep = 0;
+ fix->ywrapstep = 0;
+- fix->line_length = 0;
++ fix->line_length = par->next_line;
+ return 0;
+ }
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-panning.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atafb-panning.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,28 @@
+Subject: [PATCH] fbdev: Fix panning in atafb
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Fix panning on ARAnyM (Falcon emulation). Without this, `fbtest test011' fails
+(for a 320x200x8 display with virtual 640x400).
+
+As the original code in 2.4.x was the same, I'm wondering:
+ o Is this a bug in the ARAnyM emulation?
+ o xpanstep is 1, but judging from the visual output on ARAnyM, it looks like
+ it should be 16?
+---
+ drivers/video/atafb.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/video/atafb.c
++++ b/drivers/video/atafb.c
+@@ -1697,8 +1697,10 @@ static int falcon_pan_display(struct fb_
+ }
+ par->hw.falcon.line_offset = bpp *
+ (info->var.xres_virtual - info->var.xres) / 16;
++#if 0
+ if (par->hw.falcon.xoffset)
+ par->hw.falcon.line_offset -= bpp;
++#endif;
+ xoffset = var->xoffset - par->hw.falcon.xoffset;
+
+ par->screen_base = screen_base +
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-block-and-console-access.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-block-and-console-access.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,453 @@
+Subject: [PATCH] m68k: Add support for ARAnyM block and console access
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Add support for ARAnyM block and console access
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/Kconfig | 16 ++++
+ arch/m68k/emu/Makefile | 2
+ arch/m68k/emu/natfeat.c | 38 ----------
+ arch/m68k/emu/nfblock.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++
+ arch/m68k/emu/nfcon.c | 164 +++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 362 insertions(+), 38 deletions(-)
+
+--- a/arch/m68k/Kconfig
++++ b/arch/m68k/Kconfig
+@@ -269,6 +269,22 @@ config NFETH
+ which will emulate a regular ethernet device while presenting an
+ ethertap device to the host system.
+
++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.
++
+ comment "Processor type"
+
+ config M68020
+--- a/arch/m68k/emu/Makefile
++++ b/arch/m68k/emu/Makefile
+@@ -5,3 +5,5 @@
+ obj-y += natfeat.o
+
+ obj-$(CONFIG_NFETH) += nfeth.o
++obj-$(CONFIG_NFBLOCK) += nfblock.o
++obj-$(CONFIG_NFCON) += nfcon.o
+--- 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");
+--- /dev/null
++++ b/arch/m68k/emu/nfblock.c
+@@ -0,0 +1,180 @@
++/*
++ * 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 <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 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;
++ nf_call(nfhd_id + NFHD_READ_WRITE, dev->id, 0, dir,
++ sec >> shift, len >> shift, bvec_to_phys(bvec));
++ sec += len;
++ }
++ bio_endio(bio, 0);
++ return 0;
++}
++
++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 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;
++
++ printk(KERN_INFO "nfhd%u: found device with %u blocks (%u bytes)\n",
++ dev_id, blocks, bsize);
++
++ if (bsize < 512 || (bsize & (bsize - 1))) {
++ printk(KERN_WARNING "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_hardsect_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) {
++ printk(KERN_WARNING "nfhd: unable to get major number\n");
++ return -ENODEV;
++ }
++
++ for (i = NFHD_DEV_OFFSET; i < 24; i++) {
++ if (nf_call(nfhd_id + 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");
+--- /dev/null
++++ b/arch/m68k/emu/nfcon.c
+@@ -0,0 +1,164 @@
++/*
++ * 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 nfcon_write(struct console *con, 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);
++}
++
++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)
++{
++ char temp[68];
++ int i = count;
++
++ temp[64] = 0;
++ while (i > 64) {
++ memcpy(temp, buf, 64);
++ nf_call(stderr_id, temp);
++ buf += 64;
++ i -= 64;
++ }
++ memcpy(temp, buf, i);
++ temp[i] = 0;
++ nf_call(stderr_id, temp);
++
++ 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,
++};
++
++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);
++
++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) {
++ printk(KERN_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");
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-export-nf-api.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-export-nf-api.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,35 @@
+Subject: [PATCH] m68k: Export ARAnyM native feature API
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+ERROR: "nf_get_id" [arch/m68k/emu/nfeth.ko] undefined!
+ERROR: "nf_call" [arch/m68k/emu/nfeth.ko] undefined!
+ERROR: "nf_get_id" [arch/m68k/emu/nfcon.ko] undefined!
+ERROR: "nf_call" [arch/m68k/emu/nfcon.ko] undefined!
+ERROR: "nf_call" [arch/m68k/emu/nfblock.ko] undefined!
+ERROR: "nf_get_id" [arch/m68k/emu/nfblock.ko] undefined!
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/emu/natfeat.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/m68k/emu/natfeat.c
++++ b/arch/m68k/emu/natfeat.c
+@@ -13,6 +13,7 @@
+ #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>
+@@ -31,6 +32,8 @@ asm("\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;
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-nf-wrappers.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-nf-wrappers.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,57 @@
+Subject: [PATCH/RFC] m68k: Wrap nfblock natfeat calls
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Add wrappers with proper prototypes for the natfeat calls in nfblock.
+This fixes the problem where sector_t was pushed on the stack as a 64-bit value
+if CONFIG_LBD=y, while all parameters of the nf_call() varargs function are
+32-bit.
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/emu/nfblock.c | 20 +++++++++++++++++---
+ 1 file changed, 17 insertions(+), 3 deletions(-)
+
+--- a/arch/m68k/emu/nfblock.c
++++ b/arch/m68k/emu/nfblock.c
+@@ -30,6 +30,20 @@ enum {
+ 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;
+@@ -56,8 +70,8 @@ static int nfhd_make_request(struct requ
+ bio_for_each_segment(bvec, bio, i) {
+ len = bvec->bv_len;
+ len >>= 9;
+- nf_call(nfhd_id + NFHD_READ_WRITE, dev->id, 0, dir,
+- sec >> shift, len >> shift, bvec_to_phys(bvec));
++ nfhd_read_write(dev->id, 0, dir, sec >> shift, len >> shift,
++ bvec_to_phys(bvec));
+ sec += len;
+ }
+ bio_endio(bio, 0);
+@@ -152,7 +166,7 @@ static int __init nfhd_init(void)
+ }
+
+ for (i = NFHD_DEV_OFFSET; i < 24; i++) {
+- if (nf_call(nfhd_id + NFHD_GET_CAPACITY, i, 0, &blocks, &bsize))
++ if (nfhd_get_capacity(i, 0, &blocks, &bsize))
+ continue;
+ nfhd_init_one(i, blocks, bsize);
+ }
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-nfcon-no-early_param-if-modular.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym-nfcon-no-early_param-if-modular.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,31 @@
+Subject: [PATCH] m68k/ARAnyM: early_param() does not exist in the modular case
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+early_param() does not exist in the modular case
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/emu/nfcon.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/m68k/emu/nfcon.c
++++ b/arch/m68k/emu/nfcon.c
+@@ -101,6 +101,8 @@ static const struct tty_operations nfcon
+ .write_room = nfcon_tty_write_room,
+ };
+
++#ifndef MODULE
++
+ static int __init nf_debug_setup(char *arg)
+ {
+ if (strcmp(arg, "nfcon"))
+@@ -117,6 +119,8 @@ static int __init nf_debug_setup(char *a
+
+ early_param("debug", nf_debug_setup);
+
++#endif /* !MODULE */
++
+ static int __init nfcon_init(void)
+ {
+ int res;
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-aranym.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,516 @@
+Subject: [PATCH] m68k: Atari ARAnyM support
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+This isn't really my kettle of fish, but I post it anyway unless Petr
+complains :-)
+
+This is what makes it possible for me to test 2.6 builds on the
+emulator...
+
+Should be signed off by Petr, really.
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/Kconfig | 15 ++
+ arch/m68k/Makefile | 1
+ arch/m68k/emu/Makefile | 7 +
+ arch/m68k/emu/natfeat.c | 113 +++++++++++++++++
+ arch/m68k/emu/nfeth.c | 284 +++++++++++++++++++++++++++++++++++++++++++++
+ arch/m68k/kernel/setup.c | 5
+ include/asm-m68k/natfeat.h | 22 +++
+ 7 files changed, 447 insertions(+)
+
+--- a/arch/m68k/Kconfig
++++ b/arch/m68k/Kconfig
+@@ -254,6 +254,21 @@ 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. Useful with the ARANYM option.
++
++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
+--- a/arch/m68k/Makefile
++++ b/arch/m68k/Makefile
+@@ -76,6 +76,7 @@ core-$(CONFIG_MVME16x) += arch/m68k/mvm
+ 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/
+--- /dev/null
++++ b/arch/m68k/emu/Makefile
+@@ -0,0 +1,7 @@
++#
++# Makefile for Linux arch/m68k/emu source directory
++#
++
++obj-y += natfeat.o
++
++obj-$(CONFIG_NFETH) += nfeth.o
+--- /dev/null
++++ b/arch/m68k/emu/natfeat.c
+@@ -0,0 +1,113 @@
++/*
++ * 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 at 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/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");
++
++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;
++}
+--- /dev/null
++++ b/arch/m68k/emu/nfeth.c
+@@ -0,0 +1,284 @@
++/*
++ * 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 <net/ieee80211.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 DRV_NAME "nfeth"
++#define DRV_VERSION "0.3"
++#define DRV_RELDATE "10/12/2005"
++
++#define MAX_UNIT 8
++
++/* 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(nfeth_debug, "i");
++MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)");
++*/
++
++
++static long nfEtherID;
++static int nfEtherIRQ;
++
++struct nfeth_private {
++ int ethX;
++ struct net_device_stats stats;
++};
++
++static struct net_device *nfeth_dev[MAX_UNIT];
++
++int nfeth_open(struct net_device *dev);
++int nfeth_stop(struct net_device *dev);
++irqreturn_t nfeth_interrupt(int irq, void *dev_id);
++int nfeth_xmit(struct sk_buff *skb, struct net_device *dev);
++
++int nfeth_open(struct net_device *dev)
++{
++ struct nfeth_private *priv = netdev_priv(dev);
++ int res;
++
++ res = nf_call(nfEtherID + XIF_START, priv->ethX);
++
++ /* Clean statistics */
++ memset(&priv->stats, 0, sizeof(struct net_device_stats));
++
++ pr_debug(DRV_NAME ": open %d\n", res);
++
++ /* Ready for data */
++ netif_start_queue(dev);
++
++ return 0;
++}
++
++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);
++ int handled = 0;
++ unsigned short pktlen;
++ struct sk_buff *skb;
++
++ /* read packet length (excluding 32 bit crc) */
++ pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX);
++
++ pr_debug(DRV_NAME ": recv_packet: %i\n", pktlen);
++
++ if (!pktlen) {
++ pr_debug(DRV_NAME ": recv_packet: pktlen == 0\n");
++ priv->stats.rx_errors++;
++ return;
++ }
++
++ skb = dev_alloc_skb(pktlen + 2);
++ if (!skb) {
++ pr_debug(DRV_NAME
++ ": recv_packet: out of mem (buf_alloc failed)\n");
++ priv->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;
++ priv->stats.rx_packets++;
++ priv->stats.rx_bytes += pktlen;
++
++ /* and enqueue packet */
++ handled = 1;
++ return;
++}
++
++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;
++}
++
++int nfeth_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ 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;
++ }
++
++ dev->trans_start = jiffies;
++
++ pr_debug(DRV_NAME ": send %d bytes\n", len);
++ nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data),
++ len);
++
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += len;
++
++ dev_kfree_skb(skb);
++ return 0;
++}
++
++static void nfeth_tx_timeout(struct net_device *dev)
++{
++ struct nfeth_private *priv = netdev_priv(dev);
++ priv->stats.tx_errors++;
++ netif_wake_queue(dev);
++}
++
++static struct net_device_stats *nfeth_get_stats(struct net_device *dev)
++{
++ struct nfeth_private *priv = netdev_priv(dev);
++ return &priv->stats;
++}
++
++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];
++ DECLARE_MAC_BUF(macfmt);
++ 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->open = nfeth_open;
++ dev->stop = nfeth_stop;
++ dev->hard_start_xmit = nfeth_xmit;
++ dev->tx_timeout = nfeth_tx_timeout;
++ dev->get_stats = nfeth_get_stats;
++ 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));
++
++ pr_info("%s: nfeth addr:%s (%s) HWaddr:%s\n", dev->name, host_ip,
++ local_ip, print_mac(macfmt, mac));
++
++ return dev;
++}
++
++int __init nfeth_init(void)
++{
++ long ver;
++ int i;
++
++ nfEtherID = nf_get_id("ETHERNET");
++ if (!nfEtherID)
++ return -ENODEV;
++
++ ver = nf_call(nfEtherID + GET_VERSION);
++ pr_info("nfeth API %lu\n", ver);
++
++ nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL);
++ if (request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED,
++ "eth emu", nfeth_interrupt)) {
++ printk(KERN_ERR "nfeth: request for irq %d failed",
++ nfEtherIRQ);
++ return -ENODEV;
++ }
++
++ for (i = 0; i < MAX_UNIT; i++)
++ nfeth_dev[i] = nfeth_probe(i);
++
++ return 0;
++}
++
++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);
+--- a/arch/m68k/kernel/setup.c
++++ b/arch/m68k/kernel/setup.c
+@@ -41,6 +41,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!
+@@ -325,6 +326,10 @@ void __init setup_arch(char **cmdline_p)
+ panic("No configuration setup");
+ }
+
++#ifdef CONFIG_NATFEAT
++ nf_init();
++#endif
++
+ paging_init();
+
+ #ifndef CONFIG_SUN3
+--- /dev/null
++++ b/include/asm-m68k/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 */
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernat-fixes.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernat-fixes.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,1006 @@
+Subject: [PATCH] m68k: Atari EtherNAT updates
+
+From: Michael Schmitz <schmitz at biophys.uni-duesseldorf.de>
+
+Here's my EtherNAT update (goes on top of your patch queue as of Oct. 18),
+fixing the various compile errors and generally cleaning up the patch. This
+brings the EtherNAT driver in sync with smc91x.c again (actually, I started
+from a clean slate and patched in only the bare essentials).
+
+Works OK, and can be trimmed a bit further if I preset the interrupt to timer
+D in the platform code. Should be replaced by smc91x.c altogether once I have
+real interrupts sorted. How's that for a perspective?
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/atari_91C111.c | 406 +++++++++++++++------------------------------
+ drivers/net/smc91x.h | 61 ++++++
+ 2 files changed, 203 insertions(+), 264 deletions(-)
+
+--- a/drivers/net/atari_91C111.c
++++ b/drivers/net/atari_91C111.c
+@@ -60,8 +60,6 @@
+ static const char version[] =
+ "smc91x.c: v1.1, sep 22 2004 by Nicolas Pitre <nico at cam.org>\n";
+
+-#define SMC_DEBUG 1
+-
+ /* Debugging level */
+ #ifndef SMC_DEBUG
+ #define SMC_DEBUG 0
+@@ -106,7 +104,7 @@ static unsigned int smc_portlist[] __ini
+ 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0
+ };
+
+-#endif /* CONFIG_ISA */
++/* MSch FIXME: endif CONFIG_ISA here? */
+
+ #ifndef SMC_IOADDR
+ # define SMC_IOADDR -1
+@@ -122,6 +120,7 @@ static int irq = SMC_IRQ;
+ module_param(irq, int, 0400);
+ MODULE_PARM_DESC(irq, "IRQ number");
+
++#endif /* CONFIG_ISA */
+
+ #ifndef SMC_NOWAIT
+ # define SMC_NOWAIT 0
+@@ -172,7 +171,7 @@ MODULE_ALIAS("platform:smc91x");
+ * but to the expense of reduced TX throughput and increased IRQ overhead.
+ * Note this is not a cure for a too slow data bus or too high IRQ latency.
+ */
+-#define THROTTLE_TX_PKTS 1
++#define THROTTLE_TX_PKTS 0 /* MSch FIXME 1 */
+
+ /*
+ * The MII clock high/low times. 2x this number gives the MII clock period
+@@ -227,7 +226,7 @@ static void PRINT_PKT(u_char *buf, int l
+
+
+ /* this enables an interrupt in the interrupt mask register */
+-#define SMC_ENABLE_INT(lp, x) do { \
++#define SMC_ENABLE_INT(lp, x) do { \
+ unsigned char mask; \
+ spin_lock_irq(&lp->lock); \
+ mask = SMC_GET_INT_MASK(lp); \
+@@ -237,7 +236,7 @@ static void PRINT_PKT(u_char *buf, int l
+ } while (0)
+
+ /* this disables an interrupt from the interrupt mask register */
+-#define SMC_DISABLE_INT(lp, x) do { \
++#define SMC_DISABLE_INT(lp, x) do { \
+ unsigned char mask; \
+ spin_lock_irq(&lp->lock); \
+ mask = SMC_GET_INT_MASK(lp); \
+@@ -252,9 +251,9 @@ static void PRINT_PKT(u_char *buf, int l
+ * decides to go south.
+ */
+ #define SMC_WAIT_MMU_BUSY(lp) do { \
+- if (unlikely(SMC_GET_MMU_CMD(lp) & MC_BUSY)) { \
++ if (unlikely(SMC_GET_MMU_CMD(lp) & MC_BUSY)) { \
+ unsigned long timeout = jiffies + 2; \
+- while (SMC_GET_MMU_CMD(lp) & MC_BUSY) { \
++ while (SMC_GET_MMU_CMD(lp) & MC_BUSY) { \
+ if (time_after(jiffies, timeout)) { \
+ printk("%s: timeout %s line %d\n", \
+ dev->name, __FILE__, __LINE__); \
+@@ -266,70 +265,25 @@ static void PRINT_PKT(u_char *buf, int l
+ } while (0)
+
+ /*
+- * Timer based operation on Atari
+- */
+-static irqreturn_t smc_interrupt(int irq, void *dev_id);
+-
+-static int use_poll = 0;
+-module_param(use_poll, int, 0);
+-MODULE_PARM_DESC(use_poll, "Use scheduling timer to poll driver");
+-
+-/* This is used by cleanup, to prevent the module from being unloaded while
+- * intrpt_routine is still in the task queue
++ * MSch: Interrupt wrapper to prevent calling the main interrupt handler
++ * from MFP timer D routine before device has been opened.
+ */
+-static wait_queue_head_t WaitQ;
+-
+-static struct delayed_work tqueue;
+
+-static struct net_device *poll_dev = NULL;
++static irqreturn_t smc_interrupt(int irq, void *dev_id);
+
+-static void atari_ethernat_int(struct work_struct *work)
++static irqreturn_t atari_ethernat_interrupt(int irq, void *dev_id)
+ {
+- struct net_device *dev = poll_dev;
+-
+- if(!dev) {
+- /* If cleanup wants us to die */
+- if (waitqueue_active(&WaitQ))
+- wake_up(&WaitQ); /* Now cleanup_module can return */
+- else
+- /* Put ourselves back in the task queue */
+- schedule_delayed_work(&tqueue, 1);
+- return;
+- }
+-
+- /* This actually does not appear to work during probe */
++ struct net_device *dev = (struct net_device *) dev_id;
+ if (netif_running(dev)) {
+- smc_interrupt(dev->irq, dev);
+- }
+-
+- /* If cleanup wants us to die */
+- if (waitqueue_active(&WaitQ))
+- wake_up(&WaitQ); /* Now cleanup_module can return */
+- else
+- /* Put ourselves back in the task queue */
+- schedule_delayed_work(&tqueue, 0); /* reduced delay from 1 */
+-}
+-
+-static void atari_ethernat_start_poll(struct net_device *dev)
+-{
+- poll_dev = dev;
+-
+- init_waitqueue_head(&WaitQ);
+-
+- /* MSch: need to insert dev into work struct?? */
+-
+- INIT_DELAYED_WORK(&tqueue, atari_ethernat_int);
+- schedule_delayed_work(&tqueue, 1);
+-}
+-
+-static void atari_ethernat_stop_poll(struct net_device *dev)
+-{
+- if (dev && (dev == poll_dev)) {
+- sleep_on(&WaitQ);
++ return smc_interrupt(dev->irq, dev);
+ }
+- poll_dev = NULL;
++ return IRQ_HANDLED;
+ }
+
++static int period = 0;
++module_param(period, int, 0);
++MODULE_PARM_DESC(period, "Timer D period (123 for 200Hz)");
++
+ /*
+ * this does a soft reset on the device
+ */
+@@ -340,7 +294,7 @@ static void smc_reset(struct net_device
+ unsigned int ctl, cfg;
+ struct sk_buff *pending_skb;
+
+- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(2, "%s: %s\n", dev->name, __func__);
+
+ /* Disable all interrupts, block TX tasklet */
+ spin_lock_irq(&lp->lock);
+@@ -378,7 +332,7 @@ static void smc_reset(struct net_device
+ * can't handle it then there will be no recovery except for
+ * a hard reset or power cycle
+ */
+- if (nowait)
++ if (lp->cfg.flags & SMC91X_NOWAIT)
+ cfg |= CONFIG_NO_WAIT;
+
+ /*
+@@ -433,7 +387,7 @@ static void smc_enable(struct net_device
+ void __iomem *ioaddr = lp->base;
+ int mask;
+
+- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(2, "%s: %s\n", dev->name, __func__);
+
+ /* see the header file for options in TCR/RCR DEFAULT */
+ SMC_SELECT_BANK(lp, 0);
+@@ -467,7 +421,7 @@ static void smc_shutdown(struct net_devi
+ void __iomem *ioaddr = lp->base;
+ struct sk_buff *pending_skb;
+
+- DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
++ DBG(2, "%s: %s\n", CARDNAME, __func__);
+
+ /* no more interrupts for me */
+ spin_lock_irq(&lp->lock);
+@@ -500,7 +454,7 @@ static inline void smc_rcv(struct net_d
+ void __iomem *ioaddr = lp->base;
+ unsigned int packet_number, status, packet_len;
+
+- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(3, "%s: %s\n", dev->name, __func__);
+
+ packet_number = SMC_GET_RXFIFO(lp);
+ if (unlikely(packet_number & RXFIFO_REMPTY)) {
+@@ -635,43 +589,9 @@ static inline void smc_rcv(struct net_d
+ #define smc_special_unlock(lock) do { } while (0)
+ #endif
+
+-
+ /*
+- * MSch: EtherNAT is 32 bit, so the misaligned data buffer hack applies.
+- * This appears to hurt quite a lot ... need to fudge with the data pointer
+- * to compensate
+- */
+-
+-#define SMC_outw_be(v, a, r) writew_be(v, (a) + (r))
+-
+-#define SMC_PUSH_DATA_BE(lp, p, l) \
+- do { \
+- if (SMC_32BIT(lp)) { \
+- void *__ptr = (p); \
+- int __len = (l); \
+- void __iomem *__ioaddr = ioaddr; \
+- if (__len >= 2 && (unsigned long)__ptr & 2) { \
+- __len -= 2; \
+- SMC_outw_be(*(u16 *)__ptr, ioaddr, \
+- DATA_REG(lp)); \
+- __ptr += 2; \
+- } \
+- if (SMC_CAN_USE_DATACS && lp->datacs) \
+- __ioaddr = lp->datacs; \
+- SMC_outsl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
+- if (__len & 2) { \
+- __ptr += (__len & ~3); \
+- SMC_outw_be(*((u16 *)__ptr), ioaddr, \
+- DATA_REG(lp)); \
+- } \
+- } else if (SMC_16BIT(lp)) \
+- SMC_outsw(ioaddr, DATA_REG(lp), (u16 *) p, (l) >> 1); \
+- else if (SMC_8BIT(lp)) \
+- SMC_outsb(ioaddr, DATA_REG(lp), p, l); \
+- } while (0)
+-
+-
+-
++ * MSch FIXME: add SMC_PUSH_DATA_BE(lp, p, l)
++ */
+
+ /*
+ * This is called to actually send a packet to the chip.
+@@ -685,7 +605,7 @@ static void smc_hardware_send_pkt(unsign
+ unsigned int packet_no, len;
+ unsigned char *buf;
+
+- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(3, "%s: %s\n", dev->name, __func__);
+
+ if (!smc_special_trylock(&lp->lock)) {
+ netif_stop_queue(dev);
+@@ -726,7 +646,7 @@ static void smc_hardware_send_pkt(unsign
+ SMC_PUT_PKT_HDR(lp, 0, len + 6);
+
+ /* send the actual data */
+- SMC_PUSH_DATA_BE(lp, buf, len & ~1);
++ SMC_PUSH_DATA(lp, buf, len & ~1);
+
+ /* Send final ctl word with the last byte if there is one */
+ SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));
+@@ -770,7 +690,7 @@ static int smc_hard_start_xmit(struct sk
+ void __iomem *ioaddr = lp->base;
+ unsigned int numPages, poll_count, status;
+
+- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(3, "%s: %s\n", dev->name, __func__);
+
+ BUG_ON(lp->pending_tx_skb != NULL);
+
+@@ -842,7 +762,7 @@ static void smc_tx(struct net_device *de
+ void __iomem *ioaddr = lp->base;
+ unsigned int saved_packet, packet_no, tx_status, pkt_len;
+
+- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(3, "%s: %s\n", dev->name, __func__);
+
+ /* If the TX FIFO is empty then nothing to do */
+ packet_no = SMC_GET_TXFIFO(lp);
+@@ -964,7 +884,7 @@ static int smc_phy_read(struct net_devic
+ SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
+
+ DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+- __FUNCTION__, phyaddr, phyreg, phydata);
++ __func__, phyaddr, phyreg, phydata);
+
+ SMC_SELECT_BANK(lp, 2);
+ return phydata;
+@@ -991,7 +911,7 @@ static void smc_phy_write(struct net_dev
+ SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
+
+ DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+- __FUNCTION__, phyaddr, phyreg, phydata);
++ __func__, phyaddr, phyreg, phydata);
+
+ SMC_SELECT_BANK(lp, 2);
+ }
+@@ -1004,7 +924,7 @@ static void smc_phy_detect(struct net_de
+ struct smc_local *lp = netdev_priv(dev);
+ int phyaddr;
+
+- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(2, "%s: %s\n", dev->name, __func__);
+
+ lp->phy_type = 0;
+
+@@ -1043,7 +963,7 @@ static int smc_phy_fixed(struct net_devi
+ int phyaddr = lp->mii.phy_id;
+ int bmcr, cfg1;
+
+- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(3, "%s: %s\n", dev->name, __func__);
+
+ /* Enter Link Disable state */
+ cfg1 = smc_phy_read(dev, phyaddr, PHY_CFG1_REG);
+@@ -1276,7 +1196,7 @@ static void smc_phy_interrupt(struct net
+ int phyaddr = lp->mii.phy_id;
+ int phy18;
+
+- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(2, "%s: %s\n", dev->name, __func__);
+
+ if (lp->phy_type == 0)
+ return;
+@@ -1344,7 +1264,7 @@ static irqreturn_t smc_interrupt(int irq
+ int status, mask, timeout, card_stats;
+ int saved_pointer;
+
+- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(3, "%s: %s\n", dev->name, __func__);
+
+ spin_lock(&lp->lock);
+
+@@ -1363,7 +1283,7 @@ static irqreturn_t smc_interrupt(int irq
+ do {
+ status = SMC_GET_INT(lp);
+
+- DBG(3, "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
++ DBG(2, "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
+ dev->name, status, mask,
+ ({ int meminfo; SMC_SELECT_BANK(lp, 0);
+ meminfo = SMC_GET_MIR(lp);
+@@ -1376,20 +1296,20 @@ static irqreturn_t smc_interrupt(int irq
+
+ if (status & IM_TX_INT) {
+ /* do this before RX as it will free memory quickly */
+- DBG(2, "%s: TX int\n", dev->name);
++ DBG(3, "%s: TX int\n", dev->name);
+ smc_tx(dev);
+ SMC_ACK_INT(lp, IM_TX_INT);
+ if (THROTTLE_TX_PKTS)
+ netif_wake_queue(dev);
+ } else if (status & IM_RCV_INT) {
+- DBG(2, "%s: RX irq\n", dev->name);
++ DBG(3, "%s: RX irq\n", dev->name);
+ smc_rcv(dev);
+ } else if (status & IM_ALLOC_INT) {
+- DBG(1, "%s: Allocation irq\n", dev->name);
++ DBG(3, "%s: Allocation irq\n", dev->name);
+ tasklet_hi_schedule(&lp->tx_task);
+ mask &= ~IM_ALLOC_INT;
+ } else if (status & IM_TX_EMPTY_INT) {
+- DBG(2, "%s: TX empty\n", dev->name);
++ DBG(3, "%s: TX empty\n", dev->name);
+ mask &= ~IM_TX_EMPTY_INT;
+
+ /* update stats */
+@@ -1407,15 +1327,13 @@ static irqreturn_t smc_interrupt(int irq
+ DBG(1, "%s: RX overrun (EPH_ST 0x%04x)\n", dev->name,
+ ({ int eph_st; SMC_SELECT_BANK(lp, 0);
+ eph_st = SMC_GET_EPH_STATUS(lp);
+- SMC_SELECT_BANK(lp, 2); eph_st; }) );
++ SMC_SELECT_BANK(lp, 2); eph_st; }));
+ SMC_ACK_INT(lp, IM_RX_OVRN_INT);
+ dev->stats.rx_errors++;
+ dev->stats.rx_fifo_errors++;
+ } else if (status & IM_EPH_INT) {
+- DBG(1, "%s: eph interrupt\n", dev->name);
+ smc_eph_interrupt(dev);
+ } else if (status & IM_MDINT) {
+- DBG(1, "%s: phy interrupt\n", dev->name);
+ SMC_ACK_INT(lp, IM_MDINT);
+ smc_phy_interrupt(dev);
+ } else if (status & IM_ERCV_INT) {
+@@ -1430,12 +1348,10 @@ static irqreturn_t smc_interrupt(int irq
+ spin_unlock(&lp->lock);
+
+ #ifndef CONFIG_NET_POLL_CONTROLLER
+-#if 0
+- if (timeout == MAX_IRQ_LOOPS)
++ if (timeout == MAX_IRQ_LOOPS && dev->irq != IRQ_MFP_TIMD)
+ PRINTK("%s: spurious interrupt (mask = 0x%02x)\n",
+ dev->name, mask);
+ #endif
+-#endif
+ DBG(3, "%s: Interrupt done (%d loops)\n",
+ dev->name, MAX_IRQ_LOOPS - timeout);
+
+@@ -1470,7 +1386,7 @@ static void smc_timeout(struct net_devic
+ void __iomem *ioaddr = lp->base;
+ int status, mask, eph_st, meminfo, fifo;
+
+- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(2, "%s: %s\n", dev->name, __func__);
+
+ spin_lock_irq(&lp->lock);
+ status = SMC_GET_INT(lp);
+@@ -1493,7 +1409,7 @@ static void smc_timeout(struct net_devic
+ * smc_phy_configure() calls msleep() which calls schedule_timeout()
+ * which calls schedule(). Hence we use a work queue.
+ */
+- if (lp->phy_type != 0)
++ if (lp->phy_type != 0)
+ schedule_work(&lp->phy_configure);
+
+ /* We can accept TX packets again */
+@@ -1514,7 +1430,7 @@ static void smc_set_multicast_list(struc
+ unsigned char multicast_table[8];
+ int update_multicast = 0;
+
+- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(2, "%s: %s\n", dev->name, __func__);
+
+ if (dev->flags & IFF_PROMISC) {
+ DBG(2, "%s: RCR_PRMS\n", dev->name);
+@@ -1617,7 +1533,7 @@ smc_open(struct net_device *dev)
+ {
+ struct smc_local *lp = netdev_priv(dev);
+
+- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(2, "%s: %s\n", dev->name, __func__);
+
+ /*
+ * Check that the address is valid. If its not, refuse
+@@ -1625,14 +1541,16 @@ smc_open(struct net_device *dev)
+ * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
+ */
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+- PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__);
++ PRINTK("%s: no valid ethernet hw addr\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Setup the default Register Modes */
+ lp->tcr_cur_mode = TCR_DEFAULT;
+ lp->rcr_cur_mode = RCR_DEFAULT;
+- lp->rpc_cur_mode = RPC_DEFAULT;
++ lp->rpc_cur_mode = RPC_DEFAULT |
++ lp->cfg.leda << RPC_LSXA_SHFT |
++ lp->cfg.ledb << RPC_LSXB_SHFT;
+
+ /*
+ * If we are not using a MII interface, we need to
+@@ -1669,7 +1587,7 @@ static int smc_close(struct net_device *
+ {
+ struct smc_local *lp = netdev_priv(dev);
+
+- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++ DBG(2, "%s: %s\n", dev->name, __func__);
+
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+@@ -1812,7 +1730,7 @@ static int __init smc_findirq(struct smc
+ int timeout = 20;
+ unsigned long cookie;
+
+- DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
++ DBG(2, "%s: %s\n", CARDNAME, __func__);
+
+ cookie = probe_irq_on();
+
+@@ -1881,7 +1799,7 @@ static int __init smc_findirq(struct smc
+ * o GRAB the region
+ */
+ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+- unsigned long irq_flags)
++ unsigned long irq_flags)
+ {
+ struct smc_local *lp = netdev_priv(dev);
+ static int version_printed = 0;
+@@ -1890,8 +1808,9 @@ static int __init smc_probe(struct net_d
+ const char *version_string;
+ DECLARE_MAC_BUF(mac);
+
+- DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
++ DBG(2, "%s: %s\n", CARDNAME, __func__);
+
++ /* First, see if there is a card at the expected address! */
+ if (!hwreg_present( ioaddr + BANK_SELECT )) {
+ retval = -ENODEV;
+ goto err_out;
+@@ -2052,14 +1971,15 @@ static int __init smc_probe(struct net_d
+ }
+
+ /* Grab the IRQ */
+- retval = request_irq(dev->irq, &smc_interrupt, irq_flags, dev->name, dev);
+- if (retval) {
+- use_poll = 1;
+- //goto err_out;
+- }
++ retval = request_irq(dev->irq, &atari_ethernat_interrupt, irq_flags, dev->name, dev);
++ if (retval)
++ goto err_out;
+
+-#ifdef SMC_USE_PXA_DMA
+- {
++#ifdef CONFIG_ARCH_PXA
++# ifdef SMC_USE_PXA_DMA
++ lp->cfg.flags |= SMC91X_USE_DMA;
++# endif
++ if (lp->cfg.flags & SMC91X_USE_DMA) {
+ int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
+ smc_pxa_dma_irq, NULL);
+ if (dma >= 0)
+@@ -2077,14 +1997,15 @@ static int __init smc_probe(struct net_d
+ if (dev->dma != (unsigned char)-1)
+ printk(" DMA %d", dev->dma);
+
+- printk("%s%s\n", nowait ? " [nowait]" : "",
++ printk(KERN_INFO "%s%s\n",
++ lp->cfg.flags & SMC91X_NOWAIT ? " [nowait]" : "",
+ THROTTLE_TX_PKTS ? " [throttle_tx]" : "");
+
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+ printk("%s: Invalid ethernet MAC address. Please "
+- "set proper address using ifconfig\n", dev->name);
++ "set using ifconfig\n", dev->name);
+ random_ether_addr(dev->dev_addr);
+- printk("%s: Ethernet addr (random): %s\n",
++ printk(KERN_INFO "%s: Ethernet addr set (random): %s\n",
+ dev->name, print_mac(mac, dev->dev_addr));
+ } else {
+ /* Print the Ethernet address */
+@@ -2099,19 +2020,10 @@ static int __init smc_probe(struct net_d
+ } else if ((lp->phy_type & 0xfffffff0) == 0x02821c50) {
+ PRINTK("%s: PHY LAN83C180\n", dev->name);
+ }
+-
+- if (SMC_32BIT(lp)) {
+- printk("%s: using 32 bit access\n", dev->name);
+- } else if (SMC_16BIT(lp)) {
+- printk("%s: using 16 bit access\n", dev->name);
+- } else {
+- printk("%s: using 8 bit access\n", dev->name);
+- }
+-
+ }
+
+ err_out:
+-#ifdef SMC_USE_PXA_DMA
++#ifdef CONFIG_ARCH_PXA
+ if (retval && dev->dma != (unsigned char)-1)
+ pxa_free_dma(dev->dma);
+ #endif
+@@ -2128,24 +2040,17 @@ static int smc_enable_device(struct plat
+ struct resource * res;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+- if (!res) {
+- printk("smc_enable_device: smc91x-attrib resource not found !\n");
++ if (!res)
+ return 0;
+- }
+-
+- printk("smc_enable_device: smc91x-attrib resource found, start=%x !\n", res->start);
+
+ /*
+ * Map the attribute space. This is overkill, but clean.
+ */
+ addr = ioremap(res->start, ATTRIB_SIZE);
+- if (!addr) {
++ if (!addr)
+ return -ENOMEM;
+- }
+
+- printk("smc_enable_device :smc91x-attrib resource remapped, start=%p !\n", addr);
+-
+- /*
++ /*
+ * Reset the device. We must disable IRQs around this
+ * since a reset causes the IRQ line become active.
+ */
+@@ -2188,23 +2093,26 @@ static int smc_enable_device(struct plat
+ return 0;
+ }
+
+-static int smc_request_attrib(struct platform_device *pdev)
++static int smc_request_attrib(struct platform_device *pdev,
++ struct net_device *ndev)
+ {
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
++ struct smc_local *lp = netdev_priv(ndev);
+
+ if (!res)
+ return 0;
+
+- if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME)) {
++ if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME))
+ return -EBUSY;
+- }
+-
++
+ return 0;
+ }
+
+-static void smc_release_attrib(struct platform_device *pdev)
++static void smc_release_attrib(struct platform_device *pdev,
++ struct net_device *ndev)
+ {
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
++ struct smc_local *lp = netdev_priv(ndev);
+
+ if (res)
+ release_mem_region(res->start, ATTRIB_SIZE);
+@@ -2245,25 +2153,6 @@ static void smc_release_datacs(struct pl
+ }
+
+ /*
+- * Resources defined and added to platform data in arch/m68k/atari/config.c
+- * These are left here for reference only!
+- */
+-
+-struct resource ethernat_attr = {
+- .start = 0x80000000,
+- .end = 0x800000FF,
+- .name = "smc91x-attrib",
+- .flags = IORESOURCE_MEM
+-};
+-
+-struct resource ethernat_datacs = {
+- .start = 0,
+- .end = 0,
+- .name = "smc91x-data32",
+- .flags = IORESOURCE_MEM
+-};
+-
+-/*
+ * smc_init(void)
+ * Input parameters:
+ * dev->base_addr == 0, try to find all possible locations
+@@ -2274,38 +2163,21 @@ struct resource ethernat_datacs = {
+ * 0 --> there is a device
+ * anything else, error
+ */
+-
+-static int __init atari_ethernat_pdev_probe(struct platform_device *pdev)
++static int smc_drv_probe(struct platform_device *pdev)
+ {
+ struct smc91x_platdata *pd = pdev->dev.platform_data;
+ struct smc_local *lp;
+ struct net_device *ndev;
+ struct resource *res, *ires;
+ unsigned int __iomem *addr;
++ unsigned long irq_flags = SMC_IRQ_FLAGS;
+ int ret;
+
+- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+- if (!res)
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!res) {
+- printk("smc91x-regs resource not found!\n");
+- ret = -ENODEV;
+- goto out;
+- }
+-
+- printk("smc91x-regs resource found, start=%x !\n", res->start);
+-
+- if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
+- printk("could not request smc91x-regs resource at %ul!\n", res->start);
+- ret = -EBUSY;
+- goto out;
+- }
+-
+ ndev = alloc_etherdev(sizeof(struct smc_local));
+ if (!ndev) {
+ printk("%s: could not allocate device.\n", CARDNAME);
+ ret = -ENOMEM;
+- goto out_release_io;
++ goto out;
+ }
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+
+@@ -2314,32 +2186,47 @@ static int __init atari_ethernat_pdev_pr
+ */
+
+ lp = netdev_priv(ndev);
+- lp->cfg.irq_flags = SMC_IRQ_FLAGS;
+
+-#ifdef SMC_DYNAMIC_BUS_CONFIG
+- if (pd)
++ if (pd) {
+ memcpy(&lp->cfg, pd, sizeof(lp->cfg));
+- else {
+- lp->cfg.flags = SMC91X_USE_8BIT;
+- lp->cfg.flags |= SMC91X_USE_16BIT;
+- lp->cfg.flags |= SMC91X_USE_32BIT;
++ lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
++ } else {
++ lp->cfg.flags |= (SMC_CAN_USE_8BIT) ? SMC91X_USE_8BIT : 0;
++ lp->cfg.flags |= (SMC_CAN_USE_16BIT) ? SMC91X_USE_16BIT : 0;
++ lp->cfg.flags |= (SMC_CAN_USE_32BIT) ? SMC91X_USE_32BIT : 0;
++ lp->cfg.flags |= (nowait) ? SMC91X_NOWAIT : 0;
+ }
+
+- lp->cfg.flags &= ~(SMC_CAN_USE_8BIT ? 0 : SMC91X_USE_8BIT);
+- lp->cfg.flags &= ~(SMC_CAN_USE_16BIT ? 0 : SMC91X_USE_16BIT);
+- lp->cfg.flags &= ~(SMC_CAN_USE_32BIT ? 0 : SMC91X_USE_32BIT);
+-#endif
++ if (!lp->cfg.leda && !lp->cfg.ledb) {
++ lp->cfg.leda = RPC_LSA_DEFAULT;
++ lp->cfg.ledb = RPC_LSB_DEFAULT;
++ }
+
+ ndev->dma = (unsigned char)-1;
+
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
++ if (!res)
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ ret = -ENODEV;
++ goto out_free_netdev;
++ }
++
++
++ if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
++ ret = -EBUSY;
++ goto out_free_netdev;
++ }
++
+ ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!ires) {
+- printk("atari_91C111: IRQ resource not found!\n");
+ ret = -ENODEV;
+- goto out_free_netdev;
++ goto out_release_io;
+ }
+
+ ndev->irq = ires->start;
++
++ if (ndev->irq != IRQ_MFP_TIMD) {
+ printk("atari_91C111: IRQ resource specified irq=%d\n", ndev->irq);
+
+ /*
+@@ -2356,35 +2243,27 @@ static int __init atari_ethernat_pdev_pr
+ ndev->irq = IRQ_MFP_TIMD;
+ ires->start = IRQ_MFP_TIMD;
+ printk("atari_91C111: IRQ forced to irq=%d\n", ndev->irq);
++ }
+
+- if (SMC_IRQ_FLAGS == -1)
+- lp->cfg.irq_flags = ires->flags & IRQF_TRIGGER_MASK;
++ if (ires->flags & IRQF_TRIGGER_MASK)
++ irq_flags = ires->flags & IRQF_TRIGGER_MASK;
+
+- if (ndev->irq < 0) {
+- printk("atari_91C111: cannot determine interrupt! Using timer D poll...\n");
+- ndev->irq = IRQ_MFP_TIMD;
+- /* timer actually set up later */
+- }
+
+ if (ndev->irq == IRQ_MFP_TIMD) {
+- printk("atari_91C111: Using timer D interrupt - do share!\n");
+- lp->cfg.irq_flags = IRQF_SHARED;
++ printk(KERN_INFO "atari_91C111: Using timer D interrupt - do share!\n");
++ irq_flags |= IRQF_SHARED;
+ }
+
+- ret = smc_request_attrib(pdev);
+- if (ret) {
+- printk("atari_91C111: attrib resource not found!\n");
+- goto out_free_netdev;
+- }
++ ret = smc_request_attrib(pdev, ndev);
++ if (ret)
++ goto out_release_io;
+ #if defined(CONFIG_SA1100_ASSABET)
+ NCR_0 |= NCR_ENET_OSC_EN;
+ #endif
+ platform_set_drvdata(pdev, ndev);
+ ret = smc_enable_device(pdev);
+- if (ret) {
+- printk("atari_91C111: failed to enable card!\n");
++ if (ret)
+ goto out_release_attrib;
+- }
+
+ addr = ioremap(res->start, SMC_IO_EXTENT);
+ if (!addr) {
+@@ -2392,7 +2271,7 @@ static int __init atari_ethernat_pdev_pr
+ goto out_release_attrib;
+ }
+
+-#ifdef SMC_USE_PXA_DMA
++#ifdef CONFIG_ARCH_PXA
+ {
+ struct smc_local *lp = netdev_priv(ndev);
+ lp->device = &pdev->dev;
+@@ -2400,46 +2279,47 @@ static int __init atari_ethernat_pdev_pr
+ }
+ #endif
+
+- printk("smc91x-regs resource remapped, start=%p!\n", addr);
+-
+ /*
+ * about to probe for device; need to enable net IRQ here!
+ * EtherNAT has interrupt enable register at 0x20 or 0x23
+ * probe for base address + 0x23 or 0x20
+ */
+
+- ret = smc_probe(ndev, addr, lp->cfg.irq_flags);
++ ret = smc_probe(ndev, addr, irq_flags);
+ if (ret != 0)
+ goto out_iounmap;
+
+- printk("smc91x probe done, irq %d!\n", ndev->irq);
+- ndev->irq = IRQ_MFP_TIMD;
++ smc_request_datacs(pdev, ndev);
+
+- if (ndev->irq < 0) {
+- if (use_poll)
+- atari_ethernat_start_poll(ndev);
+- } else if (ndev->irq == IRQ_MFP_TIMD) {
++ if (ndev->irq == IRQ_MFP_TIMD) {
+ /* maybe instead use MFP timer C ?? */
+ /* init timer if not already running */
++
++ int timd = period * 4;
++ if (timd == 0)
++ timd = 192; /* 200 Hz */
++ else if (timd < 80)
++ timd = 80;
++ else if (timd > 255)
++ timd = 255;
++ printk(KERN_INFO "Timer D frequency: %d Hz\n", (38400UL/(unsigned int)timd));
+ /* set Timer D data Register */
+- mfp.tim_dt_d = 123; /* 200 Hz */
++ mfp.tim_dt_d = timd; /* 200 Hz */
+ /* start timer D, div = 1:100 */
+- mfp.tim_ct_cd = (mfp.tim_ct_cd & 0xf0) | 0x6;
++ mfp.tim_ct_cd = (mfp.tim_ct_cd & 0xf0) | 0x5;
+ }
+
+- smc_request_datacs(pdev, ndev);
+-
+ return 0;
+
+ out_iounmap:
+ platform_set_drvdata(pdev, NULL);
+ iounmap(addr);
+ out_release_attrib:
+- smc_release_attrib(pdev);
+- out_free_netdev:
+- free_netdev(ndev);
++ smc_release_attrib(pdev, ndev);
+ out_release_io:
+ release_mem_region(res->start, SMC_IO_EXTENT);
++ out_free_netdev:
++ free_netdev(ndev);
+ out:
+ printk("%s: not found (%d).\n", CARDNAME, ret);
+
+@@ -2454,25 +2334,22 @@ static int smc_drv_remove(struct platfor
+
+ platform_set_drvdata(pdev, NULL);
+
+- if (use_poll)
+- atari_ethernat_stop_poll(ndev);
+-
+ unregister_netdev(ndev);
+
+ free_irq(ndev->irq, ndev);
+
+-#ifdef SMC_USE_PXA_DMA
++#ifdef CONFIG_ARCH_PXA
+ if (ndev->dma != (unsigned char)-1)
+ pxa_free_dma(ndev->dma);
+ #endif
+ iounmap(lp->base);
+
+ smc_release_datacs(pdev,ndev);
+- smc_release_attrib(pdev);
++ smc_release_attrib(pdev, ndev);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+ if (!res)
+- platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, SMC_IO_EXTENT);
+
+ free_netdev(ndev);
+@@ -2513,12 +2390,13 @@ static int smc_drv_resume(struct platfor
+ }
+
+ static struct platform_driver smc_driver = {
+- .probe = atari_ethernat_pdev_probe,
++ .probe = smc_drv_probe,
+ .remove = smc_drv_remove,
+ .suspend = smc_drv_suspend,
+ .resume = smc_drv_resume,
+ .driver = {
+ .name = CARDNAME,
++ .owner = THIS_MODULE,
+ },
+ };
+
+--- a/drivers/net/smc91x.h
++++ b/drivers/net/smc91x.h
+@@ -436,6 +436,32 @@ static inline void LPD7_SMC_outsw (unsig
+
+ #include <asm/unit/smc91111.h>
+
++#elif defined(CONFIG_ATARI_ETHERNAT) || defined(CONFIG_ATARI_ETHERNAT_MODULE)
++
++#define SMC_CAN_USE_8BIT 1
++#define SMC_CAN_USE_16BIT 1
++#define SMC_CAN_USE_32BIT 1
++#define SMC_NOWAIT 1
++
++#define writew_be(val, addr) out_be16((addr), (val))
++
++#define SMC_inb(a, r) readb((a) + (r))
++#define SMC_inw(a, r) readw((a) + (r))
++#define SMC_inl(a, r) readl((a) + (r))
++#define SMC_outb(v, a, r) writeb(v, (a) + (r))
++#define SMC_outw(v, a, r) writew(v, (a) + (r))
++#define SMC_outw_be(v, a, r) writew_be(v, (a) + (r))
++#define SMC_outl(v, a, r) writel(v, (a) + (r))
++#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
++#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
++#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
++#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
++
++#define RPC_LSA_DEFAULT RPC_LED_100_10
++#define RPC_LSB_DEFAULT RPC_LED_TX_RX
++
++#define SMC_DYNAMIC_BUS_CONFIG
++
+ #else
+
+ /*
+@@ -1270,6 +1296,40 @@ static const char * chip_ids[ 16 ] = {
+ } \
+ } while (0)
+
++#if defined(CONFIG_ATARI_ETHERNAT) || defined(CONFIG_ATARI_ETHERNAT_MODULE)
++/*
++ * MSch: EtherNAT is 32 bit, so the misaligned data buffer hack applies.
++ * This appears to hurt quite a lot ... we actually need to byte swap the
++ * misaligned write because the data end up in the packet buffer swapped
++ * otherwise (resulting in the first two bytes of the target MAC address
++ * being swapped)
++ */
++#define SMC_PUSH_DATA(lp, p, l) \
++ do { \
++ if (SMC_32BIT(lp)) { \
++ void *__ptr = (p); \
++ int __len = (l); \
++ void __iomem *__ioaddr = ioaddr; \
++ if (__len >= 2 && (unsigned long)__ptr & 2) { \
++ __len -= 2; \
++ SMC_outw_be(*(u16 *)__ptr, ioaddr, \
++ DATA_REG(lp)); \
++ __ptr += 2; \
++ } \
++ if (SMC_CAN_USE_DATACS && lp->datacs) \
++ __ioaddr = lp->datacs; \
++ SMC_outsl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
++ if (__len & 2) { \
++ __ptr += (__len & ~3); \
++ SMC_outw_be(*((u16 *)__ptr), ioaddr, \
++ DATA_REG(lp)); \
++ } \
++ } else if (SMC_16BIT(lp)) \
++ SMC_outsw(ioaddr, DATA_REG(lp), (u16 *) p, (l) >> 1); \
++ else if (SMC_8BIT(lp)) \
++ SMC_outsb(ioaddr, DATA_REG(lp), p, l); \
++ } while (0)
++#else
+ #define SMC_PUSH_DATA(lp, p, l) \
+ do { \
+ if (SMC_32BIT(lp)) { \
+@@ -1295,6 +1355,7 @@ static const char * chip_ids[ 16 ] = {
+ else if (SMC_8BIT(lp)) \
+ SMC_outsb(ioaddr, DATA_REG(lp), p, l); \
+ } while (0)
++#endif
+
+ #define SMC_PULL_DATA(lp, p, l) \
+ do { \
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernat-warning-fix.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernat-warning-fix.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,66 @@
+Subject: [PATCH] m68k: Atari EtherNAT warning fixes
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+drivers/net/atari_91C111.c: In function 'smc_rcv':
+drivers/net/atari_91C111.c:538: warning: passing argument 2 of 'raw_insw' from incompatible pointer type
+drivers/net/atari_91C111.c: In function 'smc_request_attrib':
+drivers/net/atari_91C111.c:2100: warning: unused variable 'lp'
+drivers/net/atari_91C111.c: In function 'smc_release_attrib':
+drivers/net/atari_91C111.c:2115: warning: unused variable 'lp'
+drivers/net/atari_91C111.c: In function 'smc_drv_probe':
+drivers/net/atari_91C111.c:2305: warning: format '%d' expects type 'int', but argument 2 has type 'long unsigned int'
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/atari_91C111.c | 4 +---
+ drivers/net/smc91x.h | 4 ++--
+ 2 files changed, 3 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/atari_91C111.c
++++ b/drivers/net/atari_91C111.c
+@@ -2097,7 +2097,6 @@ static int smc_request_attrib(struct pla
+ struct net_device *ndev)
+ {
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+- struct smc_local *lp = netdev_priv(ndev);
+
+ if (!res)
+ return 0;
+@@ -2112,7 +2111,6 @@ static void smc_release_attrib(struct pl
+ struct net_device *ndev)
+ {
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+- struct smc_local *lp = netdev_priv(ndev);
+
+ if (res)
+ release_mem_region(res->start, ATTRIB_SIZE);
+@@ -2302,7 +2300,7 @@ static int smc_drv_probe(struct platform
+ timd = 80;
+ else if (timd > 255)
+ timd = 255;
+- printk(KERN_INFO "Timer D frequency: %d Hz\n", (38400UL/(unsigned int)timd));
++ printk(KERN_INFO "Timer D frequency: %u Hz\n", 38400/timd);
+ /* set Timer D data Register */
+ mfp.tim_dt_d = timd; /* 200 Hz */
+ /* start timer D, div = 1:100 */
+--- a/drivers/net/smc91x.h
++++ b/drivers/net/smc91x.h
+@@ -1351,7 +1351,7 @@ static const char * chip_ids[ 16 ] = {
+ DATA_REG(lp)); \
+ } \
+ } else if (SMC_16BIT(lp)) \
+- SMC_outsw(ioaddr, DATA_REG(lp), p, (l) >> 1); \
++ SMC_outsw(ioaddr, DATA_REG(lp), (u16 *) p, (l) >> 1); \
+ else if (SMC_8BIT(lp)) \
+ SMC_outsb(ioaddr, DATA_REG(lp), p, l); \
+ } while (0)
+@@ -1387,7 +1387,7 @@ static const char * chip_ids[ 16 ] = {
+ __len += 2; \
+ SMC_insl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
+ } else if (SMC_16BIT(lp)) \
+- SMC_insw(ioaddr, DATA_REG(lp), p, (l) >> 1); \
++ SMC_insw(ioaddr, DATA_REG(lp), (u16 *) p, (l) >> 1); \
+ else if (SMC_8BIT(lp)) \
+ SMC_insb(ioaddr, DATA_REG(lp), p, l); \
+ } while (0)
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernat.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernat.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,2658 @@
+Subject: [PATCH] m68k: Atari EtherNAT (SMC91C111) driver
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+SMC91C111 driver aka EtherNAT driver for the Atari Falcon
+
+Signed-off-by: Michael Schmitz <schmitz at biophys.uni-duesseldorf.de>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+
+FIXME checkpatch
+---
+One thing that I am not entirely happy about is having the driver resource
+registered unconditionally in atari/config.c, regardless whether the
+driver is built or not. May I incude autoconf.h in the arch code? The
+other one is a kconfig issue - I need to select MMIO either as module or
+builtin, depending on how the EtherNAT driver is built. That does not
+appear to be automatic yet.
+
+ arch/m68k/atari/config.c | 41
+ drivers/net/Kconfig | 10
+ drivers/net/Makefile | 1
+ drivers/net/atari_91C111.c | 2548 +++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 2600 insertions(+)
+
+--- a/arch/m68k/atari/config.c
++++ b/arch/m68k/atari/config.c
+@@ -31,6 +31,7 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/ioport.h>
++#include <linux/platform_device.h>
+ #include <linux/vt_kern.h>
+ #include <linux/module.h>
+
+@@ -656,3 +657,43 @@ static void atari_get_hardware_list(stru
+ ATARIHW_ANNOUNCE(VME, "VME Bus");
+ ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
+ }
++
++/*
++ * MSch: initial platform device support for Atari, required for EtherNAT
++ */
++
++#define ATARI_ETHERNAT_PHYS_ADDR 0x80000000
++#define ATARI_ETHERNAT_IRQ 0xc3
++
++static struct resource smc91x_resources[] = {
++ [0] = {
++ .name = "smc91x-regs",
++ .start = ATARI_ETHERNAT_PHYS_ADDR,
++ .end = ATARI_ETHERNAT_PHYS_ADDR + 0xfffff,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .name = "smc91x-irq",
++ .start = ATARI_ETHERNAT_IRQ,
++ .end = ATARI_ETHERNAT_IRQ,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device smc91x_device = {
++ .name = "smc91x",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(smc91x_resources),
++ .resource = smc91x_resources,
++};
++
++static struct platform_device *atari_platform_devices[] __initdata = {
++ &smc91x_device
++};
++
++int __init atari_platform_init(void)
++{
++ return platform_add_devices(atari_platform_devices, ARRAY_SIZE(atari_platform_devices));
++}
++
++arch_initcall(atari_platform_init);
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -414,6 +414,16 @@ config ATARI_ETHERNEC
+ ROM port. The driver works by polling instead of interrupts, so it
+ is quite slow.
+
++config ATARI_ETHERNAT
++ tristate "Atari EtherNAT Ethernet support"
++ select CRC32
++ select MII
++ depends on NET_ETHERNET && ATARI
++ help
++ Say Y to include support for the EtherNAT network adapter for the
++ CT/60 extension 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 SUN3 || SUN3X
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -203,6 +203,7 @@ obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
+ obj-$(CONFIG_DECLANCE) += declance.o
+ obj-$(CONFIG_ATARILANCE) += atarilance.o
+ obj-$(CONFIG_ATARI_ETHERNEC) += atari_ethernec.o 8390.o
++obj-$(CONFIG_ATARI_ETHERNAT) += atari_91C111.o
+ obj-$(CONFIG_A2065) += a2065.o
+ obj-$(CONFIG_HYDRA) += hydra.o
+ obj-$(CONFIG_ARIADNE) += ariadne.o
+--- /dev/null
++++ b/drivers/net/atari_91C111.c
+@@ -0,0 +1,2548 @@
++/*
++ * smc91x.c
++ * This is a driver for SMSC's 91C9x/91C1xx single-chip Ethernet devices.
++ *
++ * Copyright (C) 1996 by Erik Stahlman
++ * Copyright (C) 2001 Standard Microsystems Corporation
++ * Developed by Simple Network Magic Corporation
++ * Copyright (C) 2003 Monta Vista Software, Inc.
++ * Unified SMC91x driver by Nicolas Pitre
++ *
++ * This program 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.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Arguments:
++ * io = for the base address
++ * irq = for the IRQ
++ * nowait = 0 for normal wait states, 1 eliminates additional wait states
++ *
++ * original author:
++ * Erik Stahlman <erik at vt.edu>
++ *
++ * hardware multicast code:
++ * Peter Cammaert <pc at denkart.be>
++ *
++ * contributors:
++ * Daris A Nevil <dnevil at snmc.com>
++ * Nicolas Pitre <nico at cam.org>
++ * Russell King <rmk at arm.linux.org.uk>
++ *
++ * History:
++ * 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet
++ * 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ"
++ * 03/16/01 Daris A Nevil modified smc9194.c for use with LAN91C111
++ * 08/22/01 Scott Anderson merge changes from smc9194 to smc91111
++ * 08/21/01 Pramod B Bhardwaj added support for RevB of LAN91C111
++ * 12/20/01 Jeff Sutherland initial port to Xscale PXA with DMA support
++ * 04/07/03 Nicolas Pitre unified SMC91x driver, killed irq races,
++ * more bus abstraction, big cleanup, etc.
++ * 29/09/03 Russell King - add driver model support
++ * - ethtool support
++ * - convert to use generic MII interface
++ * - add link up/down notification
++ * - don't try to handle full negotiation in
++ * smc_phy_configure
++ * - clean up (and fix stack overrun) in PHY
++ * MII read/write functions
++ * 22/09/04 Nicolas Pitre big update (see commit log for details)
++ */
++static const char version[] =
++ "smc91x.c: v1.1, sep 22 2004 by Nicolas Pitre <nico at cam.org>\n";
++
++#define SMC_DEBUG 1
++
++/* Debugging level */
++#ifndef SMC_DEBUG
++#define SMC_DEBUG 0
++#endif
++
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/errno.h>
++#include <linux/ioport.h>
++#include <linux/crc32.h>
++#include <linux/platform_device.h>
++#include <linux/spinlock.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/workqueue.h>
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++
++#include <asm/hwtest.h>
++#include <asm/atariints.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++
++#include "smc91x.h"
++
++#ifdef CONFIG_ISA
++/*
++ * the LAN91C111 can be at any of the following port addresses. To change,
++ * for a slightly different card, you can add it to the array. Keep in
++ * mind that the array must end in zero.
++ */
++static unsigned int smc_portlist[] __initdata = {
++ 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
++ 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0
++};
++
++#endif /* CONFIG_ISA */
++
++#ifndef SMC_IOADDR
++# define SMC_IOADDR -1
++#endif
++static unsigned long io = SMC_IOADDR;
++module_param(io, ulong, 0400);
++MODULE_PARM_DESC(io, "I/O base address");
++
++#ifndef SMC_IRQ
++# define SMC_IRQ -1
++#endif
++static int irq = SMC_IRQ;
++module_param(irq, int, 0400);
++MODULE_PARM_DESC(irq, "IRQ number");
++
++
++#ifndef SMC_NOWAIT
++# define SMC_NOWAIT 0
++#endif
++static int nowait = SMC_NOWAIT;
++module_param(nowait, int, 0400);
++MODULE_PARM_DESC(nowait, "set to 1 for no wait state");
++
++/*
++ * Transmit timeout, default 5 seconds.
++ */
++static int watchdog = 1000;
++module_param(watchdog, int, 0400);
++MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
++
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:smc91x");
++
++/*
++ * The internal workings of the driver. If you are changing anything
++ * here with the SMC stuff, you should have the datasheet and know
++ * what you are doing.
++ */
++#define CARDNAME "smc91x"
++
++/*
++ * Use power-down feature of the chip
++ */
++#define POWER_DOWN 1
++
++/*
++ * Wait time for memory to be free. This probably shouldn't be
++ * tuned that much, as waiting for this means nothing else happens
++ * in the system
++ */
++#define MEMORY_WAIT_TIME 16
++
++/*
++ * The maximum number of processing loops allowed for each call to the
++ * IRQ handler.
++ */
++#define MAX_IRQ_LOOPS 8
++
++/*
++ * This selects whether TX packets are sent one by one to the SMC91x internal
++ * memory and throttled until transmission completes. This may prevent
++ * RX overruns a litle by keeping much of the memory free for RX packets
++ * but to the expense of reduced TX throughput and increased IRQ overhead.
++ * Note this is not a cure for a too slow data bus or too high IRQ latency.
++ */
++#define THROTTLE_TX_PKTS 1
++
++/*
++ * The MII clock high/low times. 2x this number gives the MII clock period
++ * in microseconds. (was 50, but this gives 6.4ms for each MII transaction!)
++ */
++#define MII_DELAY 1
++
++#if SMC_DEBUG > 0
++#define DBG(n, args...) \
++ do { \
++ if (SMC_DEBUG >= (n)) \
++ printk(args); \
++ } while (0)
++
++#define PRINTK(args...) printk(args)
++#else
++#define DBG(n, args...) do { } while(0)
++#define PRINTK(args...) printk(KERN_DEBUG args)
++#endif
++
++#if SMC_DEBUG > 3
++static void PRINT_PKT(u_char *buf, int length)
++{
++ int i;
++ int remainder;
++ int lines;
++
++ lines = length / 16;
++ remainder = length % 16;
++
++ for (i = 0; i < lines ; i ++) {
++ int cur;
++ for (cur = 0; cur < 8; cur++) {
++ u_char a, b;
++ a = *buf++;
++ b = *buf++;
++ printk("%02x%02x ", a, b);
++ }
++ printk("\n");
++ }
++ for (i = 0; i < remainder/2 ; i++) {
++ u_char a, b;
++ a = *buf++;
++ b = *buf++;
++ printk("%02x%02x ", a, b);
++ }
++ printk("\n");
++}
++#else
++#define PRINT_PKT(x...) do { } while(0)
++#endif
++
++
++/* this enables an interrupt in the interrupt mask register */
++#define SMC_ENABLE_INT(lp, x) do { \
++ unsigned char mask; \
++ spin_lock_irq(&lp->lock); \
++ mask = SMC_GET_INT_MASK(lp); \
++ mask |= (x); \
++ SMC_SET_INT_MASK(lp, mask); \
++ spin_unlock_irq(&lp->lock); \
++} while (0)
++
++/* this disables an interrupt from the interrupt mask register */
++#define SMC_DISABLE_INT(lp, x) do { \
++ unsigned char mask; \
++ spin_lock_irq(&lp->lock); \
++ mask = SMC_GET_INT_MASK(lp); \
++ mask &= ~(x); \
++ SMC_SET_INT_MASK(lp, mask); \
++ spin_unlock_irq(&lp->lock); \
++} while (0)
++
++/*
++ * Wait while MMU is busy. This is usually in the order of a few nanosecs
++ * if at all, but let's avoid deadlocking the system if the hardware
++ * decides to go south.
++ */
++#define SMC_WAIT_MMU_BUSY(lp) do { \
++ if (unlikely(SMC_GET_MMU_CMD(lp) & MC_BUSY)) { \
++ unsigned long timeout = jiffies + 2; \
++ while (SMC_GET_MMU_CMD(lp) & MC_BUSY) { \
++ if (time_after(jiffies, timeout)) { \
++ printk("%s: timeout %s line %d\n", \
++ dev->name, __FILE__, __LINE__); \
++ break; \
++ } \
++ cpu_relax(); \
++ } \
++ } \
++} while (0)
++
++/*
++ * Timer based operation on Atari
++ */
++static irqreturn_t smc_interrupt(int irq, void *dev_id);
++
++static int use_poll = 0;
++module_param(use_poll, int, 0);
++MODULE_PARM_DESC(use_poll, "Use scheduling timer to poll driver");
++
++/* This is used by cleanup, to prevent the module from being unloaded while
++ * intrpt_routine is still in the task queue
++ */
++static wait_queue_head_t WaitQ;
++
++static struct delayed_work tqueue;
++
++static struct net_device *poll_dev = NULL;
++
++static void atari_ethernat_int(struct work_struct *work)
++{
++ struct net_device *dev = poll_dev;
++
++ if(!dev) {
++ /* If cleanup wants us to die */
++ if (waitqueue_active(&WaitQ))
++ wake_up(&WaitQ); /* Now cleanup_module can return */
++ else
++ /* Put ourselves back in the task queue */
++ schedule_delayed_work(&tqueue, 1);
++ return;
++ }
++
++ /* This actually does not appear to work during probe */
++ if (netif_running(dev)) {
++ smc_interrupt(dev->irq, dev);
++ }
++
++ /* If cleanup wants us to die */
++ if (waitqueue_active(&WaitQ))
++ wake_up(&WaitQ); /* Now cleanup_module can return */
++ else
++ /* Put ourselves back in the task queue */
++ schedule_delayed_work(&tqueue, 0); /* reduced delay from 1 */
++}
++
++static void atari_ethernat_start_poll(struct net_device *dev)
++{
++ poll_dev = dev;
++
++ init_waitqueue_head(&WaitQ);
++
++ /* MSch: need to insert dev into work struct?? */
++
++ INIT_DELAYED_WORK(&tqueue, atari_ethernat_int);
++ schedule_delayed_work(&tqueue, 1);
++}
++
++static void atari_ethernat_stop_poll(struct net_device *dev)
++{
++ if (dev && (dev == poll_dev)) {
++ sleep_on(&WaitQ);
++ }
++ poll_dev = NULL;
++}
++
++/*
++ * this does a soft reset on the device
++ */
++static void smc_reset(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ unsigned int ctl, cfg;
++ struct sk_buff *pending_skb;
++
++ DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++
++ /* Disable all interrupts, block TX tasklet */
++ spin_lock_irq(&lp->lock);
++ SMC_SELECT_BANK(lp, 2);
++ SMC_SET_INT_MASK(lp, 0);
++ pending_skb = lp->pending_tx_skb;
++ lp->pending_tx_skb = NULL;
++ spin_unlock_irq(&lp->lock);
++
++ /* free any pending tx skb */
++ if (pending_skb) {
++ dev_kfree_skb(pending_skb);
++ dev->stats.tx_errors++;
++ dev->stats.tx_aborted_errors++;
++ }
++
++ /*
++ * This resets the registers mostly to defaults, but doesn't
++ * affect EEPROM. That seems unnecessary
++ */
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RCR(lp, RCR_SOFTRST);
++
++ /*
++ * Setup the Configuration Register
++ * This is necessary because the CONFIG_REG is not affected
++ * by a soft reset
++ */
++ SMC_SELECT_BANK(lp, 1);
++
++ cfg = CONFIG_DEFAULT;
++
++ /*
++ * Setup for fast accesses if requested. If the card/system
++ * can't handle it then there will be no recovery except for
++ * a hard reset or power cycle
++ */
++ if (nowait)
++ cfg |= CONFIG_NO_WAIT;
++
++ /*
++ * Release from possible power-down state
++ * Configuration register is not affected by Soft Reset
++ */
++ cfg |= CONFIG_EPH_POWER_EN;
++
++ SMC_SET_CONFIG(lp, cfg);
++
++ /* this should pause enough for the chip to be happy */
++ /*
++ * elaborate? What does the chip _need_? --jgarzik
++ *
++ * This seems to be undocumented, but something the original
++ * driver(s) have always done. Suspect undocumented timing
++ * info/determined empirically. --rmk
++ */
++ udelay(1);
++
++ /* Disable transmit and receive functionality */
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RCR(lp, RCR_CLEAR);
++ SMC_SET_TCR(lp, TCR_CLEAR);
++
++ SMC_SELECT_BANK(lp, 1);
++ ctl = SMC_GET_CTL(lp) | CTL_LE_ENABLE;
++
++ /*
++ * Set the control register to automatically release successfully
++ * transmitted packets, to make the best use out of our limited
++ * memory
++ */
++ if(!THROTTLE_TX_PKTS)
++ ctl |= CTL_AUTO_RELEASE;
++ else
++ ctl &= ~CTL_AUTO_RELEASE;
++ SMC_SET_CTL(lp, ctl);
++
++ /* Reset the MMU */
++ SMC_SELECT_BANK(lp, 2);
++ SMC_SET_MMU_CMD(lp, MC_RESET);
++ SMC_WAIT_MMU_BUSY(lp);
++}
++
++/*
++ * Enable Interrupts, Receive, and Transmit
++ */
++static void smc_enable(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ int mask;
++
++ DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++
++ /* see the header file for options in TCR/RCR DEFAULT */
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_TCR(lp, lp->tcr_cur_mode);
++ SMC_SET_RCR(lp, lp->rcr_cur_mode);
++
++ SMC_SELECT_BANK(lp, 1);
++ SMC_SET_MAC_ADDR(lp, dev->dev_addr);
++
++ /* now, enable interrupts */
++ mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT;
++ if (lp->version >= (CHIP_91100 << 4))
++ mask |= IM_MDINT;
++ SMC_SELECT_BANK(lp, 2);
++ SMC_SET_INT_MASK(lp, mask);
++
++ /*
++ * From this point the register bank must _NOT_ be switched away
++ * to something else than bank 2 without proper locking against
++ * races with any tasklet or interrupt handlers until smc_shutdown()
++ * or smc_reset() is called.
++ */
++}
++
++/*
++ * this puts the device in an inactive state
++ */
++static void smc_shutdown(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ struct sk_buff *pending_skb;
++
++ DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
++
++ /* no more interrupts for me */
++ spin_lock_irq(&lp->lock);
++ SMC_SELECT_BANK(lp, 2);
++ SMC_SET_INT_MASK(lp, 0);
++ pending_skb = lp->pending_tx_skb;
++ lp->pending_tx_skb = NULL;
++ spin_unlock_irq(&lp->lock);
++ if (pending_skb)
++ dev_kfree_skb(pending_skb);
++
++ /* and tell the card to stay away from that nasty outside world */
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RCR(lp, RCR_CLEAR);
++ SMC_SET_TCR(lp, TCR_CLEAR);
++
++#ifdef POWER_DOWN
++ /* finally, shut the chip down */
++ SMC_SELECT_BANK(lp, 1);
++ SMC_SET_CONFIG(lp, SMC_GET_CONFIG(lp) & ~CONFIG_EPH_POWER_EN);
++#endif
++}
++
++/*
++ * This is the procedure to handle the receipt of a packet.
++ */
++static inline void smc_rcv(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ unsigned int packet_number, status, packet_len;
++
++ DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++
++ packet_number = SMC_GET_RXFIFO(lp);
++ if (unlikely(packet_number & RXFIFO_REMPTY)) {
++ PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name);
++ return;
++ }
++
++ /* read from start of packet */
++ SMC_SET_PTR(lp, PTR_READ | PTR_RCV | PTR_AUTOINC);
++
++ /* First two words are status and packet length */
++ SMC_GET_PKT_HDR(lp, status, packet_len);
++ packet_len &= 0x07ff; /* mask off top bits */
++ DBG(2, "%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n",
++ dev->name, packet_number, status,
++ packet_len, packet_len);
++
++ back:
++ if (unlikely(packet_len < 6 || status & RS_ERRORS)) {
++ if (status & RS_TOOLONG && packet_len <= (1514 + 4 + 6)) {
++ /* accept VLAN packets */
++ status &= ~RS_TOOLONG;
++ goto back;
++ }
++ if (packet_len < 6) {
++ /* bloody hardware */
++ printk(KERN_ERR "%s: fubar (rxlen %u status %x\n",
++ dev->name, packet_len, status);
++ status |= RS_TOOSHORT;
++ }
++ SMC_WAIT_MMU_BUSY(lp);
++ SMC_SET_MMU_CMD(lp, MC_RELEASE);
++ dev->stats.rx_errors++;
++ if (status & RS_ALGNERR)
++ dev->stats.rx_frame_errors++;
++ if (status & (RS_TOOSHORT | RS_TOOLONG))
++ dev->stats.rx_length_errors++;
++ if (status & RS_BADCRC)
++ dev->stats.rx_crc_errors++;
++ } else {
++ struct sk_buff *skb;
++ unsigned char *data;
++ unsigned int data_len;
++
++ /* set multicast stats */
++ if (status & RS_MULTICAST)
++ dev->stats.multicast++;
++
++ /*
++ * Actual payload is packet_len - 6 (or 5 if odd byte).
++ * We want skb_reserve(2) and the final ctrl word
++ * (2 bytes, possibly containing the payload odd byte).
++ * Furthermore, we add 2 bytes to allow rounding up to
++ * multiple of 4 bytes on 32 bit buses.
++ * Hence packet_len - 6 + 2 + 2 + 2.
++ */
++ skb = dev_alloc_skb(packet_len);
++ if (unlikely(skb == NULL)) {
++ printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
++ dev->name);
++ SMC_WAIT_MMU_BUSY(lp);
++ SMC_SET_MMU_CMD(lp, MC_RELEASE);
++ dev->stats.rx_dropped++;
++ return;
++ }
++
++ /* Align IP header to 32 bits */
++ skb_reserve(skb, 2);
++
++ /* BUG: the LAN91C111 rev A never sets this bit. Force it. */
++ if (lp->version == 0x90)
++ status |= RS_ODDFRAME;
++
++ /*
++ * If odd length: packet_len - 5,
++ * otherwise packet_len - 6.
++ * With the trailing ctrl byte it's packet_len - 4.
++ */
++ data_len = packet_len - ((status & RS_ODDFRAME) ? 5 : 6);
++ data = skb_put(skb, data_len);
++ SMC_PULL_DATA(lp, data, packet_len - 4);
++
++ SMC_WAIT_MMU_BUSY(lp);
++ SMC_SET_MMU_CMD(lp, MC_RELEASE);
++
++ PRINT_PKT(data, packet_len - 4);
++
++ dev->last_rx = jiffies;
++ skb->protocol = eth_type_trans(skb, dev);
++ netif_rx(skb);
++ dev->stats.rx_packets++;
++ dev->stats.rx_bytes += data_len;
++ }
++}
++
++#ifdef CONFIG_SMP
++/*
++ * On SMP we have the following problem:
++ *
++ * A = smc_hardware_send_pkt()
++ * B = smc_hard_start_xmit()
++ * C = smc_interrupt()
++ *
++ * A and B can never be executed simultaneously. However, at least on UP,
++ * it is possible (and even desirable) for C to interrupt execution of
++ * A or B in order to have better RX reliability and avoid overruns.
++ * C, just like A and B, must have exclusive access to the chip and
++ * each of them must lock against any other concurrent access.
++ * Unfortunately this is not possible to have C suspend execution of A or
++ * B taking place on another CPU. On UP this is no an issue since A and B
++ * are run from softirq context and C from hard IRQ context, and there is
++ * no other CPU where concurrent access can happen.
++ * If ever there is a way to force at least B and C to always be executed
++ * on the same CPU then we could use read/write locks to protect against
++ * any other concurrent access and C would always interrupt B. But life
++ * isn't that easy in a SMP world...
++ */
++#define smc_special_trylock(lock) \
++({ \
++ int __ret; \
++ local_irq_disable(); \
++ __ret = spin_trylock(lock); \
++ if (!__ret) \
++ local_irq_enable(); \
++ __ret; \
++})
++#define smc_special_lock(lock) spin_lock_irq(lock)
++#define smc_special_unlock(lock) spin_unlock_irq(lock)
++#else
++#define smc_special_trylock(lock) (1)
++#define smc_special_lock(lock) do { } while (0)
++#define smc_special_unlock(lock) do { } while (0)
++#endif
++
++
++/*
++ * MSch: EtherNAT is 32 bit, so the misaligned data buffer hack applies.
++ * This appears to hurt quite a lot ... need to fudge with the data pointer
++ * to compensate
++ */
++
++#define SMC_outw_be(v, a, r) writew_be(v, (a) + (r))
++
++#define SMC_PUSH_DATA_BE(lp, p, l) \
++ do { \
++ if (SMC_32BIT(lp)) { \
++ void *__ptr = (p); \
++ int __len = (l); \
++ void __iomem *__ioaddr = ioaddr; \
++ if (__len >= 2 && (unsigned long)__ptr & 2) { \
++ __len -= 2; \
++ SMC_outw_be(*(u16 *)__ptr, ioaddr, \
++ DATA_REG(lp)); \
++ __ptr += 2; \
++ } \
++ if (SMC_CAN_USE_DATACS && lp->datacs) \
++ __ioaddr = lp->datacs; \
++ SMC_outsl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
++ if (__len & 2) { \
++ __ptr += (__len & ~3); \
++ SMC_outw_be(*((u16 *)__ptr), ioaddr, \
++ DATA_REG(lp)); \
++ } \
++ } else if (SMC_16BIT(lp)) \
++ SMC_outsw(ioaddr, DATA_REG(lp), (u16 *) p, (l) >> 1); \
++ else if (SMC_8BIT(lp)) \
++ SMC_outsb(ioaddr, DATA_REG(lp), p, l); \
++ } while (0)
++
++
++
++
++/*
++ * This is called to actually send a packet to the chip.
++ */
++static void smc_hardware_send_pkt(unsigned long data)
++{
++ struct net_device *dev = (struct net_device *)data;
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ struct sk_buff *skb;
++ unsigned int packet_no, len;
++ unsigned char *buf;
++
++ DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++
++ if (!smc_special_trylock(&lp->lock)) {
++ netif_stop_queue(dev);
++ tasklet_schedule(&lp->tx_task);
++ return;
++ }
++
++ skb = lp->pending_tx_skb;
++ if (unlikely(!skb)) {
++ smc_special_unlock(&lp->lock);
++ return;
++ }
++ lp->pending_tx_skb = NULL;
++
++ packet_no = SMC_GET_AR(lp);
++ if (unlikely(packet_no & AR_FAILED)) {
++ printk("%s: Memory allocation failed.\n", dev->name);
++ dev->stats.tx_errors++;
++ dev->stats.tx_fifo_errors++;
++ smc_special_unlock(&lp->lock);
++ goto done;
++ }
++
++ /* point to the beginning of the packet */
++ SMC_SET_PN(lp, packet_no);
++ SMC_SET_PTR(lp, PTR_AUTOINC);
++
++ buf = skb->data;
++ len = skb->len;
++ DBG(2, "%s: TX PNR 0x%x LENGTH 0x%04x (%d) BUF 0x%p\n",
++ dev->name, packet_no, len, len, buf);
++ PRINT_PKT(buf, len);
++
++ /*
++ * Send the packet length (+6 for status words, length, and ctl.
++ * The card will pad to 64 bytes with zeroes if packet is too small.
++ */
++ SMC_PUT_PKT_HDR(lp, 0, len + 6);
++
++ /* send the actual data */
++ SMC_PUSH_DATA_BE(lp, buf, len & ~1);
++
++ /* Send final ctl word with the last byte if there is one */
++ SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));
++
++ /*
++ * If THROTTLE_TX_PKTS is set, we stop the queue here. This will
++ * have the effect of having at most one packet queued for TX
++ * in the chip's memory at all time.
++ *
++ * If THROTTLE_TX_PKTS is not set then the queue is stopped only
++ * when memory allocation (MC_ALLOC) does not succeed right away.
++ */
++ if (THROTTLE_TX_PKTS)
++ netif_stop_queue(dev);
++
++ /* queue the packet for TX */
++ SMC_SET_MMU_CMD(lp, MC_ENQUEUE);
++ smc_special_unlock(&lp->lock);
++
++ dev->trans_start = jiffies;
++ dev->stats.tx_packets++;
++ dev->stats.tx_bytes += len;
++
++ SMC_ENABLE_INT(lp, IM_TX_INT | IM_TX_EMPTY_INT);
++
++done: if (!THROTTLE_TX_PKTS)
++ netif_wake_queue(dev);
++
++ dev_kfree_skb(skb);
++}
++
++/*
++ * Since I am not sure if I will have enough room in the chip's ram
++ * to store the packet, I call this routine which either sends it
++ * now, or set the card to generates an interrupt when ready
++ * for the packet.
++ */
++static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ unsigned int numPages, poll_count, status;
++
++ DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++
++ BUG_ON(lp->pending_tx_skb != NULL);
++
++ /*
++ * The MMU wants the number of pages to be the number of 256 bytes
++ * 'pages', minus 1 (since a packet can't ever have 0 pages :))
++ *
++ * The 91C111 ignores the size bits, but earlier models don't.
++ *
++ * Pkt size for allocating is data length +6 (for additional status
++ * words, length and ctl)
++ *
++ * If odd size then last byte is included in ctl word.
++ */
++ numPages = ((skb->len & ~1) + (6 - 1)) >> 8;
++ if (unlikely(numPages > 7)) {
++ printk("%s: Far too big packet error.\n", dev->name);
++ dev->stats.tx_errors++;
++ dev->stats.tx_dropped++;
++ dev_kfree_skb(skb);
++ return 0;
++ }
++
++ smc_special_lock(&lp->lock);
++
++ /* now, try to allocate the memory */
++ SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages);
++
++ /*
++ * Poll the chip for a short amount of time in case the
++ * allocation succeeds quickly.
++ */
++ poll_count = MEMORY_WAIT_TIME;
++ do {
++ status = SMC_GET_INT(lp);
++ if (status & IM_ALLOC_INT) {
++ SMC_ACK_INT(lp, IM_ALLOC_INT);
++ break;
++ }
++ } while (--poll_count);
++
++ smc_special_unlock(&lp->lock);
++
++ lp->pending_tx_skb = skb;
++ if (!poll_count) {
++ /* oh well, wait until the chip finds memory later */
++ netif_stop_queue(dev);
++ DBG(2, "%s: TX memory allocation deferred.\n", dev->name);
++ SMC_ENABLE_INT(lp, IM_ALLOC_INT);
++ } else {
++ /*
++ * Allocation succeeded: push packet to the chip's own memory
++ * immediately.
++ */
++ smc_hardware_send_pkt((unsigned long)dev);
++ }
++
++ return 0;
++}
++
++/*
++ * This handles a TX interrupt, which is only called when:
++ * - a TX error occurred, or
++ * - CTL_AUTO_RELEASE is not set and TX of a packet completed.
++ */
++static void smc_tx(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ unsigned int saved_packet, packet_no, tx_status, pkt_len;
++
++ DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++
++ /* If the TX FIFO is empty then nothing to do */
++ packet_no = SMC_GET_TXFIFO(lp);
++ if (unlikely(packet_no & TXFIFO_TEMPTY)) {
++ PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name);
++ return;
++ }
++
++ /* select packet to read from */
++ saved_packet = SMC_GET_PN(lp);
++ SMC_SET_PN(lp, packet_no);
++
++ /* read the first word (status word) from this packet */
++ SMC_SET_PTR(lp, PTR_AUTOINC | PTR_READ);
++ SMC_GET_PKT_HDR(lp, tx_status, pkt_len);
++ DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n",
++ dev->name, tx_status, packet_no);
++
++ if (!(tx_status & ES_TX_SUC))
++ dev->stats.tx_errors++;
++
++ if (tx_status & ES_LOSTCARR)
++ dev->stats.tx_carrier_errors++;
++
++ if (tx_status & (ES_LATCOL | ES_16COL)) {
++ PRINTK("%s: %s occurred on last xmit\n", dev->name,
++ (tx_status & ES_LATCOL) ?
++ "late collision" : "too many collisions");
++ dev->stats.tx_window_errors++;
++ if (!(dev->stats.tx_window_errors & 63) && net_ratelimit()) {
++ printk(KERN_INFO "%s: unexpectedly large number of "
++ "bad collisions. Please check duplex "
++ "setting.\n", dev->name);
++ }
++ }
++
++ /* kill the packet */
++ SMC_WAIT_MMU_BUSY(lp);
++ SMC_SET_MMU_CMD(lp, MC_FREEPKT);
++
++ /* Don't restore Packet Number Reg until busy bit is cleared */
++ SMC_WAIT_MMU_BUSY(lp);
++ SMC_SET_PN(lp, saved_packet);
++
++ /* re-enable transmit */
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_TCR(lp, lp->tcr_cur_mode);
++ SMC_SELECT_BANK(lp, 2);
++}
++
++
++/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/
++
++static void smc_mii_out(struct net_device *dev, unsigned int val, int bits)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ unsigned int mii_reg, mask;
++
++ mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO);
++ mii_reg |= MII_MDOE;
++
++ for (mask = 1 << (bits - 1); mask; mask >>= 1) {
++ if (val & mask)
++ mii_reg |= MII_MDO;
++ else
++ mii_reg &= ~MII_MDO;
++
++ SMC_SET_MII(lp, mii_reg);
++ udelay(MII_DELAY);
++ SMC_SET_MII(lp, mii_reg | MII_MCLK);
++ udelay(MII_DELAY);
++ }
++}
++
++static unsigned int smc_mii_in(struct net_device *dev, int bits)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ unsigned int mii_reg, mask, val;
++
++ mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO);
++ SMC_SET_MII(lp, mii_reg);
++
++ for (mask = 1 << (bits - 1), val = 0; mask; mask >>= 1) {
++ if (SMC_GET_MII(lp) & MII_MDI)
++ val |= mask;
++
++ SMC_SET_MII(lp, mii_reg);
++ udelay(MII_DELAY);
++ SMC_SET_MII(lp, mii_reg | MII_MCLK);
++ udelay(MII_DELAY);
++ }
++
++ return val;
++}
++
++/*
++ * Reads a register from the MII Management serial interface
++ */
++static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ unsigned int phydata;
++
++ SMC_SELECT_BANK(lp, 3);
++
++ /* Idle - 32 ones */
++ smc_mii_out(dev, 0xffffffff, 32);
++
++ /* Start code (01) + read (10) + phyaddr + phyreg */
++ smc_mii_out(dev, 6 << 10 | phyaddr << 5 | phyreg, 14);
++
++ /* Turnaround (2bits) + phydata */
++ phydata = smc_mii_in(dev, 18);
++
++ /* Return to idle state */
++ SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
++
++ DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
++ __FUNCTION__, phyaddr, phyreg, phydata);
++
++ SMC_SELECT_BANK(lp, 2);
++ return phydata;
++}
++
++/*
++ * Writes a register to the MII Management serial interface
++ */
++static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
++ int phydata)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++
++ SMC_SELECT_BANK(lp, 3);
++
++ /* Idle - 32 ones */
++ smc_mii_out(dev, 0xffffffff, 32);
++
++ /* Start code (01) + write (01) + phyaddr + phyreg + turnaround + phydata */
++ smc_mii_out(dev, 5 << 28 | phyaddr << 23 | phyreg << 18 | 2 << 16 | phydata, 32);
++
++ /* Return to idle state */
++ SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
++
++ DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
++ __FUNCTION__, phyaddr, phyreg, phydata);
++
++ SMC_SELECT_BANK(lp, 2);
++}
++
++/*
++ * Finds and reports the PHY address
++ */
++static void smc_phy_detect(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ int phyaddr;
++
++ DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++
++ lp->phy_type = 0;
++
++ /*
++ * Scan all 32 PHY addresses if necessary, starting at
++ * PHY#1 to PHY#31, and then PHY#0 last.
++ */
++ for (phyaddr = 1; phyaddr < 33; ++phyaddr) {
++ unsigned int id1, id2;
++
++ /* Read the PHY identifiers */
++ id1 = smc_phy_read(dev, phyaddr & 31, MII_PHYSID1);
++ id2 = smc_phy_read(dev, phyaddr & 31, MII_PHYSID2);
++
++ DBG(3, "%s: phy_id1=0x%x, phy_id2=0x%x\n",
++ dev->name, id1, id2);
++
++ /* Make sure it is a valid identifier */
++ if (id1 != 0x0000 && id1 != 0xffff && id1 != 0x8000 &&
++ id2 != 0x0000 && id2 != 0xffff && id2 != 0x8000) {
++ /* Save the PHY's address */
++ lp->mii.phy_id = phyaddr & 31;
++ lp->phy_type = id1 << 16 | id2;
++ break;
++ }
++ }
++}
++
++/*
++ * Sets the PHY to a configuration as determined by the user
++ */
++static int smc_phy_fixed(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ int phyaddr = lp->mii.phy_id;
++ int bmcr, cfg1;
++
++ DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++
++ /* Enter Link Disable state */
++ cfg1 = smc_phy_read(dev, phyaddr, PHY_CFG1_REG);
++ cfg1 |= PHY_CFG1_LNKDIS;
++ smc_phy_write(dev, phyaddr, PHY_CFG1_REG, cfg1);
++
++ /*
++ * Set our fixed capabilities
++ * Disable auto-negotiation
++ */
++ bmcr = 0;
++
++ if (lp->ctl_rfduplx)
++ bmcr |= BMCR_FULLDPLX;
++
++ if (lp->ctl_rspeed == 100)
++ bmcr |= BMCR_SPEED100;
++
++ /* Write our capabilities to the phy control register */
++ smc_phy_write(dev, phyaddr, MII_BMCR, bmcr);
++
++ /* Re-Configure the Receive/Phy Control register */
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RPC(lp, lp->rpc_cur_mode);
++ SMC_SELECT_BANK(lp, 2);
++
++ return 1;
++}
++
++/*
++ * smc_phy_reset - reset the phy
++ * @dev: net device
++ * @phy: phy address
++ *
++ * Issue a software reset for the specified PHY and
++ * wait up to 100ms for the reset to complete. We should
++ * not access the PHY for 50ms after issuing the reset.
++ *
++ * The time to wait appears to be dependent on the PHY.
++ *
++ * Must be called with lp->lock locked.
++ */
++static int smc_phy_reset(struct net_device *dev, int phy)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ unsigned int bmcr;
++ int timeout;
++
++ smc_phy_write(dev, phy, MII_BMCR, BMCR_RESET);
++
++ for (timeout = 2; timeout; timeout--) {
++ spin_unlock_irq(&lp->lock);
++ msleep(50);
++ spin_lock_irq(&lp->lock);
++
++ bmcr = smc_phy_read(dev, phy, MII_BMCR);
++ if (!(bmcr & BMCR_RESET))
++ break;
++ }
++
++ return bmcr & BMCR_RESET;
++}
++
++/*
++ * smc_phy_powerdown - powerdown phy
++ * @dev: net device
++ *
++ * Power down the specified PHY
++ */
++static void smc_phy_powerdown(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ unsigned int bmcr;
++ int phy = lp->mii.phy_id;
++
++ if (lp->phy_type == 0)
++ return;
++
++ /* We need to ensure that no calls to smc_phy_configure are
++ pending.
++ */
++ cancel_work_sync(&lp->phy_configure);
++
++ bmcr = smc_phy_read(dev, phy, MII_BMCR);
++ smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN);
++}
++
++/*
++ * smc_phy_check_media - check the media status and adjust TCR
++ * @dev: net device
++ * @init: set true for initialisation
++ *
++ * Select duplex mode depending on negotiation state. This
++ * also updates our carrier state.
++ */
++static void smc_phy_check_media(struct net_device *dev, int init)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++
++ if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
++ /* duplex state has changed */
++ if (lp->mii.full_duplex) {
++ lp->tcr_cur_mode |= TCR_SWFDUP;
++ } else {
++ lp->tcr_cur_mode &= ~TCR_SWFDUP;
++ }
++
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_TCR(lp, lp->tcr_cur_mode);
++ }
++}
++
++/*
++ * Configures the specified PHY through the MII management interface
++ * using Autonegotiation.
++ * Calls smc_phy_fixed() if the user has requested a certain config.
++ * If RPC ANEG bit is set, the media selection is dependent purely on
++ * the selection by the MII (either in the MII BMCR reg or the result
++ * of autonegotiation.) If the RPC ANEG bit is cleared, the selection
++ * is controlled by the RPC SPEED and RPC DPLX bits.
++ */
++static void smc_phy_configure(struct work_struct *work)
++{
++ struct smc_local *lp =
++ container_of(work, struct smc_local, phy_configure);
++ struct net_device *dev = lp->dev;
++ void __iomem *ioaddr = lp->base;
++ int phyaddr = lp->mii.phy_id;
++ int my_phy_caps; /* My PHY capabilities */
++ int my_ad_caps; /* My Advertised capabilities */
++ int status;
++
++ DBG(3, "%s:smc_program_phy()\n", dev->name);
++
++ spin_lock_irq(&lp->lock);
++
++ /*
++ * We should not be called if phy_type is zero.
++ */
++ if (lp->phy_type == 0)
++ goto smc_phy_configure_exit;
++
++ if (smc_phy_reset(dev, phyaddr)) {
++ printk("%s: PHY reset timed out\n", dev->name);
++ goto smc_phy_configure_exit;
++ }
++
++ /*
++ * Enable PHY Interrupts (for register 18)
++ * Interrupts listed here are disabled
++ */
++ smc_phy_write(dev, phyaddr, PHY_MASK_REG,
++ PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD |
++ PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB |
++ PHY_INT_SPDDET | PHY_INT_DPLXDET);
++
++ /* Configure the Receive/Phy Control register */
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RPC(lp, lp->rpc_cur_mode);
++
++ /* If the user requested no auto neg, then go set his request */
++ if (lp->mii.force_media) {
++ smc_phy_fixed(dev);
++ goto smc_phy_configure_exit;
++ }
++
++ /* Copy our capabilities from MII_BMSR to MII_ADVERTISE */
++ my_phy_caps = smc_phy_read(dev, phyaddr, MII_BMSR);
++
++ if (!(my_phy_caps & BMSR_ANEGCAPABLE)) {
++ printk(KERN_INFO "Auto negotiation NOT supported\n");
++ smc_phy_fixed(dev);
++ goto smc_phy_configure_exit;
++ }
++
++ my_ad_caps = ADVERTISE_CSMA; /* I am CSMA capable */
++
++ if (my_phy_caps & BMSR_100BASE4)
++ my_ad_caps |= ADVERTISE_100BASE4;
++ if (my_phy_caps & BMSR_100FULL)
++ my_ad_caps |= ADVERTISE_100FULL;
++ if (my_phy_caps & BMSR_100HALF)
++ my_ad_caps |= ADVERTISE_100HALF;
++ if (my_phy_caps & BMSR_10FULL)
++ my_ad_caps |= ADVERTISE_10FULL;
++ if (my_phy_caps & BMSR_10HALF)
++ my_ad_caps |= ADVERTISE_10HALF;
++
++ /* Disable capabilities not selected by our user */
++ if (lp->ctl_rspeed != 100)
++ my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF);
++
++ if (!lp->ctl_rfduplx)
++ my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL);
++
++ /* Update our Auto-Neg Advertisement Register */
++ smc_phy_write(dev, phyaddr, MII_ADVERTISE, my_ad_caps);
++ lp->mii.advertising = my_ad_caps;
++
++ /*
++ * Read the register back. Without this, it appears that when
++ * auto-negotiation is restarted, sometimes it isn't ready and
++ * the link does not come up.
++ */
++ status = smc_phy_read(dev, phyaddr, MII_ADVERTISE);
++
++ DBG(2, "%s: phy caps=%x\n", dev->name, my_phy_caps);
++ DBG(2, "%s: phy advertised caps=%x\n", dev->name, my_ad_caps);
++
++ /* Restart auto-negotiation process in order to advertise my caps */
++ smc_phy_write(dev, phyaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
++
++ smc_phy_check_media(dev, 1);
++
++smc_phy_configure_exit:
++ SMC_SELECT_BANK(lp, 2);
++ spin_unlock_irq(&lp->lock);
++}
++
++/*
++ * smc_phy_interrupt
++ *
++ * Purpose: Handle interrupts relating to PHY register 18. This is
++ * called from the "hard" interrupt handler under our private spinlock.
++ */
++static void smc_phy_interrupt(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ int phyaddr = lp->mii.phy_id;
++ int phy18;
++
++ DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++
++ if (lp->phy_type == 0)
++ return;
++
++ for(;;) {
++ smc_phy_check_media(dev, 0);
++
++ /* Read PHY Register 18, Status Output */
++ phy18 = smc_phy_read(dev, phyaddr, PHY_INT_REG);
++ if ((phy18 & PHY_INT_INT) == 0)
++ break;
++ }
++}
++
++/*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/
++
++static void smc_10bt_check_media(struct net_device *dev, int init)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ unsigned int old_carrier, new_carrier;
++
++ old_carrier = netif_carrier_ok(dev) ? 1 : 0;
++
++ SMC_SELECT_BANK(lp, 0);
++ new_carrier = (SMC_GET_EPH_STATUS(lp) & ES_LINK_OK) ? 1 : 0;
++ SMC_SELECT_BANK(lp, 2);
++
++ if (init || (old_carrier != new_carrier)) {
++ if (!new_carrier) {
++ netif_carrier_off(dev);
++ } else {
++ netif_carrier_on(dev);
++ }
++ if (netif_msg_link(lp))
++ printk(KERN_INFO "%s: link %s\n", dev->name,
++ new_carrier ? "up" : "down");
++ }
++}
++
++static void smc_eph_interrupt(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ unsigned int ctl;
++
++ smc_10bt_check_media(dev, 0);
++
++ SMC_SELECT_BANK(lp, 1);
++ ctl = SMC_GET_CTL(lp);
++ SMC_SET_CTL(lp, ctl & ~CTL_LE_ENABLE);
++ SMC_SET_CTL(lp, ctl);
++ SMC_SELECT_BANK(lp, 2);
++}
++
++/*
++ * This is the main routine of the driver, to handle the device when
++ * it needs some attention.
++ */
++static irqreturn_t smc_interrupt(int irq, void *dev_id)
++{
++ struct net_device *dev = dev_id;
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ int status, mask, timeout, card_stats;
++ int saved_pointer;
++
++ DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
++
++ spin_lock(&lp->lock);
++
++ /* A preamble may be used when there is a potential race
++ * between the interruptible transmit functions and this
++ * ISR. */
++ SMC_INTERRUPT_PREAMBLE;
++
++ saved_pointer = SMC_GET_PTR(lp);
++ mask = SMC_GET_INT_MASK(lp);
++ SMC_SET_INT_MASK(lp, 0);
++
++ /* set a timeout value, so I don't stay here forever */
++ timeout = MAX_IRQ_LOOPS;
++
++ do {
++ status = SMC_GET_INT(lp);
++
++ DBG(3, "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
++ dev->name, status, mask,
++ ({ int meminfo; SMC_SELECT_BANK(lp, 0);
++ meminfo = SMC_GET_MIR(lp);
++ SMC_SELECT_BANK(lp, 2); meminfo; }),
++ SMC_GET_FIFO(lp));
++
++ status &= mask;
++ if (!status)
++ break;
++
++ if (status & IM_TX_INT) {
++ /* do this before RX as it will free memory quickly */
++ DBG(2, "%s: TX int\n", dev->name);
++ smc_tx(dev);
++ SMC_ACK_INT(lp, IM_TX_INT);
++ if (THROTTLE_TX_PKTS)
++ netif_wake_queue(dev);
++ } else if (status & IM_RCV_INT) {
++ DBG(2, "%s: RX irq\n", dev->name);
++ smc_rcv(dev);
++ } else if (status & IM_ALLOC_INT) {
++ DBG(1, "%s: Allocation irq\n", dev->name);
++ tasklet_hi_schedule(&lp->tx_task);
++ mask &= ~IM_ALLOC_INT;
++ } else if (status & IM_TX_EMPTY_INT) {
++ DBG(2, "%s: TX empty\n", dev->name);
++ mask &= ~IM_TX_EMPTY_INT;
++
++ /* update stats */
++ SMC_SELECT_BANK(lp, 0);
++ card_stats = SMC_GET_COUNTER(lp);
++ SMC_SELECT_BANK(lp, 2);
++
++ /* single collisions */
++ dev->stats.collisions += card_stats & 0xF;
++ card_stats >>= 4;
++
++ /* multiple collisions */
++ dev->stats.collisions += card_stats & 0xF;
++ } else if (status & IM_RX_OVRN_INT) {
++ DBG(1, "%s: RX overrun (EPH_ST 0x%04x)\n", dev->name,
++ ({ int eph_st; SMC_SELECT_BANK(lp, 0);
++ eph_st = SMC_GET_EPH_STATUS(lp);
++ SMC_SELECT_BANK(lp, 2); eph_st; }) );
++ SMC_ACK_INT(lp, IM_RX_OVRN_INT);
++ dev->stats.rx_errors++;
++ dev->stats.rx_fifo_errors++;
++ } else if (status & IM_EPH_INT) {
++ DBG(1, "%s: eph interrupt\n", dev->name);
++ smc_eph_interrupt(dev);
++ } else if (status & IM_MDINT) {
++ DBG(1, "%s: phy interrupt\n", dev->name);
++ SMC_ACK_INT(lp, IM_MDINT);
++ smc_phy_interrupt(dev);
++ } else if (status & IM_ERCV_INT) {
++ SMC_ACK_INT(lp, IM_ERCV_INT);
++ PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name);
++ }
++ } while (--timeout);
++
++ /* restore register states */
++ SMC_SET_PTR(lp, saved_pointer);
++ SMC_SET_INT_MASK(lp, mask);
++ spin_unlock(&lp->lock);
++
++#ifndef CONFIG_NET_POLL_CONTROLLER
++#if 0
++ if (timeout == MAX_IRQ_LOOPS)
++ PRINTK("%s: spurious interrupt (mask = 0x%02x)\n",
++ dev->name, mask);
++#endif
++#endif
++ DBG(3, "%s: Interrupt done (%d loops)\n",
++ dev->name, MAX_IRQ_LOOPS - timeout);
++
++ /*
++ * We return IRQ_HANDLED unconditionally here even if there was
++ * nothing to do. There is a possibility that a packet might
++ * get enqueued into the chip right after TX_EMPTY_INT is raised
++ * but just before the CPU acknowledges the IRQ.
++ * Better take an unneeded IRQ in some occasions than complexifying
++ * the code for all cases.
++ */
++ return IRQ_HANDLED;
++}
++
++#ifdef CONFIG_NET_POLL_CONTROLLER
++/*
++ * Polling receive - used by netconsole and other diagnostic tools
++ * to allow network i/o with interrupts disabled.
++ */
++static void smc_poll_controller(struct net_device *dev)
++{
++ disable_irq(dev->irq);
++ smc_interrupt(dev->irq, dev);
++ enable_irq(dev->irq);
++}
++#endif
++
++/* Our watchdog timed out. Called by the networking layer */
++static void smc_timeout(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ int status, mask, eph_st, meminfo, fifo;
++
++ DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++
++ spin_lock_irq(&lp->lock);
++ status = SMC_GET_INT(lp);
++ mask = SMC_GET_INT_MASK(lp);
++ fifo = SMC_GET_FIFO(lp);
++ SMC_SELECT_BANK(lp, 0);
++ eph_st = SMC_GET_EPH_STATUS(lp);
++ meminfo = SMC_GET_MIR(lp);
++ SMC_SELECT_BANK(lp, 2);
++ spin_unlock_irq(&lp->lock);
++ PRINTK( "%s: TX timeout (INT 0x%02x INTMASK 0x%02x "
++ "MEM 0x%04x FIFO 0x%04x EPH_ST 0x%04x)\n",
++ dev->name, status, mask, meminfo, fifo, eph_st );
++
++ smc_reset(dev);
++ smc_enable(dev);
++
++ /*
++ * Reconfiguring the PHY doesn't seem like a bad idea here, but
++ * smc_phy_configure() calls msleep() which calls schedule_timeout()
++ * which calls schedule(). Hence we use a work queue.
++ */
++ if (lp->phy_type != 0)
++ schedule_work(&lp->phy_configure);
++
++ /* We can accept TX packets again */
++ dev->trans_start = jiffies;
++ netif_wake_queue(dev);
++}
++
++/*
++ * This routine will, depending on the values passed to it,
++ * either make it accept multicast packets, go into
++ * promiscuous mode (for TCPDUMP and cousins) or accept
++ * a select set of multicast packets
++ */
++static void smc_set_multicast_list(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ void __iomem *ioaddr = lp->base;
++ unsigned char multicast_table[8];
++ int update_multicast = 0;
++
++ DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++
++ if (dev->flags & IFF_PROMISC) {
++ DBG(2, "%s: RCR_PRMS\n", dev->name);
++ lp->rcr_cur_mode |= RCR_PRMS;
++ }
++
++/* BUG? I never disable promiscuous mode if multicasting was turned on.
++ Now, I turn off promiscuous mode, but I don't do anything to multicasting
++ when promiscuous mode is turned on.
++*/
++
++ /*
++ * Here, I am setting this to accept all multicast packets.
++ * I don't need to zero the multicast table, because the flag is
++ * checked before the table is
++ */
++ else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) {
++ DBG(2, "%s: RCR_ALMUL\n", dev->name);
++ lp->rcr_cur_mode |= RCR_ALMUL;
++ }
++
++ /*
++ * This sets the internal hardware table to filter out unwanted
++ * multicast packets before they take up memory.
++ *
++ * The SMC chip uses a hash table where the high 6 bits of the CRC of
++ * address are the offset into the table. If that bit is 1, then the
++ * multicast packet is accepted. Otherwise, it's dropped silently.
++ *
++ * To use the 6 bits as an offset into the table, the high 3 bits are
++ * the number of the 8 bit register, while the low 3 bits are the bit
++ * within that register.
++ */
++ else if (dev->mc_count) {
++ int i;
++ struct dev_mc_list *cur_addr;
++
++ /* table for flipping the order of 3 bits */
++ static const unsigned char invert3[] = {0, 4, 2, 6, 1, 5, 3, 7};
++
++ /* start with a table of all zeros: reject all */
++ memset(multicast_table, 0, sizeof(multicast_table));
++
++ cur_addr = dev->mc_list;
++ for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) {
++ int position;
++
++ /* do we have a pointer here? */
++ if (!cur_addr)
++ break;
++ /* make sure this is a multicast address -
++ shouldn't this be a given if we have it here ? */
++ if (!(*cur_addr->dmi_addr & 1))
++ continue;
++
++ /* only use the low order bits */
++ position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f;
++
++ /* do some messy swapping to put the bit in the right spot */
++ multicast_table[invert3[position&7]] |=
++ (1<<invert3[(position>>3)&7]);
++ }
++
++ /* be sure I get rid of flags I might have set */
++ lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL);
++
++ /* now, the table can be loaded into the chipset */
++ update_multicast = 1;
++ } else {
++ DBG(2, "%s: ~(RCR_PRMS|RCR_ALMUL)\n", dev->name);
++ lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL);
++
++ /*
++ * since I'm disabling all multicast entirely, I need to
++ * clear the multicast list
++ */
++ memset(multicast_table, 0, sizeof(multicast_table));
++ update_multicast = 1;
++ }
++
++ spin_lock_irq(&lp->lock);
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RCR(lp, lp->rcr_cur_mode);
++ if (update_multicast) {
++ SMC_SELECT_BANK(lp, 3);
++ SMC_SET_MCAST(lp, multicast_table);
++ }
++ SMC_SELECT_BANK(lp, 2);
++ spin_unlock_irq(&lp->lock);
++}
++
++
++/*
++ * Open and Initialize the board
++ *
++ * Set up everything, reset the card, etc..
++ */
++static int
++smc_open(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++
++ DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++
++ /*
++ * Check that the address is valid. If its not, refuse
++ * to bring the device up. The user must specify an
++ * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
++ */
++ if (!is_valid_ether_addr(dev->dev_addr)) {
++ PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ /* Setup the default Register Modes */
++ lp->tcr_cur_mode = TCR_DEFAULT;
++ lp->rcr_cur_mode = RCR_DEFAULT;
++ lp->rpc_cur_mode = RPC_DEFAULT;
++
++ /*
++ * If we are not using a MII interface, we need to
++ * monitor our own carrier signal to detect faults.
++ */
++ if (lp->phy_type == 0)
++ lp->tcr_cur_mode |= TCR_MON_CSN;
++
++ /* reset the hardware */
++ smc_reset(dev);
++ smc_enable(dev);
++
++ /* Configure the PHY, initialize the link state */
++ if (lp->phy_type != 0)
++ smc_phy_configure(&lp->phy_configure);
++ else {
++ spin_lock_irq(&lp->lock);
++ smc_10bt_check_media(dev, 1);
++ spin_unlock_irq(&lp->lock);
++ }
++
++ netif_start_queue(dev);
++ return 0;
++}
++
++/*
++ * smc_close
++ *
++ * this makes the board clean up everything that it can
++ * and not talk to the outside world. Caused by
++ * an 'ifconfig ethX down'
++ */
++static int smc_close(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++
++ DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
++
++ netif_stop_queue(dev);
++ netif_carrier_off(dev);
++
++ /* clear everything */
++ smc_shutdown(dev);
++ tasklet_kill(&lp->tx_task);
++ smc_phy_powerdown(dev);
++ return 0;
++}
++
++/*
++ * Ethtool support
++ */
++static int
++smc_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ int ret;
++
++ cmd->maxtxpkt = 1;
++ cmd->maxrxpkt = 1;
++
++ if (lp->phy_type != 0) {
++ spin_lock_irq(&lp->lock);
++ ret = mii_ethtool_gset(&lp->mii, cmd);
++ spin_unlock_irq(&lp->lock);
++ } else {
++ cmd->supported = SUPPORTED_10baseT_Half |
++ SUPPORTED_10baseT_Full |
++ SUPPORTED_TP | SUPPORTED_AUI;
++
++ if (lp->ctl_rspeed == 10)
++ cmd->speed = SPEED_10;
++ else if (lp->ctl_rspeed == 100)
++ cmd->speed = SPEED_100;
++
++ cmd->autoneg = AUTONEG_DISABLE;
++ cmd->transceiver = XCVR_INTERNAL;
++ cmd->port = 0;
++ cmd->duplex = lp->tcr_cur_mode & TCR_SWFDUP ? DUPLEX_FULL : DUPLEX_HALF;
++
++ ret = 0;
++ }
++
++ return ret;
++}
++
++static int
++smc_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ int ret;
++
++ if (lp->phy_type != 0) {
++ spin_lock_irq(&lp->lock);
++ ret = mii_ethtool_sset(&lp->mii, cmd);
++ spin_unlock_irq(&lp->lock);
++ } else {
++ if (cmd->autoneg != AUTONEG_DISABLE ||
++ cmd->speed != SPEED_10 ||
++ (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) ||
++ (cmd->port != PORT_TP && cmd->port != PORT_AUI))
++ return -EINVAL;
++
++// lp->port = cmd->port;
++ lp->ctl_rfduplx = cmd->duplex == DUPLEX_FULL;
++
++// if (netif_running(dev))
++// smc_set_port(dev);
++
++ ret = 0;
++ }
++
++ return ret;
++}
++
++static void
++smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
++{
++ strncpy(info->driver, CARDNAME, sizeof(info->driver));
++ strncpy(info->version, version, sizeof(info->version));
++ strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info));
++}
++
++static int smc_ethtool_nwayreset(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ int ret = -EINVAL;
++
++ if (lp->phy_type != 0) {
++ spin_lock_irq(&lp->lock);
++ ret = mii_nway_restart(&lp->mii);
++ spin_unlock_irq(&lp->lock);
++ }
++
++ return ret;
++}
++
++static u32 smc_ethtool_getmsglevel(struct net_device *dev)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ return lp->msg_enable;
++}
++
++static void smc_ethtool_setmsglevel(struct net_device *dev, u32 level)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ lp->msg_enable = level;
++}
++
++static const struct ethtool_ops smc_ethtool_ops = {
++ .get_settings = smc_ethtool_getsettings,
++ .set_settings = smc_ethtool_setsettings,
++ .get_drvinfo = smc_ethtool_getdrvinfo,
++
++ .get_msglevel = smc_ethtool_getmsglevel,
++ .set_msglevel = smc_ethtool_setmsglevel,
++ .nway_reset = smc_ethtool_nwayreset,
++ .get_link = ethtool_op_get_link,
++// .get_eeprom = smc_ethtool_geteeprom,
++// .set_eeprom = smc_ethtool_seteeprom,
++};
++
++/*
++ * smc_findirq
++ *
++ * This routine has a simple purpose -- make the SMC chip generate an
++ * interrupt, so an auto-detect routine can detect it, and find the IRQ,
++ */
++/*
++ * does this still work?
++ *
++ * I just deleted auto_irq.c, since it was never built...
++ * --jgarzik
++ */
++static int __init smc_findirq(struct smc_local *lp)
++{
++ void __iomem *ioaddr = lp->base;
++ int timeout = 20;
++ unsigned long cookie;
++
++ DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
++
++ cookie = probe_irq_on();
++
++ /*
++ * What I try to do here is trigger an ALLOC_INT. This is done
++ * by allocating a small chunk of memory, which will give an interrupt
++ * when done.
++ */
++ /* enable ALLOCation interrupts ONLY */
++ SMC_SELECT_BANK(lp, 2);
++ SMC_SET_INT_MASK(lp, IM_ALLOC_INT);
++
++ /*
++ * Allocate 512 bytes of memory. Note that the chip was just
++ * reset so all the memory is available
++ */
++ SMC_SET_MMU_CMD(lp, MC_ALLOC | 1);
++
++ /*
++ * Wait until positive that the interrupt has been generated
++ */
++ do {
++ int int_status;
++ udelay(10);
++ int_status = SMC_GET_INT(lp);
++ if (int_status & IM_ALLOC_INT)
++ break; /* got the interrupt */
++ } while (--timeout);
++
++ /*
++ * there is really nothing that I can do here if timeout fails,
++ * as autoirq_report will return a 0 anyway, which is what I
++ * want in this case. Plus, the clean up is needed in both
++ * cases.
++ */
++
++ /* and disable all interrupts again */
++ SMC_SET_INT_MASK(lp, 0);
++
++ /* and return what I found */
++ return probe_irq_off(cookie);
++}
++
++/*
++ * Function: smc_probe(unsigned long ioaddr)
++ *
++ * Purpose:
++ * Tests to see if a given ioaddr points to an SMC91x chip.
++ * Returns a 0 on success
++ *
++ * Algorithm:
++ * (1) see if the high byte of BANK_SELECT is 0x33
++ * (2) compare the ioaddr with the base register's address
++ * (3) see if I recognize the chip ID in the appropriate register
++ *
++ * Here I do typical initialization tasks.
++ *
++ * o Initialize the structure if needed
++ * o print out my vanity message if not done so already
++ * o print out what type of hardware is detected
++ * o print out the ethernet address
++ * o find the IRQ
++ * o set up my private data
++ * o configure the dev structure with my subroutines
++ * o actually GRAB the irq.
++ * o GRAB the region
++ */
++static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
++ unsigned long irq_flags)
++{
++ struct smc_local *lp = netdev_priv(dev);
++ static int version_printed = 0;
++ int retval;
++ unsigned int val, revision_register;
++ const char *version_string;
++ DECLARE_MAC_BUF(mac);
++
++ DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
++
++ if (!hwreg_present( ioaddr + BANK_SELECT )) {
++ retval = -ENODEV;
++ goto err_out;
++ }
++
++ /* First, see if the high byte is 0x33 */
++ val = SMC_CURRENT_BANK(lp);
++ DBG(2, "%s: bank signature probe returned 0x%04x\n", CARDNAME, val);
++ if ((val & 0xFF00) != 0x3300) {
++ if ((val & 0xFF) == 0x33) {
++ printk(KERN_WARNING
++ "%s: Detected possible byte-swapped interface"
++ " at IOADDR %p\n", CARDNAME, ioaddr);
++ }
++ retval = -ENODEV;
++ goto err_out;
++ }
++
++ /*
++ * The above MIGHT indicate a device, but I need to write to
++ * further test this.
++ */
++ SMC_SELECT_BANK(lp, 0);
++ val = SMC_CURRENT_BANK(lp);
++ if ((val & 0xFF00) != 0x3300) {
++ retval = -ENODEV;
++ goto err_out;
++ }
++
++ /*
++ * well, we've already written once, so hopefully another
++ * time won't hurt. This time, I need to switch the bank
++ * register to bank 1, so I can access the base address
++ * register
++ */
++ SMC_SELECT_BANK(lp, 1);
++ val = SMC_GET_BASE(lp);
++ val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
++ if (((unsigned int)ioaddr & (0x3e0 << SMC_IO_SHIFT)) != val) {
++ printk("%s: IOADDR %p doesn't match configuration (%x).\n",
++ CARDNAME, ioaddr, val);
++ }
++
++ /*
++ * check if the revision register is something that I
++ * recognize. These might need to be added to later,
++ * as future revisions could be added.
++ */
++ SMC_SELECT_BANK(lp, 3);
++ revision_register = SMC_GET_REV(lp);
++ DBG(2, "%s: revision = 0x%04x\n", CARDNAME, revision_register);
++ version_string = chip_ids[ (revision_register >> 4) & 0xF];
++ if (!version_string || (revision_register & 0xff00) != 0x3300) {
++ /* I don't recognize this chip, so... */
++ printk("%s: IO %p: Unrecognized revision register 0x%04x"
++ ", Contact author.\n", CARDNAME,
++ ioaddr, revision_register);
++
++ retval = -ENODEV;
++ goto err_out;
++ }
++
++ /* At this point I'll assume that the chip is an SMC91x. */
++ if (version_printed++ == 0)
++ printk("%s", version);
++
++ /* fill in some of the fields */
++ dev->base_addr = (unsigned long)ioaddr;
++ lp->base = ioaddr;
++ lp->version = revision_register & 0xff;
++ spin_lock_init(&lp->lock);
++
++ /* Get the MAC address */
++ SMC_SELECT_BANK(lp, 1);
++ SMC_GET_MAC_ADDR(lp, dev->dev_addr);
++
++ /* now, reset the chip, and put it into a known state */
++ smc_reset(dev);
++
++ /*
++ * If dev->irq is 0, then the device has to be banged on to see
++ * what the IRQ is.
++ *
++ * This banging doesn't always detect the IRQ, for unknown reasons.
++ * a workaround is to reset the chip and try again.
++ *
++ * Interestingly, the DOS packet driver *SETS* the IRQ on the card to
++ * be what is requested on the command line. I don't do that, mostly
++ * because the card that I have uses a non-standard method of accessing
++ * the IRQs, and because this _should_ work in most configurations.
++ *
++ * Specifying an IRQ is done with the assumption that the user knows
++ * what (s)he is doing. No checking is done!!!!
++ */
++ if (dev->irq < 1) {
++ int trials;
++
++ trials = 3;
++ while (trials--) {
++ dev->irq = smc_findirq(lp);
++ if (dev->irq)
++ break;
++ /* kick the card and try again */
++ smc_reset(dev);
++ }
++ }
++ if (dev->irq == 0) {
++ printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
++ dev->name);
++ retval = -ENODEV;
++ goto err_out;
++ }
++ dev->irq = irq_canonicalize(dev->irq);
++
++ /* Fill in the fields of the device structure with ethernet values. */
++ ether_setup(dev);
++
++ dev->open = smc_open;
++ dev->stop = smc_close;
++ dev->hard_start_xmit = smc_hard_start_xmit;
++ dev->tx_timeout = smc_timeout;
++ dev->watchdog_timeo = msecs_to_jiffies(watchdog);
++ dev->set_multicast_list = smc_set_multicast_list;
++ dev->ethtool_ops = &smc_ethtool_ops;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ dev->poll_controller = smc_poll_controller;
++#endif
++
++ tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev);
++ INIT_WORK(&lp->phy_configure, smc_phy_configure);
++ lp->dev = dev;
++ lp->mii.phy_id_mask = 0x1f;
++ lp->mii.reg_num_mask = 0x1f;
++ lp->mii.force_media = 0;
++ lp->mii.full_duplex = 0;
++ lp->mii.dev = dev;
++ lp->mii.mdio_read = smc_phy_read;
++ lp->mii.mdio_write = smc_phy_write;
++
++ /*
++ * Locate the phy, if any.
++ */
++ if (lp->version >= (CHIP_91100 << 4))
++ smc_phy_detect(dev);
++
++ /* then shut everything down to save power */
++ smc_shutdown(dev);
++ smc_phy_powerdown(dev);
++
++ /* Set default parameters */
++ lp->msg_enable = NETIF_MSG_LINK;
++ lp->ctl_rfduplx = 0;
++ lp->ctl_rspeed = 10;
++
++ if (lp->version >= (CHIP_91100 << 4)) {
++ lp->ctl_rfduplx = 1;
++ lp->ctl_rspeed = 100;
++ }
++
++ /* Grab the IRQ */
++ retval = request_irq(dev->irq, &smc_interrupt, irq_flags, dev->name, dev);
++ if (retval) {
++ use_poll = 1;
++ //goto err_out;
++ }
++
++#ifdef SMC_USE_PXA_DMA
++ {
++ int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
++ smc_pxa_dma_irq, NULL);
++ if (dma >= 0)
++ dev->dma = dma;
++ }
++#endif
++
++ retval = register_netdev(dev);
++ if (retval == 0) {
++ /* now, print out the card info, in a short format.. */
++ printk("%s: %s (rev %d) at %p IRQ %d",
++ dev->name, version_string, revision_register & 0x0f,
++ lp->base, dev->irq);
++
++ if (dev->dma != (unsigned char)-1)
++ printk(" DMA %d", dev->dma);
++
++ printk("%s%s\n", nowait ? " [nowait]" : "",
++ THROTTLE_TX_PKTS ? " [throttle_tx]" : "");
++
++ if (!is_valid_ether_addr(dev->dev_addr)) {
++ printk("%s: Invalid ethernet MAC address. Please "
++ "set proper address using ifconfig\n", dev->name);
++ random_ether_addr(dev->dev_addr);
++ printk("%s: Ethernet addr (random): %s\n",
++ dev->name, print_mac(mac, dev->dev_addr));
++ } else {
++ /* Print the Ethernet address */
++ printk("%s: Ethernet addr: %s\n",
++ dev->name, print_mac(mac, dev->dev_addr));
++ }
++
++ if (lp->phy_type == 0) {
++ PRINTK("%s: No PHY found\n", dev->name);
++ } else if ((lp->phy_type & 0xfffffff0) == 0x0016f840) {
++ PRINTK("%s: PHY LAN83C183 (LAN91C111 Internal)\n", dev->name);
++ } else if ((lp->phy_type & 0xfffffff0) == 0x02821c50) {
++ PRINTK("%s: PHY LAN83C180\n", dev->name);
++ }
++
++ if (SMC_32BIT(lp)) {
++ printk("%s: using 32 bit access\n", dev->name);
++ } else if (SMC_16BIT(lp)) {
++ printk("%s: using 16 bit access\n", dev->name);
++ } else {
++ printk("%s: using 8 bit access\n", dev->name);
++ }
++
++ }
++
++err_out:
++#ifdef SMC_USE_PXA_DMA
++ if (retval && dev->dma != (unsigned char)-1)
++ pxa_free_dma(dev->dma);
++#endif
++ return retval;
++}
++
++static int smc_enable_device(struct platform_device *pdev)
++{
++ struct net_device *ndev = platform_get_drvdata(pdev);
++ struct smc_local *lp = netdev_priv(ndev);
++ unsigned long flags;
++ unsigned char ecor, ecsr;
++ void __iomem *addr;
++ struct resource * res;
++
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
++ if (!res) {
++ printk("smc_enable_device: smc91x-attrib resource not found !\n");
++ return 0;
++ }
++
++ printk("smc_enable_device: smc91x-attrib resource found, start=%x !\n", res->start);
++
++ /*
++ * Map the attribute space. This is overkill, but clean.
++ */
++ addr = ioremap(res->start, ATTRIB_SIZE);
++ if (!addr) {
++ return -ENOMEM;
++ }
++
++ printk("smc_enable_device :smc91x-attrib resource remapped, start=%p !\n", addr);
++
++ /*
++ * Reset the device. We must disable IRQs around this
++ * since a reset causes the IRQ line become active.
++ */
++ local_irq_save(flags);
++ ecor = readb(addr + (ECOR << SMC_IO_SHIFT)) & ~ECOR_RESET;
++ writeb(ecor | ECOR_RESET, addr + (ECOR << SMC_IO_SHIFT));
++ readb(addr + (ECOR << SMC_IO_SHIFT));
++
++ /*
++ * Wait 100us for the chip to reset.
++ */
++ udelay(100);
++
++ /*
++ * The device will ignore all writes to the enable bit while
++ * reset is asserted, even if the reset bit is cleared in the
++ * same write. Must clear reset first, then enable the device.
++ */
++ writeb(ecor, addr + (ECOR << SMC_IO_SHIFT));
++ writeb(ecor | ECOR_ENABLE, addr + (ECOR << SMC_IO_SHIFT));
++
++ /*
++ * Set the appropriate byte/word mode.
++ */
++ ecsr = readb(addr + (ECSR << SMC_IO_SHIFT)) & ~ECSR_IOIS8;
++ if (!SMC_16BIT(lp))
++ ecsr |= ECSR_IOIS8;
++ writeb(ecsr, addr + (ECSR << SMC_IO_SHIFT));
++ local_irq_restore(flags);
++
++ iounmap(addr);
++
++ /*
++ * Wait for the chip to wake up. We could poll the control
++ * register in the main register space, but that isn't mapped
++ * yet. We know this is going to take 750us.
++ */
++ msleep(1);
++
++ return 0;
++}
++
++static int smc_request_attrib(struct platform_device *pdev)
++{
++ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
++
++ if (!res)
++ return 0;
++
++ if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME)) {
++ return -EBUSY;
++ }
++
++ return 0;
++}
++
++static void smc_release_attrib(struct platform_device *pdev)
++{
++ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
++
++ if (res)
++ release_mem_region(res->start, ATTRIB_SIZE);
++}
++
++static inline void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev)
++{
++ if (SMC_CAN_USE_DATACS) {
++ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
++ struct smc_local *lp = netdev_priv(ndev);
++
++ if (!res)
++ return;
++
++ if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) {
++ printk(KERN_INFO "%s: failed to request datacs memory region.\n", CARDNAME);
++ return;
++ }
++
++ lp->datacs = ioremap(res->start, SMC_DATA_EXTENT);
++ }
++}
++
++static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev)
++{
++ if (SMC_CAN_USE_DATACS) {
++ struct smc_local *lp = netdev_priv(ndev);
++ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
++
++ if (lp->datacs)
++ iounmap(lp->datacs);
++
++ lp->datacs = NULL;
++
++ if (res)
++ release_mem_region(res->start, SMC_DATA_EXTENT);
++ }
++}
++
++/*
++ * Resources defined and added to platform data in arch/m68k/atari/config.c
++ * These are left here for reference only!
++ */
++
++struct resource ethernat_attr = {
++ .start = 0x80000000,
++ .end = 0x800000FF,
++ .name = "smc91x-attrib",
++ .flags = IORESOURCE_MEM
++};
++
++struct resource ethernat_datacs = {
++ .start = 0,
++ .end = 0,
++ .name = "smc91x-data32",
++ .flags = IORESOURCE_MEM
++};
++
++/*
++ * smc_init(void)
++ * Input parameters:
++ * dev->base_addr == 0, try to find all possible locations
++ * dev->base_addr > 0x1ff, this is the address to check
++ * dev->base_addr == <anything else>, return failure code
++ *
++ * Output:
++ * 0 --> there is a device
++ * anything else, error
++ */
++
++static int __init atari_ethernat_pdev_probe(struct platform_device *pdev)
++{
++ struct smc91x_platdata *pd = pdev->dev.platform_data;
++ struct smc_local *lp;
++ struct net_device *ndev;
++ struct resource *res, *ires;
++ unsigned int __iomem *addr;
++ int ret;
++
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
++ if (!res)
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ printk("smc91x-regs resource not found!\n");
++ ret = -ENODEV;
++ goto out;
++ }
++
++ printk("smc91x-regs resource found, start=%x !\n", res->start);
++
++ if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
++ printk("could not request smc91x-regs resource at %ul!\n", res->start);
++ ret = -EBUSY;
++ goto out;
++ }
++
++ ndev = alloc_etherdev(sizeof(struct smc_local));
++ if (!ndev) {
++ printk("%s: could not allocate device.\n", CARDNAME);
++ ret = -ENOMEM;
++ goto out_release_io;
++ }
++ SET_NETDEV_DEV(ndev, &pdev->dev);
++
++ /* get configuration from platform data, only allow use of
++ * bus width if both SMC_CAN_USE_xxx and SMC91X_USE_xxx are set.
++ */
++
++ lp = netdev_priv(ndev);
++ lp->cfg.irq_flags = SMC_IRQ_FLAGS;
++
++#ifdef SMC_DYNAMIC_BUS_CONFIG
++ if (pd)
++ memcpy(&lp->cfg, pd, sizeof(lp->cfg));
++ else {
++ lp->cfg.flags = SMC91X_USE_8BIT;
++ lp->cfg.flags |= SMC91X_USE_16BIT;
++ lp->cfg.flags |= SMC91X_USE_32BIT;
++ }
++
++ lp->cfg.flags &= ~(SMC_CAN_USE_8BIT ? 0 : SMC91X_USE_8BIT);
++ lp->cfg.flags &= ~(SMC_CAN_USE_16BIT ? 0 : SMC91X_USE_16BIT);
++ lp->cfg.flags &= ~(SMC_CAN_USE_32BIT ? 0 : SMC91X_USE_32BIT);
++#endif
++
++ ndev->dma = (unsigned char)-1;
++
++ ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ if (!ires) {
++ printk("atari_91C111: IRQ resource not found!\n");
++ ret = -ENODEV;
++ goto out_free_netdev;
++ }
++
++ ndev->irq = ires->start;
++ printk("atari_91C111: IRQ resource specified irq=%d\n", ndev->irq);
++
++ /*
++ * 080720 MSch: testing timer based interrupts - need to set valid
++ * interrupt here or request_irq bails out.
++ * polling (use_poll == 1) not tested so far
++ * Ultimately, this needs to be set in the platform device
++ * data, or be overridden by module arguments
++ * The actual level6 interrupt is hardwired to vector
++ * 0xc4 according to the MiNT driver source. Interrupts
++ * are enabled for the device by setting bit 1 at base+0x20
++ * or base+0x23!
++ */
++ ndev->irq = IRQ_MFP_TIMD;
++ ires->start = IRQ_MFP_TIMD;
++ printk("atari_91C111: IRQ forced to irq=%d\n", ndev->irq);
++
++ if (SMC_IRQ_FLAGS == -1)
++ lp->cfg.irq_flags = ires->flags & IRQF_TRIGGER_MASK;
++
++ if (ndev->irq < 0) {
++ printk("atari_91C111: cannot determine interrupt! Using timer D poll...\n");
++ ndev->irq = IRQ_MFP_TIMD;
++ /* timer actually set up later */
++ }
++
++ if (ndev->irq == IRQ_MFP_TIMD) {
++ printk("atari_91C111: Using timer D interrupt - do share!\n");
++ lp->cfg.irq_flags = IRQF_SHARED;
++ }
++
++ ret = smc_request_attrib(pdev);
++ if (ret) {
++ printk("atari_91C111: attrib resource not found!\n");
++ goto out_free_netdev;
++ }
++#if defined(CONFIG_SA1100_ASSABET)
++ NCR_0 |= NCR_ENET_OSC_EN;
++#endif
++ platform_set_drvdata(pdev, ndev);
++ ret = smc_enable_device(pdev);
++ if (ret) {
++ printk("atari_91C111: failed to enable card!\n");
++ goto out_release_attrib;
++ }
++
++ addr = ioremap(res->start, SMC_IO_EXTENT);
++ if (!addr) {
++ ret = -ENOMEM;
++ goto out_release_attrib;
++ }
++
++#ifdef SMC_USE_PXA_DMA
++ {
++ struct smc_local *lp = netdev_priv(ndev);
++ lp->device = &pdev->dev;
++ lp->physaddr = res->start;
++ }
++#endif
++
++ printk("smc91x-regs resource remapped, start=%p!\n", addr);
++
++ /*
++ * about to probe for device; need to enable net IRQ here!
++ * EtherNAT has interrupt enable register at 0x20 or 0x23
++ * probe for base address + 0x23 or 0x20
++ */
++
++ ret = smc_probe(ndev, addr, lp->cfg.irq_flags);
++ if (ret != 0)
++ goto out_iounmap;
++
++ printk("smc91x probe done, irq %d!\n", ndev->irq);
++ ndev->irq = IRQ_MFP_TIMD;
++
++ if (ndev->irq < 0) {
++ if (use_poll)
++ atari_ethernat_start_poll(ndev);
++ } else if (ndev->irq == IRQ_MFP_TIMD) {
++ /* maybe instead use MFP timer C ?? */
++ /* init timer if not already running */
++ /* set Timer D data Register */
++ mfp.tim_dt_d = 123; /* 200 Hz */
++ /* start timer D, div = 1:100 */
++ mfp.tim_ct_cd = (mfp.tim_ct_cd & 0xf0) | 0x6;
++ }
++
++ smc_request_datacs(pdev, ndev);
++
++ return 0;
++
++ out_iounmap:
++ platform_set_drvdata(pdev, NULL);
++ iounmap(addr);
++ out_release_attrib:
++ smc_release_attrib(pdev);
++ out_free_netdev:
++ free_netdev(ndev);
++ out_release_io:
++ release_mem_region(res->start, SMC_IO_EXTENT);
++ out:
++ printk("%s: not found (%d).\n", CARDNAME, ret);
++
++ return ret;
++}
++
++static int smc_drv_remove(struct platform_device *pdev)
++{
++ struct net_device *ndev = platform_get_drvdata(pdev);
++ struct smc_local *lp = netdev_priv(ndev);
++ struct resource *res;
++
++ platform_set_drvdata(pdev, NULL);
++
++ if (use_poll)
++ atari_ethernat_stop_poll(ndev);
++
++ unregister_netdev(ndev);
++
++ free_irq(ndev->irq, ndev);
++
++#ifdef SMC_USE_PXA_DMA
++ if (ndev->dma != (unsigned char)-1)
++ pxa_free_dma(ndev->dma);
++#endif
++ iounmap(lp->base);
++
++ smc_release_datacs(pdev,ndev);
++ smc_release_attrib(pdev);
++
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
++ if (!res)
++ platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(res->start, SMC_IO_EXTENT);
++
++ free_netdev(ndev);
++
++ return 0;
++}
++
++static int smc_drv_suspend(struct platform_device *dev, pm_message_t state)
++{
++ struct net_device *ndev = platform_get_drvdata(dev);
++
++ if (ndev) {
++ if (netif_running(ndev)) {
++ netif_device_detach(ndev);
++ smc_shutdown(ndev);
++ smc_phy_powerdown(ndev);
++ }
++ }
++ return 0;
++}
++
++static int smc_drv_resume(struct platform_device *dev)
++{
++ struct net_device *ndev = platform_get_drvdata(dev);
++
++ if (ndev) {
++ struct smc_local *lp = netdev_priv(ndev);
++ smc_enable_device(dev);
++ if (netif_running(ndev)) {
++ smc_reset(ndev);
++ smc_enable(ndev);
++ if (lp->phy_type != 0)
++ smc_phy_configure(&lp->phy_configure);
++ netif_device_attach(ndev);
++ }
++ }
++ return 0;
++}
++
++static struct platform_driver smc_driver = {
++ .probe = atari_ethernat_pdev_probe,
++ .remove = smc_drv_remove,
++ .suspend = smc_drv_suspend,
++ .resume = smc_drv_resume,
++ .driver = {
++ .name = CARDNAME,
++ },
++};
++
++static int __init smc_init(void)
++{
++ if (!MACH_IS_ATARI)
++ return -ENODEV;
++
++#ifdef MODULE
++#ifdef CONFIG_ISA
++ if (io == -1)
++ printk(KERN_WARNING
++ "%s: You shouldn't use auto-probing with insmod!\n",
++ CARDNAME);
++#endif
++#endif
++
++ return platform_driver_register(&smc_driver);
++}
++
++static void __exit smc_cleanup(void)
++{
++ platform_driver_unregister(&smc_driver);
++}
++
++module_init(smc_init);
++module_exit(smc_cleanup);
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernec-fixes.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernec-fixes.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,65 @@
+From: Michael Schmitz <schmitz at debian.org>
+
+Use wrapper around ei_interrupt to prevent delivery of (timer!) interrupts
+before card is opened.
+
+Limit IO addresses to 0x300 (this is hardwired on the bus adapter anyway, and
+the card needs to be programmed to use that IO in some way before the adapter
+can work).
+
+Preset io=0x300 for module use.
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+
+---
+ drivers/net/atari_ethernec.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/atari_ethernec.c
++++ b/drivers/net/atari_ethernec.c
+@@ -124,7 +124,7 @@ static const char version2[] =
+ /* A zero-terminated list of I/O addresses to be probed at boot. */
+ #ifndef MODULE
+ static unsigned int netcard_portlist[] __initdata = {
+- 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
++ 0x300, 0
+ };
+ #endif
+
+@@ -227,6 +227,14 @@ static struct delayed_work tqueue;
+
+ static struct net_device *poll_dev = NULL;
+
++irqreturn_t atari_ei_interrupt(int irq, void *dev_id)
++{
++ struct net_device *dev = dev_id;
++ if (netif_running(dev))
++ return ei_interrupt(dev->irq, dev);
++ return IRQ_NONE;
++}
++
+ static void atari_ethernec_int(struct work_struct *work)
+ {
+ struct net_device *dev = poll_dev;
+@@ -619,7 +627,7 @@ static int __init ne_probe1(struct net_d
+ mfp.tim_ct_cd = (mfp.tim_ct_cd & 0xf0) | 0x6;
+ }
+ /* Must make this shared in case other timer ints are needed */
+- ret = request_irq(dev->irq, ei_interrupt, IRQF_SHARED, name, dev);
++ ret = request_irq(dev->irq, atari_ei_interrupt, IRQF_SHARED, name, dev);
+ if (ret) {
+ printk(" unable to get IRQ %d (errno=%d), polling instead.\n",
+ dev->irq, ret);
+@@ -941,9 +949,9 @@ retry:
+
+
+ #ifdef MODULE
+-#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
++#define MAX_NE_CARDS 1 /* Max number of NE cards per module */
+ static struct net_device *dev_ne[MAX_NE_CARDS];
+-static int io[MAX_NE_CARDS];
++static int io[MAX_NE_CARDS] = { 0x300 };
+ static int irq[MAX_NE_CARDS];
+ static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernec.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-ethernec.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,1089 @@
+Subject: [PATCH] m68k: Atari EtherNEC driver
+Cc: Jeff Garzik <jgarzik at pobox.com>, netdev at vger.kernel.org
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+Atari EtherNEC driver
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/Kconfig | 8
+ drivers/net/Makefile | 1
+ drivers/net/Space.c | 4
+ drivers/net/atari_ethernec.c | 1022 +++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 1035 insertions(+)
+
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -406,6 +406,14 @@ config ATARILANCE
+ on the AMD Lance chipset: RieblCard (with or without battery), or
+ PAMCard VME (also the version by Rhotron, with different addresses).
+
++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 SUN3 || SUN3X
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -202,6 +202,7 @@ obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
+ obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
+ obj-$(CONFIG_DECLANCE) += declance.o
+ obj-$(CONFIG_ATARILANCE) += atarilance.o
++obj-$(CONFIG_ATARI_ETHERNEC) += atari_ethernec.o 8390.o
+ obj-$(CONFIG_A2065) += a2065.o
+ obj-$(CONFIG_HYDRA) += hydra.o
+ obj-$(CONFIG_ARIADNE) += ariadne.o
+--- a/drivers/net/Space.c
++++ b/drivers/net/Space.c
+@@ -72,6 +72,7 @@ extern struct net_device *SK_init(int un
+ 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 *sun3lance_probe(int unit);
+ extern struct net_device *sun3_82586_probe(int unit);
+ extern struct net_device *apne_probe(int unit);
+@@ -253,6 +254,9 @@ static struct devprobe2 m68k_probes[] __
+ #ifdef CONFIG_ATARILANCE /* Lance-based Atari ethernet boards */
+ {atarilance_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
+--- /dev/null
++++ b/drivers/net/atari_ethernec.c
+@@ -0,0 +1,1022 @@
++/*
++ * atari_ethernec.c: Atari cartridge port ethernet adapter
++ * (C) 2006 Michael Schmitz
++ *
++ * Modified after:
++ */
++
++/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
++/*
++ Written 1992-94 by Donald Becker.
++
++ Copyright 1993 United States Government as represented by the
++ Director, National Security Agency.
++
++ This software may be used and distributed according to the terms
++ of the GNU General Public License, incorporated herein by reference.
++
++ The author may be reached as becker at scyld.com, or C/O
++ Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
++
++ This driver should work with many programmed-I/O 8390-based ethernet
++ boards. Currently it supports the NE1000, NE2000, many clones,
++ and some Cabletron products.
++
++ Changelog:
++
++ Paul Gortmaker : use ENISR_RDC to monitor Tx PIO uploads, made
++ sanity checks and bad clone support optional.
++ Paul Gortmaker : new reset code, reset card after probe at boot.
++ Paul Gortmaker : multiple card support for module users.
++ Paul Gortmaker : Support for PCI ne2k clones, similar to lance.c
++ Paul Gortmaker : Allow users with bad cards to avoid full probe.
++ Paul Gortmaker : PCI probe changes, more PCI cards supported.
++ rjohnson at analogic.com : Changed init order so an interrupt will only
++ occur after memory is allocated for dev->priv. Deallocated memory
++ last in cleanup_modue()
++ Richard Guenther : Added support for ISAPnP cards
++ Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead.
++ Hayato Fujiwara : Add m32r support.
++
++*/
++
++/*
++ * From the driver distribution kit by Thomas Redelberger:
++ *
++ * Hardware circuit description (see directory ETHERNEC for schematics)
++ *
++ * As there is no reset line on the CP, a resistor and a capacitor are
++ * used to reset the NE card on power up.
++ *
++ * Reading from the NE card is done by a read cycle on the CP at address
++ * /ROM4 + 512*ISA address as the ISA address lines A0-A4 are connected
++ * to CP A9-A13. /ROM4 going low will start the ISA read cycle, enable
++ * the ISA bus buffers of the NE card and start decoding of the ISA IO
++ * address by the NE card. /ROM4 going high ends the cycle and the
++ * processor latches the data.
++ *
++ * Because the CP is read only writing to the NE card must be done with
++ * the trick to read from addresses that stand for the data. Dummy reads
++ * at /ROM3 base address + data*2 + ISA address*512 effect this. You
++ * might wonder why everything appears to be shifted up one bit. There is
++ * no CP "A0" address line. There are the signals /UDS and /LDS instead
++ * typical for the 68000 family. The original design which generated an
++ * "A0" worked on an ST and an STE but did not on a Falcon.
++ *
++ * The falling edge of /ROM3 enables the CP address lines A1-A8 onto the
++ * data bus and starts the ISA write cycle. The rising edge will end the
++ * ISA write cycle and the NE latches the data. The processor will also
++ * see and just read this same data but that is harmless.
++ * Elmar Hilgart reported that the bus buffer IC shall be an TTL F-type
++ * to keep up with the fast cycles on the Falcon.
++ *
++ * Base addresses:
++ * rom4 EQU $00fa0000 ; ROM4 base address
++ * rom3 EQU $00fb0000 ; ROM3 base address
++ *
++ */
++
++/* Routines for the NatSemi-based designs (NE[12]000). */
++
++static const char version1[] =
++"ne.c:v1.10 9/23/94 Donald Becker (becker at scyld.com)\n";
++static const char version2[] =
++"atari_ethernec.c 11/10/06 Michael Schmitz (schmitz at debian.org)\n";
++
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/isapnp.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/jiffies.h>
++#include <linux/workqueue.h>
++
++#include <asm/system.h>
++#include <asm/atarihw.h>
++#include <asm/atariints.h>
++#include <asm/io.h>
++
++#include "8390.h"
++
++#define DRV_NAME "ethernec"
++
++/* Some defines that people can play with if so inclined. */
++
++/* Do we support clones that don't adhere to 14,15 of the SAprom ? */
++#define SUPPORT_NE_BAD_CLONES
++
++/* Do we perform extra sanity checks on stuff ? */
++/* #define NE_SANITY_CHECK */
++
++/* Do we implement the read before write bugfix ? */
++/* #define NE_RW_BUGFIX */
++
++/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
++/* #define PACKETBUF_MEMSIZE 0x40 */
++
++/* A zero-terminated list of I/O addresses to be probed at boot. */
++#ifndef MODULE
++static unsigned int netcard_portlist[] __initdata = {
++ 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
++};
++#endif
++
++static struct isapnp_device_id isapnp_clone_list[] __initdata = {
++ { ISAPNP_CARD_ID('A','X','E',0x2011),
++ ISAPNP_VENDOR('A','X','E'), ISAPNP_FUNCTION(0x2011),
++ (long) "NetGear EA201" },
++ { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
++ ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216),
++ (long) "NN NE2000" },
++ { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
++ ISAPNP_VENDOR('P','N','P'), ISAPNP_FUNCTION(0x80d6),
++ (long) "Generic PNP" },
++ { } /* terminate list */
++};
++
++MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list);
++
++#ifdef SUPPORT_NE_BAD_CLONES
++/* A list of bad clones that we none-the-less recognize. */
++static struct { const char *name8, *name16; unsigned char SAprefix[4];}
++bad_clone_list[] __initdata = {
++ {"DE100", "DE200", {0x00, 0xDE, 0x01,}},
++ {"DE120", "DE220", {0x00, 0x80, 0xc8,}},
++ {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh? */
++ {"EtherNext UTP8", "EtherNext UTP16", {0x00, 0x00, 0x79}},
++ {"NE1000","NE2000-invalid", {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */
++ {"NN1000", "NN2000", {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */
++ {"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}}, /* Outlaw 4-Dimension cards. */
++ {"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */
++ {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
++ {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
++ {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
++ {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
++ {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
++#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
++ {"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}}, /* Toshiba built-in */
++#endif
++ {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
++ {NULL,}
++};
++#endif
++
++/* ---- No user-serviceable parts below ---- */
++
++#define NE_BASE (dev->base_addr)
++#define NE_CMD 0x00
++#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */
++#define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */
++#define NE_IO_EXTENT 0x20
++
++#define NE1SM_START_PG 0x20 /* First page of TX buffer */
++#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
++#define NESM_START_PG 0x40 /* First page of TX buffer */
++#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
++
++#if defined(CONFIG_PLAT_MAPPI)
++# define DCR_VAL 0x4b
++#elif defined(CONFIG_PLAT_OAKS32R) || \
++ defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938) || \
++ defined(CONFIG_ATARI_ETHERNEC) || defined(CONFIG_ATARI_ETHERNEC_MODULE)
++# define DCR_VAL 0x48 /* 8-bit mode */
++#else
++# define DCR_VAL 0x49
++#endif
++
++#if defined(CONFIG_ATARI_ETHERNEC) || defined(CONFIG_ATARI_ETHERNEC_MODULE)
++# define ETHERNEC_RTL_8019_BASE 0x300
++# define ETHERNEC_RTL_8019_IRQ IRQ_MFP_TIMD
++#endif
++
++static int ne_probe1(struct net_device *dev, int ioaddr);
++static int ne_probe_isapnp(struct net_device *dev);
++
++static int ne_open(struct net_device *dev);
++static int ne_close(struct net_device *dev);
++
++static void ne_reset_8390(struct net_device *dev);
++static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
++ int ring_page);
++static void ne_block_input(struct net_device *dev, int count,
++ struct sk_buff *skb, int ring_offset);
++static void ne_block_output(struct net_device *dev, const int count,
++ const unsigned char *buf, const int start_page);
++
++
++/*
++ * The Atari ROM port has no interrupt line, so we poll the card instead.
++ */
++
++static int use_poll;
++
++/*
++ * This is used by cleanup, to prevent the module from being unloaded while
++ * intrpt_routine is still in the task queue
++ */
++static wait_queue_head_t WaitQ;
++
++static struct delayed_work tqueue;
++
++static struct net_device *poll_dev = NULL;
++
++static void atari_ethernec_int(struct work_struct *work)
++{
++ struct net_device *dev = poll_dev;
++
++ if (!dev) {
++ /* If cleanup wants us to die */
++ if (waitqueue_active(&WaitQ))
++ wake_up(&WaitQ); /* Now cleanup_module can return */
++ else
++ /* Put ourselves back in the task queue */
++ schedule_delayed_work(&tqueue, 1);
++ return;
++ }
++
++ if (netif_running(dev))
++ ei_interrupt(dev->irq, dev);
++
++ /* If cleanup wants us to die */
++ if (waitqueue_active(&WaitQ))
++ wake_up(&WaitQ); /* Now cleanup_module can return */
++ else
++ /* Put ourselves back in the task queue */
++ schedule_delayed_work(&tqueue, 0); /* reduced delay from 1 */
++}
++
++static void atari_ethernec_start_poll(struct net_device *dev)
++{
++ poll_dev = dev;
++
++ init_waitqueue_head(&WaitQ);
++
++ INIT_DELAYED_WORK(&tqueue, atari_ethernec_int);
++ schedule_delayed_work(&tqueue, 1);
++}
++
++static void atari_ethernec_stop_poll(struct net_device *dev)
++{
++ poll_dev = NULL;
++
++ if (dev)
++ sleep_on(&WaitQ);
++}
++
++
++/* Probe for various non-shared-memory ethercards.
++
++ NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
++ buffer memory space. NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
++ the SAPROM, while other supposed NE2000 clones must be detected by their
++ SA prefix.
++
++ Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
++ mode results in doubled values, which can be detected and compensated for.
++
++ The probe is also responsible for initializing the card and filling
++ in the 'dev' and 'ei_status' structures.
++
++ We use the minimum memory size for some ethercard product lines, iff we can't
++ distinguish models. You can increase the packet buffer size by setting
++ PACKETBUF_MEMSIZE. Reported Cabletron packet buffer locations are:
++ E1010 starts at 0x100 and ends at 0x2000.
++ E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
++ E2010 starts at 0x100 and ends at 0x4000.
++ E2010-x starts at 0x100 and ends at 0xffff.
++*/
++
++static int __init do_ne_probe(struct net_device *dev)
++{
++ unsigned int base_addr = dev->base_addr;
++ int rv;
++#ifndef MODULE
++ int orig_irq = dev->irq;
++#endif
++
++ /* First check any supplied i/o locations. User knows best. <cough> */
++ if (base_addr > 0x1ff) { /* Check a single specified location. */
++ rv = ne_probe1(dev, base_addr);
++ if (!rv && use_poll) {
++ /* Seems we have a valid device here; set up polling routine */
++ poll_dev = dev;
++ atari_ethernec_start_poll(dev);
++ }
++ return rv;
++ } else if (base_addr != 0) /* Don't probe at all. */
++ return -ENXIO;
++
++ /* Then look for any installed ISAPnP clones */
++ if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
++ return 0;
++
++#ifndef MODULE
++ /* Last resort. The semi-risky ISA auto-probe. */
++ for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
++ int ioaddr = netcard_portlist[base_addr];
++ dev->irq = orig_irq;
++ rv = ne_probe1(dev, ioaddr);
++ if (rv == 0) {
++ if (use_poll) {
++ poll_dev = dev;
++ atari_ethernec_start_poll(dev);
++ }
++ return 0;
++ }
++ }
++#endif
++
++ return -ENODEV;
++}
++
++#ifndef MODULE
++struct net_device * __init atari_ethernec_probe(int unit)
++{
++ struct net_device *dev;
++ int err;
++
++ if (!MACH_IS_ATARI)
++ return ERR_PTR(-ENODEV);
++
++ dev = alloc_ei_netdev();
++ if (!dev)
++ return ERR_PTR(-ENOMEM);
++
++ sprintf(dev->name, "eth%d", unit);
++ netdev_boot_setup_check(dev);
++
++#if defined(CONFIG_ATARI_ETHERNEC)
++ dev->base_addr = ETHERNEC_RTL_8019_BASE;
++ dev->irq = ETHERNEC_RTL_8019_IRQ;
++#endif
++ err = do_ne_probe(dev);
++ if (err)
++ goto out;
++
++ /* Seems we have a valid device here; set up polling routine */
++ return dev;
++out:
++ free_netdev(dev);
++ return ERR_PTR(err);
++}
++#endif
++
++static int __init ne_probe_isapnp(struct net_device *dev)
++{
++ int i;
++
++ for (i = 0; isapnp_clone_list[i].vendor != 0; i++) {
++ struct pnp_dev *idev = NULL;
++
++ while ((idev = pnp_find_dev(NULL,
++ isapnp_clone_list[i].vendor,
++ isapnp_clone_list[i].function,
++ idev))) {
++ /* Avoid already found cards from previous calls */
++ if (pnp_device_attach(idev) < 0)
++ continue;
++ if (pnp_activate_dev(idev) < 0) {
++ pnp_device_detach(idev);
++ continue;
++ }
++ /* if no io and irq, search for next */
++ if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
++ pnp_device_detach(idev);
++ continue;
++ }
++ /* found it */
++ dev->base_addr = pnp_port_start(idev, 0);
++ dev->irq = pnp_irq(idev, 0);
++ printk(KERN_INFO "atari_ethernec.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
++ (char *) isapnp_clone_list[i].driver_data,
++ dev->base_addr, dev->irq);
++ if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */
++ printk(KERN_ERR "atari_ethernec.c: Probe of ISAPnP card at %#lx failed.\n",
++ dev->base_addr);
++ pnp_device_detach(idev);
++ return -ENXIO;
++ }
++ ei_status.priv = (unsigned long)idev;
++ break;
++ }
++ if (!idev)
++ continue;
++ return 0;
++ }
++
++ return -ENODEV;
++}
++
++static int __init ne_probe1(struct net_device *dev, int ioaddr)
++{
++ int i;
++ unsigned char SA_prom[32];
++ int wordlength = 2;
++ const char *name = NULL;
++ int start_page, stop_page;
++ int neX000, ctron, copam, bad_card;
++ int reg0, ret;
++ static unsigned version_printed;
++
++ if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
++ return -EBUSY;
++
++ reg0 = inb_p(ioaddr);
++ if (reg0 == 0xFF) {
++ ret = -ENODEV;
++ goto err_out;
++ }
++
++ /* Do a preliminary verification that we have a 8390. */
++ {
++ int regd;
++ outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
++ regd = inb_p(ioaddr + 0x0d);
++ outb_p(0xff, ioaddr + 0x0d);
++ outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
++ inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
++ if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
++ outb_p(reg0, ioaddr);
++ outb_p(regd, ioaddr + 0x0d); /* Restore the old values. */
++ ret = -ENODEV;
++ goto err_out;
++ }
++ }
++
++ if (ei_debug && version_printed++ == 0)
++ printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
++
++ /* A user with a poor card that fails to ack the reset, or that
++ does not have a valid 0x57,0x57 signature can still use this
++ without having to recompile. Specifying an i/o address along
++ with an otherwise unused dev->mem_end value of "0xBAD" will
++ cause the driver to skip these parts of the probe. */
++
++ bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
++
++ /* Reset card. Who knows what dain-bramaged state it was left in. */
++
++ {
++ unsigned long reset_start_time = jiffies;
++
++ /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
++ outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
++
++ while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0) {
++ if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
++ if (bad_card) {
++ printk(" (warning: no reset ack)");
++ break;
++ } else {
++ // MSch: ARAnyM exits here
++ printk(" not found (no reset ack).\n");
++ ret = -ENODEV;
++ goto err_out;
++ }
++ }
++ }
++
++ outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */
++ }
++
++ /* Read the 16 bytes of station address PROM.
++ We must first initialize registers, similar to NS8390_init(eifdev, 0).
++ We can't reliably read the SAPROM address without this.
++ (I learned the hard way!). */
++ {
++ struct {unsigned char value, offset; } program_seq[] =
++ {
++ {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
++ {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */
++ {0x00, EN0_RCNTLO}, /* Clear the count regs. */
++ {0x00, EN0_RCNTHI},
++ {0x00, EN0_IMR}, /* Mask completion irq. */
++ {0xFF, EN0_ISR},
++ {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
++ {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
++ {32, EN0_RCNTLO},
++ {0x00, EN0_RCNTHI},
++ {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
++ {0x00, EN0_RSARHI},
++ {E8390_RREAD+E8390_START, E8390_CMD},
++ };
++
++ for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
++ outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
++
++ }
++ for (i = 0; i < 32 /*sizeof(SA_prom)*/; i += 2) {
++ SA_prom[i] = inb(ioaddr + NE_DATAPORT);
++ SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
++ if (SA_prom[i] != SA_prom[i+1])
++ wordlength = 1;
++ }
++
++ if (wordlength == 2) {
++ for (i = 0; i < 16; i++)
++ SA_prom[i] = SA_prom[i+i];
++ /* We must set the 8390 for word mode. */
++ outb_p(DCR_VAL, ioaddr + EN0_DCFG);
++ start_page = NESM_START_PG;
++
++ /*
++ * Realtek RTL8019AS datasheet says that the PSTOP register
++ * shouldn't exceed 0x60 in 8-bit mode.
++ * This chip can be identified by reading the signature from
++ * the remote byte count registers (otherwise write-only)...
++ */
++ if ((DCR_VAL & 0x01) == 0 && /* 8-bit mode */
++ inb(ioaddr + EN0_RCNTLO) == 0x50 &&
++ inb(ioaddr + EN0_RCNTHI) == 0x70)
++ stop_page = 0x60;
++ else
++ stop_page = NESM_STOP_PG;
++ } else {
++ start_page = NE1SM_START_PG;
++ stop_page = NE1SM_STOP_PG;
++ }
++
++#if defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R)
++ neX000 = ((SA_prom[14] == 0x57 && SA_prom[15] == 0x57)
++ || (SA_prom[14] == 0x42 && SA_prom[15] == 0x42));
++#else
++ neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
++#endif
++ ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
++ copam = (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
++
++ /* Set up the rest of the parameters. */
++ if (neX000 || bad_card || copam) {
++ name = (wordlength == 2) ? "NE2000" : "NE1000";
++ } else if (ctron) {
++ name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
++ start_page = 0x01;
++ stop_page = (wordlength == 2) ? 0x40 : 0x20;
++ } else {
++#ifdef SUPPORT_NE_BAD_CLONES
++ /* Ack! Well, there might be a *bad* NE*000 clone there.
++ Check for total bogus addresses. */
++ for (i = 0; bad_clone_list[i].name8; i++) {
++ if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
++ SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
++ SA_prom[2] == bad_clone_list[i].SAprefix[2]) {
++ if (wordlength == 2) {
++ name = bad_clone_list[i].name16;
++ } else {
++ name = bad_clone_list[i].name8;
++ }
++ break;
++ }
++ }
++ if (bad_clone_list[i].name8 == NULL) {
++ printk(" not found (invalid signature %2.2x %2.2x).\n",
++ SA_prom[14], SA_prom[15]);
++ ret = -ENXIO;
++ goto err_out;
++ }
++#else
++ printk(" not found.\n");
++ ret = -ENXIO;
++ goto err_out;
++#endif
++ }
++
++ if (dev->irq < 2) {
++ unsigned long cookie = probe_irq_on();
++ outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */
++ outb_p(0x00, ioaddr + EN0_RCNTLO);
++ outb_p(0x00, ioaddr + EN0_RCNTHI);
++ outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
++ mdelay(10); /* wait 10ms for interrupt to propagate */
++ outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */
++ dev->irq = probe_irq_off(cookie);
++ if (ei_debug > 2)
++ printk(" autoirq is %d\n", dev->irq);
++ } else if (dev->irq == 2)
++ /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
++ or don't know which one to set. */
++ dev->irq = 9;
++
++ /*
++ * use timer based polling!
++ */
++ if (! dev->irq) {
++ printk(" failed to detect IRQ line. Assuming irq %d\n",
++ ETHERNEC_RTL_8019_IRQ);
++ dev->irq = ETHERNEC_RTL_8019_IRQ;
++ /* timer routine set up in atari_ethernec_probe() */
++ if (dev->irq == IRQ_MFP_TIMD) {
++ /* set Timer D data Register */
++ mfp.tim_dt_d = 123; /* 200 Hz */
++ /* start timer D, div = 1:100 */
++ mfp.tim_ct_cd = (mfp.tim_ct_cd & 0xf0) | 0x6;
++ }
++ /* Must make this shared in case other timer ints are needed */
++ ret = request_irq(dev->irq, ei_interrupt, IRQF_SHARED, name, dev);
++ if (ret) {
++ printk(" unable to get IRQ %d (errno=%d), polling instead.\n",
++ dev->irq, ret);
++ use_poll = 1;
++ }
++ } else {
++
++ /* Snarf the interrupt now. There's no point in waiting since we cannot
++ share and the board will usually be enabled. */
++ ret = request_irq(dev->irq, ei_interrupt, 0, name, dev);
++ if (ret) {
++ printk(" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
++ goto err_out;
++ }
++ }
++ dev->base_addr = ioaddr;
++
++#ifdef CONFIG_PLAT_MAPPI
++ outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
++ ioaddr + E8390_CMD); /* 0x61 */
++ for (i = 0; i < ETHER_ADDR_LEN; i++) {
++ dev->dev_addr[i] = SA_prom[i] = inb_p(ioaddr + EN1_PHYS_SHIFT(i));
++ printk(" %2.2x", SA_prom[i]);
++ }
++#else
++ for (i = 0; i < ETHER_ADDR_LEN; i++) {
++ printk(" %2.2x", SA_prom[i]);
++ dev->dev_addr[i] = SA_prom[i];
++ }
++#endif
++
++ printk("\n%s: %s found at %#x, using IRQ %d.\n",
++ dev->name, name, ioaddr, dev->irq);
++
++ ei_status.name = name;
++ ei_status.tx_start_page = start_page;
++ ei_status.stop_page = stop_page;
++
++ /* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
++ ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
++
++ ei_status.rx_start_page = start_page + TX_PAGES;
++#ifdef PACKETBUF_MEMSIZE
++ /* Allow the packet buffer size to be overridden by know-it-alls. */
++ ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
++#endif
++
++ ei_status.reset_8390 = &ne_reset_8390;
++ ei_status.block_input = &ne_block_input;
++ ei_status.block_output = &ne_block_output;
++ ei_status.get_8390_hdr = &ne_get_8390_hdr;
++ ei_status.priv = 0;
++ dev->open = &ne_open;
++ dev->stop = &ne_close;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ dev->poll_controller = ei_poll;
++#endif
++ NS8390_init(dev, 0);
++
++ ret = register_netdev(dev);
++ if (ret)
++ goto out_irq;
++ return 0;
++
++out_irq:
++ free_irq(dev->irq, dev);
++err_out:
++ release_region(ioaddr, NE_IO_EXTENT);
++ return ret;
++}
++
++static int ne_open(struct net_device *dev)
++{
++ ei_open(dev);
++ return 0;
++}
++
++static int ne_close(struct net_device *dev)
++{
++ if (ei_debug > 1)
++ printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
++ ei_close(dev);
++ return 0;
++}
++
++/* Hard reset the card. This used to pause for the same period that a
++ 8390 reset command required, but that shouldn't be necessary. */
++
++static void ne_reset_8390(struct net_device *dev)
++{
++ unsigned long reset_start_time = jiffies;
++
++ if (ei_debug > 1)
++ printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
++
++ /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
++ outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
++
++ ei_status.txing = 0;
++ ei_status.dmaing = 0;
++
++ /* This check _should_not_ be necessary, omit eventually. */
++ while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) {
++ if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
++ printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n",
++ dev->name);
++ break;
++ }
++ }
++ outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
++}
++
++/* Grab the 8390 specific header. Similar to the block_input routine, but
++ we don't need to be concerned with ring wrap as the header will be at
++ the start of a page, so we optimize accordingly. */
++
++static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
++{
++ int nic_base = dev->base_addr;
++
++ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
++
++ if (ei_status.dmaing)
++ {
++ printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
++ "[DMAstat:%d][irqlock:%d].\n",
++ dev->name, ei_status.dmaing, ei_status.irqlock);
++ return;
++ }
++
++ ei_status.dmaing |= 0x01;
++ outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
++ outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
++ outb_p(0, nic_base + EN0_RCNTHI);
++ outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
++ outb_p(ring_page, nic_base + EN0_RSARHI);
++ outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
++
++ if (ei_status.word16)
++ insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
++ else
++ insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
++
++ outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
++ ei_status.dmaing &= ~0x01;
++
++ le16_to_cpus(&hdr->count);
++}
++
++/* Block input and output, similar to the Crynwr packet driver. If you
++ are porting to a new ethercard, look at the packet driver source for hints.
++ The NEx000 doesn't share the on-board packet memory -- you have to put
++ the packet out through the "remote DMA" dataport using outb. */
++
++static void ne_block_input(struct net_device *dev, int count,
++ struct sk_buff *skb, int ring_offset)
++{
++#ifdef NE_SANITY_CHECK
++ int xfer_count = count;
++#endif
++ int nic_base = dev->base_addr;
++ char *buf = skb->data;
++
++ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
++ if (ei_status.dmaing) {
++ printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
++ "[DMAstat:%d][irqlock:%d].\n",
++ dev->name, ei_status.dmaing, ei_status.irqlock);
++ return;
++ }
++ ei_status.dmaing |= 0x01;
++ outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
++ outb_p(count & 0xff, nic_base + EN0_RCNTLO);
++ outb_p(count >> 8, nic_base + EN0_RCNTHI);
++ outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
++ outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
++ outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
++
++ if (ei_status.word16) {
++ insw(NE_BASE + NE_DATAPORT,buf,count>>1);
++ if (count & 0x01) {
++ buf[count-1] = inb(NE_BASE + NE_DATAPORT);
++#ifdef NE_SANITY_CHECK
++ xfer_count++;
++#endif
++ }
++ } else {
++ insb(NE_BASE + NE_DATAPORT, buf, count);
++ }
++
++#ifdef NE_SANITY_CHECK
++ /* This was for the ALPHA version only, but enough people have
++ been encountering problems so it is still here. If you see
++ this message you either 1) have a slightly incompatible clone
++ or 2) have noise/speed problems with your bus. */
++
++ if (ei_debug > 1) {
++ /* DMA termination address check... */
++ int addr, tries = 20;
++ do {
++ /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
++ -- it's broken for Rx on some cards! */
++ int high = inb_p(nic_base + EN0_RSARHI);
++ int low = inb_p(nic_base + EN0_RSARLO);
++ addr = (high << 8) + low;
++ if (((ring_offset + xfer_count) & 0xff) == low)
++ break;
++ } while (--tries > 0);
++ if (tries <= 0)
++ printk(KERN_WARNING "%s: RX transfer address mismatch,"
++ "%#4.4x (expected) vs. %#4.4x (actual).\n",
++ dev->name, ring_offset + xfer_count, addr);
++ }
++#endif
++ outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
++ ei_status.dmaing &= ~0x01;
++}
++
++static void ne_block_output(struct net_device *dev, int count,
++ const unsigned char *buf, const int start_page)
++{
++ int nic_base = NE_BASE;
++ unsigned long dma_start;
++#ifdef NE_SANITY_CHECK
++ int retries = 0;
++#endif
++
++ /* Round the count up for word writes. Do we need to do this?
++ What effect will an odd byte count have on the 8390?
++ I should check someday. */
++
++ if (ei_status.word16 && (count & 0x01))
++ count++;
++
++ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
++ if (ei_status.dmaing) {
++ printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
++ "[DMAstat:%d][irqlock:%d]\n",
++ dev->name, ei_status.dmaing, ei_status.irqlock);
++ return;
++ }
++ ei_status.dmaing |= 0x01;
++ /* We should already be in page 0, but to be safe... */
++ outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
++
++#ifdef NE_SANITY_CHECK
++retry:
++#endif
++
++#ifdef NE8390_RW_BUGFIX
++ /* Handle the read-before-write bug the same way as the
++ Crynwr packet driver -- the NatSemi method doesn't work.
++ Actually this doesn't always work either, but if you have
++ problems with your NEx000 this is better than nothing! */
++
++ outb_p(0x42, nic_base + EN0_RCNTLO);
++ outb_p(0x00, nic_base + EN0_RCNTHI);
++ outb_p(0x42, nic_base + EN0_RSARLO);
++ outb_p(0x00, nic_base + EN0_RSARHI);
++ outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
++ /* Make certain that the dummy read has occurred. */
++ udelay(6);
++#endif
++
++ outb_p(ENISR_RDC, nic_base + EN0_ISR);
++
++ /* Now the normal output. */
++ outb_p(count & 0xff, nic_base + EN0_RCNTLO);
++ outb_p(count >> 8, nic_base + EN0_RCNTHI);
++ outb_p(0x00, nic_base + EN0_RSARLO);
++ outb_p(start_page, nic_base + EN0_RSARHI);
++
++ outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
++ if (ei_status.word16)
++ outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
++ else
++ outsb(NE_BASE + NE_DATAPORT, buf, count);
++
++ dma_start = jiffies;
++
++#ifdef NE_SANITY_CHECK
++ /* This was for the ALPHA version only, but enough people have
++ been encountering problems so it is still here. */
++
++ if (ei_debug > 1) {
++ /* DMA termination address check... */
++ int addr, tries = 20;
++ do {
++ int high = inb_p(nic_base + EN0_RSARHI);
++ int low = inb_p(nic_base + EN0_RSARLO);
++ addr = (high << 8) + low;
++ if ((start_page << 8) + count == addr)
++ break;
++ } while (--tries > 0);
++
++ if (tries <= 0) {
++ printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
++ "%#4.4x (expected) vs. %#4.4x (actual).\n",
++ dev->name, (start_page << 8) + count, addr);
++ if (retries++ == 0)
++ goto retry;
++ }
++ }
++#endif
++
++ while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
++ if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
++ printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
++ ne_reset_8390(dev);
++ NS8390_init(dev, 1);
++ break;
++ }
++ }
++
++ outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
++ ei_status.dmaing &= ~0x01;
++ return;
++}
++
++
++#ifdef MODULE
++#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
++static struct net_device *dev_ne[MAX_NE_CARDS];
++static int io[MAX_NE_CARDS];
++static int irq[MAX_NE_CARDS];
++static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
++
++module_param_array(io, int, NULL, 0);
++module_param_array(irq, int, NULL, 0);
++module_param_array(bad, int, NULL, 0);
++module_param(use_poll, int, 0);
++MODULE_PARM_DESC(io, "I/O base address(es),required");
++MODULE_PARM_DESC(irq, "IRQ number(s)");
++MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
++MODULE_PARM_DESC(use_poll, "Use timer interrupt to poll driver");
++MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
++MODULE_LICENSE("GPL");
++
++/* This is set up so that no ISA autoprobe takes place. We can't guarantee
++that the ne2k probe is the last 8390 based probe to take place (as it
++is at boot) and so the probe will get confused by any other 8390 cards.
++ISA device autoprobes on a running machine are not recommended anyway. */
++
++int __init init_module(void)
++{
++ int this_dev, found = 0;
++
++ if (!MACH_IS_ATARI)
++ return -ENODEV;
++
++ for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
++ struct net_device *dev = alloc_ei_netdev();
++ if (!dev)
++ break;
++ dev->irq = irq[this_dev];
++ dev->mem_end = bad[this_dev];
++ dev->base_addr = io[this_dev];
++ if (do_ne_probe(dev) == 0) {
++ dev_ne[found++] = dev;
++ continue;
++ }
++ free_netdev(dev);
++ if (found)
++ break;
++ if (io[this_dev] != 0)
++ printk(KERN_WARNING "atari_ethernec.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
++ else
++ printk(KERN_NOTICE "atari_ethernec.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
++ return -ENXIO;
++ }
++ if (found)
++ return 0;
++ return -ENODEV;
++}
++
++static void cleanup_card(struct net_device *dev)
++{
++ struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
++ if (idev)
++ pnp_device_detach(idev);
++ free_irq(dev->irq, dev);
++ release_region(dev->base_addr, NE_IO_EXTENT);
++}
++
++void cleanup_module(void)
++{
++ int this_dev;
++
++ for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
++ struct net_device *dev = dev_ne[this_dev];
++ if (dev) {
++ if (use_poll)
++ atari_ethernec_stop_poll(dev);
++ unregister_netdev(dev);
++ cleanup_card(dev);
++ free_netdev(dev);
++ }
++ }
++}
++#endif /* MODULE */
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-io-fixes.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-io-fixes.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,70 @@
+Subject: [PATCH] m68k: Atari io.h fixes for EtherNAT driver
+
+From: Michael Schmitz <schmitz at biophys.uni-duesseldorf.de>
+
+This patch fixes errors I introduced in preparing the io.h code for ROM port
+ISA access (for the EtherNEC driver, originally).
+
+My assumption was that insb/outsb and friends should be mapped to the ROM
+port accessors unconditionally, and the read*/write* functions should behave
+like regular ISA accesses. As it turned out, it's just the other way 'round.
+"Regular" ISA readb would apply the ROM port address mapping without
+actually using the correct access function.
+
+ins*/outs* are conditionalized now (port < 1024 goes to the ROM port, all
+else via MMIO), read*/write* use straight MMIO no questions asked.
+
+This fixes register access problems for the EtherNAT (SMC91C111) when used
+together with the EtherNEC (ROM port NE2k clone). Tested on my Falcon.
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ include/asm-m68k/io.h | 29 ++++++++++++++++-------------
+ 1 file changed, 16 insertions(+), 13 deletions(-)
+
+--- a/include/asm-m68k/io.h
++++ b/include/asm-m68k/io.h
+@@ -380,8 +380,8 @@ static inline void isa_delay(void)
+ /*
+ * kernel with both ROM port ISA and IDE compiled in, those have
+ * conflicting defs for in/out. Simply consider port < 1024
+- * ROM port ISA and everything else regular ISA for IDE. read,write not defined
+- * in this case
++ * ROM port ISA and everything else regular ISA for IDE. read,write defined
++ * below.
+ */
+ #define inb(port) ((port) < 1024 ? isa_rom_inb(port) : in_8(port))
+ #define inb_p(port) ((port) < 1024 ? isa_rom_inb_p(port) : in_8(port))
+@@ -397,17 +397,20 @@ static inline void isa_delay(void)
+ #define outl(val, port) ((port) < 1024 ? isa_rom_outl((val), (port)) : out_le32((port), (val)))
+ #define outl_p(val, port) ((port) < 1024 ? isa_rom_outl_p((val), (port)) : out_le32((port), (val)))
+
+-#define insb isa_rom_insb
+-#define insw isa_rom_insw
+-#define insl isa_rom_insl
+-#define outsb isa_rom_outsb
+-#define outsw isa_rom_outsw
+-#define outsl isa_rom_outsl
+-
+-#define readb isa_readb
+-#define readw isa_readw
+-#define writeb isa_writeb
+-#define writew isa_writew
++#define insb(port, buf, nr) ((port) < 1024 ? isa_rom_insb((port), (buf), (nr)) : isa_insb((port), (buf), (nr)))
++#define insw(port, buf, nr) ((port) < 1024 ? isa_rom_insw((port), (buf), (nr)) : isa_insw((port), (buf), (nr)))
++#define insl(port, buf, nr) ((port) < 1024 ? isa_rom_insl((port), (buf), (nr)) : isa_insl((port), (buf), (nr)))
++#define outsb(port, buf, nr) ((port) < 1024 ? isa_rom_outsb((port), (buf), (nr)) : isa_outsb((port), (buf), (nr)))
++#define outsw(port, buf, nr) ((port) < 1024 ? isa_rom_outsw((port), (buf), (nr)) : isa_outsw((port), (buf), (nr)))
++#define outsl(port, buf, nr) ((port) < 1024 ? isa_rom_outsl((port), (buf), (nr)) : isa_outsl((port), (buf), (nr)))
++
++#define readb(addr) in_8(addr)
++#define writeb(val,addr) out_8((addr),(val))
++#define readw(addr) in_le16(addr)
++#define writew(val,addr) out_le16((addr),(val))
++
++#define readsw raw_insw
++#define writesw raw_outsw
+ #define readsl raw_insl
+ #define writesl raw_outsl
+ #endif /* CONFIG_ATARI_ROM_ISA */
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-platform-device.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-platform-device.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,77 @@
+Subject: [PATCH] m68k: Initial Atari platform device handling
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+arch/m68k/atari/ataints.c: ATARIHW_PRESENT(TT_MFP)) || \
+arch/m68k/atari/ataints.c: !((n) & 1) && ATARIHW_PRESENT(SCC)) || \
+arch/m68k/atari/ataints.c: if (ATARIHW_PRESENT(TT_MFP)) {
+arch/m68k/atari/ataints.c: if (ATARIHW_PRESENT(SCC) && !atari_SCC_reset_done) {
+arch/m68k/atari/ataints.c: if (ATARIHW_PRESENT(SCU)) {
+arch/m68k/atari/ataints.c: if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) {
+arch/m68k/atari/config.c: if (!MACH_IS_HADES && !ATARIHW_PRESENT(ST_SCSI)) {
+arch/m68k/atari/config.c: if (ATARIHW_PRESENT(MSTE_CLK))
+arch/m68k/atari/config.c: if (ATARIHW_PRESENT(name)) \
+arch/m68k/atari/debug.c: if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
+drivers/block/ataflop.c: if (ATARIHW_PRESENT(FDCSPEED))
+drivers/block/ataflop.c: if (ATARIHW_PRESENT(FDCSPEED))
+drivers/block/ataflop.c: if (ATARIHW_PRESENT(FDCSPEED))
+drivers/block/ataflop.c: if (ATARIHW_PRESENT(FDCSPEED)) {
+drivers/block/ataflop.c: if (ATARIHW_PRESENT(FDCSPEED))
+drivers/block/ataflop.c: if (ATARIHW_PRESENT(EXTD_DMA)) {
+drivers/block/ataflop.c: paddr = ATARIHW_PRESENT(EXTD_DMA) ?
+drivers/block/ataflop.c: if (ATARIHW_PRESENT(EXTD_DMA))
+drivers/block/ataflop.c: if (ATARIHW_PRESENT( EXTD_DMA ))
+drivers/block/ataflop.c: if (ATARIHW_PRESENT(FDCSPEED)) {
+drivers/block/ataflop.c: addr = ATARIHW_PRESENT( EXTD_DMA ) ? ReqData : DMABuffer;
+drivers/block/ataflop.c: if (!ATARIHW_PRESENT( EXTD_DMA ))
+drivers/block/ataflop.c: if (ATARIHW_PRESENT( EXTD_DMA ))
+drivers/block/ataflop.c: if (ATARIHW_PRESENT( FDCSPEED ) || MACH_IS_MEDUSA)
+drivers/block/ataflop.c: if (ATARIHW_PRESENT(FDCSPEED))
+drivers/char/dsp56k.c: if(!MACH_IS_ATARI || !ATARIHW_PRESENT(DSP56K)) {
+drivers/char/nvram.c:#define CHECK_DRIVER_INIT() (MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK))
+drivers/ide/falconide.c: if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) {
+drivers/input/keyboard/atakbd.c: if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
+drivers/input/mouse/atarimouse.c: if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
+drivers/scsi/atari_scsi.c:#define IS_A_TT() ATARIHW_PRESENT(TT_SCSI)
+drivers/scsi/atari_scsi.c: (!ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(TT_SCSI)) ||
+drivers/scsi/atari_scsi.c: if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) {
+drivers/scsi/atari_scsi.c: if (MACH_IS_ATARI && ATARIHW_PRESENT(ST_SCSI) &&
+drivers/scsi/atari_scsi.c: !ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) {
+drivers/scsi/atari_scsi.c: atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000
+drivers/video/atafb.c: if (ATARIHW_PRESENT(PCM_8BIT)) {
+drivers/video/atafb.c: if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
+drivers/video/atafb.c: var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
+drivers/video/atafb.c: if (ATARIHW_PRESENT(EXTD_SHIFTER))
+drivers/video/atafb.c: if (ATARIHW_PRESENT(EXTD_SHIFTER))
+drivers/video/atafb.c: if (ATARIHW_PRESENT(PCM_8BIT)) {
+drivers/video/atafb.c: if (!ATARIHW_PRESENT(EXTD_SHIFTER))
+drivers/video/atafb.c: if (ATARIHW_PRESENT(EXTD_SHIFTER))
+drivers/video/atafb.c: (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
+drivers/video/atafb.c: if (ATARIHW_PRESENT(TT_SHIFTER)) {
+drivers/video/atafb.c: if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
+drivers/video/atafb.c: if (ATARIHW_PRESENT(STND_SHIFTER) ||
+drivers/video/atafb.c: ATARIHW_PRESENT(EXTD_SHIFTER)) {
+include/asm-m68k/atarihw.h:#define ATARIHW_PRESENT(name) (atari_hw_present.name)
+sound/oss/dmasound/dmasound_atari.c: if (MACH_IS_ATARI && ATARIHW_PRESENT(PCM_8BIT)) {
+sound/oss/dmasound/dmasound_atari.c: if (ATARIHW_PRESENT(CODEC)) {
+sound/oss/dmasound/dmasound_atari.c: } else if (ATARIHW_PRESENT(MICROWIRE)) {
+drivers/char/atari_scc.c: int escc = ATARIHW_PRESENT(ST_ESCC);
+drivers/char/atari_scc.c: if (!(ATARIHW_PRESENT(SCC) || ATARIHW_PRESENT(ST_ESCC)))
+drivers/char/atari_scc.c: if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
+---
+ arch/m68k/atari/platform.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- /dev/null
++++ b/arch/m68k/atari/platform.c
+@@ -0,0 +1,10 @@
++/*
++ * Copyright (C) 2007 Geert Uytterhoeven
++ *
++ * 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/platform_device.h>
++
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-rom-isa.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-rom-isa.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,421 @@
+Subject: [PATCH] m68k: Atari ROM port ISA adapter support
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+Atari ROM port ISA adapter support
+
+FIXME missing last hunk of original patch
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/Kconfig | 10 +++
+ arch/m68k/kernel/setup.c | 6 +
+ include/asm-m68k/io.h | 140 +++++++++++++++++++++++++++++++++++++++++++++-
+ include/asm-m68k/raw_io.h | 116 +++++++++++++++++++++++++++++++++++++-
+ 4 files changed, 268 insertions(+), 4 deletions(-)
+
+--- a/arch/m68k/Kconfig
++++ b/arch/m68k/Kconfig
+@@ -124,6 +124,16 @@ config ATARI
+ this kernel on an Atari, say Y here and browse the material
+ available in <file:Documentation/m68k>; otherwise say N.
+
++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 MAC
+ bool "Macintosh support"
+ select MMU_MOTOROLA if MMU
+--- a/arch/m68k/kernel/setup.c
++++ b/arch/m68k/kernel/setup.c
+@@ -372,6 +372,12 @@ void __init setup_arch(char **cmdline_p)
+ isa_sex = 1;
+ }
+ #endif
++#ifdef CONFIG_ATARI_ROM_ISA
++ if (MACH_IS_ATARI) {
++ isa_type = ISA_TYPE_ENEC;
++ isa_sex = 0;
++ }
++#endif
+ #endif
+ }
+
+--- a/include/asm-m68k/io.h
++++ b/include/asm-m68k/io.h
+@@ -80,9 +80,26 @@ extern unsigned long gg2_isa_base;
+ #endif
+ #endif /* AMIGA_PCMCIA */
+
++#ifdef CONFIG_ATARI_ROM_ISA
+
++#define enec_isa_read_base 0xfffa0000
++#define enec_isa_write_base 0xfffb0000
+
+-#ifdef CONFIG_ISA
++#define ENEC_ISA_IO_B(ioaddr) (enec_isa_read_base+((((unsigned long)(ioaddr))&0x1F)<<9))
++#define ENEC_ISA_IO_W(ioaddr) (enec_isa_read_base+((((unsigned long)(ioaddr))&0x1F)<<9))
++#define ENEC_ISA_MEM_B(madr) (enec_isa_read_base+((((unsigned long)(madr))&0x1F)<<9))
++#define ENEC_ISA_MEM_W(madr) (enec_isa_read_base+((((unsigned long)(madr))&0x1F)<<9))
++
++#ifndef MULTI_ISA
++#define MULTI_ISA 0
++#else
++#undef MULTI_ISA
++#define MULTI_ISA 1
++#endif
++#endif /* ATARI_ROM_ISA */
++
++
++#if defined(CONFIG_ISA) || defined(CONFIG_ATARI_ROM_ISA)
+
+ #if MULTI_ISA == 0
+ #undef MULTI_ISA
+@@ -91,6 +108,7 @@ extern unsigned long gg2_isa_base;
+ #define ISA_TYPE_Q40 (1)
+ #define ISA_TYPE_GG2 (2)
+ #define ISA_TYPE_AG (3)
++#define ISA_TYPE_ENEC (4)
+
+ #if defined(CONFIG_Q40) && !defined(MULTI_ISA)
+ #define ISA_TYPE ISA_TYPE_Q40
+@@ -104,6 +122,10 @@ extern unsigned long gg2_isa_base;
+ #define ISA_TYPE ISA_TYPE_GG2
+ #define ISA_SEX 0
+ #endif
++#if defined(CONFIG_ATARI_ROM_ISA) && !defined(MULTI_ISA)
++#define ISA_TYPE ISA_TYPE_ENEC
++#define ISA_SEX 0
++#endif
+
+ #ifdef MULTI_ISA
+ extern int isa_type;
+@@ -131,6 +153,9 @@ static inline u8 __iomem *isa_itb(unsign
+ #ifdef CONFIG_AMIGA_PCMCIA
+ case ISA_TYPE_AG: return (u8 __iomem *)AG_ISA_IO_B(addr);
+ #endif
++#ifdef CONFIG_ATARI_ROM_ISA
++ case ISA_TYPE_ENEC: return (u8 __iomem *)ENEC_ISA_IO_B(addr);
++#endif
+ default: return NULL; /* avoid warnings, just in case */
+ }
+ }
+@@ -147,6 +172,9 @@ static inline u16 __iomem *isa_itw(unsig
+ #ifdef CONFIG_AMIGA_PCMCIA
+ case ISA_TYPE_AG: return (u16 __iomem *)AG_ISA_IO_W(addr);
+ #endif
++#ifdef CONFIG_ATARI_ROM_ISA
++ case ISA_TYPE_ENEC: return (u16 __iomem *)ENEC_ISA_IO_W(addr);
++#endif
+ default: return NULL; /* avoid warnings, just in case */
+ }
+ }
+@@ -173,6 +201,9 @@ static inline u8 __iomem *isa_mtb(unsign
+ #ifdef CONFIG_AMIGA_PCMCIA
+ case ISA_TYPE_AG: return (u8 __iomem *)addr;
+ #endif
++#ifdef CONFIG_ATARI_ROM_ISA
++ case ISA_TYPE_ENEC: return (u8 __iomem *)ENEC_ISA_MEM_B(addr);
++#endif
+ default: return NULL; /* avoid warnings, just in case */
+ }
+ }
+@@ -189,6 +220,9 @@ static inline u16 __iomem *isa_mtw(unsig
+ #ifdef CONFIG_AMIGA_PCMCIA
+ case ISA_TYPE_AG: return (u16 __iomem *)addr;
+ #endif
++#ifdef CONFIG_ATARI_ROM_ISA
++ case ISA_TYPE_ENEC: return (u16 __iomem *)ENEC_ISA_MEM_W(addr);
++#endif
+ default: return NULL; /* avoid warnings, just in case */
+ }
+ }
+@@ -210,6 +244,34 @@ static inline u16 __iomem *isa_mtw(unsig
+ (ISA_SEX ? out_be16(isa_mtw((unsigned long)(p)),(val)) \
+ : out_le16(isa_mtw((unsigned long)(p)),(val)))
+
++#ifdef CONFIG_ATARI_ROM_ISA
++#define isa_rom_inb(port) rom_in_8(isa_itb(port))
++#define isa_rom_inw(port) \
++ (ISA_SEX ? rom_in_be16(isa_itw(port)) \
++ : rom_in_le16(isa_itw(port)))
++#define isa_rom_inl(port) \
++ (ISA_SEX ? rom_in_be32(isa_itw(port)) \
++ : rom_in_le32(isa_itw(port)))
++
++#define isa_rom_outb(val, port) rom_out_8(isa_itb(port), (val))
++#define isa_rom_outw(val, port) \
++ (ISA_SEX ? rom_out_be16(isa_itw(port), (val)) \
++ : rom_out_le16(isa_itw(port), (val)))
++#define isa_rom_outl(val, port) \
++ (ISA_SEX ? rom_out_be32(isa_itw(port), (val)) \
++ : rom_out_le32(isa_itw(port), (val)))
++
++#define isa_rom_readb(p) rom_in_8(isa_mtb((unsigned long)(p)))
++#define isa_rom_readw(p) \
++ (ISA_SEX ? rom_in_be16(isa_mtw((unsigned long)(p))) \
++ : rom_in_le16(isa_mtw((unsigned long)(p))))
++
++#define isa_rom_writeb(val, p) rom_out_8(isa_mtb((unsigned long)(p)), (val))
++#define isa_rom_writew(val, p) \
++ (ISA_SEX ? rom_out_be16(isa_mtw((unsigned long)(p)), (val)) \
++ : rom_out_le16(isa_mtw((unsigned long)(p)), (val)))
++#endif /* CONFIG_ATARI_ROM_ISA */
++
+ static inline void isa_delay(void)
+ {
+ switch(ISA_TYPE)
+@@ -223,6 +285,9 @@ static inline void isa_delay(void)
+ #ifdef CONFIG_AMIGA_PCMCIA
+ case ISA_TYPE_AG: break;
+ #endif
++#ifdef CONFIG_ATARI_ROM_ISA
++ case ISA_TYPE_ENEC: break;
++#endif
+ default: break; /* avoid warnings */
+ }
+ }
+@@ -254,6 +319,39 @@ static inline void isa_delay(void)
+ raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
+
+
++#ifdef CONFIG_ATARI_ROM_ISA
++#define isa_rom_inb_p(p) ({ u8 _v = isa_rom_inb(p); isa_delay(); _v; })
++#define isa_rom_inw_p(p) ({ u16 _v = isa_rom_inw(p); isa_delay(); _v; })
++#define isa_rom_inl_p(p) ({ u32 _v = isa_rom_inl(p); isa_delay(); _v; })
++#define isa_rom_outb_p(v, p) ({ isa_rom_outb((v), (p)); isa_delay(); })
++#define isa_rom_outw_p(v, p) ({ isa_rom_outw((v), (p)); isa_delay(); })
++#define isa_rom_outl_p(v, p) ({ isa_rom_outl((v), (p)); isa_delay(); })
++
++#define isa_rom_insb(port, buf, nr) raw_rom_insb(isa_itb(port), (u8 *)(buf), (nr))
++
++#define isa_rom_insw(port, buf, nr) \
++ (ISA_SEX ? raw_rom_insw(isa_itw(port), (u16 *)(buf), (nr)) : \
++ raw_rom_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
++
++#define isa_rom_insl(port, buf, nr) \
++ (ISA_SEX ? raw_rom_insl(isa_itw(port), (u32 *)(buf), (nr)) : \
++ raw_rom_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
++
++#define isa_rom_outsb(port, buf, nr) raw_rom_outsb(isa_itb(port), (u8 *)(buf), (nr))
++
++#define isa_rom_outsw(port, buf, nr) \
++ (ISA_SEX ? raw_rom_outsw(isa_itw(port), (u16 *)(buf), (nr)) : \
++ raw_rom_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
++
++#define isa_rom_outsl(port, buf, nr) \
++ (ISA_SEX ? raw_rom_outsl(isa_itw(port), (u32 *)(buf), (nr)) : \
++ raw_rom_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
++#endif /* CONFIG_ATARI_ROM_ISA */
++
++#endif /* CONFIG_ISA || CONFIG_ATARI_ROM_ISA */
++
++
++#if defined(CONFIG_ISA) && !defined(CONFIG_ATARI_ROM_ISA)
+ #define inb isa_inb
+ #define inb_p isa_inb_p
+ #define outb isa_outb
+@@ -276,9 +374,45 @@ static inline void isa_delay(void)
+ #define readw isa_readw
+ #define writeb isa_writeb
+ #define writew isa_writew
++#endif /* CONFIG_ISA && !CONFIG_ATARI_ROM_ISA */
+
+-#else /* CONFIG_ISA */
++#ifdef CONFIG_ATARI_ROM_ISA
++/*
++ * kernel with both ROM port ISA and IDE compiled in, those have
++ * conflicting defs for in/out. Simply consider port < 1024
++ * ROM port ISA and everything else regular ISA for IDE. read,write not defined
++ * in this case
++ */
++#define inb(port) ((port) < 1024 ? isa_rom_inb(port) : in_8(port))
++#define inb_p(port) ((port) < 1024 ? isa_rom_inb_p(port) : in_8(port))
++#define inw(port) ((port) < 1024 ? isa_rom_inw(port) : in_le16(port))
++#define inw_p(port) ((port) < 1024 ? isa_rom_inw_p(port) : in_le16(port))
++#define inl(port) ((port) < 1024 ? isa_rom_inl(port) : in_le32(port))
++#define inl_p(port) ((port) < 1024 ? isa_rom_inl_p(port) : in_le32(port))
++
++#define outb(val, port) ((port) < 1024 ? isa_rom_outb((val), (port)) : out_8((port), (val)))
++#define outb_p(val, port) ((port) < 1024 ? isa_rom_outb_p((val), (port)) : out_8((port), (val)))
++#define outw(val, port) ((port) < 1024 ? isa_rom_outw((val), (port)) : out_le16((port), (val)))
++#define outw_p(val, port) ((port) < 1024 ? isa_rom_outw_p((val), (port)) : out_le16((port), (val)))
++#define outl(val, port) ((port) < 1024 ? isa_rom_outl((val), (port)) : out_le32((port), (val)))
++#define outl_p(val, port) ((port) < 1024 ? isa_rom_outl_p((val), (port)) : out_le32((port), (val)))
++
++#define insb isa_rom_insb
++#define insw isa_rom_insw
++#define insl isa_rom_insl
++#define outsb isa_rom_outsb
++#define outsw isa_rom_outsw
++#define outsl isa_rom_outsl
++
++#define readb isa_readb
++#define readw isa_readw
++#define writeb isa_writeb
++#define writew isa_writew
++#define readsl raw_insl
++#define writesl raw_outsl
++#endif /* CONFIG_ATARI_ROM_ISA */
+
++#if !defined(CONFIG_ISA) && !defined(CONFIG_ATARI_ROM_ISA)
+ /*
+ * We need to define dummy functions for GENERIC_IOMAP support.
+ */
+@@ -306,7 +440,7 @@ static inline void isa_delay(void)
+ #define readw(addr) in_le16(addr)
+ #define writew(val,addr) out_le16((addr),(val))
+
+-#endif /* CONFIG_ISA */
++#endif /* !CONFIG_ISA && !CONFIG_ATARI_ROM_ISA */
+
+ #define readl(addr) in_le32(addr)
+ #define writel(val,addr) out_le32((addr),(val))
+--- a/include/asm-m68k/raw_io.h
++++ b/include/asm-m68k/raw_io.h
+@@ -10,7 +10,7 @@
+
+ #ifdef __KERNEL__
+
+-#include <asm/types.h>
++#include <asm/byteorder.h>
+
+
+ /* Values for nocacheflag and cmode */
+@@ -60,6 +60,46 @@ extern void __iounmap(void *addr, unsign
+ #define __raw_writew(val,addr) out_be16((addr),(val))
+ #define __raw_writel(val,addr) out_be32((addr),(val))
+
++/*
++ * Atari ROM port (cartridge port) ISA adapter, used for the EtherNEC NE2000
++ * network card driver.
++ * The ISA adapter connects address lines A9-A13 to ISA address lines A0-A4,
++ * and hardwires the rest of the ISA addresses for a base address of 0x300.
++ *
++ * Data lines D8-D15 are connected to ISA data lines D0-D7 for reading.
++ * For writes, address lines A1-A8 are latched to ISA data lines D0-D7
++ * (meaning the bit pattern on A1-A8 can be read back as byte).
++ *
++ * Reads and writes are byte only.
++ */
++
++#if defined(CONFIG_ATARI_ROM_ISA)
++#define rom_in_8(addr) \
++ ({ u16 __v = (*(__force volatile u16 *) (addr)); __v >>= 8; __v; })
++#define rom_in_be16(addr) \
++ ({ u16 __v = (*(__force volatile u16 *) (addr)); __v >>= 8; __v; })
++#define rom_in_be32(addr) \
++ ({ u32 __v = (*(__force volatile u32 *) (addr)); __v >>= 8; __v; })
++#define rom_in_le16(addr) \
++ ({ u16 __v = le16_to_cpu(*(__force volatile u16 *) (addr)); __v >>= 8; __v; })
++#define rom_in_le32(addr) \
++ ({ u32 __v = le32_to_cpu(*(__force volatile u32 *) (addr)); __v >>= 8; __v; })
++
++#define rom_out_8(addr, b) ({u8 __w, __v = (b); __w = ((*(__force volatile u8 *) ((addr) + 0x10000 + (__v<<1)))); })
++#define rom_out_be16(addr, w) ({u16 __w, __v = (w); __w = ((*(__force volatile u16 *) ((addr) + 0x10000 + (__v<<1)))); })
++#define rom_out_be32(addr, l) ({u32 __w, __v = (l); __w = ((*(__force volatile u32 *) ((addr) + 0x10000 + (__v<<1)))); })
++#define rom_out_le16(addr, w) ({u16 __w, __v = cpu_to_le16(w); __w = ((*(__force volatile u16 *) ((addr) + 0x10000 + (__v<<1)))); })
++#define rom_out_le32(addr, l) ({u32 __w, __v = cpu_to_le32(l); __w = ((*(__force volatile u32 *) ((addr) + 0x10000 + (__v<<1)))); })
++
++#define raw_rom_inb rom_in_8
++#define raw_rom_inw rom_in_be16
++#define raw_rom_inl rom_in_be32
++
++#define raw_rom_outb(val, port) rom_out_8((port), (val))
++#define raw_rom_outw(val, port) rom_out_be16((port), (val))
++#define raw_rom_outl(val, port) rom_out_be32((port), (val))
++#endif /* CONFIG_ATARI_ROM_ISA */
++
+ static inline void raw_insb(volatile u8 __iomem *port, u8 *buf, unsigned int len)
+ {
+ unsigned int i;
+@@ -342,6 +382,80 @@ static inline void raw_outsw_swapw(volat
+ : "d0", "a0", "a1", "d6");
+ }
+
++
++#if defined(CONFIG_ATARI_ROM_ISA)
++static inline void raw_rom_insb(volatile u8 __iomem *port, u8 *buf, unsigned int len)
++{
++ unsigned int i;
++
++ for (i = 0; i < len; i++)
++ *buf++ = rom_in_8(port);
++}
++
++static inline void raw_rom_outsb(volatile u8 __iomem *port, const u8 *buf,
++ unsigned int len)
++{
++ unsigned int i;
++
++ for (i = 0; i < len; i++)
++ rom_out_8(port, *buf++);
++}
++
++static inline void raw_rom_insw(volatile u16 __iomem *port, u16 *buf,
++ unsigned int nr)
++{
++ unsigned int i;
++
++ for (i = 0; i < nr; i++)
++ *buf++ = rom_in_be16(port);
++}
++
++static inline void raw_rom_outsw(volatile u16 __iomem *port, const u16 *buf,
++ unsigned int nr)
++{
++ unsigned int i;
++
++ for (i = 0; i < nr; i++)
++ rom_out_be16(port, *buf++);
++}
++
++static inline void raw_rom_insw_swapw(volatile u16 __iomem *port, u16 *buf,
++ unsigned int nr)
++{
++ unsigned int i;
++
++ for (i = 0; i < nr; i++)
++ *buf++ = rom_in_le16(port);
++}
++
++static inline void raw_rom_outsw_swapw(volatile u16 __iomem *port, const u16 *buf,
++ unsigned int nr)
++{
++ unsigned int i;
++
++ for (i = 0; i < nr; i++)
++ rom_out_le16(port, *buf++);
++}
++
++static inline void raw_rom_insl(volatile u16 __iomem *port, u32 *buf,
++ unsigned int nr)
++{
++ unsigned int i;
++
++ for (i = 0; i < nr; i++)
++ *buf++ = rom_in_be32(port);
++}
++
++static inline void raw_rom_outsl(volatile u16 __iomem *port, const u32 *buf,
++ unsigned int nr)
++{
++ unsigned int i;
++
++ for (i = 0; i < nr; i++)
++ rom_out_be32(port, *buf++);
++}
++#endif /* CONFIG_ATARI_ROM_ISA */
++
+ #endif /* __KERNEL__ */
+
+ #endif /* _RAW_IO_H */
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-break_ctl.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-break_ctl.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,41 @@
+Subject: [PATCH] m68k: Atari SCC serial driver break_ctl update
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Update for commit 9e98966c7bb94355689478bc84cc3e0c190f977e ("tty: rework break
+handling"), which made break_ctl return an error code.
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/char/atari_scc.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/atari_scc.c
++++ b/drivers/char/atari_scc.c
+@@ -89,7 +89,7 @@ static irqreturn_t scc_rx_int(int irq, v
+ static irqreturn_t scc_stat_int(int irq, void *data);
+ static irqreturn_t scc_spcond_int(int irq, void *data);
+ static void scc_setsignals(struct scc_port *port, int dtr, int rts);
+-static void scc_break_ctl(struct tty_struct *tty, int break_state);
++static int scc_break_ctl(struct tty_struct *tty, int break_state);
+
+ static struct tty_driver *scc_driver;
+
+@@ -1385,7 +1385,7 @@ static int scc_ioctl(struct tty_struct *
+ }
+
+
+-static void scc_break_ctl(struct tty_struct *tty, int break_state)
++static int scc_break_ctl(struct tty_struct *tty, int break_state)
+ {
+ struct scc_port *port = (struct scc_port *)tty->driver_data;
+ unsigned long flags;
+@@ -1396,6 +1396,8 @@ static void scc_break_ctl(struct tty_str
+ SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, break_state ? TCR_SEND_BREAK : 0);
+ local_irq_restore(flags);
+ pr_debug("SCC: break ctl done!\n");
++
++ return 0;
+ }
+
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-checkpatch.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-checkpatch.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,1324 @@
+Subject: [PATCH] m68k: Atari SCC serial driver checkpatch cleanups
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/atari/ataints.c | 2
+ arch/m68k/atari/debug.c | 6
+ drivers/char/atari_scc.c | 570 +++++++++++++++++----------------------------
+ include/asm-m68k/atarihw.h | 3
+ 4 files changed, 232 insertions(+), 349 deletions(-)
+
+--- a/arch/m68k/atari/ataints.c
++++ b/arch/m68k/atari/ataints.c
+@@ -318,8 +318,6 @@ __ALIGN_STR "\n\t"
+
+ extern void atari_microwire_cmd(int cmd);
+
+-extern int atari_SCC_reset_done;
+-
+ static int atari_startup_irq(unsigned int irq)
+ {
+ m68k_irq_startup(irq);
+--- a/arch/m68k/atari/debug.c
++++ b/arch/m68k/atari/debug.c
+@@ -20,6 +20,11 @@
+ #include <asm/atarihw.h>
+ #include <asm/atariints.h>
+
++/*
++ * Flags to indicate one of the serial ports has already been initialized by the
++ * serial debug driver. We may want to hold off reinitializing ...
++ */
++
+ /* Flag that Modem1 port is already initialized and used */
+ int atari_SCC_init_done;
+ EXPORT_SYMBOL(atari_SCC_init_done);
+@@ -206,7 +211,6 @@ static void __init atari_init_mfp_port(i
+
+ static void __init atari_init_scc_port(int cflag)
+ {
+- extern int atari_SCC_reset_done;
+ static int clksrc_table[9] =
+ /* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
+ { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
+--- a/drivers/char/atari_scc.c
++++ b/drivers/char/atari_scc.c
+@@ -22,7 +22,7 @@
+
+ #include <linux/module.h>
+ #include <linux/kdev_t.h>
+-#include <asm/io.h>
++#include <linux/io.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/ioport.h>
+@@ -39,14 +39,14 @@
+ #include <linux/miscdevice.h>
+ #include <linux/console.h>
+ #include <linux/init.h>
++#include <linux/uaccess.h>
++#include <linux/generic_serial.h>
++
+ #include <asm/setup.h>
+-#include <asm/uaccess.h>
+ #include <asm/bootinfo.h>
+-
+ #include <asm/atarihw.h>
+ #include <asm/atariints.h>
+
+-#include <linux/generic_serial.h>
+ #include "scc.h"
+
+ #define CONFIG_TT_SCC 1
+@@ -61,7 +61,7 @@
+ static unsigned char scc_shadow[2][16];
+
+ /* Location to access for SCC register access delay */
+-static volatile unsigned char *scc_del = NULL;
++static volatile unsigned char *scc_del;
+
+ /* To keep track of STATUS_REG state for detection of Ext/Status int source */
+ static unsigned char scc_last_status_reg[2];
+@@ -95,16 +95,6 @@ static struct tty_driver *scc_driver;
+
+ static struct scc_port scc_ports[2];
+
+-/*
+- * Flags to indicate one of the serial ports has already been initialized by the
+- * serial debug driver. We may want to hold off reinitializing ...
+- */
+-
+-/* Flag that Modem1 port is already initialized and used */
+-extern int atari_SCC_init_done;
+-/* Can be set somewhere, if a SCC master reset has already be done and should
+- * not be repeated; used by kgdb */
+-extern int atari_SCC_reset_done;
+
+ /*---------------------------------------------------------------------------
+ * Interface from generic_serial.c back here
+@@ -144,17 +134,17 @@ static struct tty_operations scc_ops = {
+
+ /* BRG values for the standard speeds and the various clock sources */
+
+-typedef struct {
+- unsigned clksrc; /* clock source to use or -1 for not possible */
+- unsigned div; /* divisor: 1, 2 and 4 correspond to
+- * direct 1:16, 1:32 and 1:64 modes,
+- * divisors >= 4 yield a BRG value of
+- * div/2-2 (in 1:16 mode)
+- */
+-} BAUD_ENTRY;
++struct baud_entry {
++ unsigned clksrc; /* clock source to use or -1 for not possible */
++ unsigned div; /* divisor: 1, 2 and 4 correspond to
++ * direct 1:16, 1:32 and 1:64 modes,
++ * divisors >= 4 yield a BRG value of
++ * div/2-2 (in 1:16 mode)
++ */
++};
+
+ /* A pointer for each channel to the current baud table */
+-static BAUD_ENTRY *scc_baud_table[2];
++static struct baud_entry *scc_baud_table[2];
+
+ /* Baud table format:
+ *
+@@ -174,7 +164,7 @@ static BAUD_ENTRY *scc_baud_table[2];
+ * channel A and for both channels on the Mega STE/Falcon. (TRxC is unused)
+ */
+
+-static BAUD_ENTRY bdtab_norm[20] = {
++static struct baud_entry bdtab_norm[20] = {
+ /* B0 */ { 0, 0 },
+ /* B50 */ { CLK_RTxC, 4590 },
+ /* B75 */ { CLK_RTxC, 3060 },
+@@ -200,7 +190,7 @@ static BAUD_ENTRY bdtab_norm[20] = {
+ /* This is a special table for the TT channel B with 307.2 kHz at RTxC
+ * and 2.4576 MHz at TRxC
+ */
+-static BAUD_ENTRY bdtab_TTChB[20] = {
++static struct baud_entry bdtab_TTChB[20] = {
+ /* B0 */ { 0, 0 },
+ /* B50 */ { CLK_RTxC, 384 },
+ /* B75 */ { CLK_RTxC, 256 },
+@@ -217,8 +207,10 @@ static BAUD_ENTRY bdtab_TTChB[20] = {
+ /* B9600 */ { CLK_RTxC, 2 },
+ /* B19200 */ { CLK_RTxC, 1 },
+ /* B38400 */ { CLK_TRxC, 4 },
+- /* B57600 */ { CLK_TRxC, 2 }, /* 57600 is not possible, use 76800 instead */
+- /* B115200 */ { CLK_TRxC, 1 }, /* 115200 is not possible, use 153600 instead */
++ /* 57600 is not possible, use 76800 instead */
++ /* B57600 */ { CLK_TRxC, 2 },
++ /* 115200 is not possible, use 153600 instead */
++ /* B115200 */ { CLK_TRxC, 1 },
+ /* B230400 */ { 0, 0 }, /* #18 spd_shi: Impossible */
+ /* B460800 */ { 0, 0 } /* #19 spd_warp: Impossible */
+ };
+@@ -248,8 +240,9 @@ static int scc_init_drivers(void)
+
+ tty_set_operations(scc_driver, &scc_ops);
+
+- if ((error = tty_register_driver(scc_driver))) {
+- printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n",
++ error = tty_register_driver(scc_driver);
++ if (error) {
++ pr_err("scc: Couldn't register scc driver, error = %d\n",
+ error);
+ put_tty_driver(scc_driver);
+ return 1;
+@@ -287,23 +280,19 @@ static int atari_tt_scc_init(void)
+ {
+ struct scc_port *port;
+
+- printk(KERN_INFO "SCC: Atari TT Serial Driver\n");
++ pr_info("SCC: Atari TT Serial Driver\n");
+ /* FIXME channel A may be switchable between modem and LAN port */
+ /* Init channel A */
+ if (atari_SCC_init_done)
+- printk(KERN_INFO "SCC: already initialized, expect trouble!\n");
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: init channel A\n");
+-#endif
++ pr_warning("SCC: already initialized, expect trouble!\n");
++ pr_debug("SCC: init channel A\n");
+ port = &scc_ports[0];
+ port->channel = CHANNEL_A;
+ port->ctrlp = (volatile unsigned char *)&scc.cha_a_ctrl;
+ port->datap = port->ctrlp + 1;
+ port->port_a = &scc_ports[0];
+ port->port_b = &scc_ports[1];
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: request channel A irqs, port = %p\n", port);
+-#endif
++ pr_debug("SCC: request channel A irqs, port = %p\n", port);
+ request_irq(IRQ_SCCA_TX, scc_tx_int, IRQ_TYPE_PRIO, "SCC-A TX", port);
+ request_irq(IRQ_SCCA_STAT, scc_stat_int, IRQ_TYPE_PRIO,
+ "SCC-A status", port);
+@@ -312,14 +301,13 @@ static int atari_tt_scc_init(void)
+ "SCC-A special cond", port);
+ {
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: read SCC status\n");
+-#endif
+- /* on the first access, read status register to reset internal pointers */
++ pr_debug("SCC: read SCC status\n");
++ /*
++ * on the first access, read status register to reset internal
++ * pointers
++ */
+ SCCread(STATUS_REG);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: reset SCC\n");
+-#endif
++ pr_debug("SCC: reset SCC\n");
+ /* FIXME: master reset, once only */
+ SCCwrite(MASTER_INT_CTRL, MIC_HARD_RESET);
+ udelay(40);
+@@ -338,18 +326,14 @@ static int atari_tt_scc_init(void)
+
+ if (!atari_SCC_init_done) {
+ /* Init channel B */
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: init channel B\n");
+-#endif
++ pr_debug("SCC: init channel B\n");
+ port = &scc_ports[1];
+ port->channel = CHANNEL_B;
+ port->ctrlp = (volatile unsigned char *)&scc.cha_b_ctrl;
+ port->datap = port->ctrlp + 1;
+ port->port_a = &scc_ports[0];
+ port->port_b = &scc_ports[1];
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: request channel B irqs, port = %p\n", port);
+-#endif
++ pr_debug("SCC: request channel B irqs, port = %p\n", port);
+ request_irq(IRQ_SCCB_TX, scc_tx_int, IRQ_TYPE_PRIO,
+ "SCC-B TX", port);
+ request_irq(IRQ_SCCB_STAT, scc_stat_int, IRQ_TYPE_PRIO,
+@@ -382,13 +366,9 @@ static int atari_tt_scc_init(void)
+ scc_baud_table[CHANNEL_B] = bdtab_TTChB;
+
+ /* Initialise the tty driver structures and register */
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: scc_init_portstructs()\n");
+-#endif
++ pr_debug("SCC: scc_init_portstructs()\n");
+ scc_init_portstructs();
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: scc_init_drivers()\n");
+-#endif
++ pr_debug("SCC: scc_init_drivers()\n");
+ scc_init_drivers();
+
+ return 0;
+@@ -401,9 +381,9 @@ static int atari_falcon_scc_init(void)
+ {
+ struct scc_port *port;
+
+- printk(KERN_INFO "SCC: Atari Falcon Serial Driver\n");
++ pr_info("SCC: Atari Falcon Serial Driver\n");
+ if (atari_SCC_init_done)
+- printk(KERN_INFO "SCC: already initialized, expect trouble!\n");
++ pr_warning("SCC: already initialized, expect trouble!\n");
+
+ /* Init channel A */
+ port = &scc_ports[0];
+@@ -421,7 +401,10 @@ static int atari_falcon_scc_init(void)
+ {
+ SCC_ACCESS_INIT(port);
+
+- /* on the first access, read status register to reset internal pointers */
++ /*
++ * on the first access, read status register to reset internal
++ * pointers
++ */
+ SCCread(STATUS_REG);
+
+ /* FIXME: master reset, once only */
+@@ -476,15 +459,15 @@ static int atari_falcon_scc_init(void)
+ static int atari_st_scc_init(void)
+ {
+ struct scc_port *port;
+-
+ int escc = ATARIHW_PRESENT(ST_ESCC);
+
+- printk(KERN_INFO "SCC: Atari MegaST/E Serial Driver\n");
++ pr_info("SCC: Atari MegaST/E Serial Driver\n");
+ /* FIXME: ports reversed logic */
+ /* Init channel A */
+ port = &scc_ports[1];
+ port->channel = CHANNEL_A;
+- port->ctrlp = (volatile unsigned char *)(escc ? &st_escc.cha_a_ctrl : &scc.cha_a_ctrl);
++ port->ctrlp = (volatile unsigned char *)(escc ? &st_escc.cha_a_ctrl
++ : &scc.cha_a_ctrl);
+ port->datap = port->ctrlp + 4;
+ port->port_a = &scc_ports[1];
+ port->port_b = &scc_ports[0];
+@@ -497,7 +480,10 @@ static int atari_st_scc_init(void)
+ {
+ SCC_ACCESS_INIT(port);
+
+- /* on the first access, read status register to reset internal pointers */
++ /*
++ * on the first access, read status register to reset internal
++ * pointers
++ */
+ SCCread(STATUS_REG);
+
+ /* FIXME: master reset, once only */
+@@ -516,7 +502,8 @@ static int atari_st_scc_init(void)
+ /* Init channel B */
+ port = &scc_ports[0];
+ port->channel = CHANNEL_B;
+- port->ctrlp = (volatile unsigned char *)(escc ? &st_escc.cha_b_ctrl : &scc.cha_b_ctrl);
++ port->ctrlp = (volatile unsigned char *)(escc ? &st_escc.cha_b_ctrl
++ : &scc.cha_b_ctrl);
+ port->datap = port->ctrlp + 4;
+ port->port_a = &scc_ports[0];
+ port->port_b = &scc_ports[1];
+@@ -550,7 +537,7 @@ static int atari_st_scc_init(void)
+ int atari_scc_init(void)
+ {
+ int res = -ENODEV;
+- static int called = 0;
++ static int called;
+
+ if (called)
+ return res;
+@@ -582,18 +569,14 @@ void atari_scc_cleanup(void)
+
+ tty_unregister_driver(scc_driver);
+ port = &scc_ports[0];
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: free channel A irqs, port = %p\n", port);
+-#endif
++ pr_debug("SCC: free channel A irqs, port = %p\n", port);
+ free_irq(IRQ_SCCA_TX, port);
+ free_irq(IRQ_SCCA_STAT, port);
+ free_irq(IRQ_SCCA_RX, port);
+ free_irq(IRQ_SCCA_SPCOND, port);
+
+ port = &scc_ports[1];
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: free channel A irqs, port = %p\n", port);
+-#endif
++ pr_debug("SCC: free channel A irqs, port = %p\n", port);
+ free_irq(IRQ_SCCB_TX, port);
+ free_irq(IRQ_SCCB_STAT, port);
+ free_irq(IRQ_SCCB_RX, port);
+@@ -613,13 +596,12 @@ static irqreturn_t scc_rx_int(int irq, v
+ unsigned char ch;
+ struct scc_port *port = data;
+ struct tty_struct *tty = port->gs.tty;
++
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: rx_int ...\n");
+-#endif
++ pr_debug("SCC: rx_int ...\n");
+ ch = SCCread_NB(RX_DATA_REG);
+ if (!tty) {
+- printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
++ pr_warning("scc_rx_int with NULL tty!\n");
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+ return IRQ_HANDLED;
+ }
+@@ -633,9 +615,11 @@ static irqreturn_t scc_rx_int(int irq, v
+ tty->flip.count++;
+ }
+ #endif
+- /* Check if another character is already ready; in that case, the
+- * spcond_int() function must be used, because this character may have an
+- * error condition that isn't signalled by the interrupt vector used!
++ /*
++ * Check if another character is already ready; in that case, the
++ * spcond_int() function must be used, because this character may have
++ * an * error condition that isn't signalled by the interrupt vector
++ * used!
+ */
+ if (SCCread(INT_PENDING_REG) &
+ (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
+@@ -646,9 +630,7 @@ static irqreturn_t scc_rx_int(int irq, v
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+
+ tty_flip_buffer_push(tty);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: rx_int done\n");
+-#endif
++ pr_debug("SCC: rx_int done\n");
+ return IRQ_HANDLED;
+ }
+
+@@ -661,11 +643,9 @@ static irqreturn_t scc_spcond_int(int ir
+ int int_pending_mask = port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX;
+
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: spcond_int ...\n");
+-#endif
++ pr_debug("SCC: spcond_int ...\n");
+ if (!tty) {
+- printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
++ pr_warning("scc_spcond_int with NULL tty!\n");
+ SCCwrite(COMMAND_REG, CR_ERROR_RESET);
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+ return IRQ_HANDLED;
+@@ -704,9 +684,7 @@ static irqreturn_t scc_spcond_int(int ir
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+
+ tty_flip_buffer_push(tty);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: spcond_int done\n");
+-#endif
++ pr_debug("SCC: spcond_int done\n");
+ return IRQ_HANDLED;
+ }
+
+@@ -724,12 +702,11 @@ static void scc_ri_int(int irq, void *da
+ static irqreturn_t scc_tx_int(int irq, void *data)
+ {
+ struct scc_port *port = data;
++
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: tx_int irq %d port %p ...\n", irq, data);
+-#endif
++ pr_debug("SCC: tx_int irq %d port %p ...\n", irq, data);
+ if (!port->gs.tty) {
+- printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
++ pr_warning("scc_tx_int with NULL tty!\n");
+ SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+ SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+@@ -737,50 +714,40 @@ static irqreturn_t scc_tx_int(int irq, v
+ }
+ while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) {
+ if (port->x_char) {
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: tx_int writing char %c\n",
+- port->x_char);
+-#endif
++ pr_debug("SCC: tx_int writing char %c\n", port->x_char);
+ SCCwrite(TX_DATA_REG, port->x_char);
+ port->x_char = 0;
+ } else if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
+ port->gs.tty->hw_stopped) {
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: nothing to do!\n");
+-#endif
++ pr_debug("SCC: nothing to do!\n");
+ break;
+ } else {
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: tx_int writing buf %c\n",
+- port->gs.xmit_buf[port->gs.xmit_tail]);
+-#endif
+- SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]);
+- port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1);
++ pr_debug("SCC: tx_int writing buf %c\n",
++ port->gs.xmit_buf[port->gs.xmit_tail]);
++ SCCwrite(TX_DATA_REG,
++ port->gs.xmit_buf[port->gs.xmit_tail++]);
++ port->gs.xmit_tail = port->gs.xmit_tail &
++ (SERIAL_XMIT_SIZE-1);
+ if (--port->gs.xmit_cnt <= 0)
+ break;
+ }
+ }
+ if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
+ port->gs.tty->hw_stopped) {
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: nothing to do, disabling int\n");
+-#endif
++ pr_debug("SCC: nothing to do, disabling int\n");
+ /* disable tx interrupts */
+ SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+- SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); /* disable tx_int on next tx underrun? */
++ /* disable tx_int on next tx underrun? */
++ SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
+ port->gs.flags &= ~GS_TX_INTEN;
+ }
+ if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) {
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: waking up tty!\n");
+-#endif
++ pr_debug("SCC: waking up tty!\n");
+ tty_wakeup(port->gs.tty);
+ }
+
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: tx_int done\n");
+-#endif
++ pr_debug("SCC: tx_int done\n");
+ return IRQ_HANDLED;
+ }
+
+@@ -790,10 +757,9 @@ static irqreturn_t scc_stat_int(int irq,
+ struct scc_port *port = data;
+ unsigned channel = port->channel;
+ unsigned char last_sr, sr, changed;
++
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: stat_int ...\n");
+-#endif
++ pr_debug("SCC: stat_int ...\n");
+ last_sr = scc_last_status_reg[channel];
+ sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG);
+ changed = last_sr ^ sr;
+@@ -811,13 +777,11 @@ static irqreturn_t scc_stat_int(int irq,
+ }
+ }
+
+- // FIXME: CTS and DSR status changes?
++ /* FIXME: CTS and DSR status changes? */
+
+ SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: stat_int done\n");
+-#endif
++ pr_debug("SCC: stat_int done\n");
+ return IRQ_HANDLED;
+ }
+
+@@ -830,17 +794,14 @@ static void scc_disable_tx_interrupts(vo
+ {
+ struct scc_port *port = ptr;
+ unsigned long flags;
++
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: disable_tx_int ...\n");
+-#endif
++ pr_debug("SCC: disable_tx_int ...\n");
+ local_irq_save(flags);
+ SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+ port->gs.flags &= ~GS_TX_INTEN;
+ local_irq_restore(flags);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: disable_tx_int done!\n");
+-#endif
++ pr_debug("SCC: disable_tx_int done!\n");
+ }
+
+
+@@ -850,17 +811,13 @@ static void scc_enable_tx_interrupts(voi
+ unsigned long flags;
+
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: enable_tx_int ...\n");
+-#endif
++ pr_debug("SCC: enable_tx_int ...\n");
+ local_irq_save(flags);
+ SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
+ /* restart the transmitter */
+ scc_tx_int(0, port);
+ local_irq_restore(flags);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: enable_tx_int done!\n");
+-#endif
++ pr_debug("SCC: enable_tx_int done!\n");
+ }
+
+
+@@ -870,16 +827,12 @@ static void scc_disable_rx_interrupts(vo
+ unsigned long flags;
+
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: disable_rx_int ...\n");
+-#endif
++ pr_debug("SCC: disable_rx_int ...\n");
+ local_irq_save(flags);
+ SCCmod(INT_AND_DMA_REG,
+ ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);
+ local_irq_restore(flags);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: disable_rx_int done!\n");
+-#endif
++ pr_debug("SCC: disable_rx_int done!\n");
+ }
+
+
+@@ -889,16 +842,12 @@ static void scc_enable_rx_interrupts(voi
+ unsigned long flags;
+
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: enable_rx_int ...\n");
+-#endif
++ pr_debug("SCC: enable_rx_int ...\n");
+ local_irq_save(flags);
+ SCCmod(INT_AND_DMA_REG, 0xff,
+ IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);
+ local_irq_restore(flags);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: enable_rx_int done!\n");
+-#endif
++ pr_debug("SCC: enable_rx_int done!\n");
+ }
+
+
+@@ -906,9 +855,8 @@ static int scc_get_CD(void *ptr)
+ {
+ struct scc_port *port = ptr;
+ unsigned channel = port->channel;
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: get_CD!\n");
+-#endif
++
++ pr_debug("SCC: get_CD!\n");
+ return !!(scc_last_status_reg[channel] & SR_DCD);
+ }
+
+@@ -916,15 +864,12 @@ static int scc_get_CD(void *ptr)
+ static void scc_shutdown_port(void *ptr)
+ {
+ struct scc_port *port = ptr;
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: shutdown_port ...\n");
+-#endif
++
++ pr_debug("SCC: shutdown_port ...\n");
+ port->gs.flags &= ~GS_ACTIVE;
+ if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL)
+ scc_setsignals(port, 0, 0);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: shutdown_port done!\n");
+-#endif
++ pr_debug("SCC: shutdown_port done!\n");
+ }
+
+
+@@ -936,15 +881,14 @@ static int scc_set_real_termios(void *pt
+ unsigned int clkmode, clksrc, div, chsize, channel, brgval = 0;
+ unsigned long flags;
+ struct scc_port *port = ptr;
++
+ SCC_ACCESS_INIT(port);
+
+ if (!port->gs.tty || !port->gs.tty->termios)
+ return 0;
+
+ channel = port->channel;
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: termios for channel %p\n", channel);
+-#endif
++ pr_debug("SCC: termios for channel %u\n", channel);
+ cflag = port->gs.tty->termios->c_cflag;
+ baud = port->gs.baud;
+ baudbits = cflag & CBAUD;
+@@ -958,7 +902,7 @@ static int scc_set_real_termios(void *pt
+ return 0;
+ } else if ((MACH_IS_TT && (baud < 50 || baud > 115200)) ||
+ (MACH_IS_FALCON && (baud < 50 || baud > 230400))) {
+- printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud);
++ pr_debug("SCC: Bad speed requested, %d\n", baud);
+ return 0;
+ }
+
+@@ -967,10 +911,12 @@ static int scc_set_real_termios(void *pt
+ else
+ port->gs.flags |= ASYNC_CHECK_CD;
+
+- // calculate brgval for Atari; enable direct modes!
+-
+- /* convert baud rate from gs.baud to table index, set custom divisor eventually */
++ /* calculate brgval for Atari; enable direct modes! */
+
++ /*
++ * convert baud rate from gs.baud to table index, set custom divisor
++ * eventually
++ */
+ div = 0;
+ clksrc = 0;
+ baudidx = 0;
+@@ -1042,14 +988,12 @@ static int scc_set_real_termios(void *pt
+ clksrc = scc_baud_table[channel][baudidx].clksrc;
+ div = scc_baud_table[channel][baudidx].div;
+ if (!div) {
+- printk(" SCC_change_speed: divisor = 0 !!!");
++ pr_debug("SCC_change_speed: divisor = 0 !!!\n");
+ return 0;
+ }
+ }
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: termios baud %d baudbits %d baudidx %d \n clksrc %d div %d\n",
+- baud, baudbits, baudidx, clksrc, div);
+-#endif
++ pr_debug("SCC: termios baud %d baudbits %d baudidx %d \n clksrc %d "
++ "div %d\n", baud, baudbits, baudidx, clksrc, div);
+ /* compute the SCC's clock source, clock mode, BRG mode and BRG
+ * value from clksrc and div
+ */
+@@ -1070,18 +1014,19 @@ static int scc_set_real_termios(void *pt
+ clksrc = CCR_TXCLK_BRG | CCR_RXCLK_BRG;
+ }
+
+- //printk(KERN_INFO "SCC: termios baud %d baudbits %d baudidx %d \n clksrc %d clkmode %d div %d brgval %d brgmode %d\n",
+- // baud, baudbits, baudidx, clksrc, clkmode, div, brgval, brgmode);
++ /*
++ * pr_info("SCC: termios baud %d baudbits %d baudidx %d \n clksrc %d "
++ * "clkmode %d div %d brgval %d brgmode %d\n", baud, baudbits,
++ * baudidx, clksrc, clkmode, div, brgval, brgmode);
++ */
+
+ /* Now we have all parameters and can go to set them: */
+ local_irq_save(flags);
+
+-#ifdef DEBUG
+- printk(" brgval=%d brgmode=%02x clkmode=%02x clksrc=%02x\n",
+- brgval, brgmode, clkmode, clksrc);
+-#endif
++ pr_debug(" brgval=%d brgmode=%02x clkmode=%02x clksrc=%02x\n", brgval,
++ brgmode, clkmode, clksrc);
+ /* receiver's character size and auto-enables */
+-#if 0 // auto-enable considered harmful ...
++#if 0 /* auto-enable considered harmful ... */
+ SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),
+ (chsize_map[chsize] << 6) |
+ ((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0));
+@@ -1089,11 +1034,9 @@ static int scc_set_real_termios(void *pt
+ /* receiver's character size */
+ SCCmod(RX_CTRL_REG, ~RCR_CHSIZE_MASK, chsize_map[chsize] << 6);
+ #endif
+-#ifdef DEBUG
+- printk(" RX_CTRL_REG <- %02x\n", SCCread( RX_CTRL_REG ));
+-#endif
++ pr_debug(" RX_CTRL_REG <- %02x\n", SCCread(RX_CTRL_REG));
+
+- // clock mode changes depending on baud rate
++ /* clock mode changes depending on baud rate */
+ /* parity and stop bits (both, Tx and Rx) and clock mode */
+ SCCmod(AUX1_CTRL_REG,
+ ~(A1CR_PARITY_MASK | A1CR_MODE_MASK | A1CR_CLKMODE_MASK),
+@@ -1103,22 +1046,17 @@ static int scc_set_real_termios(void *pt
+ | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1)
+ | clkmode));
+
+-#ifdef DEBUG
+- printk(" AUX1_CTRL_REG <- %02x\n", SCCread(AUX1_CTRL_REG));
+-#endif
++ pr_debug(" AUX1_CTRL_REG <- %02x\n", SCCread(AUX1_CTRL_REG));
+ /* sender's character size, set DTR for valid baud rate */
+- SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR);
+-#ifdef DEBUG
+- printk(" TX_CTRL_REG <- %02x\n", SCCread(TX_CTRL_REG));
+-#endif
++ SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK,
++ chsize_map[chsize] << 5 | TCR_DTR);
++ pr_debug(" TX_CTRL_REG <- %02x\n", SCCread(TX_CTRL_REG));
+
+- // clock sources change for TT !!
++ /* clock sources change for TT !! */
+ /* clock sources never change */
+ /* clock sources */
+ SCCmod(CLK_CTRL_REG, ~(CCR_TXCLK_MASK | CCR_RXCLK_MASK), clksrc);
+-#ifdef DEBUG
+- printk(" CLK_CTRL_REG <- %02x\n", SCCread(CLK_CTRL_REG));
+-#endif
++ pr_debug(" CLK_CTRL_REG <- %02x\n", SCCread(CLK_CTRL_REG));
+
+ /* disable BRG before changing the value */
+ SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0);
+@@ -1126,20 +1064,14 @@ static int scc_set_real_termios(void *pt
+ SCCwrite(TIMER_LOW_REG, brgval & 0xff);
+ SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff);
+ /* BRG enable, and clock source never changes */
+- //SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
++ /* SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB); */
+ SCCmod(DPLL_CTRL_REG, ~(DCR_BRG_ENAB | DCR_BRG_USE_PCLK), brgmode);
+-#ifdef DEBUG
+- printk(" TIMER_LOW_REG <- %02x\n", SCCread(TIMER_LOW_REG));
+- printk(" TIMER_HIGH_REG <- %02x\n", SCCread(TIMER_HIGH_REG));
+-#endif
+-#ifdef DEBUG
+- printk(" DPLL_CTRL_REG <- %02x\n", SCCread(DPLL_CTRL_REG));
+-#endif
++ pr_debug(" TIMER_LOW_REG <- %02x\n", SCCread(TIMER_LOW_REG));
++ pr_debug(" TIMER_HIGH_REG <- %02x\n", SCCread(TIMER_HIGH_REG));
++ pr_debug(" DPLL_CTRL_REG <- %02x\n", SCCread(DPLL_CTRL_REG));
+
+ local_irq_restore(flags);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: done termios for channel %d\n", channel);
+-#endif
++ pr_debug("SCC: done termios for channel %d\n", channel);
+ return 0;
+ }
+
+@@ -1150,10 +1082,11 @@ static int scc_chars_in_buffer(void *ptr
+ #ifdef DEBUG
+ int rv;
+ #endif
++
+ SCC_ACCESS_INIT(port);
+ #ifdef DEBUG
+ rv = (SCCread(SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0 : 1;
+- printk(KERN_INFO "SCC: chars_in_buffer: %d\n", rv);
++ pr_debug("SCC: chars_in_buffer: %d\n", rv);
+ return rv;
+ #else
+ return (SCCread(SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0 : 1;
+@@ -1172,27 +1105,19 @@ static int scc_chars_in_buffer(void *ptr
+
+ static void scc_hungup(void *ptr)
+ {
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: hungup ...\n");
+-#endif
++ pr_debug("SCC: hungup ...\n");
+ scc_disable_tx_interrupts(ptr);
+ scc_disable_rx_interrupts(ptr);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: hungup done\n");
+-#endif
++ pr_debug("SCC: hungup done\n");
+ }
+
+
+ static void scc_close(void *ptr)
+ {
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: close ...\n");
+-#endif
++ pr_debug("SCC: close ...\n");
+ scc_disable_tx_interrupts(ptr);
+ scc_disable_rx_interrupts(ptr);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: close done\n");
+-#endif
++ pr_debug("SCC: close done\n");
+ }
+
+
+@@ -1204,10 +1129,9 @@ static void scc_setsignals(struct scc_po
+ {
+ unsigned long flags;
+ unsigned char t;
++
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: setsignals dtr %d rts %d...\n", dtr, rts);
+-#endif
++ pr_debug("SCC: setsignals dtr %d rts %d...\n", dtr, rts);
+ local_irq_save(flags);
+ t = SCCread(TX_CTRL_REG);
+ if (dtr >= 0)
+@@ -1216,24 +1140,19 @@ static void scc_setsignals(struct scc_po
+ t = rts? (t | TCR_RTS): (t & ~TCR_RTS);
+ SCCwrite(TX_CTRL_REG, t);
+ local_irq_restore(flags);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: setsignals done\n");
+-#endif
++ pr_debug("SCC: setsignals done\n");
+ }
+
+
+ static void scc_send_xchar(struct tty_struct *tty, char ch)
+ {
+ struct scc_port *port = (struct scc_port *)tty->driver_data;
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: send_xchar ...\n");
+-#endif
++
++ pr_debug("SCC: send_xchar ...\n");
+ port->x_char = ch;
+ if (ch)
+ scc_enable_tx_interrupts(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: send_xchar done\n");
+-#endif
++ pr_debug("SCC: send_xchar done\n");
+ }
+
+
+@@ -1254,7 +1173,8 @@ static int scc_open(struct tty_struct *t
+ unsigned reg, val;
+ } scc_init_tab[] = {
+ /* no parity, 1 stop bit, async, 1:16 */
+- { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x64 },
++ { AUX1_CTRL_REG,
++ A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x64 },
+ /* parity error is special cond, ints disabled, no DMA */
+ { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
+ /* Rx 8 bits/char, no auto enable, Rx off */
+@@ -1264,14 +1184,16 @@ static int scc_open(struct tty_struct *t
+ /* special features off */
+ { AUX2_CTRL_REG, 0 },
+ /* RTxC is XTAL, TRxC is input, both clocks = RTxC */
+- { CLK_CTRL_REG, CCR_TRxCOUT_XTAL | CCR_TXCLK_RTxC | CCR_RXCLK_RTxC },
++ { CLK_CTRL_REG,
++ CCR_TRxCOUT_XTAL | CCR_TXCLK_RTxC | CCR_RXCLK_RTxC },
+ { DPLL_CTRL_REG, 0 },
+ /* Start Rx */
+ { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
+ /* Start Tx */
+ { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
+ /* Ext/Stat ints: CTS, DCD, SYNC (DSR) */
+- { INT_CTRL_REG, ICR_ENAB_DCD_INT | ICR_ENAB_CTS_INT | ICR_ENAB_SYNC_INT },
++ { INT_CTRL_REG,
++ ICR_ENAB_DCD_INT | ICR_ENAB_CTS_INT | ICR_ENAB_SYNC_INT },
+ /* Reset Ext/Stat ints */
+ { COMMAND_REG, CR_EXTSTAT_RESET },
+ /* ...again */
+@@ -1284,57 +1206,46 @@ static int scc_open(struct tty_struct *t
+ if (atari_SCC_init_done && line == 1)
+ return -ENODEV;
+
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: open port ...\n");
+-#endif
++ pr_debug("SCC: open port ...\n");
+ if (!(port->gs.flags & ASYNC_INITIALIZED)) {
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: init port ...\n");
+-#endif
++ pr_debug("SCC: init port ...\n");
+ local_irq_save(flags);
+
+ SCCmod(MASTER_INT_CTRL, 0x3f,
+ channel == 0 ? MIC_CH_A_RESET : MIC_CH_B_RESET);
+ udelay(40); /* extra delay after a reset */
+
+- for (i = 0; i < sizeof(scc_init_tab)/sizeof(*scc_init_tab); ++i)
++ for (i = 0; i < ARRAY_SIZE(scc_init_tab); ++i)
+ SCCwrite(scc_init_tab[i].reg, scc_init_tab[i].val);
+
+
+- /* remember status register for detection of DCD and CTS changes */
++ /*
++ * remember status register for detection of DCD and CTS
++ * changes
++ */
+ scc_last_status_reg[channel] = SCCread(STATUS_REG);
+
+ port->c_dcd = 0; /* Prevent initial 1->0 interrupt */
+ scc_setsignals(port, 1, 1);
+ local_irq_restore(flags);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: init port done!\n");
+-#endif
++ pr_debug("SCC: init port done!\n");
+ }
+
+ tty->driver_data = port;
+ port->gs.tty = tty;
+ port->gs.count++;
+-#ifdef DEBUG
+- printk(KERN_WARNING "SCC: gs init port ...\n");
+-#endif
++ pr_debug(KERN_WARNING "SCC: gs init port ...\n");
+ retval = gs_init_port(&port->gs);
+ if (retval) {
+ port->gs.count--;
+ return retval;
+ }
+-#ifdef DEBUG
+- printk(KERN_WARNING "SCC: gs init port done!\n");
+-#endif
++ pr_debug(KERN_WARNING "SCC: gs init port done!\n");
+ port->gs.flags |= GS_ACTIVE;
+
+-#ifdef DEBUG
+- printk(KERN_WARNING "SCC: gs wait ready ...\n");
+-#endif
++ pr_debug(KERN_WARNING "SCC: gs wait ready ...\n");
+ retval = gs_block_til_ready(port, filp);
+-#ifdef DEBUG
+- printk(KERN_WARNING "SCC: gs wait ready done!\n");
+-#endif
++ pr_debug(KERN_WARNING "SCC: gs wait ready done!\n");
+ if (retval) {
+ port->gs.count--;
+ return retval;
+@@ -1342,15 +1253,10 @@ static int scc_open(struct tty_struct *t
+
+ port->c_dcd = scc_get_CD(port);
+
+-#ifdef DEBUG
+- printk(KERN_WARNING "SCC: enable rx ints ...\n");
+-#endif
++ pr_debug(KERN_WARNING "SCC: enable rx ints ...\n");
+ scc_enable_rx_interrupts(port);
+-#ifdef DEBUG
+- printk(KERN_WARNING "SCC: enable rx ints done!\n");
+-
+- printk(KERN_INFO "SCC: open port done!\n");
+-#endif
++ pr_debug(KERN_WARNING "SCC: enable rx ints done!\n");
++ pr_info("SCC: open port done!\n");
+ return 0;
+ }
+
+@@ -1359,10 +1265,9 @@ static void scc_throttle(struct tty_stru
+ {
+ struct scc_port *port = (struct scc_port *)tty->driver_data;
+ unsigned long flags;
++
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: throttle ...\n");
+-#endif
++ pr_debug("SCC: throttle ...\n");
+ if (tty->termios->c_cflag & CRTSCTS) {
+ local_irq_save(flags);
+ SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
+@@ -1370,9 +1275,7 @@ static void scc_throttle(struct tty_stru
+ }
+ if (I_IXOFF(tty))
+ scc_send_xchar(tty, STOP_CHAR(tty));
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: throttle done!\n");
+-#endif
++ pr_debug("SCC: throttle done!\n");
+ }
+
+
+@@ -1380,10 +1283,9 @@ static void scc_unthrottle(struct tty_st
+ {
+ struct scc_port *port = (struct scc_port *)tty->driver_data;
+ unsigned long flags;
++
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: unthrottle ...\n");
+-#endif
++ pr_debug("SCC: unthrottle ...\n");
+ if (tty->termios->c_cflag & CRTSCTS) {
+ local_irq_save(flags);
+ SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);
+@@ -1391,9 +1293,7 @@ static void scc_unthrottle(struct tty_st
+ }
+ if (I_IXOFF(tty))
+ scc_send_xchar(tty, START_CHAR(tty));
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: unthrottle done!\n");
+-#endif
++ pr_debug("SCC: unthrottle done!\n");
+ }
+
+
+@@ -1402,11 +1302,10 @@ static int scc_ioctl(struct tty_struct *
+ {
+ struct scc_port *port = (struct scc_port *)tty->driver_data;
+ int retval;
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl! cmd %d, arg %p \n", cmd, arg);
+-#endif
+- //if (serial_paranoia_check(info, tty->device, "zs_ioctl"))
+- // return -ENODEV;
++
++ pr_debug("SCC: ioctl! cmd %d, arg %lu\n", cmd, arg);
++ /* if (serial_paranoia_check(info, tty->device, "zs_ioctl")) */
++ /* return -ENODEV; */
+
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
+@@ -1417,37 +1316,29 @@ static int scc_ioctl(struct tty_struct *
+
+ switch (cmd) {
+ case TCSBRK: /* SVID version: non-zero arg --> no break */
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl TCSBRK\n");
+-#endif
++ pr_debug("SCC: ioctl TCSBRK\n");
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+- //if (!arg)
+- // send_break(info, HZ/4); /* 1/4 second */
++ /* if (!arg) */
++ /* send_break(info, HZ/4); */
+ return 0;
+ case TCSBRKP: /* support for POSIX tcsendbreak() */
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl TCSBRKP\n");
+-#endif
++ pr_debug("SCC: ioctl TCSBRKP\n");
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+- //send_break(info, arg ? arg*(HZ/10) : HZ/4);
++ /* send_break(info, arg ? arg*(HZ/10) : HZ/4); */
+ return 0;
+ case TIOCGSOFTCAR:
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl TIOCGSOFTCAR\n");
+-#endif
++ pr_debug("SCC: ioctl TIOCGSOFTCAR\n");
+ if (put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg))
+ return -EFAULT;
+ return 0;
+ case TIOCSSOFTCAR:
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl TIOCSSOFTCAR\n");
+-#endif
++ pr_debug("SCC: ioctl TIOCSSOFTCAR\n");
+ if (get_user(arg, (unsigned long *)arg))
+ return -EFAULT;
+ tty->termios->c_cflag =
+@@ -1455,54 +1346,38 @@ static int scc_ioctl(struct tty_struct *
+ (arg ? CLOCAL : 0));
+ return 0;
+ case TIOCMGET:
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl TIOCMGET\n");
+-#endif
+- //return get_modem_info(info, (unsigned int *)arg);
++ pr_debug("SCC: ioctl TIOCMGET\n");
++ /* return get_modem_info(info, (unsigned int *)arg); */
+ return 0;
+ case TIOCMBIS:
+ case TIOCMBIC:
+ case TIOCMSET:
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl TIOCMSET\n");
+-#endif
+- //return set_modem_info(info, cmd, (unsigned int *)arg);
++ pr_debug("SCC: ioctl TIOCMSET\n");
++ /* return set_modem_info(info, cmd, (unsigned int *)arg); */
+ return 0;
+ case TIOCGSERIAL:
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl TIOCGSERIAL\n");
+-#endif
++ pr_debug("SCC: ioctl TIOCGSERIAL\n");
+ return 0;
+- //return get_serial_info(info,
+- // (struct serial_struct *)arg);
++ /* return get_serial_info(info, (struct serial_struct *)arg); */
+ case TIOCSSERIAL:
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl TIOCSSERIAL\n");
+-#endif
++ pr_debug("SCC: ioctl TIOCSSERIAL\n");
+ return 0;
+- //return set_serial_info(info,
+- // (struct serial_struct *)arg);
++ /* return set_serial_info(info, (struct serial_struct *)arg); */
+ case TIOCSERGETLSR: /* Get line status register */
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl TIOCSERGETLSR\n");
+-#endif
++ pr_debug("SCC: ioctl TIOCSERGETLSR\n");
+ return 0;
+- //return get_lsr_info(info, (unsigned int *)arg);
++ /* return get_lsr_info(info, (unsigned int *)arg); */
+
+ case TIOCSERGSTRUCT:
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl TIOCSERGSTRUCT\n");
+-#endif
++ pr_debug("SCC: ioctl TIOCSERGSTRUCT\n");
+ return 0;
+- if (copy_to_user((struct scc_port *)arg,
+- port, sizeof(struct scc_port)))
++ if (copy_to_user((struct scc_port *)arg, port,
++ sizeof(struct scc_port)))
+ return -EFAULT;
+ return 0;
+
+ default:
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: ioctl default\n");
+-#endif
++ pr_debug("SCC: ioctl default\n");
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+@@ -1513,16 +1388,13 @@ static void scc_break_ctl(struct tty_str
+ {
+ struct scc_port *port = (struct scc_port *)tty->driver_data;
+ unsigned long flags;
++
+ SCC_ACCESS_INIT(port);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: break ctl ...\n");
+-#endif
++ pr_debug("SCC: break ctl ...\n");
+ local_irq_save(flags);
+ SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, break_state ? TCR_SEND_BREAK : 0);
+ local_irq_restore(flags);
+-#ifdef DEBUG
+- printk(KERN_INFO "SCC: break ctl done!\n");
+-#endif
++ pr_debug("SCC: break ctl done!\n");
+ }
+
+
+@@ -1541,18 +1413,19 @@ static void scc_break_ctl(struct tty_str
+ scc_delay(); \
+ } while (0)
+
+-/* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
+- * delay of ~ 60us. */
++/*
++ * loops_per_jiffy isn't initialized yet, so we can't use udelay().
++ * This does a delay of ~ 60us.
++ */
+ #define LONG_DELAY() \
+ do { \
+ int i; \
+- for (i = 100; i > 0; --i) \
++ for (i = 100; i > 0; i--) \
+ scc_delay(); \
+ } while (0)
+
+ static void atari_init_scc_port(int cflag)
+ {
+- extern int atari_SCC_reset_done;
+ static int clksrc_table[9] =
+ /* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
+ { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
+@@ -1573,15 +1446,20 @@ static void atari_init_scc_port(int cfla
+
+ if (cflag & CBAUDEX)
+ baud += B38400;
+- if (baud < B1200 || baud > B38400+2)
+- baud = B9600; /* use default 9600bps for non-implemented rates */
++ if (baud < B1200 || baud > B38400+2) {
++ /* use default 9600bps for non-implemented rates */
++ baud = B9600;
++ }
+ baud -= B1200; /* tables starts at 1200bps */
+
+ clksrc = clksrc_table[baud];
+ clkmode = clkmode_table[baud];
+ div = div_table[baud];
+ if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
+- /* special treatment for TT, where rates >= 38400 are done via TRxC */
++ /*
++ * special treatment for TT, where rates >= 38400 are done via
++ * TRxC
++ */
+ clksrc = 0x28; /* TRxC */
+ clkmode = baud == 6 ? 0xc0 :
+ baud == 7 ? 0x80 : /* really 76800bps */
+@@ -1630,21 +1508,21 @@ static void scc_ch_write(char ch)
+
+ do {
+ scc_delay();
+- }
+- while (!(*p & 4));
+- // scc_delay();
+- // *p = 8;
++ } while (!(*p & 4));
++ /* scc_delay(); */
++ /* *p = 8; */
+ scc_delay();
+ *(p+1) = ch;
+ }
+
+ /* The console must be locked when we get here. */
+
+-static void scc_console_write(struct console *co, const char *str, unsigned count)
++static void scc_console_write(struct console *co, const char *str,
++ unsigned count)
+ {
+ unsigned long flags;
+
+- //printk("scc_console_write: %s\n", str);
++ /* printk("scc_console_write: %s\n", str); */
+ local_irq_save(flags);
+
+ while (count--) {
+@@ -1653,7 +1531,7 @@ static void scc_console_write(struct con
+ scc_ch_write(*str++);
+ }
+ local_irq_restore(flags);
+- //printk("scc_console_write done!\n");
++ /* printk("scc_console_write done!\n"); */
+ }
+
+ static struct tty_driver *scc_console_device(struct console *c, int *index)
+@@ -1665,9 +1543,9 @@ static struct tty_driver *scc_console_de
+
+ static int __init scc_console_setup(struct console *co, char *options)
+ {
+- printk("scc_console_setup: initializing SCC port B\n");
++ pr_debug("scc_console_setup: initializing SCC port B\n");
+ atari_init_scc_port(B9600|CS8);
+- printk("scc_console_setup: done!\n");
++ pr_debug("scc_console_setup: done!\n");
+ return 0;
+ }
+
+@@ -1682,14 +1560,14 @@ static struct console sercons = {
+ };
+
+
+-static int __init vme_scc_console_init(void)
++static int __init atari_scc_console_init(void)
+ {
+ if (MACH_IS_TT || MACH_IS_ST || MACH_IS_FALCON)
+ register_console(&sercons);
+ return 0;
+ }
+
+-console_initcall(vme_scc_console_init);
++console_initcall(atari_scc_console_init);
+ #endif
+
+ /***************************** End of Functions *********************/
+--- a/include/asm-m68k/atarihw.h
++++ b/include/asm-m68k/atarihw.h
+@@ -30,6 +30,9 @@ extern u_long atari_switches;
+ extern int atari_rtc_year_offset;
+ extern int atari_dont_touch_floppy_select;
+
++extern int atari_SCC_init_done;
++extern int atari_SCC_reset_done;
++
+ /* convenience macros for testing machine type */
+ #define MACH_IS_ST ((atari_mch_cookie >> 16) == ATARI_MCH_ST)
+ #define MACH_IS_STE ((atari_mch_cookie >> 16) == ATARI_MCH_STE && \
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-gs-fix.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-gs-fix.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,191 @@
+Subject: [PATCH] m68k: Atari SCC serial driver gs update
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Update for commit commit b5391e29f428d11755ca2c91074c6db6f5c69d7c ("gs: use
+tty_port"), which moved some fields
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/char/atari_scc.c | 59 +++++++++++++++++++++++------------------------
+ 1 file changed, 30 insertions(+), 29 deletions(-)
+
+--- a/drivers/char/atari_scc.c
++++ b/drivers/char/atari_scc.c
+@@ -269,8 +269,8 @@ static void scc_init_portstructs(void)
+ #ifdef NEW_WRITE_LOCKING
+ port->gs.port_write_sem = MUTEX;
+ #endif
+- init_waitqueue_head(&port->gs.open_wait);
+- init_waitqueue_head(&port->gs.close_wait);
++ init_waitqueue_head(&port->gs.port.open_wait);
++ init_waitqueue_head(&port->gs.port.close_wait);
+ }
+ }
+
+@@ -595,7 +595,7 @@ static irqreturn_t scc_rx_int(int irq, v
+ {
+ unsigned char ch;
+ struct scc_port *port = data;
+- struct tty_struct *tty = port->gs.tty;
++ struct tty_struct *tty = port->gs.port.tty;
+
+ SCC_ACCESS_INIT(port);
+ pr_debug("SCC: rx_int ...\n");
+@@ -638,7 +638,7 @@ static irqreturn_t scc_rx_int(int irq, v
+ static irqreturn_t scc_spcond_int(int irq, void *data)
+ {
+ struct scc_port *port = data;
+- struct tty_struct *tty = port->gs.tty;
++ struct tty_struct *tty = port->gs.port.tty;
+ unsigned char stat, ch, err;
+ int int_pending_mask = port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX;
+
+@@ -705,7 +705,7 @@ static irqreturn_t scc_tx_int(int irq, v
+
+ SCC_ACCESS_INIT(port);
+ pr_debug("SCC: tx_int irq %d port %p ...\n", irq, data);
+- if (!port->gs.tty) {
++ if (!port->gs.port.tty) {
+ pr_warning("scc_tx_int with NULL tty!\n");
+ SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+ SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
+@@ -717,8 +717,9 @@ static irqreturn_t scc_tx_int(int irq, v
+ pr_debug("SCC: tx_int writing char %c\n", port->x_char);
+ SCCwrite(TX_DATA_REG, port->x_char);
+ port->x_char = 0;
+- } else if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
+- port->gs.tty->hw_stopped) {
++ } else if ((port->gs.xmit_cnt <= 0) ||
++ port->gs.port.tty->stopped ||
++ port->gs.port.tty->hw_stopped) {
+ pr_debug("SCC: nothing to do!\n");
+ break;
+ } else {
+@@ -732,18 +733,18 @@ static irqreturn_t scc_tx_int(int irq, v
+ break;
+ }
+ }
+- if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
+- port->gs.tty->hw_stopped) {
++ if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped ||
++ port->gs.port.tty->hw_stopped) {
+ pr_debug("SCC: nothing to do, disabling int\n");
+ /* disable tx interrupts */
+ SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+ /* disable tx_int on next tx underrun? */
+ SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
+- port->gs.flags &= ~GS_TX_INTEN;
++ port->gs.port.flags &= ~GS_TX_INTEN;
+ }
+- if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) {
++ if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) {
+ pr_debug("SCC: waking up tty!\n");
+- tty_wakeup(port->gs.tty);
++ tty_wakeup(port->gs.port.tty);
+ }
+
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+@@ -766,14 +767,14 @@ static irqreturn_t scc_stat_int(int irq,
+
+ if (changed & SR_DCD) {
+ port->c_dcd = !!(sr & SR_DCD);
+- if (!(port->gs.flags & ASYNC_CHECK_CD))
++ if (!(port->gs.port.flags & ASYNC_CHECK_CD))
+ ; /* Don't report DCD changes */
+ else if (port->c_dcd) {
+ /* Are we blocking in open? */
+- wake_up_interruptible(&port->gs.open_wait);
++ wake_up_interruptible(&port->gs.port.open_wait);
+ } else {
+- if (port->gs.tty)
+- tty_hangup(port->gs.tty);
++ if (port->gs.port.tty)
++ tty_hangup(port->gs.port.tty);
+ }
+ }
+
+@@ -799,7 +800,7 @@ static void scc_disable_tx_interrupts(vo
+ pr_debug("SCC: disable_tx_int ...\n");
+ local_irq_save(flags);
+ SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+- port->gs.flags &= ~GS_TX_INTEN;
++ port->gs.port.flags &= ~GS_TX_INTEN;
+ local_irq_restore(flags);
+ pr_debug("SCC: disable_tx_int done!\n");
+ }
+@@ -866,8 +867,8 @@ static void scc_shutdown_port(void *ptr)
+ struct scc_port *port = ptr;
+
+ pr_debug("SCC: shutdown_port ...\n");
+- port->gs.flags &= ~GS_ACTIVE;
+- if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL)
++ port->gs.port.flags &= ~GS_ACTIVE;
++ if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL)
+ scc_setsignals(port, 0, 0);
+ pr_debug("SCC: shutdown_port done!\n");
+ }
+@@ -884,12 +885,12 @@ static int scc_set_real_termios(void *pt
+
+ SCC_ACCESS_INIT(port);
+
+- if (!port->gs.tty || !port->gs.tty->termios)
++ if (!port->gs.port.tty || !port->gs.port.tty->termios)
+ return 0;
+
+ channel = port->channel;
+ pr_debug("SCC: termios for channel %u\n", channel);
+- cflag = port->gs.tty->termios->c_cflag;
++ cflag = port->gs.port.tty->termios->c_cflag;
+ baud = port->gs.baud;
+ baudbits = cflag & CBAUD;
+ chsize = (cflag & CSIZE) >> 4;
+@@ -907,9 +908,9 @@ static int scc_set_real_termios(void *pt
+ }
+
+ if (cflag & CLOCAL)
+- port->gs.flags &= ~ASYNC_CHECK_CD;
++ port->gs.port.flags &= ~ASYNC_CHECK_CD;
+ else
+- port->gs.flags |= ASYNC_CHECK_CD;
++ port->gs.port.flags |= ASYNC_CHECK_CD;
+
+ /* calculate brgval for Atari; enable direct modes! */
+
+@@ -1207,7 +1208,7 @@ static int scc_open(struct tty_struct *t
+ return -ENODEV;
+
+ pr_debug("SCC: open port ...\n");
+- if (!(port->gs.flags & ASYNC_INITIALIZED)) {
++ if (!(port->gs.port.flags & ASYNC_INITIALIZED)) {
+ pr_debug("SCC: init port ...\n");
+ local_irq_save(flags);
+
+@@ -1232,22 +1233,22 @@ static int scc_open(struct tty_struct *t
+ }
+
+ tty->driver_data = port;
+- port->gs.tty = tty;
+- port->gs.count++;
++ port->gs.port.tty = tty;
++ port->gs.port.count++;
+ pr_debug(KERN_WARNING "SCC: gs init port ...\n");
+ retval = gs_init_port(&port->gs);
+ if (retval) {
+- port->gs.count--;
++ port->gs.port.count--;
+ return retval;
+ }
+ pr_debug(KERN_WARNING "SCC: gs init port done!\n");
+- port->gs.flags |= GS_ACTIVE;
++ port->gs.port.flags |= GS_ACTIVE;
+
+ pr_debug(KERN_WARNING "SCC: gs wait ready ...\n");
+ retval = gs_block_til_ready(port, filp);
+ pr_debug(KERN_WARNING "SCC: gs wait ready done!\n");
+ if (retval) {
+- port->gs.count--;
++ port->gs.port.count--;
+ return retval;
+ }
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-no-serial-console-if-modular.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-no-serial-console-if-modular.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,47 @@
+Subject: [PATCH] m68k: Disable Atari serial console support if modular
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+If CONFIG_ATARI_SCC=m, I get the following warnings:
+
+| drivers/char/atari_scc.c: At top level:
+| drivers/char/atari_scc.c:1573: warning: data definition has no type or storage class
+| drivers/char/atari_scc.c:1573: warning: type defaults to 'int' in declaration of 'console_initcall'
+| drivers/char/atari_scc.c:1573: warning: parameter names (without types) in function declaration
+| drivers/char/atari_scc.c:1567: warning: 'atari_scc_console_init' defined but not used
+
+Apparently console_initcall() is not defined in the modular case.
+
+Disable serial console support if the driver is modular.
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/char/atari_scc.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/atari_scc.c
++++ b/drivers/char/atari_scc.c
+@@ -1401,10 +1401,12 @@ static int scc_break_ctl(struct tty_stru
+ }
+
+
++#if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE)
++
+ /*---------------------------------------------------------------------------
+ * Serial console stuff...
+ *--------------------------------------------------------------------------*/
+-#if 1
++
+ #define scc_delay() \
+ asm volatile ("tstb %0" : : "m" (*scc_del) : "cc")
+
+@@ -1571,7 +1573,8 @@ static int __init atari_scc_console_init
+ }
+
+ console_initcall(atari_scc_console_init);
+-#endif
++
++#endif /* CONFIG_SERIAL_CONSOLE && !MODULE */
+
+ /***************************** End of Functions *********************/
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-readd-CONFIG_ATARI_SCC.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-readd-CONFIG_ATARI_SCC.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,42 @@
+Subject: [PATCH] m68k: Atari SCC serial driver needs CONFIG_ATARI_SCC
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+commit 7ccaee5cadd7a771773bbb878e139697511ebdde ("m68k/Atari: remove the dead
+ATARI_SCC{,_DMA} options") removed CONFIG_ATARI_SCC, which we now need again
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/Kconfig | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/arch/m68k/Kconfig
++++ b/arch/m68k/Kconfig
+@@ -474,6 +474,18 @@ config ATARI_MFPSER
+ Note for Falcon users: You also have an MFP port, it's just not
+ wired to the outside... But you could use the port under Linux.
+
++config ATARI_SCC
++ tristate "Atari SCC serial support"
++ depends on ATARI
++ ---help---
++ If you have serial ports based on a Zilog SCC chip (Modem2, Serial2,
++ LAN) and like to use them under Linux, say Y. All built-in SCC's are
++ supported (TT, MegaSTE, Falcon), and also the ST-ESCC. If you have
++ two connectors for channel A (Serial2 and LAN), they are visible as
++ two separate devices.
++
++ To compile this driver as a module, choose M here.
++
+ config ATARI_MIDI
+ tristate "Atari MIDI serial support"
+ depends on ATARI
+@@ -590,7 +602,7 @@ config DN_SERIAL
+
+ config SERIAL_CONSOLE
+ bool "Support for serial port console"
+- depends on (AMIGA || ATARI || MAC || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
++ depends on (AMIGA || ATARI || MAC || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_SCC=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
+ ---help---
+ If you say Y here, it will be possible to use a serial port as the
+ system console (the system console is the device which receives all
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-readd-atari_SCC_init_done.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc-readd-atari_SCC_init_done.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,33 @@
+Subject: [PATCH] m68k: Atari SCC serial driver needs atari_SCC_init_done
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+commit 5575d0a3c9676b2886adad67dd4b2ac126a49f1f ("m68k/atari/debug.c: possible
+cleanups") removed atari_SCC_init_done, which we now need again
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/atari/debug.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/m68k/atari/debug.c
++++ b/arch/m68k/atari/debug.c
+@@ -20,6 +20,10 @@
+ #include <asm/atarihw.h>
+ #include <asm/atariints.h>
+
++/* Flag that Modem1 port is already initialized and used */
++int atari_SCC_init_done;
++EXPORT_SYMBOL(atari_SCC_init_done);
++
+ /* Can be set somewhere, if a SCC master reset has already be done and should
+ * not be repeated; used by kgdb */
+ int atari_SCC_reset_done;
+@@ -259,6 +263,7 @@ static void __init atari_init_scc_port(i
+ SCC_WRITE(5, reg5 | 8);
+
+ atari_SCC_reset_done = 1;
++ atari_SCC_init_done = 1;
+ }
+
+ static void __init atari_init_midi_port(int cflag)
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/atari-scc.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,1737 @@
+To: linus, akpm
+Cc: lkml
+Subject: [PATCH] m68k: Atari SCC serial driver
+
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+
+Atari SCC serial driver - this one works less well in 2.6 than it did in 2.4,
+most likely due to the way flip buffer push is handled now - i.e. no
+immediate push of received characters to the line disc. if the handler
+runs in interrupt context, and the bottom half for pushing is run as
+delayed task. 9 out of 10 ping packets end up in the bit bucket this way.
+I haven't figured out how to prevent overruns yet, and getting this right
+will require a bit more testing.
+
+Anyway, the basics are working, and maybe someone can figure out a better
+way to push characters up to the ldisc.
+
+Signed-off-by: Michael Schmitz <schmitz at debian.org>
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/char/Makefile | 1
+ drivers/char/atari_scc.c | 1699 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 1700 insertions(+)
+
+--- a/drivers/char/Makefile
++++ b/drivers/char/Makefile
+@@ -31,6 +31,7 @@ obj-$(CONFIG_DIGIEPCA) += epca.o
+ obj-$(CONFIG_SPECIALIX) += specialix.o
+ obj-$(CONFIG_MOXA_INTELLIO) += moxa.o
+ obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o
++obj-$(CONFIG_ATARI_SCC) += atari_scc.o generic_serial.o
+ obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
+ obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
+ obj-$(CONFIG_COMPUTONE) += ip2/
+--- /dev/null
++++ b/drivers/char/atari_scc.c
+@@ -0,0 +1,1699 @@
++/*
++ * Atari TT/Falcon Am8530 SCC serial ports implementation.
++ *
++ * Copyright 2005 Michael Schmitz
++ *
++ * Based on:
++ * drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports
++ * implementation.
++ * Copyright 1999 Richard Hirst <richard at sleepie.demon.co.uk>
++ *
++ * which, in turn, was
++ *
++ * Based on atari_SCC.c which was
++ * Copyright 1994-95 Roman Hodek <Roman.Hodek at informatik.uni-erlangen.de>
++ * Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o
++ *
++ * 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/kdev_t.h>
++#include <asm/io.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/ioport.h>
++#include <linux/interrupt.h>
++#include <linux/errno.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/mm.h>
++#include <linux/serial.h>
++#include <linux/fcntl.h>
++#include <linux/major.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/miscdevice.h>
++#include <linux/console.h>
++#include <linux/init.h>
++#include <asm/setup.h>
++#include <asm/uaccess.h>
++#include <asm/bootinfo.h>
++
++#include <asm/atarihw.h>
++#include <asm/atariints.h>
++
++#include <linux/generic_serial.h>
++#include "scc.h"
++
++#define CONFIG_TT_SCC 1
++#define CONFIG_FALCON_SCC 1
++
++#define CHANNEL_A 0
++#define CHANNEL_B 1
++
++#define SCC_MINOR_BASE 64
++
++/* Shadows for all SCC write registers */
++static unsigned char scc_shadow[2][16];
++
++/* Location to access for SCC register access delay */
++static volatile unsigned char *scc_del = NULL;
++
++/* To keep track of STATUS_REG state for detection of Ext/Status int source */
++static unsigned char scc_last_status_reg[2];
++
++/***************************** Prototypes *****************************/
++
++/* Function prototypes */
++static void scc_disable_tx_interrupts(void *ptr);
++static void scc_enable_tx_interrupts(void *ptr);
++static void scc_disable_rx_interrupts(void *ptr);
++static void scc_enable_rx_interrupts(void *ptr);
++static int scc_get_CD(void *ptr);
++static void scc_shutdown_port(void *ptr);
++static int scc_set_real_termios(void *ptr);
++static void scc_hungup(void *ptr);
++static void scc_close(void *ptr);
++static int scc_chars_in_buffer(void *ptr);
++static int scc_open(struct tty_struct *tty, struct file *filp);
++static int scc_ioctl(struct tty_struct *tty, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++static void scc_throttle(struct tty_struct *tty);
++static void scc_unthrottle(struct tty_struct *tty);
++static irqreturn_t scc_tx_int(int irq, void *data);
++static irqreturn_t scc_rx_int(int irq, void *data);
++static irqreturn_t scc_stat_int(int irq, void *data);
++static irqreturn_t scc_spcond_int(int irq, void *data);
++static void scc_setsignals(struct scc_port *port, int dtr, int rts);
++static void scc_break_ctl(struct tty_struct *tty, int break_state);
++
++static struct tty_driver *scc_driver;
++
++static struct scc_port scc_ports[2];
++
++/*
++ * Flags to indicate one of the serial ports has already been initialized by the
++ * serial debug driver. We may want to hold off reinitializing ...
++ */
++
++/* Flag that Modem1 port is already initialized and used */
++extern int atari_SCC_init_done;
++/* Can be set somewhere, if a SCC master reset has already be done and should
++ * not be repeated; used by kgdb */
++extern int atari_SCC_reset_done;
++
++/*---------------------------------------------------------------------------
++ * Interface from generic_serial.c back here
++ *--------------------------------------------------------------------------*/
++
++static struct real_driver scc_real_driver = {
++ .disable_tx_interrupts = scc_disable_tx_interrupts,
++ .enable_tx_interrupts = scc_enable_tx_interrupts,
++ .disable_rx_interrupts = scc_disable_rx_interrupts,
++ .enable_rx_interrupts = scc_enable_rx_interrupts,
++ .get_CD = scc_get_CD,
++ .shutdown_port = scc_shutdown_port,
++ .set_real_termios = scc_set_real_termios,
++ .chars_in_buffer = scc_chars_in_buffer,
++ .close = scc_close,
++ .hungup = scc_hungup,
++};
++
++static struct tty_operations scc_ops = {
++ .open = scc_open,
++ .close = gs_close,
++ .write = gs_write,
++ .put_char = gs_put_char,
++ .flush_chars = gs_flush_chars,
++ .write_room = gs_write_room,
++ .chars_in_buffer = gs_chars_in_buffer,
++ .flush_buffer = gs_flush_buffer,
++ .ioctl = scc_ioctl,
++ .throttle = scc_throttle,
++ .unthrottle = scc_unthrottle,
++ .set_termios = gs_set_termios,
++ .stop = gs_stop,
++ .start = gs_start,
++ .hangup = gs_hangup,
++ .break_ctl = scc_break_ctl,
++};
++
++/* BRG values for the standard speeds and the various clock sources */
++
++typedef struct {
++ unsigned clksrc; /* clock source to use or -1 for not possible */
++ unsigned div; /* divisor: 1, 2 and 4 correspond to
++ * direct 1:16, 1:32 and 1:64 modes,
++ * divisors >= 4 yield a BRG value of
++ * div/2-2 (in 1:16 mode)
++ */
++} BAUD_ENTRY;
++
++/* A pointer for each channel to the current baud table */
++static BAUD_ENTRY *scc_baud_table[2];
++
++/* Baud table format:
++ *
++ * Each entry consists of the clock source (CLK_RTxC, CLK_TRxC or
++ * CLK_PCLK) and a divisor. The following rules apply to the divisor:
++ *
++ * - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use
++ * the BRG)
++ *
++ * - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible)
++ *
++ * - CLK_PCLK: >= 4 and even (no direct modes, only BRG)
++ *
++ */
++
++/* This table is used if RTxC = 3.672 MHz. This is the case for TT's
++ * channel A and for both channels on the Mega STE/Falcon. (TRxC is unused)
++ */
++
++static BAUD_ENTRY bdtab_norm[20] = {
++ /* B0 */ { 0, 0 },
++ /* B50 */ { CLK_RTxC, 4590 },
++ /* B75 */ { CLK_RTxC, 3060 },
++ /* B110 */ { CLK_PCLK, 4576 },
++ /* B134 */ { CLK_PCLK, 3756 },
++ /* B150 */ { CLK_RTxC, 1530 },
++ /* B200 */ { CLK_PCLK, 2516 },
++ /* B300 */ { CLK_PCLK, 1678 },
++ /* B600 */ { CLK_PCLK, 838 },
++ /* B1200 */ { CLK_PCLK, 420 },
++ /* B1800 */ { CLK_PCLK, 280 },
++ /* B2400 */ { CLK_PCLK, 210 },
++ /* B4800 */ { CLK_RTxC, 48 },
++ /* B9600 */ { CLK_RTxC, 24 },
++ /* B19200 */ { CLK_RTxC, 12 },
++ /* B38400 */ { CLK_RTxC, 6 }, /* #15 spd_extra */
++ /* B57600 */ { CLK_RTxC, 4 }, /* #16 spd_hi */
++ /* B115200 */ { CLK_RTxC, 2 }, /* #17 spd_vhi */
++ /* B230400 */ { CLK_RTxC, 1 }, /* #18 spd_shi */
++ /* B460800 */ { 0, 0 } /* #19 spd_warp: Impossible */
++};
++
++/* This is a special table for the TT channel B with 307.2 kHz at RTxC
++ * and 2.4576 MHz at TRxC
++ */
++static BAUD_ENTRY bdtab_TTChB[20] = {
++ /* B0 */ { 0, 0 },
++ /* B50 */ { CLK_RTxC, 384 },
++ /* B75 */ { CLK_RTxC, 256 },
++ /* B110 */ { CLK_PCLK, 4576 },
++ /* B134 */ { CLK_PCLK, 3756 },
++ /* B150 */ { CLK_RTxC, 128 },
++ /* B200 */ { CLK_RTxC, 96 },
++ /* B300 */ { CLK_RTxC, 64 },
++ /* B600 */ { CLK_RTxC, 32 },
++ /* B1200 */ { CLK_RTxC, 16 },
++ /* B1800 */ { CLK_PCLK, 280 },
++ /* B2400 */ { CLK_RTxC, 8 },
++ /* B4800 */ { CLK_RTxC, 4 },
++ /* B9600 */ { CLK_RTxC, 2 },
++ /* B19200 */ { CLK_RTxC, 1 },
++ /* B38400 */ { CLK_TRxC, 4 },
++ /* B57600 */ { CLK_TRxC, 2 }, /* 57600 is not possible, use 76800 instead */
++ /* B115200 */ { CLK_TRxC, 1 }, /* 115200 is not possible, use 153600 instead */
++ /* B230400 */ { 0, 0 }, /* #18 spd_shi: Impossible */
++ /* B460800 */ { 0, 0 } /* #19 spd_warp: Impossible */
++};
++
++
++/*----------------------------------------------------------------------------
++ * atari_scc_init() and support functions
++ *---------------------------------------------------------------------------*/
++
++static int scc_init_drivers(void)
++{
++ int error;
++
++ scc_driver = alloc_tty_driver(2);
++ if (!scc_driver)
++ return -ENOMEM;
++ scc_driver->owner = THIS_MODULE;
++ scc_driver->driver_name = "scc";
++ scc_driver->name = "ttyS";
++ scc_driver->major = TTY_MAJOR;
++ scc_driver->minor_start = SCC_MINOR_BASE;
++ scc_driver->type = TTY_DRIVER_TYPE_SERIAL;
++ scc_driver->subtype = SERIAL_TYPE_NORMAL;
++ scc_driver->init_termios = tty_std_termios;
++ scc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
++ scc_driver->flags = TTY_DRIVER_REAL_RAW;
++
++ tty_set_operations(scc_driver, &scc_ops);
++
++ if ((error = tty_register_driver(scc_driver))) {
++ printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n",
++ error);
++ put_tty_driver(scc_driver);
++ return 1;
++ }
++
++ return 0;
++}
++
++
++/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1).
++ */
++
++static void scc_init_portstructs(void)
++{
++ struct scc_port *port;
++ int i;
++
++ for (i = 0; i < 2; i++) {
++ port = scc_ports + i;
++ port->gs.magic = SCC_MAGIC;
++ port->gs.close_delay = HZ/2;
++ port->gs.closing_wait = 30 * HZ;
++ port->gs.rd = &scc_real_driver;
++#ifdef NEW_WRITE_LOCKING
++ port->gs.port_write_sem = MUTEX;
++#endif
++ init_waitqueue_head(&port->gs.open_wait);
++ init_waitqueue_head(&port->gs.close_wait);
++ }
++}
++
++
++#ifdef CONFIG_TT_SCC
++static int atari_tt_scc_init(void)
++{
++ struct scc_port *port;
++
++ printk(KERN_INFO "SCC: Atari TT Serial Driver\n");
++ /* FIXME channel A may be switchable between modem and LAN port */
++ /* Init channel A */
++ if (atari_SCC_init_done)
++ printk(KERN_INFO "SCC: already initialized, expect trouble!\n");
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: init channel A\n");
++#endif
++ port = &scc_ports[0];
++ port->channel = CHANNEL_A;
++ port->ctrlp = (volatile unsigned char *)&scc.cha_a_ctrl;
++ port->datap = port->ctrlp + 1;
++ port->port_a = &scc_ports[0];
++ port->port_b = &scc_ports[1];
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: request channel A irqs, port = %p\n", port);
++#endif
++ request_irq(IRQ_SCCA_TX, scc_tx_int, IRQ_TYPE_PRIO, "SCC-A TX", port);
++ request_irq(IRQ_SCCA_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++ "SCC-A status", port);
++ request_irq(IRQ_SCCA_RX, scc_rx_int, IRQ_TYPE_PRIO, "SCC-A RX", port);
++ request_irq(IRQ_SCCA_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++ "SCC-A special cond", port);
++ {
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: read SCC status\n");
++#endif
++ /* on the first access, read status register to reset internal pointers */
++ SCCread(STATUS_REG);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: reset SCC\n");
++#endif
++ /* FIXME: master reset, once only */
++ SCCwrite(MASTER_INT_CTRL, MIC_HARD_RESET);
++ udelay(40);
++
++ /* disable interrupts for this channel */
++ SCCwrite(INT_AND_DMA_REG, 0);
++ /* Set the interrupt vector ; 0x60 for all Atari models */
++ SCCwrite(INT_VECTOR_REG, 0x60);
++ /* Interrupt parameters: vector includes status, status low */
++ SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
++ SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
++
++ /* disable interrupts for this channel */
++ SCCwrite(INT_AND_DMA_REG, 0);
++ }
++
++ if (!atari_SCC_init_done) {
++ /* Init channel B */
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: init channel B\n");
++#endif
++ port = &scc_ports[1];
++ port->channel = CHANNEL_B;
++ port->ctrlp = (volatile unsigned char *)&scc.cha_b_ctrl;
++ port->datap = port->ctrlp + 1;
++ port->port_a = &scc_ports[0];
++ port->port_b = &scc_ports[1];
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: request channel B irqs, port = %p\n", port);
++#endif
++ request_irq(IRQ_SCCB_TX, scc_tx_int, IRQ_TYPE_PRIO,
++ "SCC-B TX", port);
++ request_irq(IRQ_SCCB_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++ "SCC-B status", port);
++ request_irq(IRQ_SCCB_RX, scc_rx_int, IRQ_TYPE_PRIO,
++ "SCC-B RX", port);
++ request_irq(IRQ_SCCB_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++ "SCC-B special cond", port);
++ {
++ SCC_ACCESS_INIT(port);
++
++ /* disable interrupts for this channel */
++ SCCwrite(INT_AND_DMA_REG, 0);
++ }
++/* not implemented yet */
++#if 0
++ request_irq(IRQ_TT_MFP_RI, scc_ri_int, IRQ_TYPE_SLOW,
++ "TT-MFP ring indicator (modem 2)", port);
++#endif
++
++ }
++
++ /* once only: initalize MFP timer C for RTxC */
++ tt_mfp.tim_ct_cd = (tt_mfp.tim_ct_cd & ~0x70) | 0x10;
++ tt_mfp.tim_dt_c = 1;
++ atari_turnoff_irq(IRQ_TT_MFP_TIMC);
++
++ /* set baud tables */
++ scc_baud_table[CHANNEL_A] = bdtab_norm;
++ scc_baud_table[CHANNEL_B] = bdtab_TTChB;
++
++ /* Initialise the tty driver structures and register */
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: scc_init_portstructs()\n");
++#endif
++ scc_init_portstructs();
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: scc_init_drivers()\n");
++#endif
++ scc_init_drivers();
++
++ return 0;
++}
++#endif
++
++
++#ifdef CONFIG_FALCON_SCC
++static int atari_falcon_scc_init(void)
++{
++ struct scc_port *port;
++
++ printk(KERN_INFO "SCC: Atari Falcon Serial Driver\n");
++ if (atari_SCC_init_done)
++ printk(KERN_INFO "SCC: already initialized, expect trouble!\n");
++
++ /* Init channel A */
++ port = &scc_ports[0];
++ port->channel = CHANNEL_A;
++ port->ctrlp = (volatile unsigned char *)&scc.cha_a_ctrl;
++ port->datap = port->ctrlp + 2;
++ port->port_a = &scc_ports[0];
++ port->port_b = &scc_ports[1];
++ request_irq(IRQ_SCCA_TX, scc_tx_int, IRQ_TYPE_PRIO, "SCC-A TX", port);
++ request_irq(IRQ_SCCA_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++ "SCC-A status", port);
++ request_irq(IRQ_SCCA_RX, scc_rx_int, IRQ_TYPE_PRIO, "SCC-A RX", port);
++ request_irq(IRQ_SCCA_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++ "SCC-A special cond", port);
++ {
++ SCC_ACCESS_INIT(port);
++
++ /* on the first access, read status register to reset internal pointers */
++ SCCread(STATUS_REG);
++
++ /* FIXME: master reset, once only */
++ SCCwrite(MASTER_INT_CTRL, MIC_HARD_RESET);
++ udelay(40);
++
++ /* disable interrupts for this channel */
++ SCCwrite(INT_AND_DMA_REG, 0);
++ /* Set the interrupt vector */
++ SCCwrite(INT_VECTOR_REG, 0x60);
++ /* Interrupt parameters: vector includes status, status low */
++ SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
++ SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
++ }
++
++ /* conditionalize if port in use by console ?? */
++ /* Init channel B */
++ port = &scc_ports[1];
++ port->channel = CHANNEL_B;
++ port->ctrlp = (volatile unsigned char *)&scc.cha_b_ctrl;
++ port->datap = port->ctrlp + 2;
++ port->port_a = &scc_ports[0];
++ port->port_b = &scc_ports[1];
++ request_irq(IRQ_SCCB_TX, scc_tx_int, IRQ_TYPE_PRIO, "SCC-B TX", port);
++ request_irq(IRQ_SCCB_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++ "SCC-B status", port);
++ request_irq(IRQ_SCCB_RX, scc_rx_int, IRQ_TYPE_PRIO, "SCC-B RX", port);
++ request_irq(IRQ_SCCB_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++ "SCC-B special cond", port);
++
++ {
++ SCC_ACCESS_INIT(port); /* Either channel will do */
++
++ /* disable interrupts for this channel */
++ SCCwrite(INT_AND_DMA_REG, 0);
++ }
++
++ /* set baud tables */
++ scc_baud_table[CHANNEL_A] = bdtab_norm;
++ scc_baud_table[CHANNEL_B] = bdtab_norm;
++
++ /* Initialise the tty driver structures and register */
++ scc_init_portstructs();
++ scc_init_drivers();
++
++ return 0;
++}
++#endif
++
++
++#ifdef CONFIG_ST_SCC
++static int atari_st_scc_init(void)
++{
++ struct scc_port *port;
++
++ int escc = ATARIHW_PRESENT(ST_ESCC);
++
++ printk(KERN_INFO "SCC: Atari MegaST/E Serial Driver\n");
++ /* FIXME: ports reversed logic */
++ /* Init channel A */
++ port = &scc_ports[1];
++ port->channel = CHANNEL_A;
++ port->ctrlp = (volatile unsigned char *)(escc ? &st_escc.cha_a_ctrl : &scc.cha_a_ctrl);
++ port->datap = port->ctrlp + 4;
++ port->port_a = &scc_ports[1];
++ port->port_b = &scc_ports[0];
++ request_irq(IRQ_SCCA_TX, scc_tx_int, IRQ_TYPE_PRIO, "SCC-A TX", port);
++ request_irq(IRQ_SCCA_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++ "SCC-A status", port);
++ request_irq(IRQ_SCCA_RX, scc_rx_int, IRQ_TYPE_PRIO, "SCC-A RX", port);
++ request_irq(SCCA_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++ "SCC-A special cond", port);
++ {
++ SCC_ACCESS_INIT(port);
++
++ /* on the first access, read status register to reset internal pointers */
++ SCCread(STATUS_REG);
++
++ /* FIXME: master reset, once only */
++ SCCwrite(MASTER_INT_CTRL, MIC_HARD_RESET);
++ udelay(40);
++
++ /* disable interrupts for this channel */
++ SCCwrite(INT_AND_DMA_REG, 0);
++ /* Set the interrupt vector */
++ SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE);
++ /* Interrupt parameters: vector includes status, status low */
++ SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
++ SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
++ }
++
++ /* Init channel B */
++ port = &scc_ports[0];
++ port->channel = CHANNEL_B;
++ port->ctrlp = (volatile unsigned char *)(escc ? &st_escc.cha_b_ctrl : &scc.cha_b_ctrl);
++ port->datap = port->ctrlp + 4;
++ port->port_a = &scc_ports[0];
++ port->port_b = &scc_ports[1];
++ request_irq(IRQ_SCCB_TX, scc_tx_int, IRQ_TYPE_PRIO, "SCC-B TX", port);
++ request_irq(IRQ_SCCB_STAT, scc_stat_int, IRQ_TYPE_PRIO,
++ "SCC-B status", port);
++ request_irq(IRQ_SCCB_RX, scc_rx_int, IRQ_TYPE_PRIO, "SCC-B RX", port);
++ request_irq(IRQ_SCCB_SPCOND, scc_spcond_int, IRQ_TYPE_PRIO,
++ "SCC-B special cond", port);
++
++ {
++ SCC_ACCESS_INIT(port); /* Either channel will do */
++
++ /* disable interrupts for this channel */
++ SCCwrite(INT_AND_DMA_REG, 0);
++ }
++
++ /* set baud tables */
++ scc_baud_table[CHANNEL_A] = bdtab_norm;
++ scc_baud_table[CHANNEL_B] = bdtab_norm;
++
++ /* Initialise the tty driver structures and register */
++ scc_init_portstructs();
++ scc_init_drivers();
++
++ return 0;
++}
++#endif
++
++
++int atari_scc_init(void)
++{
++ int res = -ENODEV;
++ static int called = 0;
++
++ if (called)
++ return res;
++ called = 1;
++
++ if (!(ATARIHW_PRESENT(SCC) || ATARIHW_PRESENT(ST_ESCC)))
++ return -ENODEV;
++
++ scc_del = &mfp.par_dt_reg;
++
++#ifdef CONFIG_TT_SCC
++ if (MACH_IS_TT)
++ res = atari_tt_scc_init();
++#endif
++#ifdef CONFIG_FALCON_SCC
++ if (MACH_IS_FALCON)
++ res = atari_falcon_scc_init();
++#endif
++#ifdef CONFIG_ST_SCC
++ if (MACH_IS_ST)
++ res = atari_st_scc_init();
++#endif
++ return res;
++}
++
++void atari_scc_cleanup(void)
++{
++ struct scc_port *port;
++
++ tty_unregister_driver(scc_driver);
++ port = &scc_ports[0];
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: free channel A irqs, port = %p\n", port);
++#endif
++ free_irq(IRQ_SCCA_TX, port);
++ free_irq(IRQ_SCCA_STAT, port);
++ free_irq(IRQ_SCCA_RX, port);
++ free_irq(IRQ_SCCA_SPCOND, port);
++
++ port = &scc_ports[1];
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: free channel A irqs, port = %p\n", port);
++#endif
++ free_irq(IRQ_SCCB_TX, port);
++ free_irq(IRQ_SCCB_STAT, port);
++ free_irq(IRQ_SCCB_RX, port);
++ free_irq(IRQ_SCCB_SPCOND, port);
++
++}
++
++module_init(atari_scc_init);
++module_exit(atari_scc_cleanup);
++
++/*---------------------------------------------------------------------------
++ * Interrupt handlers
++ *--------------------------------------------------------------------------*/
++
++static irqreturn_t scc_rx_int(int irq, void *data)
++{
++ unsigned char ch;
++ struct scc_port *port = data;
++ struct tty_struct *tty = port->gs.tty;
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: rx_int ...\n");
++#endif
++ ch = SCCread_NB(RX_DATA_REG);
++ if (!tty) {
++ printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
++ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++ return IRQ_HANDLED;
++ }
++ tty_insert_flip_char(tty, ch, 0);
++#if 0
++ if (tty->flip.count < TTY_FLIPBUF_SIZE) {
++ *tty->flip.char_buf_ptr = ch;
++ *tty->flip.flag_buf_ptr = 0;
++ tty->flip.flag_buf_ptr++;
++ tty->flip.char_buf_ptr++;
++ tty->flip.count++;
++ }
++#endif
++ /* Check if another character is already ready; in that case, the
++ * spcond_int() function must be used, because this character may have an
++ * error condition that isn't signalled by the interrupt vector used!
++ */
++ if (SCCread(INT_PENDING_REG) &
++ (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
++ scc_spcond_int(irq, data);
++ return IRQ_HANDLED;
++ }
++
++ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++
++ tty_flip_buffer_push(tty);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: rx_int done\n");
++#endif
++ return IRQ_HANDLED;
++}
++
++
++static irqreturn_t scc_spcond_int(int irq, void *data)
++{
++ struct scc_port *port = data;
++ struct tty_struct *tty = port->gs.tty;
++ unsigned char stat, ch, err;
++ int int_pending_mask = port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX;
++
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: spcond_int ...\n");
++#endif
++ if (!tty) {
++ printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
++ SCCwrite(COMMAND_REG, CR_ERROR_RESET);
++ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++ return IRQ_HANDLED;
++ }
++ do {
++ stat = SCCread(SPCOND_STATUS_REG);
++ ch = SCCread_NB(RX_DATA_REG);
++
++ if (stat & SCSR_RX_OVERRUN)
++ err = TTY_OVERRUN;
++ else if (stat & SCSR_PARITY_ERR)
++ err = TTY_PARITY;
++ else if (stat & SCSR_CRC_FRAME_ERR)
++ err = TTY_FRAME;
++ else
++ err = 0;
++
++ tty_insert_flip_char(tty, ch, err);
++#if 0
++ if (tty->flip.count < TTY_FLIPBUF_SIZE) {
++ *tty->flip.char_buf_ptr = ch;
++ *tty->flip.flag_buf_ptr = err;
++ tty->flip.flag_buf_ptr++;
++ tty->flip.char_buf_ptr++;
++ tty->flip.count++;
++ }
++#endif
++ /* ++TeSche: *All* errors have to be cleared manually,
++ * else the condition persists for the next chars
++ */
++ if (err)
++ SCCwrite(COMMAND_REG, CR_ERROR_RESET);
++
++ } while (SCCread(INT_PENDING_REG) & int_pending_mask);
++
++ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++
++ tty_flip_buffer_push(tty);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: spcond_int done\n");
++#endif
++ return IRQ_HANDLED;
++}
++
++/* not implemented yet */
++#if 0
++static void scc_ri_int(int irq, void *data)
++{
++ struct scc_port *port = data;
++ /* update input line counter */
++ port->icount.rng++;
++ wake_up_interruptible(&port->delta_msr_wait);
++}
++#endif
++
++static irqreturn_t scc_tx_int(int irq, void *data)
++{
++ struct scc_port *port = data;
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: tx_int irq %d port %p ...\n", irq, data);
++#endif
++ if (!port->gs.tty) {
++ printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
++ SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
++ SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
++ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++ return IRQ_HANDLED;
++ }
++ while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) {
++ if (port->x_char) {
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: tx_int writing char %c\n",
++ port->x_char);
++#endif
++ SCCwrite(TX_DATA_REG, port->x_char);
++ port->x_char = 0;
++ } else if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
++ port->gs.tty->hw_stopped) {
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: nothing to do!\n");
++#endif
++ break;
++ } else {
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: tx_int writing buf %c\n",
++ port->gs.xmit_buf[port->gs.xmit_tail]);
++#endif
++ SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]);
++ port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1);
++ if (--port->gs.xmit_cnt <= 0)
++ break;
++ }
++ }
++ if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
++ port->gs.tty->hw_stopped) {
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: nothing to do, disabling int\n");
++#endif
++ /* disable tx interrupts */
++ SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
++ SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); /* disable tx_int on next tx underrun? */
++ port->gs.flags &= ~GS_TX_INTEN;
++ }
++ if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) {
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: waking up tty!\n");
++#endif
++ tty_wakeup(port->gs.tty);
++ }
++
++ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: tx_int done\n");
++#endif
++ return IRQ_HANDLED;
++}
++
++
++static irqreturn_t scc_stat_int(int irq, void *data)
++{
++ struct scc_port *port = data;
++ unsigned channel = port->channel;
++ unsigned char last_sr, sr, changed;
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: stat_int ...\n");
++#endif
++ last_sr = scc_last_status_reg[channel];
++ sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG);
++ changed = last_sr ^ sr;
++
++ if (changed & SR_DCD) {
++ port->c_dcd = !!(sr & SR_DCD);
++ if (!(port->gs.flags & ASYNC_CHECK_CD))
++ ; /* Don't report DCD changes */
++ else if (port->c_dcd) {
++ /* Are we blocking in open? */
++ wake_up_interruptible(&port->gs.open_wait);
++ } else {
++ if (port->gs.tty)
++ tty_hangup(port->gs.tty);
++ }
++ }
++
++ // FIXME: CTS and DSR status changes?
++
++ SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
++ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: stat_int done\n");
++#endif
++ return IRQ_HANDLED;
++}
++
++
++/*---------------------------------------------------------------------------
++ * generic_serial.c callback funtions
++ *--------------------------------------------------------------------------*/
++
++static void scc_disable_tx_interrupts(void *ptr)
++{
++ struct scc_port *port = ptr;
++ unsigned long flags;
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: disable_tx_int ...\n");
++#endif
++ local_irq_save(flags);
++ SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
++ port->gs.flags &= ~GS_TX_INTEN;
++ local_irq_restore(flags);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: disable_tx_int done!\n");
++#endif
++}
++
++
++static void scc_enable_tx_interrupts(void *ptr)
++{
++ struct scc_port *port = ptr;
++ unsigned long flags;
++
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: enable_tx_int ...\n");
++#endif
++ local_irq_save(flags);
++ SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
++ /* restart the transmitter */
++ scc_tx_int(0, port);
++ local_irq_restore(flags);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: enable_tx_int done!\n");
++#endif
++}
++
++
++static void scc_disable_rx_interrupts(void *ptr)
++{
++ struct scc_port *port = ptr;
++ unsigned long flags;
++
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: disable_rx_int ...\n");
++#endif
++ local_irq_save(flags);
++ SCCmod(INT_AND_DMA_REG,
++ ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);
++ local_irq_restore(flags);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: disable_rx_int done!\n");
++#endif
++}
++
++
++static void scc_enable_rx_interrupts(void *ptr)
++{
++ struct scc_port *port = ptr;
++ unsigned long flags;
++
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: enable_rx_int ...\n");
++#endif
++ local_irq_save(flags);
++ SCCmod(INT_AND_DMA_REG, 0xff,
++ IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);
++ local_irq_restore(flags);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: enable_rx_int done!\n");
++#endif
++}
++
++
++static int scc_get_CD(void *ptr)
++{
++ struct scc_port *port = ptr;
++ unsigned channel = port->channel;
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: get_CD!\n");
++#endif
++ return !!(scc_last_status_reg[channel] & SR_DCD);
++}
++
++
++static void scc_shutdown_port(void *ptr)
++{
++ struct scc_port *port = ptr;
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: shutdown_port ...\n");
++#endif
++ port->gs.flags &= ~GS_ACTIVE;
++ if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL)
++ scc_setsignals(port, 0, 0);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: shutdown_port done!\n");
++#endif
++}
++
++
++static int scc_set_real_termios(void *ptr)
++{
++ /* the SCC has char sizes 5,7,6,8 in that order! */
++ static int chsize_map[4] = { 0, 2, 1, 3 };
++ unsigned int cflag, baud, baudbits, baudidx, brgmode;
++ unsigned int clkmode, clksrc, div, chsize, channel, brgval = 0;
++ unsigned long flags;
++ struct scc_port *port = ptr;
++ SCC_ACCESS_INIT(port);
++
++ if (!port->gs.tty || !port->gs.tty->termios)
++ return 0;
++
++ channel = port->channel;
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: termios for channel %p\n", channel);
++#endif
++ cflag = port->gs.tty->termios->c_cflag;
++ baud = port->gs.baud;
++ baudbits = cflag & CBAUD;
++ chsize = (cflag & CSIZE) >> 4;
++
++ if (baud == 0) {
++ /* speed == 0 -> drop DTR */
++ local_irq_save(flags);
++ SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);
++ local_irq_restore(flags);
++ return 0;
++ } else if ((MACH_IS_TT && (baud < 50 || baud > 115200)) ||
++ (MACH_IS_FALCON && (baud < 50 || baud > 230400))) {
++ printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud);
++ return 0;
++ }
++
++ if (cflag & CLOCAL)
++ port->gs.flags &= ~ASYNC_CHECK_CD;
++ else
++ port->gs.flags |= ASYNC_CHECK_CD;
++
++ // calculate brgval for Atari; enable direct modes!
++
++ /* convert baud rate from gs.baud to table index, set custom divisor eventually */
++
++ div = 0;
++ clksrc = 0;
++ baudidx = 0;
++
++ switch (baud) {
++ case 50:
++ baudidx = 1;
++ break;
++ case 75:
++ baudidx = 2;
++ break;
++ case 110:
++ baudidx = 3;
++ break;
++ case 134:
++ baudidx = 4;
++ break;
++ case 150:
++ baudidx = 5;
++ break;
++ case 200:
++ baudidx = 6;
++ break;
++ case 300:
++ baudidx = 7;
++ break;
++ case 600:
++ baudidx = 8;
++ break;
++ case 1200:
++ baudidx = 9;
++ break;
++ case 1800:
++ baudidx = 10;
++ break;
++ case 2400:
++ baudidx = 11;
++ break;
++ case 4800:
++ baudidx = 12;
++ break;
++ case 9600:
++ baudidx = 13;
++ break;
++ case 19200:
++ baudidx = 14;
++ break;
++ case 38400:
++ baudidx = 15;
++ break;
++ case 57600:
++ baudidx = 16;
++ break;
++ case 115200:
++ baudidx = 17;
++ break;
++ case 230400:
++ baudidx = 18;
++ break;
++ default:
++ baudidx = 15;
++ break;
++ }
++
++ /* do we have a custom divisor ?? */
++ if (!div) {
++ if (baudidx > 19)
++ baudidx = 19;
++ clksrc = scc_baud_table[channel][baudidx].clksrc;
++ div = scc_baud_table[channel][baudidx].div;
++ if (!div) {
++ printk(" SCC_change_speed: divisor = 0 !!!");
++ return 0;
++ }
++ }
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: termios baud %d baudbits %d baudidx %d \n clksrc %d div %d\n",
++ baud, baudbits, baudidx, clksrc, div);
++#endif
++ /* compute the SCC's clock source, clock mode, BRG mode and BRG
++ * value from clksrc and div
++ */
++ if (div <= 4) {
++ clkmode = (div == 1 ? A1CR_CLKMODE_x16 :
++ div == 2 ? A1CR_CLKMODE_x32 :
++ A1CR_CLKMODE_x64);
++ clksrc = (clksrc == CLK_RTxC
++ ? CCR_TXCLK_RTxC | CCR_RXCLK_RTxC
++ : CCR_TXCLK_TRxC | CCR_RXCLK_TRxC);
++ brgmode = 0; /* off */
++ brgval = 0;
++ } else {
++ brgval = div/2 - 2;
++ brgmode = (DCR_BRG_ENAB |
++ (clksrc == CLK_PCLK ? DCR_BRG_USE_PCLK : 0));
++ clkmode = A1CR_CLKMODE_x16;
++ clksrc = CCR_TXCLK_BRG | CCR_RXCLK_BRG;
++ }
++
++ //printk(KERN_INFO "SCC: termios baud %d baudbits %d baudidx %d \n clksrc %d clkmode %d div %d brgval %d brgmode %d\n",
++ // baud, baudbits, baudidx, clksrc, clkmode, div, brgval, brgmode);
++
++ /* Now we have all parameters and can go to set them: */
++ local_irq_save(flags);
++
++#ifdef DEBUG
++ printk(" brgval=%d brgmode=%02x clkmode=%02x clksrc=%02x\n",
++ brgval, brgmode, clkmode, clksrc);
++#endif
++ /* receiver's character size and auto-enables */
++#if 0 // auto-enable considered harmful ...
++ SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),
++ (chsize_map[chsize] << 6) |
++ ((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0));
++#else
++ /* receiver's character size */
++ SCCmod(RX_CTRL_REG, ~RCR_CHSIZE_MASK, chsize_map[chsize] << 6);
++#endif
++#ifdef DEBUG
++ printk(" RX_CTRL_REG <- %02x\n", SCCread( RX_CTRL_REG ));
++#endif
++
++ // clock mode changes depending on baud rate
++ /* parity and stop bits (both, Tx and Rx) and clock mode */
++ SCCmod(AUX1_CTRL_REG,
++ ~(A1CR_PARITY_MASK | A1CR_MODE_MASK | A1CR_CLKMODE_MASK),
++ ((cflag & PARENB
++ ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN)
++ : A1CR_PARITY_NONE)
++ | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1)
++ | clkmode));
++
++#ifdef DEBUG
++ printk(" AUX1_CTRL_REG <- %02x\n", SCCread(AUX1_CTRL_REG));
++#endif
++ /* sender's character size, set DTR for valid baud rate */
++ SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR);
++#ifdef DEBUG
++ printk(" TX_CTRL_REG <- %02x\n", SCCread(TX_CTRL_REG));
++#endif
++
++ // clock sources change for TT !!
++ /* clock sources never change */
++ /* clock sources */
++ SCCmod(CLK_CTRL_REG, ~(CCR_TXCLK_MASK | CCR_RXCLK_MASK), clksrc);
++#ifdef DEBUG
++ printk(" CLK_CTRL_REG <- %02x\n", SCCread(CLK_CTRL_REG));
++#endif
++
++ /* disable BRG before changing the value */
++ SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0);
++ /* BRG value */
++ SCCwrite(TIMER_LOW_REG, brgval & 0xff);
++ SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff);
++ /* BRG enable, and clock source never changes */
++ //SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
++ SCCmod(DPLL_CTRL_REG, ~(DCR_BRG_ENAB | DCR_BRG_USE_PCLK), brgmode);
++#ifdef DEBUG
++ printk(" TIMER_LOW_REG <- %02x\n", SCCread(TIMER_LOW_REG));
++ printk(" TIMER_HIGH_REG <- %02x\n", SCCread(TIMER_HIGH_REG));
++#endif
++#ifdef DEBUG
++ printk(" DPLL_CTRL_REG <- %02x\n", SCCread(DPLL_CTRL_REG));
++#endif
++
++ local_irq_restore(flags);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: done termios for channel %d\n", channel);
++#endif
++ return 0;
++}
++
++
++static int scc_chars_in_buffer(void *ptr)
++{
++ struct scc_port *port = ptr;
++#ifdef DEBUG
++ int rv;
++#endif
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ rv = (SCCread(SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0 : 1;
++ printk(KERN_INFO "SCC: chars_in_buffer: %d\n", rv);
++ return rv;
++#else
++ return (SCCread(SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0 : 1;
++#endif
++}
++
++
++/* Comment taken from sx.c (2.4.0):
++ I haven't the foggiest why the decrement use count has to happen
++ here. The whole linux serial drivers stuff needs to be redesigned.
++ My guess is that this is a hack to minimize the impact of a bug
++ elsewhere. Thinking about it some more. (try it sometime) Try
++ running minicom on a serial port that is driven by a modularized
++ driver. Have the modem hangup. Then remove the driver module. Then
++ exit minicom. I expect an "oops". -- REW */
++
++static void scc_hungup(void *ptr)
++{
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: hungup ...\n");
++#endif
++ scc_disable_tx_interrupts(ptr);
++ scc_disable_rx_interrupts(ptr);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: hungup done\n");
++#endif
++}
++
++
++static void scc_close(void *ptr)
++{
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: close ...\n");
++#endif
++ scc_disable_tx_interrupts(ptr);
++ scc_disable_rx_interrupts(ptr);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: close done\n");
++#endif
++}
++
++
++/*---------------------------------------------------------------------------
++ * Internal support functions
++ *--------------------------------------------------------------------------*/
++
++static void scc_setsignals(struct scc_port *port, int dtr, int rts)
++{
++ unsigned long flags;
++ unsigned char t;
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: setsignals dtr %d rts %d...\n", dtr, rts);
++#endif
++ local_irq_save(flags);
++ t = SCCread(TX_CTRL_REG);
++ if (dtr >= 0)
++ t = dtr? (t | TCR_DTR): (t & ~TCR_DTR);
++ if (rts >= 0)
++ t = rts? (t | TCR_RTS): (t & ~TCR_RTS);
++ SCCwrite(TX_CTRL_REG, t);
++ local_irq_restore(flags);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: setsignals done\n");
++#endif
++}
++
++
++static void scc_send_xchar(struct tty_struct *tty, char ch)
++{
++ struct scc_port *port = (struct scc_port *)tty->driver_data;
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: send_xchar ...\n");
++#endif
++ port->x_char = ch;
++ if (ch)
++ scc_enable_tx_interrupts(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: send_xchar done\n");
++#endif
++}
++
++
++/*---------------------------------------------------------------------------
++ * Driver entrypoints referenced from above
++ *--------------------------------------------------------------------------*/
++
++static int scc_open(struct tty_struct *tty, struct file *filp)
++{
++ int line = tty->index;
++ int retval;
++ struct scc_port *port = &scc_ports[line];
++ int i, channel = port->channel;
++ unsigned long flags;
++ SCC_ACCESS_INIT(port);
++
++ static const struct {
++ unsigned reg, val;
++ } scc_init_tab[] = {
++ /* no parity, 1 stop bit, async, 1:16 */
++ { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x64 },
++ /* parity error is special cond, ints disabled, no DMA */
++ { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
++ /* Rx 8 bits/char, no auto enable, Rx off */
++ { RX_CTRL_REG, RCR_CHSIZE_8 },
++ /* DTR off, Tx 8 bits/char, RTS off, Tx off */
++ { TX_CTRL_REG, TCR_CHSIZE_8 },
++ /* special features off */
++ { AUX2_CTRL_REG, 0 },
++ /* RTxC is XTAL, TRxC is input, both clocks = RTxC */
++ { CLK_CTRL_REG, CCR_TRxCOUT_XTAL | CCR_TXCLK_RTxC | CCR_RXCLK_RTxC },
++ { DPLL_CTRL_REG, 0 },
++ /* Start Rx */
++ { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
++ /* Start Tx */
++ { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
++ /* Ext/Stat ints: CTS, DCD, SYNC (DSR) */
++ { INT_CTRL_REG, ICR_ENAB_DCD_INT | ICR_ENAB_CTS_INT | ICR_ENAB_SYNC_INT },
++ /* Reset Ext/Stat ints */
++ { COMMAND_REG, CR_EXTSTAT_RESET },
++ /* ...again */
++ { COMMAND_REG, CR_EXTSTAT_RESET },
++ /* Rx int always, TX int off, Ext/Stat int on */
++ { INT_AND_DMA_REG, IDR_EXTSTAT_INT_ENAB |
++ IDR_PARERR_AS_SPCOND | IDR_RX_INT_ALL }
++ };
++
++ if (atari_SCC_init_done && line == 1)
++ return -ENODEV;
++
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: open port ...\n");
++#endif
++ if (!(port->gs.flags & ASYNC_INITIALIZED)) {
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: init port ...\n");
++#endif
++ local_irq_save(flags);
++
++ SCCmod(MASTER_INT_CTRL, 0x3f,
++ channel == 0 ? MIC_CH_A_RESET : MIC_CH_B_RESET);
++ udelay(40); /* extra delay after a reset */
++
++ for (i = 0; i < sizeof(scc_init_tab)/sizeof(*scc_init_tab); ++i)
++ SCCwrite(scc_init_tab[i].reg, scc_init_tab[i].val);
++
++
++ /* remember status register for detection of DCD and CTS changes */
++ scc_last_status_reg[channel] = SCCread(STATUS_REG);
++
++ port->c_dcd = 0; /* Prevent initial 1->0 interrupt */
++ scc_setsignals(port, 1, 1);
++ local_irq_restore(flags);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: init port done!\n");
++#endif
++ }
++
++ tty->driver_data = port;
++ port->gs.tty = tty;
++ port->gs.count++;
++#ifdef DEBUG
++ printk(KERN_WARNING "SCC: gs init port ...\n");
++#endif
++ retval = gs_init_port(&port->gs);
++ if (retval) {
++ port->gs.count--;
++ return retval;
++ }
++#ifdef DEBUG
++ printk(KERN_WARNING "SCC: gs init port done!\n");
++#endif
++ port->gs.flags |= GS_ACTIVE;
++
++#ifdef DEBUG
++ printk(KERN_WARNING "SCC: gs wait ready ...\n");
++#endif
++ retval = gs_block_til_ready(port, filp);
++#ifdef DEBUG
++ printk(KERN_WARNING "SCC: gs wait ready done!\n");
++#endif
++ if (retval) {
++ port->gs.count--;
++ return retval;
++ }
++
++ port->c_dcd = scc_get_CD(port);
++
++#ifdef DEBUG
++ printk(KERN_WARNING "SCC: enable rx ints ...\n");
++#endif
++ scc_enable_rx_interrupts(port);
++#ifdef DEBUG
++ printk(KERN_WARNING "SCC: enable rx ints done!\n");
++
++ printk(KERN_INFO "SCC: open port done!\n");
++#endif
++ return 0;
++}
++
++
++static void scc_throttle(struct tty_struct *tty)
++{
++ struct scc_port *port = (struct scc_port *)tty->driver_data;
++ unsigned long flags;
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: throttle ...\n");
++#endif
++ if (tty->termios->c_cflag & CRTSCTS) {
++ local_irq_save(flags);
++ SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
++ local_irq_restore(flags);
++ }
++ if (I_IXOFF(tty))
++ scc_send_xchar(tty, STOP_CHAR(tty));
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: throttle done!\n");
++#endif
++}
++
++
++static void scc_unthrottle(struct tty_struct *tty)
++{
++ struct scc_port *port = (struct scc_port *)tty->driver_data;
++ unsigned long flags;
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: unthrottle ...\n");
++#endif
++ if (tty->termios->c_cflag & CRTSCTS) {
++ local_irq_save(flags);
++ SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);
++ local_irq_restore(flags);
++ }
++ if (I_IXOFF(tty))
++ scc_send_xchar(tty, START_CHAR(tty));
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: unthrottle done!\n");
++#endif
++}
++
++
++static int scc_ioctl(struct tty_struct *tty, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ struct scc_port *port = (struct scc_port *)tty->driver_data;
++ int retval;
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl! cmd %d, arg %p \n", cmd, arg);
++#endif
++ //if (serial_paranoia_check(info, tty->device, "zs_ioctl"))
++ // return -ENODEV;
++
++ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
++ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
++ (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
++ if (tty->flags & (1 << TTY_IO_ERROR))
++ return -EIO;
++ }
++
++ switch (cmd) {
++ case TCSBRK: /* SVID version: non-zero arg --> no break */
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl TCSBRK\n");
++#endif
++ retval = tty_check_change(tty);
++ if (retval)
++ return retval;
++ tty_wait_until_sent(tty, 0);
++ //if (!arg)
++ // send_break(info, HZ/4); /* 1/4 second */
++ return 0;
++ case TCSBRKP: /* support for POSIX tcsendbreak() */
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl TCSBRKP\n");
++#endif
++ retval = tty_check_change(tty);
++ if (retval)
++ return retval;
++ tty_wait_until_sent(tty, 0);
++ //send_break(info, arg ? arg*(HZ/10) : HZ/4);
++ return 0;
++ case TIOCGSOFTCAR:
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl TIOCGSOFTCAR\n");
++#endif
++ if (put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg))
++ return -EFAULT;
++ return 0;
++ case TIOCSSOFTCAR:
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl TIOCSSOFTCAR\n");
++#endif
++ if (get_user(arg, (unsigned long *)arg))
++ return -EFAULT;
++ tty->termios->c_cflag =
++ ((tty->termios->c_cflag & ~CLOCAL) |
++ (arg ? CLOCAL : 0));
++ return 0;
++ case TIOCMGET:
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl TIOCMGET\n");
++#endif
++ //return get_modem_info(info, (unsigned int *)arg);
++ return 0;
++ case TIOCMBIS:
++ case TIOCMBIC:
++ case TIOCMSET:
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl TIOCMSET\n");
++#endif
++ //return set_modem_info(info, cmd, (unsigned int *)arg);
++ return 0;
++ case TIOCGSERIAL:
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl TIOCGSERIAL\n");
++#endif
++ return 0;
++ //return get_serial_info(info,
++ // (struct serial_struct *)arg);
++ case TIOCSSERIAL:
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl TIOCSSERIAL\n");
++#endif
++ return 0;
++ //return set_serial_info(info,
++ // (struct serial_struct *)arg);
++ case TIOCSERGETLSR: /* Get line status register */
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl TIOCSERGETLSR\n");
++#endif
++ return 0;
++ //return get_lsr_info(info, (unsigned int *)arg);
++
++ case TIOCSERGSTRUCT:
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl TIOCSERGSTRUCT\n");
++#endif
++ return 0;
++ if (copy_to_user((struct scc_port *)arg,
++ port, sizeof(struct scc_port)))
++ return -EFAULT;
++ return 0;
++
++ default:
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: ioctl default\n");
++#endif
++ return -ENOIOCTLCMD;
++ }
++ return 0;
++}
++
++
++static void scc_break_ctl(struct tty_struct *tty, int break_state)
++{
++ struct scc_port *port = (struct scc_port *)tty->driver_data;
++ unsigned long flags;
++ SCC_ACCESS_INIT(port);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: break ctl ...\n");
++#endif
++ local_irq_save(flags);
++ SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, break_state ? TCR_SEND_BREAK : 0);
++ local_irq_restore(flags);
++#ifdef DEBUG
++ printk(KERN_INFO "SCC: break ctl done!\n");
++#endif
++}
++
++
++/*---------------------------------------------------------------------------
++ * Serial console stuff...
++ *--------------------------------------------------------------------------*/
++#if 1
++#define scc_delay() \
++ asm volatile ("tstb %0" : : "m" (*scc_del) : "cc")
++
++#define SCC_WRITE(reg,val) \
++ do { \
++ scc.cha_b_ctrl = (reg); \
++ scc_delay(); \
++ scc.cha_b_ctrl = (val); \
++ scc_delay(); \
++ } while (0)
++
++/* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
++ * delay of ~ 60us. */
++#define LONG_DELAY() \
++ do { \
++ int i; \
++ for (i = 100; i > 0; --i) \
++ scc_delay(); \
++ } while (0)
++
++static void atari_init_scc_port(int cflag)
++{
++ extern int atari_SCC_reset_done;
++ static int clksrc_table[9] =
++ /* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
++ { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
++ static int brgsrc_table[9] =
++ /* reg 14: 0 = RTxC, 2 = PCLK */
++ { 2, 2, 2, 2, 2, 2, 0, 2, 2 };
++ static int clkmode_table[9] =
++ /* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
++ { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
++ static int div_table[9] =
++ /* reg12 (BRG low) */
++ { 208, 138, 103, 50, 24, 11, 1, 0, 0 };
++
++ int baud = cflag & CBAUD;
++ int clksrc, clkmode, div, reg3, reg5;
++
++ scc_del = &mfp.par_dt_reg;
++
++ if (cflag & CBAUDEX)
++ baud += B38400;
++ if (baud < B1200 || baud > B38400+2)
++ baud = B9600; /* use default 9600bps for non-implemented rates */
++ baud -= B1200; /* tables starts at 1200bps */
++
++ clksrc = clksrc_table[baud];
++ clkmode = clkmode_table[baud];
++ div = div_table[baud];
++ if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
++ /* special treatment for TT, where rates >= 38400 are done via TRxC */
++ clksrc = 0x28; /* TRxC */
++ clkmode = baud == 6 ? 0xc0 :
++ baud == 7 ? 0x80 : /* really 76800bps */
++ 0x40; /* really 153600bps */
++ div = 0;
++ }
++
++ reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
++ reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
++
++ (void)scc.cha_b_ctrl; /* reset reg pointer */
++ SCC_WRITE(9, 0xc0); /* reset */
++ LONG_DELAY(); /* extra delay after WR9 access */
++ SCC_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
++ 0x04 /* 1 stopbit */ |
++ clkmode);
++ SCC_WRITE(3, reg3);
++ SCC_WRITE(5, reg5);
++ SCC_WRITE(9, 0); /* no interrupts */
++ LONG_DELAY(); /* extra delay after WR9 access */
++ SCC_WRITE(10, 0); /* NRZ mode */
++ SCC_WRITE(11, clksrc); /* main clock source */
++ SCC_WRITE(12, div); /* BRG value */
++ SCC_WRITE(13, 0); /* BRG high byte */
++ SCC_WRITE(14, brgsrc_table[baud]);
++ SCC_WRITE(14, brgsrc_table[baud] | (div ? 1 : 0));
++ SCC_WRITE(3, reg3 | 1);
++ SCC_WRITE(5, reg5 | 8);
++
++ atari_SCC_reset_done = 1;
++ atari_SCC_init_done = 1;
++}
++
++static void scc_ch_write(char ch)
++{
++ volatile char *p = NULL;
++
++ if (MACH_IS_TT || MACH_IS_FALCON)
++ p = (volatile char *)&scc.cha_b_ctrl;
++
++ if (MACH_IS_ST)
++ p = (volatile char *)&scc.cha_b_ctrl;
++
++ if (MACH_IS_STE)
++ p = (volatile char *)&st_escc.cha_b_ctrl;
++
++ do {
++ scc_delay();
++ }
++ while (!(*p & 4));
++ // scc_delay();
++ // *p = 8;
++ scc_delay();
++ *(p+1) = ch;
++}
++
++/* The console must be locked when we get here. */
++
++static void scc_console_write(struct console *co, const char *str, unsigned count)
++{
++ unsigned long flags;
++
++ //printk("scc_console_write: %s\n", str);
++ local_irq_save(flags);
++
++ while (count--) {
++ if (*str == '\n')
++ scc_ch_write('\r');
++ scc_ch_write(*str++);
++ }
++ local_irq_restore(flags);
++ //printk("scc_console_write done!\n");
++}
++
++static struct tty_driver *scc_console_device(struct console *c, int *index)
++{
++ *index = c->index;
++ return scc_driver;
++}
++
++
++static int __init scc_console_setup(struct console *co, char *options)
++{
++ printk("scc_console_setup: initializing SCC port B\n");
++ atari_init_scc_port(B9600|CS8);
++ printk("scc_console_setup: done!\n");
++ return 0;
++}
++
++
++static struct console sercons = {
++ .name = "ttyS",
++ .write = scc_console_write,
++ .device = scc_console_device,
++ .setup = scc_console_setup,
++ .flags = CON_PRINTBUFFER,
++ .index = -1,
++};
++
++
++static int __init vme_scc_console_init(void)
++{
++ if (MACH_IS_TT || MACH_IS_ST || MACH_IS_FALCON)
++ register_console(&sercons);
++ return 0;
++}
++
++console_initcall(vme_scc_console_init);
++#endif
++
++/***************************** End of Functions *********************/
++
++MODULE_AUTHOR("Michael Schmitz");
++MODULE_DESCRIPTION("Atari Amd8350 SCC serial driver");
++MODULE_LICENSE("GPL");
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/falconide-fix-ide_release_lock-imbalance.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/falconide-fix-ide_release_lock-imbalance.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,36 @@
+From schmitz at opal.biophys.uni-duesseldorf.de Fri Jun 27 10:42:06 2008
+Date: Fri, 27 Jun 2008 10:40:43 +0200 (CEST)
+From: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+To: Michael Schmitz <schmitz at opal.biophys.uni-duesseldorf.de>
+Cc: Stephen R Marenka <stephen at marenka.net>, linux-m68k at vger.kernel.org, Geert Uytterhoeven <geert at linux-m68k.org>
+Subject: Re: ide_release_lock: bug
+
+Hi,
+
+The following patch does, indeed, fix the ide_release_lock imbalance. No
+more warnings.
+
+Signed-off-by: <schmitz at biophys.uni-duesseldorf.de>
+---
+ drivers/ide/ide-io.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/ide/ide-io.c
++++ b/drivers/ide/ide-io.c
+@@ -967,14 +967,13 @@ static void ide_do_request (ide_hwgroup_
+ ide_startstop_t startstop;
+ int loops = 0;
+
+- /* for atari only: POSSIBLY BROKEN HERE(?) */
+- ide_get_lock(ide_intr, hwgroup);
+-
+ /* caller must own ide_lock */
+ BUG_ON(!irqs_disabled());
+
+ while (!hwgroup->busy) {
+ hwgroup->busy = 1;
++ /* for atari only */
++ ide_get_lock(ide_intr, hwgroup);
+ drive = choose_drive(hwgroup);
+ if (drive == NULL) {
+ int sleeping = 0;
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/fbcon-protect-free-irq-by-MACH_IS_ATARI-check.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/fbcon-protect-free-irq-by-MACH_IS_ATARI-check.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,25 @@
+Subject: [PATCH] fbcon: Protect free_irq() by MACH_IS_ATARI check
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Add missing check for Atari in free_irq() call, which could cause problems on
+multi-platform m68k kernels.
+
+Reported-by: Brad Boyer <flar at allandria.com>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/video/console/fbcon.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/video/console/fbcon.c
++++ b/drivers/video/console/fbcon.c
+@@ -3458,7 +3458,8 @@ static void fbcon_exit(void)
+ return;
+
+ #ifdef CONFIG_ATARI
+- free_irq(IRQ_AUTO_4, fb_vbl_handler);
++ if (MACH_IS_ATARI)
++ free_irq(IRQ_AUTO_4, fb_vbl_handler);
+ #endif
+
+ kfree((void *)softback_buf);
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/fbcon-remove-broken-mac-vbl-handler.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/fbcon-remove-broken-mac-vbl-handler.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,145 @@
+Subject: [PATCH] fbcon: remove broken mac vbl handler
+cc: linux-fbdev-devel at lists.sourceforge.net
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Remove the Mac VBL interrupt code as it doesn't work properly and
+doesn't bring any benefit when fixed. Also remove unused
+DEFAULT_CURSOR_BLINK_RATE macro and irqres variable.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/video/console/fbcon.c | 75 +-----------------------------------------
+ 1 file changed, 3 insertions(+), 72 deletions(-)
+
+--- a/drivers/video/console/fbcon.c
++++ b/drivers/video/console/fbcon.c
+@@ -81,9 +81,6 @@
+ #ifdef CONFIG_ATARI
+ #include <asm/atariints.h>
+ #endif
+-#ifdef CONFIG_MAC
+-#include <asm/macints.h>
+-#endif
+ #if defined(__mc68000__)
+ #include <asm/machdep.h>
+ #include <asm/setup.h>
+@@ -160,8 +157,6 @@ static int fbcon_set_origin(struct vc_da
+
+ /* # VBL ints between cursor state changes */
+ #define ATARI_CURSOR_BLINK_RATE (42)
+-#define MAC_CURSOR_BLINK_RATE (32)
+-#define DEFAULT_CURSOR_BLINK_RATE (20)
+
+ static int vbl_cursor_cnt;
+ static int fbcon_cursor_noblink;
+@@ -210,19 +205,6 @@ static void fbcon_start(void);
+ static void fbcon_exit(void);
+ static struct device *fbcon_device;
+
+-#ifdef CONFIG_MAC
+-/*
+- * On the Macintoy, there may or may not be a working VBL int. We need to probe
+- */
+-static int vbl_detected;
+-
+-static irqreturn_t fb_vbl_detect(int irq, void *dummy)
+-{
+- vbl_detected++;
+- return IRQ_HANDLED;
+-}
+-#endif
+-
+ #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
+ static inline void fbcon_set_rotation(struct fb_info *info)
+ {
+@@ -421,7 +403,7 @@ static void fb_flashcursor(struct work_s
+ release_console_sem();
+ }
+
+-#if defined(CONFIG_ATARI) || defined(CONFIG_MAC)
++#ifdef CONFIG_ATARI
+ static int cursor_blink_rate;
+ static irqreturn_t fb_vbl_handler(int irq, void *dev_id)
+ {
+@@ -949,9 +931,7 @@ static const char *fbcon_startup(void)
+ struct fb_info *info = NULL;
+ struct fbcon_ops *ops;
+ int rows, cols;
+- int irqres;
+
+- irqres = 1;
+ /*
+ * If num_registered_fb is zero, this is a call for the dummy part.
+ * The frame buffer devices weren't initialized yet.
+@@ -1040,56 +1020,11 @@ static const char *fbcon_startup(void)
+ #ifdef CONFIG_ATARI
+ if (MACH_IS_ATARI) {
+ cursor_blink_rate = ATARI_CURSOR_BLINK_RATE;
+- irqres =
+- request_irq(IRQ_AUTO_4, fb_vbl_handler,
++ (void)request_irq(IRQ_AUTO_4, fb_vbl_handler,
+ IRQ_TYPE_PRIO, "framebuffer vbl",
+ info);
+ }
+-#endif /* CONFIG_ATARI */
+-
+-#ifdef CONFIG_MAC
+- /*
+- * On a Macintoy, the VBL interrupt may or may not be active.
+- * As interrupt based cursor is more reliable and race free, we
+- * probe for VBL interrupts.
+- */
+- if (MACH_IS_MAC) {
+- int ct = 0;
+- /*
+- * Probe for VBL: set temp. handler ...
+- */
+- irqres = request_irq(IRQ_MAC_VBL, fb_vbl_detect, 0,
+- "framebuffer vbl", info);
+- vbl_detected = 0;
+-
+- /*
+- * ... and spin for 20 ms ...
+- */
+- while (!vbl_detected && ++ct < 1000)
+- udelay(20);
+-
+- if (ct == 1000)
+- printk
+- ("fbcon_startup: No VBL detected, using timer based cursor.\n");
+-
+- free_irq(IRQ_MAC_VBL, fb_vbl_detect);
+-
+- if (vbl_detected) {
+- /*
+- * interrupt based cursor ok
+- */
+- cursor_blink_rate = MAC_CURSOR_BLINK_RATE;
+- irqres =
+- request_irq(IRQ_MAC_VBL, fb_vbl_handler, 0,
+- "framebuffer vbl", info);
+- } else {
+- /*
+- * VBL not detected: fall through, use timer based cursor
+- */
+- irqres = 1;
+- }
+- }
+-#endif /* CONFIG_MAC */
++#endif /* CONFIG_ATARI */
+
+ fbcon_add_cursor_timer(info);
+ fbcon_has_exited = 0;
+@@ -3525,10 +3460,6 @@ static void fbcon_exit(void)
+ #ifdef CONFIG_ATARI
+ free_irq(IRQ_AUTO_4, fb_vbl_handler);
+ #endif
+-#ifdef CONFIG_MAC
+- if (MACH_IS_MAC && vbl_detected)
+- free_irq(IRQ_MAC_VBL, fb_vbl_handler);
+-#endif
+
+ kfree((void *)softback_buf);
+ softback_buf = 0UL;
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-PRIVATE-m68k-changes.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-PRIVATE-m68k-changes.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,29 @@
+Subject: [PATCH] Local m68k changes
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Local m68k changes, _NEVER_ to be submitted upstream:
+ - Force ARCH to be m68k
+ - Append `-m68k' to EXTRAVERSION
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org> for m68k CVS only
+---
+ Makefile | 2 +-
+ localversion.m68k | 1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+--- a/Makefile
++++ b/Makefile
+@@ -190,7 +190,7 @@ SUBARCH := $(shell uname -m | sed -e s/i
+ # Default value for CROSS_COMPILE is not to prefix executables
+ # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
+ export KBUILD_BUILDHOST := $(SUBARCH)
+-ARCH ?= $(SUBARCH)
++ARCH ?= m68k
+ CROSS_COMPILE ?=
+
+ # Architecture as present in compile.h
+--- /dev/null
++++ b/localversion.m68k
+@@ -0,0 +1 @@
++-m68k
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-add-install-target.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-add-install-target.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,82 @@
+From Laurent at lvivier.info Thu Oct 30 21:23:26 2008
+Date: Thu, 30 Oct 2008 21:17:47 +0100
+From: Laurent at lvivier.info
+To: geert at linux-m68k.org
+Cc: linux-m68k at vger.kernel.org, Laurent Vivier <Laurent at lvivier.info>
+Subject: [PATCH] Add install target for m68k architecture.
+
+From: Laurent Vivier <Laurent at lvivier.info>
+
+This patch enables the use of "make install" on m68k architecture
+to copy kernel to /boot.
+
+Signed-off-by: Laurent Vivier <Laurent at lvivier.info>
+---
+ arch/m68k/Makefile | 3 ++
+ arch/m68k/install.sh | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 55 insertions(+)
+
+--- a/arch/m68k/Makefile
++++ b/arch/m68k/Makefile
+@@ -118,3 +118,6 @@ endif
+
+ archclean:
+ rm -f vmlinux.gz vmlinux.bz2
++
++install:
++ sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
+--- /dev/null
++++ b/arch/m68k/install.sh
+@@ -0,0 +1,52 @@
++#!/bin/sh
++#
++# 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.
++#
++# Copyright (C) 1995 by Linus Torvalds
++#
++# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
++#
++# "make install" script for m68k architecture
++#
++# Arguments:
++# $1 - kernel version
++# $2 - kernel image file
++# $3 - kernel map file
++# $4 - default install path (blank if root directory)
++#
++
++verify () {
++ if [ ! -f "$1" ]; then
++ echo "" 1>&2
++ echo " *** Missing file: $1" 1>&2
++ echo ' *** You need to run "make" before "make install".' 1>&2
++ echo "" 1>&2
++ exit 1
++ fi
++}
++
++# Make sure the files actually exist
++verify "$2"
++verify "$3"
++
++# User may have a custom install script
++
++if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
++if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
++
++# Default install - same as make zlilo
++
++if [ -f $4/vmlinuz ]; then
++ mv $4/vmlinuz $4/vmlinuz.old
++fi
++
++if [ -f $4/System.map ]; then
++ mv $4/System.map $4/System.old
++fi
++
++cat $2 > $4/vmlinuz
++cp $3 $4/System.map
++
++sync
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-allow-all-kernel-traps-to-be-handled-via-exception-fixups-all.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-allow-all-kernel-traps-to-be-handled-via-exception-fixups-all.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,185 @@
+From: Andreas Schwab <andreas at ubb.ca>
+
+Allow all kernel traps to be handled via exception fixups.
+
+Signed-off-by: Andreas Schwab <schwab at suse.de>
+
+--------------------
+
+From: Roman Zippel <zippel at linux-m68k.org>
+
+Add helper function handle_kernel_fault() in signal.c, so
+frame_extra_sizes can become static and to reduce code duplication.
+Use base_trap_init() to initialize vectors, so basic initialization is
+all in one place.
+Remove the VEC_TRACE check from trap_c, I can only guess it's left from
+an old kgdb patch, as right now it does nothing.
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+
+--------------------
+
+From: Andreas Schwab <andreas at ubb.ca>
+
+Reinstate VEC_TRACE check, needed for 68020/30.
+
+Signed-off-by: Andreas Schwab <schwab at suse.de>
+
+--------------------
+
+From: Roman Zippel <zippel at ubb.ca>
+
+no need to set TIF_DELAYED_TRACE
+
+Signed-off-by: Roman Zippel <zippel at linux-m68k.org>
+
+---
+ arch/m68k/kernel/signal.c | 24 +++++++++++++++++++++++-
+ arch/m68k/kernel/traps.c | 21 ++++++++++++---------
+ arch/m68k/mm/fault.c | 16 +---------------
+ include/asm-m68k/processor.h | 2 ++
+ 4 files changed, 38 insertions(+), 25 deletions(-)
+
+--- a/arch/m68k/kernel/signal.c
++++ b/arch/m68k/kernel/signal.c
+@@ -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>
+@@ -53,7 +54,7 @@
+
+ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
+
+-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),
+@@ -71,6 +72,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.
+ */
+--- a/arch/m68k/kernel/traps.c
++++ b/arch/m68k/kernel/traps.c
+@@ -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,10 +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 */
+- current->ptrace |= PT_DTRACE;
+- } 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;
+ }
+--- a/arch/m68k/mm/fault.c
++++ b/arch/m68k/mm/fault.c
+@@ -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,
+--- a/include/asm-m68k/processor.h
++++ b/include/asm-m68k/processor.h
+@@ -127,4 +127,6 @@ unsigned long get_wchan(struct task_stru
+
+ #define cpu_relax() barrier()
+
++extern int handle_kernel_fault(struct pt_regs *regs);
++
+ #endif
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-fpsp040-fix-trigraph-ignored-warning.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-fpsp040-fix-trigraph-ignored-warning.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,27 @@
+Subject: [PATCH] m68k: fix trigraph ignored warning in setox.S
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Fix the warning: trigraph ??/ ignored, use -trigraphs to enable
+caused by the recent removal of -traditional option.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/fpsp040/setox.S | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/m68k/fpsp040/setox.S
++++ b/arch/m68k/fpsp040/setox.S
+@@ -36,9 +36,9 @@
+ | depending on their values, the program may run faster or slower --
+ | but no worse than 10% slower even in the extreme cases.
+ |
+-| The program setoxm1 takes approximately ???/??? cycles for input
++| The program setoxm1 takes approximately ??? / ??? cycles for input
+ | argument X, 0.25 <= |X| < 70log2. For |X| < 0.25, it takes
+-| approximately ???/??? cycles. For the less common arguments,
++| approximately ??? / ??? cycles. For the less common arguments,
+ | depending on their values, the program may run faster or slower --
+ | but no worse than 10% slower even in the extreme cases.
+ |
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-noswap-linux-swap-h-needs-linux-pagemap-h.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-noswap-linux-swap-h-needs-linux-pagemap-h.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,47 @@
+Subject: [PATCH] CONFIG_SWAP=n: include/linux/swap.h needs <linux/pagemap.h>
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+When compiling a m68k kernel with CONFIG_SWAP=n, I get:
+
+ include/asm-generic/tlb.h: In function 'tlb_flush_mmu':
+ include/asm-generic/tlb.h:76: error: implicit declaration of function 'release_pages'
+ include/asm-generic/tlb.h: In function 'tlb_remove_page':
+ include/asm-generic/tlb.h:105: error: implicit declaration of function 'page_cache_release'
+
+because include/linux/swap.h defines free_page_and_swap_cache() and
+free_pages_and_swap_cache() to page_cache_release() resp. release_pages()
+without including <linux/pagemap.h>.
+
+As the comment in include/linux/swap.h says it cannot include <linux/pagemap.h>
+on sparc
+---
+ include/asm-generic/tlb.h | 5 +++++
+ include/linux/swap.h | 2 ++
+ 2 files changed, 7 insertions(+)
+
+--- a/include/asm-generic/tlb.h
++++ b/include/asm-generic/tlb.h
+@@ -14,6 +14,11 @@
+ #define _ASM_GENERIC__TLB_H
+
+ #include <linux/swap.h>
++
++#ifndef CONFIG_SWAP
++#include <linux/pagemap.h>
++#endif
++
+ #include <asm/pgalloc.h>
+ #include <asm/tlbflush.h>
+
+--- a/include/linux/swap.h
++++ b/include/linux/swap.h
+@@ -334,6 +334,8 @@ static inline void disable_swap_token(vo
+
+ #else /* CONFIG_SWAP */
+
++//#include <linux/pagemap.h>
++
+ #define total_swap_pages 0
+ #define total_swapcache_pages 0UL
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-replace-linux-68k-by-linux-m68k.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-replace-linux-68k-by-linux-m68k.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,591 @@
+Subject: [PATCH] m68k: Replace `Linux/68k' by `Linux/m68k'
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+m68k: Replace `Linux/68k' by `Linux/m68k'
+
+We switched to `Linux/m68k' a very long time ago
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ CREDITS | 6 +++---
+ Documentation/crypto/descore-readme.txt | 2 +-
+ Documentation/devices.txt | 10 +++++-----
+ Documentation/m68k/kernel-options.txt | 2 +-
+ arch/m68k/Kconfig | 2 +-
+ arch/m68k/ifpsp060/iskeleton.S | 6 +++---
+ arch/m68k/ifpsp060/os.S | 4 ++--
+ arch/m68k/kernel/head.S | 4 ++--
+ arch/m68knommu/Kconfig | 4 ++--
+ arch/m68knommu/include/asm/bootstd.h | 2 +-
+ arch/m68knommu/include/asm/delay.h | 2 +-
+ arch/m68knommu/include/asm/elf.h | 2 +-
+ arch/m68knommu/include/asm/entry.h | 2 +-
+ arch/m68knommu/include/asm/processor.h | 2 +-
+ arch/m68knommu/platform/68328/ints.c | 2 +-
+ drivers/char/ser_a2232fw.ax | 2 +-
+ drivers/macintosh/via-cuda.c | 2 +-
+ drivers/macintosh/via-pmu68k.c | 8 ++++----
+ drivers/net/a2065.c | 4 ++--
+ drivers/net/a2065.h | 4 ++--
+ drivers/net/apne.c | 2 +-
+ drivers/net/lib8390.c | 2 +-
+ drivers/net/macmace.c | 4 ++--
+ drivers/net/pcmcia/axnet_cs.c | 2 +-
+ drivers/net/sonic.h | 2 +-
+ drivers/scsi/NCR5380.c | 2 +-
+ drivers/scsi/atari_NCR5380.c | 2 +-
+ drivers/scsi/sun3_NCR5380.c | 2 +-
+ drivers/serial/68360serial.c | 2 +-
+ drivers/video/macfb.c | 4 ++--
+ drivers/video/valkyriefb.c | 2 +-
+ drivers/video/valkyriefb.h | 2 +-
+ fs/affs/Changes | 2 +-
+ include/asm-m68k/elf.h | 2 +-
+ include/asm-xtensa/bootparam.h | 2 +-
+ include/linux/pmu.h | 4 ++--
+ 36 files changed, 55 insertions(+), 55 deletions(-)
+
+--- a/CREDITS
++++ b/CREDITS
+@@ -174,7 +174,7 @@ N: Ralf Baechle
+ E: ralf at gnu.org
+ P: 1024/AF7B30C1 CF 97 C2 CC 6D AE A7 FE C8 BA 9C FC 88 DE 32 C3
+ D: Linux/MIPS port
+-D: Linux/68k hacker
++D: Linux/m68k hacker
+ S: Hauptstrasse 19
+ S: 79837 St. Blasien
+ S: Germany
+@@ -1561,7 +1561,7 @@ E: dhd at eradicator.org
+ E: dhd at cepstral.com
+ D: PA-RISC port
+ D: Nubus subsystem
+-D: Generic 68k Macintosh framebuffer driver
++D: Generic m68k Macintosh framebuffer driver
+ D: STI framebuffer tweaks
+ D: LTPC driver tweaks
+ S: 110 S. 12th St., Apt. A
+@@ -2145,7 +2145,7 @@ D: dv1394
+
+ N: Hamish Macdonald
+ E: hamishm at lucent.com
+-D: Linux/68k port
++D: Linux/m68k port
+ S: 32 Clydesdale Avenue
+ S: Kanata, Ontario
+ S: Canada K2M-2G7
+--- a/Documentation/crypto/descore-readme.txt
++++ b/Documentation/crypto/descore-readme.txt
+@@ -249,7 +249,7 @@ b) the compiler may be too stupid to rea
+
+ i assume that indexing is cheaper or equivalent to auto increment/decrement,
+ where the index is 7 bits unsigned or smaller.
+-this assumption is reversed for 68k and vax.
++this assumption is reversed for m68k and vax.
+
+ i assume that addresses can be cheaply formed from two registers,
+ or from a register and a small constant.
+--- a/Documentation/devices.txt
++++ b/Documentation/devices.txt
+@@ -19,8 +19,8 @@ The LaTeX version of this document is no
+ This document is included by reference into the Filesystem Hierarchy
+ Standard (FHS). The FHS is available from http://www.pathname.com/fhs/.
+
+-Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga
+-platform only. Allocations marked (68k/Atari) apply to Linux/68k on
++Allocations marked (m68k/Amiga) apply to Linux/m68k on the Amiga
++platform only. Allocations marked (m68k/Atari) apply to Linux/m68k on
+ the Atari platform only.
+
+ The symbol {2.6} means the allocation is obsolete and scheduled for
+@@ -328,7 +328,7 @@ Your cooperation is appreciated.
+ 2 = /dev/inportbm Microsoft Inport bus mouse
+ 3 = /dev/atibm ATI XL bus mouse
+ 4 = /dev/jbm J-mouse
+- 4 = /dev/amigamouse Amiga mouse (68k/Amiga)
++ 4 = /dev/amigamouse Amiga mouse (m68k/Amiga)
+ 5 = /dev/atarimouse Atari mouse
+ 6 = /dev/sunmouse Sun mouse
+ 7 = /dev/amigamouse1 Second Amiga mouse
+@@ -691,7 +691,7 @@ Your cooperation is appreciated.
+ 2 = /dev/staliomem2 Third Stallion card I/O memory
+ 3 = /dev/staliomem3 Fourth Stallion card I/O memory
+
+- 28 char Atari SLM ACSI laser printer (68k/Atari)
++ 28 char Atari SLM ACSI laser printer (m68k/Atari)
+ 0 = /dev/slm0 First SLM laser printer
+ 1 = /dev/slm1 Second SLM laser printer
+ ...
+@@ -701,7 +701,7 @@ Your cooperation is appreciated.
+ 2 = /dev/sbpcd14 Panasonic CD-ROM controller 3 unit 2
+ 3 = /dev/sbpcd15 Panasonic CD-ROM controller 3 unit 3
+
+- 28 block ACSI disk (68k/Atari)
++ 28 block ACSI disk (m68k/Atari)
+ 0 = /dev/ada First ACSI disk whole disk
+ 16 = /dev/adb Second ACSI disk whole disk
+ 32 = /dev/adc Third ACSI disk whole disk
+--- a/Documentation/m68k/kernel-options.txt
++++ b/Documentation/m68k/kernel-options.txt
+@@ -852,7 +852,7 @@ use of this option is now highly unrecom
+ Incorrect use can lead to unpredictable behavior, so please only use
+ this option if you *know* what you are doing and have a reason to do
+ so. In any case if you experience problems and need to use this
+-option, please inform us about it by mailing to the Linux/68k kernel
++option, please inform us about it by mailing to the Linux/m68k kernel
+ mailing list.
+
+ The address mask set by this option specifies which addresses are
+--- a/arch/m68k/Kconfig
++++ b/arch/m68k/Kconfig
+@@ -58,7 +58,7 @@ config HZ
+ int
+ default 100
+
+-mainmenu "Linux/68k Kernel Configuration"
++mainmenu "Linux/m68k Kernel Configuration"
+
+ source "init/Kconfig"
+
+--- a/arch/m68k/ifpsp060/iskeleton.S
++++ b/arch/m68k/ifpsp060/iskeleton.S
+@@ -65,7 +65,7 @@
+ | To simply continue execution at the next instruction, just
+ | do an "rte".
+ |
+-| Linux/68k: If returning to user space, check for needed reselections.
++| Linux/m68k: If returning to user space, check for needed reselections.
+
+ .global _060_isp_done
+ _060_isp_done:
+@@ -87,7 +87,7 @@ _060_isp_done:
+ | a CHK exception stack frame from the Unimplemented Integer Instrcution
+ | stack frame and branches to this routine.
+ |
+-| Linux/68k: commented out test for tracing
++| Linux/m68k: commented out test for tracing
+
+ .global _060_real_chk
+ _060_real_chk:
+@@ -127,7 +127,7 @@ real_chk_end:
+ | then it create a Trace exception stack frame from the "chk" exception
+ | stack frame and branches to the _real_trace() entry point.
+ |
+-| Linux/68k: commented out test for tracing
++| Linux/m68k: commented out test for tracing
+
+ .global _060_real_divbyzero
+ _060_real_divbyzero:
+--- a/arch/m68k/ifpsp060/os.S
++++ b/arch/m68k/ifpsp060/os.S
+@@ -65,7 +65,7 @@
+ | The result is that Unix processes are allowed to sleep as a consequence
+ | of a page fault during a _copyout.
+ |
+-| Linux/68k: The _060_[id]mem_{read,write}_{byte,word,long} functions
++| Linux/m68k: The _060_[id]mem_{read,write}_{byte,word,long} functions
+ | (i.e. all the known length <= 4) are implemented by single moves
+ | statements instead of (more expensive) copy{in,out} calls, if
+ | working in user space
+@@ -305,7 +305,7 @@ dmwls: move.l %d0,(%a0) | store super
+ | Assumes that D0/D1/A0/A1 are scratch registers. The _copyin/_copyout
+ | below assume that the SFC/DFC have been set previously.
+ |
+-| Linux/68k: These are basically non-inlined versions of
++| Linux/m68k: These are basically non-inlined versions of
+ | memcpy_{to,from}fs, but without long-transfer optimization
+ | Note: Assumed that SFC/DFC are pointing correctly to user data
+ | space... Should be right, or are there any exceptions?
+--- a/arch/m68k/kernel/head.S
++++ b/arch/m68k/kernel/head.S
+@@ -1,7 +1,7 @@
+ /* -*- mode: asm -*-
+ **
+ ** head.S -- This file contains the initial boot code for the
+-** Linux/68k kernel.
++** Linux/m68k kernel.
+ **
+ ** Copyright 1993 by Hamish Macdonald
+ **
+@@ -1568,7 +1568,7 @@ func_return get_bi_record
+ /*
+ * MMU Initialization Begins Here
+ *
+- * The structure of the MMU tables on the 68k machines
++ * The structure of the MMU tables on the m68k machines
+ * is thus:
+ * Root Table
+ * Logical addresses are translated through
+--- a/arch/m68knommu/Kconfig
++++ b/arch/m68knommu/Kconfig
+@@ -3,7 +3,7 @@
+ # see Documentation/kbuild/kconfig-language.txt.
+ #
+
+-mainmenu "uClinux/68k (w/o MMU) Kernel Configuration"
++mainmenu "uClinux/m68k (w/o MMU) Kernel Configuration"
+
+ config M68K
+ bool
+@@ -185,7 +185,7 @@ config CLOCK_SET
+ help
+ On some CPU's you do not need to know what the core CPU clock
+ frequency is. On these you can disable clock setting. On some
+- traditional 68K parts, and on all ColdFire parts you need to set
++ traditional m68k parts, and on all ColdFire parts you need to set
+ the appropriate CPU clock frequency. On these devices many of the
+ onboard peripherals derive their timing from the master CPU clock
+ frequency.
+--- a/arch/m68knommu/include/asm/bootstd.h
++++ b/arch/m68knommu/include/asm/bootstd.h
+@@ -30,7 +30,7 @@
+ #define __BN_flash_erase_range 19
+ #define __BN_flash_write_range 20
+
+-/* Calling conventions compatible to (uC)linux/68k
++/* Calling conventions compatible to (uC)linux/m68k
+ * We use simmilar macros to call into the bootloader as for uClinux
+ */
+
+--- a/arch/m68knommu/include/asm/delay.h
++++ b/arch/m68knommu/include/asm/delay.h
+@@ -34,7 +34,7 @@ static inline void __delay(unsigned long
+
+ /*
+ * Ideally we use a 32*32->64 multiply to calculate the number of
+- * loop iterations, but the older standard 68k and ColdFire do not
++ * loop iterations, but the older standard m68k and ColdFire do not
+ * have this instruction. So for them we have a clsoe approximation
+ * loop using 32*32->32 multiplies only. This calculation based on
+ * the ARM version of delay.
+--- a/arch/m68knommu/include/asm/elf.h
++++ b/arch/m68knommu/include/asm/elf.h
+@@ -9,7 +9,7 @@
+ #include <asm/user.h>
+
+ /*
+- * 68k ELF relocation types
++ * m68k ELF relocation types
+ */
+ #define R_68K_NONE 0
+ #define R_68K_32 1
+--- a/arch/m68knommu/include/asm/entry.h
++++ b/arch/m68knommu/include/asm/entry.h
+@@ -152,7 +152,7 @@ LENOSYS = 38
+ #else /* !CONFIG_COLDFIRE */
+
+ /*
+- * Standard 68k interrupt entry and exit macros.
++ * Standard m68k interrupt entry and exit macros.
+ */
+ .macro SAVE_ALL
+ clrl %sp at - /* stkadj */
+--- a/arch/m68knommu/include/asm/processor.h
++++ b/arch/m68knommu/include/asm/processor.h
+@@ -80,7 +80,7 @@ struct thread_struct {
+
+ /*
+ * Coldfire stacks need to be re-aligned on trap exit, conventional
+- * 68k can handle this case cleanly.
++ * m68k can handle this case cleanly.
+ */
+ #if defined(CONFIG_COLDFIRE)
+ #define reformat(_regs) do { (_regs)->format = 0x4; } while(0)
+--- a/arch/m68knommu/platform/68328/ints.c
++++ b/arch/m68knommu/platform/68328/ints.c
+@@ -101,7 +101,7 @@ void __init init_vectors(void)
+ IMR = ~0;
+ }
+
+-/* The 68k family did not have a good way to determine the source
++/* The m68k family did not have a good way to determine the source
+ * of interrupts until later in the family. The EC000 core does
+ * not provide the vector number on the stack, we vector everything
+ * into one vector and look in the blasted mask register...
+--- a/drivers/char/ser_a2232fw.ax
++++ b/drivers/char/ser_a2232fw.ax
+@@ -462,7 +462,7 @@ Speedy2 lda ACIA0+A_SR ; read status
+ beq Speedy2 ; not yet, wait more ;
+ stx CIA+C_CTRLA ; stop the timer ;
+ ; ;
+- lda CIA+C_TAL ; copy timer value for 68k ;
++ lda CIA+C_TAL ; copy timer value for m68k ;
+ sta TimerL ; ;
+ lda CIA+C_TAH ; ;
+ sta TimerH ; ;
+--- a/drivers/macintosh/via-cuda.c
++++ b/drivers/macintosh/via-cuda.c
+@@ -157,7 +157,7 @@ int __init find_via_cuda(void)
+ return 0;
+ }
+
+- /* Clear and enable interrupts, but only on PPC. On 68K it's done */
++ /* Clear and enable interrupts, but only on PPC. On m68k it's done */
+ /* for us by the main VIA driver in arch/m68k/mac/via.c */
+
+ out_8(&via[IFR], 0x7f); /* clear interrupts by writing 1s */
+--- a/drivers/macintosh/via-pmu68k.c
++++ b/drivers/macintosh/via-pmu68k.c
+@@ -1,5 +1,5 @@
+ /*
+- * Device driver for the PMU on 68K-based Apple PowerBooks
++ * Device driver for the PMU on m68k-based Apple PowerBooks
+ *
+ * The VIA (versatile interface adapter) interfaces to the PMU,
+ * a 6805 microprocessor core whose primary function is to control
+@@ -8,7 +8,7 @@
+ * to the keyboard and mouse, as well as the non-volatile RAM
+ * and the RTC (real time clock) chip.
+ *
+- * Adapted for 68K PMU by Joshua M. Thompson
++ * Adapted for m68k PMU by Joshua M. Thompson
+ *
+ * Based largely on the PowerMac PMU code by Paul Mackerras and
+ * Fabio Riccardi.
+@@ -120,7 +120,7 @@ static void pmu_enable_backlight(int on)
+ static void pmu_set_brightness(int level);
+
+ struct adb_driver via_pmu_driver = {
+- "68K PMU",
++ "m68k PMU",
+ pmu_probe,
+ pmu_init,
+ pmu_send_request,
+@@ -258,7 +258,7 @@ pmu_init(void)
+ /* Enable backlight */
+ pmu_enable_backlight(1);
+
+- printk("adb: PMU 68K driver v0.5 for Unified ADB.\n");
++ printk("adb: PMU m68k driver v0.5 for Unified ADB.\n");
+
+ return 0;
+ }
+--- a/drivers/net/a2065.c
++++ b/drivers/net/a2065.c
+@@ -1,5 +1,5 @@
+ /*
+- * Amiga Linux/68k A2065 Ethernet Driver
++ * Amiga Linux/m68k A2065 Ethernet Driver
+ *
+ * (C) Copyright 1995-2003 by Geert Uytterhoeven <geert at linux-m68k.org>
+ *
+@@ -12,7 +12,7 @@
+ *
+ * This program is based on
+ *
+- * ariadne.?: Amiga Linux/68k Ariadne Ethernet Driver
++ * ariadne.?: Amiga Linux/m68k Ariadne Ethernet Driver
+ * (C) Copyright 1995 by Geert Uytterhoeven,
+ * Peter De Schrijver
+ *
+--- a/drivers/net/a2065.h
++++ b/drivers/net/a2065.h
+@@ -1,5 +1,5 @@
+ /*
+- * Amiga Linux/68k A2065 Ethernet Driver
++ * Amiga Linux/m68k A2065 Ethernet Driver
+ *
+ * (C) Copyright 1995 by Geert Uytterhoeven <geert at linux-m68k.org>
+ *
+@@ -7,7 +7,7 @@
+ *
+ * This program is based on
+ *
+- * ariadne.?: Amiga Linux/68k Ariadne Ethernet Driver
++ * ariadne.?: Amiga Linux/m68k Ariadne Ethernet Driver
+ * (C) Copyright 1995 by Geert Uytterhoeven,
+ * Peter De Schrijver
+ *
+--- a/drivers/net/apne.c
++++ b/drivers/net/apne.c
+@@ -1,5 +1,5 @@
+ /*
+- * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
++ * Amiga Linux/m68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
+ *
+ * (C) Copyright 1997 Alain Malek
+ * (Alain.Malek at cryogen.com)
+--- a/drivers/net/lib8390.c
++++ b/drivers/net/lib8390.c
+@@ -36,7 +36,7 @@
+ Paul Gortmaker : tweak ANK's above multicast changes a bit.
+ Paul Gortmaker : update packet statistics for v2.1.x
+ Alan Cox : support arbitary stupid port mappings on the
+- 68K Macintosh. Support >16bit I/O spaces
++ m68k Macintosh. Support >16bit I/O spaces
+ Paul Gortmaker : add kmod support for auto-loading of the 8390
+ module by all drivers that require it.
+ Alan Cox : Spinlocking work, added 'BUG_83C690'
+--- a/drivers/net/macmace.c
++++ b/drivers/net/macmace.c
+@@ -1,5 +1,5 @@
+ /*
+- * Driver for the Macintosh 68K onboard MACE controller with PSC
++ * Driver for the Macintosh m68k onboard MACE controller with PSC
+ * driven DMA. The MACE driver code is derived from mace.c. The
+ * Mac68k theory of operation is courtesy of the MacBSD wizards.
+ *
+@@ -249,7 +249,7 @@ static int __devinit mace_probe(struct p
+ dev->set_multicast_list = mace_set_multicast;
+ dev->set_mac_address = mace_set_address;
+
+- printk(KERN_INFO "%s: 68K MACE, hardware address %s\n",
++ printk(KERN_INFO "%s: m68k MACE, hardware address %s\n",
+ dev->name, print_mac(mac, dev->dev_addr));
+
+ err = register_netdev(dev);
+--- a/drivers/net/pcmcia/axnet_cs.c
++++ b/drivers/net/pcmcia/axnet_cs.c
+@@ -850,7 +850,7 @@ module_exit(exit_axnet_cs);
+ Paul Gortmaker : tweak ANK's above multicast changes a bit.
+ Paul Gortmaker : update packet statistics for v2.1.x
+ Alan Cox : support arbitary stupid port mappings on the
+- 68K Macintosh. Support >16bit I/O spaces
++ m68k Macintosh. Support >16bit I/O spaces
+ Paul Gortmaker : add kmod support for auto-loading of the 8390
+ module by all drivers that require it.
+ Alan Cox : Spinlocking work, added 'BUG_83C690'
+--- a/drivers/net/sonic.h
++++ b/drivers/net/sonic.h
+@@ -9,7 +9,7 @@
+ * and pad structure members must be exchanged. Also, the structures
+ * need to be changed accordingly to the bus size.
+ *
+- * 981229 MSch: did just that for the 68k Mac port (32 bit, big endian)
++ * 981229 MSch: did just that for the m68k Mac port (32 bit, big endian)
+ *
+ * 990611 David Huggins-Daines <dhd at debian.org>: This machine abstraction
+ * does not cope with 16-bit bus sizes very well. Therefore I have
+--- a/drivers/scsi/NCR5380.c
++++ b/drivers/scsi/NCR5380.c
+@@ -125,7 +125,7 @@
+ *
+ * This is a generic 5380 driver. To use it on a different platform,
+ * one simply writes appropriate system specific macros (ie, data
+- * transfer - some PC's will use the I/O bus, 68K's must use
++ * transfer - some PC's will use the I/O bus, m68k's must use
+ * memory mapped) and drops this file in their 'C' wrapper.
+ *
+ * (Note from hch: unfortunately it was not enough for the different
+--- a/drivers/scsi/atari_NCR5380.c
++++ b/drivers/scsi/atari_NCR5380.c
+@@ -126,7 +126,7 @@
+ * This driver attempts to address these problems :
+ * This is a generic 5380 driver. To use it on a different platform,
+ * one simply writes appropriate system specific macros (ie, data
+- * transfer - some PC's will use the I/O bus, 68K's must use
++ * transfer - some PC's will use the I/O bus, m68k's must use
+ * memory mapped) and drops this file in their 'C' wrapper.
+ *
+ * As far as command queueing, two queues are maintained for
+--- a/drivers/scsi/sun3_NCR5380.c
++++ b/drivers/scsi/sun3_NCR5380.c
+@@ -120,7 +120,7 @@
+ * This driver attempts to address these problems :
+ * This is a generic 5380 driver. To use it on a different platform,
+ * one simply writes appropriate system specific macros (ie, data
+- * transfer - some PC's will use the I/O bus, 68K's must use
++ * transfer - some PC's will use the I/O bus, m68k's must use
+ * memory mapped) and drops this file in their 'C' wrapper.
+ *
+ * As far as command queueing, two queues are maintained for
+--- a/drivers/serial/68360serial.c
++++ b/drivers/serial/68360serial.c
+@@ -2802,7 +2802,7 @@ int serial_console_setup( struct console
+ volatile struct uart_pram *sup;
+
+ /* mleslie TODO:
+- * add something to the 68k bootloader to store a desired initial console baud rate */
++ * add something to the m68k bootloader to store a desired initial console baud rate */
+
+ /* bd_t *bd; */ /* a board info struct used by EPPC-bug */
+ /* bd = (bd_t *)__res; */
+--- a/drivers/video/macfb.c
++++ b/drivers/video/macfb.c
+@@ -561,7 +561,7 @@ static int macfb_setcolreg(unsigned regn
+ }
+ break;
+ /* I'm pretty sure that one or the other of these
+- doesn't exist on 68k Macs */
++ doesn't exist on m68k Macs */
+ case 24:
+ red >>= 8;
+ green >>= 8;
+@@ -717,7 +717,7 @@ static int __init macfb_init(void)
+ break;
+ case 24:
+ case 32:
+- /* XXX: have to test these... can any 68k Macs
++ /* XXX: have to test these... can any m68k Macs
+ actually do this on internal video? */
+ macfb_defined.red.offset = 16;
+ macfb_defined.red.length = 8;
+--- a/drivers/video/valkyriefb.c
++++ b/drivers/video/valkyriefb.c
+@@ -332,7 +332,7 @@ int __init valkyriefb_init(void)
+ || mac_bi_data.id == MAC_MODEL_P588))
+ return 0;
+
+- /* Hardcoded addresses... welcome to 68k Macintosh country :-) */
++ /* Hardcoded addresses... welcome to m68k Macintosh country :-) */
+ frame_buffer_phys = 0xf9000000;
+ cmap_regs_phys = 0x50f24000;
+ flags = IOMAP_NOCACHE_SER; /* IOMAP_WRITETHROUGH?? */
+--- a/drivers/video/valkyriefb.h
++++ b/drivers/video/valkyriefb.h
+@@ -9,7 +9,7 @@
+ *
+ * vmode 10 changed by Steven Borley <sjb at salix.demon.co.uk>, 14 mai 2000
+ *
+- * Ported to 68k Macintosh by David Huggins-Daines <dhd at debian.org>
++ * Ported to m68k Macintosh by David Huggins-Daines <dhd at debian.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+--- a/fs/affs/Changes
++++ b/fs/affs/Changes
+@@ -197,7 +197,7 @@ Version 3.6
+ - Fixed bug in add_entry(): When doing a sorted insert,
+ the pointer to the next entry in the hash chain wasn't
+ correctly byte-swapped. Since most of the users of the
+- affs use it on a 68k, they didn't notice. But why did
++ affs use it on a m68k, they didn't notice. But why did
+ I not find this during my tests?
+
+ - Fixed some oversights (version wasn't updated on some
+--- a/include/asm-m68k/elf.h
++++ b/include/asm-m68k/elf.h
+@@ -9,7 +9,7 @@
+ #include <asm/user.h>
+
+ /*
+- * 68k ELF relocation types
++ * m68k ELF relocation types
+ */
+ #define R_68K_NONE 0
+ #define R_68K_32 1
+--- a/include/asm-xtensa/bootparam.h
++++ b/include/asm-xtensa/bootparam.h
+@@ -9,7 +9,7 @@
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+- * (Concept borrowed from the 68K port)
++ * (Concept borrowed from the m68k port)
+ */
+
+ #ifndef _XTENSA_BOOTPARAM_H
+--- a/include/linux/pmu.h
++++ b/include/linux/pmu.h
+@@ -90,8 +90,8 @@ enum {
+ PMU_HEATHROW_BASED, /* PowerBook G3 series */
+ PMU_PADDINGTON_BASED, /* 1999 PowerBook G3 */
+ PMU_KEYLARGO_BASED, /* Core99 motherboard (PMU99) */
+- PMU_68K_V1, /* 68K PMU, version 1 */
+- PMU_68K_V2, /* 68K PMU, version 2 */
++ PMU_68K_V1, /* m68k PMU, version 1 */
++ PMU_68K_V2, /* m68k PMU, version 2 */
+ };
+
+ /* PMU PMU_POWER_EVENTS commands */
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-scsi-HOST_C-cleanup.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-scsi-HOST_C-cleanup.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,24 @@
+Subject: [PATCH] scsi: Clean up mvme147.c
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+FIXME a few more to take care of
+FIXME merge include files that are included only once into the .c file
+
+git grep HOSTS_C
+---
+ drivers/scsi/mvme147.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/scsi/mvme147.c
++++ b/drivers/scsi/mvme147.c
+@@ -128,9 +128,6 @@ static int mvme147_bus_reset(struct scsi
+ return SUCCESS;
+ }
+
+-#define HOSTS_C
+-
+-#include "mvme147.h"
+
+ static struct scsi_host_template driver_template = {
+ .proc_name = "MVME147",
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-update-defconfig-latest.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-update-defconfig-latest.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,61 @@
+Subject: [PATCH] m68k: Update defconfigs for new drivers and features
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/configs/atari_defconfig | 4 ++++
+ arch/m68k/configs/multi_defconfig | 4 ++++
+ 2 files changed, 8 insertions(+)
+
+--- a/arch/m68k/configs/atari_defconfig
++++ b/arch/m68k/configs/atari_defconfig
+@@ -122,12 +122,15 @@ CONFIG_CLASSIC_RCU=y
+ # CONFIG_SUN3 is not set
+ # CONFIG_AMIGA is not set
+ CONFIG_ATARI=y
++CONFIG_ATARI_ROM_ISA=y
+ # CONFIG_MAC is not set
+ # CONFIG_APOLLO is not set
+ # CONFIG_VME is not set
+ # CONFIG_HP300 is not set
+ # CONFIG_SUN3X is not set
+ # CONFIG_Q40 is not set
++CONFIG_NATFEAT=y
++CONFIG_NFETH=y
+
+ #
+ # Processor type
+@@ -567,6 +570,7 @@ CONFIG_VETH=m
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=m
+ CONFIG_ATARILANCE=m
++CONFIG_ATARI_ETHERNEC=m
+ # CONFIG_IBM_NEW_EMAC_ZMII is not set
+ # CONFIG_IBM_NEW_EMAC_RGMII is not set
+ # CONFIG_IBM_NEW_EMAC_TAH is not set
+--- a/arch/m68k/configs/multi_defconfig
++++ b/arch/m68k/configs/multi_defconfig
+@@ -122,6 +122,7 @@ CONFIG_CLASSIC_RCU=y
+ # CONFIG_SUN3 is not set
+ CONFIG_AMIGA=y
+ CONFIG_ATARI=y
++CONFIG_ATARI_ROM_ISA=y
+ CONFIG_MAC=y
+ CONFIG_NUBUS=y
+ CONFIG_M68K_L2_CACHE=y
+@@ -134,6 +135,8 @@ CONFIG_HP300=y
+ CONFIG_DIO=y
+ CONFIG_SUN3X=y
+ CONFIG_Q40=y
++CONFIG_NATFEAT=y
++CONFIG_NFETH=y
+
+ #
+ # Processor type
+@@ -643,6 +646,7 @@ CONFIG_MVME147_NET=y
+ CONFIG_MVME16x_NET=y
+ CONFIG_BVME6000_NET=y
+ CONFIG_ATARILANCE=m
++CONFIG_ATARI_ETHERNEC=m
+ CONFIG_SUN3LANCE=y
+ CONFIG_HPLANCE=y
+ # CONFIG_NET_VENDOR_3COM is not set
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-use-the-new-byteorder-headers.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/m68k-use-the-new-byteorder-headers.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,49 @@
+Subject: [PATCH] m68k: use the new byteorder headers
+
+From: Harvey Harrison <harvey.harrison at gmail.com>
+
+Signed-off-by: Harvey Harrison <harvey.harrison at gmail.com>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+The final prerequisite patches to prevent breakage of headers-install and
+usage of the swabb.h functions have gone into mainline, please move your arch
+to the new header.
+
+b8e465f4945bc0e9f324e3bbe15f5180a8e9a6fe byteorder: add new headers for make headers-install
+acf0108a84edae22b99655eb2f6f6c9f7ec4d449 byteorder: use generic C version for value byteswapping
+1d8cca44b6a244b7e378546d719041819049a0f9 byteorder: provide swabb.h generically in asm/byteorder.h
+1a651a00e20fd4997f0b91258f6f95b7d96edcd9 byteorder: remove direct includes of linux/byteorder/swab[b].h
+
+ include/asm-m68k/byteorder.h | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+--- a/include/asm-m68k/byteorder.h
++++ b/include/asm-m68k/byteorder.h
+@@ -4,22 +4,16 @@
+ #include <asm/types.h>
+ #include <linux/compiler.h>
+
+-#ifdef __GNUC__
++#define __BIG_ENDIAN
++#define __SWAB_64_THRU_32__
+
+-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 val)
++static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
+ {
+ __asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val));
+ return val;
+ }
+-#define __arch__swab32(x) ___arch__swab32(x)
++#define __arch_swab32 __arch_swab32
+
+-#endif
+-
+-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+-# define __BYTEORDER_HAS_U64__
+-# define __SWAB_64_THRU_32__
+-#endif
+-
+-#include <linux/byteorder/big_endian.h>
++#include <linux/byteorder.h>
+
+ #endif /* _M68K_BYTEORDER_H */
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-add-SWIM-floppy-support.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-add-SWIM-floppy-support.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,1378 @@
+From laurent at lvivier.info Sat Nov 15 16:19:25 2008
+Date: Sat, 15 Nov 2008 16:10:10 +0100
+From: Laurent Vivier <laurent at lvivier.info>
+To: Geert Uytterhoeven <geert at linux-m68k.org>
+Cc: Laurent Vivier <laurent at lvivier.info>, Linux/m68k <linux-m68k at vger.kernel.org>
+Subject: [PATCH][v5] Add SWIM floppy support for m68k Macs.
+
+It allows to read data from a floppy, but not to write to, and to eject the
+floppy (useful on our Mac without eject button).
+
+Signed-off-by: Laurent Vivier <Laurent at lvivier.info>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+Changelog:
+v2- use platform device infrastructure
+v3- some cleanups, probe if chip supports SWIM mode
+v4- use platform_device, correct swim_action() and swim_eject()
+ according swim3 driver.
+v5- use a structure for IWM registers (like for SWIM ones)
+
+ arch/m68k/mac/config.c | 40 +
+ arch/m68k/mac/via.c | 9
+ drivers/block/Kconfig | 7
+ drivers/block/Makefile | 3
+ drivers/block/swim.c | 997 +++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/block/swim_asm.S | 247 +++++++++++
+ 6 files changed, 1303 insertions(+)
+
+--- a/arch/m68k/mac/config.c
++++ b/arch/m68k/mac/config.c
+@@ -22,6 +22,7 @@
+ /* keyb */
+ #include <linux/init.h>
+ #include <linux/vt_kern.h>
++#include <linux/platform_device.h>
+
+ #define BOOTINFO_COMPAT_1_0
+ #include <asm/setup.h>
+@@ -882,3 +883,42 @@ static void mac_get_model(char *str)
+ strcpy(str, "Macintosh ");
+ strcat(str, macintosh_config->name);
+ }
++
++static struct resource swim_resources[1];
++
++static struct platform_device swim_device = {
++ .name = "swim",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(swim_resources),
++ .resource = swim_resources,
++};
++
++static struct platform_device *mac_platform_devices[] __initdata = {
++ &swim_device
++};
++
++int __init mac_platform_init(void)
++{
++ u8 *swim_base;
++
++ switch (macintosh_config->floppy_type) {
++ case MAC_FLOPPY_SWIM_ADDR1:
++ swim_base = (u8 *)(VIA1_BASE + 0x1E000);
++ break;
++ case MAC_FLOPPY_SWIM_ADDR2:
++ swim_base = (u8 *)(VIA1_BASE + 0x16000);
++ break;
++ default:
++ return 0;
++ }
++
++ swim_resources[0].name = "swim-regs";
++ swim_resources[0].start = (resource_size_t)swim_base;
++ swim_resources[0].end = (resource_size_t)(swim_base + 0x2000);
++ swim_resources[0].flags = IORESOURCE_MEM;
++
++ return platform_add_devices(mac_platform_devices,
++ ARRAY_SIZE(mac_platform_devices));
++}
++
++arch_initcall(mac_platform_init);
+--- a/arch/m68k/mac/via.c
++++ b/arch/m68k/mac/via.c
+@@ -638,3 +638,12 @@ int via_irq_pending(int irq)
+ }
+ return 0;
+ }
++
++void via1_set_head(int head)
++{
++ if (head == 0)
++ via1[vBufA] &= ~VIA1A_vHeadSel;
++ else
++ via1[vBufA] |= VIA1A_vHeadSel;
++}
++EXPORT_SYMBOL(via1_set_head);
+--- a/drivers/block/Kconfig
++++ b/drivers/block/Kconfig
+@@ -45,6 +45,13 @@ config MAC_FLOPPY
+ If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple)
+ floppy controller, say Y here. Most commonly found in PowerMacs.
+
++config BLK_DEV_SWIM
++ tristate "Support for SWIM Macintosh floppy"
++ depends on M68K && MAC
++ help
++ You should select this option if you want floppy support
++ and you don't have a II, IIfx, Q900, Q950 or AV series.
++
+ config AMIGA_Z2RAM
+ tristate "Amiga Zorro II ramdisk support"
+ depends on ZORRO
+--- a/drivers/block/Makefile
++++ b/drivers/block/Makefile
+@@ -6,6 +6,7 @@
+ #
+
+ obj-$(CONFIG_MAC_FLOPPY) += swim3.o
++obj-$(CONFIG_BLK_DEV_SWIM) += swim_mod.o
+ obj-$(CONFIG_BLK_DEV_FD) += floppy.o
+ obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o
+ obj-$(CONFIG_PS3_DISK) += ps3disk.o
+@@ -32,3 +33,5 @@ obj-$(CONFIG_BLK_DEV_UB) += ub.o
+ obj-$(CONFIG_BLK_DEV_HD) += hd.o
+
+ obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
++
++swim_mod-objs := swim.o swim_asm.o
+--- /dev/null
++++ b/drivers/block/swim.c
+@@ -0,0 +1,997 @@
++/*
++ * Driver for SWIM (Sander Woz Integrated Machine) floppy controller
++ *
++ * Copyright (C) 2004,2008 Laurent Vivier <Laurent at lvivier.info>
++ *
++ * based on Alastair Bridgewater SWIM analysis, 2001
++ * based on SWIM3 driver (c) Paul Mackerras, 1996
++ * based on netBSD IWM driver (c) 1997, 1998 Hauke Fath.
++ *
++ * This program 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.
++ *
++ * 2004-08-21 (lv) - Initial implementation
++ * 2008-10-30 (lv) - Port to 2.6
++ */
++
++#include <linux/module.h>
++#include <linux/fd.h>
++#include <linux/blkdev.h>
++#include <linux/hdreg.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++
++#include <asm/macintosh.h>
++#include <asm/mac_via.h>
++
++#define CARDNAME "swim"
++#define SWIM_IO_SIZE 0x2000
++
++struct sector_header {
++ unsigned char side;
++ unsigned char track;
++ unsigned char sector;
++ unsigned char size;
++ unsigned char crc0;
++ unsigned char crc1;
++} __attribute__((packed));
++
++#define DRIVER_VERSION "Version 0.2 (2008-10-30)"
++
++#define REG(x) unsigned char x, x ## _pad[0x200 - 1];
++
++struct swim {
++ REG(write_data)
++ REG(write_mark)
++ REG(write_CRC)
++ REG(write_parameter)
++ REG(write_phase)
++ REG(write_setup)
++ REG(write_mode0)
++ REG(write_mode1)
++
++ REG(read_data)
++ REG(read_mark)
++ REG(read_error)
++ REG(read_parameter)
++ REG(read_phase)
++ REG(read_setup)
++ REG(read_status)
++ REG(read_handshake)
++} __attribute__((packed));
++
++#define swim_write(base, reg, v) out_8(&(base)->write_##reg, (v))
++#define swim_read(base, reg) in_8(&(base)->read_##reg)
++
++/* IWM registers */
++
++struct iwm {
++ REG(ph0L)
++ REG(ph0H)
++ REG(ph1L)
++ REG(ph1H)
++ REG(ph2L)
++ REG(ph2H)
++ REG(ph3L)
++ REG(ph3H)
++ REG(mtrOff)
++ REG(mtrOn)
++ REG(intDrive)
++ REG(extDrive)
++ REG(q6L)
++ REG(q6H)
++ REG(q7L)
++ REG(q7H)
++} __attribute__((packed));
++
++#define iwm_write(base, reg, v) out_8(&(base)->reg, (v))
++#define iwm_read(base, reg) in_8(&(base)->reg)
++
++/* bits in phase register */
++
++#define SEEK_POSITIVE 0x070
++#define SEEK_NEGATIVE 0x074
++#define STEP 0x071
++#define MOTOR_ON 0x072
++#define MOTOR_OFF 0x076
++#define INDEX 0x073
++#define EJECT 0x077
++#define SETMFM 0x171
++#define SETGCR 0x175
++
++#define RELAX 0x033
++#define LSTRB 0x008
++
++#define CA_MASK 0x077
++
++/* Select values for swim_select and swim_readbit */
++
++#define READ_DATA_0 0x074
++#define TWOMEG_DRIVE 0x075
++#define SINGLE_SIDED 0x076
++#define DRIVE_PRESENT 0x077
++#define DISK_IN 0x170
++#define WRITE_PROT 0x171
++#define TRACK_ZERO 0x172
++#define TACHO 0x173
++#define READ_DATA_1 0x174
++#define MFM_MODE 0x175
++#define SEEK_COMPLETE 0x176
++#define ONEMEG_MEDIA 0x177
++
++/* Bits in handshake register */
++
++#define MARK_BYTE 0x01
++#define CRC_ZERO 0x02
++#define RDDATA 0x04
++#define SENSE 0x08
++#define MOTEN 0x10
++#define ERROR 0x20
++#define DAT2BYTE 0x40
++#define DAT1BYTE 0x80
++
++/* bits in setup register */
++
++#define S_INV_WDATA 0x01
++#define S_3_5_SELECT 0x02
++#define S_GCR 0x04
++#define S_FCLK_DIV2 0x08
++#define S_ERROR_CORR 0x10
++#define S_IBM_DRIVE 0x20
++#define S_GCR_WRITE 0x40
++#define S_TIMEOUT 0x80
++
++/* bits in mode register */
++
++#define CLFIFO 0x01
++#define ENBL1 0x02
++#define ENBL2 0x04
++#define ACTION 0x08
++#define WRITE_MODE 0x10
++#define HEDSEL 0x20
++#define MOTON 0x80
++
++/*----------------------------------------------------------------------------*/
++
++enum drive_location {
++ INTERNAL_DRIVE = 0x02,
++ EXTERNAL_DRIVE = 0x04,
++};
++
++enum media_type {
++ DD_MEDIA,
++ HD_MEDIA,
++};
++
++struct floppy_state {
++
++ /* physical properties */
++
++ enum drive_location location; /* internal or external drive */
++ int head_number; /* single- or double-sided drive */
++
++ /* media */
++
++ int disk_in;
++ int ejected;
++ enum media_type type;
++ int write_protected;
++
++ int total_secs;
++ int secpercyl;
++ int secpertrack;
++
++ /* in-use information */
++
++ int track;
++ int ref_count;
++
++ struct gendisk *disk;
++
++ /* parent controller */
++
++ struct swim_priv *swd;
++};
++
++enum motor_action {
++ OFF,
++ ON,
++};
++
++enum head {
++ LOWER_HEAD = 0,
++ UPPER_HEAD = 1,
++};
++
++#define FD_MAX_UNIT 2
++
++struct swim_priv {
++ struct swim __iomem *base;
++ spinlock_t lock;
++ struct request_queue *queue;
++ int floppy_count;
++ struct floppy_state unit[FD_MAX_UNIT];
++};
++
++extern int swim_read_sector_header(struct swim *base,
++ struct sector_header *header);
++extern int swim_read_sector_data(struct swim *base, unsigned char *data);
++
++static inline void set_swim_mode(struct swim *base, int enable)
++{
++ struct iwm *iwm_base;
++ unsigned long flags;
++
++ if (!enable) {
++ swim_write(base, mode0, 0xf8);
++ return;
++ }
++
++ iwm_base = (struct iwm *)base;
++ local_save_flags(flags);
++ local_irq_disable();
++
++ iwm_read(iwm_base, q7L);
++ iwm_read(iwm_base, mtrOff);
++ iwm_read(iwm_base, q6H);
++
++ iwm_write(iwm_base, q7H, 0x57);
++ iwm_write(iwm_base, q7H, 0x17);
++ iwm_write(iwm_base, q7H, 0x57);
++ iwm_write(iwm_base, q7H, 0x57);
++
++ local_irq_restore(flags);
++}
++
++static inline int get_swim_mode(struct swim *base)
++{
++ unsigned long flags;
++
++ local_save_flags(flags);
++ local_irq_disable();
++
++ swim_write(base, phase, 0xf5);
++ if (swim_read(base, phase) != 0xf5)
++ goto is_iwm;
++ swim_write(base, phase, 0xf6);
++ if (swim_read(base, phase) != 0xf6)
++ goto is_iwm;
++ swim_write(base, phase, 0xf7);
++ if (swim_read(base, phase) != 0xf7)
++ goto is_iwm;
++ local_irq_restore(flags);
++ return 1;
++is_iwm:
++ local_irq_restore(flags);
++ return 0;
++}
++
++static inline void swim_select(struct swim *base, int sel)
++{
++ swim_write(base, phase, RELAX);
++
++ via1_set_head(sel & 0x100);
++
++ swim_write(base, phase, sel & CA_MASK);
++}
++
++static inline void swim_action(struct swim *base, int action)
++{
++ unsigned long flags;
++
++ local_save_flags(flags);
++ local_irq_disable();
++
++ swim_select(base, action);
++ udelay(1);
++ swim_write(base, phase, (LSTRB<<4) | LSTRB);
++ udelay(1);
++ swim_write(base, phase, (LSTRB<<4) | ((~LSTRB) & 0x0F));
++ udelay(1);
++
++ local_irq_restore(flags);
++}
++
++static inline int swim_readbit(struct swim *base, int bit)
++{
++ int stat;
++
++ swim_select(base, bit);
++
++ udelay(10);
++
++ stat = swim_read(base, handshake);
++
++ return (stat & SENSE) == 0;
++}
++
++static inline void swim_drive(struct swim *base, enum drive_location location)
++{
++ if (location == INTERNAL_DRIVE) {
++ swim_write(base, mode0, EXTERNAL_DRIVE); /* clear drive 1 bit */
++ swim_write(base, mode1, INTERNAL_DRIVE); /* set drive 0 bit */
++ } else if (location == EXTERNAL_DRIVE) {
++ swim_write(base, mode0, INTERNAL_DRIVE); /* clear drive 0 bit */
++ swim_write(base, mode1, EXTERNAL_DRIVE); /* set drive 1 bit */
++ }
++}
++
++static inline void swim_motor(struct swim *base, enum motor_action action)
++{
++ if (action == ON) {
++ int i;
++
++ swim_action(base, MOTOR_ON);
++
++ for (i = 0; i < 2*HZ; i++) {
++ swim_select(base, RELAX);
++ if (swim_readbit(base, MOTOR_ON))
++ break;
++ current->state = TASK_INTERRUPTIBLE;
++ schedule_timeout(1);
++ }
++ } else if (action == OFF) {
++ swim_action(base, MOTOR_OFF);
++ swim_select(base, RELAX);
++ }
++}
++
++static inline void swim_eject(struct swim *base)
++{
++ int i;
++
++ swim_action(base, EJECT);
++
++ for (i = 0; i < 2*HZ; i++) {
++ swim_select(base, RELAX);
++ if (!swim_readbit(base, DISK_IN))
++ break;
++ current->state = TASK_INTERRUPTIBLE;
++ schedule_timeout(1);
++ }
++ swim_select(base, RELAX);
++}
++
++static inline void swim_head(struct swim *base, enum head head)
++{
++ /* wait drive is ready */
++
++ if (head == UPPER_HEAD)
++ swim_select(base, READ_DATA_1);
++ else if (head == LOWER_HEAD)
++ swim_select(base, READ_DATA_0);
++}
++
++static inline int swim_step(struct swim *base)
++{
++ int wait;
++
++ swim_action(base, STEP);
++
++ for (wait = 0; wait < HZ; wait++) {
++
++ current->state = TASK_INTERRUPTIBLE;
++ schedule_timeout(1);
++
++ swim_select(base, RELAX);
++ if (!swim_readbit(base, STEP))
++ return 0;
++ }
++ return -1;
++}
++
++static inline int swim_track00(struct swim *base)
++{
++ int try;
++
++ swim_action(base, SEEK_NEGATIVE);
++
++ for (try = 0; try < 100; try++) {
++
++ swim_select(base, RELAX);
++ if (swim_readbit(base, TRACK_ZERO))
++ break;
++
++ if (swim_step(base))
++ return -1;
++ }
++
++ if (swim_readbit(base, TRACK_ZERO))
++ return 0;
++
++ return -1;
++}
++
++static inline int swim_seek(struct swim *base, int step)
++{
++ if (step == 0)
++ return 0;
++
++ if (step < 0) {
++ swim_action(base, SEEK_NEGATIVE);
++ step = -step;
++ } else
++ swim_action(base, SEEK_POSITIVE);
++
++ for ( ; step > 0; step--) {
++ if (swim_step(base))
++ return -1;
++ }
++
++ return 0;
++}
++
++static inline int swim_track(struct floppy_state *fs, int track)
++{
++ struct swim *base = fs->swd->base;
++ int ret;
++
++ ret = swim_seek(base, track - fs->track);
++
++ if (ret == 0)
++ fs->track = track;
++ else {
++ swim_track00(base);
++ fs->track = 0;
++ }
++
++ return ret;
++}
++
++static int floppy_eject(struct floppy_state *fs)
++{
++ struct swim *base = fs->swd->base;
++
++ swim_drive(base, fs->location);
++ swim_motor(base, OFF);
++ swim_eject(base);
++
++ fs->disk_in = 0;
++ fs->ejected = 1;
++
++ return 0;
++}
++
++static inline int swim_read_sector(struct floppy_state *fs,
++ int side, int track,
++ int sector, unsigned char *buffer)
++{
++ struct swim *base = fs->swd->base;
++ unsigned long flags;
++ struct sector_header header;
++ int ret = -1;
++ short i;
++
++ swim_track(fs, track);
++
++ swim_write(base, mode1, MOTON);
++ swim_head(base, side);
++ swim_write(base, mode0, side);
++
++ local_save_flags(flags);
++ local_irq_disable();
++ for (i = 0; i < 36; i++) {
++ ret = swim_read_sector_header(base, &header);
++ if (!ret && (header.sector == sector)) {
++ /* found */
++
++ ret = swim_read_sector_data(base, buffer);
++ break;
++ }
++ }
++ local_irq_restore(flags);
++
++ swim_write(base, mode0, MOTON);
++
++ if ((header.side != side) || (header.track != track) ||
++ (header.sector != sector))
++ return 0;
++
++ return ret;
++}
++
++static int floppy_read_sectors(struct floppy_state *fs,
++ int req_sector, int sectors_nb,
++ unsigned char *buffer)
++{
++ struct swim *base = fs->swd->base;
++ int ret;
++ int side, track, sector;
++ int i, try;
++
++
++ swim_drive(base, fs->location);
++ for (i = req_sector; i < req_sector + sectors_nb; i++) {
++ int x;
++ track = i / fs->secpercyl;
++ x = i % fs->secpercyl;
++ side = x / fs->secpertrack;
++ sector = x % fs->secpertrack + 1;
++
++ try = 5;
++ do {
++ ret = swim_read_sector(fs, side, track, sector,
++ buffer);
++ if (try-- == 0)
++ return -1;
++ } while (ret != 512);
++
++ buffer += ret;
++ }
++
++ return 0;
++}
++
++static void redo_fd_request(struct request_queue *q)
++{
++ struct request *req;
++ struct floppy_state *fs;
++
++ while ((req = elv_next_request(q))) {
++
++ fs = req->rq_disk->private_data;
++ if (req->sector < 0 || req->sector >= fs->total_secs) {
++ end_request(req, 0);
++ continue;
++ }
++ if (req->current_nr_sectors == 0) {
++ end_request(req, 1);
++ continue;
++ }
++ if (!fs->disk_in) {
++ end_request(req, 0);
++ continue;
++ }
++ if (rq_data_dir(req) == WRITE) {
++ if (fs->write_protected) {
++ end_request(req, 0);
++ continue;
++ }
++ }
++ switch (rq_data_dir(req)) {
++ case WRITE:
++ /* NOT IMPLEMENTED */
++ end_request(req, 0);
++ break;
++ case READ:
++ if (floppy_read_sectors(fs, req->sector,
++ req->current_nr_sectors,
++ req->buffer)) {
++ end_request(req, 0);
++ continue;
++ }
++ req->nr_sectors -= req->current_nr_sectors;
++ req->sector += req->current_nr_sectors;
++ req->buffer += req->current_nr_sectors * 512;
++ end_request(req, 1);
++ break;
++ }
++ }
++}
++
++static void do_fd_request(struct request_queue *q)
++{
++ redo_fd_request(q);
++}
++
++static struct floppy_struct floppy_type[4] = {
++ { 0, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, NULL }, /* no testing */
++ { 720, 9, 1, 80, 0, 0x2A, 0x02, 0xDF, 0x50, NULL }, /* 360KB SS 3.5"*/
++ { 1440, 9, 2, 80, 0, 0x2A, 0x02, 0xDF, 0x50, NULL }, /* 720KB 3.5" */
++ { 2880, 18, 2, 80, 0, 0x1B, 0x00, 0xCF, 0x6C, NULL }, /* 1.44MB 3.5" */
++};
++
++static int get_floppy_geometry(struct floppy_state *fs, int type,
++ struct floppy_struct **g)
++{
++ if (type >= ARRAY_SIZE(floppy_type))
++ return -EINVAL;
++
++ if (type)
++ *g = &floppy_type[type];
++ else if (fs->type == HD_MEDIA) /* High-Density media */
++ *g = &floppy_type[3];
++ else if (fs->head_number == 2) /* double-sided */
++ *g = &floppy_type[2];
++ else
++ *g = &floppy_type[1];
++
++ return 0;
++}
++
++static void setup_medium(struct floppy_state *fs)
++{
++ struct swim *base = fs->swd->base;
++
++ if (swim_readbit(base, DISK_IN)) {
++ struct floppy_struct *g;
++ fs->disk_in = 1;
++ fs->write_protected = swim_readbit(base, WRITE_PROT);
++ fs->type = swim_readbit(base, ONEMEG_MEDIA);
++
++ if (swim_track00(base))
++ printk(KERN_ERR
++ "SWIM: cannot move floppy head to track 0\n");
++
++ swim_track00(base);
++
++ get_floppy_geometry(fs, 0, &g);
++ fs->total_secs = g->size;
++ fs->secpercyl = g->head * g->sect;
++ fs->secpertrack = g->sect;
++ fs->track = 0;
++ } else {
++ fs->disk_in = 0;
++ }
++}
++
++static int floppy_open(struct block_device *bdev, fmode_t mode)
++{
++ struct floppy_state *fs = bdev->bd_disk->private_data;
++ struct swim *base = fs->swd->base;
++ int err;
++
++ if (fs->ref_count == -1 || (fs->ref_count && mode & FMODE_EXCL))
++ return -EBUSY;
++
++ if (mode & FMODE_EXCL)
++ fs->ref_count = -1;
++ else
++ fs->ref_count++;
++
++ swim_write(base, setup, S_IBM_DRIVE | S_FCLK_DIV2);
++ udelay(10);
++ swim_drive(base, INTERNAL_DRIVE);
++ swim_motor(base, ON);
++ swim_action(base, SETMFM);
++ if (fs->ejected)
++ setup_medium(fs);
++ if (!fs->disk_in) {
++ err = -ENXIO;
++ goto out;
++ }
++
++ if (mode & FMODE_NDELAY)
++ return 0;
++
++ if (mode & (FMODE_READ|FMODE_WRITE)) {
++ check_disk_change(bdev);
++ if ((mode & FMODE_WRITE) && fs->write_protected) {
++ err = -EROFS;
++ goto out;
++ }
++ }
++ return 0;
++out:
++ if (fs->ref_count < 0)
++ fs->ref_count = 0;
++ else if (fs->ref_count > 0)
++ --fs->ref_count;
++
++ if (fs->ref_count == 0)
++ swim_motor(base, OFF);
++ return err;
++}
++
++static int floppy_release(struct gendisk *disk, fmode_t mode)
++{
++ struct floppy_state *fs = disk->private_data;
++ struct swim *base = fs->swd->base;
++
++ if (fs->ref_count < 0)
++ fs->ref_count = 0;
++ else if (fs->ref_count > 0)
++ --fs->ref_count;
++
++ if (fs->ref_count == 0)
++ swim_motor(base, OFF);
++
++ return 0;
++}
++
++static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
++ unsigned int cmd, unsigned long param)
++{
++ struct floppy_state *fs = bdev->bd_disk->private_data;
++ int err;
++
++ if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ switch (cmd) {
++ case FDEJECT:
++ if (fs->ref_count != 1)
++ return -EBUSY;
++ err = floppy_eject(fs);
++ return err;
++
++ case FDGETPRM:
++ if (copy_to_user((void *) param, (void *) &floppy_type,
++ sizeof(struct floppy_struct)))
++ return -EFAULT;
++ break;
++
++ default:
++ printk(KERN_DEBUG "SWIM floppy_ioctl: unknown cmd %d\n",
++ cmd);
++ return -ENOSYS;
++ }
++ return 0;
++}
++
++static int floppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
++{
++ struct floppy_state *fs = bdev->bd_disk->private_data;
++ struct floppy_struct *g;
++ int ret;
++
++ ret = get_floppy_geometry(fs, 0, &g);
++ if (ret)
++ return ret;
++
++ geo->heads = g->head;
++ geo->sectors = g->sect;
++ geo->cylinders = g->track;
++
++ return 0;
++}
++
++static int floppy_check_change(struct gendisk *disk)
++{
++ struct floppy_state *fs = disk->private_data;
++
++ return fs->ejected;
++}
++
++static int floppy_revalidate(struct gendisk *disk)
++{
++ struct floppy_state *fs = disk->private_data;
++ struct swim *base = fs->swd->base;
++
++ swim_drive(base, fs->location);
++
++ if (fs->ejected)
++ setup_medium(fs);
++
++ if (!fs->disk_in)
++ swim_motor(base, OFF);
++ else
++ fs->ejected = 0;
++
++ return !fs->disk_in;
++}
++
++static struct block_device_operations floppy_fops = {
++ .owner = THIS_MODULE,
++ .open = floppy_open,
++ .release = floppy_release,
++ .locked_ioctl = floppy_ioctl,
++ .getgeo = floppy_getgeo,
++ .media_changed = floppy_check_change,
++ .revalidate_disk = floppy_revalidate,
++};
++
++static struct kobject *floppy_find(dev_t dev, int *part, void *data)
++{
++ struct swim_priv *swd = data;
++ int drive = (*part & 3);
++
++ if (drive > swd->floppy_count)
++ return NULL;
++
++ *part = 0;
++ return get_disk(swd->unit[drive].disk);
++}
++
++static int __devinit swim_add_floppy(struct swim_priv *swd,
++ enum drive_location location)
++{
++ struct floppy_state *fs = &swd->unit[swd->floppy_count];
++ struct swim *base = swd->base;
++
++ fs->location = location;
++
++ swim_drive(base, location);
++
++ swim_motor(base, OFF);
++
++ if (swim_readbit(base, SINGLE_SIDED))
++ fs->head_number = 1;
++ else
++ fs->head_number = 2;
++ fs->ref_count = 0;
++ fs->ejected = 1;
++
++ swd->floppy_count++;
++
++ return 0;
++}
++
++static int __devinit swim_floppy_init(struct swim_priv *swd)
++{
++ int err;
++ int drive;
++ struct swim *base = swd->base;
++
++ /* scan floppy drives */
++
++ swim_drive(base, INTERNAL_DRIVE);
++ if (swim_readbit(base, DRIVE_PRESENT))
++ swim_add_floppy(swd, INTERNAL_DRIVE);
++ swim_drive(base, EXTERNAL_DRIVE);
++ if (swim_readbit(base, DRIVE_PRESENT))
++ swim_add_floppy(swd, EXTERNAL_DRIVE);
++
++ /* register floppy drives */
++
++ err = register_blkdev(FLOPPY_MAJOR, "fd");
++ if (err) {
++ printk(KERN_ERR "Unable to get major %d for SWIM floppy\n",
++ FLOPPY_MAJOR);
++ return -EBUSY;
++ }
++
++ for (drive = 0; drive < swd->floppy_count; drive++) {
++ swd->unit[drive].disk = alloc_disk(1);
++ if (swd->unit[drive].disk == NULL) {
++ err = -ENOMEM;
++ goto exit_put_disks;
++ }
++ swd->unit[drive].swd = swd;
++ }
++
++ swd->queue = blk_init_queue(do_fd_request, &swd->lock);
++ if (!swd->queue) {
++ err = -ENOMEM;
++ goto exit_put_disks;
++ }
++
++ for (drive = 0; drive < swd->floppy_count; drive++) {
++ swd->unit[drive].disk->flags = GENHD_FL_REMOVABLE;
++ swd->unit[drive].disk->major = FLOPPY_MAJOR;
++ swd->unit[drive].disk->first_minor = drive;
++ sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive);
++ swd->unit[drive].disk->fops = &floppy_fops;
++ swd->unit[drive].disk->private_data = &swd->unit[drive];
++ swd->unit[drive].disk->queue = swd->queue;
++ set_capacity(swd->unit[drive].disk, 2880);
++ add_disk(swd->unit[drive].disk);
++ }
++
++ blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
++ floppy_find, NULL, swd);
++
++ return 0;
++
++exit_put_disks:
++ unregister_blkdev(FLOPPY_MAJOR, "fd");
++ while (drive--)
++ put_disk(swd->unit[drive].disk);
++ return err;
++}
++
++static int __devinit swim_probe(struct platform_device *dev)
++{
++ struct resource *res;
++ struct swim *swim_base;
++ struct swim_priv *swd;
++ int ret;
++
++ res = platform_get_resource_byname(dev, IORESOURCE_MEM, "swim-regs");
++ if (!res) {
++ ret = -ENODEV;
++ goto out;
++ }
++
++ if (!request_mem_region(res->start, SWIM_IO_SIZE, CARDNAME)) {
++ ret = -EBUSY;
++ goto out;
++ }
++
++ swim_base = (struct swim *)ioremap(res->start, SWIM_IO_SIZE);
++ if (!swim_base) {
++ return -ENOMEM;
++ goto out_release_io;
++ }
++
++ /* probe device */
++
++ set_swim_mode(swim_base, 1);
++ if (!get_swim_mode(swim_base)) {
++ printk(KERN_INFO "SWIM device not found !\n");
++ ret = -ENODEV;
++ goto out_iounmap;
++ }
++
++ /* set platform driver data */
++
++ swd = kzalloc(sizeof(struct swim_priv), GFP_KERNEL);
++ if (!swd) {
++ ret = -ENOMEM;
++ goto out_iounmap;
++ }
++ platform_set_drvdata(dev, swd);
++
++ swd->base = swim_base;
++
++ ret = swim_floppy_init(swd);
++ if (ret)
++ goto out_kfree;
++
++ return 0;
++
++out_kfree:
++ platform_set_drvdata(dev, NULL);
++ kfree(swd);
++out_iounmap:
++ iounmap(swim_base);
++out_release_io:
++ release_mem_region(res->start, SWIM_IO_SIZE);
++out:
++ return ret;
++}
++
++static int __devexit swim_remove(struct platform_device *dev)
++{
++ struct swim_priv *swd = platform_get_drvdata(dev);
++ int drive;
++ struct resource *res;
++
++ blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
++
++ for (drive = 0; drive < swd->floppy_count; drive++) {
++ del_gendisk(swd->unit[drive].disk);
++ put_disk(swd->unit[drive].disk);
++ }
++
++ unregister_blkdev(FLOPPY_MAJOR, "fd");
++
++ blk_cleanup_queue(swd->queue);
++
++ /* eject floppies */
++
++ for (drive = 0; drive < swd->floppy_count; drive++)
++ floppy_eject(&swd->unit[drive]);
++
++ iounmap(swd->base);
++
++ res = platform_get_resource_byname(dev, IORESOURCE_MEM, "swim-regs");
++ if (res)
++ release_mem_region(res->start, SWIM_IO_SIZE);
++
++ platform_set_drvdata(dev, NULL);
++ kfree(swd);
++
++ return 0;
++}
++
++static struct platform_driver swim_driver = {
++ .probe = swim_probe,
++ .remove = swim_remove,
++ .driver = {
++ .name = CARDNAME,
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init swim_init(void)
++{
++ printk(KERN_INFO "SWIM floppy driver %s\n", DRIVER_VERSION);
++
++ return platform_driver_register(&swim_driver);
++}
++module_init(swim_init);
++
++static void __exit swim_exit(void)
++{
++ platform_driver_unregister(&swim_driver);
++}
++module_exit(swim_exit);
++
++MODULE_DESCRIPTION("Driver for SWIM floppy controller");
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Laurent Vivier <laurent at lvivier.info>");
++MODULE_ALIAS_BLOCKDEV_MAJOR(FLOPPY_MAJOR);
+--- /dev/null
++++ b/drivers/block/swim_asm.S
+@@ -0,0 +1,247 @@
++/*
++ * low-level functions for the SWIM floppy controller
++ *
++ * needs assembly language because is very timing dependent
++ * this controller exists only on macintosh 680x0 based
++ *
++ * Copyright (C) 2004,2008 Laurent Vivier <Laurent at lvivier.info>
++ *
++ * based on Alastair Bridgewater SWIM analysis, 2001
++ * based on netBSD IWM driver (c) 1997, 1998 Hauke Fath.
++ *
++ * This program 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.
++ *
++ * 2004-08-21 (lv) - Initial implementation
++ * 2008-11-05 (lv) - add get_swim_mode
++ */
++
++ .equ write_data, 0x0000
++ .equ write_mark, 0x0200
++ .equ write_CRC, 0x0400
++ .equ write_parameter,0x0600
++ .equ write_phase, 0x0800
++ .equ write_setup, 0x0a00
++ .equ write_mode0, 0x0c00
++ .equ write_mode1, 0x0e00
++ .equ read_data, 0x1000
++ .equ read_mark, 0x1200
++ .equ read_error, 0x1400
++ .equ read_parameter, 0x1600
++ .equ read_phase, 0x1800
++ .equ read_setup, 0x1a00
++ .equ read_status, 0x1c00
++ .equ read_handshake, 0x1e00
++
++ .equ o_side, 0
++ .equ o_track, 1
++ .equ o_sector, 2
++ .equ o_size, 3
++ .equ o_crc0, 4
++ .equ o_crc1, 5
++
++ .equ seek_time, 30000
++ .equ max_retry, 40
++ .equ sector_size, 512
++
++ .global swim_read_sector_header
++swim_read_sector_header:
++ link %a6, #0
++ moveml %d1-%d5/%a0-%a4,%sp at -
++ movel %a6@(0x0c), %a4
++ bsr mfm_read_addrmark
++ moveml %sp at +, %d1-%d5/%a0-%a4
++ unlk %a6
++ rts
++
++sector_address_mark:
++ .byte 0xa1, 0xa1, 0xa1, 0xfe
++sector_data_mark:
++ .byte 0xa1, 0xa1, 0xa1, 0xfb
++
++mfm_read_addrmark:
++ movel %a6@(0x08), %a3
++ lea %a3@(read_handshake), %a2
++ lea %a3@(read_mark), %a3
++ moveq #-1, %d0
++ movew #seek_time, %d2
++
++wait_header_init:
++ tstb %a3@(read_error - read_mark)
++ moveb #0x18, %a3@(write_mode0 - read_mark)
++ moveb #0x01, %a3@(write_mode1 - read_mark)
++ moveb #0x01, %a3@(write_mode0 - read_mark)
++ tstb %a3@(read_error - read_mark)
++ moveb #0x08, %a3@(write_mode1 - read_mark)
++
++ lea sector_address_mark, %a0
++ moveq #3, %d1
++
++wait_addr_mark_byte:
++
++ tstb %a2@
++ dbmi %d2, wait_addr_mark_byte
++ bpl header_exit
++
++ moveb %a3@, %d3
++ cmpb %a0 at +, %d3
++ dbne %d1, wait_addr_mark_byte
++ bne wait_header_init
++
++ moveq #max_retry, %d2
++
++amark0: tstb %a2@
++ dbmi %d2, amark0
++ bpl signal_nonyb
++
++ moveb %a3@, %a4@(o_track)
++
++ moveq #max_retry, %d2
++
++amark1: tstb %a2@
++ dbmi %d2, amark1
++ bpl signal_nonyb
++
++ moveb %a3@, %a4@(o_side)
++
++ moveq #max_retry, %d2
++
++amark2: tstb %a2@
++ dbmi %d2, amark2
++ bpl signal_nonyb
++
++ moveb %a3@, %a4@(o_sector)
++
++ moveq #max_retry, %d2
++
++amark3: tstb %a2@
++ dbmi %d2, amark3
++ bpl signal_nonyb
++
++ moveb %a3@, %a4@(o_size)
++
++ moveq #max_retry, %d2
++
++crc0: tstb %a2@
++ dbmi %d2, crc0
++ bpl signal_nonyb
++
++ moveb %a3@, %a4@(o_crc0)
++
++ moveq #max_retry, %d2
++
++crc1: tstb %a2@
++ dbmi %d2, crc1
++ bpl signal_nonyb
++
++ moveb %a3@, %a4@(o_crc1)
++
++ tstb %a3@(read_error - read_mark)
++
++header_exit:
++ moveq #0, %d0
++ moveb #0x18, %a3@(write_mode0 - read_mark)
++ rts
++signal_nonyb:
++ moveq #-1, %d0
++ moveb #0x18, %a3@(write_mode0 - read_mark)
++ rts
++
++ .global swim_read_sector_data
++swim_read_sector_data:
++ link %a6, #0
++ moveml %d1-%d5/%a0-%a5,%sp at -
++ movel %a6@(0x0c), %a4
++ bsr mfm_read_data
++ moveml %sp at +, %d1-%d5/%a0-%a5
++ unlk %a6
++ rts
++
++mfm_read_data:
++ movel %a6@(0x08), %a3
++ lea %a3@(read_handshake), %a2
++ lea %a3@(read_data), %a5
++ lea %a3@(read_mark), %a3
++ movew #seek_time, %d2
++
++wait_data_init:
++ tstb %a3@(read_error - read_mark)
++ moveb #0x18, %a3@(write_mode0 - read_mark)
++ moveb #0x01, %a3@(write_mode1 - read_mark)
++ moveb #0x01, %a3@(write_mode0 - read_mark)
++ tstb %a3@(read_error - read_mark)
++ moveb #0x08, %a3@(write_mode1 - read_mark)
++
++ lea sector_data_mark, %a0
++ moveq #3, %d1
++
++ /* wait data address mark */
++
++wait_data_mark_byte:
++
++ tstb %a2@
++ dbmi %d2, wait_data_mark_byte
++ bpl data_exit
++
++ moveb %a3@, %d3
++ cmpb %a0 at +, %d3
++ dbne %d1, wait_data_mark_byte
++ bne wait_data_init
++
++ /* read data */
++
++ tstb %a3@(read_error - read_mark)
++
++ movel #sector_size-1, %d4 /* sector size */
++read_new_data:
++ movew #max_retry, %d2
++read_data_loop:
++ moveb %a2@, %d5
++ andb #0xc0, %d5
++ dbne %d2, read_data_loop
++ beq data_exit
++ moveb %a5@, %a4 at +
++ andb #0x40, %d5
++ dbne %d4, read_new_data
++ beq exit_loop
++ moveb %a5@, %a4 at +
++ dbra %d4, read_new_data
++exit_loop:
++
++ /* read CRC */
++
++ movew #max_retry, %d2
++data_crc0:
++
++ tstb %a2@
++ dbmi %d2, data_crc0
++ bpl data_exit
++
++ moveb %a3@, %d5
++
++ moveq #max_retry, %d2
++
++data_crc1:
++
++ tstb %a2@
++ dbmi %d2, data_crc1
++ bpl data_exit
++
++ moveb %a3@, %d5
++
++ tstb %a3@(read_error - read_mark)
++
++ moveb #0x18, %a3@(write_mode0 - read_mark)
++
++ /* return number of bytes read */
++
++ movel #sector_size, %d0
++ addw #1, %d4
++ subl %d4, %d0
++ rts
++data_exit:
++ moveb #0x18, %a3@(write_mode0 - read_mark)
++ moveq #-1, %d0
++ rts
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-add-floppy-model-entry.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-add-floppy-model-entry.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,589 @@
+From laurent at lvivier.info Thu Nov 6 21:04:17 2008
+Date: Thu, 6 Nov 2008 20:57:41 +0100
+From: Laurent Vivier <laurent at lvivier.info>
+To: geert at linux-m68k.org
+Cc: linux-m68k at vger.kernel.org, Laurent Vivier <Laurent at lvivier.info>
+Subject: [PATCH 1/2][RESEND] Add a new entry in mac_model to identify the floppy controller type.
+
+From: Laurent Vivier <Laurent at lvivier.info>
+
+This patch adds a field "floppy_type" which can take the following values:
+
+MAC_FLOPPY_IWM for an IWM based mac
+MAC_FLOPPY_SWIM_ADDR1 for a SWIM based mac with controller at VIA1 + 0x1E000
+MAC_FLOPPY_SWIM_ADDR2 for a SWIM based mac with controller at VIA1 + 0x16000
+MAC_FLOPPY_IOP for an IOP based mac
+MAC_FLOPPY_AV for an AV based mac
+
+Signed-off-by: Laurent Vivier <Laurent at lvivier.info>
+---
+ arch/m68k/mac/config.c | 163 ++++++++++++++++++++++++++++---------------
+ include/asm-m68k/macintosh.h | 7 +
+ 2 files changed, 116 insertions(+), 54 deletions(-)
+
+--- a/arch/m68k/mac/config.c
++++ b/arch/m68k/mac/config.c
+@@ -232,7 +232,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_II,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_IWM
+ },
+
+ /*
+@@ -247,7 +248,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_II,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_IWM
+ }, {
+ .ident = MAC_MODEL_IIX,
+ .name = "IIx",
+@@ -255,7 +257,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_II,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_IICX,
+ .name = "IIcx",
+@@ -263,7 +266,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_II,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_SE30,
+ .name = "SE/30",
+@@ -271,7 +275,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_II,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ },
+
+ /*
+@@ -288,7 +293,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_IIFX,
+ .name = "IIfx",
+@@ -296,7 +302,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_IOP,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_IOP
+ }, {
+ .ident = MAC_MODEL_IISI,
+ .name = "IIsi",
+@@ -304,7 +311,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_IIVI,
+ .name = "IIvi",
+@@ -312,7 +320,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_IIVX,
+ .name = "IIvx",
+@@ -320,7 +329,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ },
+
+ /*
+@@ -334,7 +344,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_CCL,
+ .name = "Color Classic",
+@@ -342,7 +353,9 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS},
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
++ },
+
+ /*
+ * Some Mac LC machines. Basically the same as the IIci, ADB like IIsi
+@@ -355,7 +368,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_LCII,
+ .name = "LC II",
+@@ -363,7 +377,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_LCIII,
+ .name = "LC III",
+@@ -371,7 +386,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ },
+
+ /*
+@@ -391,7 +407,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_QUADRA,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_Q605_ACC,
+ .name = "Quadra 605",
+@@ -399,7 +416,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_QUADRA,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_Q610,
+ .name = "Quadra 610",
+@@ -408,7 +426,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_QUADRA,
+ .scc_type = MAC_SCC_QUADRA,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_Q630,
+ .name = "Quadra 630",
+@@ -418,7 +437,8 @@ static struct mac_model mac_data_table[]
+ .ide_type = MAC_IDE_QUADRA,
+ .scc_type = MAC_SCC_QUADRA,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_Q650,
+ .name = "Quadra 650",
+@@ -427,7 +447,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_QUADRA,
+ .scc_type = MAC_SCC_QUADRA,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ },
+ /* The Q700 does have a NS Sonic */
+ {
+@@ -438,7 +459,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_QUADRA2,
+ .scc_type = MAC_SCC_QUADRA,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_Q800,
+ .name = "Quadra 800",
+@@ -447,7 +469,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_QUADRA,
+ .scc_type = MAC_SCC_QUADRA,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_Q840,
+ .name = "Quadra 840AV",
+@@ -456,7 +479,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_QUADRA3,
+ .scc_type = MAC_SCC_PSC,
+ .ether_type = MAC_ETHER_MACE,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_AV
+ }, {
+ .ident = MAC_MODEL_Q900,
+ .name = "Quadra 900",
+@@ -465,7 +489,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_QUADRA2,
+ .scc_type = MAC_SCC_IOP,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_IOP
+ }, {
+ .ident = MAC_MODEL_Q950,
+ .name = "Quadra 950",
+@@ -474,7 +499,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_QUADRA2,
+ .scc_type = MAC_SCC_IOP,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_IOP
+ },
+
+ /*
+@@ -488,7 +514,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_P475,
+ .name = "Performa 475",
+@@ -496,7 +523,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_QUADRA,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_P475F,
+ .name = "Performa 475",
+@@ -504,7 +532,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_QUADRA,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_P520,
+ .name = "Performa 520",
+@@ -512,7 +541,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_P550,
+ .name = "Performa 550",
+@@ -520,7 +550,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ },
+ /* These have the comm slot, and therefore the possibility of SONIC ethernet */
+ {
+@@ -531,7 +562,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_QUADRA,
+ .scc_type = MAC_SCC_II,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_P588,
+ .name = "Performa 588",
+@@ -541,7 +573,8 @@ static struct mac_model mac_data_table[]
+ .ide_type = MAC_IDE_QUADRA,
+ .scc_type = MAC_SCC_II,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_TV,
+ .name = "TV",
+@@ -549,7 +582,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_P600,
+ .name = "Performa 600",
+@@ -557,7 +591,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_II,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ },
+
+ /*
+@@ -573,7 +608,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_QUADRA,
+ .scc_type = MAC_SCC_QUADRA,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_C650,
+ .name = "Centris 650",
+@@ -582,7 +618,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_QUADRA,
+ .scc_type = MAC_SCC_QUADRA,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR1
+ }, {
+ .ident = MAC_MODEL_C660,
+ .name = "Centris 660AV",
+@@ -591,7 +628,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_QUADRA3,
+ .scc_type = MAC_SCC_PSC,
+ .ether_type = MAC_ETHER_MACE,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_AV
+ },
+
+ /*
+@@ -607,7 +645,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB145,
+ .name = "PowerBook 145",
+@@ -615,7 +654,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB150,
+ .name = "PowerBook 150",
+@@ -624,7 +664,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_OLD,
+ .ide_type = MAC_IDE_PB,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB160,
+ .name = "PowerBook 160",
+@@ -632,7 +673,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB165,
+ .name = "PowerBook 165",
+@@ -640,7 +682,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB165C,
+ .name = "PowerBook 165c",
+@@ -648,7 +691,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB170,
+ .name = "PowerBook 170",
+@@ -656,7 +700,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB180,
+ .name = "PowerBook 180",
+@@ -664,7 +709,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB180C,
+ .name = "PowerBook 180c",
+@@ -672,7 +718,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_QUADRA,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB190,
+ .name = "PowerBook 190",
+@@ -681,7 +728,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_OLD,
+ .ide_type = MAC_IDE_BABOON,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB520,
+ .name = "PowerBook 520",
+@@ -690,7 +738,8 @@ static struct mac_model mac_data_table[]
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+ .ether_type = MAC_ETHER_SONIC,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ },
+
+ /*
+@@ -710,7 +759,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB230,
+ .name = "PowerBook Duo 230",
+@@ -718,7 +768,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB250,
+ .name = "PowerBook Duo 250",
+@@ -726,7 +777,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB270C,
+ .name = "PowerBook Duo 270c",
+@@ -734,7 +786,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB280,
+ .name = "PowerBook Duo 280",
+@@ -742,7 +795,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ }, {
+ .ident = MAC_MODEL_PB280C,
+ .name = "PowerBook Duo 280c",
+@@ -750,7 +804,8 @@ static struct mac_model mac_data_table[]
+ .via_type = MAC_VIA_IIci,
+ .scsi_type = MAC_SCSI_OLD,
+ .scc_type = MAC_SCC_QUADRA,
+- .nubus_type = MAC_NUBUS
++ .nubus_type = MAC_NUBUS,
++ .floppy_type = MAC_FLOPPY_SWIM_ADDR2
+ },
+
+ /*
+--- a/include/asm-m68k/macintosh.h
++++ b/include/asm-m68k/macintosh.h
+@@ -34,6 +34,7 @@ struct mac_model
+ char scc_type;
+ char ether_type;
+ char nubus_type;
++ char floppy_type;
+ };
+
+ #define MAC_ADB_NONE 0
+@@ -71,6 +72,12 @@ struct mac_model
+ #define MAC_NO_NUBUS 0
+ #define MAC_NUBUS 1
+
++#define MAC_FLOPPY_IWM 0
++#define MAC_FLOPPY_SWIM_ADDR1 1
++#define MAC_FLOPPY_SWIM_ADDR2 2
++#define MAC_FLOPPY_SWIM_IOP 3
++#define MAC_FLOPPY_AV 4
++
+ /*
+ * Gestalt numbers
+ */
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-baboon-interrupt-enable-disable.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-baboon-interrupt-enable-disable.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,130 @@
+Subject: [PATCH] m68k: mac baboon interrupt enable/disable
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+No-one seems to know how to mask individual baboon interrupts, so we just
+mask the umbrella IRQ. This will work as long as only the IDE driver uses
+the baboon chip (it can't deadlock). Use mac_enable_irq/mac_disable_irq
+rather than enable_irq/disable_irq because the latter routines count the
+depth of nested calls which triggers a warning and call trace because
+IRQ_NUBUS_C is enabled twice in a row (once when the baboon handler is
+registered, and once when the IDE IRQ is registered).
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/mac/baboon.c | 42 +++++++++++++++++++++++++++++++-----------
+ arch/m68k/mac/macints.c | 8 ++++----
+ 2 files changed, 35 insertions(+), 15 deletions(-)
+
+--- a/arch/m68k/mac/baboon.c
++++ b/arch/m68k/mac/baboon.c
+@@ -18,11 +18,14 @@
+ #include <asm/macints.h>
+ #include <asm/mac_baboon.h>
+
+-/* #define DEBUG_BABOON */
+ /* #define DEBUG_IRQS */
+
++extern void mac_enable_irq(unsigned int);
++extern void mac_disable_irq(unsigned int);
++
+ int baboon_present;
+ static volatile struct baboon *baboon;
++static unsigned char baboon_disabled;
+
+ #if 0
+ extern int macide_ack_intr(struct ata_channel *);
+@@ -88,34 +91,51 @@ static irqreturn_t baboon_irq(int irq, v
+
+ void __init baboon_register_interrupts(void)
+ {
+- request_irq(IRQ_NUBUS_C, baboon_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+- "baboon", (void *) baboon);
++ baboon_disabled = 0;
++ request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon);
+ }
+
+-void baboon_irq_enable(int irq) {
++/*
++ * The means for masking individual baboon interrupts remains a mystery, so
++ * enable the umbrella interrupt only when no baboon interrupt is disabled.
++ */
++
++void baboon_irq_enable(int irq)
++{
++ int irq_idx = IRQ_IDX(irq);
++
+ #ifdef DEBUG_IRQUSE
+ printk("baboon_irq_enable(%d)\n", irq);
+ #endif
+- /* FIXME: figure out how to mask and unmask baboon interrupt sources */
+- enable_irq(IRQ_NUBUS_C);
++
++ baboon_disabled &= ~(1 << irq_idx);
++ if (!baboon_disabled)
++ mac_enable_irq(IRQ_NUBUS_C);
+ }
+
+-void baboon_irq_disable(int irq) {
++void baboon_irq_disable(int irq)
++{
++ int irq_idx = IRQ_IDX(irq);
++
+ #ifdef DEBUG_IRQUSE
+ printk("baboon_irq_disable(%d)\n", irq);
+ #endif
+- disable_irq(IRQ_NUBUS_C);
++
++ baboon_disabled |= 1 << irq_idx;
++ if (baboon_disabled)
++ mac_disable_irq(IRQ_NUBUS_C);
+ }
+
+-void baboon_irq_clear(int irq) {
+- int irq_idx = IRQ_IDX(irq);
++void baboon_irq_clear(int irq)
++{
++ int irq_idx = IRQ_IDX(irq);
+
+ baboon->mb_ifr &= ~(1 << irq_idx);
+ }
+
+ int baboon_irq_pending(int irq)
+ {
+- int irq_idx = IRQ_IDX(irq);
++ int irq_idx = IRQ_IDX(irq);
+
+ return baboon->mb_ifr & (1 << irq_idx);
+ }
+--- a/arch/m68k/mac/macints.c
++++ b/arch/m68k/mac/macints.c
+@@ -214,8 +214,8 @@ irqreturn_t mac_debug_handler(int, void
+
+ /* #define DEBUG_MACINTS */
+
+-static void mac_enable_irq(unsigned int irq);
+-static void mac_disable_irq(unsigned int irq);
++void mac_enable_irq(unsigned int irq);
++void mac_disable_irq(unsigned int irq);
+
+ static struct irq_controller mac_irq_controller = {
+ .name = "mac",
+@@ -274,7 +274,7 @@ void __init mac_init_IRQ(void)
+ * These routines are just dispatchers to the VIA/OSS/PSC routines.
+ */
+
+-static void mac_enable_irq(unsigned int irq)
++void mac_enable_irq(unsigned int irq)
+ {
+ int irq_src = IRQ_SRC(irq);
+
+@@ -307,7 +307,7 @@ static void mac_enable_irq(unsigned int
+ }
+ }
+
+-static void mac_disable_irq(unsigned int irq)
++void mac_disable_irq(unsigned int irq)
+ {
+ int irq_src = IRQ_SRC(irq);
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-esp-fix-for-quadras-with-two-esp-chips.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-esp-fix-for-quadras-with-two-esp-chips.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,154 @@
+Subject: [PATCH] mac_esp: fix for quadras with two esp chips
+cc: linux-scsi at vger.kernel.org
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+On the Quadra 900 and 950 there are two ESP chips sharing one IRQ. Because
+the shared IRQ is edge-triggered, we must make sure that an IRQ transition
+from one chip doesn't go unnoticed when the shared IRQ is already active
+due to the other. This patch prevents interrupts getting lost so that both
+SCSI busses may be used simultaneously.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/scsi/mac_esp.c | 83 ++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 59 insertions(+), 24 deletions(-)
+
+--- a/drivers/scsi/mac_esp.c
++++ b/drivers/scsi/mac_esp.c
+@@ -53,7 +53,8 @@ struct mac_esp_priv {
+ void __iomem *pdma_io;
+ int error;
+ };
+-static struct platform_device *internal_esp, *external_esp;
++static struct platform_device *internal_pdev, *external_pdev;
++static struct esp *esp_chips[2];
+
+ #define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
+ platform_get_drvdata((struct platform_device *) \
+@@ -443,6 +444,32 @@ static u32 mac_esp_dma_length_limit(stru
+ return dma_len > 0xFFFF ? 0xFFFF : dma_len;
+ }
+
++static irqreturn_t mac_scsi_esp_intr(int irq, void *dev_id)
++{
++ int got_intr;
++
++ /*
++ * This is an edge triggered IRQ, so we have to be careful to
++ * avoid missing a transition when it is shared by two ESP devices.
++ */
++
++ do {
++ got_intr = 0;
++ if (esp_chips[0] &&
++ (mac_esp_read8(esp_chips[0], ESP_STATUS) & ESP_STAT_INTR)) {
++ (void)scsi_esp_intr(irq, esp_chips[0]);
++ got_intr = 1;
++ }
++ if (esp_chips[1] &&
++ (mac_esp_read8(esp_chips[1], ESP_STATUS) & ESP_STAT_INTR)) {
++ (void)scsi_esp_intr(irq, esp_chips[1]);
++ got_intr = 1;
++ }
++ } while (got_intr);
++
++ return IRQ_HANDLED;
++}
++
+ static struct esp_driver_ops mac_esp_ops = {
+ .esp_write8 = mac_esp_write8,
+ .esp_read8 = mac_esp_read8,
+@@ -557,10 +584,16 @@ static int __devinit esp_mac_probe(struc
+ }
+
+ host->irq = IRQ_MAC_SCSI;
+- err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "Mac ESP",
+- esp);
+- if (err < 0)
+- goto fail_free_priv;
++ esp_chips[dev->id] = esp;
++ mb();
++ if (esp_chips[!dev->id] == NULL) {
++ err = request_irq(host->irq, mac_scsi_esp_intr, 0,
++ "Mac ESP", NULL);
++ if (err < 0) {
++ esp_chips[dev->id] = NULL;
++ goto fail_free_priv;
++ }
++ }
+
+ err = scsi_esp_register(esp, &dev->dev);
+ if (err)
+@@ -569,7 +602,8 @@ static int __devinit esp_mac_probe(struc
+ return 0;
+
+ fail_free_irq:
+- free_irq(host->irq, esp);
++ if (esp_chips[!dev->id] == NULL)
++ free_irq(host->irq, esp);
+ fail_free_priv:
+ kfree(mep);
+ fail_free_command_block:
+@@ -588,7 +622,9 @@ static int __devexit esp_mac_remove(stru
+
+ scsi_esp_unregister(esp);
+
+- free_irq(irq, esp);
++ esp_chips[dev->id] = NULL;
++ if (!(esp_chips[0] || esp_chips[1]))
++ free_irq(irq, NULL);
+
+ kfree(mep);
+
+@@ -615,19 +651,18 @@ static int __init mac_esp_init(void)
+ if (err)
+ return err;
+
+- internal_esp = platform_device_alloc(DRV_MODULE_NAME, 0);
+- if (internal_esp && platform_device_add(internal_esp)) {
+- platform_device_put(internal_esp);
+- internal_esp = NULL;
++ internal_pdev = platform_device_alloc(DRV_MODULE_NAME, 0);
++ if (internal_pdev && platform_device_add(internal_pdev)) {
++ platform_device_put(internal_pdev);
++ internal_pdev = NULL;
+ }
+-
+- external_esp = platform_device_alloc(DRV_MODULE_NAME, 1);
+- if (external_esp && platform_device_add(external_esp)) {
+- platform_device_put(external_esp);
+- external_esp = NULL;
++ external_pdev = platform_device_alloc(DRV_MODULE_NAME, 1);
++ if (external_pdev && platform_device_add(external_pdev)) {
++ platform_device_put(external_pdev);
++ external_pdev = NULL;
+ }
+
+- if (internal_esp || external_esp) {
++ if (internal_pdev || external_pdev) {
+ return 0;
+ } else {
+ platform_driver_unregister(&esp_mac_driver);
+@@ -639,13 +674,13 @@ static void __exit mac_esp_exit(void)
+ {
+ platform_driver_unregister(&esp_mac_driver);
+
+- if (internal_esp) {
+- platform_device_unregister(internal_esp);
+- internal_esp = NULL;
+- }
+- if (external_esp) {
+- platform_device_unregister(external_esp);
+- external_esp = NULL;
++ if (internal_pdev) {
++ platform_device_unregister(internal_pdev);
++ internal_pdev = NULL;
++ }
++ if (external_pdev) {
++ platform_device_unregister(external_pdev);
++ external_pdev = NULL;
+ }
+ }
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-mac_esp-asm-fix.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-mac_esp-asm-fix.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,79 @@
+Subject: [PATCH] m68k: mac_esp asm fix
+cc: linux-scsi at vger.kernel.org
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Fix asm constraints and arguments so as not to transfer an odd byte when
+there may be more words to transfer. The bug would probably also cause
+exceptions sometimes by transferring one too many bytes.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/scsi/mac_esp.c | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+--- a/drivers/scsi/mac_esp.c
++++ b/drivers/scsi/mac_esp.c
+@@ -170,7 +170,7 @@ static inline int mac_esp_wait_for_dreq(
+
+ #define MAC_ESP_PDMA_LOOP(operands) \
+ asm volatile ( \
+- " tstw %2 \n" \
++ " tstw %1 \n" \
+ " jbeq 20f \n" \
+ "1: movew " operands " \n" \
+ "2: movew " operands " \n" \
+@@ -188,14 +188,14 @@ static inline int mac_esp_wait_for_dreq(
+ "14: movew " operands " \n" \
+ "15: movew " operands " \n" \
+ "16: movew " operands " \n" \
+- " subqw #1,%2 \n" \
++ " subqw #1,%1 \n" \
+ " jbne 1b \n" \
+- "20: tstw %3 \n" \
++ "20: tstw %2 \n" \
+ " jbeq 30f \n" \
+ "21: movew " operands " \n" \
+- " subqw #1,%3 \n" \
++ " subqw #1,%2 \n" \
+ " jbne 21b \n" \
+- "30: tstw %4 \n" \
++ "30: tstw %3 \n" \
+ " jbeq 40f \n" \
+ "31: moveb " operands " \n" \
+ "32: nop \n" \
+@@ -223,8 +223,8 @@ static inline int mac_esp_wait_for_dreq(
+ " .long 31b,40b \n" \
+ " .long 32b,40b \n" \
+ " .previous \n" \
+- : "+a" (addr) \
+- : "a" (mep->pdma_io), "r" (count32), "r" (count2), "g" (esp_count))
++ : "+a" (addr), "+r" (count32), "+r" (count2) \
++ : "g" (count1), "a" (mep->pdma_io))
+
+ static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
+ u32 dma_count, int write, u8 cmd)
+@@ -247,19 +247,20 @@ static void mac_esp_send_pdma_cmd(struct
+ do {
+ unsigned int count32 = esp_count >> 5;
+ unsigned int count2 = (esp_count & 0x1F) >> 1;
++ unsigned int count1 = esp_count & 1;
+ unsigned int start_addr = addr;
+
+ if (mac_esp_wait_for_dreq(esp))
+ break;
+
+ if (write) {
+- MAC_ESP_PDMA_LOOP("%1@,%0 at +");
++ MAC_ESP_PDMA_LOOP("%4@,%0 at +");
+
+ esp_count -= addr - start_addr;
+ } else {
+ unsigned int n;
+
+- MAC_ESP_PDMA_LOOP("%0 at +,%1@");
++ MAC_ESP_PDMA_LOOP("%0 at +,%4@");
+
+ if (mac_esp_wait_for_empty_fifo(esp))
+ break;
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-macfb-annotations-and-compiler-warning-fix.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-macfb-annotations-and-compiler-warning-fix.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,96 @@
+Subject: [PATCH] macfb annotations and compiler warning fix
+cc: linux-fbdev-devel at lists.sourceforge.net
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Add some __iomem annotations. Remove some volatile qualifiers to fix
+several compiler warnings: "passing arg 1 of `iounmap' discards qualifiers
+from pointer target type".
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/video/macfb.c | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+--- a/drivers/video/macfb.c
++++ b/drivers/video/macfb.c
+@@ -77,34 +77,34 @@ static int csc_setpalette (unsigned int
+ unsigned int green, unsigned int blue,
+ struct fb_info *fb_info);
+
+-static volatile struct {
++static struct {
+ unsigned char addr;
+ /* Note: word-aligned */
+ char pad[3];
+ unsigned char lut;
+-} *valkyrie_cmap_regs;
++} __iomem *valkyrie_cmap_regs;
+
+-static volatile struct {
++static struct {
+ unsigned char addr;
+ unsigned char lut;
+-} *v8_brazil_cmap_regs;
++} __iomem *v8_brazil_cmap_regs;
+
+-static volatile struct {
++static struct {
+ unsigned char addr;
+ char pad1[3]; /* word aligned */
+ unsigned char lut;
+ char pad2[3]; /* word aligned */
+ unsigned char cntl; /* a guess as to purpose */
+-} *rbv_cmap_regs;
++} __iomem *rbv_cmap_regs;
+
+-static volatile struct {
++static struct {
+ unsigned long reset;
+ unsigned long pad1[3];
+ unsigned char pad2[3];
+ unsigned char lut;
+-} *dafb_cmap_regs;
++} __iomem *dafb_cmap_regs;
+
+-static volatile struct {
++static struct {
+ unsigned char addr; /* OFFSET: 0x00 */
+ unsigned char pad1[15];
+ unsigned char lut; /* OFFSET: 0x10 */
+@@ -113,16 +113,16 @@ static volatile struct {
+ unsigned char pad3[7];
+ unsigned long vbl_addr; /* OFFSET: 0x28 */
+ unsigned int status2; /* OFFSET: 0x2C */
+-} *civic_cmap_regs;
++} __iomem *civic_cmap_regs;
+
+-static volatile struct {
++static struct {
+ char pad1[0x40];
+ unsigned char clut_waddr; /* 0x40 */
+ char pad2;
+ unsigned char clut_data; /* 0x42 */
+ char pad3[0x3];
+ unsigned char clut_raddr; /* 0x46 */
+-} *csc_cmap_regs;
++} __iomem *csc_cmap_regs;
+
+ /* We will leave these the way they are for the time being */
+ struct mdc_cmap_regs {
+@@ -506,10 +506,10 @@ static int csc_setpalette (unsigned int
+ struct fb_info *info)
+ {
+ mdelay(1);
+- csc_cmap_regs->clut_waddr = regno;
+- csc_cmap_regs->clut_data = red;
+- csc_cmap_regs->clut_data = green;
+- csc_cmap_regs->clut_data = blue;
++ nubus_writeb(regno, &csc_cmap_regs->clut_waddr);
++ nubus_writeb(red, &csc_cmap_regs->clut_data);
++ nubus_writeb(green, &csc_cmap_regs->clut_data);
++ nubus_writeb(blue, &csc_cmap_regs->clut_data);
+ return 0;
+ }
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-macfb-do-not-overflow-fix-id.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-macfb-do-not-overflow-fix-id.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,233 @@
+Subject: [PATCH] macfb: Do not overflow fb_fix_screeninfo.id
+cc: linux-fbdev-devel at lists.sourceforge.net
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Don't overflow the 16-character fb_fix_screeninfo id string (fixes some
+console erasing and blanking artifacts). Have the ID default to "Unknown"
+on machines with no built-in video and no nubus devices. Check for
+fb_alloc_cmap failure.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/video/macfb.c | 74 +++++++++++++++++++++++---------------------------
+ 1 file changed, 35 insertions(+), 39 deletions(-)
+
+--- a/drivers/video/macfb.c
++++ b/drivers/video/macfb.c
+@@ -164,7 +164,6 @@ static struct fb_var_screeninfo macfb_de
+ };
+
+ static struct fb_fix_screeninfo macfb_fix = {
+- .id = "Macintosh ",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .accel = FB_ACCEL_NONE,
+ };
+@@ -760,22 +759,22 @@ static int __init macfb_init(void)
+
+ switch(ndev->dr_hw) {
+ case NUBUS_DRHW_APPLE_MDC:
+- strcat( macfb_fix.id, "Display Card" );
++ strcpy(macfb_fix.id, "Mac Disp. Card");
+ macfb_setpalette = mdc_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ break;
+ case NUBUS_DRHW_APPLE_TFB:
+- strcat( macfb_fix.id, "Toby" );
++ strcpy(macfb_fix.id, "Toby");
+ macfb_setpalette = toby_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ break;
+ case NUBUS_DRHW_APPLE_JET:
+- strcat( macfb_fix.id, "Jet");
++ strcpy(macfb_fix.id, "Jet");
+ macfb_setpalette = jet_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ break;
+ default:
+- strcat( macfb_fix.id, "Generic NuBus" );
++ strcpy(macfb_fix.id, "Generic NuBus");
+ break;
+ }
+ }
+@@ -786,21 +785,11 @@ static int __init macfb_init(void)
+ if (!video_is_nubus)
+ switch( mac_bi_data.id )
+ {
+- /* These don't have onboard video. Eventually, we may
+- be able to write separate framebuffer drivers for
+- them (tobyfb.c, hiresfb.c, etc, etc) */
+- case MAC_MODEL_II:
+- case MAC_MODEL_IIX:
+- case MAC_MODEL_IICX:
+- case MAC_MODEL_IIFX:
+- strcat( macfb_fix.id, "Generic NuBus" );
+- break;
+-
+ /* Valkyrie Quadras */
+ case MAC_MODEL_Q630:
+ /* I'm not sure about this one */
+ case MAC_MODEL_P588:
+- strcat( macfb_fix.id, "Valkyrie built-in" );
++ strcpy(macfb_fix.id, "Valkyrie");
+ macfb_setpalette = valkyrie_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ valkyrie_cmap_regs = ioremap(DAC_BASE, 0x1000);
+@@ -823,7 +812,7 @@ static int __init macfb_init(void)
+ case MAC_MODEL_Q700:
+ case MAC_MODEL_Q900:
+ case MAC_MODEL_Q950:
+- strcat( macfb_fix.id, "DAFB built-in" );
++ strcpy(macfb_fix.id, "DAFB");
+ macfb_setpalette = dafb_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
+@@ -831,7 +820,7 @@ static int __init macfb_init(void)
+
+ /* LC II uses the V8 framebuffer */
+ case MAC_MODEL_LCII:
+- strcat( macfb_fix.id, "V8 built-in" );
++ strcpy(macfb_fix.id, "V8");
+ macfb_setpalette = v8_brazil_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+@@ -843,7 +832,7 @@ static int __init macfb_init(void)
+ case MAC_MODEL_IIVI:
+ case MAC_MODEL_IIVX:
+ case MAC_MODEL_P600:
+- strcat( macfb_fix.id, "Brazil built-in" );
++ strcpy(macfb_fix.id, "Brazil");
+ macfb_setpalette = v8_brazil_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+ v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+@@ -860,7 +849,7 @@ static int __init macfb_init(void)
+ case MAC_MODEL_P460:
+ macfb_setpalette = v8_brazil_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+- strcat( macfb_fix.id, "Sonora built-in" );
++ strcpy(macfb_fix.id, "Sonora");
+ v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ break;
+
+@@ -871,7 +860,7 @@ static int __init macfb_init(void)
+ case MAC_MODEL_IISI:
+ macfb_setpalette = rbv_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+- strcat( macfb_fix.id, "RBV built-in" );
++ strcpy(macfb_fix.id, "RBV");
+ rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ break;
+
+@@ -880,7 +869,7 @@ static int __init macfb_init(void)
+ case MAC_MODEL_C660:
+ macfb_setpalette = civic_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+- strcat( macfb_fix.id, "Civic built-in" );
++ strcpy(macfb_fix.id, "Civic");
+ civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
+ break;
+
+@@ -901,7 +890,7 @@ static int __init macfb_init(void)
+ v8_brazil_cmap_regs =
+ ioremap(DAC_BASE, 0x1000);
+ }
+- strcat( macfb_fix.id, "LC built-in" );
++ strcpy(macfb_fix.id, "LC");
+ break;
+ /* We think this may be like the LC II */
+ case MAC_MODEL_CCL:
+@@ -911,18 +900,18 @@ static int __init macfb_init(void)
+ v8_brazil_cmap_regs =
+ ioremap(DAC_BASE, 0x1000);
+ }
+- strcat( macfb_fix.id, "Color Classic built-in" );
++ strcpy(macfb_fix.id, "Color Classic");
+ break;
+
+ /* And we *do* mean "weirdos" */
+ case MAC_MODEL_TV:
+- strcat( macfb_fix.id, "Mac TV built-in" );
++ strcpy(macfb_fix.id, "Mac TV");
+ break;
+
+ /* These don't have colour, so no need to worry */
+ case MAC_MODEL_SE30:
+ case MAC_MODEL_CLII:
+- strcat( macfb_fix.id, "Monochrome built-in" );
++ strcpy(macfb_fix.id, "Monochrome");
+ break;
+
+ /* Powerbooks are particularly difficult. Many of
+@@ -935,7 +924,7 @@ static int __init macfb_init(void)
+ case MAC_MODEL_PB140:
+ case MAC_MODEL_PB145:
+ case MAC_MODEL_PB170:
+- strcat( macfb_fix.id, "DDC built-in" );
++ strcpy(macfb_fix.id, "DDC");
+ break;
+
+ /* Internal is GSC, External (if present) is ViSC */
+@@ -945,13 +934,13 @@ static int __init macfb_init(void)
+ case MAC_MODEL_PB180:
+ case MAC_MODEL_PB210:
+ case MAC_MODEL_PB230:
+- strcat( macfb_fix.id, "GSC built-in" );
++ strcpy(macfb_fix.id, "GSC");
+ break;
+
+ /* Internal is TIM, External is ViSC */
+ case MAC_MODEL_PB165C:
+ case MAC_MODEL_PB180C:
+- strcat( macfb_fix.id, "TIM built-in" );
++ strcpy(macfb_fix.id, "TIM");
+ break;
+
+ /* Internal is CSC, External is Keystone+Ariel. */
+@@ -963,12 +952,12 @@ static int __init macfb_init(void)
+ case MAC_MODEL_PB280C:
+ macfb_setpalette = csc_setpalette;
+ macfb_defined.activate = FB_ACTIVATE_NOW;
+- strcat( macfb_fix.id, "CSC built-in" );
++ strcpy(macfb_fix.id, "CSC");
+ csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
+ break;
+
+ default:
+- strcat( macfb_fix.id, "Unknown/Unsupported built-in" );
++ strcpy(macfb_fix.id, "Unknown");
+ break;
+ }
+
+@@ -978,16 +967,23 @@ static int __init macfb_init(void)
+ fb_info.pseudo_palette = pseudo_palette;
+ fb_info.flags = FBINFO_DEFAULT;
+
+- fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
++ err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
++ if (err)
++ goto fail_unmap;
+
+ err = register_framebuffer(&fb_info);
+- if (!err)
+- printk("fb%d: %s frame buffer device\n",
+- fb_info.node, fb_info.fix.id);
+- else {
+- iounmap(fb_info.screen_base);
+- iounmap_macfb();
+- }
++ if (err)
++ goto fail_dealloc;
++
++ printk("fb%d: %s frame buffer device\n",
++ fb_info.node, fb_info.fix.id);
++ return 0;
++
++fail_dealloc:
++ fb_dealloc_cmap(&fb_info.cmap);
++fail_unmap:
++ iounmap(fb_info.screen_base);
++ iounmap_macfb();
+ return err;
+ }
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-machw_h_cleanup.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-machw_h_cleanup.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,165 @@
+Subject: [PATCH] m68k: machw.h cleanup
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Remove some more cruft from machw.h and drop the #include where it isn't
+needed.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/mac/debug.c | 1 -
+ arch/m68k/mac/macints.c | 1 -
+ arch/m68k/mac/oss.c | 1 -
+ arch/m68k/mac/via.c | 1 -
+ drivers/ide/macide.c | 1 -
+ drivers/macintosh/via-cuda.c | 1 -
+ drivers/macintosh/via-macii.c | 1 -
+ drivers/macintosh/via-maciisi.c | 1 -
+ drivers/macintosh/via-pmu68k.c | 1 -
+ drivers/scsi/mac_scsi.c | 1 -
+ drivers/video/macfb.c | 1 -
+ include/asm-m68k/machw.h | 22 ----------------------
+ 12 files changed, 33 deletions(-)
+
+--- a/arch/m68k/mac/debug.c
++++ b/arch/m68k/mac/debug.c
+@@ -24,7 +24,6 @@
+ #define BOOTINFO_COMPAT_1_0
+ #include <asm/setup.h>
+ #include <asm/bootinfo.h>
+-#include <asm/machw.h>
+ #include <asm/macints.h>
+
+ extern unsigned long mac_videobase;
+--- a/arch/m68k/mac/macints.c
++++ b/arch/m68k/mac/macints.c
+@@ -127,7 +127,6 @@
+ #include <asm/irq.h>
+ #include <asm/traps.h>
+ #include <asm/bootinfo.h>
+-#include <asm/machw.h>
+ #include <asm/macintosh.h>
+ #include <asm/mac_via.h>
+ #include <asm/mac_psc.h>
+--- a/arch/m68k/mac/oss.c
++++ b/arch/m68k/mac/oss.c
+@@ -21,7 +21,6 @@
+ #include <linux/init.h>
+
+ #include <asm/bootinfo.h>
+-#include <asm/machw.h>
+ #include <asm/macintosh.h>
+ #include <asm/macints.h>
+ #include <asm/mac_via.h>
+--- a/arch/m68k/mac/via.c
++++ b/arch/m68k/mac/via.c
+@@ -32,7 +32,6 @@
+ #include <asm/bootinfo.h>
+ #include <asm/macintosh.h>
+ #include <asm/macints.h>
+-#include <asm/machw.h>
+ #include <asm/mac_via.h>
+ #include <asm/mac_psc.h>
+
+--- a/drivers/ide/macide.c
++++ b/drivers/ide/macide.c
+@@ -18,7 +18,6 @@
+ #include <linux/delay.h>
+ #include <linux/ide.h>
+
+-#include <asm/machw.h>
+ #include <asm/macintosh.h>
+ #include <asm/macints.h>
+ #include <asm/mac_baboon.h>
+--- a/drivers/macintosh/via-cuda.c
++++ b/drivers/macintosh/via-cuda.c
+@@ -23,7 +23,6 @@
+ #else
+ #include <asm/macintosh.h>
+ #include <asm/macints.h>
+-#include <asm/machw.h>
+ #include <asm/mac_via.h>
+ #endif
+ #include <asm/io.h>
+--- a/drivers/macintosh/via-macii.c
++++ b/drivers/macintosh/via-macii.c
+@@ -33,7 +33,6 @@
+ #include <linux/init.h>
+ #include <asm/macintosh.h>
+ #include <asm/macints.h>
+-#include <asm/machw.h>
+ #include <asm/mac_via.h>
+ #include <asm/system.h>
+
+--- a/drivers/macintosh/via-maciisi.c
++++ b/drivers/macintosh/via-maciisi.c
+@@ -24,7 +24,6 @@
+ #include <linux/interrupt.h>
+ #include <asm/macintosh.h>
+ #include <asm/macints.h>
+-#include <asm/machw.h>
+ #include <asm/mac_via.h>
+
+ static volatile unsigned char *via;
+--- a/drivers/macintosh/via-pmu68k.c
++++ b/drivers/macintosh/via-pmu68k.c
+@@ -35,7 +35,6 @@
+
+ #include <asm/macintosh.h>
+ #include <asm/macints.h>
+-#include <asm/machw.h>
+ #include <asm/mac_via.h>
+
+ #include <asm/pgtable.h>
+--- a/drivers/scsi/mac_scsi.c
++++ b/drivers/scsi/mac_scsi.c
+@@ -47,7 +47,6 @@
+
+ #include <asm/macintosh.h>
+ #include <asm/macints.h>
+-#include <asm/machw.h>
+ #include <asm/mac_via.h>
+
+ #include "scsi.h"
+--- a/drivers/video/macfb.c
++++ b/drivers/video/macfb.c
+@@ -36,7 +36,6 @@
+ #include <asm/irq.h>
+ #include <asm/macintosh.h>
+ #include <asm/io.h>
+-#include <asm/machw.h>
+
+ /* Common DAC base address for the LC, RBV, Valkyrie, and IIvx */
+ #define DAC_BASE 0x50f24000
+--- a/include/asm-m68k/machw.h
++++ b/include/asm-m68k/machw.h
+@@ -26,28 +26,6 @@
+ #include <linux/types.h>
+
+ #if 0
+-/* Mac SCSI Controller 5380 */
+-
+-#define MAC_5380_BAS (0x50F10000) /* This is definitely wrong!! */
+-struct MAC_5380 {
+- u_char scsi_data;
+- u_char char_dummy1;
+- u_char scsi_icr;
+- u_char char_dummy2;
+- u_char scsi_mode;
+- u_char char_dummy3;
+- u_char scsi_tcr;
+- u_char char_dummy4;
+- u_char scsi_idstat;
+- u_char char_dummy5;
+- u_char scsi_dmastat;
+- u_char char_dummy6;
+- u_char scsi_targrcv;
+- u_char char_dummy7;
+- u_char scsi_inircv;
+-};
+-#define mac_scsi ((*(volatile struct MAC_5380 *)MAC_5380_BAS))
+-
+ /*
+ ** SCC Z8530
+ */
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-platform-device.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-platform-device.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,24 @@
+Subject: [PATCH] m68k: Initial Mac platform device handling
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+drivers/scsi/mac_esp.c: if (MACHW_PRESENT(MAC_SCSI_96)) {
+drivers/scsi/mac_esp.c: if (MACHW_PRESENT(MAC_SCSI_96_2)) {
+include/asm-m68k/machw.h:#define MACHW_PRESENT(name) (mac_hw_present.name)
+---
+ arch/m68k/mac/platform.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- /dev/null
++++ b/arch/m68k/mac/platform.c
+@@ -0,0 +1,10 @@
++/*
++ * Copyright (C) 2007 Geert Uytterhoeven
++ *
++ * 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/platform_device.h>
++
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-reinstate-rtc.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-reinstate-rtc.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,78 @@
+Subject: [PATCH] m68k: Reinstate mac rtc
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+Reinstate the Mac hardware clock for CUDA ADB and Mac II ADB models.
+It doesn't work properly on Mac IIsi ADB and PMU ADB yet, so leave them
+out.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/mac/config.c | 3 ---
+ arch/m68k/mac/misc.c | 16 ++++++++++------
+ 2 files changed, 10 insertions(+), 9 deletions(-)
+
+--- a/arch/m68k/mac/config.c
++++ b/arch/m68k/mac/config.c
+@@ -162,10 +162,7 @@ void __init config_mac(void)
+ mach_init_IRQ = mac_init_IRQ;
+ mach_get_model = mac_get_model;
+ mach_gettimeoffset = mac_gettimeoffset;
+-#warning move to adb/via init
+-#if 0
+ mach_hwclk = mac_hwclk;
+-#endif
+ mach_set_clock_mmss = mac_set_clock_mmss;
+ mach_reset = mac_reset;
+ mach_halt = mac_poweroff;
+--- a/arch/m68k/mac/misc.c
++++ b/arch/m68k/mac/misc.c
+@@ -93,7 +93,7 @@ static void cuda_write_pram(int offset,
+ #define cuda_write_pram NULL
+ #endif
+
+-#ifdef CONFIG_ADB_PMU68K
++#if 0 /* def CONFIG_ADB_PMU68K */
+ static long pmu_read_time(void)
+ {
+ struct adb_request req;
+@@ -148,7 +148,7 @@ static void pmu_write_pram(int offset, _
+ #define pmu_write_pram NULL
+ #endif
+
+-#ifdef CONFIG_ADB_MACIISI
++#if 0 /* def CONFIG_ADB_MACIISI */
+ extern int maciisi_request(struct adb_request *req,
+ void (*done)(struct adb_request *), int nbytes, ...);
+
+@@ -717,13 +717,18 @@ int mac_hwclk(int op, struct rtc_time *t
+ unmktime(now, 0,
+ &t->tm_year, &t->tm_mon, &t->tm_mday,
+ &t->tm_hour, &t->tm_min, &t->tm_sec);
++#if 0
+ printk("mac_hwclk: read %04d-%02d-%-2d %02d:%02d:%02d\n",
+- t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
++ t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
++ t->tm_hour, t->tm_min, t->tm_sec);
++#endif
+ } else { /* write */
++#if 0
+ printk("mac_hwclk: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n",
+- t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
++ t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
++ t->tm_hour, t->tm_min, t->tm_sec);
++#endif
+
+-#if 0 /* it trashes my rtc */
+ now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+
+@@ -742,7 +747,6 @@ int mac_hwclk(int op, struct rtc_time *t
+ case MAC_ADB_IISI:
+ maciisi_write_time(now);
+ }
+-#endif
+ }
+ return 0;
+ }
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-via-cleanup-and-commentry.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/mac-via-cleanup-and-commentry.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,151 @@
+Subject: [PATCH] m68k: Mac via cleanup and commentry
+
+From: Finn Thain <fthain at telegraphics.com.au>
+
+No behavioural changes, just cleanups and better documentation.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/m68k/mac/via.c | 79 +++++++++++++++++++++-------------------------------
+ 1 file changed, 32 insertions(+), 47 deletions(-)
+
+--- a/arch/m68k/mac/via.c
++++ b/arch/m68k/mac/via.c
+@@ -37,10 +37,6 @@
+ #include <asm/mac_psc.h>
+
+ volatile __u8 *via1, *via2;
+-#if 0
+-/* See note in mac_via.h about how this is possibly not useful */
+-volatile long *via_memory_bogon=(long *)&via_memory_bogon;
+-#endif
+ int rbv_present;
+ int via_alt_mapping;
+ EXPORT_SYMBOL(via_alt_mapping);
+@@ -66,7 +62,7 @@ static int gIER,gIFR,gBufA,gBufB;
+ #define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF)
+ #define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8)
+
+-/* To disable a NuBus slot on Quadras we make the slot IRQ lines outputs, set
++/* To disable a NuBus slot on Quadras we make that slot IRQ line an output set
+ * high. On RBV we just use the slot interrupt enable register. On Macs with
+ * genuine VIA chips we must use nubus_disabled to keep track of disabled slot
+ * interrupts. When any slot IRQ is disabled we mask the (edge triggered) CA1
+@@ -180,7 +176,7 @@ void __init via_init(void)
+ via1[vT1CH] = 0;
+ via1[vT2CL] = 0;
+ via1[vT2CH] = 0;
+- via1[vACR] &= 0x3F;
++ via1[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */
+ via1[vACR] &= ~0x03; /* disable port A & B latches */
+
+ /*
+@@ -203,40 +199,41 @@ void __init via_init(void)
+
+ /* Everything below this point is VIA2/RBV only... */
+
+- if (oss_present) return;
++ if (oss_present)
++ return;
+
+-#if 1
+ /* Some machines support an alternate IRQ mapping that spreads */
+ /* Ethernet and Sound out to their own autolevel IRQs and moves */
+ /* VIA1 to level 6. A/UX uses this mapping and we do too. Note */
+ /* that the IIfx emulates this alternate mapping using the OSS. */
+
+- switch(macintosh_config->ident) {
+- case MAC_MODEL_P475:
+- case MAC_MODEL_P475F:
+- case MAC_MODEL_P575:
+- case MAC_MODEL_Q605:
+- case MAC_MODEL_Q605_ACC:
+- case MAC_MODEL_C610:
+- case MAC_MODEL_Q610:
+- case MAC_MODEL_Q630:
+- case MAC_MODEL_C650:
+- case MAC_MODEL_Q650:
+- case MAC_MODEL_Q700:
+- case MAC_MODEL_Q800:
+- case MAC_MODEL_Q900:
+- case MAC_MODEL_Q950:
++ via_alt_mapping = 0;
++ if (macintosh_config->via_type == MAC_VIA_QUADRA)
++ switch (macintosh_config->ident) {
++ case MAC_MODEL_C660:
++ case MAC_MODEL_Q840:
++ /* not applicable */
++ break;
++ case MAC_MODEL_P588:
++ case MAC_MODEL_TV:
++ case MAC_MODEL_PB140:
++ case MAC_MODEL_PB145:
++ case MAC_MODEL_PB160:
++ case MAC_MODEL_PB165:
++ case MAC_MODEL_PB165C:
++ case MAC_MODEL_PB170:
++ case MAC_MODEL_PB180:
++ case MAC_MODEL_PB180C:
++ case MAC_MODEL_PB190:
++ case MAC_MODEL_PB520:
++ /* not yet tested */
++ break;
++ default:
+ via_alt_mapping = 1;
+ via1[vDirB] |= 0x40;
+ via1[vBufB] &= ~0x40;
+ break;
+- default:
+- via_alt_mapping = 0;
+- break;
+- }
+-#else
+- via_alt_mapping = 0;
+-#endif
++ }
+
+ /*
+ * Now initialize VIA2. For RBV we just kill all interrupts;
+@@ -252,14 +249,17 @@ void __init via_init(void)
+ via2[vT1CH] = 0;
+ via2[vT2CL] = 0;
+ via2[vT2CH] = 0;
+- via2[vACR] &= 0x3F;
++ via2[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */
+ via2[vACR] &= ~0x03; /* disable port A & B latches */
+ }
+
+ /*
+- * Set vPCR for SCSI interrupts (but not on RBV)
++ * Set vPCR for control line interrupts (but not on RBV)
+ */
+ if (!rbv_present) {
++ /* For all VIA types, CA1 (SLOTS IRQ) and CB1 (ASC IRQ)
++ * are made negative edge triggered here.
++ */
+ if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
+ /* CB2 (IRQ) indep. input, positive edge */
+ /* CA2 (DRQ) indep. input, positive edge */
+@@ -466,21 +466,6 @@ irqreturn_t via1_irq(int irq, void *dev_
+ ++irq_num;
+ irq_bit <<= 1;
+ } while (events >= irq_bit);
+-
+-#if 0 /* freakin' pmu is doing weird stuff */
+- if (!oss_present) {
+- /* This (still) seems to be necessary to get IDE
+- working. However, if you enable VBL interrupts,
+- you're screwed... */
+- /* FIXME: should we check the SLOTIRQ bit before
+- pulling this stunt? */
+- /* No, it won't be set. that's why we're doing this. */
+- via_irq_disable(IRQ_MAC_NUBUS);
+- via_irq_clear(IRQ_MAC_NUBUS);
+- m68k_handle_int(IRQ_MAC_NUBUS);
+- via_irq_enable(IRQ_MAC_NUBUS);
+- }
+-#endif
+ return IRQ_HANDLED;
+ }
+
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/parisc-__kernel_time_t-is-always-long.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/parisc-__kernel_time_t-is-always-long.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,29 @@
+[PATCH] parisc: __kernel_time_t is always long
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+__kernel_time_t is always long on PA-RISC, irrespective of CONFIG_64BIT,
+hence move it out of the #ifdef CONFIG_64BIT / #else / #endif block.
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ arch/parisc/include/asm/posix_types.h | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/arch/parisc/include/asm/posix_types.h
++++ b/arch/parisc/include/asm/posix_types.h
+@@ -24,13 +24,12 @@ typedef int __kernel_daddr_t;
+ typedef unsigned long __kernel_size_t;
+ typedef long __kernel_ssize_t;
+ typedef long __kernel_ptrdiff_t;
+-typedef long __kernel_time_t;
+ #else
+ typedef unsigned int __kernel_size_t;
+ typedef int __kernel_ssize_t;
+ typedef int __kernel_ptrdiff_t;
+-typedef long __kernel_time_t;
+ #endif
++typedef long __kernel_time_t;
+ typedef char * __kernel_caddr_t;
+
+ typedef unsigned short __kernel_uid16_t;
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/revert-7557bc66be629d19a402e752673708bfbb8b5e86.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/revert-7557bc66be629d19a402e752673708bfbb8b5e86.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,72 @@
+Subject: [PATCH] Revert "msdos fs: remove unsettable atari option"
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Revert commit 7557bc66be629d19a402e752673708bfbb8b5e86 ("msdos fs: remove
+unsettable atari option")
+---
+ fs/fat/fat.h | 1 +
+ fs/fat/namei_msdos.c | 18 ++++++++++++------
+ 2 files changed, 13 insertions(+), 6 deletions(-)
+
+--- a/fs/fat/fat.h
++++ b/fs/fat/fat.h
+@@ -35,6 +35,7 @@ struct fat_mount_options {
+ utf8:1, /* Use of UTF-8 character set (Default) */
+ unicode_xlate:1, /* create escape sequences for unhandled Unicode */
+ numtail:1, /* Does first alias have a numeric '~1' type tail? */
++ atari:1, /* Use Atari GEMDOS variation of MS-DOS fs */
+ flush:1, /* write things quickly */
+ nocase:1, /* Does this need case conversion? 0=need case conversion*/
+ usefree:1, /* Use free_clusters for FAT32 */
+--- a/fs/fat/namei_msdos.c
++++ b/fs/fat/namei_msdos.c
+@@ -14,7 +14,12 @@
+
+ /* Characters that are undesirable in an MS-DOS file name */
+ static unsigned char bad_chars[] = "*?<>|\"";
+-static unsigned char bad_if_strict[] = "+=,; ";
++static unsigned char bad_if_strict_pc[] = "+=,; ";
++/* GEMDOS is less restrictive */
++static unsigned char bad_if_strict_atari[] = " ";
++
++#define bad_if_strict(opts) \
++ ((opts)->atari ? bad_if_strict_atari : bad_if_strict_pc)
+
+ /***** Formats an MS-DOS file name. Rejects invalid names. */
+ static int msdos_format_name(const unsigned char *name, int len,
+@@ -35,20 +40,21 @@ static int msdos_format_name(const unsig
+ /* Get rid of dot - test for it elsewhere */
+ name++;
+ len--;
+- } else
++ } else if (!opts->atari)
+ return -EINVAL;
+ }
+ /*
+- * disallow names that _really_ start with a dot
++ * disallow names that _really_ start with a dot for MS-DOS,
++ * GEMDOS does not care
+ */
+- space = 1;
++ space = !opts->atari;
+ c = 0;
+ for (walk = res; len && walk - res < 8; walk++) {
+ c = *name++;
+ len--;
+ if (opts->name_check != 'r' && strchr(bad_chars, c))
+ return -EINVAL;
+- if (opts->name_check == 's' && strchr(bad_if_strict, c))
++ if (opts->name_check == 's' && strchr(bad_if_strict(opts), c))
+ return -EINVAL;
+ if (c >= 'A' && c <= 'Z' && opts->name_check == 's')
+ return -EINVAL;
+@@ -88,7 +94,7 @@ static int msdos_format_name(const unsig
+ if (opts->name_check != 'r' && strchr(bad_chars, c))
+ return -EINVAL;
+ if (opts->name_check == 's' &&
+- strchr(bad_if_strict, c))
++ strchr(bad_if_strict(opts), c))
+ return -EINVAL;
+ if (c < ' ' || c == ':' || c == '\\')
+ return -EINVAL;
Added: dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/zorro-module-device-table.diff
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/m68k/2.6.28/zorro-module-device-table.diff Mon Mar 2 21:29:17 2009
@@ -0,0 +1,240 @@
+Subject: [PATCH] Add Amiga Zorro bus modalias support
+
+From: Geert Uytterhoeven <geert at linux-m68k.org>
+
+Add Amiga Zorro bus modalias and uevent support
+
+Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
+---
+ drivers/net/a2065.c | 1 +
+ drivers/net/ariadne.c | 1 +
+ drivers/net/hydra.c | 1 +
+ drivers/net/zorro8390.c | 1 +
+ drivers/scsi/zorro7xx.c | 1 +
+ drivers/video/cirrusfb.c | 1 +
+ drivers/video/fm2fb.c | 1 +
+ drivers/zorro/zorro-driver.c | 24 ++++++++++++++++++++++++
+ drivers/zorro/zorro-sysfs.c | 11 +++++++++++
+ include/linux/mod_devicetable.h | 10 ++++++++++
+ include/linux/zorro.h | 13 +------------
+ scripts/mod/file2alias.c | 15 +++++++++++++++
+ 12 files changed, 68 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/a2065.c
++++ b/drivers/net/a2065.c
+@@ -694,6 +694,7 @@ static struct zorro_device_id a2065_zorr
+ { ZORRO_PROD_AMERISTAR_A2065 },
+ { 0 }
+ };
++MODULE_DEVICE_TABLE(zorro, a2065_zorro_tbl);
+
+ static struct zorro_driver a2065_driver = {
+ .name = "a2065",
+--- a/drivers/net/ariadne.c
++++ b/drivers/net/ariadne.c
+@@ -147,6 +147,7 @@ static struct zorro_device_id ariadne_zo
+ { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
+ { 0 }
+ };
++MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);
+
+ static struct zorro_driver ariadne_driver = {
+ .name = "ariadne",
+--- a/drivers/net/hydra.c
++++ b/drivers/net/hydra.c
+@@ -72,6 +72,7 @@ static struct zorro_device_id hydra_zorr
+ { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
+ { 0 }
+ };
++MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl);
+
+ static struct zorro_driver hydra_driver = {
+ .name = "hydra",
+--- a/drivers/net/zorro8390.c
++++ b/drivers/net/zorro8390.c
+@@ -102,6 +102,7 @@ static struct zorro_device_id zorro8390_
+ { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
+ { 0 }
+ };
++MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);
+
+ static struct zorro_driver zorro8390_driver = {
+ .name = "zorro8390",
+--- a/drivers/scsi/zorro7xx.c
++++ b/drivers/scsi/zorro7xx.c
+@@ -68,6 +68,7 @@ static struct zorro_device_id zorro7xx_z
+ },
+ { 0 }
+ };
++MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl);
+
+ static int __devinit zorro7xx_init_one(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
+--- a/drivers/video/cirrusfb.c
++++ b/drivers/video/cirrusfb.c
+@@ -298,6 +298,7 @@ static const struct zorro_device_id cirr
+ },
+ { 0 }
+ };
++MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
+
+ static const struct {
+ zorro_id id2;
+--- a/drivers/video/fm2fb.c
++++ b/drivers/video/fm2fb.c
+@@ -219,6 +219,7 @@ static struct zorro_device_id fm2fb_devi
+ { ZORRO_PROD_HELFRICH_RAINBOW_II },
+ { 0 }
+ };
++MODULE_DEVICE_TABLE(zorro, fm2fb_devices);
+
+ static struct zorro_driver fm2fb_driver = {
+ .name = "fm2fb",
+--- a/drivers/zorro/zorro-driver.c
++++ b/drivers/zorro/zorro-driver.c
+@@ -137,10 +137,34 @@ static int zorro_bus_match(struct device
+ return 0;
+ }
+
++static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++#ifdef CONFIG_HOTPLUG
++ struct zorro_dev *z;
++
++ if (!dev)
++ return -ENODEV;
++
++ z = to_zorro_dev(dev);
++ if (!z)
++ return -ENODEV;
++
++ if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) ||
++ add_uevent_var(env, "ZORRO_SLOT_NAME=%s", z->dev.bus_id) ||
++ add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) ||
++ add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id))
++ return -ENOMEM;
++
++ return 0;
++#else /* !CONFIG_HOTPLUG */
++ return -ENODEV;
++#endif /* !CONFIG_HOTPLUG */
++}
+
+ struct bus_type zorro_bus_type = {
+ .name = "zorro",
+ .match = zorro_bus_match,
++ .uevent = zorro_uevent,
+ .probe = zorro_device_probe,
+ .remove = zorro_device_remove,
+ };
+--- a/drivers/zorro/zorro-sysfs.c
++++ b/drivers/zorro/zorro-sysfs.c
+@@ -77,6 +77,16 @@ static struct bin_attribute zorro_config
+ .read = zorro_read_config,
+ };
+
++static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct zorro_dev *z = to_zorro_dev(dev);
++
++ return sprintf(buf, ZORRO_DEVICE_MODALIAS_FMT "\n", z->id);
++}
++
++static DEVICE_ATTR(modalias, S_IRUGO, modalias_show, NULL);
++
+ void zorro_create_sysfs_dev_files(struct zorro_dev *z)
+ {
+ struct device *dev = &z->dev;
+@@ -88,6 +98,7 @@ void zorro_create_sysfs_dev_files(struct
+ device_create_file(dev, &dev_attr_slotaddr);
+ device_create_file(dev, &dev_attr_slotsize);
+ device_create_file(dev, &dev_attr_resource);
++ device_create_file(dev, &dev_attr_modalias);
+ sysfs_create_bin_file(&dev->kobj, &zorro_config_attr);
+ }
+
+--- a/include/linux/mod_devicetable.h
++++ b/include/linux/mod_devicetable.h
+@@ -447,4 +447,14 @@ struct dmi_system_id {
+
+ #define DMI_MATCH(a, b) { a, b }
+
++struct zorro_device_id {
++ __u32 id; /* Device ID or ZORRO_WILDCARD */
++ kernel_ulong_t driver_data; /* Data private to the driver */
++};
++
++#define ZORRO_WILDCARD (0xffffffff) /* not official */
++
++#define ZORRO_DEVICE_MODALIAS_FMT "zorro:i%08X"
++
++
+ #endif /* LINUX_MOD_DEVICETABLE_H */
+--- a/include/linux/zorro.h
++++ b/include/linux/zorro.h
+@@ -38,8 +38,6 @@
+ typedef __u32 zorro_id;
+
+
+-#define ZORRO_WILDCARD (0xffffffff) /* not official */
+-
+ /* Include the ID list */
+ #include <linux/zorro_ids.h>
+
+@@ -116,6 +114,7 @@ struct ConfigDev {
+
+ #include <linux/init.h>
+ #include <linux/ioport.h>
++#include <linux/mod_devicetable.h>
+
+ #include <asm/zorro.h>
+
+@@ -155,16 +154,6 @@ extern struct bus_type zorro_bus_type;
+
+
+ /*
+- * Zorro device IDs
+- */
+-
+-struct zorro_device_id {
+- zorro_id id; /* Device ID or ZORRO_WILDCARD */
+- unsigned long driver_data; /* Data private to the driver */
+-};
+-
+-
+- /*
+ * Zorro device drivers
+ */
+
+--- a/scripts/mod/file2alias.c
++++ b/scripts/mod/file2alias.c
+@@ -696,6 +696,17 @@ static int do_dmi_entry(const char *file
+ strcat(alias, ":");
+ return 1;
+ }
++
++/* Looks like: zorro:iN. */
++static int do_zorro_entry(const char *filename, struct zorro_device_id *id,
++ char *alias)
++{
++ id->id = TO_NATIVE(id->id);
++ strcpy(alias, "zorro:");
++ ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id);
++ return 1;
++}
++
+ /* Ignore any prefix, eg. some architectures prepend _ */
+ static inline int sym_is(const char *symbol, const char *name)
+ {
+@@ -835,6 +846,10 @@ void handle_moddevtable(struct module *m
+ do_table(symval, sym->st_size,
+ sizeof(struct dmi_system_id), "dmi",
+ do_dmi_entry, mod);
++ else if (sym_is(symname, "__mod_zorro_device_table"))
++ do_table(symval, sym->st_size,
++ sizeof(struct zorro_device_id), "zorro",
++ do_zorro_entry, mod);
+ free(zeros);
+ }
+
Modified: dists/sid/linux-2.6/debian/patches/series/2
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/2 (original)
+++ dists/sid/linux-2.6/debian/patches/series/2 Mon Mar 2 21:29:17 2009
@@ -1 +1,142 @@
+ bugfix/all/stable/2.6.28.7.patch
+
+# m68k patches
+# updated 2009/03/12 srm notes based on
+# http://www.kernel.org/pub/linux/kernel/people/geert/linux-m68k-patches-2.6/series
+
+# Source: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+# BASE 9bf1a2445f3c569098b8de7097ca324e65abecc2
+
+# NEXT_PATCHES_START
+
+# --- submitted ---
+#srm: failed to apply
+#+ bugfix/m68k/2.6.28/mac-macfb-do-not-overflow-fix-id.diff arch=m68k
+
+# --- for 2.6.28 ---
+
+# --- for 2.6.29 ---
++ bugfix/m68k/2.6.28/mac-reinstate-rtc.diff arch=m68k
++ bugfix/m68k/2.6.28/mac-via-cleanup-and-commentry.diff arch=m68k
++ bugfix/m68k/2.6.28/mac-machw_h_cleanup.diff arch=m68k
++ bugfix/m68k/2.6.28/mac-baboon-interrupt-enable-disable.diff arch=m68k
++ bugfix/m68k/2.6.28/mac-macfb-annotations-and-compiler-warning-fix.diff arch=m68k
++ bugfix/m68k/2.6.28/m68k-fpsp040-fix-trigraph-ignored-warning.diff arch=m68k
++ bugfix/m68k/2.6.28/fbcon-remove-broken-mac-vbl-handler.diff arch=m68k
++ bugfix/m68k/2.6.28/fbcon-protect-free-irq-by-MACH_IS_ATARI-check.diff arch=m68k
++ bugfix/m68k/2.6.28/m68k-use-the-new-byteorder-headers.diff arch=m68k
+
+# --- for 2.6.29 via scsi-misc ---
++ bugfix/m68k/2.6.28/mac-mac_esp-asm-fix.diff arch=m68k
++ bugfix/m68k/2.6.28/mac-esp-fix-for-quadras-with-two-esp-chips.diff arch=m68k
+
+# NEXT_PATCHES_END
+
+# --- pending ---
++ bugfix/m68k/2.6.28/m68k-replace-linux-68k-by-linux-m68k.diff arch=m68k
+
+# Atari SCC support
++ bugfix/m68k/2.6.28/atari-scc-readd-atari_SCC_init_done.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-scc-readd-CONFIG_ATARI_SCC.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-scc.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-scc-checkpatch.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-scc-gs-fix.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-scc-break_ctl.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-scc-no-serial-console-if-modular.diff arch=m68k
+
+#NCR5380-struct-scsi_cmnd.diff arch=m68k
+#NCR53C9x-struct-scsi_cmnd.diff arch=m68k
+#amiga-blz1230-struct-scsi_cmnd.diff arch=m68k
+#amiga-blz2060-struct-scsi_cmnd.diff arch=m68k
+#amiga-cyberstorm-struct-scsi_cmnd.diff arch=m68k
+#amiga-cyberstormII-struct-scsi_cmnd.diff arch=m68k
+#amiga-fastlane-struct-scsi_cmnd.diff arch=m68k
+#amiga-oktagon_esp-struct-scsi_cmnd.diff arch=m68k
+#atari_scsi-struct-scsi_cmnd.diff arch=m68k
+#mac_esp-struct-scsi_cmnd.diff arch=m68k
+#sun3x_esp-struct-scsi_cmnd.diff arch=m68k
+
+#POSTPONED/130-adbraw.diff arch=m68k
+#POSTPONED/143-ioext.diff arch=m68k
+#POSTPONED/149-mc68681.diff arch=m68k
+#POSTPONED/478-serial.diff arch=m68k
+
+# NEVER to be applied outside m68k space!
+#m68k-PRIVATE-m68k-changes.diff arch=m68k
+
+# Atari FAT
++ bugfix/m68k/2.6.28/revert-7557bc66be629d19a402e752673708bfbb8b5e86.diff arch=m68k
+#POSTPONED/134-atari-fat.diff arch=m68k
+
+
+# Atari EtherNEC
++ bugfix/m68k/2.6.28/atari-rom-isa.diff arch=m68k # FIXME missing 32-bit I/O
++ bugfix/m68k/2.6.28/atari-io-fixes.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-ethernec.diff arch=m68k # FIXME rewrite for lib8390?
++ bugfix/m68k/2.6.28/atari-ethernec-fixes.diff arch=m68k
+
+# Atari ARAnyM
++ bugfix/m68k/2.6.28/atari-aranym.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-aranym-export-nf-api.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-aranym-block-and-console-access.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-aranym-nfcon-no-early_param-if-modular.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-aranym-nf-wrappers.diff arch=m68k
+
+# Atari EtherNAT
++ bugfix/m68k/2.6.28/atari-ethernat.diff arch=m68k
+#atari-ethernat-old.diff arch=m68k
+#atari-ethernat-old-is-broken.diff arch=m68k
+#atari-ethernat-add-writew_be.diff arch=m68k
+#atari-ethernat-is-broken.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-ethernat-fixes.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-ethernat-warning-fix.diff arch=m68k
+
+#obsolete/sun3-3x-cg3-bw2.diff arch=m68k # FIXME rewrite for removal of struct all_info
+#obsolete/sun3-3x-serial.diff arch=m68k # FIXME rewrite for common drivers/of/
+
+#falconide_intr_lock-reentrant.diff arch=m68k # FIXME Reverted
+#falconide_intr_lock-ratelimit.diff arch=m68k # FIXME Obsolete
+#srm: failed to apply
+#+ bugfix/m68k/2.6.28/falconide-fix-ide_release_lock-imbalance.diff arch=m68k
+
++ bugfix/m68k/2.6.28/amiga-debug=mem.diff arch=m68k
++ bugfix/m68k/2.6.28/m68k-scsi-HOST_C-cleanup.diff arch=m68k
+
+# Device model
++ bugfix/m68k/2.6.28/zorro-module-device-table.diff arch=m68k
++ bugfix/m68k/2.6.28/amiga-platform-device.diff arch=m68k
++ bugfix/m68k/2.6.28/atari-platform-device.diff arch=m68k
++ bugfix/m68k/2.6.28/mac-platform-device.diff arch=m68k
+#cross-mod_devicetable.diff arch=m68k
+#m68k-esp-scsi-blz2060.diff arch=m68k
+
+
++ bugfix/m68k/2.6.28/m68k-noswap-linux-swap-h-needs-linux-pagemap-h.diff arch=m68k
++ bugfix/m68k/2.6.28/m68k-allow-all-kernel-traps-to-be-handled-via-exception-fixups-all.diff arch=m68k
+#m68k-allow-all-kernel-traps-to-be-handled-via-exception-fixups.diff arch=m68k
+#m68k-cleanup-patch.diff arch=m68k
+#m68k-reinstate-VEC_TRACE-check-for-68020-30.diff arch=m68k
+#m68k-no-need-to-set-TIF_DELAYED_TRACE.diff arch=m68k
+
+# To be handled by m68knommu, as they include asm-m68k files
+#m68k-move-includes-to-arch-m68k-include.diff arch=m68k
+
+#srm: failed to apply
+#+ bugfix/m68k/2.6.28/parisc-__kernel_time_t-is-always-long.diff arch=m68k
+
+#m68k-add-irqs_disabled_flags.diff arch=m68k
++ bugfix/m68k/2.6.28/m68k-add-install-target.diff arch=m68k
+
+# MAC SWIM
++ bugfix/m68k/2.6.28/mac-add-floppy-model-entry.diff arch=m68k
++ bugfix/m68k/2.6.28/mac-add-SWIM-floppy-support.diff arch=m68k
+
+# Atari atafb
++ bugfix/m68k/2.6.28/atafb-c2p.diff arch=m68k
++ bugfix/m68k/2.6.28/atafb-line_length.diff arch=m68k
++ bugfix/m68k/2.6.28/atafb-cfb16.diff arch=m68k
++ bugfix/m68k/2.6.28/atafb-panning.diff arch=m68k
+
+# defconfig updates!
+#srm: failed to apply
+#+ bugfix/m68k/2.6.28/m68k-update-defconfig-latest.diff arch=m68k
More information about the Kernel-svn-changes
mailing list