summaryrefslogtreecommitdiffstats
path: root/arch/m68k
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
commitc7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch)
tree3682407a599b8f9f03fc096298134cafba1c9b2f /arch/m68k
parent1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff)
o Merge with Linux 2.1.116.
o New Newport console code. o New G364 console code.
Diffstat (limited to 'arch/m68k')
-rw-r--r--arch/m68k/Makefile12
-rw-r--r--arch/m68k/amiga/Makefile6
-rw-r--r--arch/m68k/amiga/amiga_ksyms.c15
-rw-r--r--arch/m68k/amiga/amiints.c5
-rw-r--r--arch/m68k/amiga/config.c33
-rw-r--r--arch/m68k/amiga/pcmcia.c112
-rw-r--r--arch/m68k/amiga/zorro.c1234
-rw-r--r--arch/m68k/apollo/config.c5
-rw-r--r--arch/m68k/atari/ataints.c2
-rw-r--r--arch/m68k/atari/atakeyb.c28
-rw-r--r--arch/m68k/atari/atasound.c123
-rw-r--r--arch/m68k/atari/config.c77
-rw-r--r--arch/m68k/atari/joystick.c1
-rw-r--r--arch/m68k/atari/stram.c19
-rw-r--r--arch/m68k/atari/time.c2
-rw-r--r--arch/m68k/bvme6000/Makefile14
-rw-r--r--arch/m68k/bvme6000/bvmeints.c154
-rw-r--r--arch/m68k/bvme6000/config.c453
-rw-r--r--arch/m68k/bvme6000/rtc.c175
-rw-r--r--arch/m68k/config.in193
-rw-r--r--arch/m68k/defconfig9
-rw-r--r--arch/m68k/fpsp040/res_func.S2
-rw-r--r--arch/m68k/fpsp040/skeleton.S10
-rw-r--r--arch/m68k/fpsp040/slogn.S2
-rw-r--r--arch/m68k/fpsp040/ssin.S2
-rw-r--r--arch/m68k/fpsp040/stan.S2
-rw-r--r--arch/m68k/fpsp040/sto_res.S2
-rw-r--r--arch/m68k/hp300/Makefile13
-rw-r--r--arch/m68k/hp300/README.hp30014
-rw-r--r--arch/m68k/hp300/config.c78
-rw-r--r--arch/m68k/hp300/hil.c250
-rw-r--r--arch/m68k/hp300/ints.c47
-rw-r--r--arch/m68k/hp300/ints.h6
-rw-r--r--arch/m68k/hp300/ksyms.c9
-rw-r--r--arch/m68k/hp300/reboot.S35
-rw-r--r--arch/m68k/hp300/time.c62
-rw-r--r--arch/m68k/hp300/time.h4
-rw-r--r--arch/m68k/ifpsp060/iskeleton.S10
-rw-r--r--arch/m68k/kernel/bios32.c50
-rw-r--r--arch/m68k/kernel/entry.S10
-rw-r--r--arch/m68k/kernel/head.S199
-rw-r--r--arch/m68k/kernel/ints.c3
-rw-r--r--arch/m68k/kernel/kgdb.c1194
-rw-r--r--arch/m68k/kernel/m68k_defs.h8
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c8
-rw-r--r--arch/m68k/kernel/process.c3
-rw-r--r--arch/m68k/kernel/ptrace.c7
-rw-r--r--arch/m68k/kernel/setup.c14
-rw-r--r--arch/m68k/kernel/signal.c400
-rw-r--r--arch/m68k/kernel/sys_m68k.c13
-rw-r--r--arch/m68k/kernel/time.c2
-rw-r--r--arch/m68k/mac/Makefile3
-rw-r--r--arch/m68k/mac/adb-bus.c831
-rw-r--r--arch/m68k/mac/config.c308
-rw-r--r--arch/m68k/mac/debug.c234
-rw-r--r--arch/m68k/mac/mac_ksyms.c (renamed from arch/m68k/mac/ksyms.c)0
-rw-r--r--arch/m68k/mac/macints.c777
-rw-r--r--arch/m68k/mac/mackeyb.c64
-rw-r--r--arch/m68k/mac/psc.h18
-rw-r--r--arch/m68k/mac/via6522.c442
-rw-r--r--arch/m68k/mm/Makefile2
-rw-r--r--arch/m68k/mm/fault.c7
-rw-r--r--arch/m68k/mm/hwtest.c81
-rw-r--r--arch/m68k/mm/init.c19
-rw-r--r--arch/m68k/mm/kmap.c4
-rw-r--r--arch/m68k/mm/memory.c215
-rw-r--r--arch/m68k/mvme16x/16xints.c2
-rw-r--r--arch/m68k/mvme16x/Makefile2
-rw-r--r--arch/m68k/mvme16x/config.c139
-rw-r--r--arch/m68k/mvme16x/rtc.c166
70 files changed, 5713 insertions, 2732 deletions
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index 255a29a7b..9cd2d1838 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -64,6 +64,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/mac/mac.o
SUBDIRS := $(SUBDIRS) arch/m68k/mac
endif
+ifdef CONFIG_HP300
+CORE_FILES := $(CORE_FILES) arch/m68k/hp300/hp300.o
+SUBDIRS := $(SUBDIRS) arch/m68k/hp300
+endif
+
ifdef CONFIG_APOLLO
CORE_FILES := $(CORE_FILES) arch/m68k/apollo/apollo.o
SUBDIRS := $(SUBDIRS) arch/m68k/apollo
@@ -74,6 +79,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/mvme16x/mvme16x.o
SUBDIRS := $(SUBDIRS) arch/m68k/mvme16x
endif
+ifdef CONFIG_BVME6000
+CORE_FILES := $(CORE_FILES) arch/m68k/bvme6000/bvme6000.o
+SUBDIRS := $(SUBDIRS) arch/m68k/bvme6000
+endif
+
ifdef CONFIG_M68040
CORE_FILES := $(CORE_FILES) arch/m68k/fpsp040/fpsp.o
SUBDIRS := $(SUBDIRS) arch/m68k/fpsp040
@@ -107,4 +117,6 @@ endif
archclean:
rm -f vmlinux.gz
+archmrproper:
+
archdep:
diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile
index 91c835d54..b0211f3a7 100644
--- a/arch/m68k/amiga/Makefile
+++ b/arch/m68k/amiga/Makefile
@@ -8,7 +8,11 @@
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := amiga.o
-O_OBJS := config.o amiints.o cia.o chipram.o amisound.o zorro.o
+O_OBJS := config.o amiints.o cia.o chipram.o amisound.o
OX_OBJS := amiga_ksyms.o
+ifdef CONFIG_AMIGA_PCMCIA
+O_OBJS := $(O_OBJS) pcmcia.o
+endif
+
include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c
index 2b9c131d7..4de6e4167 100644
--- a/arch/m68k/amiga/amiga_ksyms.c
+++ b/arch/m68k/amiga/amiga_ksyms.c
@@ -1,7 +1,9 @@
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/zorro.h>
#include <asm/amigahw.h>
+#include <asm/amipcmcia.h>
extern volatile u_short amiga_audio_min_period;
extern u_short amiga_audio_period;
@@ -20,8 +22,11 @@ EXPORT_SYMBOL(amiga_chip_size);
EXPORT_SYMBOL(amiga_audio_period);
EXPORT_SYMBOL(amiga_audio_min_period);
-EXPORT_SYMBOL(zorro_find);
-EXPORT_SYMBOL(zorro_get_board);
-EXPORT_SYMBOL(zorro_config_board);
-EXPORT_SYMBOL(zorro_unconfig_board);
-EXPORT_SYMBOL(zorro_unused_z2ram);
+#ifdef CONFIG_AMIGA_PCMCIA
+ EXPORT_SYMBOL(pcmcia_reset);
+ EXPORT_SYMBOL(pcmcia_copy_tuple);
+ EXPORT_SYMBOL(pcmcia_program_voltage);
+ EXPORT_SYMBOL(pcmcia_access_speed);
+ EXPORT_SYMBOL(pcmcia_write_enable);
+ EXPORT_SYMBOL(pcmcia_write_disable);
+#endif
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
index b7110188c..9aa47cf7c 100644
--- a/arch/m68k/amiga/amiints.c
+++ b/arch/m68k/amiga/amiints.c
@@ -32,6 +32,7 @@
#include <asm/traps.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
+#include <asm/amipcmcia.h>
extern int cia_request_irq(struct ciabase *base,int irq,
void (*handler)(int, void *, struct pt_regs *),
@@ -89,6 +90,10 @@ __initfunc(void amiga_init_IRQ(void))
for (i = 0; i < AMI_IRQS; i++)
ami_ablecount[i] = 0;
+ /* turn off PCMCIA interrupts */
+ if (AMIGAHW_PRESENT(PCMCIA))
+ pcmcia_disable_irq();
+
/* turn off all interrupts and enable the master interrupt bit */
custom.intena = 0x7fff;
custom.intreq = 0x7fff;
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index ce52ad852..3c5dff56d 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -51,6 +51,7 @@ static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *));
/* amiga specific keyboard functions */
extern int amiga_keyb_init(void);
extern int amiga_kbdrate (struct kbd_repeat *);
+extern void amiga_kbd_reset_setup(char*, int);
/* amiga specific irq functions */
extern void amiga_init_IRQ (void);
extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
@@ -76,8 +77,6 @@ extern void amiga_floppy_setup(char *, int *);
#endif
static void amiga_reset (void);
static int amiga_wait_key (struct console *co);
-extern struct consw fb_con;
-extern void zorro_init(void);
extern void amiga_init_sound(void);
static void amiga_savekmsg_init(void);
static void amiga_mem_console_write(struct console *co, const char *b,
@@ -343,6 +342,7 @@ __initfunc(void config_amiga(void))
mach_sched_init = amiga_sched_init;
mach_keyb_init = amiga_keyb_init;
mach_kbdrate = amiga_kbdrate;
+ kbd_reset_setup = amiga_kbd_reset_setup;
mach_init_IRQ = amiga_init_IRQ;
mach_default_handler = &amiga_default_handler;
mach_request_irq = amiga_request_irq;
@@ -376,7 +376,7 @@ __initfunc(void config_amiga(void))
mach_floppy_setup = amiga_floppy_setup;
#endif
mach_reset = amiga_reset;
- conswitchp = &fb_con;
+ conswitchp = &dummy_con;
kd_mksound = amiga_mksound;
#ifdef CONFIG_MAGIC_SYSRQ
mach_sysrq_key = 0x5f; /* HELP */
@@ -397,27 +397,6 @@ __initfunc(void config_amiga(void))
/* ensure that the DMA master bit is set */
custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
- /* don't use Z2 RAM as system memory on Z3 capable machines */
- if (AMIGAHW_PRESENT(ZORRO3)) {
- int i, j;
- unsigned long z2mem = 0;
- for (i = 0; i < m68k_num_memory; i++)
- if (m68k_memory[i].addr < 16*1024*1024) {
- if (i == 0) {
- /* don't cut off the branch we're sitting on */
- printk("Warning: kernel runs in Zorro II memory\n");
- continue;
- }
- z2mem += m68k_memory[i].size;
- m68k_num_memory--;
- for (j = i; j < m68k_num_memory; j++)
- m68k_memory[j] = m68k_memory[j+1];
- }
- if (z2mem)
- printk("%ldK of Zorro II memory will not be used as system memory\n",
- z2mem>>10);
- }
-
/* initialize chipram allocator */
amiga_chip_init ();
@@ -443,12 +422,8 @@ __initfunc(void config_amiga(void))
if (AMIGAHW_PRESENT(MAGIC_REKICK))
*(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
- zorro_init();
#ifdef CONFIG_ZORRO
- /*
- * Identify all known AutoConfig Expansion Devices
- */
- zorro_identify();
+ zorro_init();
#endif
}
diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c
new file mode 100644
index 000000000..3faac7eda
--- /dev/null
+++ b/arch/m68k/amiga/pcmcia.c
@@ -0,0 +1,112 @@
+/*
+** asm-m68k/pcmcia.c -- Amiga Linux PCMCIA support
+** most information was found by disassembling card.resource
+** I'm still looking for an official doc !
+**
+** Copyright 1997 by Alain Malek
+**
+** 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.
+**
+** Created: 12/10/97 by Alain Malek
+*/
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <asm/amigayle.h>
+#include <asm/amipcmcia.h>
+
+/* gayle config byte for program voltage and access speed */
+static u_char cfg_byte = GAYLE_CFG_0V|GAYLE_CFG_150NS;
+
+void pcmcia_reset(void)
+{
+ unsigned long reset_start_time = jiffies;
+ unsigned char b;
+
+ gayle_reset = 0x00;
+ while (jiffies - reset_start_time < 1*HZ/100);
+ b = gayle_reset;
+}
+
+
+/* copy a tuple, including tuple header. return nb bytes copied */
+/* be carefull as this may trigger a GAYLE_IRQ_WR interrupt ! */
+
+int pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len)
+{
+ unsigned char id, *dest;
+ int cnt, pos, len;
+
+ dest = tuple;
+ pos = 0;
+
+ id = gayle_attribute[pos];
+
+ while((id != CISTPL_END) && (pos < 0x10000)) {
+ len = (int)gayle_attribute[pos+2] + 2;
+ if (id == tuple_id) {
+ len = (len > max_len)?max_len:len;
+ for (cnt = 0; cnt < len; cnt++) {
+ *dest++ = gayle_attribute[pos+(cnt<<1)];
+ }
+
+ return len;
+ }
+ pos += len<<1;
+ id = gayle_attribute[pos];
+ }
+
+ return 0;
+}
+
+void pcmcia_program_voltage(int voltage)
+{
+ u_char v;
+
+ switch (voltage) {
+ case PCMCIA_0V:
+ v = GAYLE_CFG_0V;
+ break;
+ case PCMCIA_5V:
+ v = GAYLE_CFG_5V;
+ break;
+ case PCMCIA_12V:
+ v = GAYLE_CFG_12V;
+ break;
+ default:
+ v = GAYLE_CFG_0V;
+ }
+
+ cfg_byte = (cfg_byte & 0xfc) | v;
+ gayle.config = cfg_byte;
+
+}
+
+void pcmcia_access_speed(int speed)
+{
+ u_char s;
+
+ if (speed <= PCMCIA_SPEED_100NS)
+ s = GAYLE_CFG_100NS;
+ else if (speed <= PCMCIA_SPEED_150NS)
+ s = GAYLE_CFG_150NS;
+ else if (speed <= PCMCIA_SPEED_250NS)
+ s = GAYLE_CFG_250NS;
+ else
+ s = GAYLE_CFG_720NS;
+
+ cfg_byte = (cfg_byte & 0xf3) | s;
+ gayle.config = cfg_byte;
+}
+
+void pcmcia_write_enable(void)
+{
+ gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA;
+}
+
+void pcmcia_write_disable(void)
+{
+ gayle.cardstatus = 0;
+}
diff --git a/arch/m68k/amiga/zorro.c b/arch/m68k/amiga/zorro.c
deleted file mode 100644
index 7f2cd8c47..000000000
--- a/arch/m68k/amiga/zorro.c
+++ /dev/null
@@ -1,1234 +0,0 @@
-/*
- * linux/arch/m68k/amiga/zorro.c
- *
- * Copyright (C) 1995 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/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <asm/setup.h>
-#include <asm/bitops.h>
-#include <asm/amigahw.h>
-#include <linux/zorro.h>
-
-
-#ifdef CONFIG_ZORRO
-
- /*
- * Zorro Expansion Device Manufacturers and Products
- */
-
-struct Manufacturer {
- const char *Name;
- u_short Manuf;
- u_short NumProd;
- const struct Product *Products;
-};
-
-struct Product {
- const char *Name;
- u_char Class;
- u_char Prod;
-};
-
-struct GVP_Product {
- const char *Name;
- u_char Class;
- u_char EPC;
-};
-
-
- /*
- * Macro's to make life easier
- */
-
-#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
-
-#define BEGIN_PROD(id) \
- static struct Product Prod_##id[] = {
-#define PROD(name, class, id) \
- { name, ZORRO_CLASS_##class, ZORRO_PROD(ZORRO_PROD_##id) },
-
-#define BEGIN_GVP_PROD \
- static struct GVP_Product Ext_Prod_GVP[] = {
-#define GVP_PROD(name, class, id) \
- { name, ZORRO_CLASS_##class, ZORRO_EPC(ZORRO_PROD_##id) },
-
-#define BEGIN_MANUF \
- static struct Manufacturer Manufacturers[] = {
-#define MANUF(name, id) \
- { name, ZORRO_MANUF_##id, ARRAYSIZE(Prod_##id), Prod_##id },
-
-#define END \
- };
-
-
- /*
- * Recognized Zorro Expansion Devices
- */
-
-BEGIN_PROD(PACIFIC_PERIPHERALS)
- PROD("SE 2000 A500", HD, PACIFIC_PERIPHERALS_SE_2000_A500)
- PROD(NULL, SCSI, PACIFIC_PERIPHERALS_SCSI)
-END
-
-BEGIN_PROD(MACROSYSTEMS_USA_2)
- PROD("Warp Engine", TURBO_SCSI_RAM, MACROSYSTEMS_WARP_ENGINE)
-END
-
-BEGIN_PROD(KUPKE_1)
- PROD("Golem RAM Box 2MB", RAM, KUPKE_GOLEM_RAM_BOX_2MB)
-END
-
-BEGIN_PROD(MEMPHIS)
- PROD("Stormbringer", TURBO, MEMPHIS_STORMBRINGER)
-END
-
-BEGIN_PROD(3_STATE)
- PROD("Megamix 2000", RAM, 3_STATE_MEGAMIX_2000)
-END
-
-BEGIN_PROD(COMMODORE_BRAUNSCHWEIG)
- PROD("A2088 XT/A2286 AT", BRIDGE, CBM_A2088_A2286)
- PROD("A2286 AT", BRIDGE, CBM_A2286)
- PROD("A4091", SCSI, CBM_A4091_1)
- PROD("A2386-SX", BRIDGE, CBM_A2386SX_1)
-END
-
-BEGIN_PROD(COMMODORE_WEST_CHESTER_1)
- PROD("A2090/A2090A", SCSI, CBM_A2090A)
- PROD("A590/A2091", SCSI, CBM_A590_A2091_1)
- PROD("A590/A2091", SCSI, CBM_A590_A2091_2)
- PROD("A2090B 2090 Autoboot", SCSI, CBM_A2090B)
- PROD("A2060", ARCNET, CBM_A2060)
- PROD("A590/A2052/A2058/A2091", RAM, CBM_A590_A2052_A2058_A2091)
- PROD("A560", RAM, CBM_A560_RAM)
- PROD("A2232 Prototype", MULTIIO, CBM_A2232_PROTOTYPE)
- PROD("A2232", MULTIIO, CBM_A2232)
- PROD("A2620 68020/RAM", TURBO_RAM, CBM_A2620)
- PROD("A2630 68030/RAM", TURBO_RAM, CBM_A2630)
- PROD("A4091", SCSI, CBM_A4091_2)
- PROD("A2065", ETHERNET, CBM_A2065_1)
- PROD("Romulator Card", UNKNOWN, CBM_ROMULATOR)
- PROD("A3000 Test Fixture", MISC, CBM_A3000_TEST_FIXTURE)
- PROD("A2386-SX", BRIDGE, CBM_A2386SX_2)
- PROD("A2065", ETHERNET, CBM_A2065_2)
-END
-
-BEGIN_PROD(COMMODORE_WEST_CHESTER_2)
- PROD("A2090/A2090A Combitec/MacroSystem", SCSI, CBM_A2090A_CM)
-END
-
-BEGIN_PROD(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS_2)
- PROD("EXP8000", RAM, PPS_EXP8000)
-END
-
-BEGIN_PROD(KOLFF_COMPUTER_SUPPLIES)
- PROD("KCS Power PC Board", BRIDGE, KCS_POWER_PC_BOARD)
-END
-
-BEGIN_PROD(CARDCO_1)
- PROD("Kronos 2000", SCSI, CARDCO_KRONOS_2000_1)
- PROD("A1000", SCSI, CARDCO_A1000_1)
- PROD("Escort", SCSI, CARDCO_ESCORT)
- PROD("A2410 HiRes", GFX, CARDCO_A2410)
-END
-
-BEGIN_PROD(A_SQUARED)
- PROD("Live! 2000", VIDEO, A_SQUARED_LIVE_2000)
-END
-
-BEGIN_PROD(COMSPEC_COMMUNICATIONS)
- PROD("AX2000", RAM, COMSPEC_COMMUNICATIONS_AX2000)
-END
-
-BEGIN_PROD(ANAKIN_RESEARCH)
- PROD("Easyl", TABLET, ANAKIN_RESEARCH_EASYL)
-END
-
-BEGIN_PROD(MICROBOTICS)
- PROD("StarBoard II", RAM, MICROBOTICS_STARBOARD_II)
- PROD("StarDrive", SCSI, MICROBOTICS_STARDRIVE)
- PROD("8-Up (Rev A)", RAM, MICROBOTICS_8_UP_A)
- PROD("8-Up (Rev Z)", RAM, MICROBOTICS_8_UP_Z)
- PROD("Delta", RAM, MICROBOTICS_DELTA_RAM)
- PROD("8-Star", RAM, MICROBOTICS_8_STAR_RAM)
- PROD("8-Star", MISC, MICROBOTICS_8_STAR)
- PROD("VXL RAM*32", RAM, MICROBOTICS_VXL_RAM_32)
- PROD("VXL-30", TURBO, MICROBOTICS_VXL_68030)
- PROD("Delta", MISC, MICROBOTICS_DELTA)
- PROD("MBX 1200/1200z", RAM, MICROBOTICS_MBX_1200_1200Z_RAM)
- PROD("Hardframe 2000", SCSI, MICROBOTICS_HARDFRAME_2000_1)
- PROD("Hardframe 2000", SCSI, MICROBOTICS_HARDFRAME_2000_2)
- PROD("MBX 1200/1200z", MISC, MICROBOTICS_MBX_1200_1200Z)
-END
-
-BEGIN_PROD(ACCESS_ASSOCIATES_ALEGRA)
-END
-
-BEGIN_PROD(EXPANSION_TECHNOLOGIES)
-END
-
-BEGIN_PROD(ASDG)
- PROD(NULL, RAM, ASDG_MEMORY_1)
- PROD(NULL, RAM, ASDG_MEMORY_2)
- PROD("EB-920 Lan Rover", ETHERNET, ASDG_EB920_LAN_ROVER)
- PROD("GPIB/Dual IEEE-488/Twin-X", MULTIIO, ASDG_GPIB_DUALIEEE488_TWIN_X)
-END
-
-BEGIN_PROD(IMTRONICS_1)
- PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_1)
- PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_2)
-END
-
-BEGIN_PROD(CBM_UNIVERSITY_OF_LOWELL)
- PROD("A2410 HiRes", GFX, CBM_A2410)
-END
-
-BEGIN_PROD(AMERISTAR)
- PROD("A2065", ETHERNET, AMERISTAR_A2065)
- PROD("A560", ARCNET, AMERISTAR_A560)
- PROD("A4066", ETHERNET, AMERISTAR_A4066)
-END
-
-BEGIN_PROD(SUPRA)
- PROD("SupraDrive 4x4", SCSI, SUPRA_SUPRADRIVE_4x4)
- PROD("1000", RAM, SUPRA_1000_RAM)
- PROD("2000 DMA", SCSI, SUPRA_2000_DMA)
- PROD("500", SCSI_RAM, SUPRA_500)
- PROD("500", SCSI, SUPRA_500_SCSI)
- PROD("500XP/2000", RAM, SUPRA_500XP_2000_RAM)
- PROD("500RX/2000", RAM, SUPRA_500RX_2000_RAM)
- PROD("2400zi", MODEM, SUPRA_2400ZI)
- PROD("500XP/SupraDrive WordSync", SCSI, SUPRA_500XP_SUPRADRIVE_WORDSYNC)
- PROD("SupraDrive WordSync II", SCSI, SUPRA_SUPRADRIVE_WORDSYNC_II)
- PROD("2400zi+", MODEM, SUPRA_2400ZIPLUS)
-END
-
-BEGIN_PROD(COMPUTER_SYSTEMS_ASSOCIATES)
- PROD("Magnum 40", TURBO_SCSI, CSA_MAGNUM)
- PROD("12 Gauge", SCSI, CSA_12_GAUGE)
-END
-
-BEGIN_PROD(MARC_MICHAEL_GROTH)
-END
-
-BEGIN_PROD(M_TECH)
- PROD("AT500", RAM, MTEC_AT500_1)
-END
-
-BEGIN_PROD(GREAT_VALLEY_PRODUCTS_1)
- PROD("Impact Series I", SCSI_RAM, GVP_IMPACT_SERIES_I)
-END
-
-BEGIN_PROD(BYTEBOX)
- PROD("A500", UNKNOWN, BYTEBOX_A500)
-END
-
-BEGIN_PROD(DKB_POWER_COMPUTING)
- PROD("SecureKey", UNKNOWN, DKB_POWER_COMPUTING_SECUREKEY)
- PROD("DKM 3128", RAM, DKB_POWER_COMPUTING_DKM_3128)
- PROD("Rapid Fire", SCSI, DKB_POWER_COMPUTING_RAPID_FIRE)
- PROD("DKM 1202", FPU_RAM, DKB_POWER_COMPUTING_DKM_1202)
- PROD("Cobra/Viper II 68EC030", TURBO, DKB_POWER_COMPUTING_COBRA_VIPER_II_68EC030)
- PROD("WildFire 060", TURBO, DKB_POWER_COMPUTING_WILDFIRE_060_1)
- PROD("WildFire 060", TURBO, DKB_POWER_COMPUTING_WILDFIRE_060_2)
-END
-
-BEGIN_PROD(GREAT_VALLEY_PRODUCTS_2)
- PROD("Impact Series I (4K)", SCSI, GVP_IMPACT_SERIES_I_4K)
- PROD("Impact Series I (16K/2)", SCSI, GVP_IMPACT_SERIES_I_16K_2)
- PROD("Impact Series I (16K/2)", SCSI, GVP_IMPACT_SERIES_I_16K_3)
- PROD("Impact 3001", IDE, GVP_IMPACT_3001_IDE_1)
- PROD("Impact 3001", RAM, GVP_IMPACT_3001_RAM)
- PROD("Impact Series II", RAM, GVP_IMPACT_SERIES_II_RAM_1)
-/* PROD(NULL, UNKNOWN, GVP_EPC_BASE) */
- PROD("Impact 3001", IDE, GVP_IMPACT_3001_IDE_2)
-/* PROD("A2000 030", TURBO, GVP_A2000_030) */
-/* PROD("GForce 040", TURBO_SCSI, GFORCE_040_SCSI_2) */
- PROD("GForce 040/060", TURBO_SCSI, GVP_GFORCE_040_060)
- PROD("Impact Vision 24", GFX, GVP_IMPACT_VISION_24)
- PROD("GForce 040", TURBO, GVP_GFORCE_040_2)
-END
-
-BEGIN_GVP_PROD /* ZORRO_PROD_GVP_EPC_BASE */
- GVP_PROD("GForce 040", TURBO, GVP_GFORCE_040_1)
- GVP_PROD("GForce 040", TURBO_SCSI, GVP_GFORCE_040_SCSI_1)
- GVP_PROD("A1291", SCSI, GVP_A1291)
- GVP_PROD("Combo 030 R4", TURBO, GVP_COMBO_030_R4)
- GVP_PROD("Combo 030 R4", TURBO_SCSI, GVP_COMBO_030_R4_SCSI)
- GVP_PROD("Phone Pak", UNKNOWN, GVP_PHONEPAK)
- GVP_PROD("IO-Extender", MULTIIO, GVP_IO_EXTENDER)
- GVP_PROD("GForce 030", TURBO, GVP_GFORCE_030)
- GVP_PROD("GForce 030", TURBO_SCSI, GVP_GFORCE_030_SCSI)
- GVP_PROD("A530", TURBO, GVP_A530)
- GVP_PROD("A530", TURBO_SCSI, GVP_A530_SCSI)
- GVP_PROD("Combo 030 R3", TURBO, GVP_COMBO_030_R3)
- GVP_PROD("Combo 030 R3", TURBO_SCSI, GVP_COMBO_030_R3_SCSI)
- GVP_PROD("Series-II", SCSI, GVP_SERIES_II)
-END
-
-BEGIN_PROD(CALIFORNIA_ACCESS_SYNERGY)
- PROD("Malibu", SCSI, CALIFORNIA_ACCESS_SYNERGY_MALIBU)
-END
-
-BEGIN_PROD(XETEC)
- PROD("FastCard", SCSI, XETEC_FASTCARD)
- PROD("FastCard", RAM, XETEC_FASTCARD_RAM)
- PROD("FastCard Plus", SCSI, XETEC_FASTCARD_PLUS)
-END
-
-BEGIN_PROD(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS)
- PROD("Mercury", TURBO, PPS_MERCURY)
- PROD("A3000 68040", TURBO, PPS_A3000_68040)
- PROD("A2000 68040", TURBO, PPS_A2000_68040)
- PROD("Zeus", TURBO_SCSI_RAM, PPS_ZEUS)
- PROD("A500 68040", TURBO, PPS_A500_68040)
-END
-
-BEGIN_PROD(XEBEC)
-END
-
-BEGIN_PROD(SPIRIT_TECHNOLOGY)
- PROD("Insider IN1000", RAM, SPIRIT_TECHNOLOGY_INSIDER_IN1000)
- PROD("Insider IN500", RAM, SPIRIT_TECHNOLOGY_INSIDER_IN500)
- PROD("SIN500", RAM, SPIRIT_TECHNOLOGY_SIN500)
- PROD("HDA 506", HD, SPIRIT_TECHNOLOGY_HDA_506)
- PROD("AX-S", MISC, SPIRIT_TECHNOLOGY_AX_S)
- PROD("OctaByte", RAM, SPIRIT_TECHNOLOGY_OCTABYTE)
- PROD("Inmate", SCSI_RAM, SPIRIT_TECHNOLOGY_INMATE)
-END
-
-BEGIN_PROD(SPIRIT_TECHNOLOGY_2)
-END
-
-BEGIN_PROD(BSC_ALFADATA_1)
- PROD("ALF 3", SCSI, BSC_ALF_3_1)
-END
-
-BEGIN_PROD(BSC_ALFADATA_2)
- PROD("ALF 2", SCSI, BSC_ALF_2_1)
- PROD("ALF 2", SCSI, BSC_ALF_2_2)
- PROD("ALF 3", SCSI, BSC_ALF_3_2)
-END
-
-BEGIN_PROD(CARDCO_2)
- PROD("Kronos", SCSI, CARDCO_KRONOS_2000_2)
- PROD("A1000", SCSI, CARDCO_A1000_2)
-END
-
-BEGIN_PROD(JOCHHEIM)
- PROD(NULL, RAM, JOCHHEIM_RAM)
-END
-
-BEGIN_PROD(CHECKPOINT_TECHNOLOGIES)
- PROD("Serial Solution", SERIAL, CHECKPOINT_TECHNOLOGIES_SERIAL_SOLUTION)
-END
-
-BEGIN_PROD(EDOTRONIK)
- PROD("IEEE-488 Interface Board", UNKNOWN, EDOTRONIK_IEEE_488)
- PROD("CBM-8032 Board", UNKNOWN, EDOTRONIK_8032)
- PROD(NULL, SERIAL, EDOTRONIK_MULTISERIAL)
- PROD("24Bit Realtime Video Digitizer", UNKNOWN, EDOTRONIK_VIDEODIGITIZER)
- PROD("32Bit Parallel I/O Interface", UNKNOWN, EDOTRONIK_PARALLEL_IO)
- PROD("PIC Prototyping Board", UNKNOWN, EDOTRONIK_PIC_PROTOYPING)
- PROD("16 Channel ADC Interface", UNKNOWN, EDOTRONIK_ADC)
- PROD("VME-Bus Controller", UNKNOWN, EDOTRONIK_VME)
- PROD("DSP96000 Realtime Data Acquisition", DSP, EDOTRONIK_DSP96000)
-END
-
-BEGIN_PROD(NES_INC)
- PROD(NULL, RAM, NES_INC_RAM)
-END
-
-BEGIN_PROD(ICD)
- PROD("Advantage 2000", SCSI, ICD_ADVANTAGE_2000_SCSI)
- PROD("Advantage", IDE, ICD_ADVANTAGE_2000_SCSI)
- PROD("Advantage 2080", RAM, ICD_ADVANTAGE_2080_RAM)
-END
-
-BEGIN_PROD(KUPKE_2)
- PROD("Omti", HD, KUPKE_OMTI)
- PROD("Golem SCSI-II", SCSI, KUPKE_SCSI_II)
- PROD("Golem Box", UNKNOWN, KUPKE_GOLEM_BOX)
- PROD("030/882", TURBO, KUPKE_030_882)
- PROD("Golem", SCSI, KUPKE_SCSI_AT)
-END
-
-BEGIN_PROD(GREAT_VALLEY_PRODUCTS_3)
- PROD("A2000-RAM8/2", MISC, GVP_A2000_RAM8)
- PROD("Impact Series II", RAM, GVP_IMPACT_SERIES_II_RAM_2)
-END
-
-BEGIN_PROD(INTERWORKS_NETWORK)
-END
-
-BEGIN_PROD(HARDITAL_SYNTHESIS)
- PROD("TQM 68030+68882", TURBO, HARDITAL_SYNTHESIS_TQM_68030_68882)
-END
-
-BEGIN_PROD(APPLIED_ENGINEERING)
- PROD("DL2000", MODEM, APPLIED_ENGINEERING_DL2000)
- PROD("RAM Works", RAM, APPLIED_ENGINEERING_RAM_WORKS)
-END
-
-BEGIN_PROD(BSC_ALFADATA_3)
- PROD("Oktagon 2008", SCSI, BSC_OKTAGON_2008)
- PROD("Tandem AT-2008/508", IDE, BSC_TANDEM_AT_2008_508)
- PROD("Alpha RAM 1200", RAM, BSC_ALFA_RAM_1200)
- PROD("Oktagon 2008", RAM, BSC_OKTAGON_2008_RAM)
- PROD("MultiFace I", MULTIIO, BSC_MULTIFACE_I)
- PROD("MultiFace II", MULTIIO, BSC_MULTIFACE_II)
- PROD("MultiFace III", MULTIIO, BSC_MULTIFACE_III)
- PROD("Framebuffer", MISC, BSC_FRAMEBUFFER)
- PROD("Graffiti", GFXRAM, BSC_GRAFFITI_RAM)
- PROD("Graffiti", GFX, BSC_GRAFFITI_REG)
- PROD("ISDN MasterCard", ISDN, BSC_ISDN_MASTERCARD)
- PROD("ISDN MasterCard II", ISDN, BSC_ISDN_MASTERCARD_II)
-END
-
-BEGIN_PROD(PHOENIX)
- PROD("ST506", HD, PHOENIX_ST506)
- PROD(NULL, SCSI, PHOENIX_SCSI)
- PROD(NULL, RAM, PHOENIX_RAM)
-END
-
-BEGIN_PROD(ADVANCED_STORAGE_SYSTEMS)
- PROD("Nexus", SCSI, ADVANCED_STORAGE_SYSTEMS_NEXUS)
- PROD("Nexus", RAM, ADVANCED_STORAGE_SYSTEMS_NEXUS_RAM)
-END
-
-BEGIN_PROD(IMPULSE)
- PROD("FireCracker 24", GFX, IMPULSE_FIRECRACKER_24)
-END
-
-BEGIN_PROD(IVS)
- PROD("GrandSlam PIC 2", RAM, IVS_GRANDSLAM_PIC_2)
- PROD("GrandSlam PIC 1", RAM, IVS_GRANDSLAM_PIC_1)
- PROD("OverDrive", HD, IVS_OVERDRIVE)
- PROD("TrumpCard Classic", SCSI, IVS_TRUMPCARD_CLASSIC)
- PROD("TrumpCard Pro/GrandSlam", SCSI, IVS_TRUMPCARD_PRO_GRANDSLAM)
- PROD("Meta-4", RAM, IVS_META_4)
- PROD("Wavetools", AUDIO, IVS_WAVETOOLS)
- PROD("Vector", SCSI, IVS_VECTOR_1)
- PROD("Vector", SCSI, IVS_VECTOR_2)
-END
-
-BEGIN_PROD(VECTOR_1)
- PROD("Connection", MULTIIO, VECTOR_CONNECTION_1)
-END
-
-BEGIN_PROD(XPERT_PRODEV)
- PROD("Visiona", GFXRAM, XPERT_PRODEV_VISIONA_RAM)
- PROD("Visiona", GFX, XPERT_PRODEV_VISIONA_REG)
- PROD("Merlin", GFXRAM, XPERT_PRODEV_MERLIN_RAM)
- PROD("Merlin", GFX, XPERT_PRODEV_MERLIN_REG_1)
- PROD("Merlin", GFX, XPERT_PRODEV_MERLIN_REG_2)
-END
-
-BEGIN_PROD(HYDRA_SYSTEMS)
- PROD("Amiganet", ETHERNET, HYDRA_SYSTEMS_AMIGANET)
-END
-
-BEGIN_PROD(SUNRIZE_INDUSTRIES)
- PROD("AD1012", AUDIO, SUNRIZE_INDUSTRIES_AD1012)
- PROD("AD516", AUDIO, SUNRIZE_INDUSTRIES_AD516)
- PROD("DD512", AUDIO, SUNRIZE_INDUSTRIES_DD512)
-END
-
-BEGIN_PROD(TRICERATOPS)
- PROD(NULL, MULTIIO, TRICERATOPS_MULTI_IO)
-END
-
-BEGIN_PROD(APPLIED_MAGIC)
- PROD("DMI Resolver", GFX, APPLIED_MAGIC_DMI_RESOLVER)
- PROD("Digital Broadcaster", VIDEO, APPLIED_MAGIC_DIGITAL_BROADCASTER)
-END
-
-BEGIN_PROD(GFX_BASE)
- PROD("GDA-1 VRAM", GFX, GFX_BASE_GDA_1_VRAM)
- PROD("GDA-1", GFX, GFX_BASE_GDA_1)
-END
-
-BEGIN_PROD(ROCTEC)
- PROD("RH 800C", HD, ROCTEC_RH_800C)
- PROD("RH 800C", RAM, ROCTEC_RH_800C_RAM)
-END
-
-BEGIN_PROD(KATO)
- PROD("Melody MPEG", AUDIO, KATO_MELODY)
- PROD("Rainbow II", GFX, HELFRICH_RAINBOW_II) /* ID clash!! */
- PROD("Rainbow III", GFX, HELFRICH_RAINBOW_III) /* ID clash!! */
-END
-
-BEGIN_PROD(ATLANTIS)
-END
-
-BEGIN_PROD(PROTAR)
-END
-
-BEGIN_PROD(ACS)
-END
-
-BEGIN_PROD(SOFTWARE_RESULTS_ENTERPRISES)
- PROD("Golden Gate 2 Bus+", BRIDGE, SOFTWARE_RESULTS_ENTERPRISES_GOLDEN_GATE_2_BUS_PLUS)
-END
-
-BEGIN_PROD(MASOBOSHI)
- PROD("MasterCard SC201", RAM, MASOBOSHI_MASTER_CARD_SC201)
- PROD("MasterCard MC702", SCSI_IDE, MASOBOSHI_MASTER_CARD_MC702)
- PROD("MVD 819", UNKNOWN, MASOBOSHI_MVD_819)
-END
-
-BEGIN_PROD(MAINHATTAN_DATA)
- PROD(NULL, IDE, MAINHATTAN_DATA_IDE)
-END
-
-BEGIN_PROD(VILLAGE_TRONIC)
- PROD("Domino", GFXRAM, VILLAGE_TRONIC_DOMINO_RAM)
- PROD("Domino", GFX, VILLAGE_TRONIC_DOMINO_REG)
- PROD("Domino 16M Prototype", GFX, VILLAGE_TRONIC_DOMINO_16M_PROTOTYPE)
- PROD("Picasso II/II+", GFXRAM, VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM)
- PROD("Picasso II/II+", GFX, VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG)
- PROD("Picasso II/II+ (Segmented Mode)", GFX, VILLAGE_TRONIC_PICASSO_II_II_PLUS_SEGMENTED_MODE)
- PROD("Picasso IV Z2", GFXRAM, VILLAGE_TRONIC_PICASSO_IV_Z2_MEM1)
- PROD("Picasso IV Z2", GFXRAM, VILLAGE_TRONIC_PICASSO_IV_Z2_MEM2)
- PROD("Picasso IV Z2", GFX, VILLAGE_TRONIC_PICASSO_IV_Z2_REG)
- PROD("Picasso IV Z3", GFX, VILLAGE_TRONIC_PICASSO_IV_Z3)
- PROD("Ariadne", ETHERNET_PARALLEL, VILLAGE_TRONIC_ARIADNE)
-END
-
-BEGIN_PROD(UTILITIES_UNLIMITED)
- PROD("Emplant Deluxe", MACEMU, UTILITIES_UNLIMITED_EMPLANT_DELUXE)
- PROD("Emplant Deluxe", MACEMU, UTILITIES_UNLIMITED_EMPLANT_DELUXE2)
-END
-
-BEGIN_PROD(AMITRIX)
- PROD(NULL, MULTIIO, AMITRIX_MULTI_IO)
- PROD("CD-RAM", RAM, AMITRIX_CD_RAM)
-END
-
-BEGIN_PROD(ARMAX)
- PROD("OmniBus", GFX, ARMAX_OMNIBUS)
-END
-
-BEGIN_PROD(NEWTEK)
- PROD("VideoToaster", VIDEO, NEWTEK_VIDEOTOASTER)
-END
-
-BEGIN_PROD(M_TECH_GERMANY)
- PROD("AT500", IDE, MTEC_AT500_2)
- PROD("68030", TURBO, MTEC_68030)
- PROD("68020i", TURBO, MTEC_68020I)
- PROD("A1200 T68030 RTC", TURBO, MTEC_A1200_T68030_RTC)
- PROD("Viper Mk V/E-Matrix 530", TURBO_RAM, MTEC_VIPER_MK_V_E_MATRIX_530)
- PROD("8MB", RAM, MTEC_8_MB_RAM)
- PROD("Viper Mk V/E-Matrix 530 SCSI/IDE", SCSI_IDE, MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE)
-END
-
-BEGIN_PROD(GREAT_VALLEY_PRODUCTS_4)
- PROD("EGS 28/24 Spectrum", GFX, GVP_EGS_28_24_SPECTRUM_REG)
- PROD("EGS 28/24 Spectrum", GFXRAM, GVP_EGS_28_24_SPECTRUM_RAM)
-END
-
-BEGIN_PROD(APOLLO_1)
- PROD("A1200", FPU_RAM, APOLLO_A1200)
-END
-
-BEGIN_PROD(HELFRICH_2)
- PROD("Piccolo", GFXRAM, HELFRICH_PICCOLO_RAM)
- PROD("Piccolo", GFX, HELFRICH_PICCOLO_REG)
- PROD("PeggyPlus MPEG", VIDEO, HELFRICH_PEGGY_PLUS_MPEG)
- PROD("VideoCruncher", VIDEO, HELFRICH_VIDEOCRUNCHER)
- PROD("Piccolo SD64", GFXRAM, HELFRICH_SD64_RAM)
- PROD("Piccolo SD64", GFX, HELFRICH_SD64_REG)
-END
-
-BEGIN_PROD(MACROSYSTEMS_USA)
- PROD("Warp Engine 40xx", TURBO_SCSI_RAM, MACROSYSTEMS_WARP_ENGINE_40xx)
-END
-
-BEGIN_PROD(ELBOX_COMPUTER)
- PROD("1200/4", RAM, ELBOX_COMPUTER_1200_4)
-END
-
-BEGIN_PROD(HARMS_PROFESSIONAL)
- PROD("030 Plus", TURBO, HARMS_PROFESSIONAL_030_PLUS)
- PROD("3500 Professional", TURBO_RAM, HARMS_PROFESSIONAL_3500)
-END
-
-BEGIN_PROD(MICRONIK)
- PROD("RCA 120", RAM, MICRONIK_RCA_120)
-END
-
-BEGIN_PROD(MICRONIK2)
- PROD("Z3i A1200 Zorro III + SCSI", SCSI, MICRONIK2_Z3I)
-END
-
-BEGIN_PROD(MEGAMICRO)
- PROD("SCRAM 500", SCSI, MEGAMICRO_SCRAM_500)
- PROD("SCRAM 500", RAM, MEGAMICRO_SCRAM_500_RAM)
-END
-
-BEGIN_PROD(IMTRONICS_2)
- PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_3)
- PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_4)
-END
-
-BEGIN_PROD(INDIVIDUAL_COMPUTERS)
- PROD("Buddha", IDE, INDIVIDUAL_COMPUTERS_BUDDHA)
- PROD("Catweasel", IDE_FLOPPY, INDIVIDUAL_COMPUTERS_CATWEASEL)
-END
-
-BEGIN_PROD(KUPKE_3)
- PROD("Golem HD 3000", HD, KUPKE_GOLEM_HD_3000)
-END
-
-BEGIN_PROD(ITH)
- PROD("ISDN-Master II", ISDN, ITH_ISDN_MASTER_II)
-END
-
-BEGIN_PROD(VMC)
- PROD("ISDN Blaster Z2", ISDN, VMC_ISDN_BLASTER_Z2)
- PROD("HyperCom 4", MULTIIO, VMC_HYPERCOM_4)
-END
-
-BEGIN_PROD(INFORMATION)
- PROD("ISDN Engine I", ISDN, INFORMATION_ISDN_ENGINE_I)
-END
-
-BEGIN_PROD(VORTEX)
- PROD("Golden Gate 80386SX", BRIDGE, VORTEX_GOLDEN_GATE_80386SX)
- PROD("Golden Gate", RAM, VORTEX_GOLDEN_GATE_RAM)
- PROD("Golden Gate 80486", BRIDGE, VORTEX_GOLDEN_GATE_80486)
-END
-
-BEGIN_PROD(EXPANSION_SYSTEMS)
- PROD("DataFlyer 4000SX", SCSI, EXPANSION_SYSTEMS_DATAFLYER_4000SX)
- PROD("DataFlyer 4000SX", RAM, EXPANSION_SYSTEMS_DATAFLYER_4000SX_RAM)
-END
-
-BEGIN_PROD(READYSOFT)
- PROD("AMax II/IV", MACEMU, READYSOFT_AMAX_II_IV)
-END
-
-BEGIN_PROD(PHASE5)
- PROD("Blizzard", RAM, PHASE5_BLIZZARD_RAM)
- PROD("Blizzard", TURBO, PHASE5_BLIZZARD)
- PROD("Blizzard 1220-IV", TURBO, PHASE5_BLIZZARD_1220_IV)
- PROD("FastLane Z3", RAM, PHASE5_FASTLANE_Z3_RAM)
- PROD("Blizzard 1230-II/Fastlane Z3/CyberSCSI/CyberStorm060", TURBO_SCSI, PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060)
- PROD("Blizzard 1220/CyberStorm", TURBO_SCSI, PHASE5_BLIZZARD_1220_CYBERSTORM)
- PROD("Blizzard 1230", TURBO, PHASE5_BLIZZARD_1230)
- PROD("Blizzard 1230-IV/1260", TURBO, PHASE5_BLIZZARD_1230_IV_1260)
- PROD("Blizzard 2060", TURBO, PHASE5_BLIZZARD_2060)
- PROD("CyberStorm Mk II", FLASHROM, PHASE5_CYBERSTORM_MK_II)
- PROD("CyberVision64", GFX, PHASE5_CYBERVISION64)
- PROD("CyberVision64-3D Prototype", GFX, PHASE5_CYBERVISION64_3D_PROTOTYPE)
- PROD("CyberVision64-3D", GFX, PHASE5_CYBERVISION64_3D)
- PROD("CyberStorm Mk III", TURBO_SCSI, PHASE5_CYBERSTORM_MK_III)
-END
-
-BEGIN_PROD(DPS)
- PROD("Personal Animation Recorder", VIDEO, DPS_PERSONAL_ANIMATION_RECORDER)
-END
-
-BEGIN_PROD(APOLLO_2)
- PROD("A620 68020", TURBO, APOLLO_A620_68020_1)
- PROD("A620 68020", TURBO, APOLLO_A620_68020_2)
-END
-
-BEGIN_PROD(APOLLO_3)
- PROD("AT-Apollo", UNKNOWN, APOLLO_AT_APOLLO)
- PROD("1230/1240/1260/2030/4040/4060", TURBO, APOLLO_1230_1240_1260_2030_4040_4060)
-END
-
-BEGIN_PROD(PETSOFF_LP)
- PROD("Delfina", AUDIO, PETSOFF_LP_DELFINA)
- PROD("Delfina Lite", AUDIO, PETSOFF_LP_DELFINA_LITE)
-END
-
-BEGIN_PROD(UWE_GERLACH)
- PROD("RAM/ROM", MISC, UWE_GERLACH_RAM_ROM)
-END
-
-BEGIN_PROD(MACROSYSTEMS_GERMANY)
- PROD("Maestro", AUDIO, MACROSYSTEMS_MAESTRO)
- PROD("VLab", VIDEO, MACROSYSTEMS_VLAB)
- PROD("Maestro Pro", AUDIO, MACROSYSTEMS_MAESTRO_PRO)
- PROD("Retina", GFX, MACROSYSTEMS_RETINA)
- PROD("MultiEvolution", SCSI, MACROSYSTEMS_MULTI_EVOLUTION)
- PROD("Toccata", AUDIO, MACROSYSTEMS_TOCCATA)
- PROD("Retina Z3", GFX, MACROSYSTEMS_RETINA_Z3)
- PROD("VLab Motion", VIDEO, MACROSYSTEMS_VLAB_MOTION)
- PROD("Altais", GFX, MACROSYSTEMS_ALTAIS)
- PROD("Falcon '040", TURBO, MACROSYSTEMS_FALCON_040)
-END
-
-BEGIN_PROD(COMBITEC)
-END
-
-BEGIN_PROD(SKI_PERIPHERALS)
- PROD("MAST Fireball", SCSI, SKI_PERIPHERALS_MAST_FIREBALL)
- PROD("SCSI/Dual Serial", SCSI_SERIAL, SKI_PERIPHERALS_SCSI_DUAL_SERIAL)
-END
-
-BEGIN_PROD(REIS_WARE_2)
- PROD("Scan King", SCANNER, REIS_WARE_SCAN_KING)
-END
-
-BEGIN_PROD(CAMERON)
- PROD("Personal A4", SCANNER, CAMERON_PERSONAL_A4)
-END
-
-BEGIN_PROD(REIS_WARE)
- PROD("Handyscanner", SCANNER, REIS_WARE_HANDYSCANNER)
-END
-
-BEGIN_PROD(PHOENIX_2)
- PROD("ST506", HD, PHOENIX_ST506_2)
- PROD(NULL, SCSI, PHOENIX_SCSI_2)
- PROD(NULL, RAM, PHOENIX_RAM_2)
-END
-
-BEGIN_PROD(COMBITEC_2)
- PROD(NULL, HD, COMBITEC_HD)
- PROD("SRAM", RAM, COMBITEC_SRAM)
-END
-
-BEGIN_PROD(HACKER) /* Unused */
-END
-
-
-BEGIN_MANUF
- MANUF("Pacific Peripherals", PACIFIC_PERIPHERALS)
- MANUF("MacroSystems USA", MACROSYSTEMS_USA_2)
- MANUF("Kupke", KUPKE_1)
- MANUF("Memphis", MEMPHIS)
- MANUF("3-State", 3_STATE)
- MANUF("Commodore Braunschweig", COMMODORE_BRAUNSCHWEIG)
- MANUF("Commodore West Chester", COMMODORE_WEST_CHESTER_1)
- MANUF("Commodore West Chester", COMMODORE_WEST_CHESTER_2)
- MANUF("Progressive Peripherals & Systems", PROGRESSIVE_PERIPHERALS_AND_SYSTEMS_2)
- MANUF("Kolff Computer Supplies", KOLFF_COMPUTER_SUPPLIES)
- MANUF("Cardco Ltd.", CARDCO_1)
- MANUF("A-Squared", A_SQUARED)
- MANUF("Comspec Communications", COMSPEC_COMMUNICATIONS)
- MANUF("Anakin Research", ANAKIN_RESEARCH)
- MANUF("Microbotics", MICROBOTICS)
- MANUF("Access Associates Alegra", ACCESS_ASSOCIATES_ALEGRA)
- MANUF("Expansion Technologies (Pacific Cypress)", EXPANSION_TECHNOLOGIES)
- MANUF("ASDG", ASDG)
- MANUF("Ronin/Imtronics", IMTRONICS_1)
- MANUF("Commodore/University of Lowell", CBM_UNIVERSITY_OF_LOWELL)
- MANUF("Ameristar", AMERISTAR)
- MANUF("Supra", SUPRA)
- MANUF("Computer Systems Assosiates", COMPUTER_SYSTEMS_ASSOCIATES)
- MANUF("Marc Michael Groth", MARC_MICHAEL_GROTH)
- MANUF("M-Tech", M_TECH)
- MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_1)
- MANUF("ByteBox", BYTEBOX)
- MANUF("DKB/Power Computing", DKB_POWER_COMPUTING)
- MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_2)
- MANUF("California Access (Synergy)", CALIFORNIA_ACCESS_SYNERGY)
- MANUF("Xetec", XETEC)
- MANUF("Progressive Peripherals & Systems", PROGRESSIVE_PERIPHERALS_AND_SYSTEMS)
- MANUF("Xebec", XEBEC)
- MANUF("Spirit Technology", SPIRIT_TECHNOLOGY)
- MANUF("Spirit Technology", SPIRIT_TECHNOLOGY_2)
- MANUF("BSC/Alfadata", BSC_ALFADATA_1)
- MANUF("BSC/Alfadata", BSC_ALFADATA_2)
- MANUF("Cardco Ltd.", CARDCO_2)
- MANUF("Jochheim", JOCHHEIM)
- MANUF("Checkpoint Technologies", CHECKPOINT_TECHNOLOGIES)
- MANUF("Edotronik", EDOTRONIK)
- MANUF("NES Inc.", NES_INC)
- MANUF("ICD", ICD)
- MANUF("Kupke", KUPKE_2)
- MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_3)
- MANUF("Interworks Network", INTERWORKS_NETWORK)
- MANUF("Hardital Synthesis", HARDITAL_SYNTHESIS)
- MANUF("Applied Engineering", APPLIED_ENGINEERING)
- MANUF("BSC/Alfadata", BSC_ALFADATA_3)
- MANUF("Phoenix", PHOENIX)
- MANUF("Advanced Storage Systems", ADVANCED_STORAGE_SYSTEMS)
- MANUF("Impulse", IMPULSE)
- MANUF("IVS", IVS)
- MANUF("Vector", VECTOR_1)
- MANUF("XPert ProDev", XPERT_PRODEV)
- MANUF("Hydra Systems", HYDRA_SYSTEMS)
- MANUF("Sunrize Industries", SUNRIZE_INDUSTRIES)
- MANUF("Triceratops", TRICERATOPS)
- MANUF("Applied Magic Inc.", APPLIED_MAGIC)
- MANUF("GFX-Base", GFX_BASE)
- MANUF("RocTec", ROCTEC)
- MANUF("Kato", KATO)
- MANUF("Atlantis", ATLANTIS)
- MANUF("Protar", PROTAR)
- MANUF("ACS", ACS)
- MANUF("Software Results Enterprises", SOFTWARE_RESULTS_ENTERPRISES)
- MANUF("Masoboshi", MASOBOSHI)
- MANUF("Mainhattan-Data (A-Team)", MAINHATTAN_DATA)
- MANUF("Village Tronic", VILLAGE_TRONIC)
- MANUF("Utilities Unlimited", UTILITIES_UNLIMITED)
- MANUF("Amitrix", AMITRIX)
- MANUF("ArMax", ARMAX)
- MANUF("NewTek", NEWTEK)
- MANUF("M-Tech Germany", M_TECH_GERMANY)
- MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_4)
- MANUF("Apollo", APOLLO_1)
- MANUF("Ingenieurbüro Helfrich", HELFRICH_2)
- MANUF("MacroSystems USA", MACROSYSTEMS_USA)
- MANUF("ElBox Computer", ELBOX_COMPUTER)
- MANUF("Harms Professional", HARMS_PROFESSIONAL)
- MANUF("Micronik", MICRONIK)
- MANUF("Micronik", MICRONIK2)
- MANUF("MegaMicro", MEGAMICRO)
- MANUF("Ronin/Imtronics", IMTRONICS_2)
- MANUF("Individual Computers", INDIVIDUAL_COMPUTERS)
- MANUF("Kupke", KUPKE_3)
- MANUF("ITH", ITH)
- MANUF("VMC", VMC)
- MANUF("Information", INFORMATION)
- MANUF("Vortex", VORTEX)
- MANUF("Expansion Systems", EXPANSION_SYSTEMS)
- MANUF("ReadySoft", READYSOFT)
- MANUF("Phase 5", PHASE5)
- MANUF("DPS", DPS)
- MANUF("Apollo", APOLLO_2)
- MANUF("Apollo", APOLLO_3)
- MANUF("Petsoff LP", PETSOFF_LP)
- MANUF("Uwe Gerlach", UWE_GERLACH)
- MANUF("MacroSystems Germany", MACROSYSTEMS_GERMANY)
- MANUF("Combitec", COMBITEC)
- MANUF("SKI Peripherals", SKI_PERIPHERALS)
- MANUF("Reis-Ware", REIS_WARE_2)
- MANUF("Cameron", CAMERON)
- MANUF("Reis-Ware", REIS_WARE)
- MANUF("Hacker Test Board", HACKER) /* Unused */
- MANUF("Phoenix", PHOENIX_2)
- MANUF("Combitec", COMBITEC_2)
-END
-
-#define NUM_MANUF (ARRAYSIZE(Manufacturers))
-#define NUM_GVP_PROD (ARRAYSIZE(Ext_Prod_GVP))
-
-
- /*
- * Zorro product classes
- *
- * Make sure to keep these in sync with include/linux/zorro.h!
- */
-
-static const char *classnames[] = {
- NULL, /* ZORRO_CLASS_UNKNOWN */
- "ArcNet Card", /* ZORRO_CLASS_ARCNET */
- "Audio Board", /* ZORRO_CLASS_AUDIO */
- "ISA Bus Bridge", /* ZORRO_CLASS_BRIDGE */
- "DSP Board", /* ZORRO_CLASS_DSP */
- "Ethernet Card", /* ZORRO_CLASS_ETHERNET */
- "Ethernet Card and Parallel Ports", /* ZORRO_CLASS_ETHERNET_PARALLEL */
- "Flash ROM", /* ZORRO_CLASS_FLASHROM */
- "FPU and RAM Expansion", /* ZORRO_CLASS_FPU_RAM */
- "Graphics Board", /* ZORRO_CLASS_GFX */
- "Graphics Board (RAM)", /* ZORRO_CLASS_GFXRAM */
- "HD Controller", /* ZORRO_CLASS_HD */
- "HD Controller and RAM Expansion", /* ZORRO_CLASS_HD_RAM */
- "IDE Interface", /* ZORRO_CLASS_IDE */
- "IDE Interface and RAM Expansion", /* ZORRO_CLASS_IDE_RAM */
- "IDE Interface and Floppy Controller", /* ZORRO_CLASS_IDE_FLOPPY */
- "ISDN Interface", /* ZORRO_CLASS_ISDN */
- "Macintosh Emulator", /* ZORRO_CLASS_MACEMU */
- "Miscellaneous Expansion Card", /* ZORRO_CLASS_MISC */
- "Modem", /* ZORRO_CLASS_MODEM */
- "Multi I/O", /* ZORRO_CLASS_MULTIIO */
- "RAM Expansion", /* ZORRO_CLASS_RAM */
- "Scanner Interface", /* ZORRO_CLASS_SCANNER */
- "SCSI Host Adapter", /* ZORRO_CLASS_SCSI */
- "SCSI Host Adapter and IDE Interface", /* ZORRO_CLASS_SCSI_IDE */
- "SCSI Host Adapter and RAM Expansion", /* ZORRO_CLASS_SCSI_RAM */
- "SCSI Host Adapter and Serial Card", /* ZORRO_CLASS_SCSI_SERIAL */
- "Multi Serial", /* ZORRO_CLASS_SERIAL */
- "Drawing Tablet Interface", /* ZORRO_CLASS_TABLET */
- "Accelerator", /* ZORRO_CLASS_TURBO */
- "Accelerator and RAM Expansion", /* ZORRO_CLASS_TURBO_RAM */
- "Accelerator and HD Controller", /* ZORRO_CLASS_TURBO_HD */
- "Accelerator and IDE Interface", /* ZORRO_CLASS_TURBO_IDE */
- "Accelerator and SCSI Host Adapter", /* ZORRO_CLASS_TURBO_SCSI */
- "Accelerator, SCSI Host Adapter and RAM Expansion", /* ZORRO_CLASS_TURBO_SCSI */
- "Video Board", /* ZORRO_CLASS_VIDEO */
-};
-
-static inline const char *get_class_name(enum Zorro_Classes class)
-{
- if (class < ARRAYSIZE(classnames))
- return(classnames[class]);
- else
- return("(**Illegal**)");
-}
-
-#endif /* CONFIG_ZORRO */
-
-
- /*
- * Expansion Devices
- */
-
-u_int zorro_num_autocon;
-struct ConfigDev zorro_autocon[ZORRO_NUM_AUTO];
-static u32 BoardPartFlags[ZORRO_NUM_AUTO] = { 0, };
-
-
- /*
- * Find the key for the next unconfigured expansion device of a specific
- * type.
- *
- * Part is a device specific number (0 <= part <= 31) to allow for the
- * independent configuration of independent parts of an expansion board.
- * Thanks to Jes Soerensen for this idea!
- *
- * Index is used to specify the first board in the autocon list
- * to be tested. It was inserted in order to solve the problem
- * with the GVP boards that uses the same product code, but
- * it should help if there are other companies which use the same
- * method as GVP. Drivers for boards which are not using this
- * method do not need to think of this - just set index = 0.
- *
- * Example:
- *
- * while ((key = zorro_find(ZORRO_PROD_MY_BOARD, MY_PART, 0))) {
- * cd = zorro_get_board(key);
- * initialise_this_board;
- * zorro_config_board(key, MY_PART);
- * }
- */
-
-u_int zorro_find(zorro_id id, u_int part, u_int index)
-{
- u_int manuf = ZORRO_MANUF(id);
- u_int prod = ZORRO_PROD(id);
- u_int epc = ZORRO_EPC(id);
- u_int key;
- const struct ConfigDev *cd;
- u_long addr;
-
- if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
- return(0);
-
- if (part > 31) {
- printk("zorro_find: bad part %d\n", part);
- return(0);
- }
-
- for (key = index + 1; key <= zorro_num_autocon; key++) {
- cd = &zorro_autocon[key-1];
- addr = (u_long)cd->cd_BoardAddr;
- if ((cd->cd_Rom.er_Manufacturer == manuf) &&
- (cd->cd_Rom.er_Product == prod) &&
- !(BoardPartFlags[key-1] & (1<<part)) &&
- (manuf != ZORRO_MANUF(ZORRO_PROD_GVP_EPC_BASE) ||
- prod != ZORRO_PROD(ZORRO_PROD_GVP_EPC_BASE) ||
- (*(u_short *)ZTWO_VADDR(addr+0x8000) & GVP_PRODMASK) == epc))
- break;
- }
- return(key <= zorro_num_autocon ? key : 0);
-}
-
-
- /*
- * Get the board corresponding to a specific key
- */
-
-const struct ConfigDev *zorro_get_board(u_int key)
-{
- const struct ConfigDev *cd = NULL;
-
- if ((key < 1) || (key > zorro_num_autocon))
- printk("zorro_get_board: bad key %d\n", key);
- else
- cd = &zorro_autocon[key-1];
-
- return(cd);
-}
-
-
- /*
- * Mark a part of a board as configured
- */
-
-void zorro_config_board(u_int key, u_int part)
-{
- if ((key < 1) || (key > zorro_num_autocon))
- printk("zorro_config_board: bad key %d\n", key);
- else if (part > 31)
- printk("zorro_config_board: bad part %d\n", part);
- else if (BoardPartFlags[key-1] & (1<<part))
- printk("zorro_config_board: key %d part %d is already configured\n",
- key, part);
- else
- BoardPartFlags[key-1] |= 1<<part;
-}
-
-
- /*
- * Mark a part of a board as unconfigured
- *
- * This function is mainly intended for the unloading of LKMs
- */
-
-void zorro_unconfig_board(u_int key, u_int part)
-{
- if ((key < 1) || (key > zorro_num_autocon))
- printk("zorro_unconfig_board: bad key %d\n", key);
- else if (part > 31)
- printk("zorro_unconfig_board: bad part %d\n", part);
- else if (!(BoardPartFlags[key-1] & (1<<part)))
- printk("zorro_config_board: key %d part %d is not yet configured\n",
- key, part);
- else
- BoardPartFlags[key-1] &= ~(1<<part);
-}
-
-
-#ifdef CONFIG_ZORRO
-
- /*
- * Identify an AutoConfig Expansion Device
- *
- * If the board was configured by a Linux/m68k driver, an asterisk will
- * be printed before the board address (except for unknown and `Hacker
- * Test' boards).
- */
-
-static int identify(u_int devnum, char *buf, int verbose)
-{
- const struct ConfigDev *cd = &zorro_autocon[devnum];
- u32 configured = BoardPartFlags[devnum];
- u_int manuf = cd->cd_Rom.er_Manufacturer;
- u_int prod = cd->cd_Rom.er_Product;
- u_int class = ZORRO_CLASS_UNKNOWN;
- u_int epc = 0;
- const char *manufname = "Unknown";
- const char *prodname = "Unknown";
- const char *classname;
- u_int i, j, k, len = 0;
- u_long addr = (u_long)cd->cd_BoardAddr;
- u_long size = cd->cd_BoardSize;
- char mag;
- int identified = 0, gvp = 0;
-
- if (manuf != ZORRO_MANUF(ZORRO_PROD_GVP_EPC_BASE) ||
- prod != ZORRO_PROD(ZORRO_PROD_GVP_EPC_BASE)) {
- for (i = 0; i < NUM_MANUF; i++)
- if (Manufacturers[i].Manuf == manuf) {
- manufname = Manufacturers[i].Name;
- for (j = 0; j < Manufacturers[i].NumProd; j++)
- if (Manufacturers[i].Products[j].Prod == prod) {
- prodname = Manufacturers[i].Products[j].Name;
- class = Manufacturers[i].Products[j].Class;
- identified = 1;
- break;
- }
- }
- /* Put workarounds for ID clashes here */
- if (manuf == ZORRO_MANUF(ZORRO_PROD_HELFRICH_RAINBOW_III) &&
- prod == ZORRO_PROD(ZORRO_PROD_HELFRICH_RAINBOW_III))
- manufname = "Ingenieurbüro Helfrich";
- } else {
- manufname = "Great Valley Products";
- gvp = 1;
- epc = *(u_short *)ZTWO_VADDR(addr+0x8000) & GVP_PRODMASK;
- for (k = 0; k < NUM_GVP_PROD; k++)
- if (epc == Ext_Prod_GVP[k].EPC) {
- prodname = Ext_Prod_GVP[k].Name;
- class = Ext_Prod_GVP[k].Class;
- identified = 1;
- break;
- }
- }
- classname = get_class_name(class);
- if (size & 0xfffff) {
- size >>= 10;
- mag = 'K';
- } else {
- size >>= 20;
- mag = 'M';
- }
- if (verbose) {
- const char *zorro;
- int is_mem = cd->cd_Rom.er_Type & ERTF_MEMLIST;
- switch (cd->cd_Rom.er_Type & ERT_TYPEMASK) {
- case ERT_ZORROII:
- zorro = "Zorro II";
- break;
- case ERT_ZORROIII:
- zorro = "Zorro III";
- break;
- default:
- zorro = "Unknown Zorro";
- break;
- }
- if (!prodname)
- prodname = "Unknown";
- if (!classname)
- classname = "Unknown";
- len = sprintf(buf, " Device %d at 0x%08lx: ID=%04x:%02x", devnum,
- addr, manuf, prod);
- if (gvp)
- len += sprintf(buf+len, ":%02x", epc);
- len += sprintf(buf+len, ", %s, %ld%c", zorro, size, mag);
- if (is_mem)
- len += sprintf(buf+len, ", System RAM");
- else
- len += sprintf(buf+len, ", Configured=%08x", configured);
- len += sprintf(buf+len, "\n"
- " Manufacturer: %s\n"
- " Product Name: %s\n"
- " Board Class : %s\n",
- manufname, prodname, classname);
- } else {
- len = sprintf(buf, " %c%08lx: ", configured ? '*' : ' ', addr);
- if (identified) {
- len += sprintf(buf+len, "%s", manufname);
- if (prodname)
- len += sprintf(buf+len, " %s", prodname);
- if (classname)
- len += sprintf(buf+len, " %s", classname);
- } else if (manuf == ZORRO_MANUF_HACKER)
- len += sprintf(buf+len, "Hacker Test Board %02x", prod);
- else if (gvp)
- len += sprintf(buf+len, "[%04x:%02x:%02x] made by %s", manuf, prod,
- epc, manufname);
- else
- len += sprintf(buf+len, "[%04x:%02x] made by %s", manuf, prod,
- manufname);
- len += sprintf(buf+len, " (%ld%c)\n", size, mag);
- if (!identified && manuf != ZORRO_MANUF_HACKER)
- len += sprintf(buf+len, " Please report this unknown device to "
- "zorro@linux-m68k.org\n");
- }
- return(len);
-}
-
-
- /*
- * Identify all known AutoConfig Expansion Devices
- */
-
-void zorro_identify(void)
-{
- u_int i;
- char tmp[256];
-
- if (!AMIGAHW_PRESENT(ZORRO))
- return;
-
- printk("Probing AutoConfig expansion device(s):\n");
- for (i = 0; i < zorro_num_autocon; i++) {
- identify(i, tmp, 0);
- printk(tmp);
- }
- if (!zorro_num_autocon)
- printk("No AutoConfig expansion devices present.\n");
-}
-
-
- /*
- * Get the list of all AutoConfig Expansion Devices
- */
-
-int zorro_get_list(char *buffer)
-{
- u_int i, len = 0, len2;
- char tmp[256];
-
- if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) {
- len = sprintf(buffer, "AutoConfig expansion devices:\n");
- for (i = 0; i < zorro_num_autocon; i++) {
- len2 = identify(i, tmp, 1);
- if (len+len2 >= 4075) {
- len += sprintf(buffer+len, "4K limit reached!\n");
- break;
- }
- strcpy(buffer+len, tmp);
- len += len2;
- }
- }
- return(len);
-}
-
-#endif /* CONFIG_ZORRO */
-
-
- /*
- * Bitmask indicating portions of available Zorro II RAM that are unused
- * by the system. Every bit represents a 64K chunk, for a maximum of 8MB
- * (128 chunks, physical 0x00200000-0x009fffff).
- *
- * If you want to use (= allocate) portions of this RAM, you should clear
- * the corresponding bits.
- *
- * Possible uses:
- * - z2ram device
- * - SCSI DMA bounce buffers
- */
-
-u32 zorro_unused_z2ram[4] = { 0, 0, 0, 0 };
-
-
-static void mark_region(u_long addr, u_long size, int flag)
-{
- u_long start, end, chunk;
-
- if (flag) {
- start = (addr+Z2RAM_CHUNKMASK) & ~Z2RAM_CHUNKMASK;
- end = (addr+size) & ~Z2RAM_CHUNKMASK;
- } else {
- start = addr & ~Z2RAM_CHUNKMASK;
- end = (addr+size+Z2RAM_CHUNKMASK) & ~Z2RAM_CHUNKMASK;
- }
- if (end <= Z2RAM_START || start >= Z2RAM_END)
- return;
- start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START;
- end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START;
- while (start < end) {
- chunk = start>>Z2RAM_CHUNKSHIFT;
- if (flag)
- set_bit( chunk, zorro_unused_z2ram );
- else
- clear_bit( chunk, zorro_unused_z2ram );
- start += Z2RAM_CHUNKSIZE;
- }
-}
-
-
- /*
- * Initialization
- */
-
-void zorro_init(void)
-{
- u_int i;
- const struct ConfigDev *cd;
-
- if (!AMIGAHW_PRESENT(ZORRO))
- return;
-
- /* Mark all available Zorro II memory */
- for (i = 0; i < zorro_num_autocon; i++) {
- cd = &zorro_autocon[i];
- if (cd->cd_Rom.er_Type & ERTF_MEMLIST)
- mark_region((u_long)cd->cd_BoardAddr, cd->cd_BoardSize, 1);
- }
-
- /* Unmark all used Zorro II memory */
- for (i = 0; i < m68k_num_memory; i++)
- mark_region(m68k_memory[i].addr, m68k_memory[i].size, 0);
-}
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index 2ad8f9c24..4c620f23e 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -14,7 +14,6 @@
#include <asm/irq.h>
#include <asm/machdep.h>
-extern struct consw fb_con;
extern void dn_sched_init(void (*handler)(int,void *,struct pt_regs *));
extern int dn_keyb_init(void);
extern int dn_dummy_kbdrate(struct kbd_repeat *);
@@ -110,7 +109,9 @@ void config_apollo(void) {
mach_floppy_setup = dn_dummy_floppy_setup;
#endif
mach_reset = dn_dummy_reset; /* */
- conswitchp = &fb_con;
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
#if 0
mach_fb_init = dn_fb_init;
mach_video_setup = dn_dummy_video_setup;
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index 61afbb50b..15e4c2d09 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -294,7 +294,7 @@ SYMBOL_NAME_STR(atari_fast_irq_handler) ":
addql #8,%%sp
addql #4,%%sp
jbra "SYMBOL_NAME_STR(ret_from_interrupt)
- : : "i" (&kstat.irqs), "n" (PT_OFF_FORMATVEC)
+ : : "i" (&kstat.irqs[0]), "n" (PT_OFF_FORMATVEC)
);
}
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
index 8c512a714..e6535f6ff 100644
--- a/arch/m68k/atari/atakeyb.c
+++ b/arch/m68k/atari/atakeyb.c
@@ -28,11 +28,9 @@
#include <asm/atariints.h>
#include <asm/atarihw.h>
#include <asm/atarikb.h>
-#include <asm/atari_mouse.h>
#include <asm/atari_joystick.h>
#include <asm/irq.h>
-extern unsigned char mach_keyboard_type;
static void atakeyb_rep( unsigned long ignore );
extern unsigned int keymap_count;
@@ -193,7 +191,7 @@ static u_short ataalt_map[NR_KEYS] __initdata = {
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
};
-static u_short atashift_alt_map[NR_KEYS] = {
+static u_short atashift_alt_map[NR_KEYS] __initdata = {
0xf200, 0xf81b, 0xf821, 0xf840, 0xf823, 0xf824, 0xf825, 0xf85e,
0xf826, 0xf82a, 0xf828, 0xf829, 0xf85f, 0xf82b, 0xf808, 0xf809,
0xf851, 0xf857, 0xf845, 0xf852, 0xf854, 0xf859, 0xf855, 0xf849,
@@ -767,19 +765,22 @@ void atari_kbd_leds (unsigned int leds)
__initfunc(int atari_keyb_init(void))
{
/* setup key map */
- memcpy(plain_map, ataplain_map, sizeof(plain_map));
- memcpy(shift_map, atashift_map, sizeof(shift_map));
+ memcpy(key_maps[0], ataplain_map, sizeof(plain_map));
+ memcpy(key_maps[1], atashift_map, sizeof(plain_map));
+ memcpy(key_maps[4], atactrl_map, sizeof(plain_map));
+ memcpy(key_maps[5], atashift_ctrl_map, sizeof(plain_map));
+ memcpy(key_maps[8], ataalt_map, sizeof(plain_map));
+ /* Atari doesn't have an altgr_map, so we can reuse its memory for
+ atashift_alt_map */
+ memcpy(key_maps[2], atashift_alt_map, sizeof(plain_map));
+ key_maps[9] = key_maps[2];
key_maps[2] = 0; /* ataaltgr_map */
- memcpy(ctrl_map, atactrl_map, sizeof(ctrl_map));
- memcpy(shift_ctrl_map, atashift_ctrl_map, sizeof(shift_ctrl_map));
- memcpy(alt_map, ataalt_map, sizeof(alt_map));
- key_maps[9] = atashift_alt_map;
- memcpy(ctrl_alt_map, atactrl_alt_map, sizeof(ctrl_alt_map));
+ memcpy(key_maps[12], atactrl_alt_map, sizeof(plain_map));
key_maps[13] = atashift_ctrl_alt_map;
keymap_count = 8;
/* say that we don't have an AltGr key */
- mach_keyboard_type = KB_84;
+ keyboard_type = KB_84;
kb_state.state = KEYBOARD;
kb_state.len = 0;
@@ -860,3 +861,8 @@ int atari_kbdrate( struct kbd_repeat *k )
return( 0 );
}
+
+/* for "kbd-reset" cmdline param */
+__initfunc(void atari_kbd_reset_setup(char *str, int *ints))
+{
+}
diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c
index 6b03b96fd..8223ce95c 100644
--- a/arch/m68k/atari/atasound.c
+++ b/arch/m68k/atari/atasound.c
@@ -10,6 +10,9 @@
* License. See the file COPYING in the main directory of this archive
* for more details.
*
+ * 1998-05-31 ++andreas: atari_mksound rewritten to always use the envelope,
+ * no timer, atari_nosound removed.
+ *
*/
@@ -31,22 +34,6 @@
* stuff from the old atasound.c
*/
-
-static void atari_nosound (unsigned long ignored)
-{
- unsigned char tmp;
- unsigned long flags;
-
- /* turn off generator A in mixer control */
- save_flags(flags);
- cli();
- sound_ym.rd_data_reg_sel = 7;
- tmp = sound_ym.rd_data_reg_sel;
- sound_ym.wd_data = tmp | 0x39;
- restore_flags(flags);
-}
-
-
void atari_microwire_cmd (int cmd)
{
tt_microwire.mask = 0x7ff;
@@ -58,90 +45,62 @@ void atari_microwire_cmd (int cmd)
}
-#define PC_FREQ 1192180
+/* PSG base frequency */
#define PSG_FREQ 125000
+/* PSG envelope base frequency times 10 */
+#define PSG_ENV_FREQ_10 78125
-
-void atari_mksound (unsigned int count, unsigned int ticks)
+void atari_mksound (unsigned int hz, unsigned int ticks)
{
- static struct timer_list sound_timer = { NULL, NULL, 0, 0,
- atari_nosound };
- /*
- * Generates sound of some count for some number of clock ticks
- * [count = 1193180 / frequency]
- */
+ /* Generates sound of some frequency for some number of clock
+ ticks. */
unsigned long flags;
unsigned char tmp;
+ int period;
save_flags(flags);
cli();
- if (count == 750 && ticks == HZ/8) {
- /* Special case: These values are used by console.c to
- * generate the console bell. They are cached here and the
- * sound actually generated is somehow special: it uses the
- * generator B and an envelope. No timer is needed therefore
- * and the bell doesn't disturb an other ongoing sound.
- */
+ /* Convert from frequency value to PSG period value (base
+ frequency 125 kHz). */
+ period = PSG_FREQ / hz;
+
+ if (period > 0xfff) period = 0xfff;
- /* set envelope duration to 492 ms */
+ /* Disable generator A in mixer control. */
+ sound_ym.rd_data_reg_sel = 7;
+ tmp = sound_ym.rd_data_reg_sel;
+ tmp |= 011;
+ sound_ym.wd_data = tmp;
+ /* Set generator A frequency to hz. */
+ sound_ym.rd_data_reg_sel = 0;
+ sound_ym.wd_data = period & 0xff;
+ sound_ym.rd_data_reg_sel = 1;
+ sound_ym.wd_data = (period >> 8) & 0xf;
+ if (ticks) {
+ /* Set length of envelope (max 8 sec). */
+ int length = (ticks * PSG_ENV_FREQ_10) / HZ / 10;
+
+ if (length > 0xffff) length = 0xffff;
sound_ym.rd_data_reg_sel = 11;
- sound_ym.wd_data = 0;
+ sound_ym.wd_data = length & 0xff;
sound_ym.rd_data_reg_sel = 12;
- sound_ym.wd_data = 15;
- /* envelope form: max -> min single */
+ sound_ym.wd_data = length >> 8;
+ /* Envelope form: max -> min single. */
sound_ym.rd_data_reg_sel = 13;
- sound_ym.wd_data = 9;
- /* set generator B frequency to 2400 Hz */
- sound_ym.rd_data_reg_sel = 2;
- sound_ym.wd_data = 52;
- sound_ym.rd_data_reg_sel = 3;
sound_ym.wd_data = 0;
- /* set volume of generator B to envelope control */
- sound_ym.rd_data_reg_sel = 9;
+ /* Use envelope for generator A. */
+ sound_ym.rd_data_reg_sel = 8;
sound_ym.wd_data = 0x10;
- /* enable generator B in the mixer control */
- sound_ym.rd_data_reg_sel = 7;
- tmp = sound_ym.rd_data_reg_sel;
- sound_ym.wd_data = (tmp & ~0x02) | 0x38;
-
- restore_flags(flags);
- return;
- }
-
- del_timer( &sound_timer );
-
- if (!count) {
- atari_nosound( 0 );
- }
- else {
-
- /* convert from frequency value
- * to PSG period value (base frequency 125 kHz).
- */
- int period = PSG_FREQ / count;
-
- if (period > 0xfff) period = 0xfff;
-
- /* set generator A frequency to 0 */
- sound_ym.rd_data_reg_sel = 0;
- sound_ym.wd_data = period & 0xff;
- sound_ym.rd_data_reg_sel = 1;
- sound_ym.wd_data = (period >> 8) & 0xf;
- /* turn on generator A in mixer control (but not noise
- * generator!) */
- sound_ym.rd_data_reg_sel = 7;
- tmp = sound_ym.rd_data_reg_sel;
- sound_ym.wd_data = (tmp & ~0x01) | 0x38;
- /* set generator A level to maximum, no envelope */
+ } else {
+ /* Set generator A level to maximum, no envelope. */
sound_ym.rd_data_reg_sel = 8;
sound_ym.wd_data = 15;
-
- if (ticks) {
- sound_timer.expires = jiffies + ticks;
- add_timer( &sound_timer );
- }
}
+ /* Turn on generator A in mixer control. */
+ sound_ym.rd_data_reg_sel = 7;
+ tmp &= ~1;
+ sound_ym.wd_data = tmp;
restore_flags(flags);
}
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 9ea8a4fab..a63e71e08 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -38,6 +38,7 @@
#include <asm/atari_stram.h>
#include <asm/system.h>
#include <asm/machdep.h>
+#include <asm/hwtest.h>
u_long atari_mch_cookie;
u_long atari_mch_type = 0;
@@ -58,6 +59,7 @@ static int atari_get_hardware_list(char *buffer);
extern int atari_keyb_init(void);
extern int atari_kbdrate (struct kbd_repeat *);
extern void atari_kbd_leds (unsigned int);
+extern void atari_kbd_reset_setup(char*, int);
/* atari specific irq functions */
extern void atari_init_IRQ (void);
extern int atari_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
@@ -70,7 +72,6 @@ extern void atari_mksound( unsigned int count, unsigned int ticks );
#ifdef CONFIG_HEARTBEAT
static void atari_heartbeat( int on );
#endif
-extern struct consw fb_con;
/* atari specific timer functions (in time.c) */
extern void atari_sched_init(void (*)(int, void *, struct pt_regs *));
@@ -99,39 +100,15 @@ static char atari_sysrq_xlate[128] =
extern void (*kd_mksound)(unsigned int, unsigned int);
-/* This function tests for the presence of an address, specially a
- * hardware register address. It is called very early in the kernel
- * initialization process, when the VBR register isn't set up yet. On
- * an Atari, it still points to address 0, which is unmapped. So a bus
- * error would cause another bus error while fetching the exception
- * vector, and the CPU would do nothing at all. So we needed to set up
- * a temporary VBR and a vector table for the duration of the test.
+/* I've moved hwreg_present() and hwreg_present_bywrite() out into
+ * mm/hwtest.c, to avoid having multiple copies of the same routine
+ * in the kernel [I wanted them in hp300 and they were already used
+ * in the nubus code. NB: I don't have an Atari so this might (just
+ * conceivably) break something.
+ * I've preserved the #if 0 version of hwreg_present_bywrite() here
+ * for posterity.
+ * -- Peter Maydell <pmaydell@chiark.greenend.org.uk>, 05/1998
*/
-
-__initfunc(static int hwreg_present( volatile void *regp ))
-{
- int ret = 0;
- long save_sp, save_vbr;
- long tmp_vectors[3];
-
- __asm__ __volatile__
- ( "movec %/vbr,%2\n\t"
- "movel #Lberr1,%4@(8)\n\t"
- "movec %4,%/vbr\n\t"
- "movel %/sp,%1\n\t"
- "moveq #0,%0\n\t"
- "tstb %3@\n\t"
- "nop\n\t"
- "moveq #1,%0\n"
- "Lberr1:\n\t"
- "movel %1,%/sp\n\t"
- "movec %2,%/vbr"
- : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
- : "a" (regp), "a" (tmp_vectors)
- );
-
- return( ret );
-}
#if 0
__initfunc(static int
@@ -164,35 +141,6 @@ hwreg_present_bywrite(volatile void *regp, unsigned char val))
}
#endif
-/* Basically the same, but writes a value into a word register, protected
- * by a bus error handler */
-
-__initfunc(static int hwreg_write( volatile void *regp, unsigned short val ))
-{
- int ret;
- long save_sp, save_vbr;
- long tmp_vectors[3];
-
- __asm__ __volatile__
- ( "movec %/vbr,%2\n\t"
- "movel #Lberr2,%4@(8)\n\t"
- "movec %4,%/vbr\n\t"
- "movel %/sp,%1\n\t"
- "moveq #0,%0\n\t"
- "movew %5,%3@\n\t"
- "nop \n\t" /* If this nop isn't present, 'ret' may already be
- * loaded with 1 at the time the bus error
- * happens! */
- "moveq #1,%0\n"
- "Lberr2:\n\t"
- "movel %1,%/sp\n\t"
- "movec %2,%/vbr"
- : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
- : "a" (regp), "a" (tmp_vectors), "g" (val)
- );
-
- return( ret );
-}
/* ++roman: This is a more elaborate test for an SCC chip, since the plain
* Medusa board generates DTACK at the SCC's standard addresses, but a SCC
@@ -302,6 +250,7 @@ __initfunc(void config_atari(void))
mach_keyb_init = atari_keyb_init;
mach_kbdrate = atari_kbdrate;
mach_kbd_leds = atari_kbd_leds;
+ kbd_reset_setup = atari_kbd_reset_setup;
mach_init_IRQ = atari_init_IRQ;
mach_request_irq = atari_request_irq;
mach_free_irq = atari_free_irq;
@@ -315,7 +264,9 @@ __initfunc(void config_atari(void))
#ifdef CONFIG_ATARI_FLOPPY
mach_floppy_setup = atari_floppy_setup;
#endif
- conswitchp = &fb_con;
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
mach_max_dma_address = 0xffffff;
kd_mksound = atari_mksound;
#ifdef CONFIG_MAGIC_SYSRQ
diff --git a/arch/m68k/atari/joystick.c b/arch/m68k/atari/joystick.c
index 82eb85288..1deec9653 100644
--- a/arch/m68k/atari/joystick.c
+++ b/arch/m68k/atari/joystick.c
@@ -15,7 +15,6 @@
#include <asm/atarikb.h>
#include <asm/atari_joystick.h>
-#include <asm/atari_mouse.h>
#include <asm/uaccess.h>
#define MAJOR_NR JOYSTICK_MAJOR
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index de9a96d03..02821ebaf 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -53,7 +53,7 @@
* ++roman:
*
* New version of ST-Ram buffer allocation. Instead of using the
- * 1 MB - 4 KB that remain when the the ST-Ram chunk starts at $1000
+ * 1 MB - 4 KB that remain when the ST-Ram chunk starts at $1000
* (1 MB granularity!), such buffers are reserved like this:
*
* - If the kernel resides in ST-Ram anyway, we can take the buffer
@@ -826,18 +826,23 @@ static int unswap_process( struct mm_struct * mm, unsigned long entry,
unsigned long page, int isswap )
{
struct vm_area_struct* vma;
+ int retval = 0;
/*
* Go through process' page directory.
*/
if (!mm || mm == &init_mm)
return 0;
+ down(&mm->mmap_sem);
for( vma = mm->mmap; vma; vma = vma->vm_next ) {
pgd_t * pgd = pgd_offset(mm, vma->vm_start);
- if (unswap_vma( vma, pgd, entry, page, isswap ))
- return 1;
+ if (unswap_vma( vma, pgd, entry, page, isswap )) {
+ retval = 1;
+ break;
+ }
}
- return 0;
+ up(&mm->mmap_sem);
+ return retval;
}
@@ -954,7 +959,7 @@ static int unswap_by_read( unsigned char *map, unsigned long max,
return( -ENOMEM );
}
DPRINTK( "unswap: reading swap page %lu to %08lx\n", i, page );
- read_swap_page( entry, (char *)page );
+ rw_swap_page( READ, entry, (char *)page, 1 );
for_each_task(p) {
if (unswap_process( p->mm, entry, page, 0 )) {
@@ -1160,7 +1165,7 @@ static unsigned long find_free_region( unsigned long n_pages,
/* setup parameters from command line */
-void stram_swap_setup( char *str, int *ints )
+__initfunc(void stram_swap_setup(char *str, int *ints))
{
if (ints[0] >= 1)
max_swap_size = ((ints[1] < 0 ? 0 : ints[1]) * 1024) & PAGE_MASK;
@@ -1256,7 +1261,7 @@ static struct file_operations stram_fops = {
block_fsync /* fsync */
};
-int stram_device_init( void )
+__initfunc(int stram_device_init(void))
{
if (!MACH_IS_ATARI)
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index 8a3921c8d..79c4f48f2 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -83,7 +83,7 @@ static void mste_write(struct MSTE_RTC *val)
#define RTC_READ(reg) \
({ unsigned char __val; \
- writeb(reg,&tt_rtc.regsel); \
+ (void) writeb(reg,&tt_rtc.regsel); \
__val = tt_rtc.data; \
__val; \
})
diff --git a/arch/m68k/bvme6000/Makefile b/arch/m68k/bvme6000/Makefile
new file mode 100644
index 000000000..e8670c60b
--- /dev/null
+++ b/arch/m68k/bvme6000/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for Linux arch/m68k/bvme6000 source directory
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := bvme6000.o
+O_OBJS := config.o bvmeints.o rtc.o
+#OX_OBJS = ksyms.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/bvme6000/bvmeints.c b/arch/m68k/bvme6000/bvmeints.c
new file mode 100644
index 000000000..a79f5555d
--- /dev/null
+++ b/arch/m68k/bvme6000/bvmeints.c
@@ -0,0 +1,154 @@
+/*
+ * arch/m68k/bvme6000/bvmeints.c
+ *
+ * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk]
+ *
+ * based on amiints.c -- Amiga Linux interrupt handling code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+
+static void bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp);
+
+/*
+ * This should ideally be 4 elements only, for speed.
+ */
+
+static struct {
+ void (*handler)(int, void *, struct pt_regs *);
+ unsigned long flags;
+ void *dev_id;
+ const char *devname;
+ unsigned count;
+} irq_tab[256];
+
+/*
+ * void bvme6000_init_IRQ (void)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ * This function is called during kernel startup to initialize
+ * the bvme6000 IRQ handling routines.
+ */
+
+void bvme6000_init_IRQ (void)
+{
+ int i;
+
+ for (i = 0; i < 256; i++) {
+ irq_tab[i].handler = bvme6000_defhand;
+ irq_tab[i].flags = IRQ_FLG_STD;
+ irq_tab[i].dev_id = NULL;
+ irq_tab[i].devname = NULL;
+ irq_tab[i].count = 0;
+ }
+}
+
+int bvme6000_request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
+{
+ if (irq > 255) {
+ printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
+ return -ENXIO;
+ }
+#if 0
+ /* Nothing special about auto-vectored devices for the BVME6000,
+ * but treat it specially to avoid changes elsewhere.
+ */
+
+ if (irq >= VEC_INT1 && irq <= VEC_INT7)
+ return sys_request_irq(irq - VEC_SPUR, handler, flags,
+ devname, dev_id);
+#endif
+ if (!(irq_tab[irq].flags & IRQ_FLG_STD)) {
+ if (irq_tab[irq].flags & IRQ_FLG_LOCK) {
+ printk("%s: IRQ %d from %s is not replaceable\n",
+ __FUNCTION__, irq, irq_tab[irq].devname);
+ return -EBUSY;
+ }
+ if (flags & IRQ_FLG_REPLACE) {
+ printk("%s: %s can't replace IRQ %d from %s\n",
+ __FUNCTION__, devname, irq, irq_tab[irq].devname);
+ return -EBUSY;
+ }
+ }
+ irq_tab[irq].handler = handler;
+ irq_tab[irq].flags = flags;
+ irq_tab[irq].dev_id = dev_id;
+ irq_tab[irq].devname = devname;
+ return 0;
+}
+
+void bvme6000_free_irq(unsigned int irq, void *dev_id)
+{
+ if (irq > 255) {
+ printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+#if 0
+ if (irq >= VEC_INT1 && irq <= VEC_INT7) {
+ sys_free_irq(irq - VEC_SPUR, dev_id);
+ return;
+ }
+#endif
+ if (irq_tab[irq].dev_id != dev_id)
+ printk("%s: Removing probably wrong IRQ %d from %s\n",
+ __FUNCTION__, irq, irq_tab[irq].devname);
+
+ irq_tab[irq].handler = bvme6000_defhand;
+ irq_tab[irq].flags = IRQ_FLG_STD;
+ irq_tab[irq].dev_id = NULL;
+ irq_tab[irq].devname = NULL;
+}
+
+void bvme6000_process_int (unsigned long vec, struct pt_regs *fp)
+{
+ if (vec > 255)
+ panic ("bvme6000_process_int: Illegal vector %ld", vec);
+ irq_tab[vec].count++;
+ irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
+}
+
+int bvme6000_get_irq_list (char *buf)
+{
+ int i, len = 0;
+
+ for (i = 0; i < 256; i++) {
+ if (irq_tab[i].count)
+ len += sprintf (buf+len, "Vec 0x%02x: %8d %s\n",
+ i, irq_tab[i].count,
+ irq_tab[i].devname ? irq_tab[i].devname : "free");
+ }
+ return len;
+}
+
+
+static void bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp)
+{
+ printk ("Unknown interrupt 0x%02x\n", irq);
+}
+
+void bvme6000_enable_irq (unsigned int irq)
+{
+}
+
+
+void bvme6000_disable_irq (unsigned int irq)
+{
+}
+
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
new file mode 100644
index 000000000..74d15e995
--- /dev/null
+++ b/arch/m68k/bvme6000/config.c
@@ -0,0 +1,453 @@
+/*
+ * arch/m68k/bvme6000/config.c
+ *
+ * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk]
+ *
+ * Based on:
+ *
+ * linux/amiga/config.c
+ *
+ * Copyright (C) 1993 Hamish Macdonald
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#include <stdarg.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/major.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/bvme6000hw.h>
+
+extern void bvme6000_process_int (int level, struct pt_regs *regs);
+extern void bvme6000_init_IRQ (void);
+extern void bvme6000_free_irq (unsigned int, void *);
+extern int bvme6000_get_irq_list (char *);
+extern void bvme6000_enable_irq (unsigned int);
+extern void bvme6000_disable_irq (unsigned int);
+static void bvme6000_get_model(char *model);
+static int bvme6000_get_hardware_list(char *buffer);
+extern int bvme6000_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+extern void bvme6000_sched_init(void (*handler)(int, void *, struct pt_regs *));
+extern int bvme6000_keyb_init(void);
+extern int bvme6000_kbdrate (struct kbd_repeat *);
+extern unsigned long bvme6000_gettimeoffset (void);
+extern void bvme6000_gettod (int *year, int *mon, int *day, int *hour,
+ int *min, int *sec);
+extern int bvme6000_hwclk (int, struct hwclk_time *);
+extern int bvme6000_set_clock_mmss (unsigned long);
+extern void bvme6000_check_partition (struct gendisk *hd, unsigned int dev);
+extern void bvme6000_mksound( unsigned int count, unsigned int ticks );
+extern void bvme6000_reset (void);
+extern void bvme6000_waitbut(void);
+void bvme6000_set_vectors (void);
+
+static unsigned char bcd2bin (unsigned char b);
+static unsigned char bin2bcd (unsigned char b);
+
+/* Save tick handler routine pointer, will point to do_timer() in
+ * kernel/sched.c, called via bvme6000_process_int() */
+
+static void (*tick_handler)(int, void *, struct pt_regs *);
+
+int bvme6000_kbdrate (struct kbd_repeat *k)
+{
+ return 0;
+}
+
+void bvme6000_mksound( unsigned int count, unsigned int ticks )
+{
+}
+
+void bvme6000_reset()
+{
+ volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
+
+ printk ("\r\n\nCalled bvme6000_reset\r\n"
+ "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r");
+ /* The string of returns is to delay the reset until the whole
+ * message is output. */
+ /* Enable the watchdog, via PIT port C bit 4 */
+
+ pit->pcddr |= 0x10; /* WDOG enable */
+
+ while(1)
+ ;
+}
+
+static void bvme6000_get_model(char *model)
+{
+ /* XXX Need to detect if BVME4000 or BVME6000 */
+ sprintf(model, "BVME6000");
+}
+
+
+/* No hardware options on BVME6000? */
+
+static int bvme6000_get_hardware_list(char *buffer)
+{
+ *buffer = '\0';
+ return 0;
+}
+
+
+__initfunc(void config_bvme6000(void))
+{
+ volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
+
+#if 0
+ /* Call bvme6000_set_vectors() so ABORT will work, along with BVMBug
+ * debugger. Note trap_init() will splat the abort vector, but
+ * bvme6000_init_IRQ() will put it back again. Hopefully. */
+
+ bvme6000_set_vectors();
+#endif
+
+ mach_sched_init = bvme6000_sched_init;
+ mach_keyb_init = bvme6000_keyb_init;
+ mach_kbdrate = bvme6000_kbdrate;
+ mach_init_IRQ = bvme6000_init_IRQ;
+ mach_gettimeoffset = bvme6000_gettimeoffset;
+ mach_gettod = bvme6000_gettod;
+ mach_hwclk = bvme6000_hwclk;
+ mach_set_clock_mmss = bvme6000_set_clock_mmss;
+/* mach_mksound = bvme6000_mksound; */
+ mach_reset = bvme6000_reset;
+ mach_free_irq = bvme6000_free_irq;
+ mach_process_int = bvme6000_process_int;
+ mach_get_irq_list = bvme6000_get_irq_list;
+ mach_request_irq = bvme6000_request_irq;
+ enable_irq = bvme6000_enable_irq;
+ disable_irq = bvme6000_disable_irq;
+ mach_get_model = bvme6000_get_model;
+ mach_get_hardware_list = bvme6000_get_hardware_list;
+
+ printk ("Board is %sconfigured as a System Controller\n",
+ *config_reg_ptr & BVME_CONFIG_SW1 ? "" : "not ");
+
+ /* Now do the PIT configuration */
+
+ pit->pgcr = 0x00; /* Unidirectional 8 bit, no handshake for now */
+ pit->psrr = 0x18; /* PIACK and PIRQ fucntions enabled */
+ pit->pacr = 0x00; /* Sub Mode 00, H2 i/p, no DMA */
+ pit->padr = 0x00; /* Just to be tidy! */
+ pit->paddr = 0x00; /* All inputs for now (safest) */
+ pit->pbcr = 0x80; /* Sub Mode 1x, H4 i/p, no DMA */
+ pit->pbdr = 0xbc | (*config_reg_ptr & BVME_CONFIG_SW1 ? 0 : 0x40);
+ /* PRI, SYSCON?, Level3, SCC clks from xtal */
+ pit->pbddr = 0xf3; /* Mostly outputs */
+ pit->pcdr = 0x01; /* PA transceiver disabled */
+ pit->pcddr = 0x03; /* WDOG disable */
+}
+
+
+void bvme6000_abort_int (int irq, void *dev_id, struct pt_regs *fp)
+{
+ unsigned long *new = (unsigned long *)vectors;
+ unsigned long *old = (unsigned long *)0xf8000000;;
+
+ /* Wait for button release */
+ while (*config_reg_ptr & BVME_ABORT_STATUS)
+ ;
+
+ *(new+4) = *(old+4); /* Illegal instruction */
+ *(new+9) = *(old+9); /* Trace */
+ *(new+47) = *(old+47); /* Trap #15 */
+ *(new+0x1f) = *(old+0x1f); /* ABORT switch */
+}
+
+
+static void bvme6000_timer_int (int irq, void *dev_id, struct pt_regs *fp)
+{
+ volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
+ unsigned char msr = rtc->msr & 0xc0;
+
+ rtc->msr = msr | 0x20; /* Ack the interrupt */
+
+ tick_handler(irq, dev_id, fp);
+}
+
+/*
+ * Set up the RTC timer 1 to mode 2, so T1 output toggles every 5ms
+ * (40000 x 125ns). It will interrupt every 10ms, when T1 goes low.
+ * So, when reading the elapsed time, you should read timer1,
+ * subtract it from 39999, and then add 40000 if T1 is high.
+ * That gives you the number of 125ns ticks in to the 10ms period,
+ * so divide by 8 to get the microsecond result.
+ */
+
+void bvme6000_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+{
+ volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
+ unsigned char msr = rtc->msr & 0xc0;
+
+ rtc->msr = 0; /* Ensure timer registers accessible */
+
+ tick_handler = timer_routine;
+ if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0,
+ "timer", bvme6000_timer_int))
+ panic ("Couldn't register timer int");
+
+ rtc->t1cr_omr = 0x04; /* Mode 2, ext clk */
+ rtc->t1msb = 39999 >> 8;
+ rtc->t1lsb = 39999 & 0xff;
+ rtc->irr_icr1 &= 0xef; /* Route timer 1 to INTR pin */
+ rtc->msr = 0x40; /* Access int.cntrl, etc */
+ rtc->pfr_icr0 = 0x80; /* Just timer 1 ints enabled */
+ rtc->irr_icr1 = 0;
+ rtc->t1cr_omr = 0x0a; /* INTR+T1 active lo, push-pull */
+ rtc->t0cr_rtmr &= 0xdf; /* Stop timers in standby */
+ rtc->msr = 0; /* Access timer 1 control */
+ rtc->t1cr_omr = 0x05; /* Mode 2, ext clk, GO */
+
+ rtc->msr = msr;
+
+ if (request_irq(BVME_IRQ_ABORT, bvme6000_abort_int, 0,
+ "abort", bvme6000_abort_int))
+ panic ("Couldn't register abort int");
+}
+
+
+/* This is always executed with interrupts disabled. */
+
+/*
+ * NOTE: Don't accept any readings within 5us of rollover, as
+ * the T1INT bit may be a little slow getting set. There is also
+ * a fault in the chip, meaning that reads may produce invalid
+ * results...
+ */
+
+unsigned long bvme6000_gettimeoffset (void)
+{
+ volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
+ volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
+ unsigned char msr = rtc->msr & 0xc0;
+ unsigned char t1int, t1op;
+ unsigned long v = 800000, ov;
+
+ rtc->msr = 0; /* Ensure timer registers accessible */
+
+ do {
+ ov = v;
+ t1int = rtc->msr & 0x20;
+ t1op = pit->pcdr & 0x04;
+ rtc->t1cr_omr |= 0x40; /* Latch timer1 */
+ v = rtc->t1msb << 8; /* Read timer1 */
+ v |= rtc->t1lsb; /* Read timer1 */
+ } while (t1int != (rtc->msr & 0x20) ||
+ t1op != (pit->pcdr & 0x04) ||
+ abs(ov-v) > 80 ||
+ v > 39960);
+
+ v = 39999 - v;
+ if (!t1op) /* If in second half cycle.. */
+ v += 40000;
+ v /= 8; /* Convert ticks to microseconds */
+ if (t1int)
+ v += 10000; /* Int pending, + 10ms */
+ rtc->msr = msr;
+
+ return v;
+}
+
+extern void bvme6000_gettod (int *year, int *mon, int *day, int *hour,
+ int *min, int *sec)
+{
+ volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
+ unsigned char msr = rtc->msr & 0xc0;
+
+ rtc->msr = 0; /* Ensure clock accessible */
+
+ do { /* Loop until we get a reading with a stable seconds field */
+ *sec = bcd2bin (rtc->bcd_sec);
+ *min = bcd2bin (rtc->bcd_min);
+ *hour = bcd2bin (rtc->bcd_hr);
+ *day = bcd2bin (rtc->bcd_dom);
+ *mon = bcd2bin (rtc->bcd_mth);
+ *year = bcd2bin (rtc->bcd_year);
+ } while (bcd2bin (rtc->bcd_sec) != *sec);
+
+ rtc->msr = msr;
+}
+
+static unsigned char bcd2bin (unsigned char b)
+{
+ return ((b>>4)*10 + (b&15));
+}
+
+static unsigned char bin2bcd (unsigned char b)
+{
+ return (((b/10)*16) + (b%10));
+}
+
+
+/*
+ * Looks like op is non-zero for setting the clock, and zero for
+ * reading the clock.
+ *
+ * struct hwclk_time {
+ * unsigned sec; 0..59
+ * unsigned min; 0..59
+ * unsigned hour; 0..23
+ * unsigned day; 1..31
+ * unsigned mon; 0..11
+ * unsigned year; 00...
+ * int wday; 0..6, 0 is Sunday, -1 means unknown/don't set
+ * };
+ */
+
+int bvme6000_hwclk(int op, struct hwclk_time *t)
+{
+ volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
+ unsigned char msr = rtc->msr & 0xc0;
+
+ rtc->msr = 0x40; /* Ensure clock and real-time-mode-register
+ * are accessible */
+ if (op)
+ { /* Write.... */
+ rtc->t0cr_rtmr = t->year%4;
+ rtc->bcd_tenms = 0;
+ rtc->bcd_sec = bin2bcd(t->sec);
+ rtc->bcd_min = bin2bcd(t->min);
+ rtc->bcd_hr = bin2bcd(t->hour);
+ rtc->bcd_dom = bin2bcd(t->day);
+ rtc->bcd_mth = bin2bcd(t->mon + 1);
+ rtc->bcd_year = bin2bcd(t->year%100);
+ if (t->wday >= 0)
+ rtc->bcd_dow = bin2bcd(t->wday+1);
+ rtc->t0cr_rtmr = t->year%4 | 0x08;
+ }
+ else
+ { /* Read.... */
+ do {
+ t->sec = bcd2bin(rtc->bcd_sec);
+ t->min = bcd2bin(rtc->bcd_min);
+ t->hour = bcd2bin(rtc->bcd_hr);
+ t->day = bcd2bin(rtc->bcd_dom);
+ t->mon = bcd2bin(rtc->bcd_mth)-1;
+ t->year = bcd2bin(rtc->bcd_year);
+ if (t->year < 70)
+ t->year += 100;
+ t->wday = bcd2bin(rtc->bcd_dow)-1;
+ } while (t->sec != bcd2bin(rtc->bcd_sec));
+ }
+
+ rtc->msr = msr;
+
+ return 0;
+}
+
+/*
+ * Set the minutes and seconds from seconds value 'nowtime'. Fail if
+ * clock is out by > 30 minutes. Logic lifted from atari code.
+ * Algorithm is to wait for the 10ms register to change, and then to
+ * wait a short while, and then set it.
+ */
+
+int bvme6000_set_clock_mmss (unsigned long nowtime)
+{
+ int retval = 0;
+ short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
+ unsigned char rtc_minutes, rtc_tenms;
+ volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
+ unsigned char msr = rtc->msr & 0xc0;
+ unsigned long flags;
+ volatile int i;
+
+ rtc->msr = 0; /* Ensure clock accessible */
+ rtc_minutes = bcd2bin (rtc->bcd_min);
+
+ if ((rtc_minutes < real_minutes
+ ? real_minutes - rtc_minutes
+ : rtc_minutes - real_minutes) < 30)
+ {
+ save_flags(flags);
+ cli();
+ rtc_tenms = rtc->bcd_tenms;
+ while (rtc_tenms == rtc->bcd_tenms)
+ ;
+ for (i = 0; i < 1000; i++)
+ ;
+ rtc->bcd_min = bin2bcd(real_minutes);
+ rtc->bcd_sec = bin2bcd(real_seconds);
+ restore_flags(flags);
+ }
+ else
+ retval = -1;
+
+ rtc->msr = msr;
+
+ return retval;
+}
+
+
+int bvme6000_keyb_init (void)
+{
+ return 0;
+}
+
+/*------------------- Serial console stuff ------------------------*/
+
+static void bvme_scc_write(struct console *co, const char *str, unsigned cnt);
+
+
+void bvme6000_init_console_port (struct console *co, int cflag)
+{
+ co->write = bvme_scc_write;
+}
+
+
+static void scc_delay (void)
+{
+ int n;
+ char i;
+
+ for (n = 0; n < 20; n++)
+ i = *(volatile char *)0;
+}
+
+static void scc_write (char ch)
+{
+ volatile char *p = (volatile char *)BVME_SCC_A_ADDR;
+
+ do {
+ scc_delay();
+ }
+ while (!(*p & 4));
+ scc_delay();
+ *p = 8;
+ scc_delay();
+ *p = ch;
+}
+
+
+static void bvme_scc_write (struct console *co, const char *str, unsigned count)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ while (count--)
+ {
+ if (*str == '\n')
+ scc_write ('\r');
+ scc_write (*str++);
+ }
+ restore_flags(flags);
+}
+
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
new file mode 100644
index 000000000..ca9f677f8
--- /dev/null
+++ b/arch/m68k/bvme6000/rtc.c
@@ -0,0 +1,175 @@
+/*
+ * Real Time Clock interface for Linux on the BVME6000
+ *
+ * Based on the PC driver by Paul Gortmaker.
+ */
+
+#define RTC_VERSION "1.00"
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */
+#include <asm/bvme6000hw.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/setup.h>
+
+/*
+ * We sponge a minor off of the misc major. No need slurping
+ * up another valuable major dev number for this. If you add
+ * an ioctl, make sure you don't conflict with SPARC's RTC
+ * ioctls.
+ */
+
+#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10)
+#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10)
+
+static unsigned char days_in_mo[] =
+{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+static char rtc_status = 0;
+
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
+ unsigned char msr;
+ unsigned long flags;
+ struct rtc_time wtime;
+
+ switch (cmd) {
+ case RTC_RD_TIME: /* Read the time/date from RTC */
+ {
+ save_flags(flags);
+ cli();
+ /* Ensure clock and real-time-mode-register are accessible */
+ msr = rtc->msr & 0xc0;
+ rtc->msr = 0x40;
+ do {
+ wtime.tm_sec = BCD2BIN(rtc->bcd_sec);
+ wtime.tm_min = BCD2BIN(rtc->bcd_min);
+ wtime.tm_hour = BCD2BIN(rtc->bcd_hr);
+ wtime.tm_mday = BCD2BIN(rtc->bcd_dom);
+ wtime.tm_mon = BCD2BIN(rtc->bcd_mth)-1;
+ wtime.tm_year = BCD2BIN(rtc->bcd_year);
+ if (wtime.tm_year < 70)
+ wtime.tm_year += 100;
+ wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1;
+ } while (wtime.tm_sec != BCD2BIN(rtc->bcd_sec));
+ rtc->msr = msr;
+ restore_flags(flags);
+ return copy_to_user((void *)arg, &wtime, sizeof wtime) ?
+ -EFAULT : 0;
+ }
+ case RTC_SET_TIME: /* Set the RTC */
+ {
+ unsigned char leap_yr;
+ struct rtc_time rtc_tm;
+
+ if (!suser())
+ return -EACCES;
+
+ if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
+ sizeof(struct rtc_time)))
+ return -EFAULT;
+
+ leap_yr = ((!(rtc_tm.tm_year % 4) && (rtc_tm.tm_year % 100)) || !(rtc_tm.tm_year % 400));
+
+ if ((rtc_tm.tm_mon > 12) || (rtc_tm.tm_mday == 0))
+ return -EINVAL;
+
+ if (rtc_tm.tm_mday > (days_in_mo[rtc_tm.tm_mon] + ((rtc_tm.tm_mon == 2) && leap_yr)))
+ return -EINVAL;
+
+ if ((rtc_tm.tm_hour >= 24) || (rtc_tm.tm_min >= 60) || (rtc_tm.tm_sec >= 60))
+ return -EINVAL;
+
+ save_flags(flags);
+ cli();
+ /* Ensure clock and real-time-mode-register are accessible */
+ msr = rtc->msr & 0xc0;
+ rtc->msr = 0x40;
+
+ rtc->t0cr_rtmr = rtc_tm.tm_year%4;
+ rtc->bcd_tenms = 0;
+ rtc->bcd_sec = BIN2BCD(rtc_tm.tm_sec);
+ rtc->bcd_min = BIN2BCD(rtc_tm.tm_min);
+ rtc->bcd_hr = BIN2BCD(rtc_tm.tm_hour);
+ rtc->bcd_dom = BIN2BCD(rtc_tm.tm_mday);
+ rtc->bcd_mth = BIN2BCD(rtc_tm.tm_mon + 1);
+ rtc->bcd_year = BIN2BCD(rtc_tm.tm_year%100);
+ if (rtc_tm.tm_wday >= 0)
+ rtc->bcd_dow = BIN2BCD(rtc_tm.tm_wday+1);
+ rtc->t0cr_rtmr = rtc_tm.tm_year%4 | 0x08;
+
+ rtc->msr = msr;
+ restore_flags(flags);
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+/*
+ * We enforce only one user at a time here with the open/close.
+ * Also clear the previous interrupt data on an open, and clean
+ * up things on a close.
+ */
+
+static int rtc_open(struct inode *inode, struct file *file)
+{
+ if(rtc_status)
+ return -EBUSY;
+
+ rtc_status = 1;
+ return 0;
+}
+
+static int rtc_release(struct inode *inode, struct file *file)
+{
+ rtc_status = 0;
+ return 0;
+}
+
+/*
+ * The various file operations we support.
+ */
+
+static struct file_operations rtc_fops = {
+ NULL,
+ NULL,
+ NULL, /* No write */
+ NULL, /* No readdir */
+ NULL,
+ rtc_ioctl,
+ NULL, /* No mmap */
+ rtc_open,
+ rtc_release
+};
+
+static struct miscdevice rtc_dev=
+{
+ RTC_MINOR,
+ "rtc",
+ &rtc_fops
+};
+
+__initfunc(int rtc_DP8570A_init(void))
+{
+ if (!MACH_IS_BVME6000)
+ return -ENODEV;
+
+ printk(KERN_INFO "DP8570A Real Time Clock Driver v%s\n", RTC_VERSION);
+ misc_register(&rtc_dev);
+ return 0;
+}
+
diff --git a/arch/m68k/config.in b/arch/m68k/config.in
index 8ad01e60b..33164f7bc 100644
--- a/arch/m68k/config.in
+++ b/arch/m68k/config.in
@@ -19,7 +19,7 @@ fi
endmenu
mainmenu_option next_comment
-comment 'Platform dependant setup'
+comment 'Platform dependent setup'
bool 'Amiga support' CONFIG_AMIGA
bool 'Atari support' CONFIG_ATARI
@@ -30,13 +30,19 @@ if [ "$CONFIG_ATARI" = "y" ]; then
fi
fi
bool 'Macintosh support' CONFIG_MAC
+if [ "$CONFIG_MAC" = "y" ]; then
+ define_bool CONFIG_NUBUS y
+fi
bool 'Apollo support' CONFIG_APOLLO
bool 'VME (Motorola and BVM) support' CONFIG_VME
if [ "$CONFIG_VME" = "y" ]; then
bool 'MVME162, 166 and 167 support' CONFIG_MVME16x
-# bool 'BVME4000 and BVME6000 support' CONFIG_BVME6000
+ bool 'BVME4000 and BVME6000 support' CONFIG_BVME6000
+fi
+bool 'HP9000/300 support' CONFIG_HP300
+if [ "$CONFIG_HP300" = "y" ]; then
+ bool 'DIO bus support' CONFIG_DIO
fi
-
if [ "$CONFIG_PCI" = "y" ]; then
bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
fi
@@ -54,9 +60,15 @@ if [ "$CONFIG_M68020" = "n" -a "$CONFIG_M68030" = "n" ]; then
bool 'Use 68060 specific optimizations' CONFIG_OPTIMIZE_060
fi
fi
+if [ "$CONFIG_VME" = "y" -a "$CONFIG_M68060" = "y" ]; then
+ define_bool CONFIG_060_WRITETHROUGH y
+fi
bool 'Advanced processor options' CONFIG_ADVANCED_CPU
if [ "$CONFIG_ADVANCED_CPU" = "y" ]; then
bool 'Use read-modify-write instructions' CONFIG_RMW_INSNS
+ if [ "$CONFIG_M68060" = "y" -a "$CONFIG_VME" = "n" ]; then
+ bool 'Use write-through caching for 68060 supervisor accesses' CONFIG_060_WRITETHROUGH
+ fi
fi
endmenu
@@ -72,12 +84,10 @@ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
if [ "$CONFIG_AMIGA" = "y" ]; then
- bool 'Amiga AutoConfig Identification' CONFIG_ZORRO
-# bool 'Amiga GSP (TMS340x0) support' CONFIG_AMIGA_GSP
-# if [ "$CONFIG_AMIGA_GSP" = "y" ]; then
-# bool 'DMI Resolver support' CONFIG_GSP_RESOLVER
-# bool 'A2410 support' CONFIG_GSP_A2410
-# fi
+ bool 'Amiga Zorro (AutoConfig) bus support' CONFIG_ZORRO
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool 'Amiga 1200/600 PCMCIA support' CONFIG_AMIGA_PCMCIA
+ fi
fi
if [ "$CONFIG_ATARI" = "y" ]; then
bool 'Support for ST-RAM as swap space' CONFIG_STRAM_SWAP
@@ -85,73 +95,17 @@ if [ "$CONFIG_ATARI" = "y" ]; then
fi
if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then
bool 'Use power LED as a heartbeat' CONFIG_HEARTBEAT
-fi
-endmenu
-
-#
-# Block device driver configuration
-#
-mainmenu_option next_comment
-comment 'Floppy, IDE, and other block devices'
-
-if [ "$CONFIG_AMIGA" = "y" ]; then
- tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY
-fi
-if [ "$CONFIG_ATARI" = "y" ]; then
- tristate 'Atari floppy support' CONFIG_ATARI_FLOPPY
-fi
-if [ "$CONFIG_MAC" = "y" ]; then
- tristate 'Macintosh IWM floppy support' CONFIG_MAC_FLOPPY
-fi
-#Normal floppy disk support' CONFIG_BLK_DEV_FD
-
-tristate 'Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support' CONFIG_BLK_DEV_IDE
-if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
- dep_tristate ' Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE
- dep_tristate ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE
- dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
- dep_tristate ' Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
- dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE
- if [ "$CONFIG_AMIGA" = "y" ]; then
- bool ' Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool ' Buddha/Catweasel IDE interface support' CONFIG_BLK_DEV_BUDDHA
- bool ' Amiga IDE Doubler support' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE
- fi
- fi
- if [ "$CONFIG_ATARI" = "y" ]; then
- bool ' Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE
- fi
-fi
-if [ "$CONFIG_AMIGA" = "y" ]; then
- tristate 'Amiga Zorro II ramdisk support' CONFIG_AMIGA_Z2RAM
-fi
-if [ "$CONFIG_ATARI" = "y" ]; then
- tristate 'Atari ACSI support' CONFIG_ATARI_ACSI
- if [ "$CONFIG_ATARI_ACSI" != "n" ]; then
- comment 'Some devices (e.g. CD jukebox) support multiple LUNs'
- bool 'Probe all LUNs on each ACSI device' CONFIG_ACSI_MULTI_LUN
- dep_tristate 'Atari SLM laser printer support' CONFIG_ATARI_SLM $CONFIG_ATARI_ACSI
+else
+ if [ "$CONFIG_HP300" = "y" ]; then
+# We have a dedicated heartbeat LED. :-)
+ define_bool CONFIG_HEARTBEAT y
fi
fi
-
-comment 'Additional Block Devices'
-
-tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
-bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
-if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
- tristate ' Linear (append) mode' CONFIG_MD_LINEAR
- tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED
-fi
-if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then
- bool ' Boot support (linear, striped)' CONFIG_MD_BOOT
-fi
-tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
-if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
- bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
-fi
+bool '/proc/hardware support' CONFIG_PROC_HARDWARE
endmenu
+source drivers/block/Config.in
+
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
@@ -185,26 +139,33 @@ comment 'SCSI low-level drivers'
if [ "$CONFIG_AMIGA" = "y" ]; then
tristate 'A3000 WD33C93A support' CONFIG_A3000_SCSI
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool 'A4000T SCSI support' CONFIG_A4000T_SCSI
+ fi
+fi
+if [ "$CONFIG_ZORRO" = "y" ]; then
tristate 'A2091 WD33C93A support' CONFIG_A2091_SCSI
tristate 'GVP Series II WD33C93A support' CONFIG_GVP11_SCSI
bool 'CyberStorm SCSI support' CONFIG_CYBERSTORM_SCSI
- bool 'CyberStorm SCSI Mk II support' CONFIG_CYBERSTORMII_SCSI
+ bool 'CyberStorm Mk II SCSI support' CONFIG_CYBERSTORMII_SCSI
bool 'Blizzard 2060 SCSI support' CONFIG_BLZ2060_SCSI
bool 'Blizzard 1230IV/1260 SCSI support' CONFIG_BLZ1230_SCSI
bool 'Fastlane SCSI support' CONFIG_FASTLANE_SCSI
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool 'A4000T SCSI support' CONFIG_A4000T_SCSI
bool 'A4091 SCSI support' CONFIG_A4091_SCSI
bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI
-# bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
+ bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
# bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI
fi
fi
if [ "$CONFIG_ATARI" = "y" ]; then
dep_tristate 'Atari native SCSI support' CONFIG_ATARI_SCSI $CONFIG_SCSI
- bool 'Long delays for Toshiba CD-ROMs' CONFIG_ATARI_SCSI_TOSHIBA_DELAY
- if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_HADES" = "y" ]; then
- bool 'Hades SCSI DMA emulator (EXPERIMENTAL)' CONFIG_TT_DMA_EMUL
+ if [ "$CONFIG_ATARI_SCSI" != "n" ]; then
+ bool ' Long delays for Toshiba CD-ROMs' CONFIG_ATARI_SCSI_TOSHIBA_DELAY
+ bool ' Reset SCSI-devices at boottime' CONFIG_ATARI_SCSI_RESET_BOOT
+ if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_HADES" = "y" ]; then
+ bool ' Hades SCSI DMA emulator (EXPERIMENTAL)' CONFIG_TT_DMA_EMUL
+ fi
fi
fi
if [ "$CONFIG_MAC" = "y" ]; then
@@ -216,6 +177,10 @@ if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then
bool 'NCR53C710 SCSI driver for MVME16x' CONFIG_MVME16x_SCSI
fi
+if [ "$CONFIG_VME" = "y" -a "$CONFIG_BVME6000" = "y" ]; then
+ bool 'NCR53C710 SCSI driver for BVME6000' CONFIG_BVME6000_SCSI
+fi
+
endmenu
fi
@@ -243,14 +208,26 @@ if [ ! "$CONFIG_PPP" = "n" ]; then
comment 'CCP compressors for PPP are only built as modules.'
fi
tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
-if [ "$CONFIG_AMIGA" = "y" ]; then
+if [ "$CONFIG_ZORRO" = "y" ]; then
tristate 'Ariadne support' CONFIG_ARIADNE
tristate 'A2065 support' CONFIG_A2065
tristate 'Hydra support' CONFIG_HYDRA
fi
+if [ "$CONFIG_AMIGA_PCMCIA" = "y" ]; then
+ tristate 'PCMCIA NE2000 support' CONFIG_APNE
+fi
if [ "$CONFIG_APOLLO" = "y" ] ; then
tristate 'Apollo 3c505 support' CONFIG_APOLLO_ELPLUS
fi
+if [ "$CONFIG_MAC" = "y" ]; then
+ bool 'Mac NS 8390 based ethernet cards' CONFIG_DAYNAPORT
+fi
+if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then
+ bool 'MVME16x Ethernet support' CONFIG_MVME16x_NET
+fi
+if [ "$CONFIG_VME" = "y" -a "$CONFIG_BVME6000" = "y" ]; then
+ bool 'BVME6000 Ethernet support' CONFIG_BVME6000_NET
+fi
if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'Atari Lance support' CONFIG_ATARILANCE
if [ "$CONFIG_ATARI_ACSI" != "n" ]; then
@@ -258,12 +235,6 @@ if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'PAMsNet support' CONFIG_ATARI_PAMSNET
fi
fi
-if [ "$CONFIG_MAC" = "y" ]; then
- bool 'Mac NS 8390 based ethernet cards' CONFIG_DAYNAPORT
-fi
-if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then
- bool 'MVME16x Ethernet support' CONFIG_APRICOT
-fi
fi
endmenu
@@ -273,7 +244,10 @@ source fs/Config.in
if [ "$CONFIG_VME" = "n" ]; then
define_bool CONFIG_FB y
+ mainmenu_option next_comment
+ comment 'Console drivers'
source drivers/video/Config.in
+ endmenu
fi
source fs/nls/Config.in
@@ -286,16 +260,17 @@ if [ "$CONFIG_VME" = "n" ]; then
if [ "$CONFIG_VT" = "y" ]; then
bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE
fi
- define_bool CONFIG_FB_CONSOLE y
fi
if [ "$CONFIG_ATARI" = "y" ]; then
define_bool CONFIG_NVRAM y
fi
-tristate 'Parallel printer support' CONFIG_PRINTER
-if [ "$CONFIG_AMIGA" = "y" ]; then
+tristate 'Parallel printer support' CONFIG_M68K_PRINTER
+if [ "$CONFIG_ZORRO" = "y" ]; then
dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_PRINTER
+fi
+if [ "$CONFIG_AMIGA" = "y" ]; then
tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE
fi
if [ "$CONFIG_ATARI" = "y" ]; then
@@ -317,26 +292,39 @@ if [ "$CONFIG_ATARI" = "y" ]; then
fi
if [ "$CONFIG_AMIGA" = "y" ]; then
tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL
+ bool 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET
+fi
+if [ "$CONFIG_ZORRO" = "y" ]; then
tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT
dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT
tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY
- bool 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET
fi
-if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then
+if [ "$CONFIG_MAC" = "y" ]; then
+ bool 'Mac SCC serial support' CONFIG_MAC_SCC
+fi
+if [ "$CONFIG_HP300" = "y" -a "$CONFIG_DIO" = "y" ]; then
+ tristate 'HP DCA serial support' CONFIG_HPDCA
+fi
+if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o \
+ "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" ]; then
if [ "$CONFIG_ATARI_MFPSER" = "y" -o "$CONFIG_ATARI_SCC" = "y" -o \
- "$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \
- "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" ]; then
+ "$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_MAC_SCC" = "y" -o \
+ "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \
+ "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" -o \
+ "$CONFIG_HPDCA" = "y" ]; then
bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE
fi
fi
-if [ "$CONFIG_MAC" = "y" ]; then
- bool 'Mac SCC serial support' CONFIG_MAC_SCC
-fi
if [ "$CONFIG_VME" = "y" ]; then
define_bool CONFIG_SERIAL_CONSOLE y
- bool 'CD2401 support for MVME166/7 serial ports' CONFIG_SERIAL167
- bool 'SCC support for MVME162 serial ports' CONFIG_MVME162_SCC
+ if [ "$CONFIG_MVME16x" = "y" ]; then
+ bool 'CD2401 support for MVME166/7 serial ports' CONFIG_SERIAL167
+ bool 'SCC support for MVME162 serial ports' CONFIG_MVME162_SCC
+ fi
+ if [ "$CONFIG_BVME6000" = "y" ]; then
+ bool 'SCC support for BVME6000 serial ports' CONFIG_BVME6000_SCC
+ fi
fi
if [ "$CONFIG_APOLLO" = "y" ]; then
bool 'Support for DN serial port (dummy)' CONFIG_SERIAL
@@ -348,9 +336,10 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then
bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
bool ' Software Watchdog' CONFIG_SOFT_WATCHDOG
fi
-bool 'Support for user misc device modules' CONFIG_UMISC
-if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then
- define_bool CONFIG_ABSTRACT_CONSOLE y
+if [ "$CONFIG_VME" = "y" ]; then
+ define_bool CONFIG_UMISC y
+else
+ bool 'Support for user misc device modules' CONFIG_UMISC
fi
if [ "$CONFIG_ATARI" = "y" ]; then
bool 'Enhanced Real Time Clock Support' CONFIG_RTC
@@ -370,10 +359,6 @@ mainmenu_option next_comment
comment 'Kernel hacking'
#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
-bool 'Kernel profiling support' CONFIG_PROFILE
-if [ "$CONFIG_PROFILE" = "y" ]; then
- int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
-fi
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
bool 'Remote debugging support' CONFIG_KGDB
endmenu
diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig
index 6ce3991d4..e866b5dd3 100644
--- a/arch/m68k/defconfig
+++ b/arch/m68k/defconfig
@@ -45,6 +45,9 @@ CONFIG_ZORRO=y
# CONFIG_AMIGA_GSP is not set
# CONFIG_GSP_RESOLVER is not set
# CONFIG_GSP_A2410 is not set
+# CONFIG_AMIGA_PCMCIA is not set
+# CONFIG_HEARTBEAT is not set
+CONFIG_PROC_HARDWARE=y
#
# Block device driver configuration
@@ -133,6 +136,8 @@ CONFIG_GVP11_SCSI=y
# CONFIG_A4091_SCSI is not set
# CONFIG_WARPENGINE_SCSI is not set
CONFIG_ATARI_SCSI=y
+# CONFIG_ATARI_SCSI_TOSHIBA_DELAY is not set
+# CONFIG_ATARI_SCSI_RESET_BOOT is not set
#
# Network device support
@@ -144,6 +149,7 @@ CONFIG_NETDEVICES=y
# CONFIG_ARIADNE is not set
# CONFIG_A2065 is not set
# CONFIG_HYDRA is not set
+# CONFIG_APNE is not set
# CONFIG_ATARILANCE is not set
# CONFIG_ATARI_BIONET is not set
# CONFIG_ATARI_PAMSNET is not set
@@ -190,7 +196,7 @@ CONFIG_NLS_CODEPAGE_437=y
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
-# CONFIG_PRINTER is not set
+# CONFIG_M68K_PRINTER is not set
CONFIG_AMIGAMOUSE=y
CONFIG_ATARIMOUSE=y
CONFIG_AMIGA_BUILTIN_SERIAL=y
@@ -211,5 +217,4 @@ CONFIG_AMIGA_BUILTIN_SERIAL=y
#
# Kernel hacking
#
-# CONFIG_PROFILE is not set
CONFIG_SCSI_CONSTANTS=y
diff --git a/arch/m68k/fpsp040/res_func.S b/arch/m68k/fpsp040/res_func.S
index 9a81bde1d..66e42d749 100644
--- a/arch/m68k/fpsp040/res_func.S
+++ b/arch/m68k/fpsp040/res_func.S
@@ -1889,7 +1889,7 @@ dp_over:
|
| Input: a0 points to a normalized number in internal extended format
| d0 is the round precision (=1 for sgl; =2 for dbl)
-| d1 is the the single precision or double precision
+| d1 is the single precision or double precision
| denorm threshold
|
| Output: (In the format for dest_sgl or dest_dbl)
diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S
index 719bcc9ce..1e4d0cf72 100644
--- a/arch/m68k/fpsp040/skeleton.S
+++ b/arch/m68k/fpsp040/skeleton.S
@@ -378,14 +378,12 @@ fpsp_done:
beq Lnotkern
rte
Lnotkern:
- tstl SYMBOL_NAME(need_resched)
- bne Lmustsched
- rte
-Lmustsched:
SAVE_ALL_INT
GET_CURRENT(%d0)
- bral SYMBOL_NAME(ret_from_exception) | deliver signals, reschedule etc..
-
+ tstl %curptr@(LTASK_NEEDRESCHED)
+ jne SYMBOL_NAME(ret_from_exception) | deliver signals,
+ | reschedule etc..
+ RESTORE_ALL
|
| mem_write --- write to user or supervisor address space
diff --git a/arch/m68k/fpsp040/slogn.S b/arch/m68k/fpsp040/slogn.S
index b660acd0d..20c5bae9f 100644
--- a/arch/m68k/fpsp040/slogn.S
+++ b/arch/m68k/fpsp040/slogn.S
@@ -17,7 +17,7 @@
| result is provably monotonic in double precision.
|
| Speed: The program slogn takes approximately 190 cycles for input
-| argument X such that |X-1| >= 1/16, which is the the usual
+| argument X such that |X-1| >= 1/16, which is the usual
| situation. For those arguments, slognp1 takes approximately
| 210 cycles. For the less common arguments, the program will
| run no worse than 10% slower.
diff --git a/arch/m68k/fpsp040/ssin.S b/arch/m68k/fpsp040/ssin.S
index 978941f4e..96e0e7141 100644
--- a/arch/m68k/fpsp040/ssin.S
+++ b/arch/m68k/fpsp040/ssin.S
@@ -21,7 +21,7 @@
| result is provably monotonic in double precision.
|
| Speed: The programs sSIN and sCOS take approximately 150 cycles for
-| input argument X such that |X| < 15Pi, which is the the usual
+| input argument X such that |X| < 15Pi, which is the usual
| situation. The speed for sSINCOS is approximately 190 cycles.
|
| Algorithm:
diff --git a/arch/m68k/fpsp040/stan.S b/arch/m68k/fpsp040/stan.S
index b7a880a2a..6bd2dda60 100644
--- a/arch/m68k/fpsp040/stan.S
+++ b/arch/m68k/fpsp040/stan.S
@@ -16,7 +16,7 @@
| result is provably monotonic in double precision.
|
| Speed: The program sTAN takes approximately 170 cycles for
-| input argument X such that |X| < 15Pi, which is the the usual
+| input argument X such that |X| < 15Pi, which is the usual
| situation.
|
| Algorithm:
diff --git a/arch/m68k/fpsp040/sto_res.S b/arch/m68k/fpsp040/sto_res.S
index 634b10855..6be6dd5ac 100644
--- a/arch/m68k/fpsp040/sto_res.S
+++ b/arch/m68k/fpsp040/sto_res.S
@@ -3,7 +3,7 @@
|
| Takes the result and puts it in where the user expects it.
| Library functions return result in fp0. If fp0 is not the
-| users destination register then fp0 is moved to the the
+| users destination register then fp0 is moved to the
| correct floating-point destination register. fp0 and fp1
| are then restored to the original contents.
|
diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile
new file mode 100644
index 000000000..a59cede94
--- /dev/null
+++ b/arch/m68k/hp300/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for Linux arch/m68k/hp300 source directory
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := hp300.o
+O_OBJS := ksyms.o config.o ints.o time.o reboot.o hil.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/hp300/README.hp300 b/arch/m68k/hp300/README.hp300
new file mode 100644
index 000000000..47073fbd4
--- /dev/null
+++ b/arch/m68k/hp300/README.hp300
@@ -0,0 +1,14 @@
+HP300 notes
+-----------
+
+The Linux/HP web page is at <http://www.tazenda.demon.co.uk/phil/linux-hp/>
+
+Currently only 9000/340 machines have been tested. Any amount of RAM should
+work now but I've only tried 16MB and 12MB.
+
+The serial console is probably broken at the moment but the Topcat/HIL keyboard
+combination seems to work for me. Your mileage may vary.
+
+The LANCE driver works after a fashion but only if you reset the chip before
+every packet. This doesn't make for very speedy operation.
+
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c
new file mode 100644
index 000000000..065430ca5
--- /dev/null
+++ b/arch/m68k/hp300/config.c
@@ -0,0 +1,78 @@
+/*
+ * linux/arch/m68k/hp300/config.c
+ *
+ * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
+ *
+ * This file contains the HP300-specific initialisation code. It gets
+ * called by setup.c.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <asm/machdep.h>
+#include <asm/blinken.h>
+#include <asm/io.h> /* readb() and writeb() */
+#include <asm/hwtest.h> /* hwreg_present() */
+
+#include "ints.h"
+#include "time.h"
+
+extern void hp300_reset(void);
+extern void hp300_hil_init(void);
+
+#ifdef CONFIG_HEARTBEAT
+static void hp300_pulse(int x)
+{
+ if (x)
+ blinken_leds(0xfe);
+ else
+ blinken_leds(0xff);
+}
+#endif
+
+static int hp300_kbdrate(struct kbd_repeat *k)
+{
+ return 0;
+}
+
+static void hp300_kbd_leds(unsigned int leds)
+{
+}
+
+__initfunc(void config_hp300(void))
+{
+ mach_sched_init = hp300_sched_init;
+ mach_keyb_init = hp300_hil_init;
+ mach_kbdrate = hp300_kbdrate;
+ mach_kbd_leds = hp300_kbd_leds;
+ mach_init_IRQ = hp300_init_IRQ;
+ mach_request_irq = hp300_request_irq;
+ mach_free_irq = hp300_free_irq;
+#if 0
+ mach_get_model = hp300_get_model;
+ mach_get_irq_list = hp300_get_irq_list;
+#endif
+ mach_gettimeoffset = hp300_gettimeoffset;
+#if 0
+ mach_gettod = hp300_gettod;
+#endif
+ mach_reset = hp300_reset;
+#ifdef CONFIG_HEARTBEAT
+ mach_heartbeat = hp300_pulse;
+#endif
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+ mach_max_dma_address = 0xffffffff;
+}
+
+/* for "kbd-reset" cmdline param */
+__initfunc(void kbd_reset_setup(char *str, int *ints))
+{
+}
diff --git a/arch/m68k/hp300/hil.c b/arch/m68k/hp300/hil.c
new file mode 100644
index 000000000..76d45b4d1
--- /dev/null
+++ b/arch/m68k/hp300/hil.c
@@ -0,0 +1,250 @@
+/*
+ * linux/arch/m68k/hp300/hil.c
+ *
+ * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
+ *
+ * HP300 Human Interface Loop driver. This handles the keyboard and mouse.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/keyboard.h>
+#include <linux/kbd_ll.h>
+#include <asm/io.h>
+#include <asm/hwtest.h>
+#include <asm/ptrace.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#define HILBASE 0xf0428000
+#define HIL_DATA 0x1
+#define HIL_CMD 0x3
+
+#define HIL_BUSY 0x02
+#define HIL_DATA_RDY 0x01
+
+#define hil_busy() (readb(HILBASE + HIL_CMD) & HIL_BUSY)
+#define hil_data_available() (readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
+#define hil_status() (readb(HILBASE + HIL_CMD))
+#define hil_command(x) do { writeb((x), HILBASE + HIL_CMD); } while (0)
+#define hil_read_data() (readb(HILBASE + HIL_DATA))
+#define hil_write_data(x) do { writeb((x), HILBASE + HIL_DATA); } while (0)
+
+#define HIL_SETARD 0xA0 /* set auto-repeat delay */
+#define HIL_SETARR 0xA2 /* set auto-repeat rate */
+#define HIL_SETTONE 0xA3 /* set tone generator */
+#define HIL_CNMT 0xB2 /* clear nmi */
+#define HIL_INTON 0x5C /* Turn on interrupts. */
+#define HIL_INTOFF 0x5D /* Turn off interrupts. */
+#define HIL_TRIGGER 0xC5 /* trigger command */
+#define HIL_STARTCMD 0xE0 /* start loop command */
+#define HIL_TIMEOUT 0xFE /* timeout */
+#define HIL_READTIME 0x13 /* Read real time register */
+
+#define HIL_READBUSY 0x02 /* internal "busy" register */
+#define HIL_READKBDLANG 0x12 /* read keyboard language code */
+#define HIL_READKBDSADR 0xF9
+#define HIL_WRITEKBDSADR 0xE9
+#define HIL_READLPSTAT 0xFA
+#define HIL_WRITELPSTAT 0xEA
+#define HIL_READLPCTRL 0xFB
+#define HIL_WRITELPCTRL 0xEB
+
+#define HIL_IRQ 1
+
+static u_short hp_plain_map[NR_KEYS] __initdata = {
+ 0xf200, 0xf01b, 0xf20e, 0xf700, 0xf700, 0xf700, 0xf702, 0xf036,
+ 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009,
+ 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
+ 0xfb62, 0xfb76, 0xf063, 0xfb78, 0xfb7a, 0xf702, 0xfb61, 0xfb73,
+ 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
+ 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xfb63, 0xfb76,
+ 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200,
+ 0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf104,
+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
+ 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
+ 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf038, 0xf039, 0xf030, 0xf200, 0xf200, 0xf008, 0xf200, 0xf200,
+ 0xfb69, 0xfb6f, 0xfb70, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
+ 0xfb6a, 0xfb6b, 0xfb6c, 0xf305, 0xf306, 0xf00d, 0xf302, 0xf303,
+ 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xfb6e, 0xf020, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
+};
+
+static u_short hp_shift_map[NR_KEYS] __initdata = {
+ 0xf200, 0xf01b, 0xf20e, 0xf700, 0xf700, 0xf700, 0xf002, 0xf036,
+ 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009,
+ 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
+ 0xfb62, 0xfb76, 0xf063, 0xfb78, 0xfb7a, 0xf702, 0xfb61, 0xfb73,
+ 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
+ 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xfb63, 0xfb76,
+ 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200,
+ 0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf104,
+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
+ 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
+ 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf038, 0xf039, 0xf030, 0xf200, 0xf200, 0xf008, 0xf200, 0xf200,
+ 0xfb69, 0xfb6f, 0xfb70, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
+ 0xfb6a, 0xfb6b, 0xfb6c, 0xf305, 0xf306, 0xf00d, 0xf302, 0xf303,
+ 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xfb6e, 0xf020, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
+};
+
+static u_short hp_ctrl_map[NR_KEYS] __initdata = {
+ 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
+ 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
+ 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
+ 0xf00f, 0xf010, 0xf003, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
+ 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
+ 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
+ 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf07f, 0xf700, 0xf200,
+ 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
+ 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
+ 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf200, 0xf1ff, 0xf202, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
+ 0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
+ 0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
+};
+
+struct {
+ unsigned char s, c;
+ int valid;
+} hil_last;
+
+#define hil_getlast(s,c) do { s = hil_last.s; c = hil_last.c; hil_last.valid = 0; } while (0)
+
+struct {
+ unsigned char data[16];
+ unsigned int ptr;
+} poll;
+
+unsigned char curdev = 0;
+
+static void poll_finished(void)
+{
+ switch (poll.data[0])
+ {
+ case 0x40:
+ {
+ unsigned char scode = (poll.data[1] >> 1) | ((poll.data[1] & 1)?0x80:0);
+#if 0
+ if (scode & 0x80)
+ printk("[%02x]", scode & 0x7f);
+#endif
+ handle_scancode(scode);
+ }
+ break;
+ }
+ curdev = 0;
+}
+
+static inline void handle_status(unsigned char s, unsigned char c)
+{
+ if (c & 0x8) {
+ /* End of block */
+ if (c & 0x10)
+ poll_finished();
+ } else {
+ if (c & 0x10) {
+ if (curdev)
+ poll_finished(); /* just in case */
+ curdev = c & 7;
+ poll.ptr = 0;
+ }
+ }
+}
+
+static inline void handle_data(unsigned char s, unsigned char c)
+{
+ if (curdev)
+ poll.data[poll.ptr++] = c;
+}
+
+/*
+ * Handle HIL interrupts.
+ */
+
+static void hil_interrupt(int irq, void *handle, struct pt_regs *regs)
+{
+ unsigned char s, c;
+ s = hil_status(); c = hil_read_data();
+ switch (s >> 4)
+ {
+ case 0x5:
+ handle_status(s, c);
+ break;
+ case 0x6:
+ handle_data(s, c);
+ break;
+ case 0x4:
+ hil_last.s = s;
+ hil_last.c = c;
+ mb();
+ hil_last.valid = 1;
+ break;
+ }
+}
+
+/*
+ * Send a command to the HIL
+ */
+
+static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
+{
+ unsigned long flags;
+ save_flags(flags); cli();
+ while (hil_busy());
+ hil_command(cmd);
+ while (len--) {
+ while (hil_busy());
+ hil_write_data(*(data++));
+ }
+ restore_flags(flags);
+}
+
+/*
+ * Initialise HIL.
+ */
+
+__initfunc(void hp300_hil_init(void))
+{
+ unsigned char s, c, kbid;
+ unsigned int n = 0;
+
+ memcpy(key_maps[0], hp_plain_map, sizeof(plain_map));
+ memcpy(key_maps[1], hp_shift_map, sizeof(plain_map));
+ memcpy(key_maps[4], hp_ctrl_map, sizeof(plain_map));
+
+ if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
+ return; /* maybe this can happen */
+
+ request_irq(HIL_IRQ, hil_interrupt, 0, "HIL", NULL);
+
+ /* Turn on interrupts */
+ hil_do(HIL_INTON, NULL, 0);
+
+ /* Look for keyboards */
+ hil_do(HIL_READKBDSADR, NULL, 0);
+ while (!hil_last.valid) {
+ if (n++ > 1000) {
+ printk("HIL: timed out, assuming no keyboard present.\n");
+ return;
+ }
+ mb();
+ }
+ hil_getlast(s, c);
+ if (c == 0) {
+ printk("HIL: no keyboard present.\n");
+ return;
+ }
+ for (kbid = 0; (kbid < 8) && ((c & (1<<kbid)) == 0); kbid++);
+ printk("HIL: keyboard found at id %d\n", kbid);
+ /* set it to raw mode */
+ c = 0;
+ hil_do(HIL_WRITEKBDSADR, &c, 1);
+}
diff --git a/arch/m68k/hp300/ints.c b/arch/m68k/hp300/ints.c
new file mode 100644
index 000000000..9f1a1a6a5
--- /dev/null
+++ b/arch/m68k/hp300/ints.c
@@ -0,0 +1,47 @@
+/*
+ * linux/arch/m68k/hp300/ints.c
+ *
+ * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
+ *
+ * This file contains the HP300-specific interrupt handling. There
+ * isn't much here -- we only use the autovector interrupts and at the
+ * moment everything difficult is handled by the generic code.
+ */
+
+#include <asm/ptrace.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include "ints.h"
+
+static void hp300_nmi_handler(int irq, void *dev_id, struct pt_regs *fp)
+{
+ extern void hp300_reset(void);
+ printk("RESET pressed - self destruct sequence initiated.\n");
+ hp300_reset();
+}
+
+int hp300_request_irq(unsigned int irq,
+ void (*handler) (int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
+{
+ return sys_request_irq(irq, handler, flags, devname, dev_id);
+}
+
+void hp300_free_irq(unsigned int irq, void *dev_id)
+{
+ sys_free_irq(irq, dev_id);
+}
+
+__initfunc(void hp300_init_IRQ(void))
+{
+ /* IPL6 - NMI (keyboard reset) */
+ sys_request_irq(7, hp300_nmi_handler, IRQ_FLG_STD, "NMI", hp300_nmi_handler);
+}
diff --git a/arch/m68k/hp300/ints.h b/arch/m68k/hp300/ints.h
new file mode 100644
index 000000000..38b62b61b
--- /dev/null
+++ b/arch/m68k/hp300/ints.h
@@ -0,0 +1,6 @@
+extern void hp300_init_IRQ(void);
+extern void (*hp300_handlers[8])(int, void *, struct pt_regs *);
+extern void hp300_free_irq(unsigned int irq, void *dev_id);
+extern int hp300_request_irq(unsigned int irq,
+ void (*handler) (int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id);
diff --git a/arch/m68k/hp300/ksyms.c b/arch/m68k/hp300/ksyms.c
new file mode 100644
index 000000000..820283076
--- /dev/null
+++ b/arch/m68k/hp300/ksyms.c
@@ -0,0 +1,9 @@
+/*
+ * linux/arch/m68k/hp300/ksyms.c
+ *
+ * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
+ *
+ * This file contains the HP300-specific kernel symbols. None yet. :-)
+ */
+
+#include <linux/module.h>
diff --git a/arch/m68k/hp300/reboot.S b/arch/m68k/hp300/reboot.S
new file mode 100644
index 000000000..aaecdbda2
--- /dev/null
+++ b/arch/m68k/hp300/reboot.S
@@ -0,0 +1,35 @@
+/*
+ * linux/arch/m68k/hp300/reboot.S
+ *
+ * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
+ *
+ * Do the dirty work of rebooting the machine. Basically we need to undo all the
+ * good stuff that head.S did when we started up. The caches and MMU must be
+ * disabled and then we jump back to the PROM. This is a bit gruesome but we put
+ * a brave face on it.
+ */
+
+/* XXX Doesn't work yet. Not sure why and can't be bothered to fix it at the moment. */
+
+ .globl hp300_reset
+hp300_reset:
+ .chip 68030
+ oriw #0x0700,%sr /* cli() */
+ movel hp300_phys_ram_base, %d1
+ movel #0, %d0
+ movec %d0, %vbr /* reset vector table */
+ lea zero, %a0
+ lea 1f, %a1
+ add %d1, %a0
+ add %d1, %a1
+ pmove %tc, %a0@
+ bclr #7, %a0@
+ pmove %a0@, %tc /* goodbye MMU */
+ jmp %a1@
+1: movel #0x808, %d0
+ movec %d0, %cacr /* cache off */
+ moveb #0, 0x1ffff
+ movel #0x1a4, %a0
+ jmp %a0@
+
+zero: .quad 0
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
new file mode 100644
index 000000000..2a60c5621
--- /dev/null
+++ b/arch/m68k/hp300/time.c
@@ -0,0 +1,62 @@
+/*
+ * linux/arch/m68k/hp300/time.c
+ *
+ * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
+ *
+ * This file contains the HP300-specific time handling code.
+ */
+
+#include <asm/ptrace.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include "ints.h"
+
+/* Clock hardware definitions */
+
+#define CLOCKBASE 0xf05f8000
+
+#define CLKCR1 0x1
+#define CLKCR2 0x3
+#define CLKCR3 CLKCR1
+#define CLKSR CLKCR2
+#define CLKMSB1 0x5
+#define CLKMSB2 0x9
+#define CLKMSB3 0xD
+
+unsigned long hp300_gettimeoffset (void)
+{
+ return 0L;
+}
+
+static void hp300_tick(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long tmp;
+ void (*vector)(int, void *, struct pt_regs *) = dev_id;
+ readb(CLOCKBASE + CLKSR);
+ asm volatile ("movpw %1@(5),%0" : "=r" (tmp) : "a" (CLOCKBASE));
+ vector(irq, NULL, regs);
+}
+
+__initfunc(void hp300_sched_init(void (*vector)(int, void *, struct pt_regs *)))
+{
+ unsigned int intval = (10000 / 4) - 1;
+
+ writeb(0x1, CLOCKBASE + CLKCR2); /* select CR1 */
+ writeb(0x1, CLOCKBASE + CLKCR1); /* reset */
+
+ asm volatile(" movpw %0,%1@(5)" : : "d" (intval), "a" (CLOCKBASE));
+
+ sys_request_irq(6, hp300_tick, IRQ_FLG_STD, "timer tick", vector);
+
+ writeb(0x1, CLOCKBASE + CLKCR2); /* select CR1 */
+ writeb(0x40, CLOCKBASE + CLKCR1); /* enable irq */
+}
+
diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h
new file mode 100644
index 000000000..a081903ee
--- /dev/null
+++ b/arch/m68k/hp300/time.h
@@ -0,0 +1,4 @@
+extern void hp300_sched_init(void (*vector)(int, void *, struct pt_regs *));
+extern unsigned long hp300_gettimeoffset (void);
+
+
diff --git a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S
index 629208409..cde14e120 100644
--- a/arch/m68k/ifpsp060/iskeleton.S
+++ b/arch/m68k/ifpsp060/iskeleton.S
@@ -72,14 +72,12 @@ _060_isp_done:
beq Lnotkern
rte
Lnotkern:
- tstl SYMBOL_NAME(need_resched)
- bne Lmustsched
- rte
-Lmustsched:
SAVE_ALL_INT
-
GET_CURRENT(%d0)
- bral SYMBOL_NAME(ret_from_exception) | deliver signals, reschedule etc..
+ tstl %curptr@(LTASK_NEEDRESCHED)
+ jne SYMBOL_NAME(ret_from_exception) | deliver signals,
+ | reschedule etc..
+ RESTORE_ALL
|
| _060_real_chk():
diff --git a/arch/m68k/kernel/bios32.c b/arch/m68k/kernel/bios32.c
index a1dc77f33..b1322261a 100644
--- a/arch/m68k/kernel/bios32.c
+++ b/arch/m68k/kernel/bios32.c
@@ -33,7 +33,6 @@
* been removed in this version.
*/
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/malloc.h>
#include <linux/mm.h>
@@ -49,7 +48,7 @@
#define GB (1024*MB)
#define MAJOR_REV 0
-#define MINOR_REV 0
+#define MINOR_REV 1
/*
* Base addresses of the PCI memory and I/O areas on the Hades.
@@ -264,12 +263,14 @@ __initfunc(static void disable_dev(struct pci_dev *dev))
#define MAX(val1, val2) ( ((val1) > (val2)) ? val1 : val2)
-__initfunc(static void layout_dev(struct pci_dev *dev))
+__initfunc(static void layout_dev(struct pci_dev *dev, unsigned long pci_mem_base,
+ unsigned long pci_io_base))
{
struct pci_bus *bus;
unsigned short cmd;
unsigned int base, mask, size, reg;
unsigned int alignto;
+ int i;
/*
* Skip video cards for the time being.
@@ -283,7 +284,7 @@ __initfunc(static void layout_dev(struct pci_dev *dev))
bus = dev->bus;
pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
- for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4)
+ for (reg = PCI_BASE_ADDRESS_0, i = 0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++)
{
/*
* Figure out how much space and of what type this
@@ -297,6 +298,7 @@ __initfunc(static void layout_dev(struct pci_dev *dev))
if (!base)
{
/* this base-address register is unused */
+ dev->base_address[i] = 0;
continue;
}
@@ -322,6 +324,7 @@ __initfunc(static void layout_dev(struct pci_dev *dev))
io_base = base + size;
pcibios_write_config_dword(bus->number, dev->devfn,
reg, base | 0x1);
+ dev->base_address[i] = (pci_io_base + base) | 1;
DBG_DEVS(("layout_dev: IO address: %lX\n", base));
}
else
@@ -369,6 +372,7 @@ __initfunc(static void layout_dev(struct pci_dev *dev))
mem_base = base + size;
pcibios_write_config_dword(bus->number, dev->devfn,
reg, base);
+ dev->base_address[i] = pci_mem_base + base;
}
}
@@ -396,7 +400,8 @@ __initfunc(static void layout_dev(struct pci_dev *dev))
bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class));
}
-__initfunc(static void layout_bus(struct pci_bus *bus))
+__initfunc(static void layout_bus(struct pci_bus *bus, unsigned long pci_mem_base,
+ unsigned long pci_io_base))
{
struct pci_dev *dev;
@@ -438,7 +443,7 @@ __initfunc(static void layout_bus(struct pci_bus *bus))
for (dev = bus->devices; dev; dev = dev->sibling)
{
if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
- layout_dev(dev);
+ layout_dev(dev, pci_mem_base, pci_io_base);
}
}
@@ -507,8 +512,7 @@ int pcibios_present(void)
return 0;
}
-__initfunc(unsigned long pcibios_init(unsigned long mem_start,
- unsigned long mem_end))
+__initfunc(void pcibios_init(void))
{
printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
@@ -516,7 +520,8 @@ __initfunc(unsigned long pcibios_init(unsigned long mem_start,
printk("...NOT modifying existing PCI configuration\n");
#endif
- return mem_start;
+ pci_mem_base = 0x80000000;
+ pci_io_base = 0xB0000000;
}
/*
@@ -555,26 +560,39 @@ __initfunc(static inline void hades_fixup(void))
}
}
-__initfunc(unsigned long pcibios_fixup(unsigned long mem_start,
- unsigned long mem_end))
+__initfunc(void pcibios_fixup(void))
{
#if PCI_MODIFY
+ unsigned long orig_mem_base, orig_io_base;
+
+ orig_mem_base = pci_mem_base;
+ orig_io_base = pci_io_base;
+ pci_mem_base = 0;
+ pci_io_base = 0;
+
/*
* Scan the tree, allocating PCI memory and I/O space.
*/
- layout_bus(&pci_root);
-#endif
+ layout_bus(&pci_root, orig_mem_base, orig_io_base);
- pci_mem_base = 0x80000000;
- pci_io_base = 0xB0000000;
+ pci_mem_base = orig_mem_base;
+ pci_io_base = orig_io_base;
+#endif
/*
* Now is the time to do all those dirty little deeds...
*/
hades_fixup();
+}
+
+__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+{
+}
- return mem_start;
+__initfunc(char *pcibios_setup(char *str))
+{
+ return str;
}
#endif /* CONFIG_PCI */
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 1c157c26a..eba9842cf 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -114,7 +114,7 @@ SYMBOL_NAME_LABEL(ret_from_exception)
| kernel stack, otherwise stack overflow can occur during
| heavy interupt load
andw #ALLOWINT,%sr
- tstl SYMBOL_NAME(need_resched)
+ tstl %curptr@(LTASK_NEEDRESCHED)
jne SYMBOL_NAME(reschedule)
cmpl #SYMBOL_NAME(task),%curptr | task[0] cannot have signals
jeq 2f
@@ -579,6 +579,14 @@ SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_pread) /* 180 */
.long SYMBOL_NAME(sys_pwrite)
.long SYMBOL_NAME(sys_lchown);
+ .long SYMBOL_NAME(sys_getcwd)
+ .long SYMBOL_NAME(sys_capget)
+ .long SYMBOL_NAME(sys_capset) /* 185 */
+ .long SYMBOL_NAME(sys_sigaltstack)
+ .long SYMBOL_NAME(sys_sendfile)
+ .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
+ .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
+
.rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
.long SYMBOL_NAME(sys_ni_syscall)
.endr
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 1f3795a7c..e98f39fa8 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -17,6 +17,7 @@
** 95/11/18 Richard Hirst: Added MVME166 support
** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with
** Magnum- and FX-alternate ram
+** 98/04/25 Phil Blundell: added HP300 support
**
** This file is subject to the terms and conditions of the GNU General Public
** License. See the file README.legal in the main directory of this archive
@@ -73,10 +74,25 @@
#include <asm/pgtable.h>
.globl SYMBOL_NAME(kernel_pg_dir), SYMBOL_NAME(kpt)
-.globl SYMBOL_NAME(availmem), SYMBOL_NAME(mvme_bdid_ptr)
+.globl SYMBOL_NAME(availmem)
.globl SYMBOL_NAME(m68k_pgtable_cachemode)
.globl SYMBOL_NAME(kernel_pmd_table), SYMBOL_NAME(swapper_pg_dir)
+#if defined(CONFIG_MVME16x)
+.globl SYMBOL_NAME(mvme_bdid_ptr)
+#endif
+
+/*
+ * Added m68k_supervisor_cachemode for 68060 boards where some drivers
+ * need writethrough caching for supervisor accesses. Drivers known to
+ * be effected are 53c7xx.c and apricot.c (when used on VME boards).
+ * Richard Hirst.
+ */
+
+#ifdef CONFIG_060_WRITETHROUGH
+.globl SYMBOL_NAME(m68k_supervisor_cachemode)
+#endif
+
D6B_0460 = 16 /* indicates 680[46]0 in d6 */
D6B_060 = 17 /* indicates 68060 in d6 */
D6F_040 = 1<<D6B_0460
@@ -146,12 +162,23 @@ TABLENR_16MB = 64 /* same for 16 MB */
#define is_not_amiga(lab) moveq &MACH_AMIGA,%d7; cmpl %d4,%d7; jne lab
#define is_not_atari(lab) moveq &MACH_ATARI,%d7; cmpl %d4,%d7; jne lab
#define is_not_mvme16x(lab) moveq &MACH_MVME16x,%d7; cmpl %d4,%d7; jne lab
+#define is_not_bvme6000(lab) moveq &MACH_BVME6000,%d7; cmpl %d4,%d7; jne lab
+#define is_not_hp300(lab) moveq &MACH_HP300,%d7 ; cmpl %d4,%d7; jne lab
#define is_040_or_060(lab) btst &D6B_0460,%d6; jne lab
#define is_not_040_or_060(lab) btst &D6B_0460,%d6; jeq lab
#define is_060(lab) btst &D6B_060,%d6; jne lab
#define is_not_060(lab) btst &D6B_060,%d6; jeq lab
+/* On the HP300 we use the on-board LEDs for debug output before
+ the console is running. Writing a 1 bit turns the corresponding LED
+ _off_ - on the 340 bit 7 is towards the back panel of the machine. */
+#ifdef CONFIG_HP300
+#define leds(x) is_not_hp300(42f) ; moveb #(x),%d7 ; jbsr Lset_leds; 42:
+#else
+#define leds(x)
+#endif
+
.text
ENTRY(_stext)
/*
@@ -164,6 +191,7 @@ ENTRY(_stext)
.long MACH_AMIGA, AMIGA_BOOTI_VERSION
.long MACH_ATARI, ATARI_BOOTI_VERSION
.long MACH_MVME16x, MVME16x_BOOTI_VERSION
+ .long MACH_BVME6000, BVME6000_BOOTI_VERSION
.long 0
1: jra SYMBOL_NAME(_start)
@@ -224,6 +252,22 @@ ENTRY(_start)
movew %d6,%d0
movel %d0,%a0@ /* save cache mode for page tables */
+ /*
+ * If this is a 68060 board using drivers with cache coherency
+ * problems, then supervisor memory accesses need to be write-through
+ * also; otherwise, we want copyback.
+ */
+
+#if defined(CONFIG_060_WRITETHROUGH)
+ is_not_060(Lset_norm)
+ jra 1f
+Lset_norm:
+ move.w #_PAGE_CACHE040,%d0
+1:
+ lea %pc@(SYMBOL_NAME(m68k_supervisor_cachemode)),%a0
+ movel %d0,%a0@
+#endif
+
/*
* raise interrupt level
*/
@@ -386,7 +430,12 @@ Lnotypetest:
movel %a3,%a0
movel %d5,%a1
- addw #_PAGE_GLOBAL040+_PAGE_CACHE040+_PAGE_PRESENT+_PAGE_ACCESSED,%a1
+#if defined(CONFIG_060_WRITETHROUGH)
+ addw #_PAGE_GLOBAL040+_PAGE_PRESENT+_PAGE_ACCESSED,%a1
+ addl m68k_supervisor_cachemode,%a1
+#else
+ addw #_PAGE_GLOBAL040+_PAGE_CACHE040+_PAGE_PRESENT+_PAGE_ACCESSED,%a1
+#endif
movew #(PAGE_TABLE_SIZE*TABLENR_4MB)-1,%d1
movel #PAGESIZE,%d2
1: movel %a1,%a0@+
@@ -424,6 +473,9 @@ Lnotypetest:
* of %a2 are forgotten.
*/
Lnot040:
+
+ leds(0x4)
+
/*
* Do any machine specific page table initializations.
*/
@@ -615,6 +667,21 @@ Lspata68040:
Lnotatari:
#endif
+#ifdef CONFIG_HP300
+ is_not_hp300(Lnothp300)
+
+/* On the HP300, we map the ROM, INTIO and DIO regions (phys. 0x00xxxxxx)
+ by mapping 32MB from 0xf0xxxxxx -> 0x00xxxxxx) using an 030 early
+ termination page descriptor. The ROM mapping is needed because the LEDs
+ are mapped there too. */
+
+ movel #_PAGE_NOCACHE030+_PAGE_PRESENT+_PAGE_ACCESSED,%d0
+ movel %d0,%a5@(0x78<<2)
+
+Lnothp300:
+
+#endif
+
#if defined(CONFIG_MVME16x)
is_not_mvme16x(Lnot16x)
@@ -639,6 +706,25 @@ Lnotatari:
Lnot16x:
#endif
+#if defined(CONFIG_BVME6000)
+ is_not_bvme6000(Lnotbvm)
+
+ /*
+ * On BVME6000 we have already created kernel page tables for
+ * 4MB of RAM at address 0, so now need to do a transparent
+ * mapping of the top of memory space. Make it 0.5GByte for now.
+ */
+
+ movel #0xe01f0000,%d2 /* logical address base */
+ orw #0xa040,%d2 /* add in magic bits */
+ .long 0x4e7b2005 /* movec d2,ittr1 */
+ .long 0x4e7b2007 /* movec d2,dttr1 */
+ .long 0x4e7b2004 /* movec d2,ittr0 */
+ .long 0x4e7b2006 /* movec d2,dttr0 */
+
+Lnotbvm:
+#endif
+
/*
* Setup a transparent mapping of the physical memory we are executing in.
*
@@ -647,6 +733,7 @@ Lnot16x:
*/
Lmapphys:
putc('J')
+ leds(0x8)
#ifdef CONFIG_AMIGA
is_not_amiga(Lmapphysnotamiga)
@@ -853,6 +940,80 @@ Lmapphysnot16x:
#endif
+#if defined(CONFIG_HP300)
+ is_not_hp300(Lmapphysnothp300)
+
+/*
+ * Physical RAM is at 0xff000000. We want to map the kernel at 0x00000000.
+ * In order to avoid disaster when we enable the MMU we need to make a
+ * transparent mapping of the RAM we're executing out of as well.
+ */
+ /*
+ * save physaddr of phys mem in register a3
+ */
+
+ .chip 68030
+ lea %pc@(Lmmu),%a3
+ movel %d5,%d0
+ andl #0xff000000,%d0 /* logical address base */
+ orw #TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0
+ movel %d0,%a3@
+ pmove %a3@,%tt0
+ /* no limit, 4byte descriptors */
+ movel #0x80000002,%a3@
+ movel %a5,%a3@(4)
+ pmove %a3@,%srp
+ pmove %a3@,%crp
+ pflusha
+ /*
+ * enable,super root enable,4096 byte pages,7 bit root index,
+ * 7 bit pointer index, 6 bit page table index.
+ */
+ movel #0x82c07760,%a3@
+ pmove %a3@,%tc /* enable the MMU */
+ jmp 1f
+1:
+ .chip 68k
+
+ /*
+ * Fix up the custom register to point to the new location of the LEDs.
+ */
+ lea %pc@(Lcustom),%a1
+ movel #0xf0000000,%a1@
+
+ /*
+ * Energise the FPU and caches.
+ */
+ orl #0x64, 0xf05f400c
+
+Lmapphysnothp300:
+
+#endif
+
+#if defined(CONFIG_BVME6000)
+ is_not_bvme6000(Lmapphysnotbvm)
+ /*
+ * save physaddr of phys mem in register a3
+ */
+ moveq #'L',%d7
+ jbsr Lserial_putc
+
+ .word 0xf4d8 /* CINVA I/D */
+ .word 0xf518 /* pflusha */
+ .long 0x4e7bd807 /* movec a5,srp */
+ .long 0x4e7bd806 /* movec a5,urp */
+ movel #(TC_ENABLE+TC_PAGE4K),%d0
+ /*
+ * this value is also ok for the 68060, we don`t use the cache
+ * mode/protection defaults
+ */
+ .long 0x4e7b0003 /* movec d0,tc (enable the MMU) */
+ jra LdoneMMUenable /* branch to continuation of startup */
+
+Lmapphysnotbvm:
+
+#endif
+
LdoneMMUenable:
/*
@@ -861,6 +1022,7 @@ LdoneMMUenable:
*/
putc('M')
+ leds(0x10)
/*
* d5 contains physaddr of kernel start
@@ -917,6 +1079,7 @@ Lcache68060:
/* jump to the kernel start */
putr()
+ leds(0x55)
subl %a6,%a6 /* clear a6 for gdb */
jbsr SYMBOL_NAME(start_kernel)
@@ -998,6 +1161,11 @@ LMFP_UDR = 0xfffa2f
#endif
#endif
+#if defined (CONFIG_BVME6000)
+BVME_SCC_CTRL_A = 0xffb0000b
+BVME_SCC_DATA_A = 0xffb0000f
+#endif
+
/*
* Serial port output support.
*/
@@ -1062,6 +1230,17 @@ Lserial_init:
9:
rts
+#ifdef CONFIG_HP300
+/* Set LEDs to %d7 */
+ .even
+Lset_leds:
+ moveml %a0/%a1,%sp@-
+ movel %pc@(Lcustom),%a1
+ moveb %d7,%a1@(0x1ffff)
+ moveml %sp@+,%a0/%a1
+ rts
+#endif
+
/*
* Output character in d7 on serial port.
* d7 thrashed.
@@ -1073,6 +1252,16 @@ Lserial_putc:
jne 2f
moveb %d7,%sp@-
.long 0x4e4f0020
+ jra 9f
+2:
+#endif
+#ifdef CONFIG_BVME6000
+ cmpil #MACH_BVME6000,%d4
+ jne 2f
+1: btst #2,BVME_SCC_CTRL_A
+ jeq 1b
+ moveb %d7,BVME_SCC_DATA_A
+ jra 9f
2:
#endif
#ifdef CONFIG_AMIGA
@@ -1199,5 +1388,11 @@ SYMBOL_NAME_LABEL(availmem)
.long 0
SYMBOL_NAME_LABEL(m68k_pgtable_cachemode)
.long 0
+#ifdef CONFIG_060_WRITETHROUGH
+SYMBOL_NAME_LABEL(m68k_supervisor_cachemode)
+ .long 0
+#endif
+#if defined(CONFIG_MVME16x)
SYMBOL_NAME_LABEL(mvme_bdid_ptr)
.long 0
+#endif
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index a9109ab0a..20e39f17f 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -31,6 +31,7 @@
#include <linux/errno.h>
#include <linux/init.h>
+#include <asm/setup.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/traps.h>
@@ -212,7 +213,7 @@ static void dummy_free_irq(unsigned int irq, void *dev_id)
asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
{
- if (vec >= VEC_INT1 && vec <= VEC_INT7) {
+ if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) {
vec -= VEC_SPUR;
kstat.irqs[0][vec]++;
irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
diff --git a/arch/m68k/kernel/kgdb.c b/arch/m68k/kernel/kgdb.c
new file mode 100644
index 000000000..cdbd250cd
--- /dev/null
+++ b/arch/m68k/kernel/kgdb.c
@@ -0,0 +1,1194 @@
+/*
+ * arch/m68k/kernel/kgdb.c -- Stub for GDB remote debugging protocol
+ *
+ * Originally written by Glenn Engel, Lake Stevens Instrument Division
+ *
+ * Contributed by HP Systems
+ *
+ * Modified for SPARC by Stu Grossman, Cygnus Support.
+ * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
+ * Modified and extended for Linux/68k by Roman Hodek
+ *
+ * Send complaints, suggestions etc. to
+ * <Roman.Hodek@informatik.uni-erlangen.de>
+ *
+ * Copyright (C) 1996-97 Roman Hodek
+ */
+
+/*
+ * kgdb usage notes:
+ * -----------------
+ *
+ * If you select CONFIG_KGDB in the configuration, the kernel will be built
+ * with different gccc flags: "-g" is added to get debug infos, and
+ * "-fomit-frame-pointer" is omitted to make debugging easier. Since the
+ * resulting kernel will be quite big (approx. > 7 MB), it will be stripped
+ * before compresion. Such a kernel will behave just as usually, except if
+ * given a "debug=<device>" command line option. (Only serial devices are
+ * allowed for <device>, i.e. no printers or the like; possible values are
+ * machine depedend and are the same as for the usual debug device, the one
+ * for logging kernel messages.) If that option is given and the device can be
+ * initialized, the kernel will connect to the remote gdb in trap_init(). The
+ * serial parameters are fixed to 8N1 and 9600bps, for easyness of
+ * implementation.
+ *
+ * Of course, you need a remote machine a suitable gdb there. I.e., it must
+ * have support for a m68k-linux target built in. If the remote machine
+ * doesn't run Linux/68k itself, you have to build a cross gdb. This is done
+ * by
+ * ./configure --target=m68k-linux
+ * in the gdb source directory. Until gdb comes with m68k-linux support by
+ * default, you have to apply some patches before. The remote debugging
+ * protocol itself is always built into gdb anyway, so you don't have to take
+ * special care about it.
+ *
+ * To start a debugging session, start that gdb with the debugging kernel
+ * image (the one with the symbols, vmlinux.debug) named on the command line.
+ * This file will be used by gdb to get symbol and debugging infos about the
+ * kernel. Next, select remote debug mode by
+ * target remote <device>
+ * where <device> is the name of the serial device over which the debugged
+ * machine is connected. Maybe you have to adjust the baud rate by
+ * set remotebaud <rate>
+ * or also other parameters with stty:
+ * shell stty ... </dev/...
+ * If the kernel to debug has already booted, it waited for gdb and now
+ * connects, and you'll see a breakpoint being reported. If the kernel isn't
+ * running yet, start it now. The order of gdb and the kernel doesn't matter.
+ * Another thing worth knowing about in the getting-started phase is how to
+ * debug the remote protocol itself. This is activated with
+ * set remotedebug 1
+ * gdb will then print out each packet sent or received. You'll also get some
+ * messages about the gdb stub on the console of the debugged machine.
+ *
+ * If all that works, you can use lots of the usual debugging techniques on
+ * the kernel, e.g. inspecting and changing variables/memory, setting
+ * breakpoints, single stepping and so on. It's also possible to interrupt the
+ * debugged kernel by pressing C-c in gdb. Have fun! :-)
+ *
+ * The gdb stub is entered (and thus the remote gdb gets control) in the
+ * following situations:
+ *
+ * - If breakpoint() is called. This is just after kgdb initialization, or if
+ * a breakpoint() call has been put somewhere into the kernel source.
+ * (Breakpoints can of course also be set the usual way in gdb.)
+ *
+ * - If there is a kernel exception, i.e. bad_super_trap() or die_if_kernel()
+ * are entered. All the CPU exceptions are mapped to (more or less..., see
+ * the hard_trap_info array below) appropriate signal, which are reported
+ * to gdb. die_if_kernel() is usually called after some kind of access
+ * error and thus is reported as SIGSEGV.
+ *
+ * - When panic() is called. This is reported as SIGABRT.
+ *
+ * - If C-c is received over the serial line, which is treated as
+ * SIGINT.
+ *
+ * Of course, all these signals are just faked for gdb, since there is no
+ * signal concept as such for the kernel. It also isn't possible --obviously--
+ * to set signal handlers from inside gdb, or restart the kernel with a
+ * signal.
+ *
+ * Current limitations:
+ *
+ * - While the kernel is stopped, interrupts are disabled for safety reasons
+ * (i.e., variables not changing magically or the like). But this also
+ * means that the clock isn't running anymore, and that interrupts from the
+ * hardware may get lost/not be served in time. This can cause some device
+ * errors...
+ *
+ * - When single-stepping, only one instruction of the current thread is
+ * executed, but interrupts are allowed for that time and will be serviced
+ * if pending. Be prepared for that.
+ *
+ * - All debugging happens in kernel virtual address space. There's no way to
+ * access physical memory not mapped in kernel space, or to access user
+ * space. A way to work around this is using get_user_long & Co. in gdb
+ * expressions, but only for the current process.
+ *
+ * - Interrupting the kernel only works if interrupts are currently allowed,
+ * and the interrupt of the serial line isn't blocked by some other means
+ * (IPL too high, disabled, ...)
+ *
+ * - The gdb stub is currently not reentrant, i.e. errors that happen therein
+ * (e.g. accesing invalid memory) may not be caught correctly. This could
+ * be removed in future by introducing a stack of struct registers.
+ *
+ */
+
+/*
+ * To enable debugger support, two things need to happen. One, a
+ * call to kgdb_init() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * (Linux/68k note: Due to the current design, kgdb has to be initialized
+ * after traps and interrupts.)
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a TRAP #15 instruction.
+ *
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
+ * baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/linkage.h>
+
+#include <asm/setup.h>
+#include <asm/ptrace.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/kgdb.h>
+#ifdef CONFIG_ATARI
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#endif
+#ifdef CONFIG_AMIGA
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#endif
+
+
+#undef DEBUG
+
+/*
+ * global variable: register structure
+ */
+
+struct gdb_regs kgdb_registers;
+
+/*
+ * serial i/o functions
+ */
+
+static int (*serial_out)( unsigned char c );
+static unsigned char (*serial_in)( void );
+static unsigned char (*serial_intr)( void );
+
+#define putDebugChar(c) serial_out(c)
+#define getDebugChar() serial_in()
+
+
+/***************************** Prototypes *****************************/
+
+static int hex( unsigned char ch);
+static void getpacket( char *buffer);
+static void putpacket( char *buffer, int expect_ack);
+static inline unsigned long *get_vbr( void );
+static int protected_read( char *p, unsigned long *vbr );
+static int protected_write( char *p, char val, unsigned long *vbr );
+static unsigned char *mem2hex( char *mem, char *buf, int count, int
+ may_fault);
+static char *hex2mem( char *buf, char *mem, int count, int may_fault);
+static int computeSignal( int tt);
+static int hexToInt( char **ptr, int *intValue);
+extern asmlinkage void kgdb_intr( int intno, void *data, struct pt_regs *fp );
+static asmlinkage void handle_exception( void );
+static void show_gdbregs( void );
+#ifdef CONFIG_ATARI
+static int atari_mfp_out( unsigned char c );
+static unsigned char atari_mfp_in( void );
+static unsigned char atari_mfp_intr( void );
+static int atari_scc_out( unsigned char c );
+static unsigned char atari_scc_in( void );
+static unsigned char atari_scc_intr( void );
+#endif
+#ifdef CONFIG_AMIGA
+extern int amiga_ser_out( unsigned char c );
+extern unsigned char amiga_ser_in( void );
+#endif
+
+/************************* End of Prototypes **************************/
+
+
+int kgdb_initialized = 0; /* !0 means we've been initialized */
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+ * at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 2048
+
+static char input_buffer[BUFMAX];
+static char output_buffer[BUFMAX];
+static const char hexchars[]="0123456789abcdef";
+/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
+static int remote_debug = 0;
+
+/* sizes (in bytes) of CPU stack frames */
+static int frame_sizes[16] = {
+ 8, 8, 12, 12, /* $0..$3 */
+ 16, 8, 8, 60, /* $4..$7 */
+ 8, 20, 32, 92, /* $8..$B */
+ 12, 4, 4, 4 /* $C..$F */
+};
+
+/*
+ * Convert ch from a hex digit to an int
+ */
+static int hex(unsigned char ch)
+{
+ if (ch >= 'a' && ch <= 'f')
+ return ch-'a'+10;
+ if (ch >= '0' && ch <= '9')
+ return ch-'0';
+ if (ch >= 'A' && ch <= 'F')
+ return ch-'A'+10;
+ return -1;
+}
+
+/*
+ * scan for the sequence $<data>#<checksum>
+ */
+static void getpacket(char *buffer)
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ unsigned char ch;
+
+ do {
+ /*
+ * wait around for the start character,
+ * ignore all other characters
+ */
+ while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+
+ checksum = 0;
+ xmitcsum = -1;
+ count = 0;
+
+ /*
+ * now, read until a # or end of buffer is found
+ */
+ while (count < BUFMAX) {
+ ch = getDebugChar() & 0x7f;
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+
+ if (count >= BUFMAX)
+ continue;
+
+ buffer[count] = 0;
+#ifdef DEBUG
+ printk( "kgdb: received packet %s\n", buffer );
+#endif
+
+ if (ch == '#') {
+ xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+ xmitcsum |= hex(getDebugChar() & 0x7f);
+
+ if (checksum != xmitcsum) {
+ if (remote_debug)
+ printk( "kgdb: bad checksum. count = 0x%x sent=0x%x "
+ "buf=%s\n", checksum, xmitcsum, buffer );
+ putDebugChar('-'); /* failed checksum */
+ }
+ else {
+ putDebugChar('+'); /* successful transfer */
+
+ /*
+ * if a sequence char is present,
+ * reply the sequence ID
+ */
+ if (buffer[2] == ':') {
+ putDebugChar(buffer[0]);
+ putDebugChar(buffer[1]);
+
+ /*
+ * remove sequence chars from buffer
+ */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++)
+ buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ }
+ while (checksum != xmitcsum);
+}
+
+/*
+ * send the packet in buffer.
+ */
+static void putpacket(char *buffer, int expect_ack)
+{
+ unsigned char checksum;
+ int count;
+ unsigned char ch;
+
+ /*
+ * $<packet info>#<checksum>.
+ */
+
+#ifdef DEBUG
+ printk( "kgdb: sending packet %s\n", buffer );
+#endif
+ do {
+ putDebugChar('$');
+ checksum = 0;
+ count = 0;
+
+ while ((ch = buffer[count]) != 0) {
+ if (!(putDebugChar(ch)))
+ return;
+ checksum += ch;
+ count += 1;
+ }
+
+ putDebugChar('#');
+ putDebugChar(hexchars[checksum >> 4]);
+ putDebugChar(hexchars[checksum & 0xf]);
+
+ }
+ while (expect_ack && (getDebugChar() & 0x7f) != '+');
+}
+
+
+static inline unsigned long *get_vbr( void )
+
+{ unsigned long *vbr;
+
+ __asm__ __volatile__ ( "movec %/vbr,%0" : "=d" (vbr) : );
+ return( vbr );
+}
+
+static int protected_read( char *p, unsigned long *vbr )
+
+{ unsigned char val;
+ int rv;
+
+ __asm__ __volatile__
+ ( "movel %3@(8),%/a0\n\t"
+ "movel #Lberr1,%3@(8)\n\t"
+ "movel %/sp,%/a1\n\t"
+ "moveq #1,%1\n\t"
+ "moveb %2@,%0\n"
+ "nop \n\t"
+ "moveq #0,%1\n\t"
+ "Lberr1:\t"
+ "movel %/a1,%/sp\n\t"
+ "movel %/a0,%3@(8)"
+ : "=&d" (val), "=&r" (rv)
+ : "a" (p), "a" (vbr)
+ : "a0", "a1" );
+
+ return( rv ? -1 : val );
+}
+
+static int protected_write( char *p, char val, unsigned long *vbr )
+
+{ int rv;
+
+ __asm__ __volatile__
+ ( "movel %3@(8),%/a0\n\t"
+ "movel #Lberr2,%3@(8)\n\t"
+ "movel %/sp,%/a1\n\t"
+ "moveq #1,%0\n\t"
+ "moveb %2,%1@\n"
+ "nop \n\t"
+ "moveq #0,%0\n\t"
+ "Lberr2:\t"
+ "movel %/a1,%/sp\n\t"
+ "movel %/a0,%3@(8)"
+ : "=&r" (rv)
+ : "a" (p), "d" (val), "a" (vbr)
+ : "a0", "a1" );
+
+ return( rv );
+}
+
+/*
+ * Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null), in case of mem fault,
+ * return 0.
+ * If MAY_FAULT is non-zero, then we will handle memory faults by returning
+ * a 0, else treat a fault like any other fault in the stub.
+ */
+static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
+{
+ int ch;
+ unsigned long *vbr = get_vbr();
+
+ for( ; count-- > 0; ++mem ) {
+ if ((ch = protected_read( mem, vbr )) < 0) {
+ /* bus error happened */
+ if (may_fault)
+ return 0;
+ else {
+ /* ignore, but print a warning */
+ printk( "Bus error on read from %p\n", mem );
+ ch = 0;
+ }
+ }
+ *buf++ = hexchars[(ch >> 4) & 0xf];
+ *buf++ = hexchars[ch & 0xf];
+ }
+
+ *buf = 0;
+
+ return buf;
+}
+
+/*
+ * convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written
+ */
+static char *hex2mem(char *buf, char *mem, int count, int may_fault)
+{
+ int i;
+ unsigned char ch;
+ unsigned long *vbr = get_vbr();
+
+ for( i = 0; i < count; i++, mem++ ) {
+ ch = hex(*buf++) << 4;
+ ch |= hex(*buf++);
+ if (protected_write( mem, ch, vbr )) {
+ /* bus error happened */
+ if (may_fault)
+ return 0;
+ else
+ /* ignore, but print a warning */
+ printk( "Bus error on write to %p\n", mem );
+ }
+ }
+
+ return mem;
+}
+
+/*
+ * This table contains the mapping between SPARC hardware trap types, and
+ * signals, which are primarily what GDB understands. It also indicates
+ * which hardware traps we need to commandeer when initializing the stub.
+ */
+static struct hard_trap_info
+{
+ unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+ { 1, SIGINT }, /* excep. 1 is used to fake SIGINT */
+ { VEC_BUSERR, SIGSEGV }, /* bus/access error */
+ { VEC_ADDRERR, SIGBUS }, /* address error */
+ { VEC_ILLEGAL, SIGILL }, /* illegal insn */
+ { VEC_ZERODIV, SIGFPE }, /* (integer) divison by zero */
+ { VEC_CHK, SIGILL }, /* CHK insn */
+ { VEC_TRAP, SIGFPE }, /* [F]TRAPcc insn */
+ { VEC_PRIV, SIGILL }, /* priviledge violation (cannot happen) */
+ { VEC_TRACE, SIGTRAP }, /* trace trap (single-stepping) */
+ { VEC_LINE10, SIGILL }, /* A-line insn */
+ { VEC_LINE11, SIGILL }, /* F-line insn */
+ { VEC_COPROC, SIGIOT }, /* coprocessor protocol error */
+ { VEC_FORMAT, SIGIOT }, /* frame format error */
+ { VEC_UNINT, SIGIOT }, /* uninitialized intr. (should not happen) */
+ { VEC_SYS, SIGILL }, /* TRAP #0 = system call (illegal in kernel) */
+ { VEC_TRAP1, SIGILL }, /* TRAP #1 */
+ { VEC_TRAP2, SIGILL }, /* TRAP #2 */
+ { VEC_TRAP3, SIGILL }, /* TRAP #3 */
+ { VEC_TRAP4, SIGILL }, /* TRAP #4 */
+ { VEC_TRAP5, SIGILL }, /* TRAP #5 */
+ { VEC_TRAP6, SIGILL }, /* TRAP #6 */
+ { VEC_TRAP7, SIGILL }, /* TRAP #7 */
+ { VEC_TRAP8, SIGILL }, /* TRAP #8 */
+ { VEC_TRAP9, SIGILL }, /* TRAP #9 */
+ { VEC_TRAP10, SIGILL }, /* TRAP #10 */
+ { VEC_TRAP11, SIGILL }, /* TRAP #11 */
+ { VEC_TRAP12, SIGILL }, /* TRAP #12 */
+ { VEC_TRAP13, SIGILL }, /* TRAP #13 */
+ { VEC_TRAP14, SIGABRT }, /* TRAP #14 (used by kgdb_abort) */
+ { VEC_TRAP15, SIGTRAP }, /* TRAP #15 (breakpoint) */
+ { VEC_FPBRUC, SIGFPE }, /* FPU */
+ { VEC_FPIR, SIGFPE }, /* FPU */
+ { VEC_FPDIVZ, SIGFPE }, /* FPU */
+ { VEC_FPUNDER, SIGFPE }, /* FPU */
+ { VEC_FPOE, SIGFPE }, /* FPU */
+ { VEC_FPOVER, SIGFPE }, /* FPU */
+ { VEC_FPNAN, SIGFPE }, /* FPU */
+ { VEC_FPUNSUP, SIGFPE }, /* FPU */
+ { VEC_UNIMPEA, SIGILL }, /* unimpl. effective address */
+ { VEC_UNIMPII, SIGILL }, /* unimpl. integer insn */
+
+ { 0, 0 } /* Must be last */
+};
+
+
+/*
+ * Set up exception handlers for tracing and breakpoints
+ */
+void kgdb_init(void)
+{
+ extern char m68k_debug_device[];
+
+ /* fake usage to avoid gcc warnings about unused stuff (they're used in
+ * assembler code) The local variables will be optimized away... */
+ void (*fake1)(void) = handle_exception;
+ int *fake2 = frame_sizes;
+ (void)fake1; (void)fake2;
+
+ /* We don't modify the real exception vectors here for the m68k.
+ * handle_exception() will be called from bad_kernel_trap() or
+ * die_if_kernel() as needed. */
+
+ /*
+ * Initialize the serial port (name in 'm68k_debug_device')
+ */
+
+ serial_in = NULL;
+ serial_out = NULL;
+ serial_intr = NULL;
+
+#ifdef CONFIG_ATARI
+ if (MACH_IS_ATARI) {
+ if (!strcmp( m68k_debug_device, "ser" )) {
+ /* defaults to ser2 for a Falcon and ser1 otherwise */
+ strcpy( m68k_debug_device,
+ ((atari_mch_cookie>>16) == ATARI_MCH_FALCON) ?
+ "ser2" : "ser1" );
+ }
+
+ if (!strcmp( m68k_debug_device, "ser1" )) {
+ /* ST-MFP Modem1 serial port init */
+ mfp.trn_stat &= ~0x01; /* disable TX */
+ mfp.rcv_stat &= ~0x01; /* disable RX */
+ mfp.usart_ctr = 0x88; /* clk 1:16, 8N1 */
+ mfp.tim_ct_cd &= 0x70; /* stop timer D */
+ mfp.tim_dt_d = 2; /* 9600 bps */
+ mfp.tim_ct_cd |= 0x01; /* start timer D, 1:4 */
+ mfp.trn_stat |= 0x01; /* enable TX */
+ mfp.rcv_stat |= 0x01; /* enable RX */
+
+ /* set function pointers */
+ serial_in = atari_mfp_in;
+ serial_out = atari_mfp_out;
+ serial_intr = atari_mfp_intr;
+
+ /* allocate interrupt */
+ request_irq( IRQ_MFP_RECFULL, kgdb_intr, IRQ_TYPE_FAST, "kgdb",
+ NULL );
+ }
+ else if (!strcmp( m68k_debug_device, "ser2" )) {
+ extern int atari_SCC_reset_done;
+
+ /* SCC Modem2 serial port init */
+ static unsigned char *p, scc_table[] = {
+ 9, 0xc0, /* Reset */
+ 4, 0x44, /* x16, 1 stopbit, no parity */
+ 3, 0xc0, /* receiver: 8 bpc */
+ 5, 0xe2, /* transmitter: 8 bpc, assert dtr/rts */
+ 2, 0x60, /* base int vector */
+ 9, 0x09, /* int enab, with status low */
+ 10, 0, /* NRZ */
+ 11, 0x50, /* use baud rate generator */
+ 12, 24, 13, 0, /* 9600 baud */
+ 14, 2, 14, 3, /* use master clock for BRG, enable */
+ 3, 0xc1, /* enable receiver */
+ 5, 0xea, /* enable transmitter */
+ 15, 0, /* no stat ints */
+ 1, 0x10, /* Rx int every char, other ints off */
+ 0
+ };
+
+ (void)scc.cha_b_ctrl; /* reset reg pointer */
+ MFPDELAY();
+ for( p = scc_table; *p != 0; ) {
+ scc.cha_b_ctrl = *p++;
+ MFPDELAY();
+ scc.cha_b_ctrl = *p++;
+ MFPDELAY();
+ if (p[-2] == 9)
+ udelay(40); /* extra delay after WR9 access */
+ }
+ /* avoid that atari_SCC.c resets the whole SCC again */
+ atari_SCC_reset_done = 1;
+
+ /* set function pointers */
+ serial_in = atari_scc_in;
+ serial_out = atari_scc_out;
+ serial_intr = atari_scc_intr;
+
+ /* allocate rx and spcond ints */
+ request_irq( IRQ_SCCB_RX, kgdb_intr, IRQ_TYPE_FAST, "kgdb", NULL );
+ request_irq( IRQ_SCCB_SPCOND, kgdb_intr, IRQ_TYPE_FAST, "kgdb",
+ NULL );
+ }
+ }
+#endif
+
+#ifdef CONFIG_AMIGA
+ if (MACH_IS_AMIGA) {
+ /* always use built-in serial port, no init required */
+ serial_in = amiga_ser_in;
+ serial_out = amiga_ser_out;
+ }
+#endif
+
+#ifdef CONFIG_ATARI
+ if (!serial_in || !serial_out) {
+ if (*m68k_debug_device)
+ printk( "kgdb_init failed: no valid serial device!\n" );
+ else
+ printk( "kgdb not enabled\n" );
+ return;
+ }
+#endif
+
+ /*
+ * In case GDB is started before us, ack any packets
+ * (presumably "$?#xx") sitting there.
+ */
+
+ putDebugChar ('+');
+ kgdb_initialized = 1;
+ printk( KERN_INFO "kgdb initialized.\n" );
+}
+
+
+/*
+ * Convert the MIPS hardware trap type code to a unix signal number.
+ */
+static int computeSignal(int tt)
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+static int hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr)
+ {
+ hexValue = hex(**ptr);
+ if (hexValue < 0)
+ break;
+
+ *intValue = (*intValue << 4) | hexValue;
+ numChars ++;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+
+/*
+ * This assembler stuff copies a struct frame (passed as argument) into struct
+ * gdb_regs registers and then calls handle_exception. After return from
+ * there, register and the like are restored from 'registers', the stack is
+ * set up and execution is continued where registers->pc tells us.
+ */
+
+/* offsets in struct frame */
+#define FRAMEOFF_D1 "0" /* d1..d5 */
+#define FRAMEOFF_A0 "5*4" /* a0..a2 */
+#define FRAMEOFF_D0 "8*4"
+#define FRAMEOFF_SR "11*4"
+#define FRAMEOFF_PC "11*4+2"
+#define FRAMEOFF_VECTOR "12*4+2"
+
+/* offsets in struct gdb_regs */
+#define GDBOFF_D0 "0"
+#define GDBOFF_D1 "1*4"
+#define GDBOFF_D6 "6*4"
+#define GDBOFF_A0 "8*4"
+#define GDBOFF_A3 "11*4"
+#define GDBOFF_A7 "15*4"
+#define GDBOFF_VECTOR "16*4"
+#define GDBOFF_SR "16*4+2"
+#define GDBOFF_PC "17*4"
+#define GDBOFF_FP0 "18*4"
+#define GDBOFF_FPCTL "42*4"
+
+__asm__
+( " .globl " SYMBOL_NAME_STR(enter_kgdb) "\n"
+ SYMBOL_NAME_STR(enter_kgdb) ":\n"
+ /* return if not initialized */
+ " tstl "SYMBOL_NAME_STR(kgdb_initialized)"\n"
+ " bne 1f\n"
+ " rts \n"
+ "1: orw #0x700,%sr\n" /* disable interrupts while in stub */
+ " tstl %sp@+\n" /* pop off return address */
+ " movel %sp@+,%a0\n" /* get pointer to fp->ptregs (param) */
+ " movel #"SYMBOL_NAME_STR(kgdb_registers)",%a1\n" /* destination */
+ /* copy d0-d5/a0-a1 into gdb_regs */
+ " movel %a0@("FRAMEOFF_D0"),%a1@("GDBOFF_D0")\n"
+ " moveml %a0@("FRAMEOFF_D1"),%d1-%d5\n"
+ " moveml %d1-%d5,%a1@("GDBOFF_D1")\n"
+ " moveml %a0@("FRAMEOFF_A0"),%d0-%d2\n"
+ " moveml %d0-%d2,%a1@("GDBOFF_A0")\n"
+ /* copy sr and pc */
+ " movel %a0@("FRAMEOFF_PC"),%a1@("GDBOFF_PC")\n"
+ " movew %a0@("FRAMEOFF_SR"),%a1@("GDBOFF_SR")\n"
+ /* copy format/vector word */
+ " movew %a0@("FRAMEOFF_VECTOR"),%a1@("GDBOFF_VECTOR")\n"
+ /* save FPU regs */
+ " fmovemx %fp0-%fp7,%a1@("GDBOFF_FP0")\n"
+ " fmoveml %fpcr/%fpsr/%fpiar,%a1@("GDBOFF_FPCTL")\n"
+
+ /* set stack to CPU frame */
+ " addl #"FRAMEOFF_SR",%a0\n"
+ " movel %a0,%sp\n"
+ " movew %sp@(6),%d0\n"
+ " andl #0xf000,%d0\n"
+ " lsrl #8,%d0\n"
+ " lsrl #2,%d0\n" /* get frame format << 2 */
+ " lea "SYMBOL_NAME_STR(frame_sizes)",%a2\n"
+ " addl %a2@(%d0),%sp\n"
+ " movel %sp,%a1@("GDBOFF_A7")\n" /* save a7 now */
+
+ /* call handle_exception() now that the stack is set up */
+ "Lcall_handle_excp:"
+ " jsr "SYMBOL_NAME_STR(handle_exception)"\n"
+
+ /* after return, first restore FPU registers */
+ " movel #"SYMBOL_NAME_STR(kgdb_registers)",%a0\n" /* source */
+ " fmovemx %a0@("GDBOFF_FP0"),%fp0-%fp7\n"
+ " fmoveml %a0@("GDBOFF_FPCTL"),%fpcr/%fpsr/%fpiar\n"
+ /* set new stack pointer */
+ " movel %a0@("GDBOFF_A7"),%sp\n"
+ " clrw %sp@-\n" /* fake format $0 frame */
+ " movel %a0@("GDBOFF_PC"),%sp@-\n" /* new PC into frame */
+ " movew %a0@("GDBOFF_SR"),%sp@-\n" /* new SR into frame */
+ /* restore general registers */
+ " moveml %a0@("GDBOFF_D0"),%d0-%d7/%a0-%a6\n"
+ /* and jump to new PC */
+ " rte"
+ );
+
+
+/*
+ * This is the entry point for the serial interrupt handler. It calls the
+ * machine specific function pointer 'serial_intr' to get the char that
+ * interrupted. If that was C-c, the stub is entered as above, but based on
+ * just a struct intframe, not a struct frame.
+ */
+
+__asm__
+( SYMBOL_NAME_STR(kgdb_intr) ":\n"
+ /* return if not initialized */
+ " tstl "SYMBOL_NAME_STR(kgdb_initialized)"\n"
+ " bne 1f\n"
+ "2: rts \n"
+ "1: movel "SYMBOL_NAME_STR(serial_intr)",%a0\n"
+ " jsr (%a0)\n" /* get char from serial */
+ " cmpb #3,%d0\n" /* is it C-c ? */
+ " bne 2b\n" /* no -> just ignore */
+ " orw #0x700,%sr\n" /* disable interrupts */
+ " subql #1,"SYMBOL_NAME_STR(local_irq_count)"\n"
+ " movel %sp@(12),%sp\n" /* revert stack to where 'inthandler' set
+ * it up */
+ /* restore regs from frame */
+ " moveml %sp@+,%d1-%d5/%a0-%a2\n"
+ " movel %sp@+,%d0\n"
+ " addql #8,%sp\n" /* throw away orig_d0 and stkadj */
+ /* save them into 'registers' */
+ " moveml %d0-%d7/%a0-%a6,"SYMBOL_NAME_STR(kgdb_registers)"\n"
+ " movel #"SYMBOL_NAME_STR(kgdb_registers)",%a1\n" /* destination */
+ /* copy sr and pc */
+ " movel %sp@(2),%a1@("GDBOFF_PC")\n"
+ " movew %sp@,%a1@("GDBOFF_SR")\n"
+ /* fake format 0 and vector 1 (translated to SIGINT) */
+ " movew #4,%a1@("GDBOFF_VECTOR")\n"
+ /* save FPU regs */
+ " fmovemx %fp0-%fp7,%a1@("GDBOFF_FP0")\n"
+ " fmoveml %fpcr/%fpsr/%fpiar,%a1@("GDBOFF_FPCTL")\n"
+ /* pop off the CPU stack frame */
+ " addql #8,%sp\n"
+ " movel %sp,%a1@("GDBOFF_A7")\n" /* save a7 now */
+ /* proceed as in enter_kgdb */
+ " jbra Lcall_handle_excp\n"
+ );
+
+/*
+ * This function does all command processing for interfacing to gdb. It
+ * returns 1 if you should skip the instruction at the trap address, 0
+ * otherwise.
+ */
+static asmlinkage void handle_exception( void )
+{
+ int trap; /* Trap type */
+ int sigval;
+ int addr;
+ int length;
+ char *ptr;
+
+ trap = kgdb_registers.vector >> 2;
+ sigval = computeSignal(trap);
+ /* clear upper half of vector/sr word */
+ kgdb_registers.vector = 0;
+ kgdb_registers.format = 0;
+
+#ifndef DEBUG
+ if (remote_debug) {
+#endif
+ printk("in handle_exception() trap=%d sigval=%d\n", trap, sigval );
+ show_gdbregs();
+#ifndef DEBUG
+ }
+#endif
+
+ /*
+ * reply to host that an exception has occurred
+ */
+ ptr = output_buffer;
+
+ /*
+ * Send trap type (converted to signal)
+ */
+ *ptr++ = 'T';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+
+ /*
+ * Send Error PC
+ */
+ *ptr++ = hexchars[GDBREG_PC >> 4];
+ *ptr++ = hexchars[GDBREG_PC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&kgdb_registers.pc, ptr, 4, 0);
+ *ptr++ = ';';
+
+ /*
+ * Send frame pointer
+ */
+ *ptr++ = hexchars[GDBREG_A6 >> 4];
+ *ptr++ = hexchars[GDBREG_A6 & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&kgdb_registers.regs[GDBREG_A6], ptr, 4, 0);
+ *ptr++ = ';';
+
+ /*
+ * Send stack pointer
+ */
+ *ptr++ = hexchars[GDBREG_SP >> 4];
+ *ptr++ = hexchars[GDBREG_SP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&kgdb_registers.regs[GDBREG_SP], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = 0;
+ putpacket(output_buffer,1); /* send it off... */
+
+ /*
+ * Wait for input from remote GDB
+ */
+ for(;;) {
+ output_buffer[0] = 0;
+ getpacket(input_buffer);
+
+ switch (input_buffer[0]) {
+ case '?':
+ output_buffer[0] = 'S';
+ output_buffer[1] = hexchars[sigval >> 4];
+ output_buffer[2] = hexchars[sigval & 0xf];
+ output_buffer[3] = 0;
+ break;
+
+ case 'd':
+ /* toggle debug flag */
+ remote_debug = !remote_debug;
+ break;
+
+ /*
+ * Return the value of the CPU registers
+ */
+ case 'g':
+ ptr = output_buffer;
+ ptr = mem2hex((char *)&kgdb_registers, ptr, NUMREGSBYTES, 0);
+ break;
+
+ /*
+ * set the value of the CPU registers - return OK
+ */
+ case 'G':
+ ptr = &input_buffer[1];
+ ptr = hex2mem(ptr, (char *)&kgdb_registers, NUMREGSBYTES, 0);
+ strcpy(output_buffer,"OK");
+ break;
+
+ /*
+ * Pn...=r... Write register n
+ */
+ case 'P':
+ ptr = &input_buffer[1];
+ if (hexToInt(&ptr, &addr) && *ptr++ == '=') {
+ if (addr >= 0 && addr <= GDBREG_PC)
+ hex2mem(ptr, (char *)&kgdb_registers.regs[addr], 4, 0);
+ else if (addr >= GDBREG_FP0 && addr <= GDBREG_FP7)
+ hex2mem(ptr, (char *)&kgdb_registers.fpregs[addr-GDBREG_FP0],
+ 12, 0);
+ else if (addr >= GDBREG_FPCR && addr <= GDBREG_FPIAR)
+ hex2mem(ptr, (char *)&kgdb_registers.fpcntl[addr-GDBREG_FPCR],
+ 4, 0);
+ }
+ else
+ strcpy(output_buffer,"E01");
+ break;
+
+ /*
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA
+ */
+ case 'm':
+ ptr = &input_buffer[1];
+
+ if (hexToInt(&ptr, &addr)
+ && *ptr++ == ','
+ && hexToInt(&ptr, &length)) {
+ if (mem2hex((char *)addr, output_buffer, length, 1))
+ break;
+ strcpy (output_buffer, "E03");
+ } else
+ strcpy(output_buffer,"E01");
+ break;
+
+ /*
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
+ */
+ case 'M':
+ ptr = &input_buffer[1];
+
+ if (hexToInt(&ptr, &addr)
+ && *ptr++ == ','
+ && hexToInt(&ptr, &length)
+ && *ptr++ == ':') {
+ if (hex2mem(ptr, (char *)addr, length, 1))
+ strcpy(output_buffer, "OK");
+ else
+ strcpy(output_buffer, "E03");
+ }
+ else
+ strcpy(output_buffer, "E02");
+ break;
+
+ /*
+ * cAA..AA Continue at address AA..AA(optional)
+ * sAA..AA Step one instruction from AA..AA(optional)
+ */
+ case 'c':
+ case 's':
+ /* try to read optional parameter, pc unchanged if no parm */
+
+ ptr = &input_buffer[1];
+ if (hexToInt(&ptr, &addr))
+ kgdb_registers.pc = addr;
+
+ kgdb_registers.sr &= 0x7fff; /* clear Trace bit */
+ if (input_buffer[0] == 's')
+ kgdb_registers.sr |= 0x8000; /* set it if step command */
+
+ if (remote_debug)
+ printk( "cont; new PC=0x%08lx SR=0x%04x\n",
+ kgdb_registers.pc, kgdb_registers.sr );
+
+ /*
+ * Need to flush the instruction cache here, as we may
+ * have deposited a breakpoint, and the icache probably
+ * has no way of knowing that a data ref to some location
+ * may have changed something that is in the instruction
+ * cache.
+ */
+
+ if (m68k_is040or060)
+ __asm__ __volatile__
+ ( ".word 0xf4f8\n\t" /* CPUSHA I/D */
+ ".word 0xf498" /* CINVA I */
+ );
+ else
+ __asm__ __volatile__
+ ( "movec %/cacr,%/d0\n\t"
+ "oriw #0x0008,%/d0\n\t"
+ "movec %/d0,%/cacr"
+ : : : "d0" );
+
+ return;
+
+ /*
+ * kill the program means reset the machine
+ */
+ case 'k' :
+ case 'r':
+ if (mach_reset) {
+ /* reply OK before actual reset */
+ strcpy(output_buffer,"OK");
+ putpacket(output_buffer,0);
+ mach_reset();
+ }
+ else
+ strcpy(output_buffer,"E01");
+ break;
+
+ /*
+ * Set baud rate (bBB)
+ * FIXME: Needs to be written (in gdb, too...)
+ */
+ case 'b':
+ strcpy(output_buffer,"E01");
+ break;
+
+ } /* switch */
+
+ /*
+ * reply to the request
+ */
+
+ putpacket(output_buffer,1);
+
+ }
+}
+
+
+/*
+ * Print registers (on target console)
+ * Used only to debug the stub...
+ */
+static void show_gdbregs( void )
+{
+ printk( "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
+ kgdb_registers.regs[0], kgdb_registers.regs[1],
+ kgdb_registers.regs[2], kgdb_registers.regs[3] );
+ printk( "d4: %08lx d5: %08lx d6: %08lx d7: %08lx\n",
+ kgdb_registers.regs[4], kgdb_registers.regs[5],
+ kgdb_registers.regs[6], kgdb_registers.regs[7] );
+ printk( "a0: %08lx a1: %08lx a2: %08lx a3: %08lx\n",
+ kgdb_registers.regs[8], kgdb_registers.regs[9],
+ kgdb_registers.regs[10], kgdb_registers.regs[11] );
+ printk( "a4: %08lx a5: %08lx a6: %08lx a7: %08lx\n",
+ kgdb_registers.regs[12], kgdb_registers.regs[13],
+ kgdb_registers.regs[14], kgdb_registers.regs[15] );
+ printk( "pc: %08lx sr: %04x\n", kgdb_registers.pc, kgdb_registers.sr );
+}
+
+
+/* -------------------- Atari serial I/O -------------------- */
+
+#ifdef CONFIG_ATARI
+
+static int atari_mfp_out( unsigned char c )
+
+{
+ while( !(mfp.trn_stat & 0x80) ) /* wait for tx buf empty */
+ barrier();
+ mfp.usart_dta = c;
+ return( 1 );
+}
+
+
+static unsigned char atari_mfp_in( void )
+
+{
+ while( !(mfp.rcv_stat & 0x80) ) /* wait for rx buf filled */
+ barrier();
+ return( mfp.usart_dta );
+}
+
+
+static unsigned char atari_mfp_intr( void )
+
+{
+ return( mfp.usart_dta );
+}
+
+
+static int atari_scc_out( unsigned char c )
+
+{
+ do {
+ MFPDELAY();
+ } while( !(scc.cha_b_ctrl & 0x04) ); /* wait for tx buf empty */
+ MFPDELAY();
+ scc.cha_b_data = c;
+ return( 1 );
+}
+
+
+static unsigned char atari_scc_in( void )
+
+{
+ do {
+ MFPDELAY();
+ } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */
+ MFPDELAY();
+ return( scc.cha_b_data );
+}
+
+
+static unsigned char atari_scc_intr( void )
+
+{ unsigned char c, stat;
+
+ MFPDELAY();
+ scc.cha_b_ctrl = 1; /* RR1 */
+ MFPDELAY();
+ stat = scc.cha_b_ctrl;
+ MFPDELAY();
+ c = scc.cha_b_data;
+ MFPDELAY();
+ if (stat & 0x30) {
+ scc.cha_b_ctrl = 0x30; /* error reset for overrun and parity */
+ MFPDELAY();
+ }
+ scc.cha_b_ctrl = 0x38; /* reset highest IUS */
+ MFPDELAY();
+ return( c );
+}
+
+#endif
diff --git a/arch/m68k/kernel/m68k_defs.h b/arch/m68k/kernel/m68k_defs.h
new file mode 100644
index 000000000..992d390c7
--- /dev/null
+++ b/arch/m68k/kernel/m68k_defs.h
@@ -0,0 +1,8 @@
+/*
+ * WARNING! This file is automatically generated - DO NOT EDIT!
+ */
+
+#define TS_MAGICKEY 0x5a5a5a5a
+#define TS_TSS 478
+#define TS_ESP0 498
+#define TS_FPU 502
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 025e11c0f..ee73b3ff2 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/linkage.h>
#include <linux/sched.h>
@@ -8,7 +7,6 @@
#include <linux/elfcore.h>
#include <linux/in6.h>
#include <linux/interrupt.h>
-#include <linux/pci.h>
#include <asm/setup.h>
#include <asm/machdep.h>
@@ -44,6 +42,8 @@ EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(local_bh_count);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy);
@@ -60,7 +60,3 @@ EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
EXPORT_SYMBOL_NOVERS(__up_wakeup);
-
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pci_devices);
-#endif
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index a6fbd5718..dac2bfcc8 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -66,13 +66,14 @@ asmlinkage int sys_idle(void)
current->priority = -100;
current->counter = -100;
for (;;){
- if (!need_resched)
+ if (!current->need_resched)
#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC)
/* block out HSYNC on the atari (falcon) */
__asm__("stop #0x2200" : : : "cc");
#else /* portable version */
__asm__("stop #0x2000" : : : "cc");
#endif /* machine compilation types */
+ check_pgt_cache();
run_task_queue(&tq_scheduler);
schedule();
}
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index 4a2a95f4b..da91d32de 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -347,9 +347,13 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out;
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
+ unsigned long flags;
+
+ write_lock_irqsave(&tasklist_lock, flags);
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
+ write_unlock_irqrestore(&tasklist_lock, flags);
}
send_sig(SIGSTOP, child, 1);
ret = 0;
@@ -491,6 +495,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
}
case PTRACE_DETACH: { /* detach a process that was attached. */
+ unsigned long flags;
long tmp;
ret = -EIO;
@@ -499,9 +504,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child);
child->exit_code = data;
+ write_lock_irqsave(&tasklist_lock, flags);
REMOVE_LINKS(child);
child->p_pptr = child->p_opptr;
SET_LINKS(child);
+ write_unlock_irqrestore(&tasklist_lock, flags);
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index fccf8b4cf..6df005fb4 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -61,6 +61,8 @@ void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initd
int (*mach_keyb_init) (void) __initdata;
int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
void (*mach_kbd_leds) (unsigned int) = NULL;
+/* machine dependent "kbd-reset" setup function */
+void (*kbd_reset_setup) (char *, int) __initdata = NULL;
/* machine dependent irq functions */
void (*mach_init_IRQ) (void) __initdata;
void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
@@ -102,6 +104,8 @@ extern void config_mac(void);
extern void config_sun3(void);
extern void config_apollo(void);
extern void config_mvme16x(void);
+extern void config_bvme6000(void);
+extern void config_hp300(void);
#define MASK_256K 0xfffc0000
@@ -250,6 +254,16 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
config_mvme16x();
break;
#endif
+#ifdef CONFIG_BVME6000
+ case MACH_BVME6000:
+ config_bvme6000();
+ break;
+#endif
+#ifdef CONFIG_HP300
+ case MACH_HP300:
+ config_hp300();
+ break;
+#endif
default:
panic ("No configuration setup");
}
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 97809d382..03214a42f 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -147,6 +147,12 @@ sys_sigaction(int sig, const struct old_sigaction *act,
return ret;
}
+asmlinkage int
+sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+ return do_sigaltstack(uss, uoss, rdusp());
+}
+
/*
* Do a signal return; undo the signal stack.
@@ -177,31 +183,33 @@ struct rt_sigframe
static unsigned char fpu_version = 0; /* version number of fpu, set by setup_frame */
-static inline void restore_fpu_state(struct sigcontext *sc)
+static inline int restore_fpu_state(struct sigcontext *sc)
{
+ int err = 1;
+
if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
/* Verify the frame format. */
if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
- goto badframe;
+ goto out;
if (CPU_IS_020_OR_030) {
if (m68k_fputype & FPU_68881 &&
!(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
- goto badframe;
+ goto out;
if (m68k_fputype & FPU_68882 &&
!(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
- goto badframe;
+ goto out;
} else if (CPU_IS_040) {
if (!(sc->sc_fpstate[1] == 0x00 ||
sc->sc_fpstate[1] == 0x28 ||
sc->sc_fpstate[1] == 0x60))
- goto badframe;
+ goto out;
} else if (CPU_IS_060) {
if (!(sc->sc_fpstate[3] == 0x00 ||
sc->sc_fpstate[3] == 0x60 ||
sc->sc_fpstate[3] == 0xe0))
- goto badframe;
+ goto out;
} else
- goto badframe;
+ goto out;
__asm__ volatile (".chip 68k/68881\n\t"
"fmovemx %0,%/fp0-%/fp1\n\t"
@@ -213,10 +221,10 @@ static inline void restore_fpu_state(struct sigcontext *sc)
__asm__ volatile (".chip 68k/68881\n\t"
"frestore %0\n\t"
".chip 68k" : : "m" (*sc->sc_fpstate));
- return;
+ err = 0;
-badframe:
- do_exit(SIGSEGV);
+out:
+ return err;
}
#define FPCONTEXT_SIZE 216
@@ -224,42 +232,43 @@ badframe:
#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
-static inline void rt_restore_fpu_state(struct ucontext *uc)
+static inline int rt_restore_fpu_state(struct ucontext *uc)
{
unsigned char fpstate[FPCONTEXT_SIZE];
int context_size = CPU_IS_060 ? 8 : 0;
fpregset_t fpregs;
+ int err = 1;
if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
- goto badframe;
+ goto out;
if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
if (!CPU_IS_060)
context_size = fpstate[1];
/* Verify the frame format. */
if (!CPU_IS_060 && (fpstate[0] != fpu_version))
- goto badframe;
+ goto out;
if (CPU_IS_020_OR_030) {
if (m68k_fputype & FPU_68881 &&
!(context_size == 0x18 || context_size == 0xb4))
- goto badframe;
+ goto out;
if (m68k_fputype & FPU_68882 &&
!(context_size == 0x38 || context_size == 0xd4))
- goto badframe;
+ goto out;
} else if (CPU_IS_040) {
if (!(context_size == 0x00 ||
context_size == 0x28 ||
context_size == 0x60))
- goto badframe;
+ goto out;
} else if (CPU_IS_060) {
if (!(fpstate[3] == 0x00 ||
fpstate[3] == 0x60 ||
fpstate[3] == 0xe0))
- goto badframe;
+ goto out;
} else
- goto badframe;
+ goto out;
if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
sizeof(fpregs)))
- goto badframe;
+ goto out;
__asm__ volatile (".chip 68k/68881\n\t"
"fmovemx %0,%/fp0-%/fp7\n\t"
"fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
@@ -271,21 +280,23 @@ static inline void rt_restore_fpu_state(struct ucontext *uc)
if (context_size &&
__copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
context_size))
- goto badframe;
+ goto out;
__asm__ volatile (".chip 68k/68881\n\t"
"frestore %0\n\t"
".chip 68k" : : "m" (*fpstate));
- return;
+ err = 0;
-badframe:
- do_exit(SIGSEGV);
+out:
+ return err;
}
static inline int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp)
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
+ int *pd0)
{
int fsize, formatvec;
struct sigcontext context;
+ int err;
/* get previous context */
if (copy_from_user(&context, usc, sizeof(context)))
@@ -303,7 +314,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp)
regs->format = formatvec >> 12;
regs->vector = formatvec & 0xfff;
- restore_fpu_state(&context);
+ err = restore_fpu_state(&context);
fsize = frame_extra_sizes[regs->format];
if (fsize < 0) {
@@ -356,49 +367,55 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp)
goto badframe;
}
- return context.sc_d0;
+ *pd0 = context.sc_d0;
+ return err;
badframe:
- do_exit(SIGSEGV);
+ return 1;
}
static inline int
rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
- struct ucontext *uc)
+ struct ucontext *uc, int *pd0)
{
int fsize, temp;
greg_t *gregs = uc->uc_mcontext.gregs;
+ unsigned long usp;
+ int err;
- __get_user(temp, &uc->uc_mcontext.version);
+ err = __get_user(temp, &uc->uc_mcontext.version);
if (temp != MCONTEXT_VERSION)
goto badframe;
/* restore passed registers */
- __get_user(regs->d0, &gregs[0]);
- __get_user(regs->d1, &gregs[1]);
- __get_user(regs->d2, &gregs[2]);
- __get_user(regs->d3, &gregs[3]);
- __get_user(regs->d4, &gregs[4]);
- __get_user(regs->d5, &gregs[5]);
- __get_user(sw->d6, &gregs[6]);
- __get_user(sw->d7, &gregs[7]);
- __get_user(regs->a0, &gregs[8]);
- __get_user(regs->a1, &gregs[9]);
- __get_user(regs->a2, &gregs[10]);
- __get_user(sw->a3, &gregs[11]);
- __get_user(sw->a4, &gregs[12]);
- __get_user(sw->a5, &gregs[13]);
- __get_user(sw->a6, &gregs[14]);
- __get_user(temp, &gregs[15]);
- wrusp(temp);
- __get_user(regs->pc, &gregs[16]);
- __get_user(temp, &gregs[17]);
+ err |= __get_user(regs->d0, &gregs[0]);
+ err |= __get_user(regs->d1, &gregs[1]);
+ err |= __get_user(regs->d2, &gregs[2]);
+ err |= __get_user(regs->d3, &gregs[3]);
+ err |= __get_user(regs->d4, &gregs[4]);
+ err |= __get_user(regs->d5, &gregs[5]);
+ err |= __get_user(sw->d6, &gregs[6]);
+ err |= __get_user(sw->d7, &gregs[7]);
+ err |= __get_user(regs->a0, &gregs[8]);
+ err |= __get_user(regs->a1, &gregs[9]);
+ err |= __get_user(regs->a2, &gregs[10]);
+ err |= __get_user(sw->a3, &gregs[11]);
+ err |= __get_user(sw->a4, &gregs[12]);
+ err |= __get_user(sw->a5, &gregs[13]);
+ err |= __get_user(sw->a6, &gregs[14]);
+ err |= __get_user(usp, &gregs[15]);
+ wrusp(usp);
+ err |= __get_user(regs->pc, &gregs[16]);
+ err |= __get_user(temp, &gregs[17]);
regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
regs->orig_d0 = -1; /* disable syscall checks */
- __get_user(temp, &uc->uc_formatvec);
+ err |= __get_user(temp, &uc->uc_formatvec);
regs->format = temp >> 12;
regs->vector = temp & 0xfff;
- rt_restore_fpu_state(uc);
+ err |= rt_restore_fpu_state(uc);
+
+ if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
+ goto badframe;
fsize = frame_extra_sizes[regs->format];
if (fsize < 0) {
@@ -449,10 +466,11 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
goto badframe;
}
- return regs->d0;
+ *pd0 = regs->d0;
+ return err;
badframe:
- do_exit(SIGSEGV);
+ return 1;
}
asmlinkage int do_sigreturn(unsigned long __unused)
@@ -462,6 +480,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
unsigned long usp = rdusp();
struct sigframe *frame = (struct sigframe *)(usp - 24);
sigset_t set;
+ int d0;
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
@@ -475,10 +494,13 @@ asmlinkage int do_sigreturn(unsigned long __unused)
current->blocked = set;
recalc_sigpending(current);
- return restore_sigcontext(regs, &frame->sc, frame + 1);
+ if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
+ goto badframe;
+ return d0;
badframe:
- do_exit(SIGSEGV);
+ force_sig(SIGSEGV, current);
+ return 0;
}
asmlinkage int do_rt_sigreturn(unsigned long __unused)
@@ -488,6 +510,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
unsigned long usp = rdusp();
struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
sigset_t set;
+ int d0;
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
@@ -498,10 +521,13 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
current->blocked = set;
recalc_sigpending(current);
- return rt_restore_ucontext(regs, sw, &frame->uc);
+ if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
+ goto badframe;
+ return d0;
badframe:
- do_exit(SIGSEGV);
+ force_sig(SIGSEGV, current);
+ return 0;
}
/*
@@ -535,17 +561,18 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
}
}
-static inline void rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
+static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
{
unsigned char fpstate[FPCONTEXT_SIZE];
int context_size = CPU_IS_060 ? 8 : 0;
+ int err = 0;
__asm__ volatile (".chip 68k/68881\n\t"
"fsave %0\n\t"
".chip 68k"
: : "m" (*fpstate) : "memory");
- __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
+ err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
fpregset_t fpregs;
if (!CPU_IS_060)
@@ -566,11 +593,13 @@ static inline void rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
: "m" (*fpregs.f_fpregs),
"m" (fpregs.f_pcr)
: "memory");
- copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, sizeof(fpregs));
+ err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
+ sizeof(fpregs));
}
if (context_size)
- copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
- context_size);
+ err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
+ context_size);
+ return err;
}
static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
@@ -588,32 +617,34 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
save_fpu_state(sc, regs);
}
-static inline void rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
+static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
{
struct switch_stack *sw = (struct switch_stack *)regs - 1;
greg_t *gregs = uc->uc_mcontext.gregs;
-
- __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
- __put_user(regs->d0, &gregs[0]);
- __put_user(regs->d1, &gregs[1]);
- __put_user(regs->d2, &gregs[2]);
- __put_user(regs->d3, &gregs[3]);
- __put_user(regs->d4, &gregs[4]);
- __put_user(regs->d5, &gregs[5]);
- __put_user(sw->d6, &gregs[6]);
- __put_user(sw->d7, &gregs[7]);
- __put_user(regs->a0, &gregs[8]);
- __put_user(regs->a1, &gregs[9]);
- __put_user(regs->a2, &gregs[10]);
- __put_user(sw->a3, &gregs[11]);
- __put_user(sw->a4, &gregs[12]);
- __put_user(sw->a5, &gregs[13]);
- __put_user(sw->a6, &gregs[14]);
- __put_user(rdusp(), &gregs[15]);
- __put_user(regs->pc, &gregs[16]);
- __put_user(regs->sr, &gregs[17]);
- __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
- rt_save_fpu_state(uc, regs);
+ int err = 0;
+
+ err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
+ err |= __put_user(regs->d0, &gregs[0]);
+ err |= __put_user(regs->d1, &gregs[1]);
+ err |= __put_user(regs->d2, &gregs[2]);
+ err |= __put_user(regs->d3, &gregs[3]);
+ err |= __put_user(regs->d4, &gregs[4]);
+ err |= __put_user(regs->d5, &gregs[5]);
+ err |= __put_user(sw->d6, &gregs[6]);
+ err |= __put_user(sw->d7, &gregs[7]);
+ err |= __put_user(regs->a0, &gregs[8]);
+ err |= __put_user(regs->a1, &gregs[9]);
+ err |= __put_user(regs->a2, &gregs[10]);
+ err |= __put_user(sw->a3, &gregs[11]);
+ err |= __put_user(sw->a4, &gregs[12]);
+ err |= __put_user(sw->a5, &gregs[13]);
+ err |= __put_user(sw->a6, &gregs[14]);
+ err |= __put_user(rdusp(), &gregs[15]);
+ err |= __put_user(regs->pc, &gregs[16]);
+ err |= __put_user(regs->sr, &gregs[17]);
+ err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
+ err |= rt_save_fpu_state(uc, regs);
+ return err;
}
static inline void push_cache (unsigned long vaddr)
@@ -708,60 +739,72 @@ static inline void push_cache (unsigned long vaddr)
}
}
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+{
+ unsigned long usp;
+
+ /* Default to using normal stack. */
+ usp = rdusp();
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (!on_sig_stack(usp))
+ usp = current->sas_ss_sp + current->sas_ss_size;
+ }
+ return (void *)((usp - frame_size) & -8UL);
+}
+
static void setup_frame (int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs *regs)
{
struct sigframe *frame;
int fsize = frame_extra_sizes[regs->format];
struct sigcontext context;
+ int err = 0;
if (fsize < 0) {
#ifdef DEBUG
printk ("setup_frame: Unknown frame format %#x\n",
regs->format);
#endif
- goto segv_and_exit;
+ goto give_sigsegv;
}
- frame = (struct sigframe *)((rdusp() - sizeof(*frame) - fsize) & -8);
-
- if (!(current->flags & PF_ONSIGSTK) && (ka->sa.sa_flags & SA_ONSTACK)) {
- frame = (struct sigframe *)(((unsigned long)ka->sa.sa_restorer
- - sizeof(*frame) - fsize) & -8);
- current->flags |= PF_ONSIGSTK;
- }
+ frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
if (fsize) {
- if (copy_to_user (frame + 1, regs + 1, fsize))
- goto segv_and_exit;
+ err |= copy_to_user (frame + 1, regs + 1, fsize);
regs->stkadj = fsize;
}
- __put_user((current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? current->exec_domain->signal_invmap[sig]
- : sig),
- &frame->sig);
+ err |= __put_user((current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32
+ ? current->exec_domain->signal_invmap[sig]
+ : sig),
+ &frame->sig);
- __put_user(regs->vector, &frame->code);
- __put_user(&frame->sc, &frame->psc);
+ err |= __put_user(regs->vector, &frame->code);
+ err |= __put_user(&frame->sc, &frame->psc);
if (_NSIG_WORDS > 1)
- copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
+ err |= copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask));
setup_sigcontext(&context, regs, set->sig[0]);
- if (copy_to_user (&frame->sc, &context, sizeof(context)))
- goto segv_and_exit;
+ err |= copy_to_user (&frame->sc, &context, sizeof(context));
/* Set up to return from userspace. */
- __put_user(frame->retcode, &frame->pretcode);
+ err |= __put_user(frame->retcode, &frame->pretcode);
/* addaw #20,sp */
- __put_user(0xdefc0014, (long *)(frame->retcode + 0));
+ err |= __put_user(0xdefc0014, (long *)(frame->retcode + 0));
/* moveq #,d0; trap #0 */
- __put_user(0x70004e40 + (__NR_sigreturn << 16),
- (long *)(frame->retcode + 4));
+ err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
+ (long *)(frame->retcode + 4));
+
+ if (err)
+ goto give_sigsegv;
push_cache ((unsigned long) &frame->retcode);
@@ -791,8 +834,10 @@ static void setup_frame (int sig, struct k_sigaction *ka,
}
return;
-segv_and_exit:
- do_exit(SIGSEGV);
+give_sigsegv:
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
}
static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -800,48 +845,53 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
{
struct rt_sigframe *frame;
int fsize = frame_extra_sizes[regs->format];
+ int err = 0;
if (fsize < 0) {
#ifdef DEBUG
printk ("setup_frame: Unknown frame format %#x\n",
regs->format);
#endif
- goto segv_and_exit;
+ goto give_sigsegv;
}
- frame = (struct rt_sigframe *)((rdusp() - sizeof(*frame)) & -8);
-
- /* XXX: Check here if we need to switch stacks.. */
+ frame = get_sigframe(ka, regs, sizeof(*frame));
if (fsize) {
- if (copy_to_user (&frame->uc.uc_extra, regs + 1, fsize))
- goto segv_and_exit;
+ err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
regs->stkadj = fsize;
}
- __put_user((current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? current->exec_domain->signal_invmap[sig]
- : sig),
- &frame->sig);
- __put_user(&frame->info, &frame->pinfo);
- __put_user(&frame->uc, &frame->puc);
- __copy_to_user(&frame->info, info, sizeof(*info));
-
- /* Clear all the bits of the ucontext we don't use. */
- clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
-
- rt_setup_ucontext(&frame->uc, regs);
- if (copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set)))
- goto segv_and_exit;
+ err |= __put_user((current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32
+ ? current->exec_domain->signal_invmap[sig]
+ : sig),
+ &frame->sig);
+ err |= __put_user(&frame->info, &frame->pinfo);
+ err |= __put_user(&frame->uc, &frame->puc);
+ err |= __copy_to_user(&frame->info, info, sizeof(*info));
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user((void *)current->sas_ss_sp,
+ &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(rdusp()),
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= rt_setup_ucontext(&frame->uc, regs);
+ err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
/* Set up to return from userspace. */
- __put_user(frame->retcode, &frame->pretcode);
+ err |= __put_user(frame->retcode, &frame->pretcode);
/* movel #,d0; trap #0 */
- __put_user(0x203c, (short *)(frame->retcode + 0));
- __put_user(__NR_rt_sigreturn, (long *)(frame->retcode + 2));
- __put_user(0x4e40, (short *)(frame->retcode + 6));
+ err |= __put_user(0x203c, (short *)(frame->retcode + 0));
+ err |= __put_user(__NR_rt_sigreturn, (long *)(frame->retcode + 2));
+ err |= __put_user(0x4e40, (short *)(frame->retcode + 6));
+
+ if (err)
+ goto give_sigsegv;
push_cache ((unsigned long) &frame->retcode);
@@ -871,8 +921,34 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
}
return;
-segv_and_exit:
- do_exit(SIGSEGV);
+give_sigsegv:
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+}
+
+static inline void
+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
+{
+ switch (regs->d0) {
+ case -ERESTARTNOHAND:
+ if (!has_handler)
+ goto do_restart;
+ regs->d0 = -EINTR;
+ break;
+
+ case -ERESTARTSYS:
+ if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
+ regs->d0 = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ do_restart:
+ regs->d0 = regs->orig_d0;
+ regs->pc -= 2;
+ break;
+ }
}
/*
@@ -883,24 +959,9 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs)
{
/* are we from a system call? */
- if (regs->orig_d0 >= 0) {
+ if (regs->orig_d0 >= 0)
/* If so, check system call restarting.. */
- switch (regs->d0) {
- case -ERESTARTNOHAND:
- regs->d0 = -EINTR;
- break;
-
- case -ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
- regs->d0 = -EINTR;
- break;
- }
- /* fallthrough */
- case -ERESTARTNOINTR:
- regs->d0 = regs->orig_d0;
- regs->pc -= 2;
- }
- }
+ handle_restart(regs, ka, 1);
/* set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
@@ -952,13 +1013,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* Did we come from a system call? */
if (regs->orig_d0 >= 0) {
- /* Restart the system call */
- if (regs->d0 == -ERESTARTNOHAND ||
- regs->d0 == -ERESTARTSYS ||
- regs->d0 == -ERESTARTNOINTR) {
- regs->d0 = regs->orig_d0;
- regs->pc -= 2;
- }
+ /* Restart the system call the same way as
+ if the process were not traced. */
+ struct k_sigaction *ka =
+ &current->sig->action[signr-1];
+ int has_handler =
+ (ka->sa.sa_handler != SIG_IGN &&
+ ka->sa.sa_handler != SIG_DFL);
+ handle_restart(regs, ka, has_handler);
}
notify_parent(current, SIGCHLD);
schedule();
@@ -1052,15 +1114,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
}
/* Did we come from a system call? */
- if (regs->orig_d0 >= 0) {
+ if (regs->orig_d0 >= 0)
/* Restart the system call - no handlers present */
- if (regs->d0 == -ERESTARTNOHAND ||
- regs->d0 == -ERESTARTSYS ||
- regs->d0 == -ERESTARTNOINTR) {
- regs->d0 = regs->orig_d0;
- regs->pc -= 2;
- }
- }
+ handle_restart(regs, NULL, 0);
/* If we are about to discard some frame stuff we must copy
over the remaining frame. */
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 50d564134..75da52541 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -66,20 +66,25 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg)
struct file * file = NULL;
struct mmap_arg_struct a;
- lock_kernel();
- error = -EFAULT;
if (copy_from_user(&a, arg, sizeof(a)))
- goto out;
+ return -EFAULT;
+ down(&current->mm->mmap_sem);
+ lock_kernel();
if (!(a.flags & MAP_ANONYMOUS)) {
error = -EBADF;
- if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
+ file = fget(a.fd);
+ if (!file)
goto out;
}
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
+ if (file)
+ fput(file);
out:
unlock_kernel();
+ up(&current->mm->mmap_sem);
return error;
}
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 51359f046..8f11a00d8 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -38,7 +38,7 @@ static inline void do_profile (unsigned long pc)
++prof_buffer[pc];
else
/*
- * Dont ignore out-of-bounds PC values silently,
+ * Don't ignore out-of-bounds PC values silently,
* put them into the last histogram slot, so if
* present, they will show up as a sharp peak.
*/
diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile
index 458a01f44..cfd63295a 100644
--- a/arch/m68k/mac/Makefile
+++ b/arch/m68k/mac/Makefile
@@ -10,7 +10,8 @@
EXTRA_CFLAGS := -Wa,-m68020
O_TARGET := mac.o
-O_OBJS := config.o ksyms.o bootparse.o macints.o via6522.o \
+O_OBJS := config.o bootparse.o macints.o via6522.o \
mackeyb.o adb-bus.o macboing.o debug.o
+OX_OBJS := mac_ksyms.o
include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/mac/adb-bus.c b/arch/m68k/mac/adb-bus.c
index ddd5176c4..0f41bc6aa 100644
--- a/arch/m68k/mac/adb-bus.c
+++ b/arch/m68k/mac/adb-bus.c
@@ -6,9 +6,11 @@
* Copyright (C) 1996 Paul Mackerras.
*
* MSch (9/97) Partial rewrite of interrupt handler to MacII style
- * ADB handshake, based on:
- * - Guide to Mac Hardware
- * - Guido Koerber's session with a logic analyzer
+ * ADB handshake, based on:
+ * - Guide to Mac Hardware
+ * - Guido Koerber's session with a logic analyzer
+ *
+ * MSch (1/98) Integrated start of IIsi driver by Robert Thompson
*/
#include <stdarg.h>
@@ -63,6 +65,9 @@
#define SR_DATA 0x08 /* Shift register data */
#define SR_CLOCK 0x10 /* Shift register clock */
+/* JRT */
+#define ADB_DELAY 150
+
static struct adb_handler {
void (*handler)(unsigned char *, int, struct pt_regs *);
} adb_handler[16];
@@ -88,6 +93,9 @@ static int prefix_len;
static int status = ST_IDLE|TREQ;
static int last_status;
+
+static int driver_running = 0;
+
/*static int adb_delay;*/
int in_keybinit = 1;
@@ -98,12 +106,19 @@ extern void adb_clock_interrupt(int irq, void *arg, struct pt_regs *regs);
extern void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs);
static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs);
+static void adb_hw_setup_IIsi(void);
+static void adb_hw_setup_cuda(void);
+
/*
- * Misc. defines for testing
+ * debug level 10 required for ADB logging (should be && debug_adb, ideally)
*/
extern int console_loglevel;
+/*
+ * Misc. defines for testing - should go to header :-(
+ */
+
#define ADBDEBUG_STATUS (1)
#define ADBDEBUG_STATE (2)
#define ADBDEBUG_READ (4)
@@ -118,11 +133,13 @@ extern int console_loglevel;
#define ADBDEBUG_INPUT (2048)
#define ADBDEBUG_DEVICE (4096)
+#define ADBDEBUG_IISI (8192)
+
-#define DEBUG_ADB
+/*#define DEBUG_ADB*/
#ifdef DEBUG_ADB
-#define ADBDEBUG (ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST)
+#define ADBDEBUG (ADBDEBUG_INPUT | ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST)
#else
#define ADBDEBUG (0)
#endif
@@ -132,7 +149,7 @@ extern int console_loglevel;
void adb_bus_init(void)
{
unsigned long flags;
- unsigned char c;
+ unsigned char c, i;
save_flags(flags);
cli();
@@ -174,31 +191,7 @@ void adb_bus_init(void)
via_write(via1, vIER, IER_SET|SR_INT);
/* This clears the interrupt bit */
via_write(via1, vIFR, SR_INT);
-#if 0
- ct=1000;
- while( ct-- && (via_read(via1, vBufB)&TREQ))
- udelay(1000);
- if(ct<0)
- printk("No sync occured\n");
- ct=1000;
- while( ct-- && !(via_read(via1, vIFR)&SR_INT))
- udelay(1000);
- if(ct<0)
- printk("No sync 2 occured\n");
- via_read(via1, vSR);
- via_write(via1, vBufB, via_read(via1, vBufB)|TACK);
- while( ct-- && !(via_read(via1, vBufB)&TREQ))
- udelay(1000);
- if(ct<0)
- printk("No sync 3 occured\n");
- ct=1000;
- while( ct-- && !(via_read(via1, vIFR)&SR_INT))
- udelay(1000);
- if(ct<0)
- printk("No sync 4 occured\n");
- via_read(via1, vSR);
- via_write(via1, vBufB, via_read(via1, vBufB)|TIP);
-#endif
+
/*
* Ok we probably ;) have a ready to use adb bus. Its also
* hopefully idle (Im assuming the mac didnt leave a half
@@ -214,20 +207,58 @@ void adb_bus_init(void)
*/
case MAC_ADB_CUDA:
printk("adb: CUDA interface.\n");
-#ifdef TRY_CUDA
+#if 0
/* don't know what to set up here ... */
adb_state = idle;
/* Set the lines up. We want TREQ as input TACK|TIP as output */
via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
+#endif
+ adb_hw_setup_cuda();
+ adb_state = idle;
request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK,
"adb CUDA interrupt", adb_cuda_interrupt);
break;
-#else
- goto nosupp;
-#endif
case MAC_ADB_IISI:
printk("adb: Using IIsi hardware.\n");
- goto nosupp;
+ printk("\tDEBUG_JRT\n");
+ /* Set the lines up. We want TREQ as input TACK|TIP as output */
+ via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
+
+ /*
+ * MSch: I'm pretty sure the setup is mildly wrong
+ * for the IIsi.
+ */
+ /* Initial state: idle (clear state bits) */
+ via_write(via1, vBufB, (via_read(via1, vBufB) & ~(TIP|TACK)) );
+ last_status = (via_read(via1, vBufB)&~ST_MASK);
+ /* Shift register on input */
+ c=via_read(via1, vACR);
+ c&=~SR_CTRL; /* Clear shift register bits */
+ c|=SR_EXT; /* Shift on external clock; out or in? */
+ via_write(via1, vACR, c);
+ /* Wipe any pending data and int */
+ via_read(via1, vSR);
+
+ /* This is interrupts on enable SR for keyboard */
+ via_write(via1, vIER, IER_SET|SR_INT);
+ /* This clears the interrupt bit */
+ via_write(via1, vIFR, SR_INT);
+
+ /* get those pesky clock ticks we missed while booting */
+ for ( i = 0; i < 30; i++) {
+ udelay(ADB_DELAY);
+ adb_hw_setup_IIsi();
+ udelay(ADB_DELAY);
+ if (via_read(via1, vBufB) & TREQ)
+ break;
+ }
+ /*
+ * Ok we probably ;) have a ready to use adb bus. Its also
+ */
+ request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK,
+ "adb interrupt", adb_cuda_interrupt);
+ adb_state = idle;
+ break;
default:
printk("adb: Unknown hardware interface.\n");
nosupp:
@@ -255,6 +286,171 @@ void adb_bus_init(void)
restore_flags(flags);
}
+void adb_hw_setup_cuda(void)
+{
+ int x;
+ unsigned long flags;
+
+ printk("CUDA: HW Setup:");
+
+ save_flags(flags);
+ cli();
+
+ if (console_loglevel == 10)
+ printk(" 1,");
+
+ /* Set the direction of the cuda signals, TIP+TACK are output TREQ is an input */
+ via_write( via1, vDirB, via_read( via1, vDirB ) | TIP | TACK );
+ via_write( via1, vDirB, via_read( via1, vDirB ) & ~TREQ );
+
+ if (console_loglevel == 10)
+ printk("2,");
+
+ /* Set the clock control. Set to shift data in by external clock CB1 */
+ via_write( via1, vACR, ( via_read(via1, vACR ) | SR_EXT ) & ~SR_OUT );
+
+ if (console_loglevel == 10)
+ printk("3,");
+
+ /* Clear any possible Cuda interrupt */
+ x = via_read( via1, vSR );
+
+ if (console_loglevel == 10)
+ printk("4,");
+
+ /* Terminate transaction and set idle state */
+ via_write( via1, vBufB, via_read( via1, vBufB ) | TIP | TACK );
+
+ if (console_loglevel == 10)
+ printk("5,");
+
+ /* Delay 4 mS for ADB reset to complete */
+ udelay(4000);
+
+ if (console_loglevel == 10)
+ printk("6,");
+
+ /* Clear pending interrupts... */
+ x = via_read( via1, vSR );
+
+ if (console_loglevel == 10)
+ printk("7,");
+ /* Issue a sync transaction, TACK asserted while TIP negated */
+ via_write( via1, vBufB, via_read( via1, vBufB ) & ~TACK );
+
+ if (console_loglevel == 10)
+ printk("8,");
+
+ /* Wait for the sync acknowledgement, Cuda to assert TREQ */
+ while( ( via_read( via1, vBufB ) & TREQ ) != 0 )
+ barrier();
+
+ if (console_loglevel == 10)
+ printk("9,");
+
+ /* Wait for the sync acknowledment interrupt */
+ while( ( via_read( via1, vIFR ) & SR_INT ) == 0 )
+ barrier();
+
+ if (console_loglevel == 10)
+ printk("10,");
+
+ /* Clear pending interrupts... */
+ x = via_read( via1, vSR );
+
+ if (console_loglevel == 10)
+ printk("11,");
+
+ /* Terminate the sync cycle by negating TACK */
+ via_write( via1, vBufB, via_read( via1, vBufB ) | TACK );
+
+ if (console_loglevel == 10)
+ printk("12,");
+
+ /* Wait for the sync termination acknowledgement, Cuda to negate TREQ */
+ while( ( via_read( via1, vBufB ) & TREQ ) == 0 )
+ barrier();
+
+ if (console_loglevel == 10)
+ printk("13,");
+
+ /* Wait for the sync termination acknowledment interrupt */
+ while( ( via_read( via1, vIFR ) & SR_INT ) == 0 )
+ barrier();
+
+ if (console_loglevel == 10)
+ printk("14,");
+
+ /* Terminate transaction and set idle state, TIP+TACK negate */
+ via_write( via1, vBufB, via_read( via1, vBufB ) | TIP );
+
+ if (console_loglevel == 10)
+ printk("15 !");
+
+ /* Clear pending interrupts... */
+ x = via_read( via1, vSR );
+
+ restore_flags(flags);
+
+ printk("\nCUDA: HW Setup done!\n");
+}
+
+void adb_hw_setup_IIsi(void)
+{
+ int dummy;
+ long poll_timeout;
+
+ printk("adb_IIsi: cleanup!\n");
+
+ /* ??? */
+ udelay(ADB_DELAY);
+
+ /* disable SR int. */
+ via_write(via1, vIER, IER_CLR|SR_INT);
+ /* set SR to shift in */
+ via_write(via1, vACR, via_read(via1, vACR ) & ~SR_OUT);
+
+ /* this is required, especially on faster machines */
+ udelay(ADB_DELAY);
+
+ if (!(via_read(via1, vBufB) & TREQ)) { /* IRQ on */
+ /* start frame */
+ via_write(via1, vBufB,via_read(via1,vBufB) | TIP);
+
+ while (1) {
+ /* poll for ADB interrupt and watch for timeout */
+ /* if time out, keep going in hopes of not hanging the
+ * ADB chip - I think */
+ poll_timeout = ADB_DELAY * 5;
+ while ( !(via_read(via1, vIFR) & SR_INT)
+ && (poll_timeout-- > 0) )
+ dummy = via_read(via1, vBufB);
+
+ dummy = via_read(via1, vSR); /* reset interrupt flag */
+
+ /* perhaps put in a check here that ignores all data
+ * after the first ADB_MAX_MSG_LENGTH bytes ??? */
+
+ /* end of frame reached ?? */
+ if (via_read(via1, vBufB) & TREQ)
+ break;
+
+ /* set ACK */
+ via_write(via1,vBufB,via_read(via1, vBufB) | TACK);
+ /* delay */
+ udelay(ADB_DELAY);
+ /* clear ACK */
+ via_write(via1,vBufB,via_read(via1, vBufB) & ~TACK);
+ }
+ /* end frame */
+ via_write(via1, vBufB,via_read(via1,vBufB) & ~TIP);
+ /* probably don't need to delay this long */
+ udelay(ADB_DELAY);
+ }
+ /* re-enable SR int. */
+ via_write(via1, vIER, IER_SET|SR_INT);
+}
+
#define WAIT_FOR(cond, what) \
do { \
for (x = 1000; !(cond); --x) { \
@@ -288,7 +484,7 @@ int adb_request(struct adb_request *req, void (*done)(struct adb_request *),
/*
* skip first byte if not CUDA
*/
- if (macintosh_config->adb_type != MAC_ADB_CUDA) {
+ if (macintosh_config->adb_type == MAC_ADB_II) {
start = va_arg(list, int);
nbytes--;
}
@@ -390,8 +586,12 @@ void adb_queue_poll(void)
printk("adb: Polling %d\n",pod);
#endif
- /* XXX: that's a TALK, register 0, MacII version */
- adb_build_request(&r,NULL, 1, (pod<<4|0xC));
+ if (macintosh_config->adb_type == MAC_ADB_II)
+ /* XXX: that's a TALK, register 0, MacII version */
+ adb_build_request(&r,NULL, 1, (pod<<4|0xC));
+ else
+ /* CUDA etc. version */
+ adb_build_request(&r,NULL, 2, 0, (pod<<4|0xC));
r.reply_expected=0;
r.done=NULL;
@@ -545,7 +745,7 @@ static void adb_start(void)
* IRQ signaled ?? (means ADB controller wants to send, or might
* be end of packet if we were reading)
*/
- if ((via_read(via1, vBufB)& TREQ) == 0)
+ if ((via_read(via1, vBufB) & TREQ) == 0)
{
switch(macintosh_config->adb_type)
{
@@ -560,7 +760,12 @@ static void adb_start(void)
/* printk("device busy - fail\n"); */
restore_flags(flags);
/* a byte is coming in from the CUDA */
- return;
+ return;
+ case MAC_ADB_IISI:
+ printk("adb_start: device busy - fail\n");
+ retry_req = req;
+ restore_flags(flags);
+ return;
case MAC_ADB_II:
/*
* if the interrupt handler set the need_poll
@@ -635,6 +840,19 @@ static void adb_start(void)
via_write(via1, vSR, req->data[0]);
via_write(via1, vBufB, via_read(via1, vBufB)&~TIP);
break;
+ case MAC_ADB_IISI:
+ /* store command byte (first byte is 'type' byte) */
+ command_byte = req->data[1];
+ /* set ADB state to 'active' */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
+ /* switch ACK off (in case it was left on) */
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ /* set the shift register to shift out and send a byte */
+ via_write(via1, vACR, via_read(via1, vACR) | SR_OUT);
+ via_write(via1, vSR, req->data[0]);
+ /* signal 'byte ready' */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+ break;
case MAC_ADB_II:
/* store command byte */
command_byte = req->data[0];
@@ -653,14 +871,14 @@ static void adb_start(void)
#endif
break;
}
+ adb_state = sent_first_byte;
+ data_index = 1;
#if (ADBDEBUG & ADBDEBUG_START)
if (console_loglevel == 10)
printk("sent first byte of %d: %x, (%x %x) ... ",
req->nbytes, req->data[0], adb_state,
(via_read(via1, vBufB) & (ST_MASK|TREQ)) );
#endif
- adb_state = sent_first_byte;
- data_index = 1;
restore_flags(flags);
}
@@ -748,16 +966,34 @@ void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs)
* and retransmit (Talk to the last active device). Cleanup of code and
* testing of the CUDA functionality is required, though.
* Note2: As of 13/12/97, CUDA support is definitely broken ...
+ * Note3: As of 21/12/97, CUDA works on a P475. What was broken? The assumption
+ * that Q700 and Q800 use CUDA :-(
+ *
+ * 27/01/98: IIsi driver implemented (thanks to Robert Thompson for the
+ * initial bits). See adb_cuda_interrupts ...
+ *
* Next TODO: implementation of IIsi ADB protocol (maybe the USE_ORIG
* conditionals can be a start?)
*/
void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
{
int x, adbdir;
+ unsigned long flags;
struct adb_request *req;
last_status = status;
+ /* prevent races due to SCSI enabling ints */
+ save_flags(flags);
+ cli();
+
+ if (driver_running) {
+ restore_flags(flags);
+ return;
+ }
+
+ driver_running = 1;
+
#ifdef USE_ORIG
status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT);
#else
@@ -774,7 +1010,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
adb_state, status, last_status, adbdir);
#endif
-
switch (adb_state)
{
case idle:
@@ -786,6 +1021,26 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
x = via_read(via1, vSR);
via_write(via1, vBufB, via_read(via1,vBufB)&~TIP);
}
+ else if(macintosh_config->adb_type==MAC_ADB_IISI)
+ {
+ udelay(150);
+ /* set SR to IN (??? no byte received else) */
+ via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
+ /* signal start of frame */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
+ /* read first byte */
+ x = via_read(via1, vSR);
+ first_byte = x;
+#if (ADBDEBUG & ADBDEBUG_READ)
+ if (console_loglevel == 10)
+ printk("adb_macIIsi : receiving unsol. packet: %x (%x %x) ",
+ x, adb_state, status);
+#endif
+ /* ACK adb chip */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+ udelay(150);
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ }
else if(macintosh_config->adb_type==MAC_ADB_II)
{
#if (ADBDEBUG & ADBDEBUG_STATUS)
@@ -801,12 +1056,8 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
printk("adb_macII: receiving unsol. packet: %x (%x %x) ",
x, adb_state, status);
#endif
-#ifdef USE_ORIG
- via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK));
-#else
/* set ADB state = even for first data byte */
via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
-#endif
}
adb_state = reading;
reply_ptr = cuda_rbuf;
@@ -831,7 +1082,34 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
x = via_read(via1, vSR);
via_write(via1,vBufB,
via_read(via1, vBufB)&~TIP);
- } else if(macintosh_config->adb_type==MAC_ADB_II) {
+ }
+ else if(macintosh_config->adb_type==MAC_ADB_IISI)
+ {
+ /* set SR to IN */
+ via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
+ /* signal start of frame */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
+ /* read first byte */
+ x = via_read(via1, vSR);
+ first_byte = x;
+#if (ADBDEBUG & ADBDEBUG_READ)
+ if (console_loglevel == 10)
+ printk("adb_macIIsi: reading reply: %x (%x %x) ",
+ x, adb_state, status);
+#endif
+#if 0
+ if( via_read(via1,vBufB) & TREQ)
+ ending = 1;
+ else
+ ending = 0;
+#endif
+ /* ACK adb chip */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+ udelay(150);
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ }
+ else if(macintosh_config->adb_type==MAC_ADB_II)
+ {
/* handshake etc. for II ?? */
x = via_read(via1, vSR);
first_byte = x;
@@ -840,12 +1118,8 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
printk("adb_macII: reading reply: %x (%x %x) ",
x, adb_state, status);
#endif
-#ifdef USE_ORIG
- via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK));
-#else
/* set ADB state = even for first data byte */
via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
-#endif
}
adb_state = reading;
reply_ptr = current_req->reply;
@@ -862,6 +1136,11 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
break;
case sent_first_byte:
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+ if (console_loglevel == 10)
+ printk(" sending: %x (%x %x) ",
+ current_req->data[1], adb_state, status);
+#endif
if(macintosh_config->adb_type==MAC_ADB_CUDA)
{
if (status == TREQ + TIP + SR_OUT)
@@ -886,14 +1165,45 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
adb_state = sending;
}
}
- else if(macintosh_config->adb_type==MAC_ADB_II)
+ else if(macintosh_config->adb_type==MAC_ADB_IISI)
{
- /* how to detect a collision here ?? */
+ /* switch ACK off */
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ if ( !(via_read(via1, vBufB) & TREQ) )
+ {
+ /* collision */
#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" sending: %x (%x %x) ",
- current_req->data[1], adb_state, status);
+ if (console_loglevel == 10)
+ printk("adb_macIIsi: send collison, aborting!\n");
+#endif
+ /* set shift in */
+ via_write(via1, vACR,
+ via_read(via1, vACR)&~SR_OUT);
+ /* clear SR int. */
+ x = via_read(via1, vSR);
+ /* set ADB state to 'idle' */
+ via_write(via1, vBufB,
+ via_read(via1,vBufB) & ~(TIP|TACK));
+ adb_state = idle;
+ }
+ else
+ {
+ /* delay */
+ udelay(ADB_DELAY);
+ /* set the shift register to shift out and send a byte */
+#if 0
+ via_write(via1, vACR, via_read(via1, vACR) | SR_OUT);
#endif
+ via_write(via1, vSR, current_req->data[1]);
+ /* signal 'byte ready' */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+ data_index=2;
+ adb_state = sending;
+ }
+ }
+ else if(macintosh_config->adb_type==MAC_ADB_II)
+ {
+ /* how to detect a collision here ?? */
/* maybe we're already done (Talk, or Poll)? */
if (data_index >= current_req->nbytes)
{
@@ -934,14 +1244,9 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
via_write(via1, vACR,
via_read(via1, vACR) & ~SR_OUT);
x=via_read(via1, vSR);
-#ifdef USE_ORIG
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
-#else
/* set ADB state idle - might get SRQ */
via_write(via1, vBufB,
(via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
-#endif
break;
}
#if (ADBDEBUG & ADBDEBUG_STATUS)
@@ -951,14 +1256,9 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
#endif
/* SR already set to shift out; send byte */
via_write(via1, vSR, current_req->data[1]);
-#ifdef USE_ORIG
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
-#else
/* set state to ST_EVEN (first byte was: ST_CMD) */
via_write(via1, vBufB,
(via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
-#endif
data_index=2;
adb_state = sending;
}
@@ -968,6 +1268,11 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
req = current_req;
if (data_index >= req->nbytes)
{
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+ if (console_loglevel == 10)
+ printk(" -> end (%d of %d) (%x %x)!\n",
+ data_index-1, req->nbytes, adb_state, status);
+#endif
/* end of packet */
if(macintosh_config->adb_type==MAC_ADB_CUDA)
{
@@ -977,29 +1282,34 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
via_write(via1, vBufB,
via_read(via1,vBufB)|TACK|TIP);
}
+ else if(macintosh_config->adb_type==MAC_ADB_IISI)
+ {
+ /* XXX maybe clear ACK here ??? */
+ /* switch ACK off */
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ /* delay */
+ udelay(ADB_DELAY);
+ /* set the shift register to shift in */
+ via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
+ /* clear SR int. */
+ x = via_read(via1, vSR);
+ /* set ADB state 'idle' (end of frame) */
+ via_write(via1, vBufB,
+ via_read(via1,vBufB) & ~(TACK|TIP));
+ }
else if(macintosh_config->adb_type==MAC_ADB_II)
{
/*
* XXX Not sure: maybe only switch to
* input mode on Talk ??
*/
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" -> end (%d of %d) (%x %x)!\n",
- data_index-1, req->nbytes, adb_state, status);
-#endif
/* set to shift in */
via_write(via1, vACR,
via_read(via1, vACR) & ~SR_OUT);
x=via_read(via1, vSR);
-#ifdef USE_ORIG
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
-#else
/* set ADB state idle - might get SRQ */
via_write(via1, vBufB,
(via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
-#endif
}
req->sent = 1;
if (req->reply_expected)
@@ -1008,7 +1318,12 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
* maybe fake a reply here on Listen ??
* Otherwise, a Listen hangs on success
*/
- if ( ((req->data[0]&0xc) == 0xc) )
+ if ( macintosh_config->adb_type==MAC_ADB_II
+ && ((req->data[0]&0xc) == 0xc) )
+ adb_state = awaiting_reply;
+ else if ( macintosh_config->adb_type != MAC_ADB_II
+ && ( req->data[0] == 0x0)
+ && ((req->data[1]&0xc) == 0xc) )
adb_state = awaiting_reply;
else {
/*
@@ -1063,34 +1378,46 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
}
else
{
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+ if (console_loglevel == 10)
+ printk(" %x (%x %x) ",
+ req->data[data_index], adb_state, status);
+#endif
if(macintosh_config->adb_type==MAC_ADB_CUDA)
{
via_write(via1, vSR, req->data[data_index++]);
via_write(via1, vBufB,
via_read(via1, vBufB)^TACK);
}
- else if(macintosh_config->adb_type==MAC_ADB_II)
+ else if(macintosh_config->adb_type==MAC_ADB_IISI)
{
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" %x (%x %x) ",
- req->data[data_index], adb_state, status);
+ /* switch ACK off */
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ /* delay */
+ udelay(ADB_DELAY);
+ /* XXX: need to check for collision?? */
+ /* set the shift register to shift out and send a byte */
+#if 0
+ via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
#endif
via_write(via1, vSR, req->data[data_index++]);
-#ifdef USE_ORIG
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
-#else
+ /* signal 'byte ready' */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+ }
+ else if(macintosh_config->adb_type==MAC_ADB_II)
+ {
+ via_write(via1, vSR, req->data[data_index++]);
/* invert state bits, toggle ODD/EVEN */
x = via_read(via1, vBufB);
via_write(via1, vBufB,
(x&~ST_MASK)|~(x&ST_MASK));
-#endif
}
}
break;
case reading:
+
+ /* timeout / SRQ handling for II hw */
#ifdef POLL_ON_TIMEOUT
if((reply_len-prefix_len)==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
#else
@@ -1128,16 +1455,12 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
x, adb_state, status);
#endif
-#ifdef USE_ORIG
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
-#else
#if 0 /* XXX leave status unchanged!! - need to check this again! */
+ /* XXX Only touch status on II !!! */
/* set ADB state to idle (required by adb_start()) */
via_write(via1, vBufB,
(via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
#endif
-#endif
/*
* What if the timeout happens on reading a
@@ -1206,6 +1529,7 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
*/
break;
}
+ /* end timeout / SRQ handling for II hw. */
if((reply_len-prefix_len)>3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
{
/* SRQ tacked on data packet */
@@ -1241,7 +1565,7 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
reply_len++;
}
/* The usual handshake ... */
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
+ if (macintosh_config->adb_type==MAC_ADB_CUDA)
{
if (status == TIP)
{
@@ -1259,7 +1583,27 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
via_read(via1, vBufB)^TACK);
}
}
- if(macintosh_config->adb_type==MAC_ADB_II)
+ else if (macintosh_config->adb_type==MAC_ADB_IISI)
+ {
+ /* ACK adb chip (maybe check for end first?) */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+ udelay(150);
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ /* end of frame?? */
+ if (status & TREQ)
+ {
+#if (ADBDEBUG & ADBDEBUG_READ)
+ if (console_loglevel == 10)
+ printk("adb_IIsi: end of frame!\n");
+#endif
+ /* that's all folks */
+ via_write(via1, vBufB,
+ via_read(via1, vBufB) & ~(TACK|TIP));
+ adb_state = read_done;
+ /* maybe process read_done here?? Handshake anyway?? */
+ }
+ }
+ else if (macintosh_config->adb_type==MAC_ADB_II)
{
/*
* NetBSD hints that the next to last byte
@@ -1277,10 +1621,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
if (console_loglevel == 10)
printk(" -> read done!\n");
#endif
-#ifdef USE_ORIG
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
-#else
#if 0 /* XXX: we take one more byte (why?), so handshake! */
/* set ADB state to idle */
via_write(via1, vBufB,
@@ -1291,7 +1631,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
via_write(via1, vBufB,
(x&~ST_MASK)|~(x&ST_MASK));
#endif
-#endif
/* adjust packet length */
reply_len--;
reply_ptr--;
@@ -1303,10 +1642,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
if(status!=TIP+TREQ)
printk("macII_adb: state=reading status=%x\n", status);
#endif
-#ifdef USE_ORIG
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
-#else
/* not caught: ST_CMD */
/* required for re-entry 'reading'! */
if ((status&ST_MASK) == ST_IDLE) {
@@ -1319,7 +1654,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
via_write(via1, vBufB,
(x&~ST_MASK)|~(x&ST_MASK));
}
-#endif
}
}
break;
@@ -1352,7 +1686,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
last_reply = command_byte;
last_active = (command_byte&0xf0)>>4;
-
/*
* Assert status = ST_IDLE ??
*/
@@ -1374,15 +1707,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
break;
}
-#ifdef USE_ORIG
- /*
- * This will fail - TREQ is active low -> 0 is IRQ !!
- */
- if (status == TREQ)
- {
- via_write(via1, vBufB,
- via_read(via1, vBufB)|~TIP);
-#else
/*
* /IRQ seen, so the ADB controller has data for us
*/
@@ -1391,7 +1715,7 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
/* set ADB state to idle */
via_write(via1, vBufB,
(via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
-#endif
+
adb_state = reading;
reply_ptr = cuda_rbuf;
reply_len = 0;
@@ -1422,35 +1746,81 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
printk("adb_interrupt: unknown adb_state %d?\n", adb_state);
#endif
}
+ /* reset mutex and interrupts */
+ driver_running = 0;
+ restore_flags(flags);
}
/*
* Restart of CUDA support: please modify this interrupt handler while
* working at the Quadra etc. ADB driver. We can try to merge them later, or
* remove the CUDA stuff from the MacII handler
+ *
+ * MSch 27/01/98: Implemented IIsi driver based on initial code by Robert
+ * Thompson and hints from the NetBSD driver. CUDA and IIsi seem more closely
+ * related than to the MacII code, so merging all three might be a bad
+ * idea.
*/
void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
{
int x, status;
struct adb_request *req;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
- status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT);
+ if(macintosh_config->adb_type==MAC_ADB_CUDA)
+ status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT);
+ else
+ status = via_read(via1, vBufB) & (TIP|TREQ);
+
+#if (ADBDEBUG & ADBDEBUG_INT)
if (console_loglevel == 10)
printk("adb_interrupt: state=%d status=%x\n", adb_state, status);
+#endif
switch (adb_state)
{
case idle:
+ first_byte = 0;
if(macintosh_config->adb_type==MAC_ADB_CUDA)
{
+#if (ADBDEBUG & ADBDEBUG_STATUS)
/* CUDA has sent us the first byte of data - unsolicited */
if (status != TREQ)
printk("cuda: state=idle, status=%x want=%x\n",
status, TREQ);
+#endif
x = via_read(via1, vSR);
+#if (ADBDEBUG & ADBDEBUG_READ)
+ if (console_loglevel == 10)
+ printk("adb_cuda: receiving unsol. packet: %x (%x %x) ",
+ x, adb_state, status);
+#endif
via_write(via1, vBufB, via_read(via1,vBufB)&~TIP);
}
+ else if(macintosh_config->adb_type==MAC_ADB_IISI)
+ {
+ udelay(150);
+ /* set SR to IN */
+ via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
+ /* signal start of frame */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
+ /* read first byte */
+ x = via_read(via1, vSR);
+ first_byte = x;
+#if (ADBDEBUG & ADBDEBUG_READ)
+ if (console_loglevel == 10)
+ printk("adb_IIsi : receiving unsol. packet: %x (%x %x) ",
+ x, adb_state, status);
+#endif
+ /* ACK adb chip */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+ udelay(150);
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ }
else if(macintosh_config->adb_type==MAC_ADB_II)
{
if (status != TREQ)
@@ -1469,13 +1839,46 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
if(macintosh_config->adb_type==MAC_ADB_CUDA)
{
/* CUDA has sent us the first byte of data of a reply */
+#if (ADBDEBUG & ADBDEBUG_STATUS)
if (status != TREQ)
printk("cuda: state=awaiting_reply, status=%x want=%x\n",
status, TREQ);
+#endif
x = via_read(via1, vSR);
+#if (ADBDEBUG & ADBDEBUG_READ)
+ if (console_loglevel == 10)
+ printk("adb_cuda: reading reply: %x (%x %x) ",
+ x, adb_state, status);
+#endif
via_write(via1,vBufB,
via_read(via1, vBufB)&~TIP);
}
+ else if(macintosh_config->adb_type==MAC_ADB_IISI)
+ {
+ /* udelay(150);*/
+ /* set SR to IN */
+ via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
+ /* signal start of frame */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
+ /* read first byte */
+ x = via_read(via1, vSR);
+ first_byte = x;
+#if (ADBDEBUG & ADBDEBUG_READ)
+ if (console_loglevel == 10)
+ printk("adb_IIsi: reading reply: %x (%x %x) ",
+ x, adb_state, status);
+#endif
+#if 0
+ if( via_read(via1,vBufB) & TREQ)
+ ending = 1;
+ else
+ ending = 0;
+#endif
+ /* ACK adb chip */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+ udelay(150);
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ }
adb_state = reading;
reply_ptr = current_req->reply;
reading_reply = 1;
@@ -1485,11 +1888,16 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
case sent_first_byte:
if(macintosh_config->adb_type==MAC_ADB_CUDA)
{
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+ if (console_loglevel == 10)
+ printk(" sending: %x (%x %x) ",
+ current_req->data[1], adb_state, status);
+#endif
if (status == TREQ + TIP + SR_OUT)
{
/* collision */
if (console_loglevel == 10)
- printk("cuda: send collision!\n");
+ printk("adb_cuda: send collision!\n");
via_write(via1, vACR,
via_read(via1, vACR)&~SR_OUT);
x = via_read(via1, vSR);
@@ -1500,9 +1908,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
else
{
/* assert status == TIP + SR_OUT */
+#if (ADBDEBUG & ADBDEBUG_STATUS)
if (status != TIP + SR_OUT)
- printk("cuda: state=sent_first_byte status=%x want=%x\n",
+ printk("adb_cuda: state=sent_first_byte status=%x want=%x\n",
status, TIP + SR_OUT);
+#endif
via_write(via1,vSR,current_req->data[1]);
via_write(via1, vBufB,
via_read(via1, vBufB)^TACK);
@@ -1510,6 +1920,42 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
adb_state = sending;
}
}
+ else if(macintosh_config->adb_type==MAC_ADB_IISI)
+ {
+ /* switch ACK off */
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ if ( !(via_read(via1, vBufB) & TREQ) )
+ {
+ /* collision */
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+ if (console_loglevel == 10)
+ printk("adb_macIIsi: send collison, aborting!\n");
+#endif
+ /* set shift in */
+ via_write(via1, vACR,
+ via_read(via1, vACR)&~SR_OUT);
+ /* clear SR int. */
+ x = via_read(via1, vSR);
+ /* set ADB state to 'idle' */
+ via_write(via1, vBufB,
+ via_read(via1,vBufB) & ~(TIP|TACK));
+ adb_state = idle;
+ }
+ else
+ {
+ /* delay */
+ udelay(ADB_DELAY);
+ /* set the shift register to shift out and send a byte */
+#if 0
+ via_write(via1, vACR, via_read(via1, vACR) | SR_OUT);
+#endif
+ via_write(via1, vSR, current_req->data[1]);
+ /* signal 'byte ready' */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+ data_index=2;
+ adb_state = sending;
+ }
+ }
else if(macintosh_config->adb_type==MAC_ADB_II)
{
if(status!=TIP+SR_OUT)
@@ -1527,6 +1973,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
req = current_req;
if (data_index >= req->nbytes)
{
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+ if (console_loglevel == 10)
+ printk(" -> end (%d of %d) (%x %x)!\n",
+ data_index-1, req->nbytes, adb_state, status);
+#endif
if(macintosh_config->adb_type==MAC_ADB_CUDA)
{
via_write(via1, vACR,
@@ -1535,6 +1986,21 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
via_write(via1, vBufB,
via_read(via1,vBufB)|TACK|TIP);
}
+ else if(macintosh_config->adb_type==MAC_ADB_IISI)
+ {
+ /* XXX maybe clear ACK here ??? */
+ /* switch ACK off */
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ /* delay */
+ udelay(ADB_DELAY);
+ /* set the shift register to shift in */
+ via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
+ /* clear SR int. */
+ x = via_read(via1, vSR);
+ /* set ADB state 'idle' (end of frame) */
+ via_write(via1, vBufB,
+ via_read(via1,vBufB) & ~(TACK|TIP));
+ }
else if(macintosh_config->adb_type==MAC_ADB_II)
{
via_write(via1, vACR,
@@ -1546,7 +2012,40 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
req->sent = 1;
if (req->reply_expected)
{
- adb_state = awaiting_reply;
+ /*
+ * maybe fake a reply here on Listen ??
+ * Otherwise, a Listen hangs on success
+ * CUDA+IIsi: only ADB Talk considered
+ * RTC/PRAM read (0x1 0x3) to follow.
+ */
+ if ( (req->data[0] == 0x0) && ((req->data[1]&0xc) == 0xc) )
+ adb_state = awaiting_reply;
+ else {
+ /*
+ * Reply expected, but none
+ * possible -> fake reply.
+ */
+#if (ADBDEBUG & ADBDEBUG_PROT)
+ printk("ADB: reply expected on Listen, faking reply\n");
+#endif
+ /* make it look weird */
+ /* XXX: return reply_len -1? */
+ /* XXX: fake ADB header? */
+ req->reply[0] = req->reply[1] = req->reply[2] = 0xFF;
+ req->reply_len = 3;
+ req->got_reply = 1;
+ current_req = req->next;
+ if (req->done)
+ (*req->done)(req);
+ /*
+ * ready with this one, run
+ * next command !
+ */
+ /* set state to idle !! */
+ adb_state = idle;
+ if (current_req || retry_req)
+ adb_start();
+ }
}
else
{
@@ -1560,12 +2059,32 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
}
else
{
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+ if (console_loglevel == 10)
+ printk(" %x (%x %x) ",
+ req->data[data_index], adb_state, status);
+#endif
if(macintosh_config->adb_type==MAC_ADB_CUDA)
{
via_write(via1, vSR, req->data[data_index++]);
via_write(via1, vBufB,
via_read(via1, vBufB)^TACK);
}
+ else if(macintosh_config->adb_type==MAC_ADB_IISI)
+ {
+ /* switch ACK off */
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ /* delay */
+ udelay(ADB_DELAY);
+ /* XXX: need to check for collision?? */
+ /* set the shift register to shift out and send a byte */
+#if 0
+ via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
+#endif
+ via_write(via1, vSR, req->data[data_index++]);
+ /* signal 'byte ready' */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+ }
else if(macintosh_config->adb_type==MAC_ADB_II)
{
via_write(via1, vSR, req->data[data_index++]);
@@ -1579,14 +2098,17 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
if(reply_len==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
{
/* Terminate the SRQ packet */
- printk("CUDA: Got an SRQ\n");
+#if (ADBDEBUG & ADBDEBUG_SRQ)
+ if (console_loglevel == 10)
+ printk("adb: Got an SRQ\n");
+#endif
adb_state = idle;
adb_queue_poll();
break;
}
/* Sanity check - botched in orig. code! */
if(reply_len>15) {
- printk("CUDA: reply buffer overrun!\n");
+ printk("adb_cuda: reply buffer overrun!\n");
/* wrap buffer */
reply_len=0;
if (reading_reply)
@@ -1595,9 +2117,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
reply_ptr = cuda_rbuf;
}
*reply_ptr = via_read(via1, vSR);
+#if (ADBDEBUG & ADBDEBUG_READ)
if (console_loglevel == 10)
- printk(" %p-> %x (%x %x) ",
- reply_ptr, *reply_ptr, adb_state, status);
+ printk(" %x (%x %x) ",
+ *reply_ptr, adb_state, status);
+#endif
reply_ptr++;
reply_len++;
if(macintosh_config->adb_type==MAC_ADB_CUDA)
@@ -1612,13 +2136,36 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
else
{
/* assert status == TIP | TREQ */
+#if (ADBDEBUG & ADBDEBUG_STATUS)
if (status != TIP + TREQ)
printk("cuda: state=reading status=%x want=%x\n",
status, TIP + TREQ);
+#endif
via_write(via1, vBufB,
via_read(via1, vBufB)^TACK);
}
}
+ else if (macintosh_config->adb_type==MAC_ADB_IISI)
+ {
+ /* ACK adb chip (maybe check for end first?) */
+ via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+ udelay(150);
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+ /* end of frame?? */
+ if (status & TREQ)
+ {
+#if (ADBDEBUG & ADBDEBUG_READ)
+ if (console_loglevel == 10)
+ printk("adb_IIsi: end of frame!\n");
+#endif
+ /* that's all folks */
+ via_write(via1, vBufB,
+ via_read(via1, vBufB) & ~(TACK|TIP));
+ adb_state = read_done;
+ /* XXX maybe process read_done here??
+ Handshake anyway?? */
+ }
+ }
if(macintosh_config->adb_type==MAC_ADB_II)
{
if( status == TIP)
@@ -1629,16 +2176,26 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
}
else
{
+#if (ADBDEBUG & ADBDEBUG_STATUS)
if(status!=TIP+TREQ)
printk("macII_adb: state=reading status=%x\n", status);
+#endif
via_write(via1, vBufB,
via_read(via1, vBufB)^TACK);
}
}
- break;
+ /* fall through for IIsi on end of frame */
+ if (macintosh_config->adb_type != MAC_ADB_IISI
+ || adb_state != read_done)
+ break;
case read_done:
x = via_read(via1, vSR);
+#if (ADBDEBUG & ADBDEBUG_READ)
+ if (console_loglevel == 10)
+ printk("adb: read done: %x (%x %x)!\n",
+ x, adb_state, status);
+#endif
if (reading_reply)
{
req = current_req;
@@ -1653,10 +2210,21 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
adb_input(cuda_rbuf, reply_ptr - cuda_rbuf, regs);
}
- if (status == TREQ)
+ if (macintosh_config->adb_type==MAC_ADB_CUDA
+ && status & TREQ)
+ {
+ via_write(via1, vBufB,
+ via_read(via1, vBufB)&~TIP);
+ adb_state = reading;
+ reply_ptr = cuda_rbuf;
+ reading_reply = 0;
+ }
+ else if (macintosh_config->adb_type==MAC_ADB_IISI
+ && !(status & TREQ))
{
+ udelay(150);
via_write(via1, vBufB,
- via_read(via1, vBufB)|~TIP);
+ via_read(via1, vBufB) | TIP);
adb_state = reading;
reply_ptr = cuda_rbuf;
reading_reply = 0;
@@ -1669,8 +2237,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
break;
default:
- printk("adb_interrupt: unknown adb_state %d?\n", adb_state);
+ printk("adb_cuda_interrupt: unknown adb_state %d?\n", adb_state);
}
+
+ restore_flags(flags);
+
}
/*
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index d711dd7b3..fe77ded05 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -35,20 +35,16 @@
#include <asm/macintosh.h>
#include <asm/macints.h>
+#include <asm/machw.h>
#include "via6522.h"
-/* old bootinfo stuff */
+/* Mac bootinfo struct */
struct mac_booter_data mac_bi_data = {0,};
int mac_bisize = sizeof mac_bi_data;
-struct compat_bootinfo compat_boot_info ={0,};
-int compat_bisize = sizeof compat_boot_info;
-
-int compat_bi = 0;
-
-/* New bootinfo stuff */
+/* New m68k bootinfo stuff and videobase */
extern int m68k_num_memory;
extern struct mem_info m68k_memory[NUM_MEMINFO];
@@ -59,42 +55,67 @@ extern char m68k_command_line[CL_SIZE];
void *mac_env; /* Loaded by the boot asm */
+/* The logical video addr. determined by head.S - testing */
+extern unsigned long mac_videobase;
+
+/* The phys. video addr. - might be bogus on some machines */
+unsigned long mac_orig_videoaddr;
+
+/* Mac specific keyboard functions */
extern int mac_keyb_init(void);
extern int mac_kbdrate(struct kbd_repeat *k);
extern void mac_kbd_leds(unsigned int leds);
+extern void mac_kbd_reset_setup(char*, int);
+
+/* Mac specific irq functions */
+extern void mac_init_IRQ (void);
+extern void (*mac_handlers[]) (int, void *, struct pt_regs *);
+extern int mac_request_irq (unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname,
+ void *dev_id);
+extern void mac_free_irq (unsigned int irq, void *dev_id);
+extern void mac_enable_irq (unsigned int);
+extern void mac_disable_irq (unsigned int);
+static void mac_get_model(char *model);
+/*static int mac_get_hardware_list(char *buffer);*/
+extern int mac_get_irq_list (char *);
+
+/* Mac specific timer functions */
+extern unsigned long mac_gettimeoffset (void);
+extern void mac_gettod (int *, int *, int *, int *, int *, int *);
+extern int mac_hwclk (int, struct hwclk_time *);
+extern int mac_set_clock_mmss (unsigned long);
+extern void via_init_clock(void (*func)(int, void *, struct pt_regs *));
extern void (*kd_mksound)(unsigned int, unsigned int);
extern void mac_mksound(unsigned int, unsigned int);
extern int mac_floppy_init(void);
extern void mac_floppy_setup(char *,int *);
-extern void mac_gettod (int *, int *, int *, int *, int *, int *);
-
extern void nubus_sweep_video(void);
-extern void via_init_clock(void (*func)(int, void *, struct pt_regs *));
-extern void mac_debugging_long(int, long);
/* Mac specific debug functions (in debug.c) */
extern void mac_debug_init(void);
+extern void mac_debugging_long(int, long);
#ifdef CONFIG_MAGIC_SYSRQ
+
+/* XXX FIXME: Atari scancodes still */
static char mac_sysrq_xlate[128] =
- "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
- "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
- "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
- "bnm,./\000\000\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
+ "bnm,./\000\000\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
"\206\207\210\211\212\000\000\000\000\000-\000\000\000+\000"/* 0x40 - 0x4f */
"\000\000\000\177\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
- "\000\000\000()/*789456123" /* 0x60 - 0x6f */
+ "\000\000\000()/*789456123" /* 0x60 - 0x6f */
"0.\r\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */
#endif
extern void (*kd_mksound)(unsigned int, unsigned int);
-void mac_get_model(char *str)
-{
- strcpy(str,"Macintosh");
-}
+static void mac_get_model(char *str);
void mac_bang(int irq, void *vector, struct pt_regs *p)
{
@@ -107,27 +128,22 @@ void mac_sched_init(void (*vector)(int, void *, struct pt_regs *))
via_init_clock(vector);
}
-unsigned long mac_gettimeoffset (void)
-{
- return 0L;
-}
-
extern int console_loglevel;
+/*
+ * This function translates the boot timeval into a proper date, to initialize
+ * the system time.
+ */
+
void mac_gettod (int *yearp, int *monp, int *dayp,
int *hourp, int *minp, int *secp)
{
unsigned long time;
int leap, oldleap, isleap;
- int mon_days[14] = { -1, 31, 27, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1 };
+ int mon_days[14] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1 };
time = mac_bi_data.boottime - 60*mac_bi_data.gmtbias; /* seconds */
-#if 0
- printk("mac_gettod: boottime 0x%lx gmtbias %ld \n",
- mac_bi_data.boottime, mac_bi_data.gmtbias);
-#endif
-
*minp = time / 60;
*secp = time - (*minp * 60);
time = *minp; /* minutes now */
@@ -143,7 +159,7 @@ void mac_gettod (int *yearp, int *monp, int *dayp,
/* for leap day calculation */
*yearp = (time / 365) + 1970; /* approx. year */
- /* leap year calculation - there's an easier way, I bet */
+ /* leap year calculation - there's an easier way, I bet. And it's broken :-( */
/* calculate leap days up to previous year */
oldleap = (*yearp-1)/4 - (*yearp-1)/100 + (*yearp-1)/400;
/* calculate leap days incl. this year */
@@ -161,7 +177,7 @@ void mac_gettod (int *yearp, int *monp, int *dayp,
time = *dayp;
if (isleap) /* add leap day ?? */
- mon_days[2] = 28;
+ mon_days[2] += 1;
/* count the months */
for (*monp = 1; time > mon_days[*monp]; (*monp)++)
@@ -169,15 +185,29 @@ void mac_gettod (int *yearp, int *monp, int *dayp,
*dayp = time;
-#if 1
- printk("mac_gettod: %d-%d-%d %d:%d.%d GMT (GMT offset %d)\n",
- *yearp, *monp, *dayp, *hourp, *minp, *secp,
- (signed long) mac_bi_data.gmtbias);
-#endif
-
return;
}
+/*
+ * TBI: read and write hwclock
+ */
+
+int mac_hwclk( int op, struct hwclk_time *t )
+{
+ return 0;
+}
+
+/*
+ * TBI: set minutes/seconds in hwclock
+ */
+
+int mac_set_clock_mmss (unsigned long nowtime)
+{
+ short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
+
+ return 0;
+}
+
void mac_waitbut (void)
{
;
@@ -187,11 +217,6 @@ extern struct consw fb_con;
extern struct fb_info *mac_fb_init(long *);
extern void mac_video_setup(char *, int *);
-void mac_debug_init (void)
-{
- ;
-}
-
void (*mac_handlers[8])(int, void *, struct pt_regs *)=
{
mac_default_handler,
@@ -213,15 +238,14 @@ __initfunc(int mac_parse_bootinfo(const struct bi_record *record))
int unknown = 0;
const u_long *data = record->data;
- if (compat_bi)
- return(unknown);
-
switch (record->tag) {
case BI_MAC_MODEL:
mac_bi_data.id = *data;
break;
case BI_MAC_VADDR:
- mac_bi_data.videoaddr = *data;
+ /* save booter supplied videobase; use the one mapped in head.S! */
+ mac_orig_videoaddr = *data;
+ mac_bi_data.videoaddr = mac_videobase;
break;
case BI_MAC_VDEPTH:
mac_bi_data.videodepth = *data;
@@ -256,39 +280,6 @@ __initfunc(int mac_parse_bootinfo(const struct bi_record *record))
return(unknown);
}
-__initfunc(void mac_copy_compat(void))
-{
- int i;
-
- compat_bi = 1;
-
- for (i=0; i<compat_boot_info.num_memory; i++) {
- m68k_memory[m68k_num_memory].addr = compat_boot_info.memory[i].addr;
- m68k_memory[m68k_num_memory].size = compat_boot_info.memory[i].size;
- m68k_num_memory++;
- }
-
- m68k_ramdisk.addr = compat_boot_info.ramdisk_addr;
- m68k_ramdisk.size = compat_boot_info.ramdisk_size;
-
- strncpy(m68k_command_line, (const char *)compat_boot_info.command_line,
- CL_SIZE);
- m68k_command_line[CL_SIZE-1] = '\0';
-
- mac_bi_data.id = compat_boot_info.bi_mac.id;
- mac_bi_data.videoaddr = compat_boot_info.bi_mac.videoaddr;
- mac_bi_data.videodepth = compat_boot_info.bi_mac.videodepth;
- mac_bi_data.videorow = compat_boot_info.bi_mac.videorow;
- mac_bi_data.dimensions = compat_boot_info.bi_mac.dimensions;
- mac_bi_data.videological = compat_boot_info.bi_mac.videological;
- mac_bi_data.sccbase = compat_boot_info.bi_mac.sccbase;
- mac_bi_data.boottime = compat_boot_info.bi_mac.boottime;
- mac_bi_data.gmtbias = compat_boot_info.bi_mac.gmtbias;
- mac_bi_data.memsize = compat_boot_info.bi_mac.memsize;
- mac_bi_data.cpuid = compat_boot_info.bi_mac.cpuid;
-
-}
-
__initfunc(void config_mac(void))
{
@@ -296,14 +287,13 @@ __initfunc(void config_mac(void))
printk("ERROR: no Mac, but config_mac() called!! \n");
}
- mac_debugging_penguin(5);
-
mac_debug_init();
mach_sched_init = mac_sched_init;
mach_keyb_init = mac_keyb_init;
mach_kbdrate = mac_kbdrate;
mach_kbd_leds = mac_kbd_leds;
+ kbd_reset_setup = mac_kbd_reset_setup;
mach_init_IRQ = mac_init_IRQ;
mach_request_irq = mac_request_irq;
mach_free_irq = mac_free_irq;
@@ -316,15 +306,13 @@ __initfunc(void config_mac(void))
mach_get_irq_list = mac_get_irq_list;
mach_gettimeoffset = mac_gettimeoffset;
mach_gettod = mac_gettod;
+ mach_hwclk = mac_hwclk;
+ mach_set_clock_mmss = mac_set_clock_mmss;
#if 0
mach_mksound = mac_mksound;
#endif
mach_reset = mac_reset;
-#ifdef CONFIG_BLK_DEV_FD
- mach_floppy_init = mac_floppy_init;
- mach_floppy_setup = mac_floppy_setup;
-#endif
- conswitchp = &fb_con;
+ conswitchp = &dummy_con;
mach_max_dma_address = 0xffffffff;
#if 0
mach_debug_init = mac_debug_init;
@@ -361,11 +349,20 @@ __initfunc(void config_mac(void))
*/
nubus_sweep_video();
+
}
/*
- * Macintosh Table
+ * Macintosh Table: hardcoded model configuration data.
+ *
+ * Much of this was defined by Alan, based on who knows what docs.
+ * I've added a lot more, and some of that was pure guesswork based
+ * on hardware pages present on the Mac web site. Possibly wildly
+ * inaccurate, so look here if a new Mac model won't run. Example: if
+ * a Mac crashes immediately after the VIA1 registers have been dumped
+ * to the screen, it probably died attempting to read DirB on a RBV.
+ * Meaning it should have MAC_VIA_IIci here :-)
*/
struct mac_model *macintosh_config;
@@ -389,10 +386,11 @@ static struct mac_model mac_data_table[]=
*
* The IIfx apparently has different ADB hardware, and stuff
* so zany nobody knows how to drive it.
+ * Even so, with Marten's help we'll try to deal with it :-)
*/
{ MAC_MODEL_IICI, "IIci", MAC_ADB_II, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_IIFX, "IIfx", MAC_ADB_NONE, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_IIFX, "IIfx", MAC_ADB_II, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_IISI, "IIsi", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_IIVI, "IIvi", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_IIVX, "IIvx", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
@@ -405,9 +403,10 @@ static struct mac_model mac_data_table[]=
{ MAC_MODEL_CCL, "Color Classic", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
/*
- * Some Mac LC machines. Basically the same as the IIci
+ * Some Mac LC machines. Basically the same as the IIci, ADB like IIsi
*/
+ { MAC_MODEL_LC, "LC", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_LCII, "LC II", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_LCIII,"LC III", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
@@ -416,75 +415,74 @@ static struct mac_model mac_data_table[]=
* 0xF9000000, via is like a MacII. We label it differently as some of the
* stuff connected to VIA2 seems different. Better SCSI chip and ???? onboard ethernet
* in all cases using a NatSemi SONIC. The 700, 900 and 950 have some I/O chips in the wrong
- * place to confuse us. The 840 seems to have a scsi location of its own
+ * place to confuse us. The 840AV seems to have a scsi location of its own
*/
- { MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
- { MAC_MODEL_Q610, "Quadra 610", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
- { MAC_MODEL_Q630, "Quadra 630", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
- { MAC_MODEL_Q650, "Quadra 650", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
+ { MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
+ { MAC_MODEL_Q610, "Quadra 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
+ { MAC_MODEL_Q630, "Quadra 630", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_QUADRA, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
+ { MAC_MODEL_Q650, "Quadra 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
/* The Q700 does have a NS Sonic */
-#if 0
- { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS},
- { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
-#else
- { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS},
- { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
-#endif
- /* Does the 840 have ethernet ??? documents seem to indicate its not quite a
+ { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS},
+ { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
+ /* Does the 840AV have ethernet ??? documents seem to indicate its not quite a
Quadra in this respect ? */
- { MAC_MODEL_Q840, "Quadra 840", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_Q900, "Quadra 900", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS},
- { MAC_MODEL_Q950, "Quadra 950", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS},
+ { MAC_MODEL_Q840, "Quadra 840AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ /* These might have IOP problems */
+ { MAC_MODEL_Q900, "Quadra 900", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS},
+ { MAC_MODEL_Q950, "Quadra 950", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS},
/*
* Performa - more LC type machines
*/
- { MAC_MODEL_P460, "Performa 460", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_TV, "TV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_P460, "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_P475F, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_P588, "Performa 588", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_TV, "TV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_P600, "Performa 600", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
#if 0 /* other sources seem to suggest the P630/Q630/LC630 is more like LCIII */
- { MAC_MODEL_P630, "Performa 630", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_P630, "Performa 630", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
#endif
/*
* Centris - just guessing again; maybe like Quadra
*/
- { MAC_MODEL_C610, "Centris 610", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_C650, "Centris 650", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_C610, "Centris 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_C650, "Centris 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
/*
* Power books - seem similar to early Quadras ? (most have 030 though)
*/
- { MAC_MODEL_PB140, "PowerBook 140", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB145, "PowerBook 145", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB140, "PowerBook 140", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB145, "PowerBook 145", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
/* The PB150 has IDE, and IIci style VIA */
- { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB160, "PowerBook 160", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB165, "PowerBook 165", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB165C, "PowerBook 165c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB170, "PowerBook 170", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB180, "PowerBook 180", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB180C, "PowerBook 180c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB190, "PowerBook 190cs", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB520, "PowerBook 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_PB1, MAC_VIA_IIci, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB160, "PowerBook 160", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB165, "PowerBook 165", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB165C, "PowerBook 165c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB170, "PowerBook 170", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB180, "PowerBook 180", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB180C, "PowerBook 180c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB190, "PowerBook 190cs", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB520, "PowerBook 520", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
/*
* Power book Duos - similar to Power books, I hope
*/
- { MAC_MODEL_PB210, "PowerBook Duo 210", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB230, "PowerBook Duo 230", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB250, "PowerBook Duo 250", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB270C, "PowerBook Duo 270c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB280, "PowerBook Duo 280", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB280C, "PowerBook Duo 280c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB210, "PowerBook Duo 210", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB230, "PowerBook Duo 230", MAC_ADB_PB2, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB250, "PowerBook Duo 250", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB270C, "PowerBook Duo 270c", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB280, "PowerBook Duo 280", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB280C, "PowerBook Duo 280c", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
/*
* Other stuff ??
@@ -517,8 +515,6 @@ void mac_identify(void)
{
printk("\nUnknown macintosh model %d, probably unsupported.\n",
model);
- mac_debugging_long(1, (long) 0x55555555);
- mac_debugging_long(1, (long) model);
model = MAC_MODEL_Q800;
printk("Defaulting to: Quadra800, model id %d\n", model);
printk("Please report this case to linux-mac68k@wave.lm.com\n");
@@ -536,19 +532,22 @@ void mac_identify(void)
/*
* Report booter data:
*/
- printk (" Penguin (bootinfo version %d) data:\n", 2-compat_bi);
- printk (" Video: addr 0x%lx row 0x%lx depth %lx dimensions %d x %d\n",
+ printk (" Penguin bootinfo data:\n");
+ printk (" Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n",
mac_bi_data.videoaddr, mac_bi_data.videorow,
- mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF,
- mac_bi_data.dimensions >> 16);
+ mac_bi_data.videodepth, (int) (mac_bi_data.dimensions & 0xFFFF),
+ (int) (mac_bi_data.dimensions >> 16));
+ printk (" Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
+ mac_bi_data.videological, mac_orig_videoaddr,
+ mac_bi_data.sccbase);
printk (" Boottime: 0x%lx GMTBias: 0x%lx \n",
mac_bi_data.boottime, mac_bi_data.gmtbias);
- printk (" Videological 0x%lx, SCC at 0x%lx \n",
- mac_bi_data.videological, mac_bi_data.sccbase);
printk (" Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize);
+#if 0
printk ("Ramdisk: addr 0x%lx size 0x%lx\n",
m68k_ramdisk.addr, m68k_ramdisk.size);
+#endif
/*
* Save the pointer
@@ -559,6 +558,25 @@ void mac_identify(void)
/*
* TODO: set the various fields in macintosh_config->hw_present here!
*/
+ switch (macintosh_config->scsi_type) {
+ case MAC_SCSI_OLD:
+ MACHW_SET(MAC_SCSI_80);
+ break;
+ case MAC_SCSI_QUADRA:
+ case MAC_SCSI_QUADRA2:
+ case MAC_SCSI_QUADRA3:
+ MACHW_SET(MAC_SCSI_96);
+ if ((macintosh_config->ident == MAC_MODEL_Q900) ||
+ (macintosh_config->ident == MAC_MODEL_Q950))
+ MACHW_SET(MAC_SCSI_96_2);
+ break;
+ default:
+ printk("config.c: wtf: unknown scsi, using 53c80\n");
+ MACHW_SET(MAC_SCSI_80);
+ break;
+
+ }
+
}
@@ -567,6 +585,12 @@ void mac_report_hardware(void)
printk("Apple Macintosh %s\n", macintosh_config->name);
}
+static void mac_get_model(char *str)
+{
+ strcpy(str,"Macintosh ");
+ strcat(str, macintosh_config->name);
+}
+
/*
* Local variables:
* c-indent-level: 4
diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c
index cc6f491fb..6fc3ac52d 100644
--- a/arch/m68k/mac/debug.c
+++ b/arch/m68k/mac/debug.c
@@ -16,6 +16,7 @@
#include <linux/config.h>
#include <linux/types.h>
+#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/init.h>
@@ -35,6 +36,9 @@ extern unsigned long mac_videobase;
extern unsigned long mac_videodepth;
extern unsigned long mac_rowbytes;
+#define DEBUG_SCREEN
+#define DEBUG_SERIAL
+
/*
* These two auxiliary debug functions should go away ASAP. Only usage:
* before the console output is up (after head.S come some other crucial
@@ -45,21 +49,30 @@ extern unsigned long mac_rowbytes;
* The 'pos' argument now simply means 'linefeed after print' ...
*/
+#ifdef DEBUG_SCREEN
static int peng=0, line=0;
+#endif
void mac_debugging_short(int pos, short num)
{
+#ifdef DEBUG_SCREEN
unsigned char *pengoffset;
unsigned char *pptr;
int i;
+#endif
+
+#ifdef DEBUG_SERIAL
+ printk("debug: %d !\n", num);
+#endif
+#ifdef DEBUG_SCREEN
if (!MACH_IS_MAC) {
/* printk("debug: %d !\n", num); */
return;
}
/* calculate current offset */
- pengoffset=(unsigned char *)(mac_videobase+(20+line*2)*mac_rowbytes)
+ pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
+80*peng;
pptr=pengoffset;
@@ -76,20 +89,28 @@ void mac_debugging_short(int pos, short num)
line++;
peng = 0;
}
+#endif
}
void mac_debugging_long(int pos, long addr)
{
+#ifdef DEBUG_SCREEN
unsigned char *pengoffset;
unsigned char *pptr;
int i;
+#endif
+#ifdef DEBUG_SERIAL
+ printk("debug: #%ld !\n", addr);
+#endif
+
+#ifdef DEBUG_SCREEN
if (!MACH_IS_MAC) {
/* printk("debug: #%ld !\n", addr); */
return;
}
- pengoffset=(unsigned char *)(mac_videobase+(20+line*2)*mac_rowbytes)
+ pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
+80*peng;
pptr=pengoffset;
@@ -105,6 +126,7 @@ void mac_debugging_long(int pos, long addr)
line++;
peng = 0;
}
+#endif
}
/*
@@ -114,24 +136,33 @@ char that_penguin[]={
#include "that_penguin.h"
};
+#ifdef DEBUG_SCREEN
/*
* B/W version of penguin, unfinished - any takers??
*/
static char bw_penguin[]={
#include "bw_penguin.h"
};
+#endif
void mac_debugging_penguin(int peng)
{
+#ifdef DEBUG_SCREEN
unsigned char *pengoffset;
unsigned char *pptr;
unsigned char *bwpdptr=bw_penguin;
int i;
+#endif
+#ifdef DEBUG_SERIAL
+ printk("Penguin: #%d !\n", peng);
+#endif
+
+#ifdef DEBUG_SCREEN
if (!MACH_IS_MAC)
return;
- if (compat_boot_info.bi_mac.videodepth ==1)
+ if (mac_videodepth ==1)
pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes)
+5*peng;
else
@@ -146,15 +177,19 @@ void mac_debugging_penguin(int peng)
bwpdptr+=4;
pptr+=mac_rowbytes;
}
+#endif
}
+#ifdef DEBUG_SCREEN
/*
* B/W version of flaming Mac, unfinished (see above).
*/
static char bw_kaboom_map[]={
#include "bw_mac.h"
};
+#endif
+#ifdef DEBUG_SCREEN
static void mac_boom_boom(void)
{
static unsigned char *boomoffset=NULL;
@@ -162,14 +197,21 @@ static void mac_boom_boom(void)
unsigned char *bwpdptr=bw_kaboom_map;
int i;
+#ifdef DEBUG_SERIAL
+ printk("BOOM !\n");
+#endif
+
+ if (!MACH_IS_MAC)
+ return;
+
if(!boomoffset)
- if (compat_boot_info.bi_mac.videodepth == 1) {
+ if (mac_videodepth == 1) {
boomoffset=(unsigned char *)(mac_videobase+160*mac_rowbytes);
} else {
boomoffset=(unsigned char *)(mac_videobase+256*mac_rowbytes);
}
else
- if (compat_boot_info.bi_mac.videodepth == 1)
+ if (mac_videodepth == 1)
boomoffset+=5;
else
boomoffset+=32;
@@ -183,25 +225,43 @@ static void mac_boom_boom(void)
pptr+=mac_rowbytes;
}
}
+#endif
void mac_boom(int booms)
{
+#ifdef DEBUG_SCREEN
int i;
+#endif
if (!MACH_IS_MAC)
return;
+#ifdef DEBUG_SCREEN
for(i=0;i<booms;i++)
mac_boom_boom();
while(1);
+#endif
}
-#if 0
+#ifdef DEBUG_SERIAL
/*
* TODO: serial debug code
*/
+#define SCC_BAS (0x50F04000)
+struct SCC
+ {
+ u_char cha_b_ctrl;
+ u_char char_dummy1;
+ u_char cha_a_ctrl;
+ u_char char_dummy2;
+ u_char cha_b_data;
+ u_char char_dummy3;
+ u_char cha_a_data;
+ };
+# define scc ((*(volatile struct SCC*)SCC_BAS))
+
/* Flag that serial port is already initialized and used */
int mac_SCC_init_done = 0;
/* Can be set somewhere, if a SCC master reset has already be done and should
@@ -224,54 +284,113 @@ static struct console mac_console_driver = {
static int scc_port;
-static inline void mac_scc_out (char c)
+/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/
+
+#define US 1
+
+static inline void mac_sccb_out (char c)
{
+ int i;
do {
- MFPDELAY();
+ for( i = US; i > 0; --i )
+ barrier();
} while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
- MFPDELAY();
+ for( i = US; i > 0; --i )
+ barrier();
scc.cha_b_data = c;
}
-void mac_scc_console_write (struct console *co, const char *str,
+static inline void mac_scca_out (char c)
+{
+ int i;
+ do {
+ for( i = US; i > 0; --i )
+ barrier();
+ } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
+ for( i = US; i > 0; --i )
+ barrier();
+ scc.cha_a_data = c;
+}
+
+void mac_sccb_console_write (struct console *co, const char *str,
unsigned int count)
{
while (count--) {
if (*str == '\n')
- mac_scc_out( '\r' );
- mac_scc_out( *str++ );
+ mac_sccb_out( '\r' );
+ mac_sccb_out( *str++ );
+ }
+}
+
+void mac_scca_console_write (struct console *co, const char *str,
+ unsigned int count)
+{
+ while (count--) {
+ if (*str == '\n')
+ mac_scca_out( '\r' );
+ mac_scca_out( *str++ );
}
}
#ifdef CONFIG_SERIAL_CONSOLE
-int mac_scc_console_wait_key(struct console *co)
+int mac_sccb_console_wait_key(struct console *co)
{
+ int i;
do {
- MFPDELAY();
+ for( i = US; i > 0; --i )
+ barrier();
} while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */
- MFPDELAY();
+ for( i = US; i > 0; --i )
+ barrier();
return( scc.cha_b_data );
}
+
+int mac_scca_console_wait_key(struct console *co)
+{
+ int i;
+ do {
+ for( i = US; i > 0; --i )
+ barrier();
+ } while( !(scc.cha_a_ctrl & 0x01) ); /* wait for rx buf filled */
+ for( i = US; i > 0; --i )
+ barrier();
+ return( scc.cha_a_data );
+}
#endif
/* The following two functions do a quick'n'dirty initialization of the MFP or
* SCC serial ports. They're used by the debugging interface, kgdb, and the
* serial console code. */
-#define SCC_WRITE(reg,val) \
+#define SCCB_WRITE(reg,val) \
do { \
+ int i; \
scc.cha_b_ctrl = (reg); \
- MFPDELAY(); \
+ for( i = US; i > 0; --i ) \
+ barrier(); \
scc.cha_b_ctrl = (val); \
- MFPDELAY(); \
+ for( i = US; i > 0; --i ) \
+ barrier(); \
+ } while(0)
+
+#define SCCA_WRITE(reg,val) \
+ do { \
+ int i; \
+ scc.cha_a_ctrl = (reg); \
+ for( i = US; i > 0; --i ) \
+ barrier(); \
+ scc.cha_a_ctrl = (val); \
+ for( i = US; i > 0; --i ) \
+ barrier(); \
} while(0)
/* loops_per_sec isn't initialized yet, so we can't use udelay(). This does a
* delay of ~ 60us. */
+/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/
#define LONG_DELAY() \
do { \
int i; \
- for( i = 100; i > 0; --i ) \
- MFPDELAY(); \
+ for( i = 60*US; i > 0; --i ) \
+ barrier(); \
} while(0)
#ifndef CONFIG_SERIAL_CONSOLE
@@ -309,30 +428,56 @@ void mac_init_scc_port( int cflag, int port )
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 );
-
+
+#if 0
+ if (port) {
+#endif
+ (void)scc.cha_b_ctrl; /* reset reg pointer */
+ SCCB_WRITE( 9, 0xc0 ); /* reset */
+ LONG_DELAY(); /* extra delay after WR9 access */
+ SCCB_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
+ 0x04 /* 1 stopbit */ |
+ clkmode );
+ SCCB_WRITE( 3, reg3 );
+ SCCB_WRITE( 5, reg5 );
+ SCCB_WRITE( 9, 0 ); /* no interrupts */
+ LONG_DELAY(); /* extra delay after WR9 access */
+ SCCB_WRITE( 10, 0 ); /* NRZ mode */
+ SCCB_WRITE( 11, clksrc ); /* main clock source */
+ SCCB_WRITE( 12, div ); /* BRG value */
+ SCCB_WRITE( 13, 0 ); /* BRG high byte */
+ SCCB_WRITE( 14, brgsrc_table[baud] );
+ SCCB_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) );
+ SCCB_WRITE( 3, reg3 | 1 );
+ SCCB_WRITE( 5, reg5 | 8 );
+#if 0
+ } else {
+#endif
+ (void)scc.cha_a_ctrl; /* reset reg pointer */
+ SCCA_WRITE( 9, 0xc0 ); /* reset */
+ LONG_DELAY(); /* extra delay after WR9 access */
+ SCCA_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
+ 0x04 /* 1 stopbit */ |
+ clkmode );
+ SCCA_WRITE( 3, reg3 );
+ SCCA_WRITE( 5, reg5 );
+ SCCA_WRITE( 9, 0 ); /* no interrupts */
+ LONG_DELAY(); /* extra delay after WR9 access */
+ SCCA_WRITE( 10, 0 ); /* NRZ mode */
+ SCCA_WRITE( 11, clksrc ); /* main clock source */
+ SCCA_WRITE( 12, div ); /* BRG value */
+ SCCA_WRITE( 13, 0 ); /* BRG high byte */
+ SCCA_WRITE( 14, brgsrc_table[baud] );
+ SCCA_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) );
+ SCCA_WRITE( 3, reg3 | 1 );
+ SCCA_WRITE( 5, reg5 | 8 );
+#if 0
+ }
+#endif
mac_SCC_reset_done = 1;
mac_SCC_init_done = 1;
}
-
+#endif /* DEBUG_SERIAL */
__initfunc(void mac_debug_init(void))
{
@@ -340,23 +485,24 @@ __initfunc(void mac_debug_init(void))
/* the m68k_debug_device is used by the GDB stub, do nothing here */
return;
#endif
+#ifdef DEBUG_SERIAL
if (!strcmp( m68k_debug_device, "ser" )) {
strcpy( m68k_debug_device, "ser1" );
}
if (!strcmp( m68k_debug_device, "ser1" )) {
/* ST-MFP Modem1 serial port */
mac_init_scc_port( B9600|CS8, 0 );
- mac_console_driver.write = mac_scc_console_write;
+ mac_console_driver.write = mac_scca_console_write;
}
else if (!strcmp( m68k_debug_device, "ser2" )) {
/* SCC Modem2 serial port */
mac_init_scc_port( B9600|CS8, 1 );
- mac_console_driver.write = mac_scc_console_write;
+ mac_console_driver.write = mac_sccb_console_write;
}
if (mac_console_driver.write)
register_console(&mac_console_driver);
-}
#endif
+}
/*
* Local variables:
diff --git a/arch/m68k/mac/ksyms.c b/arch/m68k/mac/mac_ksyms.c
index 05373b04e..05373b04e 100644
--- a/arch/m68k/mac/ksyms.c
+++ b/arch/m68k/mac/mac_ksyms.c
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index b9c3331e9..d2ea26e05 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -28,6 +28,12 @@
*
* 7 - Debug output
*
+ * AV Macs only, handled by PSC:
+ *
+ * 3 - MACE ethernet IRQ (DMA complete on level 4)
+ *
+ * 5 - DSP ??
+ *
* Using the autovector irq numbers for Linux/m68k hardware interrupts without
* the IRQ_MACHSPEC bit set would interfere with the general m68k interrupt
* handling in kernel versions 2.0.x, so the following strategy is used:
@@ -57,13 +63,19 @@
* should be sufficient to use the same numbers (everything > 7 is assumed
* to be machspec, according to Jes!).
*
+ * TODO:
+ * - integrate Nubus interrupts in request/free_irq
+ *
+ * -
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h> /* for intr_count */
+#include <linux/delay.h>
#include <asm/system.h>
#include <asm/irq.h>
@@ -98,7 +110,10 @@ struct irqflags {
static struct irqhandler via1_handler[8];
static struct irqhandler via2_handler[8];
static struct irqhandler rbv_handler[8];
+static struct irqhandler psc3_handler[8];
static struct irqhandler scc_handler[8];
+static struct irqhandler psc5_handler[8];
+static struct irqhandler psc6_handler[8];
static struct irqhandler nubus_handler[8];
static struct irqhandler *handler_table[8];
@@ -111,7 +126,10 @@ static struct irqhandler *handler_table[8];
static struct irqparam via1_param[8];
static struct irqparam via2_param[8];
static struct irqparam rbv_param[8];
+static struct irqparam psc3_param[8];
static struct irqparam scc_param[8];
+static struct irqparam psc5_param[8];
+static struct irqparam psc6_param[8];
static struct irqparam nubus_param[8];
static struct irqparam *param_table[8];
@@ -125,27 +143,57 @@ static struct irqflags irq_flags[8];
/*
* This array holds the pointers to the various VIA or other interrupt
- * controllers
+ * controllers, indexed by interrupt level
*/
static volatile unsigned char *via_table[8];
-#ifdef VIABASE_WEIRDNESS
/*
- * VIA2 / RBV default base address
+ * Arrays with irq statistics
*/
+static unsigned long via1_irqs[8];
+static unsigned long via2_irqs[8];
+static unsigned long rbv_irqs[8];
+static unsigned long psc3_irqs[8];
+static unsigned long scc_irqs[8];
+static unsigned long psc5_irqs[8];
+static unsigned long psc6_irqs[8];
+static unsigned long nubus_irqs[8];
-volatile unsigned char *via2_regp = ((volatile unsigned char *)VIA2_BAS);
-volatile unsigned char *rbv_regp = ((volatile unsigned char *)VIA2_BAS_IIci);
-#endif
+static unsigned long *mac_irqs[8];
+
+/*
+ * VIA2 / RBV register base pointers
+ */
+
+volatile unsigned char *via2_regp=(volatile unsigned char *)VIA2_BAS;
+volatile unsigned char *rbv_regp=(volatile unsigned char *)VIA2_BAS_IIci;
+volatile unsigned char *oss_regp=(volatile unsigned char *)OSS_BAS;
+volatile unsigned char *psc_regp=(volatile unsigned char *)PSC_BAS;
/*
* Flags to control via2 / rbv behaviour
*/
static int via2_is_rbv = 0;
+static int via2_is_oss = 0;
static int rbv_clear = 0;
+/* fake VIA2 to OSS bit mapping */
+static int oss_map[8] = {2, 7, 0, 1, 3, 4, 5};
+
+void oss_irq(int irq, void *dev_id, struct pt_regs *regs);
+static void oss_do_nubus(int irq, void *dev_id, struct pt_regs *regs);
+
+/* PSC ints */
+void psc_irq(int irq, void *dev_id, struct pt_regs *regs);
+
+/*
+ * PSC hooks
+ */
+
+extern void psc_init(void);
+
/*
* console_loglevel determines NMI handler function
*/
@@ -174,11 +222,13 @@ void mac_init_IRQ(void)
{
int i;
- mac_debugging_penguin(6);
-
#ifdef DEBUG_MACINTS
printk("Mac interrupt stuff initializing ...\n");
#endif
+
+ via2_regp = (unsigned char *)VIA2_BAS;
+ rbv_regp = (unsigned char *)VIA2_BAS_IIci;
+
/* initialize the hardwired (primary, autovector) IRQs */
/* level 1 IRQ: VIA1, always present */
@@ -186,17 +236,33 @@ void mac_init_IRQ(void)
/* via2 or rbv?? */
if (macintosh_config->via_type == MAC_VIA_IIci) {
- /* VIA2 is part of the RBV: different base, other offsets */
- via2_is_rbv = 1;
- /* LC III weirdness: IFR seems to behave like VIA2 */
- /* FIXME: maybe also for LC II ?? */
- if (macintosh_config->ident == MAC_MODEL_LCIII) {
- rbv_clear = 0x0;
+ /*
+ * A word of caution: the definitions here only affect interrupt
+ * handling, see via6522.c for yet another file to change
+ * base addresses and RBV flags
+ */
+
+ /* yes, this is messy - the IIfx deserves a class of his own */
+ if (macintosh_config->ident == MAC_MODEL_IIFX) {
+ /* no real VIA2, the OSS seems _very_different */
+ via2_is_oss = 1;
+ /* IIfx has OSS, at a different base address than RBV */
+ rbv_regp = (unsigned char *) OSS_BAS;
+ sys_request_irq(2, oss_irq, IRQ_FLG_LOCK, "oss", oss_irq);
} else {
- rbv_clear = 0x80;
+ /* VIA2 is part of the RBV: different base, other offsets */
+ via2_is_rbv = 1;
+
+ /* LC III weirdness: IFR seems to behave like VIA2 */
+ /* FIXME: maybe also for LC II ?? */
+ if (macintosh_config->ident == MAC_MODEL_LCIII) {
+ rbv_clear = 0x0;
+ } else {
+ rbv_clear = 0x80;
+ }
+ /* level 2 IRQ: RBV/OSS; we only care about RBV for now */
+ sys_request_irq(2, rbv_irq, IRQ_FLG_LOCK, "rbv", rbv_irq);
}
- /* level 2 IRQ: RBV/OSS; we only care about RBV for now */
- sys_request_irq(2, rbv_irq, IRQ_FLG_LOCK, "rbv", rbv_irq);
} else
/* level 2 IRQ: VIA2 */
sys_request_irq(2, via2_irq, IRQ_FLG_LOCK, "via2", via2_irq);
@@ -207,7 +273,7 @@ void mac_init_IRQ(void)
* Currently, one interrupt per channel is used, solely
* to pass the correct async_info as parameter!
*/
-#if 0 /* doesn't seem to work yet */
+#if 0 /* want to install debug/SCC shutup routine until SCC init */
sys_request_irq(4, mac_SCC_handler, IRQ_FLG_STD, "INT4", mac_SCC_handler);
#else
sys_request_irq(4, mac_debug_handler, IRQ_FLG_STD, "INT4", mac_debug_handler);
@@ -255,26 +321,65 @@ void mac_init_IRQ(void)
via_table[0] = via1_regp;
handler_table[0] = &via1_handler[0];
param_table[0] = &via1_param[0];
+ mac_irqs[0] = &via1_irqs[0];
- if (via2_is_rbv) {
+ if (via2_is_rbv || via2_is_oss) {
via_table[1] = rbv_regp;
handler_table[1] = &rbv_handler[0];
param_table[1] = &rbv_param[0];
+ mac_irqs[1] = &rbv_irqs[0];
} else {
via_table[1] = via2_regp;
handler_table[1] = &via2_handler[0];
param_table[1] = &via2_param[0];
+ mac_irqs[1] = &via2_irqs[0];
}
via_table[2] = NULL;
via_table[3] = NULL;
handler_table[2] = &rbv_handler[0];
- handler_table[3] = &nubus_handler[0];
+ handler_table[3] = &scc_handler[0];
+ handler_table[4] = NULL;
+ handler_table[5] = NULL;
+ handler_table[6] = NULL;
+ handler_table[7] = &nubus_handler[0];
param_table[2] = &rbv_param[0];
- param_table[3] = &nubus_param[0];
+ param_table[3] = &scc_param[0];
+ param_table[7] = &nubus_param[0];
+
+ mac_irqs[2] = &rbv_irqs[0];
+ mac_irqs[3] = &scc_irqs[0];
+ mac_irqs[7] = &nubus_irqs[0];
+
+ /*
+ * AV Macs: shutup the PSC ints
+ */
+ if (macintosh_config->ident == MAC_MODEL_C660
+ || macintosh_config->ident == MAC_MODEL_Q840) {
+ psc_init();
+
+ handler_table[2] = &psc3_handler[0];
+ /* handler_table[3] = &psc4_handler[0]; */
+ handler_table[4] = &psc5_handler[0];
+ handler_table[5] = &psc6_handler[0];
+
+ param_table[2] = &psc3_param[0];
+ /* param_table[3] = &psc4_param[0]; */
+ param_table[4] = &psc5_param[0];
+ param_table[5] = &psc6_param[0];
+
+ mac_irqs[2] = &psc3_irqs[0];
+ /* mac_irqs[3] = &psc4_irqs[0]; */
+ mac_irqs[4] = &psc5_irqs[0];
+ mac_irqs[5] = &psc6_irqs[0];
+
+ sys_request_irq(3, psc_irq, IRQ_FLG_STD, "PSC3", psc_irq);
+ sys_request_irq(4, psc_irq, IRQ_FLG_STD, "PSC4", psc_irq);
+ sys_request_irq(5, psc_irq, IRQ_FLG_STD, "PSC5", psc_irq);
+ sys_request_irq(6, psc_irq, IRQ_FLG_STD, "PSC6", psc_irq);
+ }
- mac_debugging_penguin(7);
#ifdef DEBUG_MACINTS
printk("Mac interrupt init done!\n");
#endif
@@ -284,7 +389,7 @@ void mac_init_IRQ(void)
* We have no machine specific interrupts on a macintoy
* Yet, we need to register/unregister interrupts ... :-)
* Currently unimplemented: Test for valid irq number, chained irqs,
- * Nubus interrupts.
+ * Nubus interrupts (use nubus_request_irq!).
*/
int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
@@ -315,8 +420,8 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re
return -EINVAL;
}
- /* figure out if SCC pseudo-irq */
- if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_NUBUS_1)) {
+ /* figure out if SCC pseudo-irq (redundant ??) */
+ if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_PSC5_0)) {
/* set specific SCC handler */
scc_handler[irqidx].handler = handler;
scc_handler[irqidx].dev_id = dev_id;
@@ -326,6 +431,8 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re
return 0;
}
+ /* add similar hack for Nubus pseudo-irq here - hide nubus_request_irq */
+
via = (volatile unsigned char *) via_table[srcidx];
if (!via)
return -EINVAL;
@@ -341,9 +448,11 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re
via_param[irqidx].flags = flags;
via_param[irqidx].devname = devname;
- /* and turn it on ... */
+ /* and turn it on ... careful, that's VIA only ... */
if (srcidx == SRC_VIA2 && via2_is_rbv)
via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx)));
+ else if (srcidx == SRC_VIA2 && via2_is_oss)
+ via_write(oss_regp, oss_map[irqidx]+8, 2);
else
via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx)));
@@ -351,8 +460,18 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re
if (irq == IRQ_IDX(IRQ_MAC_SCSI)) {
/*
* Set vPCR for SCSI interrupts. (what about RBV here?)
+ * 980429 MS: RBV is ok, OSS seems to be differentt
*/
- via_write(via, vPCR, 0x66);
+ if (!via2_is_oss)
+ /* CB2 (IRQ) indep. interrupt input, positive edge */
+ /* CA2 (DRQ) indep. interrupt input, positive edge */
+ via_write(via, vPCR, 0x66);
+#if 0
+ else
+ /* CB2 (IRQ) indep. interrupt input, negative edge */
+ /* CA2 (DRQ) indep. interrupt input, negative edge */
+ via_write(via, vPCR, 0x22);
+#endif
}
return 0;
@@ -382,7 +501,7 @@ void mac_free_irq (unsigned int irq, void *dev_id)
cli();
/* figure out if SCC pseudo-irq */
- if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_NUBUS_1)) {
+ if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_PSC5_0)) {
/* clear specific SCC handler */
scc_handler[irqidx].handler = mac_default_handler;
scc_handler[irqidx].dev_id = NULL;
@@ -411,6 +530,8 @@ void mac_free_irq (unsigned int irq, void *dev_id)
/* and turn it off */
if (srcidx == SRC_VIA2 && via2_is_rbv)
via_write(via, rIER, (via_read(via, rIER)&(1<<irqidx)));
+ else if (srcidx == SRC_VIA2 && via2_is_oss)
+ via_write(oss_regp, oss_map[irqidx]+8, 0);
else
via_write(via, vIER, (via_read(via, vIER)&(1<<irqidx)));
@@ -453,8 +574,8 @@ not_found:
void mac_enable_irq (unsigned int irq)
{
- int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
- int irqidx = (irq & IRQ_IDX_MASK);
+ int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
+ int irqidx = (irq & IRQ_IDX_MASK);
irq_flags[srcidx].disabled &= ~(1<<irqidx);
/*
@@ -468,8 +589,8 @@ void mac_enable_irq (unsigned int irq)
void mac_disable_irq (unsigned int irq)
{
- int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
- int irqidx = (irq & IRQ_IDX_MASK);
+ int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
+ int irqidx = (irq & IRQ_IDX_MASK);
irq_flags[srcidx].disabled |= (1<<irqidx);
}
@@ -481,8 +602,8 @@ void mac_disable_irq (unsigned int irq)
void mac_turnon_irq( unsigned int irq )
{
- int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
- int irqidx = (irq & IRQ_IDX_MASK);
+ int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
+ int irqidx = (irq & IRQ_IDX_MASK);
volatile unsigned char *via;
via = (volatile unsigned char *) via_table[srcidx];
@@ -491,6 +612,11 @@ void mac_turnon_irq( unsigned int irq )
if (srcidx == SRC_VIA2 && via2_is_rbv)
via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx)));
+ else if (srcidx == SRC_VIA2 && via2_is_oss)
+ via_write(oss_regp, oss_map[irqidx]+8, 2);
+ else if (srcidx >= SRC_VIA2)
+ via_write(via, (0x104 + 0x10*srcidx),
+ via_read(via, (0x104 + 0x10*srcidx))|0x80|(1<<(irqidx)));
else
via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx)));
@@ -498,8 +624,8 @@ void mac_turnon_irq( unsigned int irq )
void mac_turnoff_irq( unsigned int irq )
{
- int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
- int irqidx = (irq & IRQ_IDX_MASK);
+ int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
+ int irqidx = (irq & IRQ_IDX_MASK);
volatile unsigned char *via;
via = (volatile unsigned char *) via_table[srcidx];
@@ -508,6 +634,11 @@ void mac_turnoff_irq( unsigned int irq )
if (srcidx == SRC_VIA2 && via2_is_rbv)
via_write(via, rIER, (via_read(via, rIER)&(1<<irqidx)));
+ else if (srcidx == SRC_VIA2 && via2_is_oss)
+ via_write(oss_regp, oss_map[irqidx]+8, 0);
+ else if (srcidx >= SRC_VIA2)
+ via_write(via, (0x104 + 0x10*srcidx),
+ via_read(via, (0x104 + 0x10*srcidx))|(1<<(irqidx)));
else
via_write(via, vIER, (via_read(via, vIER)&(1<<irqidx)));
}
@@ -522,23 +653,109 @@ void mac_turnoff_irq( unsigned int irq )
void mac_clear_pending_irq( unsigned int irq )
{
- int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
- int irqidx = (irq & IRQ_IDX_MASK);
+ int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
+ int irqidx = (irq & IRQ_IDX_MASK);
irq_flags[srcidx].pending &= ~(1<<irqidx);
}
int mac_irq_pending( unsigned int irq )
{
- int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
- int irqidx = (irq & IRQ_IDX_MASK);
+ int pending = 0;
+ volatile unsigned char *via;
+
+ int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1;
+ int irqidx = (irq & IRQ_IDX_MASK);
- return (irq_flags[srcidx].pending & (1<<irqidx));
+ pending = irq_flags[srcidx].pending & (1<<irqidx);
+
+ via = (volatile unsigned char *) via_table[srcidx];
+ if (!via)
+ return (pending);
+
+ if (srcidx == SRC_VIA2 && via2_is_rbv)
+ pending |= via_read(via, rIFR)&(1<<irqidx);
+ else if (srcidx == SRC_VIA2 && via2_is_oss)
+ pending |= via_read(via, oIFR)&0x03&(1<<oss_map[irqidx]);
+ else if (srcidx >= SRC_VIA2)
+ pending |= via_read(via, (0x100 + 0x10*srcidx))&(1<<irqidx);
+ else
+ pending |= via_read(via, vIFR)&(1<<irqidx);
+
+ return (pending);
}
int mac_get_irq_list (char *buf)
{
- return 0;
+ int i, len = 0;
+ int srcidx, irqidx;
+
+ for (i = VIA1_SOURCE_BASE; i < NUM_MAC_SOURCES+8; ++i) {
+ srcidx = ((i & IRQ_SRC_MASK)>>3) - 1;
+ irqidx = (i & IRQ_IDX_MASK);
+
+ /*
+ * Not present: skip
+ */
+
+ if (mac_irqs[srcidx] == NULL)
+ continue;
+
+ /*
+ * never used by VIAs, unused by others so far, counts
+ * the magic 'nothing pending' cases ...
+ */
+ if (irqidx == 7 && mac_irqs[srcidx][irqidx]) {
+ len += sprintf(buf+len, "Level %01d: %10lu (spurious) \n",
+ srcidx,
+ mac_irqs[srcidx][irqidx]);
+ continue;
+ }
+
+ /*
+ * Nothing registered for this IPL: skip
+ */
+
+ if (handler_table[srcidx] == NULL)
+ continue;
+
+ /*
+ * No handler installed: skip
+ */
+
+ if (handler_table[srcidx][irqidx].handler == mac_default_handler ||
+ handler_table[srcidx][irqidx].handler == nubus_wtf)
+ continue;
+
+
+ if (i < VIA2_SOURCE_BASE)
+ len += sprintf(buf+len, "via1 %01d: %10lu ",
+ irqidx,
+ mac_irqs[srcidx][irqidx]);
+ else if (i < RBV_SOURCE_BASE)
+ len += sprintf(buf+len, "via2 %01d: %10lu ",
+ irqidx,
+ mac_irqs[srcidx][irqidx]);
+ else if (i < MAC_SCC_SOURCE_BASE)
+ len += sprintf(buf+len, "rbv %01d: %10lu ",
+ irqidx,
+ mac_irqs[srcidx][irqidx]);
+ else if (i < NUBUS_SOURCE_BASE)
+ len += sprintf(buf+len, "scc %01d: %10lu ",
+ irqidx,
+ mac_irqs[srcidx][irqidx]);
+ else /* Nubus */
+ len += sprintf(buf+len, "nubus %01d: %10lu ",
+ irqidx,
+ mac_irqs[srcidx][irqidx]);
+
+ len += sprintf(buf+len, "%s\n",
+ param_table[srcidx][irqidx].devname);
+
+ }
+ if (num_spurious)
+ len += sprintf(buf+len, "spurio.: %10u\n", num_spurious);
+ return len;
}
void via_scsi_clear(void)
@@ -547,6 +764,9 @@ void via_scsi_clear(void)
if (via2_is_rbv) {
via_write(rbv_regp, rIFR, (1<<3)|(1<<0)|0x80);
deep_magic = via_read(rbv_regp, rBufB);
+ } else if (via2_is_oss) {
+ /* nothing */
+ /* via_write(oss_regp, 9, 0) */;
} else
deep_magic = via_read(via2_regp, vBufB);
mac_enable_irq( IRQ_IDX(IRQ_MAC_SCSI) );
@@ -570,12 +790,45 @@ void mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs)
}
}
+void scsi_mac_debug(void);
+void scsi_mac_polled(void);
+
+static int in_nmi = 0;
+static volatile int nmi_hold = 0;
+
void mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp)
{
+ int i;
/*
* generate debug output on NMI switch if 'debug' kernel option given
* (only works with Penguin!)
*/
+
+ in_nmi++;
+#if 0
+ scsi_mac_debug();
+ printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp);
+#endif
+ for (i=0; i<100; i++)
+ udelay(1000);
+
+ if (in_nmi == 1) {
+ nmi_hold = 1;
+ printk("... pausing, press NMI to resume ...");
+ } else {
+ printk(" ok!\n");
+ nmi_hold = 0;
+ }
+
+ barrier();
+
+ while (nmi_hold == 1)
+ udelay(1000);
+
+#if 0
+ scsi_mac_polled();
+#endif
+
if ( console_loglevel >= 8 ) {
#if 0
show_state();
@@ -595,6 +848,7 @@ void mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp)
/* printk("NMI "); */
#endif
}
+ in_nmi--;
}
/*
@@ -610,6 +864,7 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs)
int ct = 0;
struct irqhandler *via_handler = handler_table[*viaidx];
struct irqparam *via_param = param_table[*viaidx];
+ unsigned long *via_irqs = mac_irqs[*viaidx];
/* to be changed, possibly: for each non'masked', enabled IRQ, read
* flag bit, ack and call handler ...
@@ -626,7 +881,12 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs)
if(events==0)
{
- printk("via_irq: nothing pending!\n");
+#ifdef DEBUG_VIA
+ /* should go away; mostly missing timer ticks and ADB events */
+ printk("via%d_irq: nothing pending, flags %x mask %x!\n",
+ *viaidx + 1, via_read(via, vIFR), via_read(via,vIER));
+#endif
+ via_irqs[7]++;
return;
}
@@ -661,9 +921,12 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs)
/* call corresponding handlers */
if (events&(1<<i)) {
if (irq_flags[*viaidx].disabled & (1<<i)) {
+ if (!irq_flags[*viaidx].pending&(1<<i))
+ via_irqs[i]++;
/* irq disabled -> mark pending */
irq_flags[*viaidx].pending |= (1<<i);
} else {
+ via_irqs[i]++;
/* irq enabled -> call handler */
(via_handler[i].handler)(irq, via, regs);
}
@@ -686,7 +949,9 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs)
ct++;
if(events && ct>8)
{
+#ifdef DEBUG_VIA
printk("via%d: stuck events %x\n", (*viaidx)+1, events);
+#endif
break;
}
}
@@ -743,6 +1008,23 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs)
struct irqhandler *via_handler = handler_table[srcidx];
struct irqparam *via_param = param_table[srcidx];
+ /* shouldn't we disable interrupts here ?? */
+
+
+ /*
+ * Shouldnt happen
+ */
+
+ if(events==0)
+ {
+#ifdef DEBUG_VIA
+ printk("rbv_irq: nothing pending, flags %x mask %x!\n",
+ via_read(via, rIFR), via_read(via,rIER));
+#endif
+ rbv_irqs[7]++;
+ return;
+ }
+
#ifdef DEBUG_VIA
/*
* limited verbosity for RBV interrupts (add more if needed)
@@ -757,19 +1039,6 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs)
* If ack for masked IRQ required: keep 'pending' info separate.
*/
- /* shouldn't we disable interrupts here ?? */
-
-
- /*
- * Shouldnt happen
- */
-
- if(events==0)
- {
- printk("rbv_irq: nothing pending!\n");
- return;
- }
-
do {
/*
* Clear the pending flag
@@ -787,12 +1056,16 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs)
int irq = (srcidx+1)* 8 + i;
/* call corresponding handlers */
if (events&(1<<i)) {
- if (irq_flags[srcidx].disabled & (1<<i))
+ if (irq_flags[srcidx].disabled & (1<<i)) {
+ if (!irq_flags[srcidx].pending&(1<<i))
+ rbv_irqs[i]++;
/* irq disabled -> mark pending */
irq_flags[srcidx].pending |= (1<<i);
- else
+ } else {
+ rbv_irqs[i]++;
/* irq enabled -> call handler */
(via_handler[i].handler)(irq, via, regs);
+ }
}
/* and call handlers for pending irqs - first ?? */
if ( (irq_flags[srcidx].pending & (1<<i))
@@ -803,7 +1076,7 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs)
irq_flags[srcidx].pending &= ~(1<<i);
}
}
-
+
/*
* And done ... check for more punishment!
*/
@@ -843,24 +1116,277 @@ void via_wtf(int slot, void *via, struct pt_regs *regs)
#endif
}
+/*
+ * Nubus / SCSI interrupts; OSS style
+ * The OSS is even more different than the RBV. OSS appears to stand for
+ * Obscenely Screwed Silicon ...
+ *
+ * Latest NetBSD sources suggest the OSS should behave like a RBV, but
+ * that's probably true for the 0x203 offset (Nubus/ADB-SWIM IOP) at best
+ */
+
+void oss_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int srcidx = IRQ_IDX(irq) - 1; /* MUST be 1 !! */
+ volatile unsigned char *via = oss_regp;
+ unsigned char events=(via_read(via, oIFR))&0x03;
+ unsigned char nub_ev=(via_read(via, nIFR))&0x4F;
+ unsigned char adb_ev;
+ int i;
+ int ct = 0;
+ struct irqhandler *via_handler = handler_table[srcidx];
+ struct irqparam *via_param = param_table[srcidx];
+
+ /* shouldn't we disable interrupts here ?? */
+
+ adb_ev = nub_ev & 0x40;
+ nub_ev &= 0x3F;
+
+ /*
+ * Shouldnt happen
+ */
+
+ if (events==0 && adb_ev==0 && nub_ev==0)
+ {
+ printk("oss_irq: nothing pending, flags %x %x!\n",
+ via_read(via, oIFR), via_read(via, nIFR));
+ rbv_irqs[7]++;
+ return;
+ }
+
+#ifdef DEBUG_VIA
+ /*
+ * limited verbosity for RBV interrupts (add more if needed)
+ */
+ if ( events != 1<<3 ) /* SCSI IRQ */
+ printk("oss_irq: irq %d events %x %x %x !\n", irq, srcidx+1,
+ events, adb_ev, nub_ev);
+#endif
+
+ /*
+ * OSS priorities: call ADB handler first if registered, other events,
+ * then Nubus
+ * ADB: yet to be implemented!
+ */
+
+ /*
+ * ADB: try to shutup the IOP
+ */
+ if (adb_ev) {
+ printk("Hands off ! Don't press this button ever again !!!\n");
+ via_write(via, 6, 0);
+ }
+
+ do {
+ /*
+ * Clear the pending flags
+ * How exactly is that supposed to work ??
+ */
+
+ /*
+ * Now see what bits are raised
+ */
+
+ for(i=0;i<7;i++)
+ {
+ /* HACK HACK: map to bit number in OSS register */
+ int irqidx = oss_map[i];
+ /* determine machspec. irq no. */
+ int irq = (srcidx+1)* 8 + i;
+ /* call corresponding handlers */
+ if ( (events&(1<<irqidx)) && /* bit set*/
+ (via_read(via, irqidx+8)&0x7) ) { /* irq enabled */
+ if (irq_flags[srcidx].disabled & (1<<i)) {
+ if (!irq_flags[srcidx].pending&(1<<i))
+ rbv_irqs[i]++;
+ /* irq disabled -> mark pending */
+ irq_flags[srcidx].pending |= (1<<i);
+ } else {
+ rbv_irqs[i]++;
+ /* irq enabled -> call handler */
+ (via_handler[i].handler)(irq, via, regs);
+ }
+ }
+ /* and call handlers for pending irqs - first ?? */
+ if ( (irq_flags[srcidx].pending & (1<<i))
+ && !(irq_flags[srcidx].disabled & (1<<i)) ) {
+ /* call handler for re-enabled irq */
+ (via_handler[i].handler)(irq, via, regs);
+ /* and clear pending flag :-) */
+ irq_flags[srcidx].pending &= ~(1<<i);
+ }
+ }
+
+ /*
+ * And done ... check for more punishment!
+ */
+
+ events=(via_read(via, oIFR)/*&via_read(via,rIER)*/)&0x03;
+ ct++;
+ if(events && ct>8)
+ {
+ printk("oss: stuck events %x\n",events);
+ for(i=0;i<7;i++)
+ {
+ if(events&(1<<i))
+ {
+ printk("oss - bashing source %d\n",
+ i);
+ /* that should disable it */
+ via_write(via, 8+i, 0);
+ }
+ }
+ break;
+ }
+ }
+ while(events);
+#if 0
+ scsi_mac_polled();
+#endif
+
+ if (nub_ev)
+ oss_do_nubus(irq, via, regs);
+
+}
+
+/*
+ * Unexpected slot interrupt
+ */
+
void nubus_wtf(int slot, void *via, struct pt_regs *regs)
{
-#ifdef DEBUG_VIA
+#ifdef DEBUG_VIA_NUBUS
printk("Unexpected interrupt on nubus slot %d\n",slot);
#endif
}
+/*
+ * SCC master interrupt handler; sole purpose: pass the registered
+ * async struct to the SCC handler proper.
+ */
+
void mac_SCC_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i;
-
- for (i = 0; i < 8; i++)
+ /* 1+2: compatibility with PSC ! */
+ for (i = 1; i < 3; i++) /* currently only these two used */
if (scc_handler[i].handler != mac_default_handler)
(scc_handler[i].handler)(i, scc_handler[i].dev_id, regs);
}
/*
+ * PSC interrupt handler
+ */
+
+void psc_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int srcidx = IRQ_IDX(irq) - 1;
+ volatile unsigned char *via = psc_regp;
+ unsigned int pIFR = 0x100 + 0x10*srcidx;
+ unsigned int pIER = 0x104 + 0x10*srcidx;
+ unsigned char events=(via_read(via, pIFR)&via_read(via,pIER))&0xF;
+ int i;
+ int ct = 0;
+ struct irqhandler *via_handler = handler_table[srcidx];
+ struct irqparam *via_param = param_table[srcidx];
+
+ /* shouldn't we disable interrupts here ?? */
+
+
+ /*
+ * Shouldnt happen
+ */
+
+ if(events==0)
+ {
+#ifdef DEBUG_VIA
+ printk("rbv_irq: nothing pending, flags %x mask %x!\n",
+ via_read(via, pIFR), via_read(via,pIER));
+#endif
+ mac_irqs[srcidx][7]++;
+ return;
+ }
+
+#ifdef DEBUG_VIA
+ /*
+ * limited verbosity for RBV interrupts (add more if needed)
+ */
+ if ( srcidx == 1 && events != 1<<3 && events != 1<<1 ) /* SCSI IRQ */
+ printk("psc_irq: irq %d events %x !\n", irq, srcidx+1, events);
+#endif
+
+ /* to be changed, possibly: for each non'masked', enabled IRQ, read
+ * flag bit, ack and call handler ...
+ * Currently: all pending irqs ack'ed en bloc.
+ * If ack for masked IRQ required: keep 'pending' info separate.
+ */
+
+ do {
+ /*
+ * Clear the pending flag
+ */
+
+ /* via_write(via, pIFR, events); */
+
+ /*
+ * Now see what bits are raised
+ */
+
+ for(i=0;i<7;i++)
+ {
+ /* determine machspec. irq no. */
+ int irq = (srcidx+1)* 8 + i;
+ /* call corresponding handlers */
+ if (events&(1<<i)) {
+ if (irq_flags[srcidx].disabled & (1<<i)) {
+ if (!irq_flags[srcidx].pending&(1<<i))
+ mac_irqs[srcidx][i]++;
+ /* irq disabled -> mark pending */
+ irq_flags[srcidx].pending |= (1<<i);
+ } else {
+ mac_irqs[srcidx][i]++;
+ /* irq enabled -> call handler */
+ (via_handler[i].handler)(irq, via, regs);
+ }
+ }
+ /* and call handlers for pending irqs - first ?? */
+ if ( (irq_flags[srcidx].pending & (1<<i))
+ && !(irq_flags[srcidx].disabled & (1<<i)) ) {
+ /* call handler for re-enabled irq */
+ (via_handler[i].handler)(irq, via, regs);
+ /* and clear pending flag :-) */
+ irq_flags[srcidx].pending &= ~(1<<i);
+ }
+ }
+
+ /*
+ * And done ... check for more punishment!
+ */
+
+ events=(via_read(via,pIFR)&via_read(via,pIER))&0x7F;
+ ct++;
+ if(events && ct>8)
+ {
+ printk("psc: stuck events %x\n",events);
+ for(i=0;i<7;i++)
+ {
+ if(events&(1<<i))
+ {
+ printk("psc - bashing source %d\n",
+ i);
+ via_write(via, pIER, 1<<i);
+ /* via_write(via, pIFR, (1<<i)); */
+ }
+ }
+ break;
+ }
+ }
+ while(events);
+}
+
+
+/*
* Nubus handling
* Caution: slot numbers are currently 'hardcoded' to the range 9-15!
* In general, the same request_irq() functions as above can be used if
@@ -869,25 +1395,26 @@ void mac_SCC_handler(int irq, void *dev_id, struct pt_regs *regs)
static int nubus_active=0;
-int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *))
+int nubus_request_irq(int slot, void *dev_id, void (*handler)(int,void *,struct pt_regs *))
{
slot-=9;
/* printk("Nubus request irq for slot %d\n",slot);*/
if(nubus_handler[slot].handler!=nubus_wtf)
return -EBUSY;
nubus_handler[slot].handler=handler;
- nubus_handler[slot].dev_id =handler;
+ nubus_handler[slot].dev_id =dev_id;
nubus_param[slot].flags = IRQ_FLG_LOCK;
- nubus_param[slot].devname = "nubus";
+ nubus_param[slot].devname = "nubus slot";
/*
* if no nubus int. was active previously: register the main nubus irq
* handler now!
*/
- if (!nubus_active)
- request_irq(IRQ_MAC_NUBUS, via_do_nubus, IRQ_FLG_LOCK,
- "nubus dispatch", via_do_nubus);
+ if (!nubus_active && !via2_is_oss) {
+ request_irq(IRQ_MAC_NUBUS, via_do_nubus, IRQ_FLG_LOCK,
+ "nubus dispatch", via_do_nubus);
+ }
nubus_active|=1<<slot;
/* printk("program slot %d\n",slot);*/
@@ -897,7 +1424,9 @@ int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *))
via_read(via2, vDirA)|(1<<slot));
via_write(via2, vBufA, 0);
#endif
- if (!via2_is_rbv) {
+ if (via2_is_oss)
+ via_write(oss_regp, slot, 2);
+ else if (!via2_is_rbv) {
/* Make sure the bit is an input */
via_write(via2_regp, vDirA,
via_read(via2_regp, vDirA)&~(1<<slot));
@@ -917,6 +1446,8 @@ int nubus_free_irq(int slot)
if (via2_is_rbv)
via_write(rbv_regp, rBufA, 1<<slot);
+ else if (via2_is_oss)
+ via_write(oss_regp, slot, 0);
else {
via_write(via2_regp, vDirA,
via_read(via2_regp, vDirA)|(1<<slot));
@@ -927,6 +1458,16 @@ int nubus_free_irq(int slot)
return 0;
}
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+/*
+ * IDE interrupt hook
+ */
+extern void (*mac_ide_intr_hook)(int, void *, struct pt_regs *);
+#endif
+
+/*
+ * Nubus dispatch handler - VIA/RBV style
+ */
static void via_do_nubus(int slot, void *via, struct pt_regs *regs)
{
unsigned char map;
@@ -941,6 +1482,14 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs)
else
via_write(via2_regp, vIFR, 0x82);
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+ /* IDE hack */
+ if (mac_ide_intr_hook)
+ /* 'slot' is lacking the machspec bit in 2.0 */
+ /* need to pass proper dev_id = hwgroup here */
+ mac_ide_intr_hook(IRQ_MAC_NUBUS, via, regs);
+#endif
+
while(1)
{
if (via2_is_rbv)
@@ -948,15 +1497,23 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs)
else
map = ~via_read(via2_regp, vBufA);
-#ifdef DEBUG_VIA
- printk("nubus_irq: map %x mask %x\n", map, nubus_active);
+ if( (map = (map&nubus_active)) ==0 ) {
+#ifdef DEBUG_NUBUS_INT
+ printk("nubus_irq: nothing pending, map %x mask %x\n",
+ map, nubus_active);
#endif
- if( (map = (map&nubus_active)) ==0 )
+ nubus_irqs[7]++;
break;
+ }
+#ifdef DEBUG_NUBUS_INT
+ printk("nubus_irq: map %x mask %x\n", map, nubus_active);
+#endif
if(ct++>2)
{
+#ifdef DEBUG_NUBUS_INT
printk("nubus stuck events - %d/%d\n", map, nubus_active);
+#endif
return;
}
@@ -964,7 +1521,8 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs)
{
if(map&(1<<i))
{
- (nubus_handler[i].handler)(i+9, via, regs);
+ nubus_irqs[i]++;
+ (nubus_handler[i].handler)(i+9, nubus_handler[i].dev_id, regs);
}
}
/* clear it */
@@ -977,3 +1535,76 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs)
/* And done */
}
+
+/*
+ * Nubus dispatch handler - OSS style
+ */
+static void oss_do_nubus(int slot, void *via, struct pt_regs *regs)
+{
+ unsigned char map;
+ int i;
+ int ct=0;
+
+/* printk("nubus interrupt\n");*/
+
+#if 0
+ /* lock the nubus interrupt */
+ if (via2_is_rbv)
+ via_write(rbv_regp, rIFR, 0x82);
+ else
+ via_write(via2_regp, vIFR, 0x82);
+#endif
+
+ /* IDE hack for Quadra: uses Nubus interrupt without any slot bit set */
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+ if (mac_ide_intr_hook)
+ mac_ide_intr_hook(IRQ_MAC_NUBUS, via, regs);
+#endif
+
+ while(1)
+ {
+ /* pending events */
+ map=(via_read(via, nIFR))&0x3F;
+
+#ifdef DEBUG_VIA_NUBUS
+ printk("nubus_irq: map %x mask %x\n", map, nubus_active);
+#endif
+ if( (map = (map&nubus_active)) ==0 ) {
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+ if (!mac_ide_intr_hook)
+ printk("nubus_irq: nothing pending, map %x mask %x\n",
+ map, nubus_active);
+#endif
+ nubus_irqs[7]++;
+ break;
+ }
+
+ if(ct++>2)
+ {
+#if 0
+ printk("nubus stuck events - %d/%d\n", map, nubus_active);
+#endif
+ return;
+ }
+
+ for(i=0;i<7;i++)
+ {
+ if(map&(1<<i))
+ {
+ nubus_irqs[i]++;
+ /* call handler */
+ (nubus_handler[i].handler)((i+9), nubus_handler[i].dev_id, regs);
+ /* clear interrupt ?? */
+#if 0
+ via_write(oss_regp, i, 0);
+#endif
+ }
+ }
+ /* clear it */
+#if 0
+ via_write(oss_regp, nIFR, map);
+#endif
+ }
+
+ /* And done */
+}
diff --git a/arch/m68k/mac/mackeyb.c b/arch/m68k/mac/mackeyb.c
index f338253f3..5946a9e8b 100644
--- a/arch/m68k/mac/mackeyb.c
+++ b/arch/m68k/mac/mackeyb.c
@@ -600,13 +600,13 @@ __initfunc(int mac_keyb_init(void))
volatile int ct;
/* setup key map */
- memcpy (plain_map, mac_plain_map, sizeof(plain_map));
- memcpy(shift_map, mac_shift_map, sizeof(shift_map));
- memcpy(altgr_map, mac_altgr_map, sizeof(altgr_map));
- memcpy(ctrl_map, mac_ctrl_map, sizeof(ctrl_map));
- memcpy(shift_ctrl_map, mac_shift_ctrl_map, sizeof(shift_ctrl_map));
- memcpy(alt_map, mac_alt_map, sizeof(alt_map));
- memcpy(ctrl_alt_map, mac_ctrl_alt_map, sizeof(ctrl_alt_map));
+ memcpy(key_maps[0], mac_plain_map, sizeof(plain_map));
+ memcpy(key_maps[1], mac_shift_map, sizeof(plain_map));
+ memcpy(key_maps[2], mac_altgr_map, sizeof(plain_map));
+ memcpy(key_maps[4], mac_ctrl_map, sizeof(plain_map));
+ memcpy(key_maps[5], mac_shift_ctrl_map, sizeof(plain_map));
+ memcpy(key_maps[8], mac_alt_map, sizeof(plain_map));
+ memcpy(key_maps[12], mac_ctrl_alt_map, sizeof(plain_map));
/* initialize mouse interrupt hook */
mac_mouse_interrupt_hook = NULL;
@@ -642,11 +642,12 @@ __initfunc(int mac_keyb_init(void))
ct=0;
while (!autopoll_req.got_reply && ++ct<1000)
{
- adb_poll();
udelay(10);
}
- if(ct==1000)
+ if(ct==1000) {
printk("Keyboard timed out.\n");
+ autopoll_req.got_reply = 1;
+ }
}
/*
@@ -654,7 +655,7 @@ __initfunc(int mac_keyb_init(void))
* care of that for other Macs.
*/
- printk("Configuring keyboard\n");
+ printk("Configuring keyboard:\n");
/*
* turn on all leds - the keyboard driver will turn them back off
@@ -668,17 +669,17 @@ __initfunc(int mac_keyb_init(void))
* The polling stuff should go away as soon as the ADB driver is stable
*/
ct = 0;
- adb_poll();
while (!led_request.got_reply && ++ct<1000)
{
- adb_poll();
udelay(10);
}
- if(ct==1000)
- printk("Keyboard timed out.\n");
+ if(ct==1000) {
+ printk("keyboard timed out.\n");
+ led_request.got_reply = 1;
+ }
#if 1
- printk("Configuring coding mode ...\n");
+ printk("configuring coding mode ...\n");
/*
* get the keyboard to send separate codes for
@@ -688,14 +689,14 @@ __initfunc(int mac_keyb_init(void))
ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3);
ct=0;
- adb_poll();
while (!confcod_req.got_reply && ++ct<1000)
{
- adb_poll();
udelay(10);
}
- if(ct==1000)
- printk("Keyboard timed out.\n");
+ if(ct==1000) {
+ printk("keyboard timed out.\n");
+ confcod_req.got_reply = 1;
+ }
#endif
#if 0 /* seems to hurt, at least Geert's Mac */
@@ -710,10 +711,8 @@ __initfunc(int mac_keyb_init(void))
ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 );
ct=0;
- adb_poll();
while (!mouse_req.got_reply && ++ct<1000)
{
- adb_poll();
udelay(10);
}
if(ct==1000)
@@ -734,19 +733,18 @@ __initfunc(int mac_keyb_init(void))
ADB_READREG(ADB_KEYBOARD, KEYB_KEYREG));
#endif
- /*
- * fake 'request done' for the driver if requests timed out
- */
-
- autopoll_req.got_reply = 1;
-#if 0
- /* XXX: results in race and hang with mac_kbd_leds and serial (why ?) */
- led_request.got_reply = 1;
-#endif
- confcod_req.got_reply = 1;
-
in_keybinit = 0;
- printk("Keyboard init done\n");
+ printk("keyboard init done\n");
return 0;
}
+
+/* for "kbd-reset" cmdline param */
+__initfunc(void mac_kbd_reset_setup(char *str, int *ints))
+{
+}
+
+/* for "kbd-reset" cmdline param */
+__initfunc(void mac_kbd_reset_setup(char *str, int *ints))
+{
+}
diff --git a/arch/m68k/mac/psc.h b/arch/m68k/mac/psc.h
new file mode 100644
index 000000000..964f6547c
--- /dev/null
+++ b/arch/m68k/mac/psc.h
@@ -0,0 +1,18 @@
+/*
+ * Apple Peripheral System Controller (PSC)
+ *
+ * The PSC is used on the AV Macs to control IO functions not handled
+ * by the VIAs (Ethernet, DSP, SCC).
+ */
+
+#define PSCBASE 0x50F31000
+
+#define pIFR3 0x130
+#define pIFR4 0x140
+#define pIFR5 0x150
+#define pIFR6 0x160
+
+#define pIER3 0x134
+#define pIER4 0x144
+#define pIER5 0x154
+#define pIER6 0x164
diff --git a/arch/m68k/mac/via6522.c b/arch/m68k/mac/via6522.c
index d2a25ab13..c867bc96d 100644
--- a/arch/m68k/mac/via6522.c
+++ b/arch/m68k/mac/via6522.c
@@ -1,4 +1,3 @@
-
/*
* 6522 Versatile Interface Adapter (VIA)
*
@@ -13,75 +12,27 @@
#include <asm/macintosh.h>
#include <asm/macints.h>
#include "via6522.h"
+#include "psc.h"
volatile unsigned char *via1=(unsigned char *)VIABASE;
volatile unsigned char *via2=(unsigned char *)VIABASE2;
+volatile unsigned char *psc=(unsigned char *)PSCBASE;
unsigned char via1_clock, via1_datab;
static int rbv=0;
+static int oss=0;
+
+extern void adb_interrupt(int slot, void *via, struct pt_regs *regs);
/*
- * Debugging the VBL ints
+ * hardware reset vector
*/
-
-extern int console_loglevel;
+static void (*rom_reset)(void);
/*
- * VIA1 - hardwired vectors
+ * Timer defs.
*/
-
-#if 0 /* gone to macints.[ch] */
-extern void via_wtf(int slot, void *via, struct pt_regs *regs);
-static void via_do_nubus(int slot, volatile void *via, struct pt_regs *regs);
-
-extern void adb_interrupt(int slot, void *via, struct pt_regs *regs);
-
-static struct via_irq_tab via1_func_tab=
-{
- {
- via_wtf, /* One second interrupt */
- via_wtf, /* Vblank */
- via_wtf, /* ADB data ready */
- via_wtf, /* ADB data */
- via_wtf, /* ADB clock */
- via_wtf,
- via_wtf, /* Slot 6 is replaced by the timer */
- via_wtf
- }
-};
-
-static struct via_irq_tab via2_func_tab=
-{
- {
- via_wtf,
- via_do_nubus,
- via_wtf,
- via_wtf,
- via_wtf,
- via_wtf,
- via_wtf,
- via_wtf
- }
-};
-
-static struct via_irq_tab nubus_func_tab=
-{
- {
- via_wtf,
- via_wtf,
- via_wtf,
- via_wtf,
- via_wtf,
- via_wtf,
- via_wtf,
- via_wtf
- }
-};
-#endif
-
-extern void adb_interrupt(int slot, void *via, struct pt_regs *regs);
-
#define MAC_CLOCK_TICK (783300/HZ) /* ticks per HZ */
#define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF)
#define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8)
@@ -91,8 +42,6 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *))
{
unsigned char c;
-/* mac_debugging_penguin(6);*/
-
switch(macintosh_config->via_type)
{
/*
@@ -102,6 +51,10 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *))
via1=(void *)0x50F00000;
via2=(void *)0x50F26000;
rbv=1;
+ if (macintosh_config->ident == MAC_MODEL_IIFX) {
+ via2=(void *)0x50F1A000;
+ oss=1;
+ }
break;
/*
* Quadra and early MacIIs agree on the VIA locations
@@ -162,7 +115,7 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *))
via_write(via2,vT2CH,0);
via_write(via2,vIER, 0x7F);
}
- else
+ else if (oss==0)
{
/*
* Init the RBV chip a bit
@@ -201,30 +154,18 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *))
request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func);
-/* mac_debugging_penguin(7);*/
-
/*
* SE/30: disable video int.
* XXX: testing for SE/30 VBL
*/
- if (macintosh_config->ident == MAC_MODEL_SE30
- && console_loglevel != 10) {
+ if (macintosh_config->ident == MAC_MODEL_SE30) {
c = via_read(via1, vBufB);
via_write(via1, vBufB, c|(0x40));
c = via_read(via1, vDirB);
via_write(via1, vDirB, c|(0x40));
}
- /*
- * XXX: use positive edge
- */
-
- if (console_loglevel == 10) {
- c = via_read(via1, vPCR);
- via_write(via1, vPCR, c|(0x1));
- }
-
#if 0 /* gone to mac_init_IRQ */
/*
* Set vPCR for SCSI interrupts.
@@ -237,172 +178,55 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *))
}
-#if 0 /* moved to macints.c */
-
-static void via_irq(volatile unsigned char *via, struct via_irq_tab *irqtab,
- struct pt_regs *regs)
-{
- unsigned char events=(via_read(via, vIFR)&via_read(via,vIER))&0x7F;
- int i;
- int ct=0;
-
- /*
- * Shouldnt happen
- */
-
- if(events==0)
- {
- printk("via_irq: nothing pending!\n");
- return;
- }
-
- do {
- /*
- * Clear the pending flag
- */
-
- /* HACK HACK - FIXME !!! - just testing some keyboard ideas */
-
- /* events&=~(1<<4); */
- via_write(via, vIFR, events);
-
- /*
- * Now see what bits are raised
- */
-
- for(i=0;i<7;i++)
- {
- if(events&(1<<i))
- (irqtab->vector[i])(i, via, regs);
- }
-
- /*
- * And done..
- */
- events=(via_read(via, vIFR)&via_read(via,vIER))&0x7F;
- ct++;
- if(events && ct>8)
- {
- printk("via: stuck events %x\n",events);
- break;
- }
- }
- while(events);
-
- scsi_mac_polled();
-}
-
/*
- *
- * The RBV is different. RBV appears to stand for randomly broken
- * VIA.
+ * get time offset between scheduling timer ticks
+ * Code stolen from arch/m68k/atari/time.c; underflow check probably
+ * wrong.
*/
-
-static void rbv_irq(volatile unsigned char *via, struct via_irq_tab *irqtab,
- struct pt_regs *regs)
+#define TICK_SIZE 10000
+
+/* This is always executed with interrupts disabled. */
+unsigned long mac_gettimeoffset (void)
{
- unsigned char events=(via_read(via, rIFR)&via_read(via,rIER))&0x7F;
- int i;
- int ct=0;
-
- /*
- * Shouldnt happen
- */
-
- if(events==0)
- {
- printk("rbv_irq: nothing pending!\n");
- return;
- }
-
- do {
- /*
- * Clear the pending flag
- */
-
- /* HACK HACK - FIXME !!! - just testing some keyboard ideas */
-
- /* events&=~(1<<4); */
- via_write(via, rIFR, events);
-
- /*
- * Now see what bits are raised
- */
-
- for(i=0;i<7;i++)
- {
- if(events&(1<<i))
- (irqtab->vector[i])(i, via, regs);
- }
-
- /*
- * And done..
- */
- events=(via_read(via, rIFR)&via_read(via,rIER))&0x7F;
- ct++;
- if(events && ct>8)
- {
- printk("rbv: stuck events %x\n",events);
- for(i=0;i<7;i++)
- {
- if(events&(1<<i))
- {
- printk("rbv - bashing source %d\n",
- i);
- via_write(via, rIER, i);
- via_write(via, rIFR, i);
- }
- }
- break;
- }
- }
- while(events);
-}
+ unsigned long ticks, offset = 0;
-/*
- * System interrupts
- */
+ /* read VIA1 timer 2 current value */
+ ticks = via_read(via1, vT1CL) + (via_read(via1, vT1CH)<<8);
+ /* The probability of underflow is less than 2% */
+ if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50)
+ /* Check for pending timer interrupt in VIA1 IFR */
+ if (via_read(via1, vIFR) & 0x40)
+ offset = TICK_SIZE;
-void via1_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
- via_irq(via1, &via1_func_tab, regs);
-}
+ ticks = MAC_CLOCK_TICK - ticks;
+ ticks = ticks * 10000L / MAC_CLOCK_TICK;
-/*
- * Nubus interrupts
- */
-
-void via2_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
-/* printk("via2 interrupt\n");*/
- if(rbv)
- rbv_irq(via2, &via2_func_tab, regs);
- else
- via_irq(via2, &via2_func_tab, regs);
+ return ticks + offset;
}
/*
- * Unexpected via interrupt
+ * PSC (AV Macs; level 3-6): initialize interrupt enable registers
*/
-
-void via_wtf(int slot, volatile void *via, struct pt_regs *regs)
-{
- printk("Unexpected event %d on via %p\n",slot,via);
-}
-void nubus_wtf(int slot, volatile void *via, struct pt_regs *regs)
+void psc_init(void)
{
- printk("Unexpected interrupt on nubus slot %d\n",slot);
+ via_write(psc, pIER3, 0x01);
+ via_write(psc, pIER4, 0x09);
+ via_write(psc, pIER4, 0x86);
+ via_write(psc, pIER5, 0x03);
+ via_write(psc, pIER6, 0x07);
}
-#endif
-
/*
* The power switch - yes its software!
*/
-void mac_reset(void)
+void mac_poweroff(void)
{
+#if 0
+ /*
+ * Powerdown, for the Macs that support it
+ */
if(rbv) {
via_write(via2, rBufB, via_read(via2, rBufB)&~0x04);
} else {
@@ -411,7 +235,38 @@ void mac_reset(void)
/* Send a value of 0 on that line */
via_write(via2,vBufB,via_read(via2,vBufB)&~0x04);
}
+#endif
+ /* We should never make it this far... */
+ /* XXX - delay do we need to spin here ? */
+ while(1); /* Just in case .. */
+}
+
+/*
+ * Not all Macs support software power down; for the rest, just
+ * try the ROM reset vector ...
+ */
+void mac_reset(void)
+{
+ unsigned long flags;
+ unsigned long *reset_hook;
+
+ save_flags(flags);
+ cli();
+
+#if 0 /* need ROMBASE in booter */
+#if 0 /* works on some */
+ rom_reset = (boot_info.bi_mac.rombase + 0xa);
+#else /* testing, doesn't work on SE/30 either */
+ reset_hook = (unsigned long *) (boot_info.bi_mac.rombase + 0x4);
+ printk("ROM reset hook: %p\n", *reset_hook);
+ rom_reset = *reset_hook;
+#endif
+ rom_reset();
+#endif
+ restore_flags(flags);
+
/* We never make it this far... */
+ printk(" reboot failed, reboot manually!\n");
/* XXX - delay do we need to spin here ? */
while(1); /* Just in case .. */
}
@@ -442,140 +297,13 @@ void via1_set_head(int head)
via_write(via1, vBufA, via_read(via1, vBufA)|0x20);
}
-#if 0 /* moved to macints.c */
-
-
-/*
- * Set up the SCSI
- */
-
-void via_scsi_disable(void)
-{
- if (rbv)
- via_write(via2, rIER, (1<<3)|(1<<0));
- else
- via_write(via2, vIER, (1<<3)|(1<<0));
-}
-
-void via_scsi_enable(void)
-{
- if (rbv)
- via_write(via2, rIER, (1<<3)|(1<<0)|0x80);
- else
- via_write(via2, vIER, (1<<3)|(1<<0)|0x80);
-}
-
-void via_scsi_clear(void)
-{
- if (rbv)
- via_write(via2, rIFR, (1<<3)|(1<<0)|0x80);
- volatile unsigned char deep_magic=via_read(via2, vBufB);
- via_scsi_enable();
-}
-
-void via_setup_scsi(void (*handler)(int,volatile void *,struct pt_regs *))
-{
- via2_func_tab.vector[0]=handler; /* SCSI DRQ */
- via2_func_tab.vector[3]=handler; /* SCSI IRQ */
- via_write(via2, vPCR, 0x66); /* Edge direction! */
- via_scsi_enable();
-}
-
-/*
- * Nubus handling
- */
-
-static int nubus_active=0;
-
-int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *))
-{
- slot-=9;
-/* printk("Nubus request irq for slot %d\n",slot);*/
- if(nubus_func_tab.vector[slot]==nubus_wtf)
- return -EBUSY;
- nubus_func_tab.vector[slot]=handler;
- nubus_active|=1<<slot;
-/* printk("program slot %d\n",slot);*/
-/* printk("via2=%p\n",via2);*/
-#if 0
- via_write(via2, vDirA,
- via_read(via2, vDirA)|(1<<slot));
- via_write(via2, vBufA, 0);
-#endif
- if (!rbv) {
- /* Make sure the bit is an input */
- via_write(via2, vDirA,
- via_read(via2, vDirA)&~(1<<slot));
- }
-/* printk("nubus irq on\n");*/
- return 0;
-}
-
-int nubus_free_irq(int slot)
-{
- slot-=9;
- nubus_active&=~(1<<slot);
- nubus_func_tab.vector[slot]=nubus_wtf;
- if (rbv) {
- via_write(via2, rBufA, 1<<slot);
- } else {
- via_write(via2, vDirA,
- via_read(via2, vDirA)|(1<<slot));
- via_write(via2, vBufA, 1<<slot);
- via_write(via2, vDirA,
- via_read(via2, vDirA)&~(1<<slot));
- }
- return 0;
-}
-
-static void via_do_nubus(int slot, volatile void *via, struct pt_regs *regs)
-{
- unsigned char map;
- int i;
- int ct=0;
-
-/* printk("nubus interrupt\n");*/
-
- if (rbv) {
- via_write(via2, rIFR, 0x82); /* lock the nubus interrupt */
- } else {
- via_write(via2, vIFR, 0x82); /* lock the nubus interrupt */
-
- while(1)
- {
- if(rbv)
- map=~via_read(via2, rBufA);
- else
- map=~via_read(via2, vBufA);
- if((map=(map&nubus_active))==0)
- break;
- if(ct++>2)
- {
- printk("nubus stuck events - %d/%d\n", map, nubus_active);
- return;
- }
- for(i=0;i<7;i++)
- {
- if(map&(1<<i))
- {
- (nubus_func_tab.vector[i])(i+9, via, regs);
- }
- }
- if (rbv)
- via_write(via2, rIFR, 0x02); /* clear it */
- else
- via_write(via2, vIFR, 0x02); /* clear it */
- }
-
- /* And done */
-}
-#endif
-
void nubus_init_via(void)
{
if (rbv) {
- via_write(via2, rBufB, via_read(via2, rBufB)|0x02);
- via_write(via2, rIER, 0x82); /* Interrupts on */
+ if (oss==0) {
+ via_write(via2, rBufB, via_read(via2, rBufB)|0x02);
+ via_write(via2, rIER, 0x82); /* Interrupts on */
+ }
} else {
/* Assert the nubus active */
via_write(via2, vDirB, via_read(via2, vDirB)|0x02);
@@ -584,7 +312,13 @@ void nubus_init_via(void)
/* via_write(via2, vDirA, 0xFF); */
via_write(via2, vIER, 0x82); /* Interrupts on */
}
- printk("BTW boot via1 acr=%X datab=%X pcr=%X\n",
- (int)via1_clock, (int)via1_datab, (int)via_read(via1, vPCR));
-}
+ printk("nubus_init_via: via1 acr=%X datab=%X pcr=%X\n",
+ (int)via_read(via1, vACR), (int)via_read(via1, vBufB),
+ (int)via_read(via1, vPCR));
+
+ if (rbv==0)
+ printk("nubus_init_via: via2 acr=%X datab=%X pcr=%X\n",
+ (int)via_read(via2, vACR), (int)via_read(via2, vBufB),
+ (int)via_read(via2, vPCR));
+}
diff --git a/arch/m68k/mm/Makefile b/arch/m68k/mm/Makefile
index 2ad15d861..54f0fae1a 100644
--- a/arch/m68k/mm/Makefile
+++ b/arch/m68k/mm/Makefile
@@ -8,6 +8,6 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := mm.o
-O_OBJS := init.o fault.o memory.o kmap.o extable.o
+O_OBJS := init.o fault.o memory.o kmap.o extable.o hwtest.o
include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index aecbe0a5d..62129782b 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -45,9 +45,12 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
#endif
down(&mm->mmap_sem);
+
vma = find_vma(mm, address);
if (!vma)
- goto bad_area;
+ goto bad_area;
+ if (vma->vm_flags & VM_IO)
+ goto bad_area;
if (vma->vm_start <= address)
goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN))
@@ -84,7 +87,6 @@ good_area:
goto bad_area;
}
handle_mm_fault(current, vma, address, write);
- up(&mm->mmap_sem);
/* There seems to be a missing invalidate somewhere in do_no_page.
* Until I found it, this one cures the problem and makes
@@ -92,6 +94,7 @@ good_area:
*/
if (CPU_IS_040_OR_060)
flush_tlb_page(vma, address);
+ up(&mm->mmap_sem);
return 0;
/*
diff --git a/arch/m68k/mm/hwtest.c b/arch/m68k/mm/hwtest.c
new file mode 100644
index 000000000..60ad5e812
--- /dev/null
+++ b/arch/m68k/mm/hwtest.c
@@ -0,0 +1,81 @@
+/* Tests for presence or absence of hardware registers.
+ * This code was originally in atari/config.c, but I noticed
+ * that it was also in drivers/nubus/nubus.c and I wanted to
+ * use it in hp300/config.c, so it seemed sensible to pull it
+ * out into its own file.
+ *
+ * The test is for use when trying to read a hardware register
+ * that isn't present would cause a bus error. We set up a
+ * temporary handler so that this doesn't kill the kernel.
+ *
+ * There is a test-by-reading and a test-by-writing; I present
+ * them here complete with the comments from the original atari
+ * config.c...
+ * -- PMM <pmaydell@chiark.greenend.org.uk>, 05/1998
+ */
+
+/* This function tests for the presence of an address, specially a
+ * hardware register address. It is called very early in the kernel
+ * initialization process, when the VBR register isn't set up yet. On
+ * an Atari, it still points to address 0, which is unmapped. So a bus
+ * error would cause another bus error while fetching the exception
+ * vector, and the CPU would do nothing at all. So we needed to set up
+ * a temporary VBR and a vector table for the duration of the test.
+ */
+
+int hwreg_present( volatile void *regp )
+{
+ int ret = 0;
+ long save_sp, save_vbr;
+ long tmp_vectors[3];
+
+ __asm__ __volatile__
+ ( "movec %/vbr,%2\n\t"
+ "movel #Lberr1,%4@(8)\n\t"
+ "movec %4,%/vbr\n\t"
+ "movel %/sp,%1\n\t"
+ "moveq #0,%0\n\t"
+ "tstb %3@\n\t"
+ "nop\n\t"
+ "moveq #1,%0\n"
+ "Lberr1:\n\t"
+ "movel %1,%/sp\n\t"
+ "movec %2,%/vbr"
+ : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
+ : "a" (regp), "a" (tmp_vectors)
+ );
+
+ return( ret );
+}
+
+/* Basically the same, but writes a value into a word register, protected
+ * by a bus error handler. Returns 1 if successful, 0 otherwise.
+ */
+
+int hwreg_write( volatile void *regp, unsigned short val )
+{
+ int ret;
+ long save_sp, save_vbr;
+ long tmp_vectors[3];
+
+ __asm__ __volatile__
+ ( "movec %/vbr,%2\n\t"
+ "movel #Lberr2,%4@(8)\n\t"
+ "movec %4,%/vbr\n\t"
+ "movel %/sp,%1\n\t"
+ "moveq #0,%0\n\t"
+ "movew %5,%3@\n\t"
+ "nop \n\t" /* If this nop isn't present, 'ret' may already be
+ * loaded with 1 at the time the bus error
+ * happens! */
+ "moveq #1,%0\n"
+ "Lberr2:\n\t"
+ "movel %1,%/sp\n\t"
+ "movec %2,%/vbr"
+ : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
+ : "a" (regp), "a" (tmp_vectors), "g" (val)
+ );
+
+ return( ret );
+}
+
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index 6dab5db9d..7ea05b3dd 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -31,6 +31,20 @@ extern void die_if_kernel(char *,struct pt_regs *,long);
extern void init_kpointer_table(void);
extern void show_net_buffers(void);
+int do_check_pgt_cache(int low, int high)
+{
+ int freed = 0;
+ if(pgtable_cache_size > high) {
+ do {
+ if(pmd_quicklist)
+ freed += free_pmd_slow(get_pmd_fast());
+ if(pte_quicklist)
+ free_pte_slow(get_pte_fast()), freed++;
+ } while(pgtable_cache_size > low);
+ }
+ return freed;
+}
+
/*
* BAD_PAGE is the page that is used for page faults when linux
* is out-of-memory. Older versions of linux just did a
@@ -76,7 +90,7 @@ void show_mem(void)
total++;
if (PageReserved(mem_map+i))
reserved++;
- if (PageSwapCache(mem_map+i))
+ else if (PageSwapCache(mem_map+i))
cached++;
else if (!atomic_read(&mem_map[i].count))
free++;
@@ -91,6 +105,7 @@ void show_mem(void)
printk("%d pages nonshared\n",nonshared);
printk("%d pages shared\n",shared);
printk("%d pages swap cached\n",cached);
+ printk("%ld pages in page table cache\n",pgtable_cache_size);
show_buffers();
#ifdef CONFIG_NET
show_net_buffers();
@@ -231,7 +246,7 @@ map_chunk (unsigned long addr, unsigned long size, unsigned long *memavailp))
*/
for (i = 0; i < 64; i++) {
pte_val(ktablep[i]) = physaddr | _PAGE_PRESENT
- | _PAGE_CACHE040 | _PAGE_GLOBAL040
+ | m68k_supervisor_cachemode | _PAGE_GLOBAL040
| _PAGE_ACCESSED;
physaddr += PAGE_SIZE;
}
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index e1bfa1540..be716a5b2 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -19,10 +19,6 @@
extern pte_t *kernel_page_table (unsigned long *memavailp);
-/* Virtual address region for use by kernel_map() */
-#define KMAP_START 0xd0000000
-#define KMAP_END 0xf0000000
-
/* Granularity of kernel_map() allocations */
#define KMAP_STEP (256*1024)
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
index 39a29b9b0..ad7c8141a 100644
--- a/arch/m68k/mm/memory.c
+++ b/arch/m68k/mm/memory.c
@@ -4,6 +4,7 @@
* Copyright (C) 1995 Hamish Macdonald
*/
+#include <linux/config.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -16,38 +17,90 @@
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/traps.h>
+#ifdef CONFIG_AMIGA
#include <asm/amigahw.h>
+#endif
-/* Strings for `extern inline' functions in <asm/pgtable.h>. If put
- directly into these functions, they are output for every file that
- includes pgtable.h */
+struct pgtable_cache_struct quicklists;
-const char PgtabStr_bad_pmd[] = "Bad pmd in pte_alloc: %08lx\n";
-const char PgtabStr_bad_pgd[] = "Bad pgd in pmd_alloc: %08lx\n";
-const char PgtabStr_bad_pmdk[] = "Bad pmd in pte_alloc_kernel: %08lx\n";
-const char PgtabStr_bad_pgdk[] = "Bad pgd in pmd_alloc_kernel: %08lx\n";
+void __bad_pte(pmd_t *pmd)
+{
+ printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+ pmd_set(pmd, BAD_PAGETABLE);
+}
-static struct ptable_desc {
- struct ptable_desc *prev;
- struct ptable_desc *next;
- unsigned long page;
- unsigned char alloced;
-} ptable_list = { &ptable_list, &ptable_list, 0, 0xff };
+void __bad_pmd(pgd_t *pgd)
+{
+ printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
+ pgd_set(pgd, (pmd_t *)BAD_PAGETABLE);
+}
-#define PD_NONEFREE(dp) ((dp)->alloced == 0xff)
-#define PD_ALLFREE(dp) ((dp)->alloced == 0)
-#define PD_TABLEFREE(dp,i) (!((dp)->alloced & (1<<(i))))
-#define PD_MARKUSED(dp,i) ((dp)->alloced |= (1<<(i)))
-#define PD_MARKFREE(dp,i) ((dp)->alloced &= ~(1<<(i)))
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+{
+ pte_t *pte;
+
+ pte = (pte_t *) __get_free_page(GFP_KERNEL);
+ if (pmd_none(*pmd)) {
+ if (pte) {
+ clear_page((unsigned long)pte);
+ flush_page_to_ram((unsigned long)pte);
+ flush_tlb_kernel_page((unsigned long)pte);
+ nocache_page((unsigned long)pte);
+ pmd_set(pmd, pte);
+ return pte + offset;
+ }
+ pmd_set(pmd, BAD_PAGETABLE);
+ return NULL;
+ }
+ free_page((unsigned long)pte);
+ if (pmd_bad(*pmd)) {
+ __bad_pte(pmd);
+ return NULL;
+ }
+ return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset)
+{
+ pmd_t *pmd;
+
+ pmd = get_pointer_table();
+ if (pgd_none(*pgd)) {
+ if (pmd) {
+ pgd_set(pgd, pmd);
+ return pmd + offset;
+ }
+ pgd_set(pgd, (pmd_t *)BAD_PAGETABLE);
+ return NULL;
+ }
+ free_pointer_table(pmd);
+ if (pgd_bad(*pgd)) {
+ __bad_pmd(pgd);
+ return NULL;
+ }
+ return (pmd_t *) pgd_page(*pgd) + offset;
+}
+
+
+/* ++andreas: {get,free}_pointer_table rewritten to use unused fields from
+ struct page instead of separately kmalloced struct. Stolen from
+ arch/sparc/mm/srmmu.c ... */
+
+typedef struct page ptable_desc;
+static ptable_desc ptable_list = { &ptable_list, &ptable_list };
+
+#define PD_MARKBITS(dp) (*(unsigned char *)&(dp)->offset)
+#define PD_PAGE(dp) (PAGE_OFFSET + ((dp)->map_nr << PAGE_SHIFT))
+#define PAGE_PD(page) ((ptable_desc *)&mem_map[MAP_NR(page)])
#define PTABLE_SIZE (PTRS_PER_PMD * sizeof(pmd_t))
pmd_t *get_pointer_table (void)
{
- pmd_t *pmdp = NULL;
- unsigned long flags;
- struct ptable_desc *dp = ptable_list.next;
- int i;
+ ptable_desc *dp = ptable_list.next;
+ unsigned char mask = PD_MARKBITS (dp);
+ unsigned char tmp;
+ unsigned int off;
/*
* For a pointer table for a user process address space, a
@@ -55,102 +108,70 @@ pmd_t *get_pointer_table (void)
* page can hold 8 pointer tables. The page is remapped in
* virtual address space to be noncacheable.
*/
- if (PD_NONEFREE (dp)) {
+ if (mask == 0) {
+ unsigned long page;
+ ptable_desc *new;
- if (!(dp = kmalloc (sizeof(struct ptable_desc),GFP_KERNEL))) {
+ if (!(page = get_free_page (GFP_KERNEL)))
return 0;
- }
- if (!(dp->page = get_free_page (GFP_KERNEL))) {
- kfree (dp);
- return 0;
- }
+ flush_tlb_kernel_page(page);
+ nocache_page (page);
- flush_tlb_kernel_page((unsigned long) dp->page);
- nocache_page (dp->page);
-
- dp->alloced = 0;
- /* put at head of list */
- save_flags(flags);
- cli();
- dp->next = ptable_list.next;
- dp->prev = ptable_list.next->prev;
- ptable_list.next->prev = dp;
- ptable_list.next = dp;
- restore_flags(flags);
+ new = PAGE_PD(page);
+ PD_MARKBITS(new) = 0xfe;
+ (new->prev = dp->prev)->next = new;
+ (new->next = dp)->prev = new;
+ return (pmd_t *)page;
}
- for (i = 0; i < 8; i++)
- if (PD_TABLEFREE (dp, i)) {
- PD_MARKUSED (dp, i);
- pmdp = (pmd_t *)(dp->page + PTABLE_SIZE*i);
- break;
- }
+ for (tmp = 1, off = 0; (mask & tmp) == 0; tmp <<= 1, off += PTABLE_SIZE);
+ PD_MARKBITS(dp) = mask & ~tmp;
+ if (!PD_MARKBITS(dp)) {
+ ptable_desc *last, *next;
- if (PD_NONEFREE (dp)) {
/* move to end of list */
- save_flags(flags);
- cli();
- dp->prev->next = dp->next;
- dp->next->prev = dp->prev;
-
- dp->next = ptable_list.next->prev;
- dp->prev = ptable_list.prev;
- ptable_list.prev->next = dp;
- ptable_list.prev = dp;
- restore_flags(flags);
- }
-
- memset (pmdp, 0, PTABLE_SIZE);
+ next = dp->next;
+ (next->prev = dp->prev)->next = next;
- return pmdp;
+ last = ptable_list.prev;
+ (dp->next = last->next)->prev = dp;
+ (dp->prev = last)->next = dp;
+ }
+ return (pmd_t *) (PD_PAGE(dp) + off);
}
-void free_pointer_table (pmd_t *ptable)
+int free_pointer_table (pmd_t *ptable)
{
- struct ptable_desc *dp;
+ ptable_desc *dp, *first;
unsigned long page = (unsigned long)ptable & PAGE_MASK;
- int index = ((unsigned long)ptable - page)/PTABLE_SIZE;
- unsigned long flags;
-
- for (dp = ptable_list.next; dp->page && dp->page != page; dp = dp->next)
- ;
-
- if (!dp->page)
- panic ("unable to find desc for ptable %p on list!", ptable);
+ unsigned char mask = 1 << (((unsigned long)ptable - page)/PTABLE_SIZE);
- if (PD_TABLEFREE (dp, index))
+ dp = PAGE_PD(page);
+ if (PD_MARKBITS (dp) & mask)
panic ("table already free!");
- PD_MARKFREE (dp, index);
+ PD_MARKBITS (dp) |= mask;
- if (PD_ALLFREE (dp)) {
+ if (PD_MARKBITS(dp) == 0xff) {
/* all tables in page are free, free page */
- save_flags(flags);
- cli();
- dp->prev->next = dp->next;
- dp->next->prev = dp->prev;
- restore_flags(flags);
- cache_page (dp->page);
- free_page (dp->page);
- kfree (dp);
- return;
- } else {
+ ptable_desc *next = dp->next;
+ (next->prev = dp->prev)->next = next;
+ cache_page (page);
+ free_page (page);
+ return 1;
+ } else if ((first = ptable_list.next) != dp) {
/*
- * move this descriptor the the front of the list, since
+ * move this descriptor to the front of the list, since
* it has one or more free tables.
*/
- save_flags(flags);
- cli();
- dp->prev->next = dp->next;
- dp->next->prev = dp->prev;
-
- dp->next = ptable_list.next;
- dp->prev = ptable_list.next->prev;
- ptable_list.next->prev = dp;
- ptable_list.next = dp;
- restore_flags(flags);
+ ptable_desc *next = dp->next;
+ (next->prev = dp->prev)->next = next;
+
+ (dp->prev = first->prev)->next = dp;
+ (dp->next = first)->prev = dp;
}
+ return 0;
}
/* maximum pages used for kpointer tables */
@@ -451,12 +472,14 @@ unsigned long mm_ptov (unsigned long paddr)
*
*/
+#ifdef CONFIG_AMIGA
/*
* if on an amiga and address is in first 16M, move it
* to the ZTWO_VADDR range
*/
if (MACH_IS_AMIGA && paddr < 16*1024*1024)
return ZTWO_VADDR(paddr);
+#endif
return paddr;
}
diff --git a/arch/m68k/mvme16x/16xints.c b/arch/m68k/mvme16x/16xints.c
index c79ff17ad..fbb370a07 100644
--- a/arch/m68k/mvme16x/16xints.c
+++ b/arch/m68k/mvme16x/16xints.c
@@ -127,7 +127,7 @@ int mvme16x_get_irq_list (char *buf)
static void mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp)
{
- panic ("Unknown interrupt 0x%02x", irq);
+ printk ("Unknown interrupt 0x%02x\n", irq);
}
diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile
index 97c670f3c..bb7485ab8 100644
--- a/arch/m68k/mvme16x/Makefile
+++ b/arch/m68k/mvme16x/Makefile
@@ -8,7 +8,7 @@
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := mvme16x.o
-O_OBJS := config.o 16xints.o
+O_OBJS := config.o 16xints.o rtc.o
#OX_OBJS = ksyms.o
include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index 00e7db8d1..838c3bbac 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -34,26 +34,10 @@
#include <asm/machdep.h>
#include <asm/mvme16xhw.h>
-typedef struct {
- unsigned char
- ctrl,
- bcd_sec,
- bcd_min,
- bcd_hr,
- bcd_dow,
- bcd_dom,
- bcd_mth,
- bcd_year;
-} MK48T08;
-
-#define RTC_WRITE 0x80
-#define RTC_READ 0x40
-#define RTC_STOP 0x20
-
int atari_SCC_reset_done = 1; /* So SCC doesn't get reset */
u_long atari_mch_cookie = 0;
-MK48T08 * volatile rtc = (MK48T08 *)0xfffc1ff8;
+static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
extern void mvme16x_process_int (int level, struct pt_regs *regs);
extern void mvme16x_init_IRQ (void);
@@ -143,6 +127,11 @@ static int mvme16x_get_hardware_list(char *buffer)
}
+#define pcc2chip ((volatile u_char *)0xfff42000)
+#define PccSCCMICR 0x1d
+#define PccSCCTICR 0x1e
+#define PccSCCRICR 0x1f
+
__initfunc(void config_mvme16x(void))
{
p_bdid p = (p_bdid)mvme_bdid_ptr;
@@ -197,7 +186,43 @@ __initfunc(void config_mvme16x(void))
rev & MVME16x_CONFIG_NO_ETHERNET ? "NOT " : "");
}
else
+ {
mvme16x_config = MVME16x_CONFIG_GOT_LP | MVME16x_CONFIG_GOT_CD2401;
+
+ /* Dont allow any interrupts from the CD2401 until the interrupt */
+ /* handlers are installed */
+
+ pcc2chip[PccSCCMICR] = 0x10;
+ pcc2chip[PccSCCTICR] = 0x10;
+ pcc2chip[PccSCCRICR] = 0x10;
+ }
+}
+
+static void mvme16x_abort_int (int irq, void *dev_id, struct pt_regs *fp)
+{
+ p_bdid p = (p_bdid)mvme_bdid_ptr;
+ unsigned long *new = (unsigned long *)vectors;
+ unsigned long *old = (unsigned long *)0xffe00000;
+ volatile unsigned char uc, *ucp;
+
+ if (p->brdno == 0x0162 || p->brdno == 0x172)
+ {
+ ucp = (volatile unsigned char *)0xfff42043;
+ uc = *ucp | 8;
+ *ucp = uc;
+ }
+ else
+ {
+ *(volatile unsigned long *)0xfff40074 = 0x40000000;
+ }
+ *(new+4) = *(old+4); /* Illegal instruction */
+ *(new+9) = *(old+9); /* Trace */
+ *(new+47) = *(old+47); /* Trap #15 */
+
+ if (p->brdno == 0x0162 || p->brdno == 0x172)
+ *(new+0x5e) = *(old+0x5e); /* ABORT switch */
+ else
+ *(new+0x6e) = *(old+0x6e); /* ABORT switch */
}
static void mvme16x_timer_int (int irq, void *dev_id, struct pt_regs *fp)
@@ -208,15 +233,26 @@ static void mvme16x_timer_int (int irq, void *dev_id, struct pt_regs *fp)
void mvme16x_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
{
+ p_bdid p = (p_bdid)mvme_bdid_ptr;
+ int irq;
+
tick_handler = timer_routine;
/* Using PCCchip2 or MC2 chip tick timer 1 */
*(volatile unsigned long *)0xfff42008 = 0;
*(volatile unsigned long *)0xfff42004 = 10000; /* 10ms */
*(volatile unsigned char *)0xfff42017 |= 3;
*(volatile unsigned char *)0xfff4201b = 0x16;
- if (request_irq(IRQ_MVME16x_TIMER, mvme16x_timer_int, 0,
+ if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0,
"timer", mvme16x_timer_int))
panic ("Couldn't register timer int");
+
+ if (p->brdno == 0x0162 || p->brdno == 0x172)
+ irq = MVME162_IRQ_ABORT;
+ else
+ irq = MVME167_IRQ_ABORT;
+ if (request_irq(irq, mvme16x_abort_int, 0,
+ "abort", mvme16x_abort_int))
+ panic ("Couldn't register abort int");
}
@@ -254,76 +290,11 @@ int mvme16x_set_clock_mmss (unsigned long nowtime)
return 0;
}
-/*
- * console_map_init(), here to avoid having to modify drivers/block/genhd.c
- */
-
-void console_map_init(void)
-{
-}
-
-/*
- * fbmem_init(), here to avoid having to modify drivers/char/mem.c
- */
-
-void fbmem_init(void)
-{
-}
-
-/* Avoid mods to drivers/char/tty_io.c */
-
-unsigned long con_init(unsigned long kmem_start)
-{
- return (kmem_start);
-}
-
-/* Avoid mods to drivers/char/tty_io.c */
-
-int vcs_init(void)
-{
- return (0);
-}
-
-/* Avoid mods to drivers/char/tty_io.c */
-
-int kbd_init(void)
-{
- return (0);
-}
-
-/* Avoid mods to init/main.c */
-
-void no_scroll(char *str, int *ints)
-{
-}
-
-/* Avoid mods to kernel/panic.c */
-
-void do_unblank_screen(void)
-{
-}
-
int mvme16x_keyb_init (void)
{
return 0;
}
-void mvme16x_set_vectors (void)
-{
- p_bdid p = (p_bdid)mvme_bdid_ptr;
- unsigned long *new = (unsigned long *)vectors;
- unsigned long *old = (unsigned long *)0xffe00000;;
-
- *(new+4) = *(old+4); /* Illegal instruction */
- *(new+9) = *(old+9); /* Trace */
- *(new+47) = *(old+47); /* Trap #15 */
-
- if (p->brdno == 0x0162 || p->brdno == 0x172)
- *(new+0x5e) = *(old+0x5e); /* ABORT switch */
- else
- *(new+0x6e) = *(old+0x6e); /* ABORT switch */
-}
-
/*------------------- Serial console stuff ------------------------*/
extern void mvme167_serial_console_setup(int cflag);
@@ -372,7 +343,7 @@ static void scc_delay (void)
static void scc_write (char ch)
{
- volatile char *p = (volatile char *)SCC_A_ADDR;
+ volatile char *p = (volatile char *)MVME_SCC_A_ADDR;
do {
scc_delay();
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
new file mode 100644
index 000000000..6b7c0c011
--- /dev/null
+++ b/arch/m68k/mvme16x/rtc.c
@@ -0,0 +1,166 @@
+/*
+ * Real Time Clock interface for Linux on the MVME16x
+ *
+ * Based on the PC driver by Paul Gortmaker.
+ */
+
+#define RTC_VERSION "1.00"
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */
+#include <asm/mvme16xhw.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/setup.h>
+
+/*
+ * We sponge a minor off of the misc major. No need slurping
+ * up another valuable major dev number for this. If you add
+ * an ioctl, make sure you don't conflict with SPARC's RTC
+ * ioctls.
+ */
+
+#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10)
+#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10)
+
+static unsigned char days_in_mo[] =
+{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+static char rtc_status = 0;
+
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE;
+ unsigned long flags;
+ struct rtc_time wtime;
+
+ switch (cmd) {
+ case RTC_RD_TIME: /* Read the time/date from RTC */
+ {
+ save_flags(flags);
+ cli();
+ /* Ensure clock and real-time-mode-register are accessible */
+ rtc->ctrl = RTC_READ;
+ wtime.tm_sec = BCD2BIN(rtc->bcd_sec);
+ wtime.tm_min = BCD2BIN(rtc->bcd_min);
+ wtime.tm_hour = BCD2BIN(rtc->bcd_hr);
+ wtime.tm_mday = BCD2BIN(rtc->bcd_dom);
+ wtime.tm_mon = BCD2BIN(rtc->bcd_mth)-1;
+ wtime.tm_year = BCD2BIN(rtc->bcd_year);
+ if (wtime.tm_year < 70)
+ wtime.tm_year += 100;
+ wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1;
+ rtc->ctrl = 0;
+ restore_flags(flags);
+ return copy_to_user((void *)arg, &wtime, sizeof wtime) ?
+ -EFAULT : 0;
+ }
+ case RTC_SET_TIME: /* Set the RTC */
+ {
+ unsigned char leap_yr;
+ struct rtc_time rtc_tm;
+
+ if (!suser())
+ return -EACCES;
+
+ if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
+ sizeof(struct rtc_time)))
+ return -EFAULT;
+
+ leap_yr = ((!(rtc_tm.tm_year % 4) && (rtc_tm.tm_year % 100)) || !(rtc_tm.tm_year % 400));
+
+ if ((rtc_tm.tm_mon > 12) || (rtc_tm.tm_mday == 0))
+ return -EINVAL;
+
+ if (rtc_tm.tm_mday > (days_in_mo[rtc_tm.tm_mon] + ((rtc_tm.tm_mon == 2) && leap_yr)))
+ return -EINVAL;
+
+ if ((rtc_tm.tm_hour >= 24) || (rtc_tm.tm_min >= 60) || (rtc_tm.tm_sec >= 60))
+ return -EINVAL;
+
+ save_flags(flags);
+ cli();
+ rtc->ctrl = RTC_WRITE;
+
+ rtc->bcd_sec = BIN2BCD(rtc_tm.tm_sec);
+ rtc->bcd_min = BIN2BCD(rtc_tm.tm_min);
+ rtc->bcd_hr = BIN2BCD(rtc_tm.tm_hour);
+ rtc->bcd_dom = BIN2BCD(rtc_tm.tm_mday);
+ rtc->bcd_mth = BIN2BCD(rtc_tm.tm_mon + 1);
+ rtc->bcd_year = BIN2BCD(rtc_tm.tm_year%100);
+ if (rtc_tm.tm_wday >= 0)
+ rtc->bcd_dow = BIN2BCD(rtc_tm.tm_wday+1);
+
+ rtc->ctrl = 0;
+ restore_flags(flags);
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+/*
+ * We enforce only one user at a time here with the open/close.
+ * Also clear the previous interrupt data on an open, and clean
+ * up things on a close.
+ */
+
+static int rtc_open(struct inode *inode, struct file *file)
+{
+ if(rtc_status)
+ return -EBUSY;
+
+ rtc_status = 1;
+ return 0;
+}
+
+static int rtc_release(struct inode *inode, struct file *file)
+{
+ rtc_status = 0;
+ return 0;
+}
+
+/*
+ * The various file operations we support.
+ */
+
+static struct file_operations rtc_fops = {
+ NULL,
+ NULL,
+ NULL, /* No write */
+ NULL, /* No readdir */
+ NULL,
+ rtc_ioctl,
+ NULL, /* No mmap */
+ rtc_open,
+ rtc_release
+};
+
+static struct miscdevice rtc_dev=
+{
+ RTC_MINOR,
+ "rtc",
+ &rtc_fops
+};
+
+__initfunc(int rtc_MK48T08_init(void))
+{
+ if (!MACH_IS_MVME16x)
+ return -ENODEV;
+
+ printk(KERN_INFO "MK48T08 Real Time Clock Driver v%s\n", RTC_VERSION);
+ misc_register(&rtc_dev);
+ return 0;
+}
+