summaryrefslogtreecommitdiffstats
path: root/arch/m68k
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k')
-rw-r--r--arch/m68k/Makefile15
-rw-r--r--arch/m68k/atari/atakeyb.c4
-rw-r--r--arch/m68k/bvme6000/config.c4
-rw-r--r--arch/m68k/config.in117
-rw-r--r--arch/m68k/defconfig1
-rw-r--r--arch/m68k/hp300/hil.c9
-rw-r--r--arch/m68k/kernel/entry.S20
-rw-r--r--arch/m68k/kernel/head.S148
-rw-r--r--arch/m68k/kernel/ints.c14
-rw-r--r--arch/m68k/kernel/m68k_defs.h47
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c4
-rw-r--r--arch/m68k/kernel/process.c12
-rw-r--r--arch/m68k/kernel/ptrace.c11
-rw-r--r--arch/m68k/kernel/setup.c88
-rw-r--r--arch/m68k/kernel/time.c3
-rw-r--r--arch/m68k/lib/semaphore.S10
-rw-r--r--arch/m68k/mac/mackeyb.c6
-rw-r--r--arch/m68k/mm/init.c22
-rw-r--r--arch/m68k/mm/kmap.c27
-rw-r--r--arch/m68k/mm/memory.c14
-rw-r--r--arch/m68k/mvme147/147ints.c142
-rw-r--r--arch/m68k/mvme147/Makefile14
-rw-r--r--arch/m68k/mvme147/config.c240
-rw-r--r--arch/m68k/mvme16x/config.c4
-rw-r--r--arch/m68k/q40/Makefile14
-rw-r--r--arch/m68k/q40/README121
-rw-r--r--arch/m68k/q40/config.c425
-rw-r--r--arch/m68k/q40/q40ints.c347
-rw-r--r--arch/m68k/sun3x/Makefile14
-rw-r--r--arch/m68k/sun3x/config.c128
-rw-r--r--arch/m68k/sun3x/dvma.c162
-rw-r--r--arch/m68k/sun3x/sbus.c44
-rw-r--r--arch/m68k/sun3x/time.c83
-rw-r--r--arch/m68k/sun3x/time.h9
34 files changed, 2240 insertions, 83 deletions
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index cb60ea268..3a5957b09 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -56,6 +56,11 @@ SUBDIRS += arch/m68k/kernel arch/m68k/mm arch/m68k/lib
CORE_FILES := arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o $(CORE_FILES)
LIBS += arch/m68k/lib/lib.a
+ifdef CONFIG_Q40
+CORE_FILES := $(CORE_FILES) arch/m68k/q40/q40.o
+SUBDIRS := $(SUBDIRS) arch/m68k/q40
+endif
+
ifdef CONFIG_AMIGA
CORE_FILES := $(CORE_FILES) arch/m68k/amiga/amiga.o
SUBDIRS := $(SUBDIRS) arch/m68k/amiga
@@ -81,6 +86,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/apollo/apollo.o
SUBDIRS := $(SUBDIRS) arch/m68k/apollo
endif
+ifdef CONFIG_MVME147
+CORE_FILES := $(CORE_FILES) arch/m68k/mvme147/mvme147.o
+SUBDIRS := $(SUBDIRS) arch/m68k/mvme147
+endif
+
ifdef CONFIG_MVME16x
CORE_FILES := $(CORE_FILES) arch/m68k/mvme16x/mvme16x.o
SUBDIRS := $(SUBDIRS) arch/m68k/mvme16x
@@ -91,6 +101,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/bvme6000/bvme6000.o
SUBDIRS := $(SUBDIRS) arch/m68k/bvme6000
endif
+ifdef CONFIG_SUN3X
+CORE_FILES := $(CORE_FILES) arch/m68k/sun3x/sun3x.o
+SUBDIRS := $(SUBDIRS) arch/m68k/sun3x
+endif
+
ifdef CONFIG_M68040
CORE_FILES := $(CORE_FILES) arch/m68k/fpsp040/fpsp.o
SUBDIRS := $(SUBDIRS) arch/m68k/fpsp040
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
index 79ef5f9fd..6de1fd686 100644
--- a/arch/m68k/atari/atakeyb.c
+++ b/arch/m68k/atari/atakeyb.c
@@ -291,7 +291,7 @@ static void atakeyb_rep( unsigned long ignore )
atakeyb_rep_timer.prev = atakeyb_rep_timer.next = NULL;
add_timer( &atakeyb_rep_timer );
- handle_scancode(rep_scancode);
+ handle_scancode(rep_scancode, 1);
}
atari_enable_irq( IRQ_MFP_ACIA );
@@ -448,7 +448,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
add_timer( &atakeyb_rep_timer );
}
- handle_scancode(break_flag | scancode);
+ handle_scancode(scancode, !break_flag);
break;
}
break;
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 543b04c74..fc1b5627f 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -417,10 +417,10 @@ void bvme6000_init_console_port (struct console *co, int cflag)
static void scc_delay (void)
{
int n;
- char i;
+ volatile int trash;
for (n = 0; n < 20; n++)
- i = *(volatile char *)0;
+ trash = n;
}
static void scc_write (char ch)
diff --git a/arch/m68k/config.in b/arch/m68k/config.in
index a67227d60..a8dacc904 100644
--- a/arch/m68k/config.in
+++ b/arch/m68k/config.in
@@ -37,6 +37,7 @@ fi
bool 'Apollo support' CONFIG_APOLLO
bool 'VME (Motorola and BVM) support' CONFIG_VME
if [ "$CONFIG_VME" = "y" ]; then
+ bool 'MVME147 support' CONFIG_MVME147
bool 'MVME162, 166 and 167 support' CONFIG_MVME16x
bool 'BVME4000 and BVME6000 support' CONFIG_BVME6000
fi
@@ -44,10 +45,13 @@ bool 'HP9000/300 support' CONFIG_HP300
if [ "$CONFIG_HP300" = "y" ]; then
bool 'DIO bus support' CONFIG_DIO
fi
+bool 'Sun3x support' CONFIG_SUN3X
+
define_bool CONFIG_SUN3 n
if [ "$CONFIG_PCI" = "y" ]; then
bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
fi
+bool 'Q40/Q60 support' CONFIG_Q40
comment 'Processor type'
bool '68020 support' CONFIG_M68020
@@ -94,6 +98,29 @@ else
fi
fi
bool '/proc/hardware support' CONFIG_PROC_HARDWARE
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Parallel port support (EXPERIMENTAL, disables old lp driver!)' CONFIG_PARPORT
+ if [ "$CONFIG_PARPORT" != "n" ]; then
+ if [ "$CONFIG_AMIGA" != "n" ]; then
+ dep_tristate ' Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT
+ if [ "$CONFIG_ZORRO" != "n" ]; then
+ dep_tristate ' Multiface III parallel port' CONFIG_PARPORT_MFC3 $CONFIG_PARPORT
+ fi
+ fi
+ if [ "$CONFIG_Q40" != "n" ]; then
+ tristate ' Q40 Parallel port' CONFIG_PARPORT
+ if [ "$CONFIG_PARPORT" != "n" ]; then
+ define_bool CONFIG_PARPORT_PC y
+ fi
+ fi
+ fi
+ if [ "$CONFIG_ATARI" == "y" ]; then
+ dep_tristate ' Atari builtin port' CONFIG_PARPORT_ATARI $CONFIG_PARPORT
+ fi
+fi
+
+
endmenu
source drivers/block/Config.in
@@ -147,6 +174,7 @@ if [ "$CONFIG_ZORRO" = "y" ]; then
bool 'A4091 SCSI support' CONFIG_A4091_SCSI
bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI
bool 'Blizzard PowerUP 603e+ SCSI' CONFIG_BLZ603EPLUS_SCSI
+ dep_tristate 'BSC Oktagon SCSI support' CONFIG_OKTAGON_SCSI $CONFIG_SCSI
bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
# bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI
fi
@@ -167,6 +195,10 @@ if [ "$CONFIG_MAC" = "y" ]; then
fi
#dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
+if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME147" = "y" ]; then
+ bool 'WD33C93 SCSI driver for MVME147' CONFIG_MVME147_SCSI
+fi
+
if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then
bool 'NCR53C710 SCSI driver for MVME16x' CONFIG_MVME16x_SCSI
fi
@@ -175,6 +207,10 @@ if [ "$CONFIG_VME" = "y" -a "$CONFIG_BVME6000" = "y" ]; then
bool 'NCR53C710 SCSI driver for BVME6000' CONFIG_BVME6000_SCSI
fi
+if [ "$CONFIG_SUN3X" = "y" ]; then
+ bool 'ESP SCSI driver' CONFIG_SUN3X_ESP
+fi
+
endmenu
fi
@@ -219,6 +255,9 @@ if [ "$CONFIG_MAC" = "y" ]; then
# bool 'Macintosh (AV) onboard MACE ethernet' CONFIG_MACMACE
bool 'Macintosh (Quadra) onboard SONIC ethernet' CONFIG_MACSONIC
fi
+if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME147" = "y" ]; then
+ tristate 'MVME147 (Lance) Ethernet support' CONFIG_MVME147_NET
+fi
if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then
tristate 'MVME16x Ethernet support' CONFIG_MVME16x_NET
fi
@@ -232,9 +271,17 @@ if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'PAMsNet support' CONFIG_ATARI_PAMSNET
fi
fi
+if [ "$CONFIG_SUN3X" = "y" ]; then
+ bool 'Sun3x Lance support' CONFIG_SUNLANCE
+fi
if [ "$CONFIG_HP300" = "y" ]; then
bool 'HP on-board LANCE support' CONFIG_HPLANCE
fi
+if [ "$CONFIG_Q40" = "y" ]; then
+ if [ ! "$CONFIG_PARPORT" = "n" ]; then
+ dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT
+ fi
+fi
fi
endmenu
@@ -243,6 +290,23 @@ fi
mainmenu_option next_comment
comment 'Character devices'
+if [ "$CONFIG_Q40" = "y" ]; then
+ tristate 'Q40 Standard/generic serial support' CONFIG_SERIAL
+fi
+
+if [ "$CONFIG_SERIAL" = "y" ]; then
+ bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE
+ bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED
+fi
+
+if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
+ bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
+ bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ
+# bool ' Autodetect IRQ - do not yet enable !!' CONFIG_SERIAL_DETECT_IRQ
+ bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT
+ bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6
+fi
+
if [ "$CONFIG_VME" = "n" ]; then
define_bool CONFIG_VT y
if [ "$CONFIG_VT" = "y" ]; then
@@ -254,10 +318,17 @@ if [ "$CONFIG_ATARI" = "y" ]; then
define_bool CONFIG_NVRAM y
fi
-tristate 'Parallel printer support' CONFIG_M68K_PRINTER
-if [ "$CONFIG_ZORRO" = "y" ]; then
- dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER
-fi
+if [ "$CONFIG_PARPORT" = "n" ]; 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_M68K_PRINTER
+ fi
+else
+ dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+ if [ "$CONFIG_PRINTER" != "n" ]; then
+ bool ' Support IEEE1284 status readback' CONFIG_PRINTER_READBACK
+ fi
+fi
if [ "$CONFIG_AMIGA" = "y" ]; then
tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE
fi
@@ -280,13 +351,17 @@ 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
+ if [ "$CONFIG_AMIGA_PCMCIA" = "y" ]; then
+ tristate 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET_SERIAL
+ fi
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
+if [ "$CONFIG_PARPORT" = "n" ]; then
+ 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
+ fi
fi
if [ "$CONFIG_MAC" = "y" ]; then
bool 'Mac SCC serial support' CONFIG_MAC_SCC
@@ -294,18 +369,32 @@ fi
if [ "$CONFIG_HP300" = "y" -a "$CONFIG_DIO" = "y" ]; then
tristate 'HP DCA serial support' CONFIG_HPDCA
fi
+if [ "$CONFIG_SUN3X" = "y" ]; then
+ bool 'Sun3x builtin serial support' CONFIG_SUN3X_ZS
+ if [ "$CONFIG_SUN3X_ZS" = "y" ]; then
+ bool 'Sun keyboard support' CONFIG_SUN_KEYBOARD
+ bool 'Sun mouse support' CONFIG_SUN_MOUSE
+ define_bool CONFIG_SBUS y
+ define_bool CONFIG_SBUSCHAR y
+ define_bool CONFIG_SUN_SERIAL y
+ fi
+fi
if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o \
- "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" ]; then
+ "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" -o \
+ "$CONFIG_SUN3X" = "y" ]; then
if [ "$CONFIG_ATARI_MFPSER" = "y" -o "$CONFIG_ATARI_SCC" = "y" -o \
"$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
+ "$CONFIG_HPDCA" = "y" -o "$CONFIG_SUN3X_ZS" = "y" ]; then
bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE
fi
fi
if [ "$CONFIG_VME" = "y" ]; then
define_bool CONFIG_SERIAL_CONSOLE y
+ if [ "$CONFIG_MVME147" = "y" ]; then
+ bool 'SCC support for MVME147 serial ports' CONFIG_MVME147_SCC
+ fi
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
@@ -346,13 +435,13 @@ endmenu
source fs/Config.in
if [ "$CONFIG_VME" = "n" ]; then
+ mainmenu_option next_comment
+ comment 'Console drivers'
if [ "$CONFIG_HP300" = "y" ]; then
bool 'Frame buffer support' CONFIG_FB
else
define_bool CONFIG_FB y
fi
- mainmenu_option next_comment
- comment 'Console drivers'
source drivers/video/Config.in
endmenu
fi
diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig
index ab9152f5d..109ce19fa 100644
--- a/arch/m68k/defconfig
+++ b/arch/m68k/defconfig
@@ -78,7 +78,6 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_PACKET=y
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
diff --git a/arch/m68k/hp300/hil.c b/arch/m68k/hp300/hil.c
index 3be0d488a..d7fe1867c 100644
--- a/arch/m68k/hp300/hil.c
+++ b/arch/m68k/hp300/hil.c
@@ -223,12 +223,13 @@ static void poll_finished(void)
{
case 0x40:
{
- unsigned char scode = (poll.data[1] >> 1) | ((poll.data[1] & 1)?0x80:0);
+ int down = (poll.data[1] & 1) == 0;
+ unsigned char scode = poll.data[1] >> 1;
#if 0
- if (scode & 0x80)
- printk("[%02x]", scode & 0x7f);
+ if (down)
+ printk("[%02x]", scode);
#endif
- handle_scancode(scode);
+ handle_scancode(scode, down);
}
break;
}
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index e21e4b21c..61482c3a8 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -164,8 +164,17 @@ SYMBOL_NAME_LABEL(inthandler)
movel %sp,%sp@-
movel %d0,%sp@- | put vector # on stack
+#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD)
+ btstb #4,0xff000000 | Q40 floppy needs very special treatment ...
+ jbeq 1f
+ btstb #3,0xff000004
+ jbeq 1f
+ jbsr SYMBOL_NAME(floppy_hardint)
+ jbra 3f
+1:
+#endif
jbsr SYMBOL_NAME(process_int)| process the IRQ
- addql #8,%sp | pop parameters off stack
+3: addql #8,%sp | pop parameters off stack
SYMBOL_NAME_LABEL(ret_from_interrupt)
subql #1,SYMBOL_NAME(local_irq_count)
@@ -295,6 +304,8 @@ SYMBOL_NAME_LABEL(resume)
2: fmovemx %fp0-%fp7,%a0@(TASK_TSS+TSS_FPREG)
fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_TSS+TSS_FPCNTL)
3:
+ /* Return previous task in %d1 */
+ movel %curptr,%d1
/* switch to new task (a1 contains new task) */
movel %a1,%curptr
@@ -320,8 +331,15 @@ SYMBOL_NAME_LABEL(resume)
movec %d0,%cacr
/* switch the root pointer */
+#ifdef CPU_M68030_ONLY
+ .chip 68030
+ pmovefd %a1@(TASK_TSS+TSS_CRP),%crp
+ .chip 68k
+ pflush #0,#4
+#else
pmove %a1@(TASK_TSS+TSS_CRP),%crp
#endif
+#endif
#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
jra 2f /* skip m68040 stuff */
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 482c15f50..361b10cb6 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -23,6 +23,7 @@
** 98/04/25 Phil Blundell: added HP300 support
** 1998/08/30 David Kilzer: Added support for fbcon_font_desc structures
** for linux-2.1.115
+** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01)
**
** 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
@@ -303,6 +304,12 @@
.globl SYMBOL_NAME(availmem)
.globl SYMBOL_NAME(m68k_pgtable_cachemode)
.globl SYMBOL_NAME(m68k_supervisor_cachemode)
+#ifdef CONFIG_MVME16x
+.globl SYMBOL_NAME(mvme_bdid_ptr)
+#endif
+#ifdef CONFIG_Q40
+.globl SYMBOL_NAME(q40_mem_cptr)
+#endif
CPUTYPE_040 = 1 /* indicates an 040 */
CPUTYPE_060 = 2 /* indicates an 060 */
@@ -512,13 +519,15 @@ func_define putn,1
#endif
.endm
-
#define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab
#define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab
#define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab
+#define is_not_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jne lab
#define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab
#define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab
#define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab
+#define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab
+#define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab
#define is_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab
#define is_not_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab
@@ -552,9 +561,11 @@ ENTRY(_stext)
.long BOOTINFOV_MAGIC
.long MACH_AMIGA, AMIGA_BOOTI_VERSION
.long MACH_ATARI, ATARI_BOOTI_VERSION
+ .long MACH_MVME147, MVME147_BOOTI_VERSION
.long MACH_MVME16x, MVME16x_BOOTI_VERSION
.long MACH_BVME6000, BVME6000_BOOTI_VERSION
.long MACH_MAC, MAC_BOOTI_VERSION
+ .long MACH_Q40, Q40_BOOTI_VERSION
.long 0
1: jra SYMBOL_NAME(__start)
@@ -859,7 +870,12 @@ L(mmu_init_amiga):
/*
* 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000
*/
- mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S
+ mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S
+ /*
+ * Map the Zorro III I/O space with transparent translation
+ * for frame buffer memory etc.
+ */
+ mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE_S
jbra L(mmu_init_done)
@@ -867,7 +883,8 @@ L(mmu_init_amiga):
/*
* 030: Map the 32Meg range physical 0x0 upto logical 0x8000.0000
*/
- mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
+ mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
+ mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030
jbra L(mmu_init_done)
@@ -926,6 +943,25 @@ L(spata68040):
L(mmu_init_not_atari):
#endif
+#ifdef CONFIG_Q40
+ is_not_q40(L(notq40))
+ /*
+ * add transparent mapping for 0xff00 0000 - 0xffff ffff
+ * non-cached serialized etc..
+ * this includes master chip, DAC, RTC and ISA ports
+ * 0xfe000000-0xfeffffff is for screen and ROM
+ */
+
+ putc 'Q'
+
+ mmu_map_tt #0,#0xfe000000,#0x01000000,#_PAGE_CACHE040W
+ mmu_map_tt #1,#0xff000000,#0x01000000,#_PAGE_NOCACHE_S
+
+ jbra L(mmu_init_done)
+
+L(notq40):
+#endif
+
#ifdef CONFIG_HP300
is_not_hp300(L(nothp300))
@@ -940,6 +976,24 @@ L(nothp300):
#endif
+#ifdef CONFIG_MVME147
+
+ is_not_mvme147(L(not147))
+
+ /*
+ * On MVME147 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,
+ * so we can access on-board i/o areas.
+ */
+
+ mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE030
+
+ jbra L(mmu_init_done)
+
+L(not147):
+#endif /* CONFIG_MVME147 */
+
#ifdef CONFIG_MVME16x
is_not_mvme16x(L(not16x))
@@ -965,7 +1019,7 @@ L(nothp300):
* 0xffe00000->0xffe1ffff.
*/
- mmu_map_tt 1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
+ mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
jbra L(mmu_init_done)
@@ -985,7 +1039,7 @@ L(not16x):
* clash with User code virtual address space.
*/
- mmu_map_tt 1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
+ mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
jbra L(mmu_init_done)
@@ -1052,13 +1106,23 @@ L(mmu_init_mac):
mmu_map_eq #0x50000000,#0x02000000,%d3
mmu_map_eq #0x60000000,#0x00400000,%d3
mmu_map_eq #0x9c000000,#0x00400000,%d3
- mmu_map_tt 1,#0xf8000000,#0x08000000,%d3
+ mmu_map_tt #1,#0xf8000000,#0x08000000,%d3
jbra L(mmu_init_done)
L(mmu_init_not_mac):
#endif
+#ifdef CONFIG_SUN3X
+ is_not_sun3x(L(notsun3x))
+
+ /* setup tt1 for I/O */
+ mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S
+
+L(notsun3x):
+ jbra L(mmu_init_done)
+#endif
+
L(mmu_init_done):
putc 'G'
@@ -1214,6 +1278,14 @@ L(mmu_fixup_done):
1:
#endif
+#ifdef CONFIG_SUN3X
+ is_not_sun3x(1f)
+
+ /* enable copro */
+ oriw #0x4000,0x61000000
+1:
+#endif
+
/*
* Fixup the addresses for the kernel pointer table and availmem.
* Convert them from physical addresses to virtual addresses.
@@ -1780,7 +1852,7 @@ func_start mmu_map_tt,%d0/%d1/%a0,4
/* Extract the highest bit set
*/
bfffo ARG3{#0,#32},%d1
- cmpw #8,%d0
+ cmpw #8,%d1
jcc L(do_map)
/* And get the mask
@@ -2155,7 +2227,9 @@ func_start mmu_temp_map,%d0/%d1/%a0/%a1
/* Temporary allocate a page table and insert it into the ptr table
*/
movel %a1@,%d0
- addl #PTR_TABLE_SIZE*4,%a1@
+ /* The 512 should be PAGE_TABLE_SIZE*4, but that violates the
+ alignment restriction for pointer tables on the '0[46]0. */
+ addl #512,%a1@
orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0
movel %d0,%a0@
dputs " (new)"
@@ -2703,6 +2777,31 @@ func_start serial_init,%d0/%d1/%a0/%a1
L(serial_init_not_mac):
#endif /* CONFIG_MAC */
+#ifdef CONFIG_Q40
+ is_not_q40(2f)
+/* debug output goes into SRAM, so we don't do it unless requested
+ - check for '%LX$' signature in SRAM */
+ lea %pc@(SYMBOL_NAME(q40_mem_cptr)),%a1
+ move.l #0xff020010,%a1@ /* must be inited - also used by debug=mem */
+ move.l #0xff020000,%a1
+ cmp.b #'%',%a1@
+ bne 2f /*nodbg*/
+ addq.w #4,%a1
+ cmp.b #'L',%a1@
+ bne 2f /*nodbg*/
+ addq.w #4,%a1
+ cmp.b #'X',%a1@
+ bne 2f /*nodbg*/
+ addq.w #4,%a1
+ cmp.b #'$',%a1@
+ bne 2f /*nodbg*/
+ /* signature OK */
+ lea %pc@(L(q40_do_debug)),%a1
+ tas %a1@
+/*nodbg: q40_do_debug is 0 by default*/
+2:
+#endif
+
L(serial_init_done):
func_return serial_init
@@ -2792,6 +2891,15 @@ func_start serial_putc,%d0/%d1/%a0/%a1
4:
#endif /* CONFIG_ATARI */
+#ifdef CONFIG_MVME147
+ is_not_mvme147(2f)
+1: btst #2,M147_SCC_CTRL_A
+ jeq 1b
+ moveb %d0,M147_SCC_DATA_A
+ jbra L(serial_putc_done)
+2:
+#endif
+
#ifdef CONFIG_MVME16x
is_not_mvme16x(2f)
/*
@@ -2805,7 +2913,7 @@ func_start serial_putc,%d0/%d1/%a0/%a1
moveml %sp@+,%d0-%d7/%a2-%a6
jbra L(serial_putc_done)
2:
-#endif CONFIG_MVME162 | CONFIG_MVME167
+#endif CONFIG_MVME16x
#ifdef CONFIG_BVME6000
is_not_bvme6000(2f)
@@ -2819,6 +2927,18 @@ func_start serial_putc,%d0/%d1/%a0/%a1
2:
#endif
+#ifdef CONFIG_Q40
+ is_not_q40(2f)
+ tst.l %pc@(L(q40_do_debug)) /* only debug if requested */
+ beq 2f
+ lea %pc@(SYMBOL_NAME(q40_mem_cptr)),%a1
+ move.l %a1@,%a0
+ move.b %d0,%a0@
+ addq.l #4,%a0
+ move.l %a0,%a1@
+2:
+#endif
+
L(serial_putc_done):
func_return serial_putc
@@ -3472,6 +3592,10 @@ L(kernel_pgdir_ptr):
L(temp_mmap_mem):
.long 0
+#if defined (CONFIG_MVME147)
+M147_SCC_CTRL_A = 0xfffe3002
+M147_SCC_DATA_A = 0xfffe3003
+#endif
#if defined (CONFIG_BVME6000)
BVME_SCC_CTRL_A = 0xffb0000b
@@ -3509,3 +3633,9 @@ SYMBOL_NAME_LABEL(m68k_supervisor_cachemode)
SYMBOL_NAME_LABEL(mvme_bdid_ptr)
.long 0
#endif
+#if defined(CONFIG_Q40)
+SYMBOL_NAME_LABEL(q40_mem_cptr)
+ .long 0
+L(q40_do_debug):
+ .long 0
+#endif
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 20e39f17f..66fc41064 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -38,6 +38,10 @@
#include <asm/page.h>
#include <asm/machdep.h>
+#ifdef CONFIG_Q40
+#include <asm/q40ints.h>
+#endif
+
/* table for system interrupt handlers */
static irq_handler_t irq_list[SYS_IRQS];
@@ -177,14 +181,24 @@ void sys_free_irq(unsigned int irq, void *dev_id)
/*
* Do we need these probe functions on the m68k?
+ *
+ * ... may be usefull with ISA devices
*/
unsigned long probe_irq_on (void)
{
+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)
+ return q40_probe_irq_on();
+#endif
return 0;
}
int probe_irq_off (unsigned long irqs)
{
+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)
+ return q40_probe_irq_off(irqs);
+#endif
return 0;
}
diff --git a/arch/m68k/kernel/m68k_defs.h b/arch/m68k/kernel/m68k_defs.h
index b32e6a1c9..4926a6dad 100644
--- a/arch/m68k/kernel/m68k_defs.h
+++ b/arch/m68k/kernel/m68k_defs.h
@@ -3,6 +3,47 @@
*/
#define TS_MAGICKEY 0x5a5a5a5a
-#define TS_TSS 482
-#define TS_ESP0 502
-#define TS_FPU 506
+#define TASK_STATE 0
+#define TASK_FLAGS 4
+#define TASK_SIGPENDING 8
+#define TASK_NEEDRESCHED 20
+#define TASK_TSS 470
+#define TASK_MM 622
+#define TSS_KSP 0
+#define TSS_USP 4
+#define TSS_SR 8
+#define TSS_FS 10
+#define TSS_CRP 12
+#define TSS_ESP0 20
+#define TSS_FPREG 24
+#define TSS_FPCNTL 120
+#define TSS_FPSTATE 132
+#define PT_D0 32
+#define PT_ORIG_D0 36
+#define PT_SR 44
+#define PT_VECTOR 50
+#define IRQ_HANDLER 0
+#define IRQ_DEVID 8
+#define IRQ_NEXT 16
+#define STAT_IRQ 120
+#define BIR_TAG 0
+#define BIR_SIZE 2
+#define BIR_DATA 4
+#define FBCON_FONT_DESC_IDX 0
+#define FBCON_FONT_DESC_NAME 4
+#define FBCON_FONT_DESC_WIDTH 8
+#define FBCON_FONT_DESC_HEIGHT 12
+#define FBCON_FONT_DESC_DATA 16
+#define FBCON_FONT_DESC_PREF 20
+#define CUSTOMBASE -2132807680
+#define C_INTENAR 28
+#define C_INTREQR 30
+#define C_INTENA 154
+#define C_INTREQ 156
+#define C_SERDATR 24
+#define C_SERDAT 48
+#define C_SERPER 50
+#define CIAABASE -2134908927
+#define CIABBASE -2134913024
+#define C_PRA 0
+#define ZTWOBASE -2147483648
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 793ca6ec7..5aae5953c 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -18,6 +18,7 @@
#include <asm/checksum.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
+#include <asm/m68kserial.h>
asmlinkage long long __ashrdi3 (long long, int);
extern char m68k_debug_device[];
@@ -54,6 +55,8 @@ EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(kernel_set_cachemode);
EXPORT_SYMBOL(kernel_thread);
+EXPORT_SYMBOL(register_serial);
+EXPORT_SYMBOL(unregister_serial);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy);
@@ -69,4 +72,5 @@ EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
+EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
EXPORT_SYMBOL_NOVERS(__up_wakeup);
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index c7c3f458e..97f3bd151 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -169,15 +169,7 @@ asmlinkage int m68k_fork(struct pt_regs *regs)
asmlinkage int m68k_vfork(struct pt_regs *regs)
{
- int child;
- struct semaphore sem = MUTEX_LOCKED;
-
- child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs);
-
- if (child > 0)
- down(&sem);
-
- return child;
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs);
}
asmlinkage int m68k_clone(struct pt_regs *regs)
@@ -190,7 +182,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs)
newsp = regs->d2;
if (!newsp)
newsp = rdusp();
- return do_fork(clone_flags & ~CLONE_VFORK, newsp, regs);
+ return do_fork(clone_flags, newsp, regs);
}
int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index 5aeb2534b..e9254cfa7 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -312,6 +312,7 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
+ unsigned long flags;
int ret;
lock_kernel();
@@ -343,21 +344,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
+ (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
goto out;
child->flags |= PF_PTRACED;
- if (child->p_pptr != current) {
- unsigned long flags;
- write_lock_irqsave(&tasklist_lock, flags);
+ write_lock_irqsave(&tasklist_lock, flags);
+ if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
- write_unlock_irqrestore(&tasklist_lock, flags);
}
+ write_unlock_irqrestore(&tasklist_lock, flags);
+
send_sig(SIGSTOP, child, 1);
ret = 0;
goto out;
@@ -502,7 +504,6 @@ 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;
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index ade12c46d..39dcd9c15 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -77,10 +77,26 @@ int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
int (*mach_set_clock_mmss) (unsigned long) = NULL;
void (*mach_reset)( void );
long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
-#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
+#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD)
void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
void (*mach_floppy_eject) (void) = NULL;
#endif
+struct serial_struct;
+#ifdef CONFIG_SERIAL
+long serial_rs_init(void);
+int serial_register_serial(struct serial_struct *);
+void serial_unregister_serial(int);
+long ser_console_init(long, long );
+#endif
+#if defined(CONFIG_USERIAL)||defined(CONFIG_BVME6000_SCC)||defined(CONFIG_MVME162_SCC)||defined(CONFIG_HPDCA)||defined(CONFIG_WHIPPET_SERIAL)||defined(CONFIG_MULTIFACE_III_TTY)||defined(CONFIG_GVPIOEXT)||defined(CONFIG_AMIGA_BUILTIN_SERIAL)||defined(CONFIG_MAC_SCC)||defined(CONFIG_ATARI_MIDI)||defined(CONFIG_ATARI_SCC)||defined(CONFIG_ATARI_MFPSER)
+#define M68K_SERIAL
+#endif
+#ifdef M68K_SERIAL
+long m68k_rs_init(void);
+int m68k_register_serial(struct serial_struct *);
+void m68k_unregister_serial(int);
+long m68k_serial_console_init(long, long );
+#endif
#ifdef CONFIG_HEARTBEAT
void (*mach_heartbeat) (int) = NULL;
#endif
@@ -97,15 +113,19 @@ char *mach_sysrq_xlate = NULL;
extern int amiga_parse_bootinfo(const struct bi_record *);
extern int atari_parse_bootinfo(const struct bi_record *);
extern int mac_parse_bootinfo(const struct bi_record *);
+extern int q40_parse_bootinfo(const struct bi_record *);
extern void config_amiga(void);
extern void config_atari(void);
extern void config_mac(void);
extern void config_sun3(void);
extern void config_apollo(void);
+extern void config_mvme147(void);
extern void config_mvme16x(void);
extern void config_bvme6000(void);
extern void config_hp300(void);
+extern void config_q40(void);
+extern void config_sun3x(void);
#define MASK_256K 0xfffc0000
@@ -149,6 +169,8 @@ __initfunc(static void m68k_parse_bootinfo(const struct bi_record *record))
unknown = atari_parse_bootinfo(record);
else if (MACH_IS_MAC)
unknown = mac_parse_bootinfo(record);
+ else if (MACH_IS_Q40)
+ unknown = q40_parse_bootinfo(record);
else
unknown = 1;
}
@@ -258,6 +280,11 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
config_apollo();
break;
#endif
+#ifdef CONFIG_MVME147
+ case MACH_MVME147:
+ config_mvme147();
+ break;
+#endif
#ifdef CONFIG_MVME16x
case MACH_MVME16x:
config_mvme16x();
@@ -273,6 +300,16 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
config_hp300();
break;
#endif
+#ifdef CONFIG_Q40
+ case MACH_Q40:
+ config_q40();
+ break;
+#endif
+#ifdef CONFIG_SUN3X
+ case MACH_SUN3X:
+ config_sun3x();
+ break;
+#endif
default:
panic ("No configuration setup");
}
@@ -384,7 +421,52 @@ int get_hardware_list(char *buffer)
return(len);
}
-#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
+#if defined(CONFIG_SERIAL) || defined(M68K_SERIAL)
+int rs_init(void)
+{
+#ifdef CONFIG_SERIAL
+ if (MACH_IS_Q40)
+ return serial_rs_init();
+#endif
+#ifdef M68K_SERIAL
+ return m68k_rs_init();
+#endif
+}
+int register_serial(struct serial_struct *p)
+{
+#ifdef CONFIG_SERIAL
+ if (MACH_IS_Q40)
+ return serial_register_serial(p);
+#endif
+#ifdef M68K_SERIAL
+ return m68k_register_serial(p);
+#endif
+}
+void unregister_serial(int i)
+{
+#ifdef CONFIG_SERIAL
+ if (MACH_IS_Q40)
+ serial_unregister_serial(i);
+#endif
+#ifdef M68K_SERIAL
+ m68k_unregister_serial(i);
+#endif
+}
+#ifdef CONFIG_SERIAL_CONSOLE
+long serial_console_init(long kmem_start, long kmem_end)
+{
+#ifdef CONFIG_SERIAL
+ if (MACH_IS_Q40)
+ return ser_console_init(kmem_start, kmem_end);
+#endif
+#if defined(M68K_SERIAL) && defined(CONFIG_SERIAL_CONSOLE)
+ return m68k_serial_console_init(kmem_start, kmem_end);
+#endif
+}
+#endif
+#endif
+
+#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD)
__initfunc(void floppy_setup(char *str, int *ints))
{
if (mach_floppy_setup)
@@ -399,7 +481,7 @@ void floppy_eject(void)
#endif
/* for "kbd-reset" cmdline param */
-void __init kbd_reset_setup(char *str, int *ints)
+__initfunc(void kbd_reset_setup(char *str, int *ints))
{
}
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 107d0de7f..9b98fdb75 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -198,8 +198,7 @@ void do_settimeofday(struct timeval *tv)
xtime = *tv;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
- time_state = TIME_ERROR; /* p. 24, (a) */
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
- sti();
+ write_unlock_irq(&xtime_lock);
}
diff --git a/arch/m68k/lib/semaphore.S b/arch/m68k/lib/semaphore.S
index 8e4141149..842f83f64 100644
--- a/arch/m68k/lib/semaphore.S
+++ b/arch/m68k/lib/semaphore.S
@@ -32,6 +32,16 @@ ENTRY(__down_failed_interruptible)
movel (%sp)+,%a0
rts
+ENTRY(__down_failed_trylock)
+ movel %a0,-(%sp)
+ movel %d1,-(%sp)
+ movel %a1,-(%sp)
+ jbsr SYMBOL_NAME(__down_trylock)
+ movel (%sp)+,%a1
+ movel (%sp)+,%d1
+ movel (%sp)+,%a0
+ rts
+
ENTRY(__up_wakeup)
moveml %a0/%d0/%d1,-(%sp)
movel %a1,-(%sp)
diff --git a/arch/m68k/mac/mackeyb.c b/arch/m68k/mac/mackeyb.c
index 5a6ae7c75..a128a6314 100644
--- a/arch/m68k/mac/mackeyb.c
+++ b/arch/m68k/mac/mackeyb.c
@@ -60,7 +60,7 @@ static void input_keycode(int, int);
extern struct kbd_struct kbd_table[];
extern void adb_bus_init(void);
-extern void handle_scancode(unsigned char);
+extern void handle_scancode(unsigned char, int);
extern void put_queue(int);
/* keyb */
@@ -387,7 +387,7 @@ input_keycode(int keycode, int repeat)
*/
switch (keycode) {
case 0x39:
- handle_scancode(keycode); /* down */
+ handle_scancode(keycode, 1); /* down */
up_flag = 0x80; /* see below ... */
mark_bh(KEYBOARD_BH);
break;
@@ -397,7 +397,7 @@ input_keycode(int keycode, int repeat)
}
}
- handle_scancode(keycode + up_flag);
+ handle_scancode(keycode, !up_flag);
}
static void
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index 8e520702f..9a41dc279 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -123,7 +123,7 @@ void show_mem(void)
unsigned long mm_cachebits = 0;
#endif
-static pte_t *__init kernel_page_table(unsigned long *memavailp)
+__initfunc(static pte_t * kernel_page_table(unsigned long *memavailp))
{
pte_t *ptablep;
@@ -140,15 +140,19 @@ static pte_t *__init kernel_page_table(unsigned long *memavailp)
static pmd_t *last_pgtable __initdata = NULL;
-static pmd_t *__init kernel_ptr_table(unsigned long *memavailp)
+__initfunc(static pmd_t * kernel_ptr_table(unsigned long *memavailp))
{
if (!last_pgtable) {
unsigned long pmd, last;
int i;
+ /* Find the last ptr table that was used in head.S and
+ * reuse the remaining space in that page for further
+ * ptr tables.
+ */
last = (unsigned long)kernel_pg_dir;
for (i = 0; i < PTRS_PER_PGD; i++) {
- if (!pgd_val(kernel_pg_dir[i]))
+ if (!pgd_present(kernel_pg_dir[i]))
continue;
pmd = pgd_page(kernel_pg_dir[i]);
if (pmd > last)
@@ -175,8 +179,8 @@ static pmd_t *__init kernel_ptr_table(unsigned long *memavailp)
return last_pgtable;
}
-static unsigned long __init
-map_chunk (unsigned long addr, long size, unsigned long *memavailp)
+__initfunc(static unsigned long
+map_chunk (unsigned long addr, long size, unsigned long *memavailp))
{
#define PTRTREESIZE (256*1024)
#define ROOTTREESIZE (32*1024*1024)
@@ -282,8 +286,8 @@ extern char __init_begin, __init_end;
* paging_init() continues the virtual memory environment setup which
* was begun by the code in arch/head.S.
*/
-unsigned long __init paging_init(unsigned long start_mem,
- unsigned long end_mem)
+__initfunc(unsigned long paging_init(unsigned long start_mem,
+ unsigned long end_mem))
{
int chunk;
unsigned long mem_avail = 0;
@@ -392,7 +396,7 @@ unsigned long __init paging_init(unsigned long start_mem,
return PAGE_ALIGN(free_area_init(start_mem, end_mem));
}
-void __init mem_init(unsigned long start_mem, unsigned long end_mem)
+__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
{
int codepages = 0;
int datapages = 0;
@@ -443,7 +447,7 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem)
/* insert pointer tables allocated so far into the tablelist */
init_pointer_table((unsigned long)kernel_pg_dir);
for (i = 0; i < PTRS_PER_PGD; i++) {
- if (pgd_val(kernel_pg_dir[i]))
+ if (pgd_present(kernel_pg_dir[i]))
init_pointer_table(pgd_page(kernel_pg_dir[i]));
}
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index d2cd29011..3fefe4e03 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -116,6 +116,14 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
if (!size || size > physaddr + size)
return NULL;
+#ifdef CONFIG_AMIGA
+ if (MACH_IS_AMIGA) {
+ if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
+ && (cacheflag == IOMAP_NOCACHE_SER))
+ return (void *)physaddr;
+ }
+#endif
+
#ifdef DEBUG
printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
#endif
@@ -174,7 +182,7 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
}
}
- while (size > 0) {
+ while ((long)size > 0) {
#ifdef DEBUG
if (!(virtaddr & (PTRTREESIZE-1)))
printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
@@ -187,7 +195,7 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
}
if (CPU_IS_020_OR_030) {
- pmd_dir->pmd[(virtaddr/PTRTREESIZE)&-16] = physaddr;
+ pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
physaddr += PTRTREESIZE;
virtaddr += PTRTREESIZE;
size -= PTRTREESIZE;
@@ -217,7 +225,14 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
*/
void iounmap(void *addr)
{
+#ifdef CONFIG_AMIGA
+ if ((!MACH_IS_AMIGA) ||
+ (((unsigned long)addr < 0x40000000) ||
+ ((unsigned long)addr > 0x60000000)))
+ free_io_area(addr);
+#else
free_io_area(addr);
+#endif
}
/*
@@ -232,7 +247,7 @@ void __iounmap(void *addr, unsigned long size)
pmd_t *pmd_dir;
pte_t *pte_dir;
- while (size > 0) {
+ while ((long)size > 0) {
pgd_dir = pgd_offset_k(virtaddr);
if (pgd_bad(*pgd_dir)) {
printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
@@ -242,7 +257,7 @@ void __iounmap(void *addr, unsigned long size)
pmd_dir = pmd_offset(pgd_dir, virtaddr);
if (CPU_IS_020_OR_030) {
- int pmd_off = (virtaddr/PTRTREESIZE) & -16;
+ int pmd_off = (virtaddr/PTRTREESIZE) & 15;
if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
pmd_dir->pmd[pmd_off] = 0;
@@ -308,7 +323,7 @@ void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
}
}
- while (size > 0) {
+ while ((long)size > 0) {
pgd_dir = pgd_offset_k(virtaddr);
if (pgd_bad(*pgd_dir)) {
printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
@@ -318,7 +333,7 @@ void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
pmd_dir = pmd_offset(pgd_dir, virtaddr);
if (CPU_IS_020_OR_030) {
- int pmd_off = (virtaddr/PTRTREESIZE) & -16;
+ int pmd_off = (virtaddr/PTRTREESIZE) & 15;
if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
index a97578ec2..a6d496571 100644
--- a/arch/m68k/mm/memory.c
+++ b/arch/m68k/mm/memory.c
@@ -11,6 +11,7 @@
#include <linux/types.h>
#include <linux/malloc.h>
#include <linux/init.h>
+#include <linux/pagemap.h>
#include <asm/setup.h>
#include <asm/segment.h>
@@ -93,12 +94,11 @@ 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))
-void __init init_pointer_table(unsigned long ptable)
+__initfunc(void init_pointer_table(unsigned long ptable))
{
ptable_desc *dp;
unsigned long page = ptable & PAGE_MASK;
@@ -166,7 +166,7 @@ pmd_t *get_pointer_table (void)
(dp->next = last->next)->prev = dp;
(dp->prev = last)->next = dp;
}
- return (pmd_t *) (PD_PAGE(dp) + off);
+ return (pmd_t *) (page_address(dp) + off);
}
int free_pointer_table (pmd_t *ptable)
@@ -215,8 +215,8 @@ static unsigned long transp_transl_matches( unsigned long regval,
/* function code match? */
base = (regval >> 4) & 7;
mask = ~(regval & 7);
- if ((SUPER_DATA & mask) != (base & mask))
- return( 0 );
+ if (((SUPER_DATA ^ base) & mask) != 0)
+ return 0;
}
else {
/* must not be user-only */
@@ -226,8 +226,8 @@ static unsigned long transp_transl_matches( unsigned long regval,
/* address match? */
base = regval & 0xff000000;
- mask = ~((regval << 8) & 0xff000000);
- return( (vaddr & mask) == (base & mask) );
+ mask = ~(regval << 8) & 0xff000000;
+ return ((vaddr ^ base) & mask) == 0;
}
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
diff --git a/arch/m68k/mvme147/147ints.c b/arch/m68k/mvme147/147ints.c
new file mode 100644
index 000000000..3121ad94f
--- /dev/null
+++ b/arch/m68k/mvme147/147ints.c
@@ -0,0 +1,142 @@
+/*
+ * arch/m68k/mvme147/147ints.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 mvme147_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 mvme147_init_IRQ (void)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ * This function is called during kernel startup to initialize
+ * the mvme147 IRQ handling routines.
+ */
+
+void mvme147_init_IRQ (void)
+{
+ int i;
+
+ for (i = 0; i < 256; i++) {
+ irq_tab[i].handler = mvme147_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 mvme147_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 (!(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 mvme147_free_irq(unsigned int irq, void *dev_id)
+{
+ if (irq > 255) {
+ printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+ 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 = mvme147_defhand;
+ irq_tab[irq].flags = IRQ_FLG_STD;
+ irq_tab[irq].dev_id = NULL;
+ irq_tab[irq].devname = NULL;
+}
+
+void mvme147_process_int (unsigned long vec, struct pt_regs *fp)
+{
+ if (vec > 255)
+ printk ("mvme147_process_int: Illegal vector %ld\n", vec);
+ else
+ {
+ irq_tab[vec].count++;
+ irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
+ }
+}
+
+int mvme147_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 mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp)
+{
+ printk ("Unknown interrupt 0x%02x\n", irq);
+}
+
+void mvme147_enable_irq (unsigned int irq)
+{
+}
+
+
+void mvme147_disable_irq (unsigned int irq)
+{
+}
+
diff --git a/arch/m68k/mvme147/Makefile b/arch/m68k/mvme147/Makefile
new file mode 100644
index 000000000..c0f064118
--- /dev/null
+++ b/arch/m68k/mvme147/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for Linux arch/m68k/mvme147 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).
+#
+
+O_TARGET := mvme147.o
+O_OBJS := config.o 147ints.o
+
+
+include $(TOPDIR)/Rules.make
+
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
new file mode 100644
index 000000000..639d5f640
--- /dev/null
+++ b/arch/m68k/mvme147/config.c
@@ -0,0 +1,240 @@
+/*
+ * arch/m68k/mvme147/config.c
+ *
+ * Copyright (C) 1996 Dave Frascone [chaos@mindspring.com]
+ * Cloned from Richard Hirst [richard@sleepie.demon.co.uk]
+ *
+ * Based on:
+ *
+ * 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 <linux/config.h>
+#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/mvme147hw.h>
+
+
+extern void mvme147_process_int (int level, struct pt_regs *regs);
+extern void mvme147_init_IRQ (void);
+extern void mvme147_free_irq (unsigned int, void *);
+extern int mvme147_get_irq_list (char *);
+extern void mvme147_enable_irq (unsigned int);
+extern void mvme147_disable_irq (unsigned int);
+static void mvme147_get_model(char *model);
+static int mvme147_get_hardware_list(char *buffer);
+extern int mvme147_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+extern void mvme147_sched_init(void (*handler)(int, void *, struct pt_regs *));
+extern int mvme147_keyb_init(void);
+extern int mvme147_kbdrate (struct kbd_repeat *);
+extern unsigned long mvme147_gettimeoffset (void);
+extern void mvme147_gettod (int *year, int *mon, int *day, int *hour,
+ int *min, int *sec);
+extern int mvme147_hwclk (int, struct hwclk_time *);
+extern int mvme147_set_clock_mmss (unsigned long);
+extern void mvme147_check_partition (struct gendisk *hd, unsigned int dev);
+extern void mvme147_reset (void);
+extern void mvme147_waitbut(void);
+
+
+static int bcd2int (unsigned char b);
+
+/* Save tick handler routine pointer, will point to do_timer() in
+ * kernel/sched.c, called via mvme147_process_int() */
+
+void (*tick_handler)(int, void *, struct pt_regs *);
+
+
+int mvme147_kbdrate (struct kbd_repeat *k)
+{
+ return 0;
+}
+
+void mvme147_reset()
+{
+ printk ("\r\n\nCalled mvme147_reset\r\n");
+ m147_pcc->watchdog = 0x0a; /* Clear timer */
+ m147_pcc->watchdog = 0xa5; /* Enable watchdog - 100ms to reset */
+ while (1)
+ ;
+}
+
+static void mvme147_get_model(char *model)
+{
+ sprintf(model, "Motorola MVME147");
+}
+
+
+static int mvme147_get_hardware_list(char *buffer)
+{
+ *buffer = '\0';
+
+ return 0;
+}
+
+
+__initfunc(void config_mvme147(void))
+{
+ mach_sched_init = mvme147_sched_init;
+ mach_keyb_init = mvme147_keyb_init;
+ mach_kbdrate = mvme147_kbdrate;
+ mach_init_IRQ = mvme147_init_IRQ;
+ mach_gettimeoffset = mvme147_gettimeoffset;
+ mach_gettod = mvme147_gettod;
+ mach_hwclk = mvme147_hwclk;
+ mach_set_clock_mmss = mvme147_set_clock_mmss;
+ mach_reset = mvme147_reset;
+ mach_free_irq = mvme147_free_irq;
+ mach_process_int = mvme147_process_int;
+ mach_get_irq_list = mvme147_get_irq_list;
+ mach_request_irq = mvme147_request_irq;
+ enable_irq = mvme147_enable_irq;
+ disable_irq = mvme147_disable_irq;
+ mach_get_model = mvme147_get_model;
+ mach_get_hardware_list = mvme147_get_hardware_list;
+}
+
+
+/* Using pcc tick timer 1 */
+
+static void mvme147_timer_int (int irq, void *dev_id, struct pt_regs *fp)
+{
+ m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
+ m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
+ tick_handler(irq, dev_id, fp);
+}
+
+
+void mvme147_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+{
+ tick_handler = timer_routine;
+ request_irq (PCC_IRQ_TIMER1, mvme147_timer_int,
+ IRQ_FLG_REPLACE, "timer 1", NULL);
+
+ /* Init the clock with a value */
+ /* our clock goes off every 6.25us */
+ m147_pcc->t1_preload = PCC_TIMER_PRELOAD;
+ m147_pcc->t1_cntrl = 0x0; /* clear timer */
+ m147_pcc->t1_cntrl = 0x3; /* start timer */
+ m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; /* clear pending ints */
+ m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
+}
+
+/* This is always executed with interrupts disabled. */
+/* XXX There are race hazards in this code XXX */
+unsigned long mvme147_gettimeoffset (void)
+{
+ volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012;
+ unsigned short n;
+
+ n = *cp;
+ while (n != *cp)
+ n = *cp;
+
+ n -= PCC_TIMER_PRELOAD;
+ return (unsigned long)n * 25 / 4;
+}
+
+extern void mvme147_gettod (int *year, int *mon, int *day, int *hour,
+ int *min, int *sec)
+{
+ m147_rtc->ctrl = RTC_READ;
+ *year = bcd2int (m147_rtc->bcd_year);
+ *mon = bcd2int (m147_rtc->bcd_mth);
+ *day = bcd2int (m147_rtc->bcd_dom);
+ *hour = bcd2int (m147_rtc->bcd_hr);
+ *min = bcd2int (m147_rtc->bcd_min);
+ *sec = bcd2int (m147_rtc->bcd_sec);
+ m147_rtc->ctrl = 0;
+}
+
+static int bcd2int (unsigned char b)
+{
+ return ((b>>4)*10 + (b&15));
+}
+
+int mvme147_hwclk(int op, struct hwclk_time *t)
+{
+ return 0;
+}
+
+int mvme147_set_clock_mmss (unsigned long nowtime)
+{
+ return 0;
+}
+
+int mvme147_keyb_init (void)
+{
+ return 0;
+}
+
+/*------------------- Serial console stuff ------------------------*/
+
+void m147_scc_write(struct console *co, const char *str, unsigned cnt);
+
+
+void mvme147_init_console_port (struct console *co, int cflag)
+{
+ co->write = m147_scc_write;
+}
+
+
+static void scc_delay (void)
+{
+ int n;
+ volatile int trash;
+
+ for (n = 0; n < 20; n++)
+ trash = n;
+}
+
+static void scc_write (char ch)
+{
+ volatile char *p = (volatile char *)M147_SCC_A_ADDR;
+
+ do {
+ scc_delay();
+ }
+ while (!(*p & 4));
+ scc_delay();
+ *p = 8;
+ scc_delay();
+ *p = ch;
+}
+
+
+void m147_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/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index 838c3bbac..db7eb3137 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -335,10 +335,10 @@ void mvme16x_init_console_port (struct console *co, int cflag)
static void scc_delay (void)
{
int n;
- char i;
+ volatile int trash;
for (n = 0; n < 20; n++)
- i = *(volatile char *)0;
+ trash = n;
}
static void scc_write (char ch)
diff --git a/arch/m68k/q40/Makefile b/arch/m68k/q40/Makefile
new file mode 100644
index 000000000..90858884f
--- /dev/null
+++ b/arch/m68k/q40/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for Linux arch/m68k/q40 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 := q40.o
+O_OBJS := config.o q40ints.o
+
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/q40/README b/arch/m68k/q40/README
new file mode 100644
index 000000000..5433796cb
--- /dev/null
+++ b/arch/m68k/q40/README
@@ -0,0 +1,121 @@
+Linux for the Q40
+=================
+
+You may try http://www.geocities.com/SiliconValley/Bay/2602/ for
+some up to date information. Booter and other tools will be also
+available from this place and ftp.uni-erlangen.de/linux/680x0/q40/
+and mirrors.
+
+Hints to documentation usually refer to the linux source tree in
+/usr/src/linux unless URL given.
+
+It seems IRQ unmasking can't be safely done on a Q40. Autoprobing is
+not yet implemented - do not try it! (See below)
+
+For a list of kernel commandline options read the documentation for the
+particular device drivers.
+
+The floppy imposes a very high interrupt load on the CPU, approx 30K/s.
+When something blocks interrupts (HD) it will loose some of them, so far
+this is not known to have caused any data loss. On hihgly loaded systems
+it can make the floppy very slow. Other Q40 OS' simply poll the floppy
+for this reason - something that can't be done in Linux.
+Only possible cure is getting a 82072 contoler with fifo instead of
+the 8272A
+
+drivers used by the Q40, appart from the very obvious (console etc.):
+ drivers/char/q40_keyb.c # use PC keymaps for national keyboards
+ serial.c # normal PC driver - any speed
+ lp.c # printer driver
+ char/joystick/* # most of this should work
+ block/q40ide.c # startup for ide
+ ide* # see Documentation/ide.txt
+ floppy.c # normal PC driver, DMA emu in asm/floppy.h
+ # and arch/m68k/kernel/entry.S
+ # see drivers/block/README.fd
+ video/q40fb.c
+ misc/parport_pc.c
+
+Various other PC drivers can be enabled simply by adding them to
+arch/m68k/config.in, especially 8 bit devices should be without any
+problems. For cards using 16bit io/mem more care is required, like
+checking byteorder issues, hacking memcpy_*_io etc.
+
+
+Debugging
+=========
+
+Upon startup the kernel will usually output "ABCQGHIJ" into the SRAM,
+preceded by the booter signature. This is a trace just in case something
+went wrong during earliest setup stages.
+*Changed* to preserve SRAM contents by default, this is only done when
+requested - SRAM must start with '%LX$' signature to do this. '-d' option
+to 'lxx' loader enables this.
+
+SRAM can also be used as additional console device, use debug=mem.
+This will save kernel startup msgs into SRAM, the screen will display
+only the penguin - and shell prompt if it gets that far..
+
+Serial console works and can also be used for debugging, provided serial
+initialisation works.
+
+Most problems seem to be caused by fawlty or badly configured io-cards or
+harddrives anyway..there are so many things that can go wrong here.
+Make sure to configure the parallel port as SPP for first testing..the
+Q40 may have trouble with parallel interrupts.
+
+
+Q40 Hardware Description
+========================
+
+This is just an overview, see asm-m68k/* for details ask if you have any
+questions.
+
+The Q40 consists of a 68040@40 MHz, 1MB video RAM, up to 32MB RAM, AT-style
+keyboard interface, 1 Programmable LED, 2 8bit DACs and up to 1MB ROM, 1MB
+shadow ROM.
+
+Most interfacing like floppy, hd, serial, parallel ports is done via ISA
+slots. The ISA io and mem range is mapped (sparse&byteswapped!) into separate
+regions of the memory.
+The main interrupt register IIRQ_REG will indicate whether an IRQ was internal
+or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs.
+
+The Q40 custom chip is programmable to provide 2 periodic timers:
+ - 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!!
+ - 10 or 20 KHz - level 4 (and possibly 6 - hardware decoding..)
+
+Linux uses the 200 Hz interrupt for timer and beep by default.
+
+
+Interrupts
+==========
+
+q40 master chip handles only level triggered interrupts :-((
+further limitation is no disabling etc. Unless someone finds
+some ingenious clue this means autoprobing will never work.
+Parallel port interrupts cause most trouble..
+
+IRQ sharing is not yet implemented.
+
+
+Keyboard
+========
+
+q40 receives AT make/break codes from the keyboard, these are translated to
+the PC scancodes x86 Linux uses. So by theory every national keyboard should
+work just by loading the apropriate x86 keytable - see any national-HOWTO.
+
+Unfortunately the AT->PC translation isn't quite trivial and even worse, my
+documentation of it is absolutely minimal - thus some exotic keys may not
+behave exactly as expected.
+
+There is still hope that it can be fixed completely though. If you encounter
+problems, email me idealy this:
+ - exact keypress/release sequence
+ - 'showkey -s' run on q40, non-X session
+ - 'showkey -s' run on a PC, non-X session
+ - AT codes as displayed by the q40 debuging ROM
+btw if the showkey output from PC and Q40 doesn't differ then you have some
+classic configuration problem - don't send me anything in this case
+
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
new file mode 100644
index 000000000..e3c35c60c
--- /dev/null
+++ b/arch/m68k/q40/config.c
@@ -0,0 +1,425 @@
+/*
+ * arch/m68k/q40/config.c
+ *
+ * originally based on:
+ *
+ * linux/bvme/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/bootinfo.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/q40_master.h>
+#include <asm/keyboard.h>
+
+extern void fd_floppy_eject(void);
+extern void fd_floppy_setup(char *str, int *ints);
+
+extern void q40_process_int (int level, struct pt_regs *regs);
+extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */
+extern void q40_init_IRQ (void);
+extern void q40_free_irq (unsigned int, void *);
+extern int q40_get_irq_list (char *);
+extern void q40_enable_irq (unsigned int);
+extern void q40_disable_irq (unsigned int);
+static void q40_get_model(char *model);
+static int q40_get_hardware_list(char *buffer);
+extern int q40_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+extern void q40_sched_init(void (*handler)(int, void *, struct pt_regs *));
+extern int q40_keyb_init(void);
+extern int q40_kbdrate (struct kbd_repeat *);
+extern unsigned long q40_gettimeoffset (void);
+extern void q40_gettod (int *year, int *mon, int *day, int *hour,
+ int *min, int *sec);
+extern int q40_hwclk (int, struct hwclk_time *);
+extern int q40_set_clock_mmss (unsigned long);
+extern void q40_reset (void);
+extern void q40_waitbut(void);
+void q40_set_vectors (void);
+extern void (*kd_mksound)(unsigned int, unsigned int);
+void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ );
+
+extern char *saved_command_line;
+extern char m68k_debug_device[];
+static void q40_mem_console_write(struct console *co, const char *b,
+ unsigned int count);
+
+static int ql_ticks=0;
+static int sound_ticks=0;
+
+static unsigned char bcd2bin (unsigned char b);
+static unsigned char bin2bcd (unsigned char b);
+
+static int q40_wait_key(struct console *co){return 0;}
+static struct console q40_console_driver = {
+ "debug",
+ NULL, /* write */
+ NULL, /* read */
+ NULL, /* device */
+ q40_wait_key, /* wait_key */
+ NULL, /* unblank */
+ NULL, /* setup */
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
+};
+
+
+/* Save tick handler routine pointer, will point to do_timer() in
+ * kernel/sched.c */
+
+/* static void (*tick_handler)(int, void *, struct pt_regs *); */
+
+
+/* early debugging function:*/
+extern char *q40_mem_cptr; /*=(char *)0xff020000;*/
+static int _cpleft;
+
+static void q40_mem_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ char *p=(char *)s;
+
+ if (count<_cpleft)
+ while (count-- >0){
+ *q40_mem_cptr=*p++;
+ q40_mem_cptr+=4;
+ _cpleft--;
+ }
+}
+#if 0
+void printq40(char *str)
+{
+ int l=strlen(str);
+ char *p=q40_mem_cptr;
+
+ while (l-- >0 && _cpleft-- >0)
+ {
+ *p=*str++;
+ p+=4;
+ }
+ q40_mem_cptr=p;
+}
+#endif
+
+#if 0
+int q40_kbdrate (struct kbd_repeat *k)
+{
+ return 0;
+}
+#endif
+
+void q40_reset()
+{
+
+ printk ("\n\n*******************************************\n"
+ "Called q40_reset : press the RESET button!! \n");
+ printk( "*******************************************\n");
+
+ while(1)
+ ;
+}
+
+static void q40_get_model(char *model)
+{
+ sprintf(model, "Q40");
+}
+
+
+/* No hardware options on Q40? */
+
+static int q40_get_hardware_list(char *buffer)
+{
+ *buffer = '\0';
+ return 0;
+}
+
+
+__initfunc(void config_q40(void))
+{
+ mach_sched_init = q40_sched_init; /* ok */
+ /*mach_kbdrate = q40_kbdrate;*/ /* unneeded ?*/
+ mach_keyb_init = q40_keyb_init; /* OK */
+ mach_init_IRQ = q40_init_IRQ;
+ mach_gettimeoffset = q40_gettimeoffset;
+ mach_gettod = q40_gettod;
+ mach_hwclk = q40_hwclk;
+ mach_set_clock_mmss = q40_set_clock_mmss;
+/* mach_mksound = q40_mksound; */
+ mach_reset = q40_reset; /* use reset button instead !*/
+ mach_free_irq = q40_free_irq;
+ mach_process_int = q40_process_int;
+ mach_get_irq_list = q40_get_irq_list;
+ mach_request_irq = q40_request_irq;
+ enable_irq = q40_enable_irq;
+ disable_irq = q40_disable_irq;
+ mach_default_handler = &q40_sys_default_handler;
+ mach_get_model = q40_get_model; /* no use..*/
+ mach_get_hardware_list = q40_get_hardware_list; /* no use */
+ kd_mksound = q40_mksound;
+ /*mach_kbd_leds = q40kbd_leds;*/
+#ifdef CONFIG_MAGIC_SYSRQ
+ mach_sysrq_key = 0x54;
+#endif
+ conswitchp = &dummy_con;
+#ifdef CONFIG_BLK_DEV_FD
+ mach_floppy_setup = fd_floppy_setup;
+ mach_floppy_eject = fd_floppy_eject;
+ /**/
+#endif
+
+ mach_max_dma_address = 0; /* no DMA at all */
+
+
+/* userfull for early debuging stages writes kernel messages into SRAM */
+
+ if (!strncmp( m68k_debug_device,"mem",3 ))
+ {
+ /*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
+ _cpleft=2000-((long)q40_mem_cptr-0xff020000)/4;
+ q40_console_driver.write = q40_mem_console_write;
+ register_console(&q40_console_driver);
+ }
+}
+
+
+int q40_parse_bootinfo(const struct bi_record *rec)
+{
+ return 1; /* unknown */
+}
+
+#define DAC_LEFT ((unsigned char *)0xff008000)
+#define DAC_RIGHT ((unsigned char *)0xff008004)
+void q40_mksound(unsigned int hz, unsigned int ticks)
+{
+ /* for now ignore hz, except that hz==0 switches off sound */
+ /* simply alternate the ampl 0-255-0-.. at 200Hz */
+ if (hz==0)
+ {
+ if (sound_ticks)
+ sound_ticks=1; /* atomic - no irq spinlock used */
+
+ *DAC_LEFT=0;
+ *DAC_RIGHT=0;
+
+ return;
+ }
+ /* sound itself is done in q40_timer_int */
+ if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */
+ sound_ticks=ticks<<1;
+}
+
+static void (*q40_timer_routine)(int, void *, struct pt_regs *);
+
+static void q40_timer_int (int irq, void *dev_id, struct pt_regs *fp)
+{
+#if (HZ==10000)
+ master_outb(-1,SAMPLE_CLEAR_REG);
+#else /* must be 50 or 100 */
+ master_outb(-1,FRAME_CLEAR_REG);
+#endif
+
+#if (HZ==100)
+ ql_ticks = ql_ticks ? 0 : 1;
+ if (sound_ticks)
+ {
+ unsigned char sval=(sound_ticks & 1) ? 0 : 255;
+ sound_ticks--;
+ *DAC_LEFT=sval;
+ *DAC_RIGHT=sval;
+ }
+ if (ql_ticks) return;
+#endif
+ q40_timer_routine(irq, dev_id, fp);
+}
+
+
+void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+{
+ int timer_irq;
+
+ q40_timer_routine = timer_routine;
+
+#if (HZ==10000)
+ timer_irq=Q40_IRQ_TIMER;
+#else
+ timer_irq=Q40_IRQ_FRAME;
+#endif
+
+ /*printk("registering sched/timer IRQ %d\n", timer_irq);*/
+
+ if (request_irq(timer_irq, q40_timer_int, 0,
+ "timer", q40_timer_int))
+ panic ("Couldn't register timer int");
+
+#if (HZ==10000)
+ master_outb(SAMPLE_LOW,SAMPLE_RATE_REG);
+ master_outb(-1,SAMPLE_CLEAR_REG);
+ master_outb(1,SAMPLE_ENABLE_REG);
+#else
+ master_outb(-1,FRAME_CLEAR_REG); /* not necessary ? */
+#if (HZ==100)
+ master_outb( 1,FRAME_RATE_REG);
+#endif
+#endif
+}
+
+
+unsigned long q40_gettimeoffset (void)
+{
+#if (HZ==100)
+ return 5000*(ql_ticks!=0);
+#else
+ return 0;
+#endif
+}
+
+extern void q40_gettod (int *year, int *mon, int *day, int *hour,
+ int *min, int *sec)
+{
+ RTC_CTRL |= RTC_READ;
+ *year = bcd2bin (RTC_YEAR);
+ *mon = bcd2bin (RTC_MNTH)-1;
+ *day = bcd2bin (RTC_DATE);
+ *hour = bcd2bin (RTC_HOUR);
+ *min = bcd2bin (RTC_MINS);
+ *sec = bcd2bin (RTC_SECS);
+ RTC_CTRL &= ~(RTC_READ);
+
+}
+
+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 q40_hwclk(int op, struct hwclk_time *t)
+{
+ if (op)
+ { /* Write.... */
+ RTC_CTRL |= RTC_WRITE;
+
+ RTC_SECS = bin2bcd(t->sec);
+ RTC_MINS = bin2bcd(t->min);
+ RTC_HOUR = bin2bcd(t->hour);
+ RTC_DATE = bin2bcd(t->day);
+ RTC_MNTH = bin2bcd(t->mon + 1);
+ RTC_YEAR = bin2bcd(t->year%100);
+ if (t->wday >= 0)
+ RTC_DOW = bin2bcd(t->wday+1);
+
+ RTC_CTRL &= ~(RTC_WRITE);
+ }
+ else
+ { /* Read.... */
+ RTC_CTRL |= RTC_READ;
+
+ t->year = bcd2bin (RTC_YEAR);
+ t->mon = bcd2bin (RTC_MNTH)-1;
+ t->day = bcd2bin (RTC_DATE);
+ t->hour = bcd2bin (RTC_HOUR);
+ t->min = bcd2bin (RTC_MINS);
+ t->sec = bcd2bin (RTC_SECS);
+
+ RTC_CTRL &= ~(RTC_READ);
+
+ if (t->year < 70)
+ t->year += 100;
+ t->wday = bcd2bin(RTC_DOW)-1;
+
+ }
+
+ 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 q40_set_clock_mmss (unsigned long nowtime)
+{
+ int retval = 0;
+ short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
+
+ int rtc_minutes;
+
+
+ rtc_minutes = bcd2bin (RTC_MINS);
+
+ if ((rtc_minutes < real_minutes
+ ? real_minutes - rtc_minutes
+ : rtc_minutes - real_minutes) < 30)
+ {
+ RTC_CTRL |= RTC_WRITE;
+ RTC_MINS = bin2bcd(real_minutes);
+ RTC_SECS = bin2bcd(real_seconds);
+ RTC_CTRL &= ~(RTC_WRITE);
+ }
+ else
+ retval = -1;
+
+
+ return retval;
+}
+
+extern void q40kbd_init_hw(void);
+
+int q40_keyb_init (void)
+{
+ q40kbd_init_hw();
+ return 0;
+}
+
+#if 0
+/* dummy to cause */
+void q40_slow_io()
+{
+ return;
+}
+#endif
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
new file mode 100644
index 000000000..e9b5a5b1f
--- /dev/null
+++ b/arch/m68k/q40/q40ints.c
@@ -0,0 +1,347 @@
+/*
+ * arch/m68k/q40/q40ints.c
+ *
+ * Copyright (C) 1999 Richard Zidlicky
+ *
+ * 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.
+ *
+ * losely based on bvme6000ints.c
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+
+#include <asm/q40_master.h>
+#include <asm/q40ints.h>
+
+/*
+ * Q40 IRQs are defined as follows:
+ * 3,4,5,6,7,10,11,14,15 : ISA dev IRQs
+ * 16-31: reserved
+ * 32 : keyboard int
+ * 33 : frame int (50 Hz periodic timer)
+ * 34 : sample int (10/20 KHz periodic timer)
+ *
+*/
+
+extern int ints_inited;
+
+
+void q40_irq2_handler (int, void *, struct pt_regs *fp);
+
+
+extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */
+
+static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp);
+static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs);
+
+/*
+ * This should ideally be 4 elements only, for speed.
+ */
+
+#define DEVNAME_SIZE 24
+
+static struct {
+ void (*handler)(int, void *, struct pt_regs *);
+ unsigned long flags;
+ void *dev_id;
+ char devname[DEVNAME_SIZE];
+ unsigned count;
+} irq_tab[Q40_IRQ_MAX+1];
+
+/*
+ * void q40_init_IRQ (void)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ * This function is called during kernel startup to initialize
+ * the q40 IRQ handling routines.
+ */
+
+void q40_init_IRQ (void)
+{
+ int i;
+
+ for (i = 0; i <= Q40_IRQ_MAX; i++) {
+ irq_tab[i].handler = q40_defhand;
+ irq_tab[i].flags = IRQ_FLG_STD;
+ irq_tab[i].dev_id = NULL;
+ irq_tab[i].devname[0] = 0;
+ irq_tab[i].count = 0;
+ }
+
+ /* setup handler for ISA ints */
+ sys_request_irq(IRQ2,q40_irq2_handler, IRQ_FLG_LOCK, "q40 ISA and master chip", NULL);
+
+ /* now enable some ints.. */
+
+#if 0 /* has been abandoned */
+ master_outb(1,SER_ENABLE_REG);
+#endif
+ master_outb(1,EXT_ENABLE_REG);
+
+ /* would be spurious ints by now, q40kbd_init_hw() does that */
+ master_outb(0,KEY_IRQ_ENABLE_REG);
+}
+
+int q40_request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
+{
+ /*printk("q40_request_irq %d, %s\n",irq,devname);*/
+
+ if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
+ printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
+ return -ENXIO;
+ }
+
+ /* test for ISA ints not implemented by HW */
+ if (irq<15)
+ {
+ switch (irq){
+ case 1: case 2: case 8: case 9:
+ case 12: case 13:
+ printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname);
+ return -ENXIO;
+ default:
+ }
+ }
+
+ if (irq<Q40_IRQ_TIMER)
+ {
+ if (irq==11) {
+ printk("warning IRQ 10 and 11 not distinguishable\n");
+ irq=10;
+ }
+ 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;
+ }
+ }
+ /*printk("IRQ %d set to handler %p\n",irq,handler);*/
+ irq_tab[irq].handler = handler;
+ irq_tab[irq].flags = flags;
+ irq_tab[irq].dev_id = dev_id;
+ strncpy(irq_tab[irq].devname,devname,DEVNAME_SIZE);
+ return 0;
+ }
+ else {
+ /* Q40_IRQ_TIMER :somewhat special actions required here ..*/
+ sys_request_irq(4,handler,flags,devname,dev_id);
+ sys_request_irq(6,handler,flags,devname,dev_id);
+ return 0;
+ }
+}
+
+void q40_free_irq(unsigned int irq, void *dev_id)
+{
+ if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
+ printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id);
+ return;
+ }
+
+ /* test for ISA ints not implemented by HW */
+ if (irq<15) {
+ switch (irq){
+ case 1: case 2: case 8: case 9:
+ case 12: case 13:
+ printk("%s: ISA IRQ %d from %x illegal\n", __FUNCTION__, irq, (unsigned)dev_id);
+ return;
+ default:
+ }
+ }
+
+ if (irq<Q40_IRQ_TIMER){
+ if (irq==11) irq=10;
+ 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 = q40_defhand;
+ irq_tab[irq].flags = IRQ_FLG_STD;
+ irq_tab[irq].dev_id = NULL;
+ /* irq_tab[irq].devname = NULL; */
+ } else { /* == Q40_IRQ_TIMER */
+ sys_free_irq(4,dev_id);
+ sys_free_irq(6,dev_id);
+ }
+}
+
+#if 1
+void q40_process_int (int level, struct pt_regs *fp)
+{
+ printk("unexpected interrupt %x\n",level);
+}
+#endif
+
+/*
+ * tables to translate bits into IRQ numbers
+ * it is a good idea to order the entries by priority
+ *
+*/
+
+struct IRQ_TABLE{ unsigned mask; int irq ;};
+
+static struct IRQ_TABLE iirqs[]={
+ {IRQ_FRAME_MASK,Q40_IRQ_FRAME},
+ {IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD},
+ {0,0}};
+static struct IRQ_TABLE eirqs[]={
+ {IRQ3_MASK,3}, /* ser 1 */
+ {IRQ4_MASK,4}, /* ser 2 */
+ {IRQ14_MASK,14}, /* IDE 1 */
+ {IRQ15_MASK,15}, /* IDE 2 */
+ {IRQ6_MASK,6}, /* floppy */
+ {IRQ7_MASK,7}, /* par */
+
+ {IRQ5_MASK,5},
+ {IRQ10_MASK,10},
+
+
+
+
+ {0,0}};
+
+/* complaiun only this many times about spurious ints : */
+static int ccleirq=60; /* ISA dev IRQ's*/
+static int cclirq=60; /* internal */
+
+/* FIX: add IRQ_INPROGRESS,mask,unmask,probing.... */
+
+void q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
+{
+ /* got level 2 interrupt, dispatch to ISA or keyboard IRQs */
+
+ unsigned mir=master_inb(IIRQ_REG);
+ unsigned mer;
+ int irq,i;
+
+ /*
+ * more than 1 bit might be set, must handle atmost 1 int source,
+ * - handle only those with explicitly set handler
+ */
+
+ if ((mir&IRQ_SER_MASK) || (mir&IRQ_EXT_MASK))
+ {
+
+ /* some ISA dev caused the int */
+
+ mer=master_inb(EIRQ_REG);
+
+ for (i=0; eirqs[i].mask; i++)
+ {
+ if (mer&(eirqs[i].mask))
+ {
+ irq=eirqs[i].irq;
+ irq_tab[irq].count++;
+ if (irq_tab[irq].handler == q40_defhand )
+ continue; /* ignore uninited INTs :-( */
+
+ irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
+ return;
+ }
+ }
+ if (ccleirq>0)
+ printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--;
+ }
+ else
+ {
+ /* internal */
+
+ for (i=0; iirqs[i].mask; i++)
+ {
+ if (mir&(iirqs[i].mask))
+ {
+ irq=iirqs[i].irq;
+ irq_tab[irq].count++;
+ if (irq_tab[irq].handler == q40_defhand )
+ continue; /* ignore uninited INTs :-( */
+
+ irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
+ return;
+ }
+ }
+ if (cclirq>0)
+ printk("internal level 2 interrupt from unknown source ? IIRQ_REG=%x\n",mir),cclirq--;
+ }
+}
+
+int q40_get_irq_list (char *buf)
+{
+ int i, len = 0;
+
+ for (i = 0; i <= Q40_IRQ_MAX; i++) {
+ if (irq_tab[i].count)
+ len += sprintf (buf+len, "Vec 0x%02x: %8d %s%s\n",
+ i, irq_tab[i].count,
+ irq_tab[i].devname[0] ? irq_tab[i].devname : "?",
+ irq_tab[i].handler == q40_defhand ?
+ " (now unassigned)" : "");
+ }
+ return len;
+}
+
+
+static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp)
+{
+#if 0
+ printk ("Unknown q40 interrupt 0x%02x\n", irq);
+#endif
+}
+static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs)
+{
+#if 0
+ if (ints_inited)
+#endif
+ printk ("Uninitialised interrupt level %d\n", lev);
+#if 0
+ else
+ printk ("Interrupt before interrupt initialisation\n");
+#endif
+}
+
+ void (*q40_sys_default_handler[SYS_IRQS]) (int, void *, struct pt_regs *) = {
+ sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler,
+ sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler
+ };
+
+void q40_enable_irq (unsigned int irq)
+{
+}
+
+
+void q40_disable_irq (unsigned int irq)
+{
+}
+
+unsigned long q40_probe_irq_on (void)
+{
+ printk("sorry, irq probing not yet implemented - reconfigure the driver to avoid this\n");
+ return 0;
+}
+int q40_probe_irq_off (unsigned long irqs)
+{
+ return -1;
+}
diff --git a/arch/m68k/sun3x/Makefile b/arch/m68k/sun3x/Makefile
new file mode 100644
index 000000000..ba1f2bbd5
--- /dev/null
+++ b/arch/m68k/sun3x/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for Linux arch/m68k/sun3x 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 := sun3x.o
+O_OBJS := config.o time.o dvma.o sbus.o
+OX_OBJS :=
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
new file mode 100644
index 000000000..5054cd888
--- /dev/null
+++ b/arch/m68k/sun3x/config.c
@@ -0,0 +1,128 @@
+/*
+ * Setup kernel for a Sun3x machine
+ *
+ * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ *
+ * based on code from Oliver Jowett <oliver@jowett.manawatu.gen.nz>
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/sun3x.h>
+
+#include "time.h"
+
+static volatile unsigned char *sun3x_intreg = (unsigned char *)SUN3X_INTREG;
+extern int serial_console;
+
+void sun3x_halt(void)
+{
+ /* Disable interrupts */
+ cli();
+
+ /* we can't drop back to PROM, so we loop here */
+ for (;;);
+}
+
+void sun3x_reboot(void)
+{
+ /* This never returns, don't bother saving things */
+ cli();
+
+ /* no idea, whether this works */
+ asm ("reset");
+}
+
+__initfunc(int sun3x_keyb_init(void))
+{
+ return 0;
+}
+
+int sun3x_kbdrate(struct kbd_repeat *r)
+{
+ return 0;
+}
+
+void sun3x_kbd_leds(unsigned int i)
+{
+
+}
+
+static void sun3x_badint (int irq, void *dev_id, struct pt_regs *fp)
+{
+ printk ("received spurious interrupt %d\n",irq);
+ num_spurious += 1;
+}
+
+void (*sun3x_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+ sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint,
+ sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint
+};
+
+void sun3x_enable_irq(unsigned int irq)
+{
+ *sun3x_intreg |= (1 << irq);
+}
+
+void sun3x_disable_irq(unsigned int irq)
+{
+ *sun3x_intreg &= ~(1 << irq);
+}
+
+__initfunc(void sun3x_init_IRQ(void))
+{
+ /* disable all interrupts initially */
+ *sun3x_intreg = 1; /* master enable only */
+}
+
+int sun3x_get_irq_list(char *buf)
+{
+ return 0;
+}
+
+/*
+ * Setup the sun3x configuration info
+ */
+__initfunc(void config_sun3x(void))
+{
+ mach_get_irq_list = sun3x_get_irq_list;
+ mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
+
+ mach_keyb_init = sun3x_keyb_init;
+ mach_kbdrate = sun3x_kbdrate;
+ mach_kbd_leds = sun3x_kbd_leds;
+
+ mach_sched_init = sun3x_sched_init;
+ mach_init_IRQ = sun3x_init_IRQ;
+ enable_irq = sun3x_enable_irq;
+ disable_irq = sun3x_disable_irq;
+ mach_request_irq = sys_request_irq;
+ mach_free_irq = sys_free_irq;
+ mach_default_handler = &sun3x_default_handler;
+ mach_gettimeoffset = sun3x_gettimeoffset;
+ mach_reset = sun3x_reboot;
+
+ mach_gettod = sun3x_gettod;
+
+ switch (*(unsigned char *)SUN3X_EEPROM_CONS) {
+ case 0x10:
+ serial_console = 1;
+ conswitchp = NULL;
+ break;
+ case 0x11:
+ serial_console = 2;
+ conswitchp = NULL;
+ break;
+ default:
+ serial_console = 0;
+ conswitchp = &dummy_con;
+ break;
+ }
+
+}
diff --git a/arch/m68k/sun3x/dvma.c b/arch/m68k/sun3x/dvma.c
new file mode 100644
index 000000000..9ef3471a2
--- /dev/null
+++ b/arch/m68k/sun3x/dvma.c
@@ -0,0 +1,162 @@
+/*
+ * Virtual DMA allocation
+ *
+ * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/mm.h>
+
+#include <asm/sun3x.h>
+#include <asm/dvma.h>
+#include <asm/io.h>
+#include <asm/page.h>
+
+/* IOMMU support */
+
+#define IOMMU_ENTRIES 2048
+#define IOMMU_ADDR_MASK 0x03ffe000
+#define IOMMU_CACHE_INHIBIT 0x00000040
+#define IOMMU_FULL_BLOCK 0x00000020
+#define IOMMU_MODIFIED 0x00000010
+#define IOMMU_USED 0x00000008
+#define IOMMU_WRITE_PROTECT 0x00000004
+#define IOMMU_DT_MASK 0x00000003
+#define IOMMU_DT_INVALID 0x00000000
+#define IOMMU_DT_VALID 0x00000001
+#define IOMMU_DT_BAD 0x00000002
+
+#define DVMA_PAGE_SHIFT 13
+#define DVMA_PAGE_SIZE (1UL << DVMA_PAGE_SHIFT)
+#define DVMA_PAGE_MASK (~(DVMA_PAGE_SIZE-1))
+
+
+static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU;
+static unsigned long iommu_use[IOMMU_ENTRIES];
+static unsigned long iommu_bitmap[IOMMU_ENTRIES/32];
+
+
+#define dvma_entry_paddr(index) (iommu_pte[index] & IOMMU_ADDR_MASK)
+#define dvma_entry_vaddr(index,paddr) ((index << DVMA_PAGE_SHIFT) | \
+ (paddr & (DVMA_PAGE_SIZE-1)))
+#define dvma_entry_set(index,addr) (iommu_pte[index] = \
+ (addr & IOMMU_ADDR_MASK) | \
+ IOMMU_DT_VALID)
+#define dvma_entry_clr(index) (iommu_pte[index] = IOMMU_DT_INVALID)
+#define dvma_entry_use(index) (iommu_use[index])
+#define dvma_entry_inc(index) (iommu_use[index]++)
+#define dvma_entry_dec(index) (iommu_use[index]--)
+#define dvma_entry_hash(addr) ((addr >> DVMA_PAGE_SHIFT) ^ \
+ ((addr & 0x03c00000) >> \
+ (DVMA_PAGE_SHIFT+4)))
+#define dvma_map iommu_bitmap
+#define dvma_map_size (IOMMU_ENTRIES/2)
+#define dvma_slow_offset (IOMMU_ENTRIES/2)
+#define dvma_is_slow(addr) ((addr) & \
+ (dvma_slow_offset << DVMA_PAGE_SHIFT))
+
+static int fixed_dvma;
+
+void __init dvma_init(void)
+{
+ unsigned long tmp;
+
+ if ((unsigned long)high_memory < (IOMMU_ENTRIES << DVMA_PAGE_SHIFT)) {
+ printk ("Sun3x fixed DVMA mapping\n");
+ fixed_dvma = 1;
+ for (tmp = 0; tmp < (unsigned long)high_memory; tmp += DVMA_PAGE_SIZE)
+ dvma_entry_set (tmp >> DVMA_PAGE_SHIFT, virt_to_phys((void *)tmp));
+ fixed_dvma = 1;
+ } else {
+ printk ("Sun3x variable DVMA mapping\n");
+ for (tmp = 0; tmp < IOMMU_ENTRIES; tmp++)
+ dvma_entry_clr (tmp);
+ fixed_dvma = 0;
+ }
+}
+
+unsigned long dvma_slow_alloc (unsigned long paddr, int npages)
+{
+ int scan, base;
+
+ scan = 0;
+ for (;;) {
+ scan = find_next_zero_bit(dvma_map, dvma_map_size, scan);
+ if ((base = scan) + npages > dvma_map_size) {
+ printk ("dvma_slow_alloc failed for %d pages\n",npages);
+ return 0;
+ }
+ for (;;) {
+ if (scan >= base + npages) goto found;
+ if (test_bit(scan, dvma_map)) break;
+ scan++;
+ }
+ }
+
+found:
+ for (scan = base; scan < base+npages; scan++) {
+ dvma_entry_set(scan+dvma_slow_offset, paddr);
+ paddr += DVMA_PAGE_SIZE;
+ set_bit(scan, dvma_map);
+ }
+ return (dvma_entry_vaddr((base+dvma_slow_offset),paddr));
+}
+
+unsigned long dvma_alloc (unsigned long paddr, unsigned long size)
+{
+ int index;
+ int pages = ((paddr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >>
+ DVMA_PAGE_SHIFT;
+
+ if (fixed_dvma)
+ return ((unsigned long)phys_to_virt (paddr));
+
+ if (pages > 1) /* multi page, allocate from slow pool */
+ return dvma_slow_alloc (paddr, pages);
+
+ index = dvma_entry_hash (paddr);
+
+ if (dvma_entry_use(index)) {
+ if (dvma_entry_paddr(index) == (paddr & DVMA_PAGE_MASK)) {
+ dvma_entry_inc(index);
+ return dvma_entry_vaddr(index,paddr);
+ }
+ /* collision, allocate from slow pool */
+ return dvma_slow_alloc (paddr, pages);
+ }
+
+ dvma_entry_set(index,paddr);
+ dvma_entry_inc(index);
+ return dvma_entry_vaddr(index,paddr);
+}
+
+void dvma_free (unsigned long dvma_addr, unsigned long size)
+{
+ int npages;
+ int index;
+
+ if (fixed_dvma)
+ return;
+
+ if (!dvma_is_slow(dvma_addr)) {
+ index = (dvma_addr >> DVMA_PAGE_SHIFT);
+ if (dvma_entry_use(index) == 0) {
+ printk ("dvma_free: %lx entry already free\n",dvma_addr);
+ return;
+ }
+ dvma_entry_dec(index);
+ if (dvma_entry_use(index) == 0)
+ dvma_entry_clr(index);
+ return;
+ }
+
+ /* free in slow pool */
+ npages = ((dvma_addr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >>
+ DVMA_PAGE_SHIFT;
+ for (index = (dvma_addr >> DVMA_PAGE_SHIFT); npages--; index++) {
+ dvma_entry_clr(index);
+ clear_bit (index,dvma_map);
+ }
+}
diff --git a/arch/m68k/sun3x/sbus.c b/arch/m68k/sun3x/sbus.c
new file mode 100644
index 000000000..f1a89df65
--- /dev/null
+++ b/arch/m68k/sun3x/sbus.c
@@ -0,0 +1,44 @@
+/*
+ * SBus helper functions
+ *
+ * Sun3x don't have a sbus, but many of the used devices are also
+ * used on Sparc machines with sbus. To avoid having a lot of
+ * duplicate code, we provide necessary glue stuff to make using
+ * of the sbus driver code possible.
+ *
+ * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+__initfunc(void sbus_init(void))
+{
+
+}
+
+void *sparc_alloc_io (u32 address, void *virtual, int len, char *name,
+ u32 bus_type, int rdonly)
+{
+ return (void *)address;
+}
+
+int prom_getintdefault(int node, char *property, int deflt)
+{
+ return deflt;
+}
+
+int prom_getbool (int node, char *prop)
+{
+ return 1;
+}
+
+void prom_printf(char *fmt, ...)
+{
+
+}
+
+void prom_halt (void)
+{
+
+}
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
new file mode 100644
index 000000000..39fa5f696
--- /dev/null
+++ b/arch/m68k/sun3x/time.c
@@ -0,0 +1,83 @@
+/*
+ * linux/arch/m68k/sun3x/time.c
+ *
+ * Sun3x-specific time handling
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/sun3x.h>
+
+#include "time.h"
+
+#define M_CONTROL 0xf8
+#define M_SEC 0xf9
+#define M_MIN 0xfa
+#define M_HOUR 0xfb
+#define M_DAY 0xfc
+#define M_DATE 0xfd
+#define M_MONTH 0xfe
+#define M_YEAR 0xff
+
+#define C_WRITE 0x80
+#define C_READ 0x40
+#define C_SIGN 0x20
+#define C_CALIB 0x1f
+
+#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
+
+/* Read the Mostek */
+void sun3x_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
+{
+ volatile unsigned char *eeprom = (unsigned char *)SUN3X_EEPROM;
+
+ /* Stop updates */
+ *(eeprom + M_CONTROL) |= C_READ;
+
+ /* Read values */
+ *yearp = BCD_TO_BIN(*(eeprom + M_YEAR));
+ *monp = BCD_TO_BIN(*(eeprom + M_MONTH));
+ *dayp = BCD_TO_BIN(*(eeprom + M_DATE));
+ *hourp = BCD_TO_BIN(*(eeprom + M_HOUR));
+ *minp = BCD_TO_BIN(*(eeprom + M_MIN));
+ *secp = BCD_TO_BIN(*(eeprom + M_SEC));
+
+ /* Restart updates */
+ *(eeprom + M_CONTROL) &= ~C_READ;
+}
+
+/* Not much we can do here */
+unsigned long sun3x_gettimeoffset (void)
+{
+ return 0L;
+}
+
+static void sun3x_timer_tick(int irq, void *dev_id, struct pt_regs *regs)
+{
+ void (*vector)(int, void *, struct pt_regs *) = dev_id;
+
+ /* Clear the pending interrupt - pulse the enable line low */
+ disable_irq(5);
+ enable_irq(5);
+
+ vector(irq, NULL, regs);
+}
+
+__initfunc(void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *)))
+{
+ sys_request_irq(5, sun3x_timer_tick, IRQ_FLG_STD, "timer tick", vector);
+
+ /* Pulse enable low to get the clock started */
+ disable_irq(5);
+ enable_irq(5);
+}
diff --git a/arch/m68k/sun3x/time.h b/arch/m68k/sun3x/time.h
new file mode 100644
index 000000000..873742d70
--- /dev/null
+++ b/arch/m68k/sun3x/time.h
@@ -0,0 +1,9 @@
+#ifndef SUN3X_TIME_H
+#define SUN3X_TIME_H
+
+void sun3x_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp);
+unsigned long sun3x_gettimeoffset (void);
+void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *));
+
+#endif