summaryrefslogtreecommitdiffstats
path: root/arch/m68k
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
committer <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
commit19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch)
tree40b1cb534496a7f1ca0f5c314a523c69f1fee464 /arch/m68k
parent7206675c40394c78a90e74812bbdbf8cf3cca1be (diff)
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'arch/m68k')
-rw-r--r--arch/m68k/Makefile57
-rw-r--r--arch/m68k/amiga/Makefile7
-rw-r--r--arch/m68k/amiga/amifb.c85
-rw-r--r--arch/m68k/amiga/amiga_ksyms.c27
-rw-r--r--arch/m68k/amiga/amiints.c94
-rw-r--r--arch/m68k/amiga/amikeyb.c2
-rw-r--r--arch/m68k/amiga/amisound.c1
-rw-r--r--arch/m68k/amiga/chipram.c13
-rw-r--r--arch/m68k/amiga/cia.c26
-rw-r--r--arch/m68k/amiga/config.c486
-rw-r--r--arch/m68k/amiga/cyberfb.c19
-rw-r--r--arch/m68k/amiga/ksyms.c40
-rw-r--r--arch/m68k/amiga/retz3fb.c3504
-rw-r--r--arch/m68k/amiga/retz3fb.h572
-rw-r--r--arch/m68k/amiga/zorro.c140
-rw-r--r--arch/m68k/atari/Makefile5
-rw-r--r--arch/m68k/atari/atafb.c37
-rw-r--r--arch/m68k/atari/ataints.c16
-rw-r--r--arch/m68k/atari/atakeyb.c65
-rw-r--r--arch/m68k/atari/atari_ksyms.c35
-rw-r--r--arch/m68k/atari/atasound.c1
-rw-r--r--arch/m68k/atari/config.c263
-rw-r--r--arch/m68k/atari/joystick.c32
-rw-r--r--arch/m68k/atari/ksyms.c40
-rw-r--r--arch/m68k/atari/stdma.c1
-rw-r--r--arch/m68k/atari/stram.c10
-rw-r--r--arch/m68k/boot/Makefile17
-rw-r--r--arch/m68k/boot/amiga/bootstrap.c204
-rw-r--r--arch/m68k/boot/amiga/bootstrap.h26
-rw-r--r--arch/m68k/boot/amiga/linuxboot.c826
-rw-r--r--arch/m68k/boot/amiga/linuxboot.h36
-rw-r--r--arch/m68k/boot/atari/bootp.c47
-rw-r--r--arch/m68k/boot/atari/bootp.h6
-rw-r--r--arch/m68k/boot/atari/bootstrap.c693
-rw-r--r--arch/m68k/boot/atari/bootstrap.h28
-rw-r--r--arch/m68k/config.in70
-rw-r--r--arch/m68k/console/fbcon.c1132
-rw-r--r--arch/m68k/console/txtcon.c28
-rw-r--r--arch/m68k/defconfig27
-rw-r--r--arch/m68k/fpsp040/Makefile1
-rw-r--r--arch/m68k/fpsp040/skeleton.S20
-rw-r--r--arch/m68k/ifpsp060/Makefile1
-rw-r--r--arch/m68k/ifpsp060/os.S41
-rw-r--r--arch/m68k/kernel/Makefile10
-rw-r--r--arch/m68k/kernel/console.c231
-rw-r--r--arch/m68k/kernel/entry.S160
-rw-r--r--arch/m68k/kernel/head.S306
-rw-r--r--arch/m68k/kernel/ints.c86
-rw-r--r--arch/m68k/kernel/ksyms.c89
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c57
-rw-r--r--arch/m68k/kernel/process.c54
-rw-r--r--arch/m68k/kernel/ptrace.c105
-rw-r--r--arch/m68k/kernel/setup.c208
-rw-r--r--arch/m68k/kernel/signal.c41
-rw-r--r--arch/m68k/kernel/sys_m68k.c347
-rw-r--r--arch/m68k/kernel/traps.c107
-rw-r--r--arch/m68k/lib/checksum.c69
-rw-r--r--arch/m68k/lib/semaphore.S20
-rw-r--r--arch/m68k/mm/extable.c26
-rw-r--r--arch/m68k/mm/fault.c10
-rw-r--r--arch/m68k/mm/init.c65
-rw-r--r--arch/m68k/mm/memory.c231
62 files changed, 8705 insertions, 2298 deletions
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index c1dd3072c..939a80387 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -18,19 +18,11 @@ COMPILE_ARCH = $(shell uname -m)
# override top level makefile
AS += -m68020
-ifdef CONFIG_KERNEL_ELF
LD += -m m68kelf
ifneq ($(COMPILE_ARCH),$(ARCH))
# prefix for cross-compiling binaries
CROSS_COMPILE = m68k-linux-
endif
-else
-LD += -m m68klinux
-ifneq ($(COMPILE_ARCH),$(ARCH))
- # prefix for cross-compiling binaries
- CROSS_COMPILE = m68k-linuxaout-
-endif
-endif
#
# Set these to indicate how to link it..
@@ -42,53 +34,58 @@ endif
# -qmagic (we need to remove the 32 byte header for bootup purposes)
#
-ifdef CONFIG_KERNEL_ELF
LINKFLAGS = -Ttext 0x1000
-else
-LINKFLAGS = -qmagic -Ttext 0xFE0
-endif
-CFLAGS := $(CFLAGS) -pipe
+CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce
ifdef CONFIG_OPTIMIZE_040
CFLAGS := $(CFLAGS) -m68040
endif
ifdef CONFIG_OPTIMIZE_060
-CFLAGS := $(CFLAGS) -m68020-40 -Wa,-m68060
+CFLAGS := $(CFLAGS) -m68020-40
+endif
+
+ifdef CONFIG_KGDB
+# If configured for kgdb support, include debugging infos and keep the
+# frame pointer
+CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g
endif
HEAD := arch/m68k/kernel/head.o
-SUBDIRS += arch/m68k/kernel arch/m68k/mm arch/m68k/console arch/m68k/lib
-ARCHIVES := arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o $(ARCHIVES)
+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_AMIGA
-ARCHIVES := $(ARCHIVES) arch/m68k/amiga/amiga.o
+CORE_FILES := $(CORE_FILES) arch/m68k/amiga/amiga.o
SUBDIRS := $(SUBDIRS) arch/m68k/amiga
endif
ifdef CONFIG_ATARI
-ARCHIVES := $(ARCHIVES) arch/m68k/atari/atari.o
+CORE_FILES := $(CORE_FILES) arch/m68k/atari/atari.o
SUBDIRS := $(SUBDIRS) arch/m68k/atari
endif
ifdef CONFIG_MAC
-ARCHIVES := $(ARCHIVES) arch/m68k/mac/mac.o
+CORE_FILES := $(CORE_FILES) arch/m68k/mac/mac.o
SUBDIRS := $(SUBDIRS) arch/m68k/mac
endif
+ifdef CONFIG_VT
# add in console.a after {amiga,atari}.o that need it
-ARCHIVES := $(ARCHIVES) arch/m68k/console/console.a
+CORE_FILES := $(CORE_FILES) arch/m68k/console/console.a
+SUBDIRS := $(SUBDIRS) arch/m68k/console
+endif
ifdef CONFIG_M68040
-ARCHIVES := $(ARCHIVES) arch/m68k/fpsp040/fpsp.o
+CORE_FILES := $(CORE_FILES) arch/m68k/fpsp040/fpsp.o
SUBDIRS := $(SUBDIRS) arch/m68k/fpsp040
endif
ifdef CONFIG_M68060
-ARCHIVES := $(ARCHIVES) arch/m68k/ifpsp060/ifpsp.o
+CORE_FILES := $(CORE_FILES) arch/m68k/ifpsp060/ifpsp.o
SUBDIRS := $(SUBDIRS) arch/m68k/ifpsp060
endif
@@ -101,10 +98,24 @@ lilo: vmlinux
cp System.map $(INSTALL_PATH)/System.map
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-bootstrap:
+zImage compressed: vmlinux.gz
+
+vmlinux.gz: vmlinux
+
+ifdef CONFIG_KGDB
+ cp vmlinux vmlinux.tmp
+ $(STRIP) vmlinux.tmp
+ gzip -9c vmlinux.tmp >vmlinux.gz
+ rm vmlinux.tmp
+else
+ gzip -9c vmlinux >vmlinux.gz
+endif
+
+bootstrap: dummy
@$(MAKEBOOT) bootstrap
archclean:
+ rm -f vmlinux.gz
@$(MAKEBOOT) clean
archdep:
diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile
index ca540b9d1..9716668ea 100644
--- a/arch/m68k/amiga/Makefile
+++ b/arch/m68k/amiga/Makefile
@@ -9,10 +9,15 @@
O_TARGET := amiga.o
O_OBJS := config.o amikeyb.o amiints.o cia.o \
- chipram.o amisound.o amifb.o zorro.o ksyms.o
+ chipram.o amisound.o amifb.o zorro.o
+OX_OBJS := amiga_ksyms.o
ifdef CONFIG_FB_CYBER
O_OBJS := $(O_OBJS) cyberfb.o
endif
+ifdef CONFIG_FB_RETINAZ3
+O_OBJS := $(O_OBJS) retz3fb.o
+endif
+
include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/amiga/amifb.c b/arch/m68k/amiga/amifb.c
index b05e314d2..c97609611 100644
--- a/arch/m68k/amiga/amifb.c
+++ b/arch/m68k/amiga/amifb.c
@@ -50,7 +50,6 @@
#include <linux/delay.h>
#include <linux/config.h>
#include <linux/interrupt.h>
-#include <asm/setup.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/irq.h>
@@ -606,6 +605,8 @@ static long vfmin = 50, vfmax = 90, hfmin = 15000, hfmax = 38000;
#define SPRITEMEMSIZE (64*64/4) /* max 64*64*4 */
#define DUMMYSPRITEMEMSIZE (8)
+#define CHIPRAM_SAFETY_LIMIT (16384)
+
static u_long videomemory, spritememory;
static u_long videomemorysize;
@@ -639,7 +640,7 @@ typedef union {
u_short w[2];
} copins;
-struct copdisplay {
+static struct copdisplay {
copins *init;
copins *wait;
copins *list[2][2];
@@ -662,7 +663,7 @@ static u_short *lofsprite, *shfsprite, *dummysprite;
* Current Video Mode
*/
-struct amiga_fb_par {
+static struct amiga_fb_par {
/* General Values */
@@ -835,7 +836,7 @@ static char *amiga_fb_modenames[] = {
"user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7"
};
-struct fb_var_screeninfo amiga_fb_predefined[] = {
+static struct fb_var_screeninfo amiga_fb_predefined[] = {
/*
* Autodetect (Default) Video Mode
@@ -1241,6 +1242,7 @@ struct fb_info *amiga_fb_init(long *mem_start);
static int amifbcon_switch(int con);
static int amifbcon_updatevar(int con);
static void amifbcon_blank(int blank);
+static int amifbcon_setcmap(struct fb_cmap *cmap, int con);
/*
* Internal routines
@@ -1314,7 +1316,15 @@ extern void Cyber_video_setup(char *options, int *ints);
extern struct fb_info *Cyber_fb_init(long *mem_start);
static int amifb_Cyber = 0;
-#endif /* CONFIG_FB_CYBER */
+#endif
+
+#ifdef CONFIG_FB_RETINAZ3 /* RetinaZ3 */
+extern int retz3_probe(void);
+extern void retz3_video_setup(char *options, int *ints);
+extern struct fb_info *retz3_fb_init(long *mem_start);
+
+static int amifb_retz3 = 0;
+#endif
#ifdef CONFIG_GSP_RESOLVER /* DMI Resolver */
extern int resolver_probe(void);
@@ -1322,7 +1332,7 @@ extern void resolver_video_setup(char *options, int *ints);
extern struct fb_info *resolver_fb_init(long *mem_start);
static int amifb_resolver = 0;
-#endif /* CONFIG_GSP_RESOLVER */
+#endif
static struct fb_ops amiga_fb_ops = {
amiga_fb_get_fix, amiga_fb_get_var, amiga_fb_set_var, amiga_fb_get_cmap,
@@ -1346,7 +1356,15 @@ void amiga_video_setup(char *options, int *ints)
Cyber_video_setup(options, ints);
return;
}
-#endif /* CONFIG_FB_CYBER */
+#endif
+#ifdef CONFIG_FB_RETINAZ3
+ if (options && *options)
+ if (!strncmp(options, "retz3", 5) && retz3_probe()) {
+ amifb_retz3 = 1;
+ retz3_video_setup(options, ints);
+ return;
+ }
+#endif
#ifdef CONFIG_GSP_RESOLVER
if (options && *options)
if (!strncmp(options, "resolver", 5) && resolver_probe()) {
@@ -1796,7 +1814,14 @@ struct fb_info *amiga_fb_init(long *mem_start)
#ifdef CONFIG_FB_CYBER
if (amifb_Cyber)
return Cyber_fb_init(mem_start);
-#endif /* CONFIG_FB_CYBER */
+#endif
+#ifdef CONFIG_FB_RETINAZ3
+ if (amifb_retz3){
+ custom.dmacon = DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
+ DMAF_BLITTER | DMAF_SPRITE;
+ return retz3_fb_init(mem_start);
+ }
+#endif
#ifdef CONFIG_GSP_RESOLVER
if (amifb_resolver){
custom.dmacon = DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
@@ -1814,7 +1839,7 @@ struct fb_info *amiga_fb_init(long *mem_start)
custom.dmacon = DMAF_ALL | DMAF_MASTER;
- switch (boot_info.bi_amiga.chipset) {
+ switch (amiga_chipset) {
#ifdef CONFIG_AMIFB_OCS
case CS_OCS:
strcat(amiga_fb_name, "OCS");
@@ -1825,7 +1850,7 @@ default_chipset:
maxdepth[TAG_LORES] = 6;
maxfmode = TAG_FMODE_1;
if (!amifb_usermode) /* Set the Default Video Mode */
- get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
+ get_video_mode(amiga_vblank == 50 ?
DEFMODE_PAL : DEFMODE_NTSC);
videomemorysize = VIDEOMEMSIZE_OCS;
break;
@@ -1841,13 +1866,14 @@ default_chipset:
maxfmode = TAG_FMODE_1;
if (!amifb_usermode) { /* Set the Default Video Mode */
if (AMIGAHW_PRESENT(AMBER_FF))
- get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
+ get_video_mode(amiga_vblank == 50 ?
DEFMODE_AMBER_PAL : DEFMODE_AMBER_NTSC);
else
- get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
+ get_video_mode(amiga_vblank == 50 ?
DEFMODE_PAL : DEFMODE_NTSC);
}
- if (boot_info.bi_amiga.chip_size > 1048576)
+ if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
+ VIDEOMEMSIZE_ECS_1M)
videomemorysize = VIDEOMEMSIZE_ECS_2M;
else
videomemorysize = VIDEOMEMSIZE_ECS_1M;
@@ -1864,7 +1890,8 @@ default_chipset:
maxfmode = TAG_FMODE_4;
if (!amifb_usermode) /* Set the Default Video Mode */
get_video_mode(DEFMODE_AGA);
- if (boot_info.bi_amiga.chip_size > 1048576)
+ if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
+ VIDEOMEMSIZE_AGA_1M)
videomemorysize = VIDEOMEMSIZE_AGA_2M;
else
videomemorysize = VIDEOMEMSIZE_AGA_1M;
@@ -1940,11 +1967,11 @@ default_chipset:
check_default_mode();
- if (request_irq(IRQ3, amifb_interrupt, IRQ_FLG_LOCK,
+ if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, IRQ_FLG_LOCK,
"fb vertb handler", NULL))
panic("Couldn't add vblank interrupt\n");
- ami_intena_vals[IRQ_IDX(IRQ_AMIGA_VERTB)] = IF_COPER;
- ami_intena_vals[IRQ_IDX(IRQ_AMIGA_COPPER)] = 0;
+ ami_intena_vals[IRQ_AMIGA_VERTB] = IF_COPER;
+ ami_intena_vals[IRQ_AMIGA_COPPER] = 0;
custom.intena = IF_VERTB;
custom.intena = IF_SETCLR | IF_COPER;
@@ -1954,6 +1981,7 @@ default_chipset:
fb_info.switch_con = &amifbcon_switch;
fb_info.updatevar = &amifbcon_updatevar;
fb_info.blank = &amifbcon_blank;
+ fb_info.setcmap = &amifbcon_setcmap;
amiga_fb_set_var(&amiga_fb_predefined[0], 0);
@@ -1992,6 +2020,15 @@ static void amifbcon_blank(int blank)
do_blank = blank ? blank : -1;
}
+ /*
+ * Set the colormap
+ */
+
+static int amifbcon_setcmap(struct fb_cmap *cmap, int con)
+{
+ return(amiga_fb_set_cmap(cmap, 1, con));
+}
+
/* ---------------------------- Generic routines ---------------------------- */
static struct fb_cmap *get_default_colormap(int bpp)
@@ -2210,10 +2247,11 @@ static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
{
u_short ints = custom.intreqr & custom.intenar;
static struct irq_server server = {0, 0};
+ unsigned long flags;
if (ints & IF_BLIT) {
custom.intreq = IF_BLIT;
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_BLIT), fp);
+ amiga_do_irq(IRQ_AMIGA_BLIT, fp);
}
if (ints & IF_COPER) {
@@ -2237,8 +2275,11 @@ static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
ami_set_sprite();
}
- if (get_vbpos() < down2(currentpar.diwstrt_v - 4))
+ save_flags(flags);
+ cli();
+ if (get_vbpos() < down2(currentpar.diwstrt_v - 6))
custom.copjmp2 = 0;
+ restore_flags(flags);
if (do_blank) {
ami_do_blank();
@@ -2249,7 +2290,7 @@ static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
ami_reinit_copper();
do_vmode_full = 0;
}
- amiga_do_irq_list(IRQ_IDX(IRQ_AMIGA_VERTB), fp, &server);
+ amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
}
if (ints & IF_VERTB) {
@@ -2504,7 +2545,7 @@ static int ami_decode_var(struct fb_var_screeninfo *var,
AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
par->beamcon0 = BMC0_PAL;
par->hsstop = 1;
- } else if (boot_info.bi_un.bi_ami.vblank != 50)
+ } else if (amiga_vblank != 50)
return -EINVAL;
} else {
/* NTSC video mode
@@ -2526,7 +2567,7 @@ static int ami_decode_var(struct fb_var_screeninfo *var,
AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
par->beamcon0 = 0;
par->hsstop = 1;
- } else if (boot_info.bi_un.bi_ami.vblank != 60)
+ } else if (amiga_vblank != 60)
return -EINVAL;
}
if (IS_OCS) {
diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c
new file mode 100644
index 000000000..fe55f5f69
--- /dev/null
+++ b/arch/m68k/amiga/amiga_ksyms.c
@@ -0,0 +1,27 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/zorro.h>
+#include <asm/amigahw.h>
+
+extern volatile u_short amiga_audio_min_period;
+extern u_short amiga_audio_period;
+
+/*
+ * Add things here when you find the need for it.
+ */
+EXPORT_SYMBOL(amiga_model);
+EXPORT_SYMBOL(amiga_hw_present);
+EXPORT_SYMBOL(amiga_eclock);
+EXPORT_SYMBOL(amiga_colorclock);
+EXPORT_SYMBOL(amiga_chip_alloc);
+EXPORT_SYMBOL(amiga_chip_free);
+EXPORT_SYMBOL(amiga_chip_avail);
+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);
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
index 5fe90949e..b527a8c6c 100644
--- a/arch/m68k/amiga/amiints.c
+++ b/arch/m68k/amiga/amiints.c
@@ -97,7 +97,7 @@ void amiga_init_IRQ(void)
cia_init_IRQ(&ciab_base);
}
-void amiga_insert_irq(irq_node_t **list, irq_node_t *node)
+static inline void amiga_insert_irq(irq_node_t **list, irq_node_t *node)
{
unsigned long flags;
irq_node_t *cur;
@@ -135,7 +135,7 @@ void amiga_insert_irq(irq_node_t **list, irq_node_t *node)
restore_flags(flags);
}
-void amiga_delete_irq(irq_node_t **list, void *dev_id)
+static inline void amiga_delete_irq(irq_node_t **list, void *dev_id)
{
unsigned long flags;
irq_node_t *node;
@@ -172,12 +172,16 @@ int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_r
return -ENXIO;
}
- if (irq >= IRQ_IDX(IRQ_AMIGA_CIAB))
- return cia_request_irq(&ciab_base, irq - IRQ_IDX(IRQ_AMIGA_CIAB),
+ if (irq >= IRQ_AMIGA_AUTO)
+ return sys_request_irq(irq - IRQ_AMIGA_AUTO, handler,
+ flags, devname, dev_id);
+
+ if (irq >= IRQ_AMIGA_CIAB)
+ return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB,
handler, flags, devname, dev_id);
- if (irq >= IRQ_IDX(IRQ_AMIGA_CIAA))
- return cia_request_irq(&ciaa_base, irq - IRQ_IDX(IRQ_AMIGA_CIAA),
+ if (irq >= IRQ_AMIGA_CIAA)
+ return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
handler, flags, devname, dev_id);
if (ami_servers[irq]) {
@@ -196,7 +200,7 @@ int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_r
__FUNCTION__, irq, ami_irq_list[irq]->devname);
return -EBUSY;
}
- if (flags & IRQ_FLG_REPLACE) {
+ if (!(flags & IRQ_FLG_REPLACE)) {
printk("%s: %s can't replace IRQ %d from %s\n",
__FUNCTION__, devname, irq, ami_irq_list[irq]->devname);
return -EBUSY;
@@ -209,7 +213,7 @@ int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_r
}
/* enable the interrupt */
- if (irq < IRQ_IDX(IRQ_AMIGA_PORTS) && !ami_ablecount[irq])
+ if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
custom.intena = IF_SETCLR | ami_intena_vals[irq];
return 0;
@@ -222,20 +226,23 @@ void amiga_free_irq(unsigned int irq, void *dev_id)
return;
}
- if (irq >= IRQ_IDX(IRQ_AMIGA_CIAB)) {
- cia_free_irq(&ciab_base, irq - IRQ_IDX(IRQ_AMIGA_CIAB), dev_id);
+ if (irq >= IRQ_AMIGA_AUTO)
+ sys_free_irq(irq - IRQ_AMIGA_AUTO, dev_id);
+
+ if (irq >= IRQ_AMIGA_CIAB) {
+ cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id);
return;
}
- if (irq >= IRQ_IDX(IRQ_AMIGA_CIAA)) {
- cia_free_irq(&ciaa_base, irq - IRQ_IDX(IRQ_AMIGA_CIAA), dev_id);
+ if (irq >= IRQ_AMIGA_CIAA) {
+ cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id);
return;
}
if (ami_servers[irq]) {
amiga_delete_irq(&ami_irq_list[irq], dev_id);
/* if server list empty, disable the interrupt */
- if (!ami_irq_list[irq] && irq < IRQ_IDX(IRQ_AMIGA_PORTS))
+ if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS)
custom.intena = ami_intena_vals[irq];
} else {
if (ami_irq_list[irq]->dev_id != dev_id)
@@ -267,15 +274,22 @@ void amiga_enable_irq(unsigned int irq)
if (--ami_ablecount[irq])
return;
- if (irq >= IRQ_IDX(IRQ_AMIGA_CIAB)) {
+ /* No action for auto-vector interrupts */
+ if (irq >= IRQ_AMIGA_AUTO){
+ printk("%s: Trying to enable auto-vector IRQ %i\n",
+ __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+ return;
+ }
+
+ if (irq >= IRQ_AMIGA_CIAB) {
cia_able_irq(&ciab_base, CIA_ICR_SETCLR |
- (1 << (irq - IRQ_IDX(IRQ_AMIGA_CIAB))));
+ (1 << (irq - IRQ_AMIGA_CIAB)));
return;
}
- if (irq >= IRQ_IDX(IRQ_AMIGA_CIAA)) {
+ if (irq >= IRQ_AMIGA_CIAA) {
cia_able_irq(&ciaa_base, CIA_ICR_SETCLR |
- (1 << (irq - IRQ_IDX(IRQ_AMIGA_CIAA))));
+ (1 << (irq - IRQ_AMIGA_CIAA)));
return;
}
@@ -293,13 +307,20 @@ void amiga_disable_irq(unsigned int irq)
if (ami_ablecount[irq]++)
return;
- if (irq >= IRQ_IDX(IRQ_AMIGA_CIAB)) {
- cia_able_irq(&ciab_base, 1 << (irq - IRQ_IDX(IRQ_AMIGA_CIAB)));
+ /* No action for auto-vector interrupts */
+ if (irq >= IRQ_AMIGA_AUTO) {
+ printk("%s: Trying to disable auto-vector IRQ %i\n",
+ __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+ return;
+ }
+
+ if (irq >= IRQ_AMIGA_CIAB) {
+ cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
return;
}
- if (irq >= IRQ_IDX(IRQ_AMIGA_CIAA)) {
- cia_able_irq(&ciaa_base, 1 << (irq - IRQ_IDX(IRQ_AMIGA_CIAA)));
+ if (irq >= IRQ_AMIGA_CIAA) {
+ cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
return;
}
@@ -310,13 +331,12 @@ void amiga_disable_irq(unsigned int irq)
inline void amiga_do_irq(int irq, struct pt_regs *fp)
{
kstat.interrupts[SYS_IRQS + irq]++;
- ami_irq_list[irq]->handler(irq | IRQ_MACHSPEC, ami_irq_list[irq]->dev_id, fp);
+ ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
}
void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
{
irq_node_t *node, *slow_nodes;
- int mach_irq = irq | IRQ_MACHSPEC;
unsigned short flags;
kstat.interrupts[SYS_IRQS + irq]++;
@@ -326,7 +346,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
for (node = ami_irq_list[irq];
node && (!(node->flags & IRQ_FLG_SLOW));
node = node->next)
- node->handler(mach_irq, node->dev_id, fp);
+ node->handler(irq, node->dev_id, fp);
custom.intreq = ami_intena_vals[irq];
if (!node) {
server->count--;
@@ -338,7 +358,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
slow_nodes = node;
for (;;) {
for (; node; node = node->next)
- node->handler(mach_irq, node->dev_id, fp);
+ node->handler(irq, node->dev_id, fp);
/* if reentrance occured, serve slow handlers again */
custom.intena = ami_intena_vals[irq];
if (!server->reentrance) {
@@ -363,19 +383,19 @@ static void ami_int1(int irq, void *dev_id, struct pt_regs *fp)
/* if serial transmit buffer empty, interrupt */
if (ints & IF_TBE) {
custom.intreq = IF_TBE;
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_TBE), fp);
+ amiga_do_irq(IRQ_AMIGA_TBE, fp);
}
/* if floppy disk transfer complete, interrupt */
if (ints & IF_DSKBLK) {
custom.intreq = IF_DSKBLK;
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_DSKBLK), fp);
+ amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
}
/* if software interrupt set, interrupt */
if (ints & IF_SOFT) {
custom.intreq = IF_SOFT;
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_SOFT), fp);
+ amiga_do_irq(IRQ_AMIGA_SOFT, fp);
}
}
@@ -387,18 +407,18 @@ static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
/* if a blitter interrupt */
if (ints & IF_BLIT) {
custom.intreq = IF_BLIT;
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_BLIT), fp);
+ amiga_do_irq(IRQ_AMIGA_BLIT, fp);
}
/* if a copper interrupt */
if (ints & IF_COPER) {
custom.intreq = IF_COPER;
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_COPPER), fp);
+ amiga_do_irq(IRQ_AMIGA_COPPER, fp);
}
/* if a vertical blank interrupt */
if (ints & IF_VERTB)
- amiga_do_irq_list(IRQ_IDX(IRQ_AMIGA_VERTB), fp, &server);
+ amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
}
static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
@@ -408,25 +428,25 @@ static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
/* if audio 0 interrupt */
if (ints & IF_AUD0) {
custom.intreq = IF_AUD0;
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_AUD0), fp);
+ amiga_do_irq(IRQ_AMIGA_AUD0, fp);
}
/* if audio 1 interrupt */
if (ints & IF_AUD1) {
custom.intreq = IF_AUD1;
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_AUD1), fp);
+ amiga_do_irq(IRQ_AMIGA_AUD1, fp);
}
/* if audio 2 interrupt */
if (ints & IF_AUD2) {
custom.intreq = IF_AUD2;
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_AUD2), fp);
+ amiga_do_irq(IRQ_AMIGA_AUD2, fp);
}
/* if audio 3 interrupt */
if (ints & IF_AUD3) {
custom.intreq = IF_AUD3;
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_AUD3), fp);
+ amiga_do_irq(IRQ_AMIGA_AUD3, fp);
}
}
@@ -437,13 +457,13 @@ static void ami_int5(int irq, void *dev_id, struct pt_regs *fp)
/* if serial receive buffer full interrupt */
if (ints & IF_RBF) {
/* acknowledge of IF_RBF must be done by the serial interrupt */
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_RBF), fp);
+ amiga_do_irq(IRQ_AMIGA_RBF, fp);
}
/* if a disk sync interrupt */
if (ints & IF_DSKSYN) {
custom.intreq = IF_DSKSYN;
- amiga_do_irq(IRQ_IDX(IRQ_AMIGA_DSKSYN), fp);
+ amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
}
}
diff --git a/arch/m68k/amiga/amikeyb.c b/arch/m68k/amiga/amikeyb.c
index d0f01dc70..f2e826023 100644
--- a/arch/m68k/amiga/amikeyb.c
+++ b/arch/m68k/amiga/amikeyb.c
@@ -23,8 +23,6 @@
#include <linux/random.h>
#include <linux/kernel.h>
-#include <asm/setup.h>
-#include <asm/amigatypes.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
#include <asm/irq.h>
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index 8b25b1453..b2b2e3055 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -11,7 +11,6 @@
#include <linux/sched.h>
#include <linux/timer.h>
-#include <asm/amigatypes.h>
#include <asm/system.h>
#include <asm/amigahw.h>
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index 28fb0c000..237662c93 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -8,7 +8,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
-#include <asm/setup.h>
#include <asm/amigahw.h>
struct chip_desc {
@@ -21,7 +20,7 @@ struct chip_desc {
#define DP(ptr) ((struct chip_desc *)(ptr))
-static unsigned long chipsize;
+u_long amiga_chip_size;
static unsigned long chipavail; /*MILAN*/
/*MILAN*/
@@ -41,22 +40,20 @@ void amiga_chip_init (void)
if (!AMIGAHW_PRESENT(CHIP_RAM))
return;
- chipsize = boot_info.bi_amiga.chip_size;
-
/* initialize start boundary */
dp = DP(chipaddr);
dp->first = 1;
dp->alloced = 0;
- dp->length = chipsize - 2*sizeof(*dp);
+ dp->length = amiga_chip_size - 2*sizeof(*dp);
/* initialize end boundary */
- dp = DP(chipaddr + chipsize) - 1;
+ dp = DP(chipaddr + amiga_chip_size) - 1;
dp->last = 1;
dp->alloced = 0;
- dp->length = chipsize - 2*sizeof(*dp);
+ dp->length = amiga_chip_size - 2*sizeof(*dp);
chipavail = dp->length; /*MILAN*/
#ifdef DEBUG
@@ -82,7 +79,7 @@ void *amiga_chip_alloc (long size)
* get pointer to descriptor for last chunk by
* going backwards from end chunk
*/
- dp = DP(chipaddr + chipsize) - 1;
+ dp = DP(chipaddr + amiga_chip_size) - 1;
dp = DP((unsigned long)dp - dp->length) - 1;
while ((dp->alloced || dp->length < size)
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index 7bf579f39..02b1ad564 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -30,13 +30,13 @@ struct ciabase {
irq_handler_t irq_list[CIA_IRQS];
} ciaa_base = {
&ciaa, 0, 0, IF_PORTS,
- IRQ2, IRQ_AMIGA_CIAA,
- IRQ_IDX(IRQ_AMIGA_PORTS),
+ IRQ_AMIGA_AUTO_2, IRQ_AMIGA_CIAA,
+ IRQ_AMIGA_PORTS,
"CIAA handler", {0, 0}
}, ciab_base = {
&ciab, 0, 0, IF_EXTER,
- IRQ6, IRQ_AMIGA_CIAB,
- IRQ_IDX(IRQ_AMIGA_EXTER),
+ IRQ_AMIGA_AUTO_6, IRQ_AMIGA_CIAB,
+ IRQ_AMIGA_EXTER,
"CIAB handler", {0, 0}
};
@@ -95,14 +95,14 @@ int cia_request_irq(struct ciabase *base, unsigned int irq,
if (!(base->irq_list[irq].flags & IRQ_FLG_STD)) {
if (base->irq_list[irq].flags & IRQ_FLG_LOCK) {
- printk("%s: IRQ %ld from %s is not replaceable\n",
- __FUNCTION__, IRQ_IDX(base->cia_irq + irq),
+ printk("%s: IRQ %i from %s is not replaceable\n",
+ __FUNCTION__, base->cia_irq + irq,
base->irq_list[irq].devname);
return -EBUSY;
}
- if (flags & IRQ_FLG_REPLACE) {
- printk("%s: %s can't replace IRQ %ld from %s\n", __FUNCTION__,
- devname, IRQ_IDX(base->cia_irq + irq),
+ if (!(flags & IRQ_FLG_REPLACE)) {
+ printk("%s: %s can't replace IRQ %i from %s\n", __FUNCTION__,
+ devname, base->cia_irq + irq,
base->irq_list[irq].devname);
return -EBUSY;
}
@@ -122,8 +122,8 @@ int cia_request_irq(struct ciabase *base, unsigned int irq,
void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id)
{
if (base->irq_list[irq].dev_id != dev_id)
- printk("%s: removing probably wrong IRQ %ld from %s\n",
- __FUNCTION__, IRQ_IDX(base->cia_irq + irq),
+ printk("%s: removing probably wrong IRQ %i from %s\n",
+ __FUNCTION__, base->cia_irq + irq,
base->irq_list[irq].devname);
base->irq_list[irq].handler = NULL;
@@ -139,7 +139,7 @@ static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
unsigned char ints;
mach_irq = base->cia_irq;
- irq = SYS_IRQS + IRQ_IDX(mach_irq);
+ irq = SYS_IRQS + mach_irq;
ints = cia_set_irq(base, CIA_ICR_ALL);
custom.intreq = base->int_mask;
for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) {
@@ -176,7 +176,7 @@ int cia_get_irq_list(struct ciabase *base, char *buf)
{
int i, j, len = 0;
- j = IRQ_IDX(base->cia_irq);
+ j = base->cia_irq;
for (i = 0; i < CIA_IRQS; i++) {
if (!(base->irq_list[i].flags & IRQ_FLG_STD)) {
len += sprintf(buf+len, "cia %2d: %10d ", j + i,
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 72e885d4d..8e6ae531c 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -21,6 +21,7 @@
#include <linux/tty.h>
#include <linux/console.h>
+#include <asm/bootinfo.h>
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/pgtable.h>
@@ -28,13 +29,25 @@
#include <asm/amigaints.h>
#include <asm/irq.h>
#include <asm/machdep.h>
+#include <linux/zorro.h>
+u_long amiga_model;
+u_long amiga_eclock;
u_long amiga_masterclock;
u_long amiga_colorclock;
+u_long amiga_chipset;
+u_char amiga_vblank;
+u_char amiga_psfreq;
+struct amiga_hw_present amiga_hw_present;
+
+static const char *amiga_models[] = {
+ "A500", "A500+", "A600", "A1000", "A1200", "A2000", "A2500", "A3000",
+ "A3000T", "A3000+", "A4000", "A4000T", "CDTV", "CD32", "Draco"
+};
extern char m68k_debug_device[];
-extern void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *));
+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 *);
@@ -43,143 +56,151 @@ extern void amiga_init_IRQ (void);
extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
extern int amiga_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id);
-extern int amiga_free_irq (unsigned int irq, void *dev_id);
+extern void amiga_free_irq (unsigned int irq, void *dev_id);
extern void amiga_enable_irq (unsigned int);
extern void amiga_disable_irq (unsigned int);
+static void amiga_get_model(char *model);
+static int amiga_get_hardware_list(char *buffer);
extern int amiga_get_irq_list (char *);
/* amiga specific timer functions */
-extern unsigned long amiga_gettimeoffset (void);
-extern void a3000_gettod (int *, int *, int *, int *, int *, int *);
-extern void a2000_gettod (int *, int *, int *, int *, int *, int *);
-extern int amiga_hwclk (int, struct hwclk_time *);
-extern int amiga_set_clock_mmss (unsigned long);
+static unsigned long amiga_gettimeoffset (void);
+static void a3000_gettod (int *, int *, int *, int *, int *, int *);
+static void a2000_gettod (int *, int *, int *, int *, int *, int *);
+static int amiga_hwclk (int, struct hwclk_time *);
+static int amiga_set_clock_mmss (unsigned long);
extern void amiga_mksound( unsigned int count, unsigned int ticks );
#ifdef CONFIG_BLK_DEV_FD
extern int amiga_floppy_init (void);
extern void amiga_floppy_setup(char *, int *);
#endif
-extern void amiga_reset (void);
-extern void amiga_waitbut(void);
+static void amiga_reset (void);
+static void amiga_wait_key(void);
extern struct consw fb_con;
extern struct fb_info *amiga_fb_init(long *);
extern void zorro_init(void);
-static void ami_savekmsg_init(void);
-static void ami_mem_print(const char *b);
-extern void amiga_debug_init(void);
+static void amiga_savekmsg_init(void);
+static void amiga_mem_console_write(const char *b, unsigned int count);
+static void amiga_serial_console_write(const char *s, unsigned int count);
+static void amiga_debug_init(void);
+
extern void amiga_video_setup(char *, int *);
+static struct console amiga_console_driver = {
+ NULL, NULL, amiga_wait_key
+};
+
extern void (*kd_mksound)(unsigned int, unsigned int);
+ /*
+ * Parse an Amiga-specific record in the bootinfo
+ */
+
+int amiga_parse_bootinfo(const struct bi_record *record)
+{
+ int unknown = 0;
+ const u_long *data = record->data;
+
+ switch (record->tag) {
+ case BI_AMIGA_MODEL:
+ amiga_model = *data;
+ break;
+
+ case BI_AMIGA_ECLOCK:
+ amiga_eclock = *data;
+ break;
+
+ case BI_AMIGA_CHIPSET:
+ amiga_chipset = *data;
+ break;
+
+ case BI_AMIGA_CHIP_SIZE:
+ amiga_chip_size = *(const int *)data;
+ break;
+
+ case BI_AMIGA_VBLANK:
+ amiga_vblank = *(const u_char *)data;
+ break;
+
+ case BI_AMIGA_PSFREQ:
+ amiga_psfreq = *(const u_char *)data;
+ break;
+
+ case BI_AMIGA_AUTOCON:
+ if (zorro_num_autocon < ZORRO_NUM_AUTO)
+ memcpy(&zorro_autocon[zorro_num_autocon++],
+ (const struct ConfigDev *)data,
+ sizeof(struct ConfigDev));
+ else
+ printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
+ break;
+
+ case BI_AMIGA_SERPER:
+ /* serial port period: ignored here */
+ break;
+
+ default:
+ unknown = 1;
+ }
+ return(unknown);
+}
+
+ /*
+ * Setup the Amiga configuration info
+ */
+
void config_amiga(void)
{
- char *type = NULL;
+ /* Fill in some default values, if necessary */
+ if (amiga_eclock == 0)
+ amiga_eclock = 709379;
+
+ memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
+
+ amiga_debug_init();
- switch(boot_info.bi_amiga.model) {
- case AMI_500:
- type = "A500";
- break;
- case AMI_500PLUS:
- type = "A500+";
- break;
- case AMI_600:
- type = "A600";
- break;
- case AMI_1000:
- type = "A1000";
- break;
- case AMI_1200:
- type = "A1200";
- break;
- case AMI_2000:
- type = "A2000";
- break;
- case AMI_2500:
- type = "A2500";
- break;
- case AMI_3000:
- type = "A3000";
- break;
- case AMI_3000T:
- type = "A3000T";
- break;
- case AMI_3000PLUS:
- type = "A3000+";
- break;
- case AMI_4000:
- type = "A4000";
- break;
- case AMI_4000T:
- type = "A4000T";
- break;
- case AMI_CDTV:
- type = "CDTV";
- break;
- case AMI_CD32:
- type = "CD32";
- break;
- case AMI_DRACO:
- type = "Draco";
- break;
- }
printk("Amiga hardware found: ");
- if (type)
- printk("[%s] ", type);
- switch(boot_info.bi_amiga.model) {
- case AMI_UNKNOWN:
- goto Generic;
+ if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
+ printk("[%s] ", amiga_models[amiga_model-AMI_500]);
- case AMI_500:
- case AMI_500PLUS:
- case AMI_1000:
- AMIGAHW_SET(A2000_CLK); /* Is this correct? */
- printk("A2000_CLK ");
+ switch(amiga_model) {
+ case AMI_UNKNOWN:
goto Generic;
case AMI_600:
case AMI_1200:
AMIGAHW_SET(A1200_IDE);
- printk("A1200_IDE ");
- AMIGAHW_SET(A2000_CLK); /* Is this correct? */
- printk("A2000_CLK ");
- goto Generic;
-
+ case AMI_500:
+ case AMI_500PLUS:
+ case AMI_1000:
case AMI_2000:
case AMI_2500:
- AMIGAHW_SET(A2000_CLK);
- printk("A2000_CLK ");
+ AMIGAHW_SET(A2000_CLK); /* Is this correct for all models? */
goto Generic;
case AMI_3000:
case AMI_3000T:
AMIGAHW_SET(AMBER_FF);
- printk("AMBER_FF ");
AMIGAHW_SET(MAGIC_REKICK);
- printk("MAGIC_REKICK ");
/* fall through */
case AMI_3000PLUS:
AMIGAHW_SET(A3000_SCSI);
- printk("A3000_SCSI ");
AMIGAHW_SET(A3000_CLK);
- printk("A3000_CLK ");
+ AMIGAHW_SET(ZORRO3);
goto Generic;
case AMI_4000T:
AMIGAHW_SET(A4000_SCSI);
- printk("A4000_SCSI ");
/* fall through */
case AMI_4000:
AMIGAHW_SET(A4000_IDE);
- printk("A4000_IDE ");
AMIGAHW_SET(A3000_CLK);
- printk("A3000_CLK ");
+ AMIGAHW_SET(ZORRO3);
goto Generic;
case AMI_CDTV:
case AMI_CD32:
AMIGAHW_SET(CD_ROM);
- printk("CD_ROM ");
AMIGAHW_SET(A2000_CLK); /* Is this correct? */
- printk("A2000_CLK ");
goto Generic;
Generic:
@@ -193,61 +214,49 @@ void config_amiga(void)
AMIGAHW_SET(AMI_PARALLEL);
AMIGAHW_SET(CHIP_RAM);
AMIGAHW_SET(PAULA);
- printk("VIDEO BLITTER AUDIO FLOPPY KEYBOARD MOUSE SERIAL PARALLEL "
- "CHIP_RAM PAULA ");
- switch(boot_info.bi_amiga.chipset) {
+ switch(amiga_chipset) {
case CS_OCS:
case CS_ECS:
case CS_AGA:
switch (custom.deniseid & 0xf) {
case 0x0c:
AMIGAHW_SET(DENISE_HR);
- printk("DENISE_HR ");
break;
case 0x08:
AMIGAHW_SET(LISA);
- printk("LISA ");
break;
}
break;
default:
AMIGAHW_SET(DENISE);
- printk("DENISE ");
break;
}
switch ((custom.vposr>>8) & 0x7f) {
case 0x00:
AMIGAHW_SET(AGNUS_PAL);
- printk("AGNUS_PAL ");
break;
case 0x10:
AMIGAHW_SET(AGNUS_NTSC);
- printk("AGNUS_NTSC ");
break;
case 0x20:
case 0x21:
AMIGAHW_SET(AGNUS_HR_PAL);
- printk("AGNUS_HR_PAL ");
break;
case 0x30:
case 0x31:
AMIGAHW_SET(AGNUS_HR_NTSC);
- printk("AGNUS_HR_NTSC ");
break;
case 0x22:
case 0x23:
AMIGAHW_SET(ALICE_PAL);
- printk("ALICE_PAL ");
break;
case 0x32:
case 0x33:
AMIGAHW_SET(ALICE_NTSC);
- printk("ALICE_NTSC ");
break;
}
AMIGAHW_SET(ZORRO);
- printk("ZORRO ");
break;
case AMI_DRACO:
@@ -256,8 +265,45 @@ void config_amiga(void)
default:
panic("Unknown Amiga Model");
}
+
+#define AMIGAHW_ANNOUNCE(name, str) \
+ if (AMIGAHW_PRESENT(name)) \
+ printk(str)
+
+ AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
+ AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
+ AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF ");
+ AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO ");
+ AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY ");
+ AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI ");
+ AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI ");
+ AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE ");
+ AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE ");
+ AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM ");
+ AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD ");
+ AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE ");
+ AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL ");
+ AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL ");
+ AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK ");
+ AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK ");
+ AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM ");
+ AMIGAHW_ANNOUNCE(PAULA, "PAULA ");
+ AMIGAHW_ANNOUNCE(DENISE, "DENISE ");
+ AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR ");
+ AMIGAHW_ANNOUNCE(LISA, "LISA ");
+ AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL ");
+ AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC ");
+ AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL ");
+ AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC ");
+ AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL ");
+ AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC ");
+ AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
+ if (AMIGAHW_SET(ZORRO))
+ printk("ZORRO%s ", AMIGAHW_SET(ZORRO3) ? "3" : "");
printk("\n");
-
+
+#undef AMIGAHW_ANNOUNCE
+
mach_sched_init = amiga_sched_init;
mach_keyb_init = amiga_keyb_init;
mach_kbdrate = amiga_kbdrate;
@@ -265,8 +311,10 @@ void config_amiga(void)
mach_default_handler = &amiga_default_handler;
mach_request_irq = amiga_request_irq;
mach_free_irq = amiga_free_irq;
- mach_enable_irq = amiga_enable_irq;
- mach_disable_irq = amiga_disable_irq;
+ enable_irq = amiga_enable_irq;
+ disable_irq = amiga_disable_irq;
+ mach_get_model = amiga_get_model;
+ mach_get_hardware_list = amiga_get_hardware_list;
mach_get_irq_list = amiga_get_irq_list;
mach_gettimeoffset = amiga_gettimeoffset;
if (AMIGAHW_PRESENT(A3000_CLK)){
@@ -288,22 +336,19 @@ void config_amiga(void)
mach_hwclk = amiga_hwclk;
mach_set_clock_mmss = amiga_set_clock_mmss;
- mach_mksound = amiga_mksound;
#ifdef CONFIG_BLK_DEV_FD
mach_floppy_init = amiga_floppy_init;
mach_floppy_setup = amiga_floppy_setup;
#endif
mach_reset = amiga_reset;
- waitbut = amiga_waitbut;
conswitchp = &fb_con;
mach_fb_init = amiga_fb_init;
- mach_debug_init = amiga_debug_init;
mach_video_setup = amiga_video_setup;
kd_mksound = amiga_mksound;
/* Fill in the clock values (based on the 700 kHz E-Clock) */
amiga_masterclock = 40*amiga_eclock; /* 28 MHz */
- amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */
+ amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */
/* clear all DMA bits */
custom.dmacon = DMAF_ALL;
@@ -313,10 +358,6 @@ void config_amiga(void)
/* initialize chipram allocator */
amiga_chip_init ();
- /* initialize only once here, not every time the debug level is raised */
- if (!strcmp( m68k_debug_device, "mem" ))
- ami_savekmsg_init();
-
/*
* if it is an A3000, set the magic bit that forces
* a hard rekick
@@ -335,7 +376,8 @@ void config_amiga(void)
static unsigned short jiffy_ticks;
-void amiga_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
+static void amiga_sched_init(void (*timer_routine)(int, void *,
+ struct pt_regs *))
{
jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
@@ -356,7 +398,7 @@ void amiga_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
#define TICK_SIZE 10000
/* This is always executed with interrupts disabled. */
-unsigned long amiga_gettimeoffset (void)
+static unsigned long amiga_gettimeoffset (void)
{
unsigned short hi, lo, hi2;
unsigned long ticks, offset = 0;
@@ -384,8 +426,8 @@ unsigned long amiga_gettimeoffset (void)
return ticks + offset;
}
-void a3000_gettod (int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp)
+static void a3000_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
{
volatile struct tod3000 *tod = TOD_3000;
@@ -401,8 +443,8 @@ void a3000_gettod (int *yearp, int *monp, int *dayp,
tod->cntrl1 = TOD3000_CNTRL1_FREE;
}
-void a2000_gettod (int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp)
+static void a2000_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
{
volatile struct tod2000 *tod = TOD_2000;
@@ -427,7 +469,7 @@ void a2000_gettod (int *yearp, int *monp, int *dayp,
tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
}
-int amiga_hwclk(int op, struct hwclk_time *t)
+static int amiga_hwclk(int op, struct hwclk_time *t)
{
if (AMIGAHW_PRESENT(A3000_CLK)) {
volatile struct tod3000 *tod = TOD_3000;
@@ -511,7 +553,7 @@ int amiga_hwclk(int op, struct hwclk_time *t)
return 0;
}
-int amiga_set_clock_mmss (unsigned long nowtime)
+static int amiga_set_clock_mmss (unsigned long nowtime)
{
short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
@@ -545,7 +587,7 @@ int amiga_set_clock_mmss (unsigned long nowtime)
return 0;
}
-void amiga_waitbut (void)
+static void amiga_wait_key (void)
{
int i;
@@ -571,33 +613,6 @@ void amiga_waitbut (void)
}
}
-void ami_serial_print (const char *str)
-{
- while (*str) {
- if (*str == '\n') {
- custom.serdat = (unsigned char)'\r' | 0x100;
- while (!(custom.serdatr & 0x2000))
- ;
- }
- custom.serdat = (unsigned char)*str++ | 0x100;
- while (!(custom.serdatr & 0x2000))
- ;
- }
-}
-
-void amiga_debug_init (void)
-{
- extern void (*debug_print_proc)(const char *);
-
- if (!strcmp( m68k_debug_device, "ser" )) {
- /* no initialization required (?) */
- debug_print_proc = ami_serial_print;
- } else if (!strcmp( m68k_debug_device, "mem" )) {
- /* already initialized by config_amiga() (needed only once) */
- debug_print_proc = ami_mem_print;
- }
-}
-
void dbprintf(const char *fmt , ...)
{
static char buf[1024];
@@ -612,10 +627,10 @@ void dbprintf(const char *fmt , ...)
console_print (buf);
}
-NORET_TYPE void amiga_reset( void )
+static NORET_TYPE void amiga_reset( void )
ATTRIB_NORET;
-void amiga_reset (void)
+static void amiga_reset (void)
{
unsigned long jmp_addr040 = VTOP(&&jmp_addr_label040);
unsigned long jmp_addr = VTOP(&&jmp_addr_label);
@@ -629,8 +644,10 @@ void amiga_reset (void)
("movel %0,%/d0\n\t"
"andl #0xff000000,%/d0\n\t"
"orw #0xe020,%/d0\n\t" /* map 16 MB, enable, cacheable */
- ".long 0x4e7b0004\n\t" /* movec d0,itt0 */
- ".long 0x4e7b0006\n\t" /* movec d0,dtt0 */
+ ".chip 68040\n\t"
+ "movec %%d0,%%itt0\n\t"
+ "movec %%d0,%%dtt0\n\t"
+ ".chip 68k\n\t"
"jmp %0@\n\t"
: /* no outputs */
: "a" (jmp_addr040));
@@ -649,7 +666,9 @@ void amiga_reset (void)
/* disable translation on '040 now */
__asm__ __volatile__
("moveq #0,%/d0\n\t"
- ".long 0x4e7b0003\n\t" /* movec d0,tc; disable MMU */
+ ".chip 68040\n\t"
+ "movec %%d0,%%tc\n\t" /* disable MMU */
+ ".chip 68k\n\t"
: /* no outputs */
: /* no inputs */
: "d0");
@@ -675,12 +694,13 @@ void amiga_reset (void)
}
-extern void *amiga_chip_alloc(long size);
+ /*
+ * Debugging
+ */
#define SAVEKMSG_MAXMEM 128*1024
-
#define SAVEKMSG_MAGIC1 0x53415645 /* 'SAVE' */
#define SAVEKMSG_MAGIC2 0x4B4D5347 /* 'KMSG' */
@@ -694,8 +714,15 @@ struct savekmsg {
static struct savekmsg *savekmsg = NULL;
+static void amiga_mem_console_write(const char *s, unsigned int count)
+{
+ if (savekmsg->size+count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
+ memcpy(savekmsg->data+savekmsg->size, s, count);
+ savekmsg->size += count;
+ }
+}
-static void ami_savekmsg_init(void)
+static void amiga_savekmsg_init(void)
{
savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM);
savekmsg->magic1 = SAVEKMSG_MAGIC1;
@@ -704,84 +731,107 @@ static void ami_savekmsg_init(void)
savekmsg->size = 0;
}
-
-static void ami_mem_print(const char *b)
+static void amiga_serial_putc(char c)
{
- int len;
+ custom.serdat = (unsigned char)c | 0x100;
+ while (!(custom.serdatr & 0x2000))
+ ;
+}
- for (len = 0; b[len]; len++);
- if (savekmsg->size+len <= SAVEKMSG_MAXMEM) {
- memcpy(savekmsg->data+savekmsg->size, b, len);
- savekmsg->size += len;
+static void amiga_serial_console_write(const char *s, unsigned int count)
+{
+ while (count--) {
+ if (*s == '\n')
+ amiga_serial_putc('\r');
+ amiga_serial_putc(*s++);
}
}
+#ifdef CONFIG_SERIAL_CONSOLE
+void amiga_serial_puts(const char *s)
+{
+ amiga_serial_console_write(s, strlen(s));
+}
-void amiga_get_model(char *model)
+void amiga_serial_gets(char *s, int len)
{
- strcpy(model, "Amiga ");
- switch (boot_info.bi_amiga.model) {
- case AMI_500:
- strcat(model, "500");
- break;
- case AMI_500PLUS:
- strcat(model, "500+");
- break;
- case AMI_600:
- strcat(model, "600");
- break;
- case AMI_1000:
- strcat(model, "1000");
- break;
- case AMI_1200:
- strcat(model, "1200");
- break;
- case AMI_2000:
- strcat(model, "2000");
- break;
- case AMI_2500:
- strcat(model, "2500");
- break;
- case AMI_3000:
- strcat(model, "3000");
- break;
- case AMI_3000T:
- strcat(model, "3000T");
- break;
- case AMI_3000PLUS:
- strcat(model, "3000+");
- break;
- case AMI_4000:
- strcat(model, "4000");
- break;
- case AMI_4000T:
- strcat(model, "4000T");
- break;
- case AMI_CDTV:
- strcat(model, "CDTV");
- break;
- case AMI_CD32:
- strcat(model, "CD32");
- break;
- case AMI_DRACO:
- strcpy(model, "DRACO");
+ int ch, cnt = 0;
+
+ while (1) {
+ while (!(custom.intreqr & IF_RBF))
+ barrier();
+ ch = custom.serdatr & 0xff;
+ /* clear the interrupt, so that another character can be read */
+ custom.intreq = IF_RBF;
+
+ /* Check for backspace. */
+ if (ch == 8 || ch == 127) {
+ if (cnt == 0) {
+ amiga_serial_putc('\007');
+ continue;
+ }
+ cnt--;
+ amiga_serial_puts("\010 \010");
+ continue;
+ }
+
+ /* Check for enter. */
+ if (ch == 10 || ch == 13)
break;
+
+ /* See if line is too long. */
+ if (cnt >= len + 1) {
+ amiga_serial_putc(7);
+ cnt--;
+ continue;
+ }
+
+ /* Store and echo character. */
+ s[cnt++] = ch;
+ amiga_serial_putc(ch);
+ }
+ /* Print enter. */
+ amiga_serial_puts("\r\n");
+ s[cnt] = 0;
+}
+#endif
+
+static void amiga_debug_init(void)
+{
+ if (!strcmp( m68k_debug_device, "ser" )) {
+ /* no initialization required (?) */
+ amiga_console_driver.write = amiga_serial_console_write;
+ } else if (!strcmp( m68k_debug_device, "mem" )) {
+ amiga_savekmsg_init();
+ amiga_console_driver.write = amiga_mem_console_write;
}
+ register_console(&amiga_console_driver);
}
-int amiga_get_hardware_list(char *buffer)
+ /*
+ * Amiga specific parts of /proc
+ */
+
+static void amiga_get_model(char *model)
+{
+ strcpy(model, "Amiga ");
+ if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
+ strcat(model, amiga_models[amiga_model-AMI_500]);
+}
+
+
+static int amiga_get_hardware_list(char *buffer)
{
int len = 0;
if (AMIGAHW_PRESENT(CHIP_RAM))
- len += sprintf(buffer+len, "Chip RAM:\t%ldK\n",
- boot_info.bi_amiga.chip_size>>10);
+ len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10);
len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
- boot_info.bi_amiga.psfreq, amiga_eclock);
+ amiga_psfreq, amiga_eclock);
if (AMIGAHW_PRESENT(AMI_VIDEO)) {
char *type;
- switch(boot_info.bi_amiga.chipset) {
+ switch(amiga_chipset) {
case CS_OCS:
type = "OCS";
break;
@@ -798,7 +848,7 @@ int amiga_get_hardware_list(char *buffer)
len += sprintf(buffer+len, "Graphics:\t%s\n", type);
}
-#define AMIGAHW_ANNOUNCE(name, str) \
+#define AMIGAHW_ANNOUNCE(name, str) \
if (AMIGAHW_PRESENT(name)) \
len += sprintf (buffer+len, "\t%s\n", str)
@@ -833,9 +883,11 @@ int amiga_get_hardware_list(char *buffer)
AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
if (AMIGAHW_PRESENT(ZORRO))
- len += sprintf(buffer+len, "\tZorro AutoConfig: %d Expansion Device%s\n",
- boot_info.bi_amiga.num_autocon,
- boot_info.bi_amiga.num_autocon == 1 ? "" : "s");
+ len += sprintf(buffer+len, "\tZorro%s AutoConfig: %d Expansion Device%s\n",
+ AMIGAHW_PRESENT(ZORRO3) ? " III" : "",
+ zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
+
+#undef AMIGAHW_ANNOUNCE
return(len);
}
diff --git a/arch/m68k/amiga/cyberfb.c b/arch/m68k/amiga/cyberfb.c
index dc2515371..d74d52c4f 100644
--- a/arch/m68k/amiga/cyberfb.c
+++ b/arch/m68k/amiga/cyberfb.c
@@ -32,7 +32,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/irq.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
#include <asm/pgtable.h>
#include <linux/fb.h>
#include "s3blit.h"
@@ -235,6 +235,7 @@ struct fb_info *Cyber_fb_init(long *mem_start); /* Through amiga_fb_init() */
static int Cyberfb_switch(int con);
static int Cyberfb_updatevar(int con);
static void Cyberfb_blank(int blank);
+static int Cyberfb_setcmap(struct fb_cmap *cmap, int con);
/*
@@ -424,6 +425,7 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
fix->xpanstep = 0;
fix->ypanstep = 0;
fix->ywrapstep = 0;
+ fix->line_length = 0;
for (i = 0; i < arraysize(fix->reserved); i++)
fix->reserved[i] = 0;
@@ -896,10 +898,10 @@ static void memcpy_fs(int fsfromto, void *to, void *from, int len)
memcpy(to, from, len);
return;
case 1:
- memcpy_fromfs(to, from, len);
+ copy_from_user(to, from, len);
return;
case 2:
- memcpy_tofs(to, from, len);
+ copy_to_user(to, from, len);
return;
}
}
@@ -1178,6 +1180,7 @@ struct fb_info *Cyber_fb_init(long *mem_start)
fb_info.switch_con = &Cyberfb_switch;
fb_info.updatevar = &Cyberfb_updatevar;
fb_info.blank = &Cyberfb_blank;
+ fb_info.setcmap = &Cyberfb_setcmap;
do_fb_set_var(&Cyber_fb_predefined[0], 1);
Cyber_fb_get_var(&disp[0].var, -1);
@@ -1225,6 +1228,16 @@ static void Cyberfb_blank(int blank)
/*
+ * Set the colormap
+ */
+
+static int Cyberfb_setcmap(struct fb_cmap *cmap, int con)
+{
+ return(Cyber_fb_set_cmap(cmap, 1, con));
+}
+
+
+ /*
* Get a Video Mode
*/
diff --git a/arch/m68k/amiga/ksyms.c b/arch/m68k/amiga/ksyms.c
deleted file mode 100644
index b306867c1..000000000
--- a/arch/m68k/amiga/ksyms.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <linux/module.h>
-#include <asm/zorro.h>
-#include <asm/amigatypes.h>
-#include <asm/amigahw.h>
-#include <asm/amigatypes.h>
-
-extern volatile u_short amiga_audio_min_period;
-extern u_short amiga_audio_period;
-
-static struct symbol_table mach_amiga_symbol_table = {
-#include <linux/symtab_begin.h>
-
- /*
- * Add things here when you find the need for it.
- */
- X(amiga_colorclock),
- X(amiga_chip_alloc),
- X(amiga_chip_free),
- X(amiga_chip_avail),
- X(amiga_audio_period),
- X(amiga_audio_min_period),
-
- X(zorro_find),
- X(zorro_get_board),
- X(zorro_config_board),
- X(zorro_unconfig_board),
- X(zorro_unused_z2ram),
-
- /* example
- X(something_you_need),
- */
-
-
-#include <linux/symtab_end.h>
-};
-
-void mach_amiga_syms_export(void)
-{
- register_symtab(&mach_amiga_symbol_table);
-}
diff --git a/arch/m68k/amiga/retz3fb.c b/arch/m68k/amiga/retz3fb.c
new file mode 100644
index 000000000..4885e48f7
--- /dev/null
+++ b/arch/m68k/amiga/retz3fb.c
@@ -0,0 +1,3504 @@
+/*
+ * Linux/arch/m68k/amiga/retz3fb.c -- Low level implementation of the
+ * RetinaZ3 frame buffer device
+ *
+ * Copyright (C) 1997 Jes Sorensen
+ *
+ * This file is based on the CyberVision64 frame buffer device and
+ * the generic Cirrus Logic driver.
+ *
+ * cyberfb.c: Copyright (C) 1996 Martin Apel,
+ * Geert Uytterhoeven
+ * clgen.c: Copyright (C) 1996 Frank Neumann
+ *
+ * History:
+ * - 22 Jan 97: Initial work
+ * - 14 Feb 97: Screen initialization works somewhat, still only
+ * 8-bit packed pixel is supported.
+ *
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <linux/zorro.h>
+#include <asm/pgtable.h>
+
+#include "retz3fb.h"
+
+/* #define DEBUG if(1) */
+#define DEBUG if(0)
+
+/*
+ * Reserve space for one pattern line.
+ *
+ * For the time being we only support 4MB boards!
+ */
+
+#define PAT_MEM_SIZE 16*3
+#define PAT_MEM_OFF (4*1024*1024 - PAT_MEM_SIZE)
+
+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
+
+struct retz3_fb_par {
+ int xres;
+ int yres;
+ int xres_vir;
+ int yres_vir;
+ int xoffset;
+ int yoffset;
+ int bpp;
+
+ struct fb_bitfield red;
+ struct fb_bitfield green;
+ struct fb_bitfield blue;
+ struct fb_bitfield transp;
+
+ int pixclock;
+ int left_margin; /* time from sync to picture */
+ int right_margin; /* time from picture to sync */
+ int upper_margin; /* time from sync to picture */
+ int lower_margin;
+ int hsync_len; /* length of horizontal sync */
+ int vsync_len; /* length of vertical sync */
+ int vmode;
+};
+
+struct display_data {
+ long h_total; /* Horizontal Total */
+ long h_sstart; /* Horizontal Sync Start */
+ long h_sstop; /* Horizontal Sync Stop */
+ long h_bstart; /* Horizontal Blank Start */
+ long h_bstop; /* Horizontal Blank Stop */
+ long h_dispend; /* Horizontal Display End */
+ long v_total; /* Vertical Total */
+ long v_sstart; /* Vertical Sync Start */
+ long v_sstop; /* Vertical Sync Stop */
+ long v_bstart; /* Vertical Blank Start */
+ long v_bstop; /* Vertical Blank Stop */
+ long v_dispend; /* Horizontal Display End */
+};
+
+static struct retz3_fb_par current_par;
+
+static int current_par_valid = 0;
+static int currcon = 0;
+
+static struct display disp[MAX_NR_CONSOLES];
+static struct fb_info fb_info;
+
+static int node; /* node of the /dev/fb?current file */
+
+
+/*
+ * Switch for Chipset Independency
+ */
+
+static struct fb_hwswitch {
+
+ /* Initialisation */
+
+ int (*init)(void);
+
+ /* Display Control */
+
+ int (*encode_fix)(struct fb_fix_screeninfo *fix, struct retz3_fb_par *par);
+ int (*decode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par);
+ int (*encode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par);
+ int (*getcolreg)(unsigned int regno, unsigned int *red, unsigned
+ int *green, unsigned int *blue, unsigned int *transp);
+ int (*setcolreg)(unsigned int regno, unsigned int red, unsigned int
+ green, unsigned int blue, unsigned int transp);
+ void (*blank)(int blank);
+} *fbhw;
+
+
+/*
+ * Frame Buffer Name
+ */
+
+static char retz3_fb_name[16] = "RetinaZ3";
+
+
+static int z3_key = 0;
+static unsigned char retz3_color_table [256][4];
+static unsigned long z3_mem;
+static unsigned long z3_fbmem;
+static unsigned long z3_size;
+static volatile unsigned char *z3_regs;
+
+static long *memstart;
+
+
+/*
+ * Predefined Video Mode Names
+ */
+
+static char *retz3_fb_modenames[] = {
+
+ /*
+ * Autodetect (Default) Video Mode
+ */
+
+ "default",
+
+ /*
+ * Predefined Video Modes
+ */
+
+ "640x480", /* RetinaZ3 8 bpp */
+ "800x600", /* RetinaZ3 8 bpp */
+ "1024x768i",
+ "640x480-16", /* RetinaZ3 16 bpp */
+ "640x480-24", /* RetinaZ3 24 bpp */
+
+ /*
+ * Dummy Video Modes
+ */
+
+ "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+ "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+ "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+
+ /*
+ * User Defined Video Modes
+ *
+ * This doesn't work yet!!
+ */
+
+ "user0", "user1", "user2", "user3",
+ "user4", "user5", "user6", "user7"
+};
+
+/*
+ * A small info on how to convert XFree86 timing values into fb
+ * timings - by Frank Neumann:
+ *
+An XFree86 mode line consists of the following fields:
+ "800x600" 50 800 856 976 1040 600 637 643 666
+ < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL
+
+The fields in the fb_var_screeninfo structure are:
+ unsigned long pixclock; * pixel clock in ps (pico seconds) *
+ unsigned long left_margin; * time from sync to picture *
+ unsigned long right_margin; * time from picture to sync *
+ unsigned long upper_margin; * time from sync to picture *
+ unsigned long lower_margin;
+ unsigned long hsync_len; * length of horizontal sync *
+ unsigned long vsync_len; * length of vertical sync *
+
+1) Pixelclock:
+ xfree: in MHz
+ fb: In Picoseconds (ps)
+
+ pixclock = 1000000 / DCF
+
+2) horizontal timings:
+ left_margin = HFL - SH2
+ right_margin = SH1 - HR
+ hsync_len = SH2 - SH1
+
+3) vertical timings:
+ upper_margin = VFL - SV2
+ lower_margin = SV1 - VR
+ vsync_len = SV2 - SV1
+
+Good examples for VESA timings can be found in the XFree86 source tree,
+under "programs/Xserver/hw/xfree86/doc/modeDB.txt".
+*/
+
+/*
+ * Predefined Video Mode Definitions
+ */
+
+static struct fb_var_screeninfo retz3_fb_predefined[] = {
+
+ /*
+ * Autodetect (Default) Video Mode
+ */
+
+ { 0, },
+
+ /*
+ * Predefined Video Modes
+ */
+
+ /*
+ * NB: it is very important to adjust the pixel-clock to the color-depth.
+ */
+
+ {
+ 640, 480, 640, 480, 0, 0, 8, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461, 28, 32, 12, 10, 96, 2,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ },
+ /*
+ ModeLine "800x600" 36 800 824 896 1024 600 601 603 625
+ < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL
+ */
+ {
+ /* 800 x 600, 8 bpp */
+ 800, 600, 800, 600, 0, 0, 8, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 27778, 64, 24, 22, 1, 120, 2,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ },
+ /*
+ ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace
+ < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL
+ */
+ {
+ /* 1024 x 768, 8 bpp, interlaced */
+ 1024, 768, 1024, 768, 0, 0, 8, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 22222, 40, 40, 32, 9, 160, 8,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED
+ },
+ {
+ 640, 480, 640, 480, 0, 0, 16, 0,
+ {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/2, 28, 32, 12, 10, 96, 2,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ },
+ {
+ 640, 480, 640, 480, 0, 0, 24, 0,
+ {8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/3, 28, 32, 12, 10, 96, 2,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ },
+
+ /*
+ * Dummy Video Modes
+ */
+
+ { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+ { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+ { 0, }, { 0, },
+
+ /*
+ * User Defined Video Modes
+ */
+
+ { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
+};
+
+
+#define NUM_TOTAL_MODES arraysize(retz3_fb_predefined)
+#define NUM_PREDEF_MODES (5)
+
+
+static int z3fb_inverse = 0;
+static int z3fb_mode = 0;
+
+
+/*
+ * Interface used by the world
+ */
+
+int retz3_probe(void);
+void retz3_video_setup(char *options, int *ints);
+
+static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con);
+static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con);
+
+
+/*
+ * Interface to the low level console driver
+ */
+
+struct fb_info *retz3_fb_init(long *mem_start); /* Through amiga_fb_init() */
+static int z3fb_switch(int con);
+static int z3fb_updatevar(int con);
+static void z3fb_blank(int blank);
+static int z3fb_setcmap(struct fb_cmap *cmap, int con);
+
+
+/*
+ * Accelerated Functions used by the low level console driver
+ */
+
+void retz3_bitblt(struct fb_var_screeninfo *scr,
+ unsigned short curx, unsigned short cury, unsigned
+ short destx, unsigned short desty, unsigned short
+ width, unsigned short height, unsigned short cmd,
+ unsigned short mask);
+void retz3_fill(unsigned short x, unsigned short y, unsigned short
+ width, unsigned short height, unsigned short mode,
+ unsigned short color);
+
+/*
+ * Hardware Specific Routines
+ */
+
+static int retz3_init(void);
+static int retz3_encode_fix(struct fb_fix_screeninfo *fix,
+ struct retz3_fb_par *par);
+static int retz3_decode_var(struct fb_var_screeninfo *var,
+ struct retz3_fb_par *par);
+static int retz3_encode_var(struct fb_var_screeninfo *var,
+ struct retz3_fb_par *par);
+static int retz3_getcolreg(unsigned int regno, unsigned int *red,
+ unsigned int *green, unsigned int *blue,
+ unsigned int *transp);
+static int retz3_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp);
+static void retz3_blank(int blank);
+
+
+/*
+ * Internal routines
+ */
+
+static void retz3_fb_get_par(struct retz3_fb_par *par);
+static void retz3_fb_set_par(struct retz3_fb_par *par);
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
+static struct fb_cmap *get_default_colormap(int bpp);
+static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+ int kspc);
+static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+ int kspc);
+static void do_install_cmap(int con);
+static void memcpy_fs(int fsfromto, void *to, void *from, int len);
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
+static void retz3_fb_set_disp(int con);
+static int get_video_mode(const char *name);
+
+
+/* -------------------- Hardware specific routines -------------------------- */
+
+static unsigned short find_fq(unsigned int freq)
+{
+ unsigned long f;
+ long tmp;
+ long prev = 0x7fffffff;
+ long n2, n1 = 3;
+ unsigned long m;
+ unsigned short res = 0;
+
+ if (freq <= 31250000)
+ n2 = 3;
+ else if (freq <= 62500000)
+ n2 = 2;
+ else if (freq <= 125000000)
+ n2 = 1;
+ else if (freq <= 250000000)
+ n2 = 0;
+ else
+ return(0);
+
+
+ do {
+ f = freq >> (10 - n2);
+
+ m = (f * n1) / (14318180/1024);
+
+ if (m > 129)
+ break;
+
+ tmp = (((m * 14318180) >> n2) / n1) - freq;
+ if (tmp < 0)
+ tmp = -tmp;
+
+ if (tmp < prev) {
+ prev = tmp;
+ res = (((n2 << 5) | (n1-2)) << 8) | (m-2);
+ }
+
+ } while ( (++n1) <= 21);
+
+ return res;
+}
+
+
+static int retz3_set_video(struct fb_var_screeninfo *var,
+ struct retz3_fb_par *par)
+{
+ float freq_f;
+ long freq;
+
+ int xres, hfront, hsync, hback;
+ int yres, vfront, vsync, vback;
+ unsigned char tmp;
+ unsigned short best_freq;
+ struct display_data data;
+
+ short clocksel = 0; /* Apparantly this is always zero */
+
+ int bpp = var->bits_per_pixel;
+
+ /*
+ * XXX
+ */
+ if (bpp == 24)
+ return 0;
+
+ if ((bpp != 8) && (bpp != 16) && (bpp != 24))
+ return -EFAULT;
+
+ par->xoffset = 0;
+ par->yoffset = 0;
+
+ xres = var->xres * bpp / 4;
+ hfront = var->right_margin * bpp / 4;
+ hsync = var->hsync_len * bpp / 4;
+ hback = var->left_margin * bpp / 4;
+
+ if (var->vmode & FB_VMODE_DOUBLE)
+ {
+ yres = var->yres * 2;
+ vfront = var->lower_margin * 2;
+ vsync = var->vsync_len * 2;
+ vback = var->upper_margin * 2;
+ }
+ else if (var->vmode & FB_VMODE_INTERLACED)
+ {
+ yres = (var->yres + 1) / 2;
+ vfront = (var->lower_margin + 1) / 2;
+ vsync = (var->vsync_len + 1) / 2;
+ vback = (var->upper_margin + 1) / 2;
+ }
+ else
+ {
+ yres = var->yres; /* -1 ? */
+ vfront = var->lower_margin;
+ vsync = var->vsync_len;
+ vback = var->upper_margin;
+ }
+
+ data.h_total = (hback / 8) + (xres / 8)
+ + (hfront / 8) + (hsync / 8) - 1 /* + 1 */;
+ data.h_dispend = ((xres + bpp - 1)/ 8) - 1;
+ data.h_bstart = xres / 8 /* + 1 */;
+
+ data.h_bstop = data.h_total+1 + 2 + 1;
+ data.h_sstart = (xres / 8) + (hfront / 8) + 1;
+ data.h_sstop = (xres / 8) + (hfront / 8) + (hsync / 8) + 1;
+
+ data.v_total = yres + vfront + vsync + vback - 1;
+
+ data.v_dispend = yres - 1;
+ data.v_bstart = yres;
+
+ data.v_bstop = data.v_total;
+ data.v_sstart = yres + vfront - 1 - 2;
+ data.v_sstop = yres + vfront + vsync - 1;
+
+#if 0 /* testing */
+
+ printk("HBS: %i\n", data.h_bstart);
+ printk("HSS: %i\n", data.h_sstart);
+ printk("HSE: %i\n", data.h_sstop);
+ printk("HBE: %i\n", data.h_bstop);
+ printk("HT: %i\n", data.h_total);
+
+ printk("hsync: %i\n", hsync);
+ printk("hfront: %i\n", hfront);
+ printk("hback: %i\n", hback);
+
+ printk("VBS: %i\n", data.v_bstart);
+ printk("VSS: %i\n", data.v_sstart);
+ printk("VSE: %i\n", data.v_sstop);
+ printk("VBE: %i\n", data.v_bstop);
+ printk("VT: %i\n", data.v_total);
+
+ printk("vsync: %i\n", vsync);
+ printk("vfront: %i\n", vfront);
+ printk("vback: %i\n", vback);
+#endif
+
+ if (data.v_total >= 1024)
+ printk("MAYDAY: v_total >= 1024; bailing out!\n");
+
+ reg_w(GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04));
+ reg_w(GREG_FEATURE_CONTROL_W, 0x00);
+
+ seq_w(SEQ_RESET, 0x00);
+ seq_w(SEQ_RESET, 0x03); /* reset sequencer logic */
+
+ /*
+ * CLOCKING_MODE bits:
+ * 2: This one is only set for certain text-modes, wonder if
+ * it may be for EGA-lines? (it was referred to as CLKDIV2)
+ * (The CL drivers sets it to 0x21 with the comment:
+ * FullBandwidth (video off) and 8/9 dot clock)
+ */
+ seq_w(SEQ_CLOCKING_MODE, 0x01 | 0x00 /* 0x08 */);
+
+ seq_w(SEQ_MAP_MASK, 0x0f); /* enable writing to plane 0-3 */
+ seq_w(SEQ_CHAR_MAP_SELECT, 0x00); /* doesn't matter in gfx-mode */
+ seq_w(SEQ_MEMORY_MODE, 0x06); /* CL driver says 0x0e for 256 col mode*/
+ seq_w(SEQ_RESET, 0x01);
+ seq_w(SEQ_RESET, 0x03);
+
+ seq_w(SEQ_EXTENDED_ENABLE, 0x05);
+
+ seq_w(SEQ_CURSOR_CONTROL, 0x00); /* disable cursor */
+ seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00);
+ seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00);
+ seq_w(SEQ_LINEAR_0, 0x4a);
+ seq_w(SEQ_LINEAR_1, 0x00);
+
+ seq_w(SEQ_SEC_HOST_OFF_HI, 0x00);
+ seq_w(SEQ_SEC_HOST_OFF_LO, 0x00);
+ seq_w(SEQ_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
+
+ /*
+ * The lower 4 bits (0-3) are used to set the font-width for
+ * text-mode - DON'T try to set this for gfx-mode.
+ */
+ seq_w(SEQ_EXT_CLOCK_MODE, 0x10);
+ seq_w(SEQ_EXT_VIDEO_ADDR, 0x03);
+
+ /*
+ * Extended Pixel Control:
+ * bit 0: text-mode=0, gfx-mode=1 (Graphics Byte ?)
+ * bit 1: (Packed/Nibble Pixel Format ?)
+ * bit 4-5: depth, 0=1-8bpp, 1=9-16bpp, 2=17-24bpp
+ */
+ seq_w(SEQ_EXT_PIXEL_CNTL, 0x01 | (((bpp / 8) - 1) << 4));
+
+ seq_w(SEQ_BUS_WIDTH_FEEDB, 0x04);
+ seq_w(SEQ_COLOR_EXP_WFG, 0x01);
+ seq_w(SEQ_COLOR_EXP_WBG, 0x00);
+ seq_w(SEQ_EXT_RW_CONTROL, 0x00);
+ seq_w(SEQ_MISC_FEATURE_SEL, (0x51 | (clocksel & 8)));
+ seq_w(SEQ_COLOR_KEY_CNTL, 0x40);
+ seq_w(SEQ_COLOR_KEY_MATCH0, 0x00);
+ seq_w(SEQ_COLOR_KEY_MATCH1, 0x00);
+ seq_w(SEQ_COLOR_KEY_MATCH2, 0x00);
+ seq_w(SEQ_CRC_CONTROL, 0x00);
+ seq_w(SEQ_PERF_SELECT, 0x10);
+ seq_w(SEQ_ACM_APERTURE_1, 0x00);
+ seq_w(SEQ_ACM_APERTURE_2, 0x30);
+ seq_w(SEQ_ACM_APERTURE_3, 0x00);
+ seq_w(SEQ_MEMORY_MAP_CNTL, 0x03);
+
+
+ /* unlock register CRT0..CRT7 */
+ crt_w(CRT_END_VER_RETR, (data.v_sstop & 0x0f) | 0x20);
+
+ /* Zuerst zu schreibende Werte nur per printk ausgeben */
+ DEBUG printk("CRT_HOR_TOTAL: %ld\n", data.h_total);
+ crt_w(CRT_HOR_TOTAL, data.h_total & 0xff);
+
+ DEBUG printk("CRT_HOR_DISP_ENA_END: %ld\n", data.h_dispend);
+ crt_w(CRT_HOR_DISP_ENA_END, (data.h_dispend) & 0xff);
+
+ DEBUG printk("CRT_START_HOR_BLANK: %ld\n", data.h_bstart);
+ crt_w(CRT_START_HOR_BLANK, data.h_bstart & 0xff);
+
+ DEBUG printk("CRT_END_HOR_BLANK: 128+%ld\n", data.h_bstop % 32);
+ crt_w(CRT_END_HOR_BLANK, 0x80 | (data.h_bstop & 0x1f));
+
+ DEBUG printk("CRT_START_HOR_RETR: %ld\n", data.h_sstart);
+ crt_w(CRT_START_HOR_RETR, data.h_sstart & 0xff);
+
+ tmp = (data.h_sstop & 0x1f);
+ if (data.h_bstop & 0x20)
+ tmp |= 0x80;
+ DEBUG printk("CRT_END_HOR_RETR: %d\n", tmp);
+ crt_w(CRT_END_HOR_RETR, tmp);
+
+ DEBUG printk("CRT_VER_TOTAL: %ld\n", data.v_total & 0xff);
+ crt_w(CRT_VER_TOTAL, (data.v_total & 0xff));
+
+ tmp = 0x10; /* LineCompare bit #9 */
+ if (data.v_total & 256)
+ tmp |= 0x01;
+ if (data.v_dispend & 256)
+ tmp |= 0x02;
+ if (data.v_sstart & 256)
+ tmp |= 0x04;
+ if (data.v_bstart & 256)
+ tmp |= 0x08;
+ if (data.v_total & 512)
+ tmp |= 0x20;
+ if (data.v_dispend & 512)
+ tmp |= 0x40;
+ if (data.v_sstart & 512)
+ tmp |= 0x80;
+ DEBUG printk("CRT_OVERFLOW: %d\n", tmp);
+ crt_w(CRT_OVERFLOW, tmp);
+
+ crt_w(CRT_PRESET_ROW_SCAN, 0x00); /* not CL !!! */
+
+ tmp = 0x40; /* LineCompare bit #8 */
+ if (data.v_bstart & 512)
+ tmp |= 0x20;
+ if (var->vmode & FB_VMODE_DOUBLE)
+ tmp |= 0x80;
+ DEBUG printk("CRT_MAX_SCAN_LINE: %d\n", tmp);
+ crt_w(CRT_MAX_SCAN_LINE, tmp);
+
+ crt_w(CRT_CURSOR_START, 0x00);
+ crt_w(CRT_CURSOR_END, 8 & 0x1f); /* font height */
+
+ crt_w(CRT_START_ADDR_HIGH, 0x00);
+ crt_w(CRT_START_ADDR_LOW, 0x00);
+
+ crt_w(CRT_CURSOR_LOC_HIGH, 0x00);
+ crt_w(CRT_CURSOR_LOC_LOW, 0x00);
+
+ DEBUG printk("CRT_START_VER_RETR: %ld\n", data.v_sstart & 0xff);
+ crt_w(CRT_START_VER_RETR, (data.v_sstart & 0xff));
+
+#if 1
+ /* 5 refresh cycles per scanline */
+ DEBUG printk("CRT_END_VER_RETR: 64+32+%ld\n", data.v_sstop % 16);
+ crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 0x40 | 0x20));
+#else
+ DEBUG printk("CRT_END_VER_RETR: 128+32+%ld\n", data.v_sstop % 16);
+ crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 128 | 32));
+#endif
+ DEBUG printk("CRT_VER_DISP_ENA_END: %ld\n", data.v_dispend & 0xff);
+ crt_w(CRT_VER_DISP_ENA_END, (data.v_dispend & 0xff));
+
+ DEBUG printk("CRT_START_VER_BLANK: %ld\n", data.v_bstart & 0xff);
+ crt_w(CRT_START_VER_BLANK, (data.v_bstart & 0xff));
+
+ DEBUG printk("CRT_END_VER_BLANK: %ld\n", data.v_bstop & 0xff);
+ crt_w(CRT_END_VER_BLANK, (data.v_bstop & 0xff));
+
+ DEBUG printk("CRT_MODE_CONTROL: 0xe3\n");
+ crt_w(CRT_MODE_CONTROL, 0xe3);
+
+ DEBUG printk("CRT_LINE_COMPARE: 0xff\n");
+ crt_w(CRT_LINE_COMPARE, 0xff);
+
+ tmp = (var->xres_virtual / 8) * (bpp / 8);
+ crt_w(CRT_OFFSET, tmp);
+
+ crt_w(CRT_UNDERLINE_LOC, 0x07); /* probably font-height - 1 */
+
+ tmp = 0x20; /* Enable extended end bits */
+ if (data.h_total & 0x100)
+ tmp |= 0x01;
+ if ((data.h_dispend) & 0x100)
+ tmp |= 0x02;
+ if (data.h_bstart & 0x100)
+ tmp |= 0x04;
+ if (data.h_sstart & 0x100)
+ tmp |= 0x08;
+ if (var->vmode & FB_VMODE_INTERLACED)
+ tmp |= 0x10;
+ DEBUG printk("CRT_EXT_HOR_TIMING1: %d\n", tmp);
+ crt_w(CRT_EXT_HOR_TIMING1, tmp);
+
+ tmp = 0x00;
+ if (((var->xres_virtual / 8) * (bpp / 8)) & 0x100)
+ tmp |= 0x10;
+ crt_w(CRT_EXT_START_ADDR, tmp);
+
+ tmp = 0x00;
+ if (data.h_total & 0x200)
+ tmp |= 0x01;
+ if ((data.h_dispend) & 0x200)
+ tmp |= 0x02;
+ if (data.h_bstart & 0x200)
+ tmp |= 0x04;
+ if (data.h_sstart & 0x200)
+ tmp |= 0x08;
+ tmp |= ((data.h_bstop & 0xc0) >> 2);
+ tmp |= ((data.h_sstop & 0x60) << 1);
+ crt_w(CRT_EXT_HOR_TIMING2, tmp);
+ DEBUG printk("CRT_EXT_HOR_TIMING2: %d\n", tmp);
+
+ tmp = 0x10; /* Line compare bit 10 */
+ if (data.v_total & 0x400)
+ tmp |= 0x01;
+ if ((data.v_dispend) & 0x400)
+ tmp |= 0x02;
+ if (data.v_bstart & 0x400)
+ tmp |= 0x04;
+ if (data.v_sstart & 0x400)
+ tmp |= 0x08;
+ tmp |= ((data.v_bstop & 0x300) >> 3);
+ if (data.v_sstop & 0x10)
+ tmp |= 0x80;
+ crt_w(CRT_EXT_VER_TIMING, tmp);
+ DEBUG printk("CRT_EXT_VER_TIMING: %d\n", tmp);
+
+ crt_w(CRT_MONITOR_POWER, 0x00);
+
+ /*
+ * Convert from ps to Hz.
+ */
+ freq_f = (1.0/(float)var->pixclock) * 1000000000;
+ freq = ((long)freq_f) * 1000;
+
+ best_freq = find_fq(freq);
+ pll_w(0x02, best_freq);
+ best_freq = find_fq(61000000);
+ pll_w(0x0a, best_freq);
+ pll_w(0x0e, 0x22);
+
+ gfx_w(GFX_SET_RESET, 0x00);
+ gfx_w(GFX_ENABLE_SET_RESET, 0x00);
+ gfx_w(GFX_COLOR_COMPARE, 0x00);
+ gfx_w(GFX_DATA_ROTATE, 0x00);
+ gfx_w(GFX_READ_MAP_SELECT, 0x00);
+ gfx_w(GFX_GRAPHICS_MODE, 0x00);
+ gfx_w(GFX_MISC, 0x05);
+ gfx_w(GFX_COLOR_XCARE, 0x0f);
+ gfx_w(GFX_BITMASK, 0xff);
+
+ reg_r(ACT_ADDRESS_RESET);
+ attr_w(ACT_PALETTE0 , 0x00);
+ attr_w(ACT_PALETTE1 , 0x01);
+ attr_w(ACT_PALETTE2 , 0x02);
+ attr_w(ACT_PALETTE3 , 0x03);
+ attr_w(ACT_PALETTE4 , 0x04);
+ attr_w(ACT_PALETTE5 , 0x05);
+ attr_w(ACT_PALETTE6 , 0x06);
+ attr_w(ACT_PALETTE7 , 0x07);
+ attr_w(ACT_PALETTE8 , 0x08);
+ attr_w(ACT_PALETTE9 , 0x09);
+ attr_w(ACT_PALETTE10, 0x0a);
+ attr_w(ACT_PALETTE11, 0x0b);
+ attr_w(ACT_PALETTE12, 0x0c);
+ attr_w(ACT_PALETTE13, 0x0d);
+ attr_w(ACT_PALETTE14, 0x0e);
+ attr_w(ACT_PALETTE15, 0x0f);
+ reg_r(ACT_ADDRESS_RESET);
+
+ attr_w(ACT_ATTR_MODE_CNTL, 0x09); /* 0x01 for CL */
+
+ attr_w(ACT_OVERSCAN_COLOR, 0x00);
+ attr_w(ACT_COLOR_PLANE_ENA, 0x0f);
+ attr_w(ACT_HOR_PEL_PANNING, 0x00);
+ attr_w(ACT_COLOR_SELECT, 0x00);
+
+ reg_r(ACT_ADDRESS_RESET);
+ reg_w(ACT_DATA, 0x20);
+
+ reg_w(VDAC_MASK, 0xff);
+
+ /*
+ * Extended palette adressing ???
+ */
+ switch (bpp){
+ case 8:
+ reg_w(0x83c6, 0x00);
+ break;
+ case 16:
+ reg_w(0x83c6, 0x60);
+ break;
+ case 24:
+ reg_w(0x83c6, 0xe0);
+ break;
+ default:
+ printk("Illegal color-depth: %i\n", bpp);
+ }
+
+ reg_w(VDAC_ADDRESS, 0x00);
+
+ seq_w(SEQ_MAP_MASK, 0x0f );
+
+ return 0;
+}
+
+/*
+ * Initialization
+ *
+ * Set the default video mode for this chipset. If a video mode was
+ * specified on the command line, it will override the default mode.
+ */
+
+static int retz3_init(void)
+{
+ int i;
+#if 0
+ volatile unsigned long *CursorBase;
+#endif
+ unsigned long board_addr, board_size;
+ struct ConfigDev *cd;
+
+ cd = zorro_get_board (z3_key);
+ zorro_config_board (z3_key, 0);
+ board_addr = (unsigned long)cd->cd_BoardAddr;
+ board_size = (unsigned long)cd->cd_BoardSize;
+
+ for (i = 0; i < 256; i++){
+ for (i = 0; i < 256; i++){
+ retz3_color_table [i][0] = i;
+ retz3_color_table [i][1] = i;
+ retz3_color_table [i][2] = i;
+ retz3_color_table [i][3] = 0;
+ }
+ }
+
+ *memstart = (*memstart + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+
+ z3_mem = kernel_map (board_addr, board_size,
+ KERNELMAP_NOCACHE_SER, memstart);
+
+ z3_regs = (char*) z3_mem;
+ z3_fbmem = z3_mem + VIDEO_MEM_OFFSET;
+
+ /* Get memory size - for now we asume its a 4MB board */
+
+ z3_size = 0x00400000; /* 4 MB */
+
+ memset ((char*)z3_fbmem, 0, z3_size);
+
+ /* Disable hardware cursor */
+
+ seq_w(SEQ_CURSOR_Y_INDEX, 0x00);
+
+
+#if 0
+ /* Initialize hardware cursor */
+ CursorBase = (unsigned long *)((char *)(z3_mem) + z3_size - 0x400);
+ for (i=0; i < 8; i++){
+ *(CursorBase +(i*4)) = 0xffffff00;
+ *(CursorBase+1+(i*4)) = 0xffff0000;
+ *(CursorBase+2+(i*4)) = 0xffff0000;
+ *(CursorBase+3+(i*4)) = 0xffff0000;
+ }
+ for (i=8; i < 64; i++){
+ *(CursorBase +(i*4)) = 0xffff0000;
+ *(CursorBase+1+(i*4)) = 0xffff0000;
+ *(CursorBase+2+(i*4)) = 0xffff0000;
+ *(CursorBase+3+(i*4)) = 0xffff0000;
+ }
+#endif
+
+ retz3_setcolreg (255, 56, 100, 160, 0);
+ retz3_setcolreg (254, 0, 0, 0, 0);
+
+ return 0;
+}
+
+
+/*
+ * This function should fill in the `fix' structure based on the
+ * values in the `par' structure.
+ */
+
+static int retz3_encode_fix(struct fb_fix_screeninfo *fix,
+ struct retz3_fb_par *par)
+{
+ int i;
+
+ strcpy(fix->id, retz3_fb_name);
+ fix->smem_start = z3_fbmem;
+ fix->smem_len = z3_size;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
+ if (par->bpp == 8)
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ else
+ fix->visual = FB_VISUAL_DIRECTCOLOR;
+
+ fix->xpanstep = 0;
+ fix->ypanstep = 0;
+ fix->ywrapstep = 0;
+ fix->line_length = 0;
+
+ for (i = 0; i < arraysize(fix->reserved); i++)
+ fix->reserved[i] = 0;
+
+ return 0;
+}
+
+
+/*
+ * Get the video params out of `var'. If a value doesn't fit, round
+ * it up, if it's too big, return -EINVAL.
+ */
+
+static int retz3_decode_var(struct fb_var_screeninfo *var,
+ struct retz3_fb_par *par)
+{
+ par->xres = var->xres;
+ par->yres = var->yres;
+ par->xres_vir = var->xres_virtual;
+ par->yres_vir = var->yres_virtual;
+ par->bpp = var->bits_per_pixel;
+ par->pixclock = var->pixclock;
+ par->vmode = var->vmode;
+
+ par->red = var->red;
+ par->green = var->green;
+ par->blue = var->blue;
+ par->transp = var->transp;
+
+ par->left_margin = var->left_margin;
+ par->right_margin = var->right_margin;
+ par->upper_margin = var->upper_margin;
+ par->lower_margin = var->lower_margin;
+ par->hsync_len = var->hsync_len;
+ par->vsync_len = var->vsync_len;
+
+ return 0;
+}
+
+
+/*
+ * Fill the `var' structure based on the values in `par' and maybe
+ * other values read out of the hardware.
+ */
+
+static int retz3_encode_var(struct fb_var_screeninfo *var,
+ struct retz3_fb_par *par)
+{
+ int i;
+
+ var->xres = par->xres;
+ var->yres = par->yres;
+ var->xres_virtual = par->xres_vir;
+ var->yres_virtual = par->yres_vir;
+ var->xoffset = 0;
+ var->yoffset = 0;
+
+ var->bits_per_pixel = par->bpp;
+ var->grayscale = 0;
+
+ var->red = par->red;
+ var->green = par->green;
+ var->blue = par->blue;
+ var->transp = par->transp;
+
+ var->nonstd = 0;
+ var->activate = 0;
+
+ var->height = -1;
+ var->width = -1;
+
+ var->accel = FB_ACCEL_RETINAZ3;
+
+ var->pixclock = par->pixclock;
+
+ var->sync = 0; /* ??? */
+ var->left_margin = par->left_margin;
+ var->right_margin = par->right_margin;
+ var->upper_margin = par->upper_margin;
+ var->lower_margin = par->lower_margin;
+ var->hsync_len = par->hsync_len;
+ var->vsync_len = par->vsync_len;
+
+ for (i = 0; i < arraysize(var->reserved); i++)
+ var->reserved[i] = 0;
+
+ var->vmode = par->vmode;
+ return 0;
+}
+
+
+/*
+ * Set a single color register. The values supplied are already
+ * rounded down to the hardware's capabilities (according to the
+ * entries in the var structure). Return != 0 for invalid regno.
+ */
+
+static int retz3_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp)
+{
+ /* We'll get to this */
+
+ if (regno > 255)
+ return 1;
+
+ retz3_color_table [regno][0] = red & 0xff;
+ retz3_color_table [regno][1] = green & 0xff;
+ retz3_color_table [regno][2] = blue & 0xff;
+ retz3_color_table [regno][3] = transp;
+
+ reg_w(VDAC_ADDRESS_W, regno);
+ reg_w(VDAC_DATA, (red & 0xff) >> 2);
+ reg_w(VDAC_DATA, (green & 0xff) >> 2);
+ reg_w(VDAC_DATA, (blue & 0xff) >> 2);
+
+ return 0;
+}
+
+
+/*
+ * Read a single color register and split it into
+ * colors/transparent. Return != 0 for invalid regno.
+ */
+
+static int retz3_getcolreg(unsigned int regno, unsigned int *red,
+ unsigned int *green, unsigned int *blue,
+ unsigned int *transp)
+{
+ if (regno > 255)
+ return 1;
+ *red = retz3_color_table [regno][0];
+ *green = retz3_color_table [regno][1];
+ *blue = retz3_color_table [regno][2];
+ *transp = retz3_color_table [regno][3];
+ return 0;
+}
+
+
+/*
+ * (Un)Blank the screen
+ */
+
+void retz3_blank(int blank)
+{
+ int i;
+
+ if (blank)
+ for (i = 0; i < 256; i++){
+ reg_w(VDAC_ADDRESS_W, i);
+ reg_w(VDAC_DATA, 0);
+ reg_w(VDAC_DATA, 0);
+ reg_w(VDAC_DATA, 0);
+ }
+ else
+ for (i = 0; i < 256; i++){
+ reg_w(VDAC_ADDRESS_W, i);
+ reg_w(VDAC_DATA, retz3_color_table [i][0] >> 2);
+ reg_w(VDAC_DATA, retz3_color_table [i][1] >> 2);
+ reg_w(VDAC_DATA, retz3_color_table [i][2] >> 2);
+ }
+}
+
+
+void retz3_bitblt (struct fb_var_screeninfo *var,
+ unsigned short srcx, unsigned short srcy, unsigned
+ short destx, unsigned short desty, unsigned short
+ width, unsigned short height, unsigned short cmd,
+ unsigned short mask)
+{
+
+ volatile unsigned long *acm = (unsigned long *) (z3_mem + ACM_OFFSET);
+ unsigned long *pattern = (unsigned long *)(z3_fbmem + PAT_MEM_OFF);
+
+ unsigned short mod;
+ unsigned long tmp;
+ unsigned long pat, src, dst;
+ unsigned char blt_status;
+
+ int i, xres_virtual = var->xres_virtual;
+ short bpp = (var->bits_per_pixel & 0xff);
+
+ if (bpp < 8)
+ bpp = 8;
+
+ tmp = mask | (mask << 16);
+
+#if 0
+ /*
+ * Check for blitter finished before we start messing with the
+ * pattern.
+ */
+ do{
+ blt_status = *(((volatile unsigned char *)acm) +
+ (ACM_START_STATUS + 2));
+ }while ((blt_status & 1) == 0);
+#endif
+
+ i = 0;
+ do{
+ *pattern++ = tmp;
+ }while(i++ < bpp/4);
+
+ tmp = cmd << 8;
+ *(acm + ACM_RASTEROP_ROTATION/4) = tmp;
+
+ mod = 0xc0c2;
+
+ pat = 8 * PAT_MEM_OFF;
+ dst = bpp * (destx + desty * xres_virtual);
+
+ /*
+ * Source is not set for clear.
+ */
+ if ((cmd != Z3BLTclear) && (cmd != Z3BLTset)) {
+ src = bpp * (srcx + srcy * xres_virtual);
+
+ if (destx > srcx) {
+ mod &= ~0x8000;
+ src += bpp * (width - 1);
+ dst += bpp * (width - 1);
+ pat += bpp * 2;
+ }
+ if (desty > srcy) {
+ mod &= ~0x4000;
+ src += bpp * (height - 1) * xres_virtual;
+ dst += bpp * (height - 1) * xres_virtual;
+ pat += bpp * 4;
+ }
+
+ *(acm + ACM_SOURCE/4) = cpu_to_le32(src);
+ }
+
+ *(acm + ACM_PATTERN/4) = cpu_to_le32(pat);
+
+ *(acm + ACM_DESTINATION/4) = cpu_to_le32(dst);
+
+ tmp = mod << 16;
+ *(acm + ACM_CONTROL/4) = tmp;
+
+ tmp = width | (height << 16);
+
+ *(acm + ACM_BITMAP_DIMENSION/4) = cpu_to_le32(tmp);
+
+ *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
+ *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
+
+ /*
+ * No reason to wait for the blitter to finish, it is better
+ * just to check if it has finished before we use it again.
+ */
+#if 1
+#if 0
+ while ((*(((volatile unsigned char *)acm) +
+ (ACM_START_STATUS + 2)) & 1) == 0);
+#else
+ do{
+ blt_status = *(((volatile unsigned char *)acm) +
+ (ACM_START_STATUS + 2));
+ }
+ while ((blt_status & 1) == 0);
+#endif
+#endif
+}
+
+#if 0
+void retz3_fill (unsigned short x, unsigned short y, unsigned
+ short width, unsigned short height,
+ unsigned short mode, unsigned short color)
+{
+
+}
+#endif
+
+
+/**************************************************************
+ * Move cursor to x, y
+ */
+void retz3_MoveCursor (unsigned short x, unsigned short y)
+{
+ /* Guess we gotta deal with the cursor at some point */
+}
+
+
+/* -------------------- Interfaces to hardware functions -------------------- */
+
+
+static struct fb_hwswitch retz3_switch = {
+ retz3_init, retz3_encode_fix, retz3_decode_var, retz3_encode_var,
+ retz3_getcolreg, retz3_setcolreg, retz3_blank
+};
+
+
+/* -------------------- Generic routines ------------------------------------ */
+
+
+/*
+ * Fill the hardware's `par' structure.
+ */
+
+static void retz3_fb_get_par(struct retz3_fb_par *par)
+{
+ if (current_par_valid)
+ *par = current_par;
+ else
+ fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], par);
+}
+
+
+static void retz3_fb_set_par(struct retz3_fb_par *par)
+{
+ current_par = *par;
+ current_par_valid = 1;
+}
+
+
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
+{
+ int err, activate;
+ struct retz3_fb_par par;
+
+ if ((err = fbhw->decode_var(var, &par)))
+ return err;
+ activate = var->activate;
+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
+ retz3_fb_set_par(&par);
+ fbhw->encode_var(var, &par);
+ var->activate = activate;
+
+#if 1
+ retz3_set_video(var, &current_par);
+#endif
+ return 0;
+}
+
+
+/*
+ * Default Colormaps
+ */
+
+static unsigned short red16[] =
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0xc000,
+ 0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff };
+static unsigned short green16[] =
+ { 0x0000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0xc000,
+ 0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff };
+static unsigned short blue16[] =
+ { 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000,
+ 0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff };
+
+
+static struct fb_cmap default_16_colors =
+ { 0, 16, red16, green16, blue16, NULL };
+
+
+static struct fb_cmap *get_default_colormap(int bpp)
+{
+ return &default_16_colors;
+}
+
+
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7fff-(val))>>16)
+#define CNVT_FROMHW(val,width) (((width) ? ((((val)<<16)-(val)) / \
+ ((1<<(width))-1)) : 0))
+
+static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+ int kspc)
+{
+ int i, start;
+ unsigned short *red, *green, *blue, *transp;
+ unsigned int hred, hgreen, hblue, htransp;
+
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ start = cmap->start;
+
+ if (start < 0)
+ return -EINVAL;
+ for (i = 0; i < cmap->len; i++) {
+ if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
+ return 0;
+ hred = CNVT_FROMHW(hred, var->red.length);
+ hgreen = CNVT_FROMHW(hgreen, var->green.length);
+ hblue = CNVT_FROMHW(hblue, var->blue.length);
+ htransp = CNVT_FROMHW(htransp, var->transp.length);
+ if (kspc) {
+ *red = hred;
+ *green = hgreen;
+ *blue = hblue;
+ if (transp)
+ *transp = htransp;
+ } else {
+ put_user(hred, red);
+ put_user(hgreen, green);
+ put_user(hblue, blue);
+ if (transp)
+ put_user(htransp, transp);
+ }
+ red++;
+ green++;
+ blue++;
+ if (transp)
+ transp++;
+ }
+ return 0;
+}
+
+
+static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+ int kspc)
+{
+ int i, start;
+ unsigned short *red, *green, *blue, *transp;
+ unsigned int hred, hgreen, hblue, htransp;
+
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ start = cmap->start;
+
+ if (start < 0)
+ return -EINVAL;
+ for (i = 0; i < cmap->len; i++) {
+ if (kspc) {
+ hred = *red;
+ hgreen = *green;
+ hblue = *blue;
+ htransp = transp ? *transp : 0;
+ } else {
+ get_user(hred, red);
+ get_user(hgreen, green);
+ get_user(hblue, blue);
+ if (transp)
+ get_user(htransp, transp);
+ else
+ htransp = 0;
+ }
+ hred = CNVT_TOHW(hred, var->red.length);
+ hgreen = CNVT_TOHW(hgreen, var->green.length);
+ hblue = CNVT_TOHW(hblue, var->blue.length);
+ htransp = CNVT_TOHW(htransp, var->transp.length);
+ red++;
+ green++;
+ blue++;
+ if (transp)
+ transp++;
+ if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
+ return 0;
+ }
+ return 0;
+}
+
+
+static void do_install_cmap(int con)
+{
+ if (con != currcon)
+ return;
+ if (disp[con].cmap.len)
+ do_fb_set_cmap(&disp[con].cmap, &disp[con].var, 1);
+ else
+ do_fb_set_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
+ &disp[con].var, 1);
+}
+
+
+static void memcpy_fs(int fsfromto, void *to, void *from, int len)
+{
+ switch (fsfromto) {
+ case 0:
+ memcpy(to, from, len);
+ return;
+ case 1:
+ copy_from_user(to, from, len);
+ return;
+ case 2:
+ copy_to_user(to, from, len);
+ return;
+ }
+}
+
+
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+{
+ int size;
+ int tooff = 0, fromoff = 0;
+
+ if (to->start > from->start)
+ fromoff = to->start-from->start;
+ else
+ tooff = from->start-to->start;
+ size = to->len-tooff;
+ if (size > from->len-fromoff)
+ size = from->len-fromoff;
+ if (size < 0)
+ return;
+ size *= sizeof(unsigned short);
+ memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
+ memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
+ memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
+ if (from->transp && to->transp)
+ memcpy_fs(fsfromto, to->transp+tooff,
+ from->transp+fromoff, size);
+}
+
+
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
+{
+ int size = len*sizeof(unsigned short);
+
+ if (cmap->len != len) {
+ if (cmap->red)
+ kfree(cmap->red);
+ if (cmap->green)
+ kfree(cmap->green);
+ if (cmap->blue)
+ kfree(cmap->blue);
+ if (cmap->transp)
+ kfree(cmap->transp);
+ cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
+ cmap->len = 0;
+ if (!len)
+ return 0;
+ if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
+ return -1;
+ if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
+ return -1;
+ if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
+ return -1;
+ if (transp) {
+ if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
+ return -1;
+ } else
+ cmap->transp = NULL;
+ }
+ cmap->start = 0;
+ cmap->len = len;
+ copy_cmap(get_default_colormap(len), cmap, 0);
+ return 0;
+}
+
+
+/*
+ * Get the Fixed Part of the Display
+ */
+
+static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
+{
+ struct retz3_fb_par par;
+ int error = 0;
+
+ if (con == -1)
+ retz3_fb_get_par(&par);
+ else
+ error = fbhw->decode_var(&disp[con].var, &par);
+ return(error ? error : fbhw->encode_fix(fix, &par));
+}
+
+
+/*
+ * Get the User Defined Part of the Display
+ */
+
+static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con)
+{
+ struct retz3_fb_par par;
+ int error = 0;
+
+ if (con == -1) {
+ retz3_fb_get_par(&par);
+ error = fbhw->encode_var(var, &par);
+ } else
+ *var = disp[con].var;
+ return error;
+}
+
+
+static void retz3_fb_set_disp(int con)
+{
+ struct fb_fix_screeninfo fix;
+
+ retz3_fb_get_fix(&fix, con);
+ if (con == -1)
+ con = 0;
+ disp[con].screen_base = (unsigned char *)fix.smem_start;
+ disp[con].visual = fix.visual;
+ disp[con].type = fix.type;
+ disp[con].type_aux = fix.type_aux;
+ disp[con].ypanstep = fix.ypanstep;
+ disp[con].ywrapstep = fix.ywrapstep;
+ disp[con].can_soft_blank = 1;
+ disp[con].inverse = z3fb_inverse;
+}
+
+
+/*
+ * Set the User Defined Part of the Display
+ */
+
+static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con)
+{
+ int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
+
+ if ((err = do_fb_set_var(var, con == currcon)))
+ return err;
+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+ oldxres = disp[con].var.xres;
+ oldyres = disp[con].var.yres;
+ oldvxres = disp[con].var.xres_virtual;
+ oldvyres = disp[con].var.yres_virtual;
+ oldbpp = disp[con].var.bits_per_pixel;
+ disp[con].var = *var;
+ if (oldxres != var->xres || oldyres != var->yres ||
+ oldvxres != var->xres_virtual ||
+ oldvyres != var->yres_virtual ||
+ oldbpp != var->bits_per_pixel) {
+ retz3_fb_set_disp(con);
+ (*fb_info.changevar)(con);
+ alloc_cmap(&disp[con].cmap, 0, 0);
+ do_install_cmap(con);
+ }
+ }
+ var->activate = 0;
+ return 0;
+}
+
+
+/*
+ * Get the Colormap
+ */
+
+static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+ if (con == currcon) /* current console? */
+ return(do_fb_get_cmap(cmap, &disp[con].var, kspc));
+ else if (disp[con].cmap.len) /* non default colormap? */
+ copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
+ else
+ copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
+ cmap, kspc ? 0 : 2);
+ return 0;
+}
+
+
+/*
+ * Set the Colormap
+ */
+
+static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+ int err;
+
+ if (!disp[con].cmap.len) { /* no colormap allocated? */
+ if ((err = alloc_cmap(&disp[con].cmap,
+ 1<<disp[con].var.bits_per_pixel, 0)))
+ return err;
+ }
+ if (con == currcon) /* current console? */
+ return(do_fb_set_cmap(cmap, &disp[con].var, kspc));
+ else
+ copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
+ return 0;
+}
+
+
+/*
+ * Pan or Wrap the Display
+ *
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+
+static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con)
+{
+ return -EINVAL;
+}
+
+
+/*
+ * RetinaZ3 Frame Buffer Specific ioctls
+ */
+
+static int retz3_fb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con)
+{
+ return -EINVAL;
+}
+
+
+static struct fb_ops retz3_fb_ops = {
+ retz3_fb_get_fix, retz3_fb_get_var, retz3_fb_set_var, retz3_fb_get_cmap,
+ retz3_fb_set_cmap, retz3_fb_pan_display, retz3_fb_ioctl
+};
+
+
+int retz3_probe(void)
+{
+ z3_key = zorro_find(MANUF_MACROSYSTEMS2, PROD_RETINA_Z3, 0, 0);
+ return(z3_key);
+}
+
+
+void retz3_video_setup(char *options, int *ints)
+{
+ char *this_opt;
+ int i;
+
+ fb_info.fontname[0] = '\0';
+
+ if (!options || !*options)
+ return;
+
+ for (this_opt = strtok(options, ","); this_opt;
+ this_opt = strtok(NULL, ",")){
+ if (!strcmp(this_opt, "inverse")) {
+ z3fb_inverse = 1;
+ for (i = 0; i < 16; i++) {
+ red16[i] = ~red16[i];
+ green16[i] = ~green16[i];
+ blue16[i] = ~blue16[i];
+ }
+ } else if (!strncmp(this_opt, "font:", 5))
+ strcpy(fb_info.fontname, this_opt+5);
+ else
+ z3fb_mode = get_video_mode(this_opt);
+ }
+}
+
+
+/*
+ * Initialization
+ */
+
+struct fb_info *retz3_fb_init(long *mem_start)
+{
+ int err;
+ struct retz3_fb_par par;
+
+ memstart = mem_start;
+
+ fbhw = &retz3_switch;
+
+ err = register_framebuffer(retz3_fb_name, &node, &retz3_fb_ops,
+ NUM_TOTAL_MODES, retz3_fb_predefined);
+ if (err < 0)
+ panic("Cannot register frame buffer\n");
+
+ fbhw->init();
+
+ if (z3fb_mode == -1)
+ z3fb_mode = 1;
+
+ fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], &par);
+ fbhw->encode_var(&retz3_fb_predefined[0], &par);
+
+ strcpy(fb_info.modename, retz3_fb_name);
+ fb_info.disp = disp;
+ fb_info.switch_con = &z3fb_switch;
+ fb_info.updatevar = &z3fb_updatevar;
+ fb_info.blank = &z3fb_blank;
+ fb_info.setcmap = &z3fb_setcmap;
+
+ do_fb_set_var(&retz3_fb_predefined[0], 0);
+ retz3_fb_get_var(&disp[0].var, -1);
+ retz3_fb_set_disp(-1);
+ do_install_cmap(0);
+
+ return &fb_info;
+}
+
+
+static int z3fb_switch(int con)
+{
+ /* Do we have to save the colormap? */
+ if (disp[currcon].cmap.len)
+ do_fb_get_cmap(&disp[currcon].cmap, &disp[currcon].var, 1);
+
+ do_fb_set_var(&disp[con].var, 1);
+ currcon = con;
+ /* Install new colormap */
+ do_install_cmap(con);
+ return 0;
+}
+
+
+/*
+ * Update the `var' structure (called by fbcon.c)
+ *
+ * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
+ * Since it's called by a kernel driver, no range checking is done.
+ */
+
+static int z3fb_updatevar(int con)
+{
+ return 0;
+}
+
+
+/*
+ * Blank the display.
+ */
+
+static void z3fb_blank(int blank)
+{
+ fbhw->blank(blank);
+}
+
+
+/*
+ * Set the colormap
+ */
+
+static int z3fb_setcmap(struct fb_cmap *cmap, int con)
+{
+ return(retz3_fb_set_cmap(cmap, 1, con));
+}
+
+
+/*
+ * Get a Video Mode
+ */
+
+static int get_video_mode(const char *name)
+{
+ int i;
+
+ for (i = 1; i <= NUM_PREDEF_MODES; i++)
+ if (!strcmp(name, retz3_fb_modenames[i])){
+ retz3_fb_predefined[0] = retz3_fb_predefined[i];
+ return i;
+ }
+ return -1;
+}
+/*
+ * Linux/arch/m68k/amiga/retz3fb.c -- Low level implementation of the
+ * RetinaZ3 frame buffer device
+ *
+ * Copyright (C) 1997 Jes Sorensen
+ *
+ * This file is based on the CyberVision64 frame buffer device and
+ * the generic Cirrus Logic driver.
+ *
+ * cyberfb.c: Copyright (C) 1996 Martin Apel,
+ * Geert Uytterhoeven
+ * clgen.c: Copyright (C) 1996 Frank Neumann
+ *
+ * History:
+ * - 22 Jan 97: Initial work
+ * - 14 Feb 97: Screen initialization works somewhat, still only
+ * 8-bit packed pixel is supported.
+ *
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <linux/zorro.h>
+#include <asm/pgtable.h>
+
+#include "retz3fb.h"
+
+/* #define DEBUG if(1) */
+#define DEBUG if(0)
+
+/*
+ * Reserve space for one pattern line.
+ *
+ * For the time being we only support 4MB boards!
+ */
+
+#define PAT_MEM_SIZE 16*3
+#define PAT_MEM_OFF (4*1024*1024 - PAT_MEM_SIZE)
+
+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
+
+struct retz3_fb_par {
+ int xres;
+ int yres;
+ int xres_vir;
+ int yres_vir;
+ int xoffset;
+ int yoffset;
+ int bpp;
+
+ struct fb_bitfield red;
+ struct fb_bitfield green;
+ struct fb_bitfield blue;
+ struct fb_bitfield transp;
+
+ int pixclock;
+ int left_margin; /* time from sync to picture */
+ int right_margin; /* time from picture to sync */
+ int upper_margin; /* time from sync to picture */
+ int lower_margin;
+ int hsync_len; /* length of horizontal sync */
+ int vsync_len; /* length of vertical sync */
+ int vmode;
+};
+
+struct display_data {
+ long h_total; /* Horizontal Total */
+ long h_sstart; /* Horizontal Sync Start */
+ long h_sstop; /* Horizontal Sync Stop */
+ long h_bstart; /* Horizontal Blank Start */
+ long h_bstop; /* Horizontal Blank Stop */
+ long h_dispend; /* Horizontal Display End */
+ long v_total; /* Vertical Total */
+ long v_sstart; /* Vertical Sync Start */
+ long v_sstop; /* Vertical Sync Stop */
+ long v_bstart; /* Vertical Blank Start */
+ long v_bstop; /* Vertical Blank Stop */
+ long v_dispend; /* Horizontal Display End */
+};
+
+static struct retz3_fb_par current_par;
+
+static int current_par_valid = 0;
+static int currcon = 0;
+
+static struct display disp[MAX_NR_CONSOLES];
+static struct fb_info fb_info;
+
+static int node; /* node of the /dev/fb?current file */
+
+
+/*
+ * Switch for Chipset Independency
+ */
+
+static struct fb_hwswitch {
+
+ /* Initialisation */
+
+ int (*init)(void);
+
+ /* Display Control */
+
+ int (*encode_fix)(struct fb_fix_screeninfo *fix, struct retz3_fb_par *par);
+ int (*decode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par);
+ int (*encode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par);
+ int (*getcolreg)(unsigned int regno, unsigned int *red, unsigned
+ int *green, unsigned int *blue, unsigned int *transp);
+ int (*setcolreg)(unsigned int regno, unsigned int red, unsigned int
+ green, unsigned int blue, unsigned int transp);
+ void (*blank)(int blank);
+} *fbhw;
+
+
+/*
+ * Frame Buffer Name
+ */
+
+static char retz3_fb_name[16] = "RetinaZ3";
+
+
+static int z3_key = 0;
+static unsigned char retz3_color_table [256][4];
+static unsigned long z3_mem;
+static unsigned long z3_fbmem;
+static unsigned long z3_size;
+static volatile unsigned char *z3_regs;
+
+static long *memstart;
+
+
+/*
+ * Predefined Video Mode Names
+ */
+
+static char *retz3_fb_modenames[] = {
+
+ /*
+ * Autodetect (Default) Video Mode
+ */
+
+ "default",
+
+ /*
+ * Predefined Video Modes
+ */
+
+ "640x480", /* RetinaZ3 8 bpp */
+ "800x600", /* RetinaZ3 8 bpp */
+ "1024x768i",
+ "640x480-16", /* RetinaZ3 16 bpp */
+ "640x480-24", /* RetinaZ3 24 bpp */
+
+ /*
+ * Dummy Video Modes
+ */
+
+ "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+ "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+ "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+
+ /*
+ * User Defined Video Modes
+ *
+ * This doesn't work yet!!
+ */
+
+ "user0", "user1", "user2", "user3",
+ "user4", "user5", "user6", "user7"
+};
+
+/*
+ * A small info on how to convert XFree86 timing values into fb
+ * timings - by Frank Neumann:
+ *
+An XFree86 mode line consists of the following fields:
+ "800x600" 50 800 856 976 1040 600 637 643 666
+ < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL
+
+The fields in the fb_var_screeninfo structure are:
+ unsigned long pixclock; * pixel clock in ps (pico seconds) *
+ unsigned long left_margin; * time from sync to picture *
+ unsigned long right_margin; * time from picture to sync *
+ unsigned long upper_margin; * time from sync to picture *
+ unsigned long lower_margin;
+ unsigned long hsync_len; * length of horizontal sync *
+ unsigned long vsync_len; * length of vertical sync *
+
+1) Pixelclock:
+ xfree: in MHz
+ fb: In Picoseconds (ps)
+
+ pixclock = 1000000 / DCF
+
+2) horizontal timings:
+ left_margin = HFL - SH2
+ right_margin = SH1 - HR
+ hsync_len = SH2 - SH1
+
+3) vertical timings:
+ upper_margin = VFL - SV2
+ lower_margin = SV1 - VR
+ vsync_len = SV2 - SV1
+
+Good examples for VESA timings can be found in the XFree86 source tree,
+under "programs/Xserver/hw/xfree86/doc/modeDB.txt".
+*/
+
+/*
+ * Predefined Video Mode Definitions
+ */
+
+static struct fb_var_screeninfo retz3_fb_predefined[] = {
+
+ /*
+ * Autodetect (Default) Video Mode
+ */
+
+ { 0, },
+
+ /*
+ * Predefined Video Modes
+ */
+
+ /*
+ * NB: it is very important to adjust the pixel-clock to the color-depth.
+ */
+
+ {
+ 640, 480, 640, 480, 0, 0, 8, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461, 28, 32, 12, 10, 96, 2,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ },
+ /*
+ ModeLine "800x600" 36 800 824 896 1024 600 601 603 625
+ < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL
+ */
+ {
+ /* 800 x 600, 8 bpp */
+ 800, 600, 800, 600, 0, 0, 8, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 27778, 64, 24, 22, 1, 120, 2,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ },
+ /*
+ ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace
+ < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL
+ */
+ {
+ /* 1024 x 768, 8 bpp, interlaced */
+ 1024, 768, 1024, 768, 0, 0, 8, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 22222, 40, 40, 32, 9, 160, 8,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED
+ },
+ {
+ 640, 480, 640, 480, 0, 0, 16, 0,
+ {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/2, 28, 32, 12, 10, 96, 2,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ },
+ {
+ 640, 480, 640, 480, 0, 0, 24, 0,
+ {8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/3, 28, 32, 12, 10, 96, 2,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ },
+
+ /*
+ * Dummy Video Modes
+ */
+
+ { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+ { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+ { 0, }, { 0, },
+
+ /*
+ * User Defined Video Modes
+ */
+
+ { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
+};
+
+
+#define NUM_TOTAL_MODES arraysize(retz3_fb_predefined)
+#define NUM_PREDEF_MODES (5)
+
+
+static int z3fb_inverse = 0;
+static int z3fb_mode = 0;
+
+
+/*
+ * Interface used by the world
+ */
+
+int retz3_probe(void);
+void retz3_video_setup(char *options, int *ints);
+
+static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con);
+static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con);
+
+
+/*
+ * Interface to the low level console driver
+ */
+
+struct fb_info *retz3_fb_init(long *mem_start); /* Through amiga_fb_init() */
+static int z3fb_switch(int con);
+static int z3fb_updatevar(int con);
+static void z3fb_blank(int blank);
+static int z3fb_setcmap(struct fb_cmap *cmap, int con);
+
+
+/*
+ * Accelerated Functions used by the low level console driver
+ */
+
+void retz3_bitblt(struct fb_var_screeninfo *scr,
+ unsigned short curx, unsigned short cury, unsigned
+ short destx, unsigned short desty, unsigned short
+ width, unsigned short height, unsigned short cmd,
+ unsigned short mask);
+void retz3_fill(unsigned short x, unsigned short y, unsigned short
+ width, unsigned short height, unsigned short mode,
+ unsigned short color);
+
+/*
+ * Hardware Specific Routines
+ */
+
+static int retz3_init(void);
+static int retz3_encode_fix(struct fb_fix_screeninfo *fix,
+ struct retz3_fb_par *par);
+static int retz3_decode_var(struct fb_var_screeninfo *var,
+ struct retz3_fb_par *par);
+static int retz3_encode_var(struct fb_var_screeninfo *var,
+ struct retz3_fb_par *par);
+static int retz3_getcolreg(unsigned int regno, unsigned int *red,
+ unsigned int *green, unsigned int *blue,
+ unsigned int *transp);
+static int retz3_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp);
+static void retz3_blank(int blank);
+
+
+/*
+ * Internal routines
+ */
+
+static void retz3_fb_get_par(struct retz3_fb_par *par);
+static void retz3_fb_set_par(struct retz3_fb_par *par);
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
+static struct fb_cmap *get_default_colormap(int bpp);
+static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+ int kspc);
+static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+ int kspc);
+static void do_install_cmap(int con);
+static void memcpy_fs(int fsfromto, void *to, void *from, int len);
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
+static void retz3_fb_set_disp(int con);
+static int get_video_mode(const char *name);
+
+
+/* -------------------- Hardware specific routines -------------------------- */
+
+static unsigned short find_fq(unsigned int freq)
+{
+ unsigned long f;
+ long tmp;
+ long prev = 0x7fffffff;
+ long n2, n1 = 3;
+ unsigned long m;
+ unsigned short res = 0;
+
+ if (freq <= 31250000)
+ n2 = 3;
+ else if (freq <= 62500000)
+ n2 = 2;
+ else if (freq <= 125000000)
+ n2 = 1;
+ else if (freq <= 250000000)
+ n2 = 0;
+ else
+ return(0);
+
+
+ do {
+ f = freq >> (10 - n2);
+
+ m = (f * n1) / (14318180/1024);
+
+ if (m > 129)
+ break;
+
+ tmp = (((m * 14318180) >> n2) / n1) - freq;
+ if (tmp < 0)
+ tmp = -tmp;
+
+ if (tmp < prev) {
+ prev = tmp;
+ res = (((n2 << 5) | (n1-2)) << 8) | (m-2);
+ }
+
+ } while ( (++n1) <= 21);
+
+ return res;
+}
+
+
+static int retz3_set_video(struct fb_var_screeninfo *var,
+ struct retz3_fb_par *par)
+{
+ float freq_f;
+ long freq;
+
+ int xres, hfront, hsync, hback;
+ int yres, vfront, vsync, vback;
+ unsigned char tmp;
+ unsigned short best_freq;
+ struct display_data data;
+
+ short clocksel = 0; /* Apparantly this is always zero */
+
+ int bpp = var->bits_per_pixel;
+
+ /*
+ * XXX
+ */
+ if (bpp == 24)
+ return 0;
+
+ if ((bpp != 8) && (bpp != 16) && (bpp != 24))
+ return -EFAULT;
+
+ par->xoffset = 0;
+ par->yoffset = 0;
+
+ xres = var->xres * bpp / 4;
+ hfront = var->right_margin * bpp / 4;
+ hsync = var->hsync_len * bpp / 4;
+ hback = var->left_margin * bpp / 4;
+
+ if (var->vmode & FB_VMODE_DOUBLE)
+ {
+ yres = var->yres * 2;
+ vfront = var->lower_margin * 2;
+ vsync = var->vsync_len * 2;
+ vback = var->upper_margin * 2;
+ }
+ else if (var->vmode & FB_VMODE_INTERLACED)
+ {
+ yres = (var->yres + 1) / 2;
+ vfront = (var->lower_margin + 1) / 2;
+ vsync = (var->vsync_len + 1) / 2;
+ vback = (var->upper_margin + 1) / 2;
+ }
+ else
+ {
+ yres = var->yres; /* -1 ? */
+ vfront = var->lower_margin;
+ vsync = var->vsync_len;
+ vback = var->upper_margin;
+ }
+
+ data.h_total = (hback / 8) + (xres / 8)
+ + (hfront / 8) + (hsync / 8) - 1 /* + 1 */;
+ data.h_dispend = ((xres + bpp - 1)/ 8) - 1;
+ data.h_bstart = xres / 8 /* + 1 */;
+
+ data.h_bstop = data.h_total+1 + 2 + 1;
+ data.h_sstart = (xres / 8) + (hfront / 8) + 1;
+ data.h_sstop = (xres / 8) + (hfront / 8) + (hsync / 8) + 1;
+
+ data.v_total = yres + vfront + vsync + vback - 1;
+
+ data.v_dispend = yres - 1;
+ data.v_bstart = yres;
+
+ data.v_bstop = data.v_total;
+ data.v_sstart = yres + vfront - 1 - 2;
+ data.v_sstop = yres + vfront + vsync - 1;
+
+#if 0 /* testing */
+
+ printk("HBS: %i\n", data.h_bstart);
+ printk("HSS: %i\n", data.h_sstart);
+ printk("HSE: %i\n", data.h_sstop);
+ printk("HBE: %i\n", data.h_bstop);
+ printk("HT: %i\n", data.h_total);
+
+ printk("hsync: %i\n", hsync);
+ printk("hfront: %i\n", hfront);
+ printk("hback: %i\n", hback);
+
+ printk("VBS: %i\n", data.v_bstart);
+ printk("VSS: %i\n", data.v_sstart);
+ printk("VSE: %i\n", data.v_sstop);
+ printk("VBE: %i\n", data.v_bstop);
+ printk("VT: %i\n", data.v_total);
+
+ printk("vsync: %i\n", vsync);
+ printk("vfront: %i\n", vfront);
+ printk("vback: %i\n", vback);
+#endif
+
+ if (data.v_total >= 1024)
+ printk("MAYDAY: v_total >= 1024; bailing out!\n");
+
+ reg_w(GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04));
+ reg_w(GREG_FEATURE_CONTROL_W, 0x00);
+
+ seq_w(SEQ_RESET, 0x00);
+ seq_w(SEQ_RESET, 0x03); /* reset sequencer logic */
+
+ /*
+ * CLOCKING_MODE bits:
+ * 2: This one is only set for certain text-modes, wonder if
+ * it may be for EGA-lines? (it was referred to as CLKDIV2)
+ * (The CL drivers sets it to 0x21 with the comment:
+ * FullBandwidth (video off) and 8/9 dot clock)
+ */
+ seq_w(SEQ_CLOCKING_MODE, 0x01 | 0x00 /* 0x08 */);
+
+ seq_w(SEQ_MAP_MASK, 0x0f); /* enable writing to plane 0-3 */
+ seq_w(SEQ_CHAR_MAP_SELECT, 0x00); /* doesn't matter in gfx-mode */
+ seq_w(SEQ_MEMORY_MODE, 0x06); /* CL driver says 0x0e for 256 col mode*/
+ seq_w(SEQ_RESET, 0x01);
+ seq_w(SEQ_RESET, 0x03);
+
+ seq_w(SEQ_EXTENDED_ENABLE, 0x05);
+
+ seq_w(SEQ_CURSOR_CONTROL, 0x00); /* disable cursor */
+ seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00);
+ seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00);
+ seq_w(SEQ_LINEAR_0, 0x4a);
+ seq_w(SEQ_LINEAR_1, 0x00);
+
+ seq_w(SEQ_SEC_HOST_OFF_HI, 0x00);
+ seq_w(SEQ_SEC_HOST_OFF_LO, 0x00);
+ seq_w(SEQ_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
+
+ /*
+ * The lower 4 bits (0-3) are used to set the font-width for
+ * text-mode - DON'T try to set this for gfx-mode.
+ */
+ seq_w(SEQ_EXT_CLOCK_MODE, 0x10);
+ seq_w(SEQ_EXT_VIDEO_ADDR, 0x03);
+
+ /*
+ * Extended Pixel Control:
+ * bit 0: text-mode=0, gfx-mode=1 (Graphics Byte ?)
+ * bit 1: (Packed/Nibble Pixel Format ?)
+ * bit 4-5: depth, 0=1-8bpp, 1=9-16bpp, 2=17-24bpp
+ */
+ seq_w(SEQ_EXT_PIXEL_CNTL, 0x01 | (((bpp / 8) - 1) << 4));
+
+ seq_w(SEQ_BUS_WIDTH_FEEDB, 0x04);
+ seq_w(SEQ_COLOR_EXP_WFG, 0x01);
+ seq_w(SEQ_COLOR_EXP_WBG, 0x00);
+ seq_w(SEQ_EXT_RW_CONTROL, 0x00);
+ seq_w(SEQ_MISC_FEATURE_SEL, (0x51 | (clocksel & 8)));
+ seq_w(SEQ_COLOR_KEY_CNTL, 0x40);
+ seq_w(SEQ_COLOR_KEY_MATCH0, 0x00);
+ seq_w(SEQ_COLOR_KEY_MATCH1, 0x00);
+ seq_w(SEQ_COLOR_KEY_MATCH2, 0x00);
+ seq_w(SEQ_CRC_CONTROL, 0x00);
+ seq_w(SEQ_PERF_SELECT, 0x10);
+ seq_w(SEQ_ACM_APERTURE_1, 0x00);
+ seq_w(SEQ_ACM_APERTURE_2, 0x30);
+ seq_w(SEQ_ACM_APERTURE_3, 0x00);
+ seq_w(SEQ_MEMORY_MAP_CNTL, 0x03);
+
+
+ /* unlock register CRT0..CRT7 */
+ crt_w(CRT_END_VER_RETR, (data.v_sstop & 0x0f) | 0x20);
+
+ /* Zuerst zu schreibende Werte nur per printk ausgeben */
+ DEBUG printk("CRT_HOR_TOTAL: %ld\n", data.h_total);
+ crt_w(CRT_HOR_TOTAL, data.h_total & 0xff);
+
+ DEBUG printk("CRT_HOR_DISP_ENA_END: %ld\n", data.h_dispend);
+ crt_w(CRT_HOR_DISP_ENA_END, (data.h_dispend) & 0xff);
+
+ DEBUG printk("CRT_START_HOR_BLANK: %ld\n", data.h_bstart);
+ crt_w(CRT_START_HOR_BLANK, data.h_bstart & 0xff);
+
+ DEBUG printk("CRT_END_HOR_BLANK: 128+%ld\n", data.h_bstop % 32);
+ crt_w(CRT_END_HOR_BLANK, 0x80 | (data.h_bstop & 0x1f));
+
+ DEBUG printk("CRT_START_HOR_RETR: %ld\n", data.h_sstart);
+ crt_w(CRT_START_HOR_RETR, data.h_sstart & 0xff);
+
+ tmp = (data.h_sstop & 0x1f);
+ if (data.h_bstop & 0x20)
+ tmp |= 0x80;
+ DEBUG printk("CRT_END_HOR_RETR: %d\n", tmp);
+ crt_w(CRT_END_HOR_RETR, tmp);
+
+ DEBUG printk("CRT_VER_TOTAL: %ld\n", data.v_total & 0xff);
+ crt_w(CRT_VER_TOTAL, (data.v_total & 0xff));
+
+ tmp = 0x10; /* LineCompare bit #9 */
+ if (data.v_total & 256)
+ tmp |= 0x01;
+ if (data.v_dispend & 256)
+ tmp |= 0x02;
+ if (data.v_sstart & 256)
+ tmp |= 0x04;
+ if (data.v_bstart & 256)
+ tmp |= 0x08;
+ if (data.v_total & 512)
+ tmp |= 0x20;
+ if (data.v_dispend & 512)
+ tmp |= 0x40;
+ if (data.v_sstart & 512)
+ tmp |= 0x80;
+ DEBUG printk("CRT_OVERFLOW: %d\n", tmp);
+ crt_w(CRT_OVERFLOW, tmp);
+
+ crt_w(CRT_PRESET_ROW_SCAN, 0x00); /* not CL !!! */
+
+ tmp = 0x40; /* LineCompare bit #8 */
+ if (data.v_bstart & 512)
+ tmp |= 0x20;
+ if (var->vmode & FB_VMODE_DOUBLE)
+ tmp |= 0x80;
+ DEBUG printk("CRT_MAX_SCAN_LINE: %d\n", tmp);
+ crt_w(CRT_MAX_SCAN_LINE, tmp);
+
+ crt_w(CRT_CURSOR_START, 0x00);
+ crt_w(CRT_CURSOR_END, 8 & 0x1f); /* font height */
+
+ crt_w(CRT_START_ADDR_HIGH, 0x00);
+ crt_w(CRT_START_ADDR_LOW, 0x00);
+
+ crt_w(CRT_CURSOR_LOC_HIGH, 0x00);
+ crt_w(CRT_CURSOR_LOC_LOW, 0x00);
+
+ DEBUG printk("CRT_START_VER_RETR: %ld\n", data.v_sstart & 0xff);
+ crt_w(CRT_START_VER_RETR, (data.v_sstart & 0xff));
+
+#if 1
+ /* 5 refresh cycles per scanline */
+ DEBUG printk("CRT_END_VER_RETR: 64+32+%ld\n", data.v_sstop % 16);
+ crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 0x40 | 0x20));
+#else
+ DEBUG printk("CRT_END_VER_RETR: 128+32+%ld\n", data.v_sstop % 16);
+ crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 128 | 32));
+#endif
+ DEBUG printk("CRT_VER_DISP_ENA_END: %ld\n", data.v_dispend & 0xff);
+ crt_w(CRT_VER_DISP_ENA_END, (data.v_dispend & 0xff));
+
+ DEBUG printk("CRT_START_VER_BLANK: %ld\n", data.v_bstart & 0xff);
+ crt_w(CRT_START_VER_BLANK, (data.v_bstart & 0xff));
+
+ DEBUG printk("CRT_END_VER_BLANK: %ld\n", data.v_bstop & 0xff);
+ crt_w(CRT_END_VER_BLANK, (data.v_bstop & 0xff));
+
+ DEBUG printk("CRT_MODE_CONTROL: 0xe3\n");
+ crt_w(CRT_MODE_CONTROL, 0xe3);
+
+ DEBUG printk("CRT_LINE_COMPARE: 0xff\n");
+ crt_w(CRT_LINE_COMPARE, 0xff);
+
+ tmp = (var->xres_virtual / 8) * (bpp / 8);
+ crt_w(CRT_OFFSET, tmp);
+
+ crt_w(CRT_UNDERLINE_LOC, 0x07); /* probably font-height - 1 */
+
+ tmp = 0x20; /* Enable extended end bits */
+ if (data.h_total & 0x100)
+ tmp |= 0x01;
+ if ((data.h_dispend) & 0x100)
+ tmp |= 0x02;
+ if (data.h_bstart & 0x100)
+ tmp |= 0x04;
+ if (data.h_sstart & 0x100)
+ tmp |= 0x08;
+ if (var->vmode & FB_VMODE_INTERLACED)
+ tmp |= 0x10;
+ DEBUG printk("CRT_EXT_HOR_TIMING1: %d\n", tmp);
+ crt_w(CRT_EXT_HOR_TIMING1, tmp);
+
+ tmp = 0x00;
+ if (((var->xres_virtual / 8) * (bpp / 8)) & 0x100)
+ tmp |= 0x10;
+ crt_w(CRT_EXT_START_ADDR, tmp);
+
+ tmp = 0x00;
+ if (data.h_total & 0x200)
+ tmp |= 0x01;
+ if ((data.h_dispend) & 0x200)
+ tmp |= 0x02;
+ if (data.h_bstart & 0x200)
+ tmp |= 0x04;
+ if (data.h_sstart & 0x200)
+ tmp |= 0x08;
+ tmp |= ((data.h_bstop & 0xc0) >> 2);
+ tmp |= ((data.h_sstop & 0x60) << 1);
+ crt_w(CRT_EXT_HOR_TIMING2, tmp);
+ DEBUG printk("CRT_EXT_HOR_TIMING2: %d\n", tmp);
+
+ tmp = 0x10; /* Line compare bit 10 */
+ if (data.v_total & 0x400)
+ tmp |= 0x01;
+ if ((data.v_dispend) & 0x400)
+ tmp |= 0x02;
+ if (data.v_bstart & 0x400)
+ tmp |= 0x04;
+ if (data.v_sstart & 0x400)
+ tmp |= 0x08;
+ tmp |= ((data.v_bstop & 0x300) >> 3);
+ if (data.v_sstop & 0x10)
+ tmp |= 0x80;
+ crt_w(CRT_EXT_VER_TIMING, tmp);
+ DEBUG printk("CRT_EXT_VER_TIMING: %d\n", tmp);
+
+ crt_w(CRT_MONITOR_POWER, 0x00);
+
+ /*
+ * Convert from ps to Hz.
+ */
+ freq_f = (1.0/(float)var->pixclock) * 1000000000;
+ freq = ((long)freq_f) * 1000;
+
+ best_freq = find_fq(freq);
+ pll_w(0x02, best_freq);
+ best_freq = find_fq(61000000);
+ pll_w(0x0a, best_freq);
+ pll_w(0x0e, 0x22);
+
+ gfx_w(GFX_SET_RESET, 0x00);
+ gfx_w(GFX_ENABLE_SET_RESET, 0x00);
+ gfx_w(GFX_COLOR_COMPARE, 0x00);
+ gfx_w(GFX_DATA_ROTATE, 0x00);
+ gfx_w(GFX_READ_MAP_SELECT, 0x00);
+ gfx_w(GFX_GRAPHICS_MODE, 0x00);
+ gfx_w(GFX_MISC, 0x05);
+ gfx_w(GFX_COLOR_XCARE, 0x0f);
+ gfx_w(GFX_BITMASK, 0xff);
+
+ reg_r(ACT_ADDRESS_RESET);
+ attr_w(ACT_PALETTE0 , 0x00);
+ attr_w(ACT_PALETTE1 , 0x01);
+ attr_w(ACT_PALETTE2 , 0x02);
+ attr_w(ACT_PALETTE3 , 0x03);
+ attr_w(ACT_PALETTE4 , 0x04);
+ attr_w(ACT_PALETTE5 , 0x05);
+ attr_w(ACT_PALETTE6 , 0x06);
+ attr_w(ACT_PALETTE7 , 0x07);
+ attr_w(ACT_PALETTE8 , 0x08);
+ attr_w(ACT_PALETTE9 , 0x09);
+ attr_w(ACT_PALETTE10, 0x0a);
+ attr_w(ACT_PALETTE11, 0x0b);
+ attr_w(ACT_PALETTE12, 0x0c);
+ attr_w(ACT_PALETTE13, 0x0d);
+ attr_w(ACT_PALETTE14, 0x0e);
+ attr_w(ACT_PALETTE15, 0x0f);
+ reg_r(ACT_ADDRESS_RESET);
+
+ attr_w(ACT_ATTR_MODE_CNTL, 0x09); /* 0x01 for CL */
+
+ attr_w(ACT_OVERSCAN_COLOR, 0x00);
+ attr_w(ACT_COLOR_PLANE_ENA, 0x0f);
+ attr_w(ACT_HOR_PEL_PANNING, 0x00);
+ attr_w(ACT_COLOR_SELECT, 0x00);
+
+ reg_r(ACT_ADDRESS_RESET);
+ reg_w(ACT_DATA, 0x20);
+
+ reg_w(VDAC_MASK, 0xff);
+
+ /*
+ * Extended palette adressing ???
+ */
+ switch (bpp){
+ case 8:
+ reg_w(0x83c6, 0x00);
+ break;
+ case 16:
+ reg_w(0x83c6, 0x60);
+ break;
+ case 24:
+ reg_w(0x83c6, 0xe0);
+ break;
+ default:
+ printk("Illegal color-depth: %i\n", bpp);
+ }
+
+ reg_w(VDAC_ADDRESS, 0x00);
+
+ seq_w(SEQ_MAP_MASK, 0x0f );
+
+ return 0;
+}
+
+/*
+ * Initialization
+ *
+ * Set the default video mode for this chipset. If a video mode was
+ * specified on the command line, it will override the default mode.
+ */
+
+static int retz3_init(void)
+{
+ int i;
+#if 0
+ volatile unsigned long *CursorBase;
+#endif
+ unsigned long board_addr, board_size;
+ struct ConfigDev *cd;
+
+ cd = zorro_get_board (z3_key);
+ zorro_config_board (z3_key, 0);
+ board_addr = (unsigned long)cd->cd_BoardAddr;
+ board_size = (unsigned long)cd->cd_BoardSize;
+
+ for (i = 0; i < 256; i++){
+ for (i = 0; i < 256; i++){
+ retz3_color_table [i][0] = i;
+ retz3_color_table [i][1] = i;
+ retz3_color_table [i][2] = i;
+ retz3_color_table [i][3] = 0;
+ }
+ }
+
+ *memstart = (*memstart + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+
+ z3_mem = kernel_map (board_addr, board_size,
+ KERNELMAP_NOCACHE_SER, memstart);
+
+ z3_regs = (char*) z3_mem;
+ z3_fbmem = z3_mem + VIDEO_MEM_OFFSET;
+
+ /* Get memory size - for now we asume its a 4MB board */
+
+ z3_size = 0x00400000; /* 4 MB */
+
+ memset ((char*)z3_fbmem, 0, z3_size);
+
+ /* Disable hardware cursor */
+
+ seq_w(SEQ_CURSOR_Y_INDEX, 0x00);
+
+
+#if 0
+ /* Initialize hardware cursor */
+ CursorBase = (unsigned long *)((char *)(z3_mem) + z3_size - 0x400);
+ for (i=0; i < 8; i++){
+ *(CursorBase +(i*4)) = 0xffffff00;
+ *(CursorBase+1+(i*4)) = 0xffff0000;
+ *(CursorBase+2+(i*4)) = 0xffff0000;
+ *(CursorBase+3+(i*4)) = 0xffff0000;
+ }
+ for (i=8; i < 64; i++){
+ *(CursorBase +(i*4)) = 0xffff0000;
+ *(CursorBase+1+(i*4)) = 0xffff0000;
+ *(CursorBase+2+(i*4)) = 0xffff0000;
+ *(CursorBase+3+(i*4)) = 0xffff0000;
+ }
+#endif
+
+ retz3_setcolreg (255, 56, 100, 160, 0);
+ retz3_setcolreg (254, 0, 0, 0, 0);
+
+ return 0;
+}
+
+
+/*
+ * This function should fill in the `fix' structure based on the
+ * values in the `par' structure.
+ */
+
+static int retz3_encode_fix(struct fb_fix_screeninfo *fix,
+ struct retz3_fb_par *par)
+{
+ int i;
+
+ strcpy(fix->id, retz3_fb_name);
+ fix->smem_start = z3_fbmem;
+ fix->smem_len = z3_size;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
+ if (par->bpp == 8)
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ else
+ fix->visual = FB_VISUAL_DIRECTCOLOR;
+
+ fix->xpanstep = 0;
+ fix->ypanstep = 0;
+ fix->ywrapstep = 0;
+ fix->line_length = 0;
+
+ for (i = 0; i < arraysize(fix->reserved); i++)
+ fix->reserved[i] = 0;
+
+ return 0;
+}
+
+
+/*
+ * Get the video params out of `var'. If a value doesn't fit, round
+ * it up, if it's too big, return -EINVAL.
+ */
+
+static int retz3_decode_var(struct fb_var_screeninfo *var,
+ struct retz3_fb_par *par)
+{
+ par->xres = var->xres;
+ par->yres = var->yres;
+ par->xres_vir = var->xres_virtual;
+ par->yres_vir = var->yres_virtual;
+ par->bpp = var->bits_per_pixel;
+ par->pixclock = var->pixclock;
+ par->vmode = var->vmode;
+
+ par->red = var->red;
+ par->green = var->green;
+ par->blue = var->blue;
+ par->transp = var->transp;
+
+ par->left_margin = var->left_margin;
+ par->right_margin = var->right_margin;
+ par->upper_margin = var->upper_margin;
+ par->lower_margin = var->lower_margin;
+ par->hsync_len = var->hsync_len;
+ par->vsync_len = var->vsync_len;
+
+ return 0;
+}
+
+
+/*
+ * Fill the `var' structure based on the values in `par' and maybe
+ * other values read out of the hardware.
+ */
+
+static int retz3_encode_var(struct fb_var_screeninfo *var,
+ struct retz3_fb_par *par)
+{
+ int i;
+
+ var->xres = par->xres;
+ var->yres = par->yres;
+ var->xres_virtual = par->xres_vir;
+ var->yres_virtual = par->yres_vir;
+ var->xoffset = 0;
+ var->yoffset = 0;
+
+ var->bits_per_pixel = par->bpp;
+ var->grayscale = 0;
+
+ var->red = par->red;
+ var->green = par->green;
+ var->blue = par->blue;
+ var->transp = par->transp;
+
+ var->nonstd = 0;
+ var->activate = 0;
+
+ var->height = -1;
+ var->width = -1;
+
+ var->accel = FB_ACCEL_RETINAZ3;
+
+ var->pixclock = par->pixclock;
+
+ var->sync = 0; /* ??? */
+ var->left_margin = par->left_margin;
+ var->right_margin = par->right_margin;
+ var->upper_margin = par->upper_margin;
+ var->lower_margin = par->lower_margin;
+ var->hsync_len = par->hsync_len;
+ var->vsync_len = par->vsync_len;
+
+ for (i = 0; i < arraysize(var->reserved); i++)
+ var->reserved[i] = 0;
+
+ var->vmode = par->vmode;
+ return 0;
+}
+
+
+/*
+ * Set a single color register. The values supplied are already
+ * rounded down to the hardware's capabilities (according to the
+ * entries in the var structure). Return != 0 for invalid regno.
+ */
+
+static int retz3_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp)
+{
+ /* We'll get to this */
+
+ if (regno > 255)
+ return 1;
+
+ retz3_color_table [regno][0] = red & 0xff;
+ retz3_color_table [regno][1] = green & 0xff;
+ retz3_color_table [regno][2] = blue & 0xff;
+ retz3_color_table [regno][3] = transp;
+
+ reg_w(VDAC_ADDRESS_W, regno);
+ reg_w(VDAC_DATA, (red & 0xff) >> 2);
+ reg_w(VDAC_DATA, (green & 0xff) >> 2);
+ reg_w(VDAC_DATA, (blue & 0xff) >> 2);
+
+ return 0;
+}
+
+
+/*
+ * Read a single color register and split it into
+ * colors/transparent. Return != 0 for invalid regno.
+ */
+
+static int retz3_getcolreg(unsigned int regno, unsigned int *red,
+ unsigned int *green, unsigned int *blue,
+ unsigned int *transp)
+{
+ if (regno > 255)
+ return 1;
+ *red = retz3_color_table [regno][0];
+ *green = retz3_color_table [regno][1];
+ *blue = retz3_color_table [regno][2];
+ *transp = retz3_color_table [regno][3];
+ return 0;
+}
+
+
+/*
+ * (Un)Blank the screen
+ */
+
+void retz3_blank(int blank)
+{
+ int i;
+
+ if (blank)
+ for (i = 0; i < 256; i++){
+ reg_w(VDAC_ADDRESS_W, i);
+ reg_w(VDAC_DATA, 0);
+ reg_w(VDAC_DATA, 0);
+ reg_w(VDAC_DATA, 0);
+ }
+ else
+ for (i = 0; i < 256; i++){
+ reg_w(VDAC_ADDRESS_W, i);
+ reg_w(VDAC_DATA, retz3_color_table [i][0] >> 2);
+ reg_w(VDAC_DATA, retz3_color_table [i][1] >> 2);
+ reg_w(VDAC_DATA, retz3_color_table [i][2] >> 2);
+ }
+}
+
+
+void retz3_bitblt (struct fb_var_screeninfo *var,
+ unsigned short srcx, unsigned short srcy, unsigned
+ short destx, unsigned short desty, unsigned short
+ width, unsigned short height, unsigned short cmd,
+ unsigned short mask)
+{
+
+ volatile unsigned long *acm = (unsigned long *) (z3_mem + ACM_OFFSET);
+ unsigned long *pattern = (unsigned long *)(z3_fbmem + PAT_MEM_OFF);
+
+ unsigned short mod;
+ unsigned long tmp;
+ unsigned long pat, src, dst;
+ unsigned char blt_status;
+
+ int i, xres_virtual = var->xres_virtual;
+ short bpp = (var->bits_per_pixel & 0xff);
+
+ if (bpp < 8)
+ bpp = 8;
+
+ tmp = mask | (mask << 16);
+
+#if 0
+ /*
+ * Check for blitter finished before we start messing with the
+ * pattern.
+ */
+ do{
+ blt_status = *(((volatile unsigned char *)acm) +
+ (ACM_START_STATUS + 2));
+ }while ((blt_status & 1) == 0);
+#endif
+
+ i = 0;
+ do{
+ *pattern++ = tmp;
+ }while(i++ < bpp/4);
+
+ tmp = cmd << 8;
+ *(acm + ACM_RASTEROP_ROTATION/4) = tmp;
+
+ mod = 0xc0c2;
+
+ pat = 8 * PAT_MEM_OFF;
+ dst = bpp * (destx + desty * xres_virtual);
+
+ /*
+ * Source is not set for clear.
+ */
+ if ((cmd != Z3BLTclear) && (cmd != Z3BLTset)) {
+ src = bpp * (srcx + srcy * xres_virtual);
+
+ if (destx > srcx) {
+ mod &= ~0x8000;
+ src += bpp * (width - 1);
+ dst += bpp * (width - 1);
+ pat += bpp * 2;
+ }
+ if (desty > srcy) {
+ mod &= ~0x4000;
+ src += bpp * (height - 1) * xres_virtual;
+ dst += bpp * (height - 1) * xres_virtual;
+ pat += bpp * 4;
+ }
+
+ *(acm + ACM_SOURCE/4) = cpu_to_le32(src);
+ }
+
+ *(acm + ACM_PATTERN/4) = cpu_to_le32(pat);
+
+ *(acm + ACM_DESTINATION/4) = cpu_to_le32(dst);
+
+ tmp = mod << 16;
+ *(acm + ACM_CONTROL/4) = tmp;
+
+ tmp = width | (height << 16);
+
+ *(acm + ACM_BITMAP_DIMENSION/4) = cpu_to_le32(tmp);
+
+ *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
+ *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
+
+ /*
+ * No reason to wait for the blitter to finish, it is better
+ * just to check if it has finished before we use it again.
+ */
+#if 1
+#if 0
+ while ((*(((volatile unsigned char *)acm) +
+ (ACM_START_STATUS + 2)) & 1) == 0);
+#else
+ do{
+ blt_status = *(((volatile unsigned char *)acm) +
+ (ACM_START_STATUS + 2));
+ }
+ while ((blt_status & 1) == 0);
+#endif
+#endif
+}
+
+#if 0
+void retz3_fill (unsigned short x, unsigned short y, unsigned
+ short width, unsigned short height,
+ unsigned short mode, unsigned short color)
+{
+
+}
+#endif
+
+
+/**************************************************************
+ * Move cursor to x, y
+ */
+void retz3_MoveCursor (unsigned short x, unsigned short y)
+{
+ /* Guess we gotta deal with the cursor at some point */
+}
+
+
+/* -------------------- Interfaces to hardware functions -------------------- */
+
+
+static struct fb_hwswitch retz3_switch = {
+ retz3_init, retz3_encode_fix, retz3_decode_var, retz3_encode_var,
+ retz3_getcolreg, retz3_setcolreg, retz3_blank
+};
+
+
+/* -------------------- Generic routines ------------------------------------ */
+
+
+/*
+ * Fill the hardware's `par' structure.
+ */
+
+static void retz3_fb_get_par(struct retz3_fb_par *par)
+{
+ if (current_par_valid)
+ *par = current_par;
+ else
+ fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], par);
+}
+
+
+static void retz3_fb_set_par(struct retz3_fb_par *par)
+{
+ current_par = *par;
+ current_par_valid = 1;
+}
+
+
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
+{
+ int err, activate;
+ struct retz3_fb_par par;
+
+ if ((err = fbhw->decode_var(var, &par)))
+ return err;
+ activate = var->activate;
+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
+ retz3_fb_set_par(&par);
+ fbhw->encode_var(var, &par);
+ var->activate = activate;
+
+#if 1
+ retz3_set_video(var, &current_par);
+#endif
+ return 0;
+}
+
+
+/*
+ * Default Colormaps
+ */
+
+static unsigned short red16[] =
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0xc000,
+ 0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff };
+static unsigned short green16[] =
+ { 0x0000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0xc000,
+ 0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff };
+static unsigned short blue16[] =
+ { 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000,
+ 0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff };
+
+
+static struct fb_cmap default_16_colors =
+ { 0, 16, red16, green16, blue16, NULL };
+
+
+static struct fb_cmap *get_default_colormap(int bpp)
+{
+ return &default_16_colors;
+}
+
+
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7fff-(val))>>16)
+#define CNVT_FROMHW(val,width) (((width) ? ((((val)<<16)-(val)) / \
+ ((1<<(width))-1)) : 0))
+
+static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+ int kspc)
+{
+ int i, start;
+ unsigned short *red, *green, *blue, *transp;
+ unsigned int hred, hgreen, hblue, htransp;
+
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ start = cmap->start;
+
+ if (start < 0)
+ return -EINVAL;
+ for (i = 0; i < cmap->len; i++) {
+ if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
+ return 0;
+ hred = CNVT_FROMHW(hred, var->red.length);
+ hgreen = CNVT_FROMHW(hgreen, var->green.length);
+ hblue = CNVT_FROMHW(hblue, var->blue.length);
+ htransp = CNVT_FROMHW(htransp, var->transp.length);
+ if (kspc) {
+ *red = hred;
+ *green = hgreen;
+ *blue = hblue;
+ if (transp)
+ *transp = htransp;
+ } else {
+ put_user(hred, red);
+ put_user(hgreen, green);
+ put_user(hblue, blue);
+ if (transp)
+ put_user(htransp, transp);
+ }
+ red++;
+ green++;
+ blue++;
+ if (transp)
+ transp++;
+ }
+ return 0;
+}
+
+
+static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+ int kspc)
+{
+ int i, start;
+ unsigned short *red, *green, *blue, *transp;
+ unsigned int hred, hgreen, hblue, htransp;
+
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ start = cmap->start;
+
+ if (start < 0)
+ return -EINVAL;
+ for (i = 0; i < cmap->len; i++) {
+ if (kspc) {
+ hred = *red;
+ hgreen = *green;
+ hblue = *blue;
+ htransp = transp ? *transp : 0;
+ } else {
+ get_user(hred, red);
+ get_user(hgreen, green);
+ get_user(hblue, blue);
+ if (transp)
+ get_user(htransp, transp);
+ else
+ htransp = 0;
+ }
+ hred = CNVT_TOHW(hred, var->red.length);
+ hgreen = CNVT_TOHW(hgreen, var->green.length);
+ hblue = CNVT_TOHW(hblue, var->blue.length);
+ htransp = CNVT_TOHW(htransp, var->transp.length);
+ red++;
+ green++;
+ blue++;
+ if (transp)
+ transp++;
+ if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
+ return 0;
+ }
+ return 0;
+}
+
+
+static void do_install_cmap(int con)
+{
+ if (con != currcon)
+ return;
+ if (disp[con].cmap.len)
+ do_fb_set_cmap(&disp[con].cmap, &disp[con].var, 1);
+ else
+ do_fb_set_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
+ &disp[con].var, 1);
+}
+
+
+static void memcpy_fs(int fsfromto, void *to, void *from, int len)
+{
+ switch (fsfromto) {
+ case 0:
+ memcpy(to, from, len);
+ return;
+ case 1:
+ copy_from_user(to, from, len);
+ return;
+ case 2:
+ copy_to_user(to, from, len);
+ return;
+ }
+}
+
+
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+{
+ int size;
+ int tooff = 0, fromoff = 0;
+
+ if (to->start > from->start)
+ fromoff = to->start-from->start;
+ else
+ tooff = from->start-to->start;
+ size = to->len-tooff;
+ if (size > from->len-fromoff)
+ size = from->len-fromoff;
+ if (size < 0)
+ return;
+ size *= sizeof(unsigned short);
+ memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
+ memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
+ memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
+ if (from->transp && to->transp)
+ memcpy_fs(fsfromto, to->transp+tooff,
+ from->transp+fromoff, size);
+}
+
+
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
+{
+ int size = len*sizeof(unsigned short);
+
+ if (cmap->len != len) {
+ if (cmap->red)
+ kfree(cmap->red);
+ if (cmap->green)
+ kfree(cmap->green);
+ if (cmap->blue)
+ kfree(cmap->blue);
+ if (cmap->transp)
+ kfree(cmap->transp);
+ cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
+ cmap->len = 0;
+ if (!len)
+ return 0;
+ if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
+ return -1;
+ if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
+ return -1;
+ if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
+ return -1;
+ if (transp) {
+ if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
+ return -1;
+ } else
+ cmap->transp = NULL;
+ }
+ cmap->start = 0;
+ cmap->len = len;
+ copy_cmap(get_default_colormap(len), cmap, 0);
+ return 0;
+}
+
+
+/*
+ * Get the Fixed Part of the Display
+ */
+
+static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
+{
+ struct retz3_fb_par par;
+ int error = 0;
+
+ if (con == -1)
+ retz3_fb_get_par(&par);
+ else
+ error = fbhw->decode_var(&disp[con].var, &par);
+ return(error ? error : fbhw->encode_fix(fix, &par));
+}
+
+
+/*
+ * Get the User Defined Part of the Display
+ */
+
+static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con)
+{
+ struct retz3_fb_par par;
+ int error = 0;
+
+ if (con == -1) {
+ retz3_fb_get_par(&par);
+ error = fbhw->encode_var(var, &par);
+ } else
+ *var = disp[con].var;
+ return error;
+}
+
+
+static void retz3_fb_set_disp(int con)
+{
+ struct fb_fix_screeninfo fix;
+
+ retz3_fb_get_fix(&fix, con);
+ if (con == -1)
+ con = 0;
+ disp[con].screen_base = (unsigned char *)fix.smem_start;
+ disp[con].visual = fix.visual;
+ disp[con].type = fix.type;
+ disp[con].type_aux = fix.type_aux;
+ disp[con].ypanstep = fix.ypanstep;
+ disp[con].ywrapstep = fix.ywrapstep;
+ disp[con].can_soft_blank = 1;
+ disp[con].inverse = z3fb_inverse;
+}
+
+
+/*
+ * Set the User Defined Part of the Display
+ */
+
+static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con)
+{
+ int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
+
+ if ((err = do_fb_set_var(var, con == currcon)))
+ return err;
+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+ oldxres = disp[con].var.xres;
+ oldyres = disp[con].var.yres;
+ oldvxres = disp[con].var.xres_virtual;
+ oldvyres = disp[con].var.yres_virtual;
+ oldbpp = disp[con].var.bits_per_pixel;
+ disp[con].var = *var;
+ if (oldxres != var->xres || oldyres != var->yres ||
+ oldvxres != var->xres_virtual ||
+ oldvyres != var->yres_virtual ||
+ oldbpp != var->bits_per_pixel) {
+ retz3_fb_set_disp(con);
+ (*fb_info.changevar)(con);
+ alloc_cmap(&disp[con].cmap, 0, 0);
+ do_install_cmap(con);
+ }
+ }
+ var->activate = 0;
+ return 0;
+}
+
+
+/*
+ * Get the Colormap
+ */
+
+static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+ if (con == currcon) /* current console? */
+ return(do_fb_get_cmap(cmap, &disp[con].var, kspc));
+ else if (disp[con].cmap.len) /* non default colormap? */
+ copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
+ else
+ copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
+ cmap, kspc ? 0 : 2);
+ return 0;
+}
+
+
+/*
+ * Set the Colormap
+ */
+
+static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+ int err;
+
+ if (!disp[con].cmap.len) { /* no colormap allocated? */
+ if ((err = alloc_cmap(&disp[con].cmap,
+ 1<<disp[con].var.bits_per_pixel, 0)))
+ return err;
+ }
+ if (con == currcon) /* current console? */
+ return(do_fb_set_cmap(cmap, &disp[con].var, kspc));
+ else
+ copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
+ return 0;
+}
+
+
+/*
+ * Pan or Wrap the Display
+ *
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+
+static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con)
+{
+ return -EINVAL;
+}
+
+
+/*
+ * RetinaZ3 Frame Buffer Specific ioctls
+ */
+
+static int retz3_fb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con)
+{
+ return -EINVAL;
+}
+
+
+static struct fb_ops retz3_fb_ops = {
+ retz3_fb_get_fix, retz3_fb_get_var, retz3_fb_set_var, retz3_fb_get_cmap,
+ retz3_fb_set_cmap, retz3_fb_pan_display, retz3_fb_ioctl
+};
+
+
+int retz3_probe(void)
+{
+ z3_key = zorro_find(MANUF_MACROSYSTEMS2, PROD_RETINA_Z3, 0, 0);
+ return(z3_key);
+}
+
+
+void retz3_video_setup(char *options, int *ints)
+{
+ char *this_opt;
+ int i;
+
+ fb_info.fontname[0] = '\0';
+
+ if (!options || !*options)
+ return;
+
+ for (this_opt = strtok(options, ","); this_opt;
+ this_opt = strtok(NULL, ",")){
+ if (!strcmp(this_opt, "inverse")) {
+ z3fb_inverse = 1;
+ for (i = 0; i < 16; i++) {
+ red16[i] = ~red16[i];
+ green16[i] = ~green16[i];
+ blue16[i] = ~blue16[i];
+ }
+ } else if (!strncmp(this_opt, "font:", 5))
+ strcpy(fb_info.fontname, this_opt+5);
+ else
+ z3fb_mode = get_video_mode(this_opt);
+ }
+}
+
+
+/*
+ * Initialization
+ */
+
+struct fb_info *retz3_fb_init(long *mem_start)
+{
+ int err;
+ struct retz3_fb_par par;
+
+ memstart = mem_start;
+
+ fbhw = &retz3_switch;
+
+ err = register_framebuffer(retz3_fb_name, &node, &retz3_fb_ops,
+ NUM_TOTAL_MODES, retz3_fb_predefined);
+ if (err < 0)
+ panic("Cannot register frame buffer\n");
+
+ fbhw->init();
+
+ if (z3fb_mode == -1)
+ z3fb_mode = 1;
+
+ fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], &par);
+ fbhw->encode_var(&retz3_fb_predefined[0], &par);
+
+ strcpy(fb_info.modename, retz3_fb_name);
+ fb_info.disp = disp;
+ fb_info.switch_con = &z3fb_switch;
+ fb_info.updatevar = &z3fb_updatevar;
+ fb_info.blank = &z3fb_blank;
+ fb_info.setcmap = &z3fb_setcmap;
+
+ do_fb_set_var(&retz3_fb_predefined[0], 0);
+ retz3_fb_get_var(&disp[0].var, -1);
+ retz3_fb_set_disp(-1);
+ do_install_cmap(0);
+
+ return &fb_info;
+}
+
+
+static int z3fb_switch(int con)
+{
+ /* Do we have to save the colormap? */
+ if (disp[currcon].cmap.len)
+ do_fb_get_cmap(&disp[currcon].cmap, &disp[currcon].var, 1);
+
+ do_fb_set_var(&disp[con].var, 1);
+ currcon = con;
+ /* Install new colormap */
+ do_install_cmap(con);
+ return 0;
+}
+
+
+/*
+ * Update the `var' structure (called by fbcon.c)
+ *
+ * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
+ * Since it's called by a kernel driver, no range checking is done.
+ */
+
+static int z3fb_updatevar(int con)
+{
+ return 0;
+}
+
+
+/*
+ * Blank the display.
+ */
+
+static void z3fb_blank(int blank)
+{
+ fbhw->blank(blank);
+}
+
+
+/*
+ * Set the colormap
+ */
+
+static int z3fb_setcmap(struct fb_cmap *cmap, int con)
+{
+ return(retz3_fb_set_cmap(cmap, 1, con));
+}
+
+
+/*
+ * Get a Video Mode
+ */
+
+static int get_video_mode(const char *name)
+{
+ int i;
+
+ for (i = 1; i <= NUM_PREDEF_MODES; i++)
+ if (!strcmp(name, retz3_fb_modenames[i])){
+ retz3_fb_predefined[0] = retz3_fb_predefined[i];
+ return i;
+ }
+ return -1;
+}
diff --git a/arch/m68k/amiga/retz3fb.h b/arch/m68k/amiga/retz3fb.h
new file mode 100644
index 000000000..9ff209060
--- /dev/null
+++ b/arch/m68k/amiga/retz3fb.h
@@ -0,0 +1,572 @@
+/*
+ * Linux/arch/m68k/amiga/retz3fb.h -- Defines and macros for the
+ * RetinaZ3 frame buffer device
+ *
+ * Copyright (C) 1997 Jes Sorensen
+ *
+ * History:
+ * - 22 Jan 97: Initial work
+ *
+ *
+ * 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.
+ */
+
+/*
+ * Macros to read and write to registers.
+ */
+#define reg_w(reg,dat) (*(z3_regs + reg) = dat)
+#define reg_r(reg) (*(z3_regs + reg))
+
+/*
+ * Macro to access the sequencer.
+ */
+#define seq_w(sreg,sdat) \
+ do{ reg_w(SEQ_IDX, sreg); reg_w(SEQ_DATA, sdat); } while(0)
+
+/*
+ * Macro to access the CRT controller.
+ */
+#define crt_w(creg,cdat) \
+ do{ reg_w(CRT_IDX, creg); reg_w(CRT_DATA, cdat); } while(0)
+
+/*
+ * Macro to access the graphics controller.
+ */
+#define gfx_w(greg,gdat) \
+ do{ reg_w(GFX_IDX, greg); reg_w(GFX_DATA, gdat); } while(0)
+
+/*
+ * Macro to access the attribute controller.
+ */
+#define attr_w(areg,adat) \
+ do{ reg_w(ACT_IDX, areg); reg_w(ACT_DATA, adat); } while(0)
+
+/*
+ * Macro to access the pll.
+ */
+#define pll_w(preg,pdat) \
+ do{ reg_w(PLL_IDX, preg); \
+ reg_w(PLL_DATA, (pdat & 0xff)); \
+ reg_w(PLL_DATA, (pdat >> 8));\
+ } while(0)
+
+/*
+ * Offsets
+ */
+#define VIDEO_MEM_OFFSET 0x00c00000
+#define ACM_OFFSET 0x00b00000
+
+/*
+ * Accelerator Control Menu
+ */
+#define ACM_PRIMARY_OFFSET 0x00
+#define ACM_SECONDARY_OFFSET 0x04
+#define ACM_MODE_CONTROL 0x08
+#define ACM_CURSOR_POSITION 0x0c
+#define ACM_START_STATUS 0x30
+#define ACM_CONTROL 0x34
+#define ACM_RASTEROP_ROTATION 0x38
+#define ACM_BITMAP_DIMENSION 0x3c
+#define ACM_DESTINATION 0x40
+#define ACM_SOURCE 0x44
+#define ACM_PATTERN 0x48
+#define ACM_FOREGROUND 0x4c
+#define ACM_BACKGROUND 0x50
+
+/*
+ * Video DAC addresses
+ */
+#define VDAC_ADDRESS 0x03c8
+#define VDAC_ADDRESS_W 0x03c8
+#define VDAC_ADDRESS_R 0x03c7
+#define VDAC_STATE 0x03c7
+#define VDAC_DATA 0x03c9
+#define VDAC_MASK 0x03c6
+
+/*
+ * Sequencer
+ */
+#define SEQ_IDX 0x03c4 /* Sequencer Index */
+#define SEQ_DATA 0x03c5
+#define SEQ_RESET 0x00
+#define SEQ_CLOCKING_MODE 0x01
+#define SEQ_MAP_MASK 0x02
+#define SEQ_CHAR_MAP_SELECT 0x03
+#define SEQ_MEMORY_MODE 0x04
+#define SEQ_EXTENDED_ENABLE 0x05 /* NCR extensions */
+#define SEQ_UNKNOWN1 0x06
+#define SEQ_UNKNOWN2 0x07
+#define SEQ_CHIP_ID 0x08
+#define SEQ_UNKNOWN3 0x09
+#define SEQ_CURSOR_COLOR1 0x0a
+#define SEQ_CURSOR_COLOR0 0x0b
+#define SEQ_CURSOR_CONTROL 0x0c
+#define SEQ_CURSOR_X_LOC_HI 0x0d
+#define SEQ_CURSOR_X_LOC_LO 0x0e
+#define SEQ_CURSOR_Y_LOC_HI 0x0f
+#define SEQ_CURSOR_Y_LOC_LO 0x10
+#define SEQ_CURSOR_X_INDEX 0x11
+#define SEQ_CURSOR_Y_INDEX 0x12
+#define SEQ_CURSOR_STORE_HI 0x13
+#define SEQ_CURSOR_STORE_LO 0x14
+#define SEQ_CURSOR_ST_OFF_HI 0x15
+#define SEQ_CURSOR_ST_OFF_LO 0x16
+#define SEQ_CURSOR_PIXELMASK 0x17
+#define SEQ_PRIM_HOST_OFF_HI 0x18
+#define SEQ_PRIM_HOST_OFF_LO 0x19
+#define SEQ_LINEAR_0 0x1a
+#define SEQ_LINEAR_1 0x1b
+#define SEQ_SEC_HOST_OFF_HI 0x1c
+#define SEQ_SEC_HOST_OFF_LO 0x1d
+#define SEQ_EXTENDED_MEM_ENA 0x1e
+#define SEQ_EXT_CLOCK_MODE 0x1f
+#define SEQ_EXT_VIDEO_ADDR 0x20
+#define SEQ_EXT_PIXEL_CNTL 0x21
+#define SEQ_BUS_WIDTH_FEEDB 0x22
+#define SEQ_PERF_SELECT 0x23
+#define SEQ_COLOR_EXP_WFG 0x24
+#define SEQ_COLOR_EXP_WBG 0x25
+#define SEQ_EXT_RW_CONTROL 0x26
+#define SEQ_MISC_FEATURE_SEL 0x27
+#define SEQ_COLOR_KEY_CNTL 0x28
+#define SEQ_COLOR_KEY_MATCH0 0x29
+#define SEQ_COLOR_KEY_MATCH1 0x2a
+#define SEQ_COLOR_KEY_MATCH2 0x2b
+#define SEQ_UNKNOWN6 0x2c
+#define SEQ_CRC_CONTROL 0x2d
+#define SEQ_CRC_DATA_LOW 0x2e
+#define SEQ_CRC_DATA_HIGH 0x2f
+#define SEQ_MEMORY_MAP_CNTL 0x30
+#define SEQ_ACM_APERTURE_1 0x31
+#define SEQ_ACM_APERTURE_2 0x32
+#define SEQ_ACM_APERTURE_3 0x33
+#define SEQ_BIOS_UTILITY_0 0x3e
+#define SEQ_BIOS_UTILITY_1 0x3f
+
+/*
+ * Graphics Controller
+ */
+#define GFX_IDX 0x03ce
+#define GFX_DATA 0x03cf
+#define GFX_SET_RESET 0x00
+#define GFX_ENABLE_SET_RESET 0x01
+#define GFX_COLOR_COMPARE 0x02
+#define GFX_DATA_ROTATE 0x03
+#define GFX_READ_MAP_SELECT 0x04
+#define GFX_GRAPHICS_MODE 0x05
+#define GFX_MISC 0x06
+#define GFX_COLOR_XCARE 0x07
+#define GFX_BITMASK 0x08
+
+/*
+ * CRT Controller
+ */
+#define CRT_IDX 0x03d4
+#define CRT_DATA 0x03d5
+#define CRT_HOR_TOTAL 0x00
+#define CRT_HOR_DISP_ENA_END 0x01
+#define CRT_START_HOR_BLANK 0x02
+#define CRT_END_HOR_BLANK 0x03
+#define CRT_START_HOR_RETR 0x04
+#define CRT_END_HOR_RETR 0x05
+#define CRT_VER_TOTAL 0x06
+#define CRT_OVERFLOW 0x07
+#define CRT_PRESET_ROW_SCAN 0x08
+#define CRT_MAX_SCAN_LINE 0x09
+#define CRT_CURSOR_START 0x0a
+#define CRT_CURSOR_END 0x0b
+#define CRT_START_ADDR_HIGH 0x0c
+#define CRT_START_ADDR_LOW 0x0d
+#define CRT_CURSOR_LOC_HIGH 0x0e
+#define CRT_CURSOR_LOC_LOW 0x0f
+#define CRT_START_VER_RETR 0x10
+#define CRT_END_VER_RETR 0x11
+#define CRT_VER_DISP_ENA_END 0x12
+#define CRT_OFFSET 0x13
+#define CRT_UNDERLINE_LOC 0x14
+#define CRT_START_VER_BLANK 0x15
+#define CRT_END_VER_BLANK 0x16
+#define CRT_MODE_CONTROL 0x17
+#define CRT_LINE_COMPARE 0x18
+#define CRT_UNKNOWN1 0x19
+#define CRT_UNKNOWN2 0x1a
+#define CRT_UNKNOWN3 0x1b
+#define CRT_UNKNOWN4 0x1c
+#define CRT_UNKNOWN5 0x1d
+#define CRT_UNKNOWN6 0x1e
+#define CRT_UNKNOWN7 0x1f
+#define CRT_UNKNOWN8 0x20
+#define CRT_UNKNOWN9 0x21
+#define CRT_UNKNOWN10 0x22
+#define CRT_UNKNOWN11 0x23
+#define CRT_UNKNOWN12 0x24
+#define CRT_UNKNOWN13 0x25
+#define CRT_UNKNOWN14 0x26
+#define CRT_UNKNOWN15 0x27
+#define CRT_UNKNOWN16 0x28
+#define CRT_UNKNOWN17 0x29
+#define CRT_UNKNOWN18 0x2a
+#define CRT_UNKNOWN19 0x2b
+#define CRT_UNKNOWN20 0x2c
+#define CRT_UNKNOWN21 0x2d
+#define CRT_UNKNOWN22 0x2e
+#define CRT_UNKNOWN23 0x2f
+#define CRT_EXT_HOR_TIMING1 0x30 /* NCR crt extensions */
+#define CRT_EXT_START_ADDR 0x31
+#define CRT_EXT_HOR_TIMING2 0x32
+#define CRT_EXT_VER_TIMING 0x33
+#define CRT_MONITOR_POWER 0x34
+
+/*
+ * General Registers
+ */
+#define GREG_STATUS0_R 0x03c2
+#define GREG_STATUS1_R 0x03da
+#define GREG_MISC_OUTPUT_R 0x03cc
+#define GREG_MISC_OUTPUT_W 0x03c2
+#define GREG_FEATURE_CONTROL_R 0x03ca
+#define GREG_FEATURE_CONTROL_W 0x03da
+#define GREG_POS 0x0102
+
+/*
+ * Attribute Controller
+ */
+#define ACT_IDX 0x03C0
+#define ACT_ADDRESS_R 0x03C0
+#define ACT_DATA 0x03C0
+#define ACT_ADDRESS_RESET 0x03DA
+#define ACT_PALETTE0 0x00
+#define ACT_PALETTE1 0x01
+#define ACT_PALETTE2 0x02
+#define ACT_PALETTE3 0x03
+#define ACT_PALETTE4 0x04
+#define ACT_PALETTE5 0x05
+#define ACT_PALETTE6 0x06
+#define ACT_PALETTE7 0x07
+#define ACT_PALETTE8 0x08
+#define ACT_PALETTE9 0x09
+#define ACT_PALETTE10 0x0A
+#define ACT_PALETTE11 0x0B
+#define ACT_PALETTE12 0x0C
+#define ACT_PALETTE13 0x0D
+#define ACT_PALETTE14 0x0E
+#define ACT_PALETTE15 0x0F
+#define ACT_ATTR_MODE_CNTL 0x10
+#define ACT_OVERSCAN_COLOR 0x11
+#define ACT_COLOR_PLANE_ENA 0x12
+#define ACT_HOR_PEL_PANNING 0x13
+#define ACT_COLOR_SELECT 0x14
+
+/*
+ * PLL
+ */
+#define PLL_IDX 0x83c8
+#define PLL_DATA 0x83c9
+
+/*
+ * Blitter operations
+ */
+#define Z3BLTclear 0x00 /* 0 */
+#define Z3BLTand 0x80 /* src AND dst */
+#define Z3BLTandReverse 0x40 /* src AND NOT dst */
+#define Z3BLTcopy 0xc0 /* src */
+#define Z3BLTandInverted 0x20 /* NOT src AND dst */
+#define Z3BLTnoop 0xa0 /* dst */
+#define Z3BLTxor 0x60 /* src XOR dst */
+#define Z3BLTor 0xe0 /* src OR dst */
+#define Z3BLTnor 0x10 /* NOT src AND NOT dst */
+#define Z3BLTequiv 0x90 /* NOT src XOR dst */
+#define Z3BLTinvert 0x50 /* NOT dst */
+#define Z3BLTorReverse 0xd0 /* src OR NOT dst */
+#define Z3BLTcopyInverted 0x30 /* NOT src */
+#define Z3BLTorInverted 0xb0 /* NOT src OR dst */
+#define Z3BLTnand 0x70 /* NOT src OR NOT dst */
+#define Z3BLTset 0xf0 /* 1 */
+/*
+ * Linux/arch/m68k/amiga/retz3fb.h -- Defines and macros for the
+ * RetinaZ3 frame buffer device
+ *
+ * Copyright (C) 1997 Jes Sorensen
+ *
+ * History:
+ * - 22 Jan 97: Initial work
+ *
+ *
+ * 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.
+ */
+
+/*
+ * Macros to read and write to registers.
+ */
+#define reg_w(reg,dat) (*(z3_regs + reg) = dat)
+#define reg_r(reg) (*(z3_regs + reg))
+
+/*
+ * Macro to access the sequencer.
+ */
+#define seq_w(sreg,sdat) \
+ do{ reg_w(SEQ_IDX, sreg); reg_w(SEQ_DATA, sdat); } while(0)
+
+/*
+ * Macro to access the CRT controller.
+ */
+#define crt_w(creg,cdat) \
+ do{ reg_w(CRT_IDX, creg); reg_w(CRT_DATA, cdat); } while(0)
+
+/*
+ * Macro to access the graphics controller.
+ */
+#define gfx_w(greg,gdat) \
+ do{ reg_w(GFX_IDX, greg); reg_w(GFX_DATA, gdat); } while(0)
+
+/*
+ * Macro to access the attribute controller.
+ */
+#define attr_w(areg,adat) \
+ do{ reg_w(ACT_IDX, areg); reg_w(ACT_DATA, adat); } while(0)
+
+/*
+ * Macro to access the pll.
+ */
+#define pll_w(preg,pdat) \
+ do{ reg_w(PLL_IDX, preg); \
+ reg_w(PLL_DATA, (pdat & 0xff)); \
+ reg_w(PLL_DATA, (pdat >> 8));\
+ } while(0)
+
+/*
+ * Offsets
+ */
+#define VIDEO_MEM_OFFSET 0x00c00000
+#define ACM_OFFSET 0x00b00000
+
+/*
+ * Accelerator Control Menu
+ */
+#define ACM_PRIMARY_OFFSET 0x00
+#define ACM_SECONDARY_OFFSET 0x04
+#define ACM_MODE_CONTROL 0x08
+#define ACM_CURSOR_POSITION 0x0c
+#define ACM_START_STATUS 0x30
+#define ACM_CONTROL 0x34
+#define ACM_RASTEROP_ROTATION 0x38
+#define ACM_BITMAP_DIMENSION 0x3c
+#define ACM_DESTINATION 0x40
+#define ACM_SOURCE 0x44
+#define ACM_PATTERN 0x48
+#define ACM_FOREGROUND 0x4c
+#define ACM_BACKGROUND 0x50
+
+/*
+ * Video DAC addresses
+ */
+#define VDAC_ADDRESS 0x03c8
+#define VDAC_ADDRESS_W 0x03c8
+#define VDAC_ADDRESS_R 0x03c7
+#define VDAC_STATE 0x03c7
+#define VDAC_DATA 0x03c9
+#define VDAC_MASK 0x03c6
+
+/*
+ * Sequencer
+ */
+#define SEQ_IDX 0x03c4 /* Sequencer Index */
+#define SEQ_DATA 0x03c5
+#define SEQ_RESET 0x00
+#define SEQ_CLOCKING_MODE 0x01
+#define SEQ_MAP_MASK 0x02
+#define SEQ_CHAR_MAP_SELECT 0x03
+#define SEQ_MEMORY_MODE 0x04
+#define SEQ_EXTENDED_ENABLE 0x05 /* NCR extensions */
+#define SEQ_UNKNOWN1 0x06
+#define SEQ_UNKNOWN2 0x07
+#define SEQ_CHIP_ID 0x08
+#define SEQ_UNKNOWN3 0x09
+#define SEQ_CURSOR_COLOR1 0x0a
+#define SEQ_CURSOR_COLOR0 0x0b
+#define SEQ_CURSOR_CONTROL 0x0c
+#define SEQ_CURSOR_X_LOC_HI 0x0d
+#define SEQ_CURSOR_X_LOC_LO 0x0e
+#define SEQ_CURSOR_Y_LOC_HI 0x0f
+#define SEQ_CURSOR_Y_LOC_LO 0x10
+#define SEQ_CURSOR_X_INDEX 0x11
+#define SEQ_CURSOR_Y_INDEX 0x12
+#define SEQ_CURSOR_STORE_HI 0x13
+#define SEQ_CURSOR_STORE_LO 0x14
+#define SEQ_CURSOR_ST_OFF_HI 0x15
+#define SEQ_CURSOR_ST_OFF_LO 0x16
+#define SEQ_CURSOR_PIXELMASK 0x17
+#define SEQ_PRIM_HOST_OFF_HI 0x18
+#define SEQ_PRIM_HOST_OFF_LO 0x19
+#define SEQ_LINEAR_0 0x1a
+#define SEQ_LINEAR_1 0x1b
+#define SEQ_SEC_HOST_OFF_HI 0x1c
+#define SEQ_SEC_HOST_OFF_LO 0x1d
+#define SEQ_EXTENDED_MEM_ENA 0x1e
+#define SEQ_EXT_CLOCK_MODE 0x1f
+#define SEQ_EXT_VIDEO_ADDR 0x20
+#define SEQ_EXT_PIXEL_CNTL 0x21
+#define SEQ_BUS_WIDTH_FEEDB 0x22
+#define SEQ_PERF_SELECT 0x23
+#define SEQ_COLOR_EXP_WFG 0x24
+#define SEQ_COLOR_EXP_WBG 0x25
+#define SEQ_EXT_RW_CONTROL 0x26
+#define SEQ_MISC_FEATURE_SEL 0x27
+#define SEQ_COLOR_KEY_CNTL 0x28
+#define SEQ_COLOR_KEY_MATCH0 0x29
+#define SEQ_COLOR_KEY_MATCH1 0x2a
+#define SEQ_COLOR_KEY_MATCH2 0x2b
+#define SEQ_UNKNOWN6 0x2c
+#define SEQ_CRC_CONTROL 0x2d
+#define SEQ_CRC_DATA_LOW 0x2e
+#define SEQ_CRC_DATA_HIGH 0x2f
+#define SEQ_MEMORY_MAP_CNTL 0x30
+#define SEQ_ACM_APERTURE_1 0x31
+#define SEQ_ACM_APERTURE_2 0x32
+#define SEQ_ACM_APERTURE_3 0x33
+#define SEQ_BIOS_UTILITY_0 0x3e
+#define SEQ_BIOS_UTILITY_1 0x3f
+
+/*
+ * Graphics Controller
+ */
+#define GFX_IDX 0x03ce
+#define GFX_DATA 0x03cf
+#define GFX_SET_RESET 0x00
+#define GFX_ENABLE_SET_RESET 0x01
+#define GFX_COLOR_COMPARE 0x02
+#define GFX_DATA_ROTATE 0x03
+#define GFX_READ_MAP_SELECT 0x04
+#define GFX_GRAPHICS_MODE 0x05
+#define GFX_MISC 0x06
+#define GFX_COLOR_XCARE 0x07
+#define GFX_BITMASK 0x08
+
+/*
+ * CRT Controller
+ */
+#define CRT_IDX 0x03d4
+#define CRT_DATA 0x03d5
+#define CRT_HOR_TOTAL 0x00
+#define CRT_HOR_DISP_ENA_END 0x01
+#define CRT_START_HOR_BLANK 0x02
+#define CRT_END_HOR_BLANK 0x03
+#define CRT_START_HOR_RETR 0x04
+#define CRT_END_HOR_RETR 0x05
+#define CRT_VER_TOTAL 0x06
+#define CRT_OVERFLOW 0x07
+#define CRT_PRESET_ROW_SCAN 0x08
+#define CRT_MAX_SCAN_LINE 0x09
+#define CRT_CURSOR_START 0x0a
+#define CRT_CURSOR_END 0x0b
+#define CRT_START_ADDR_HIGH 0x0c
+#define CRT_START_ADDR_LOW 0x0d
+#define CRT_CURSOR_LOC_HIGH 0x0e
+#define CRT_CURSOR_LOC_LOW 0x0f
+#define CRT_START_VER_RETR 0x10
+#define CRT_END_VER_RETR 0x11
+#define CRT_VER_DISP_ENA_END 0x12
+#define CRT_OFFSET 0x13
+#define CRT_UNDERLINE_LOC 0x14
+#define CRT_START_VER_BLANK 0x15
+#define CRT_END_VER_BLANK 0x16
+#define CRT_MODE_CONTROL 0x17
+#define CRT_LINE_COMPARE 0x18
+#define CRT_UNKNOWN1 0x19
+#define CRT_UNKNOWN2 0x1a
+#define CRT_UNKNOWN3 0x1b
+#define CRT_UNKNOWN4 0x1c
+#define CRT_UNKNOWN5 0x1d
+#define CRT_UNKNOWN6 0x1e
+#define CRT_UNKNOWN7 0x1f
+#define CRT_UNKNOWN8 0x20
+#define CRT_UNKNOWN9 0x21
+#define CRT_UNKNOWN10 0x22
+#define CRT_UNKNOWN11 0x23
+#define CRT_UNKNOWN12 0x24
+#define CRT_UNKNOWN13 0x25
+#define CRT_UNKNOWN14 0x26
+#define CRT_UNKNOWN15 0x27
+#define CRT_UNKNOWN16 0x28
+#define CRT_UNKNOWN17 0x29
+#define CRT_UNKNOWN18 0x2a
+#define CRT_UNKNOWN19 0x2b
+#define CRT_UNKNOWN20 0x2c
+#define CRT_UNKNOWN21 0x2d
+#define CRT_UNKNOWN22 0x2e
+#define CRT_UNKNOWN23 0x2f
+#define CRT_EXT_HOR_TIMING1 0x30 /* NCR crt extensions */
+#define CRT_EXT_START_ADDR 0x31
+#define CRT_EXT_HOR_TIMING2 0x32
+#define CRT_EXT_VER_TIMING 0x33
+#define CRT_MONITOR_POWER 0x34
+
+/*
+ * General Registers
+ */
+#define GREG_STATUS0_R 0x03c2
+#define GREG_STATUS1_R 0x03da
+#define GREG_MISC_OUTPUT_R 0x03cc
+#define GREG_MISC_OUTPUT_W 0x03c2
+#define GREG_FEATURE_CONTROL_R 0x03ca
+#define GREG_FEATURE_CONTROL_W 0x03da
+#define GREG_POS 0x0102
+
+/*
+ * Attribute Controller
+ */
+#define ACT_IDX 0x03C0
+#define ACT_ADDRESS_R 0x03C0
+#define ACT_DATA 0x03C0
+#define ACT_ADDRESS_RESET 0x03DA
+#define ACT_PALETTE0 0x00
+#define ACT_PALETTE1 0x01
+#define ACT_PALETTE2 0x02
+#define ACT_PALETTE3 0x03
+#define ACT_PALETTE4 0x04
+#define ACT_PALETTE5 0x05
+#define ACT_PALETTE6 0x06
+#define ACT_PALETTE7 0x07
+#define ACT_PALETTE8 0x08
+#define ACT_PALETTE9 0x09
+#define ACT_PALETTE10 0x0A
+#define ACT_PALETTE11 0x0B
+#define ACT_PALETTE12 0x0C
+#define ACT_PALETTE13 0x0D
+#define ACT_PALETTE14 0x0E
+#define ACT_PALETTE15 0x0F
+#define ACT_ATTR_MODE_CNTL 0x10
+#define ACT_OVERSCAN_COLOR 0x11
+#define ACT_COLOR_PLANE_ENA 0x12
+#define ACT_HOR_PEL_PANNING 0x13
+#define ACT_COLOR_SELECT 0x14
+
+/*
+ * PLL
+ */
+#define PLL_IDX 0x83c8
+#define PLL_DATA 0x83c9
+
+/*
+ * Blitter operations
+ */
+#define Z3BLTclear 0x00 /* 0 */
+#define Z3BLTand 0x80 /* src AND dst */
+#define Z3BLTandReverse 0x40 /* src AND NOT dst */
+#define Z3BLTcopy 0xc0 /* src */
+#define Z3BLTandInverted 0x20 /* NOT src AND dst */
+#define Z3BLTnoop 0xa0 /* dst */
+#define Z3BLTxor 0x60 /* src XOR dst */
+#define Z3BLTor 0xe0 /* src OR dst */
+#define Z3BLTnor 0x10 /* NOT src AND NOT dst */
+#define Z3BLTequiv 0x90 /* NOT src XOR dst */
+#define Z3BLTinvert 0x50 /* NOT dst */
+#define Z3BLTorReverse 0xd0 /* src OR NOT dst */
+#define Z3BLTcopyInverted 0x30 /* NOT src */
+#define Z3BLTorInverted 0xb0 /* NOT src OR dst */
+#define Z3BLTnand 0x70 /* NOT src OR NOT dst */
+#define Z3BLTset 0xf0 /* 1 */
diff --git a/arch/m68k/amiga/zorro.c b/arch/m68k/amiga/zorro.c
index ccc9c7249..acca3e6bc 100644
--- a/arch/m68k/amiga/zorro.c
+++ b/arch/m68k/amiga/zorro.c
@@ -16,7 +16,7 @@
#include <asm/setup.h>
#include <asm/bitops.h>
#include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
#ifdef CONFIG_ZORRO
@@ -82,6 +82,10 @@ BEGIN_PROD(MEMPHIS)
PROD("Stormbringer", STORMBRINGER)
END
+BEGIN_PROD(3_STATE)
+ PROD("Megamix 2000 RAM", MEGAMIX_2000)
+END
+
BEGIN_PROD(COMMODORE2)
PROD("A2088 XT Bridgeboard", A2088)
PROD("A2286 AT Bridgeboard", A2286)
@@ -141,8 +145,12 @@ BEGIN_PROD(MICROBOTICS)
PROD("StarDrive", STARDRIVE)
PROD("8-Up (Rev A)", 8_UP_A)
PROD("8-Up (Rev Z)", 8_UP_Z)
+ PROD("Delta Card RAM", DELTA_RAM)
+ PROD("8-Star RAM", 8_STAR_RAM)
+ PROD("8-Star", 8_STAR)
PROD("VXL RAM", VXL_RAM)
PROD("VXL-30 Turbo Board", VXL_30)
+ PROD("Delta Card", DELTA)
PROD("MBX 1200", MBX_1200)
PROD("Hardframe 2000", HARDFRAME_2000)
PROD("MBX 1200", MBX_1200_2)
@@ -180,8 +188,8 @@ BEGIN_PROD(SUPRA)
PROD("SupraDrive 4x4 SCSI Controller", SUPRADRIVE_4x4)
PROD("2000 DMA HD", SUPRA_2000)
PROD("500 HD/RAM", SUPRA_500)
+ PROD("500XP/2000 RAM", SUPRA_500XP)
PROD("500RX/2000 RAM", SUPRA_500RX)
- PROD("500RX/2000 RAM", SUPRA_500RX_2)
PROD("2400zi Modem", SUPRA_2400ZI)
PROD("Wordsync SCSI Controller", WORDSYNC)
PROD("Wordsync II SCSI Controller", WORDSYNC_II)
@@ -193,6 +201,10 @@ BEGIN_PROD(CSA)
PROD("12 Gauge SCSI Controller", 12GAUGE)
END
+BEGIN_PROD(MTEC2)
+ PROD("AT500 RAM", AT500_2)
+END
+
BEGIN_PROD(GVP3)
PROD("Impact SCSI/Memory", IMPACT)
END
@@ -203,7 +215,11 @@ END
BEGIN_PROD(POWER_COMPUTING)
PROD("DKB 3128 RAM", DKB_3128)
+ PROD("Rapid Fire SCSI Controller", RAPID_FIRE)
+ PROD("DKB 1202 RAM", DKB_1202)
PROD("DKB Cobra / Viper II Turbo Board", VIPER_II_COBRA)
+ PROD("WildFire 060 Turbo Board", WILDFIRE_060)
+ PROD("WildFire 060 Turbo Board", WILDFIRE_060_2)
END
BEGIN_PROD(GVP)
@@ -257,6 +273,9 @@ BEGIN_PROD(PPI)
PROD("PP&S A500 68040 Turbo Board", PPS_A500_040)
END
+BEGIN_PROD(XEBEC)
+END
+
BEGIN_PROD(SPIRIT)
PROD("HDA 506 Harddisk", HDA_506)
PROD("OctaByte RAM", OCTABYTE_RAM)
@@ -268,6 +287,7 @@ END
BEGIN_PROD(BSC3)
PROD("ALF 2 SCSI Controller", ALF_2_SCSI)
+ PROD("ALF 2 SCSI Controller", ALF_2_SCSI_2)
PROD("ALF 3 SCSI Controller", ALF_3_SCSI_2)
END
@@ -291,9 +311,17 @@ END
BEGIN_PROD(KUPKE2)
PROD("Golem SCSI-II Controller", KUPKE_SCSI_II)
PROD("Golem Box", GOLEM_BOX)
+ PROD("030/882 Turbo Board", KUPKE_TURBO)
PROD("Golem SCSI/AT Controller", KUPKE_SCSI_AT)
END
+BEGIN_PROD(GVP4)
+ PROD("A2000-RAM8/2", A2000_RAM8)
+END
+
+BEGIN_PROD(INTERWORKS_NET)
+END
+
BEGIN_PROD(HARDITAL)
PROD("TQM 68030+68882 Turbo Board", TQM)
END
@@ -301,10 +329,14 @@ END
BEGIN_PROD(BSC2)
PROD("Oktagon 2008 SCSI Controller", OKTAGON_SCSI)
PROD("Tandem AT-2008/508 IDE Controller", TANDEM)
+ PROD("Alpha RAM 1200", ALPHA_RAM_1200)
PROD("Oktagon 2008 RAM", OKTAGON_RAM)
PROD("Alfa Data MultiFace I", MULTIFACE_I)
PROD("Alfa Data MultiFace II", MULTIFACE_II)
PROD("Alfa Data MultiFace III", MULTIFACE_III)
+ PROD("Framebuffer", BSC_FRAEMBUFFER)
+ PROD("Graffiti Graphics Board (RAM)", GRAFFITI_RAM)
+ PROD("Graffiti Graphics Board (REG)", GRAFFITI_REG)
PROD("ISDN MasterCard", ISDN_MASTERCARD)
PROD("ISDN MasterCard II", ISDN_MASTERCARD_2)
END
@@ -319,12 +351,15 @@ BEGIN_PROD(IMPULSE)
END
BEGIN_PROD(IVS)
- PROD("GrandSlam RAM", GRANDSLAM)
+ PROD("GrandSlam PIC 2 RAM", GRANDSLAM_PIC_2)
+ PROD("GrandSlam PIC 1 RAM", GRANDSLAM_PIC_1)
PROD("OverDrive HD", IVS_OVERDRIVE)
PROD("Trumpcard Classic SCSI Controller", TRUMPCARD_CLASSIC)
PROD("Trumpcard Pro SCSI Controller", TRUMPCARD_PRO)
PROD("Meta-4 RAM", META_4)
+ PROD("Wavetools Sound Board", WAVETOOLS)
PROD("Vector SCSI Controller", VECTOR)
+ PROD("Vector SCSI Controller", VECTOR_2)
END
BEGIN_PROD(VECTOR)
@@ -336,6 +371,7 @@ BEGIN_PROD(XPERT_PRODEV)
PROD("Visiona Graphics Board (REG)", VISIONA_REG)
PROD("Merlin Graphics Board (RAM)", MERLIN_RAM)
PROD("Merlin Graphics Board (REG)", MERLIN_REG)
+ PROD("Merlin Graphics Board (REG)", MERLIN_REG_2)
END
BEGIN_PROD(HYDRA_SYSTEMS)
@@ -388,7 +424,11 @@ BEGIN_PROD(VILLAGE_TRONIC)
PROD("Domino Graphics Board (REG)", DOMINO_REG)
PROD("Picasso II Graphics Board (RAM)", PICASSO_II_RAM)
PROD("Picasso II Graphics Board (REG)", PICASSO_II_REG)
- PROD("Picasso II Graphics Board (REG)", PICASSO_II_REG_2)
+ PROD("Picasso II/II+ Graphics Board (Segmented Mode)", PICASSO_II_SEGM)
+ PROD("Picassio IV Graphics Board", PICASSO_IV)
+ PROD("Picassio IV Graphics Board", PICASSO_IV_2)
+ PROD("Picassio IV Graphics Board", PICASSO_IV_3)
+ PROD("Picassio IV Graphics Board", PICASSO_IV_4)
PROD("Ariadne Ethernet Card", ARIADNE)
END
@@ -402,8 +442,18 @@ BEGIN_PROD(AMITRIX)
PROD("CD-RAM Memory", AMITRIX_CD_RAM)
END
+BEGIN_PROD(ARMAX)
+ PROD("OmniBus Graphics Board", OMNIBUS)
+END
+
+BEGIN_PROD(NEWTEK)
+ PROD("VideoToaster", VIDEOTOASTER)
+END
+
BEGIN_PROD(MTEC)
+ PROD("AT500 IDE Controller", AT500)
PROD("68030 Turbo Board", MTEC_68030)
+ PROD("68020i Turbo Board", MTEC_68020I)
PROD("A1200 T68030/42 RTC Turbo Board", MTEC_T1230)
PROD("8MB RAM", MTEC_RAM)
END
@@ -439,6 +489,11 @@ BEGIN_PROD(MICRONIK)
PROD("RCA 120 RAM", RCA_120)
END
+BEGIN_PROD(MEGA_MICRO)
+ PROD("SCRAM 500 SCSI Controller", SCRAM_500_SCSI)
+ PROD("SCRAM 500 RAM", SCRAM_500_RAM)
+END
+
BEGIN_PROD(IMTRONICS2)
PROD("Hurricane 2800 68030", HURRICANE_2800_3)
PROD("Hurricane 2800 68030", HURRICANE_2800_4)
@@ -448,6 +503,15 @@ BEGIN_PROD(KUPKE3)
PROD("Golem HD 3000", GOLEM_3000)
END
+BEGIN_PROD(ITH)
+ PROD("ISDN-Master II", ISDN_MASTER_II)
+END
+
+BEGIN_PROD(VMC)
+ PROD("ISDN Blaster Z2", ISDN_BLASTER_Z2)
+ PROD("HyperCom 4", HYPERCOM_4)
+END
+
BEGIN_PROD(INFORMATION)
PROD("ISDN Engine I", ISDN_ENGINE_I)
END
@@ -479,6 +543,8 @@ BEGIN_PROD(PHASE5)
PROD("Blizzard 2060 SCSI Controller", BLIZZARD_2060SCSI)
PROD("CyberStorm Mk II", CYBERSTORM_II)
PROD("CyberVision64 Graphics Board", CYBERVISION)
+ PROD("CyberVision64-3D Graphics Board Prototype)", CYBERVISION3D_PRT)
+ PROD("CyberVision64-3D Graphics Board", CYBERVISION3D)
END
BEGIN_PROD(DPS)
@@ -487,6 +553,7 @@ END
BEGIN_PROD(APOLLO2)
PROD("A620 68020 Accelerator", A620)
+ PROD("A620 68020 Accelerator", A620_2)
END
BEGIN_PROD(APOLLO)
@@ -494,6 +561,10 @@ BEGIN_PROD(APOLLO)
PROD("Turbo Board", APOLLO_TURBO)
END
+BEGIN_PROD(PETSOFF)
+ PROD("Delfina DSP", DELFINA)
+END
+
BEGIN_PROD(UWE_GERLACH)
PROD("RAM/ROM", UG_RAM_ROM)
END
@@ -507,6 +578,7 @@ BEGIN_PROD(MACROSYSTEMS2)
PROD("Toccata Sound Board", TOCCATA)
PROD("Retina Z3 Graphics Board", RETINA_Z3)
PROD("VLab Motion", VLAB_MOTION)
+ PROD("Altais Graphics Board", ALTAIS)
PROD("Falcon '040 Turbo Board", FALCON_040)
END
@@ -514,11 +586,12 @@ BEGIN_PROD(COMBITEC)
END
BEGIN_PROD(SKI)
+ PROD("MAST Fireball SCSI Controller", MAST_FIREBALL)
PROD("SCSI / Dual Serial", SKI_SCSI_SERIAL)
END
BEGIN_PROD(CAMERON)
- PROD("Scanner Interface", CAMERON_SCANNER)
+ PROD("Personal A4", PERSONAL_A4)
END
BEGIN_PROD(REIS_WARE)
@@ -530,6 +603,7 @@ BEGIN_MANUF
MANUF("Pacific Peripherals", PACIFIC)
MANUF("Kupke", KUPKE)
MANUF("Memphis", MEMPHIS)
+ MANUF("3-State", 3_STATE)
MANUF("Commodore", COMMODORE2)
MANUF("Commodore", COMMODORE)
MANUF("Commodore", COMMODORE3)
@@ -546,7 +620,8 @@ BEGIN_MANUF
MANUF("University of Lowell", UNIV_OF_LOWELL)
MANUF("Ameristar", AMERISTAR)
MANUF("Supra", SUPRA)
- MANUF("CSA", CSA)
+ MANUF("Computer Systems Ass.", CSA)
+ MANUF("M-Tech", MTEC2)
MANUF("Great Valley Products", GVP3)
MANUF("ByteBox", BYTEBOX)
MANUF("Power Computing", POWER_COMPUTING)
@@ -554,6 +629,7 @@ BEGIN_MANUF
MANUF("Synergy", SYNERGY)
MANUF("Xetec", XETEC)
MANUF("Progressive Peripherals", PPI)
+ MANUF("Xebec", XEBEC)
MANUF("Spirit", SPIRIT)
MANUF("BSC", BSC)
MANUF("BSC", BSC3)
@@ -562,6 +638,8 @@ BEGIN_MANUF
MANUF("Checkpoint Technologies", CHECKPOINT)
MANUF("ICD", ICD)
MANUF("Kupke", KUPKE2)
+ MANUF("Great Valley Products", GVP4)
+ MANUF("Interworks Network", INTERWORKS_NET)
MANUF("Hardital Synthesis", HARDITAL)
MANUF("BSC", BSC2)
MANUF("Advanced Systems & Software", ADV_SYS_SOFT)
@@ -582,15 +660,20 @@ BEGIN_MANUF
MANUF("Village Tronic", VILLAGE_TRONIC)
MANUF("Utilities Unlimited", UTILITIES_ULTD)
MANUF("Amitrix", AMITRIX)
- MANUF("MTEC", MTEC)
+ MANUF("ArMax", ARMAX)
+ MANUF("NewTek", NEWTEK)
+ MANUF("M-Tech", MTEC)
MANUF("Great Valley Products", GVP2)
MANUF("Helfrich", HELFRICH2)
MANUF("MacroSystems", MACROSYSTEMS)
MANUF("ElBox Computer", ELBOX)
MANUF("Harms Professional", HARMS_PROF)
MANUF("Micronik", MICRONIK)
+ MANUF("MegaMicro", MEGA_MICRO)
MANUF("Imtronics", IMTRONICS2)
MANUF("Kupke", KUPKE3)
+ MANUF("ITH", ITH)
+ MANUF("VMC", VMC)
MANUF("Information", INFORMATION)
MANUF("Vortex", VORTEX)
MANUF("DataFlyer", DATAFLYER)
@@ -599,6 +682,7 @@ BEGIN_MANUF
MANUF("DPS", DPS)
MANUF("Apollo", APOLLO2)
MANUF("Apollo", APOLLO)
+ MANUF("Petsoff LP", PETSOFF)
MANUF("Uwe Gerlach", UWE_GERLACH)
MANUF("MacroSystems", MACROSYSTEMS2)
MANUF("Combitec", COMBITEC)
@@ -614,10 +698,12 @@ END
/*
- * Configured Expansion Devices
+ * Expansion Devices
*/
-static u_long BoardPartFlags[NUM_AUTO] = { 0, };
+int zorro_num_autocon;
+struct ConfigDev zorro_autocon[ZORRO_NUM_AUTO];
+static u_long BoardPartFlags[ZORRO_NUM_AUTO] = { 0, };
/*
@@ -657,14 +743,14 @@ int zorro_find(int manuf, int prod, int part, int index)
return(0);
}
- for (key = index + 1; key <= boot_info.bi_amiga.num_autocon; key++) {
- cd = &boot_info.bi_amiga.autocon[key-1];
+ for (key = index + 1; key <= zorro_num_autocon; key++) {
+ cd = &zorro_autocon[key-1];
if ((cd->cd_Rom.er_Manufacturer == manuf) &&
(cd->cd_Rom.er_Product == prod) &&
!(BoardPartFlags[key-1] & (1<<part)))
break;
}
- return(key <= boot_info.bi_amiga.num_autocon ? key : 0);
+ return(key <= zorro_num_autocon ? key : 0);
}
@@ -676,10 +762,10 @@ struct ConfigDev *zorro_get_board(int key)
{
struct ConfigDev *cd = NULL;
- if ((key < 1) || (key > boot_info.bi_amiga.num_autocon))
+ if ((key < 1) || (key > zorro_num_autocon))
printk("zorro_get_board: bad key %d\n", key);
else
- cd = &boot_info.bi_amiga.autocon[key-1];
+ cd = &zorro_autocon[key-1];
return(cd);
}
@@ -691,7 +777,7 @@ struct ConfigDev *zorro_get_board(int key)
void zorro_config_board(int key, int part)
{
- if ((key < 1) || (key > boot_info.bi_amiga.num_autocon))
+ if ((key < 1) || (key > zorro_num_autocon))
printk("zorro_config_board: bad key %d\n", key);
else if ((part < 0) || (part > 31))
printk("zorro_config_board: bad part %d\n", part);
@@ -708,7 +794,7 @@ void zorro_config_board(int key, int part)
void zorro_unconfig_board(int key, int part)
{
- if ((key < 1) || (key > boot_info.bi_amiga.num_autocon))
+ if ((key < 1) || (key > zorro_num_autocon))
printk("zorro_unconfig_board: bad key %d\n", key);
else if ((part < 0) || (part > 31))
printk("zorro_unconfig_board: bad part %d\n", part);
@@ -738,7 +824,7 @@ static int identify(int devnum, char *buf)
int i, j, k, len = 0;
enum GVP_ident epc;
- cd = &boot_info.bi_amiga.autocon[devnum];
+ cd = &zorro_autocon[devnum];
manuf = cd->cd_Rom.er_Manufacturer;
prod = cd->cd_Rom.er_Product;
addr = (u_long)cd->cd_BoardAddr;
@@ -756,7 +842,11 @@ static int identify(int devnum, char *buf)
identified = 1;
break;
} else {
- epc = *(enum GVP_ident *)ZTWO_VADDR(addr+0x8000) &
+ /*
+ * The epc must be read as a short from the
+ * hardware.
+ */
+ epc = *(unsigned short *)ZTWO_VADDR(addr+0x8000) &
GVP_PRODMASK;
for (k = 0; k < NUM_GVP_PROD; k++)
if (Ext_Prod_GVP[k].ID == epc) {
@@ -820,11 +910,11 @@ void zorro_identify(void)
return;
printk("Probing AutoConfig expansion device(s):\n");
- for (i = 0; i < boot_info.bi_amiga.num_autocon; i++) {
+ for (i = 0; i < zorro_num_autocon; i++) {
identify(i, tmp);
printk(tmp);
}
- if (!boot_info.bi_amiga.num_autocon)
+ if (!zorro_num_autocon)
printk("No AutoConfig expansion devices present.\n");
}
@@ -840,7 +930,7 @@ int zorro_get_list(char *buffer)
if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) {
len = sprintf(buffer, "AutoConfig expansion devices:\n");
- for (i = 0; i < boot_info.bi_amiga.num_autocon; i++) {
+ for (i = 0; i < zorro_num_autocon; i++) {
j = identify(i, tmp);
if (len+j >= 4075) {
len += sprintf(buffer+len, "4K limit reached!\n");
@@ -911,12 +1001,12 @@ void zorro_init(void)
return;
/* Mark all available Zorro II memory */
- for (i = 0; i < boot_info.bi_amiga.num_autocon; i++) {
- cd = &boot_info.bi_amiga.autocon[i];
+ 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 < boot_info.num_memory; i++)
- mark_region(boot_info.memory[i].addr, boot_info.memory[i].size, 0);
+ for (i = 0; i < m68k_num_memory; i++)
+ mark_region(m68k_memory[i].addr, m68k_memory[i].size, 0);
}
diff --git a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile
index 77324bc10..77d5c7c2b 100644
--- a/arch/m68k/atari/Makefile
+++ b/arch/m68k/atari/Makefile
@@ -7,10 +7,9 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-EXTRA_CFLAGS := -Wa,-m68030
-
O_TARGET := atari.o
O_OBJS := config.o atakeyb.o ataints.o \
- stdma.o atasound.o joystick.o stram.o atafb.o ksyms.o
+ stdma.o atasound.o joystick.o stram.o atafb.o
+OX_OBJS := atari_ksyms.o
include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/atari/atafb.c b/arch/m68k/atari/atafb.c
index 488ecc302..64c9a62d3 100644
--- a/arch/m68k/atari/atafb.c
+++ b/arch/m68k/atari/atafb.c
@@ -210,11 +210,11 @@ And on the MV300 it's difficult to read out the hardware palette. So we
just keep track of the set colors in our own array here, and use that!
*/
-struct { unsigned char red,green,blue,pad; } MV300_color[256];
+static struct { unsigned char red,green,blue,pad; } MV300_color[256];
#endif /* ATAFB_EXT */
-int inverse=0;
+static int inverse=0;
extern int fontheight_8x8;
extern int fontwidth_8x8;
@@ -332,7 +332,7 @@ static char *user6_names[] = {"user6", NULL};
static char *user7_names[] = {"user7", NULL};
static char *dummy_names[] = {"dummy", NULL};
-char **fb_var_names[] = {
+static char **fb_var_names[] = {
/* Writing the name arrays directly in this array (via "(char *[]){...}")
* crashes gcc 2.5.8 (sigsegv) if the inner array
* contains more than two items. I've also seen that all elements
@@ -365,7 +365,7 @@ char **fb_var_names[] = {
/* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
};
-struct fb_var_screeninfo atari_fb_predefined[] = {
+static struct fb_var_screeninfo atari_fb_predefined[] = {
/*
* yres_virtual==0 means use hw-scrolling if possible, else yres
*/
@@ -467,7 +467,7 @@ struct fb_var_screeninfo atari_fb_predefined[] = {
0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }
};
-int num_atari_fb_predefined=arraysize(atari_fb_predefined);
+static int num_atari_fb_predefined=arraysize(atari_fb_predefined);
static int
@@ -2348,7 +2348,7 @@ static int pan_display( struct fb_var_screeninfo *var,
#ifdef ATAFB_TT
-struct fb_hwswitch tt_switch = {
+static struct fb_hwswitch tt_switch = {
tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var,
tt_get_par, tt_set_par, tt_getcolreg, tt_setcolreg,
set_screen_base, NULL, pan_display
@@ -2356,7 +2356,7 @@ struct fb_hwswitch tt_switch = {
#endif
#ifdef ATAFB_FALCON
-struct fb_hwswitch falcon_switch = {
+static struct fb_hwswitch falcon_switch = {
falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var,
falcon_get_par, falcon_set_par, falcon_getcolreg,
falcon_setcolreg, set_screen_base, falcon_blank, falcon_pan_display
@@ -2364,7 +2364,7 @@ struct fb_hwswitch falcon_switch = {
#endif
#ifdef ATAFB_STE
-struct fb_hwswitch st_switch = {
+static struct fb_hwswitch st_switch = {
stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var,
stste_get_par, stste_set_par, stste_getcolreg, stste_setcolreg,
stste_set_screen_base, NULL, pan_display
@@ -2372,7 +2372,7 @@ struct fb_hwswitch st_switch = {
#endif
#ifdef ATAFB_EXT
-struct fb_hwswitch ext_switch = {
+static struct fb_hwswitch ext_switch = {
ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var,
ext_get_par, ext_set_par, ext_getcolreg, ext_setcolreg, NULL, NULL, NULL
};
@@ -2463,9 +2463,15 @@ static short green2[]=
static short blue2[]=
{ 0x0000,0xffff};
-struct fb_cmap default_16_colors = { 0, 16, red16, green16, blue16, NULL };
-struct fb_cmap default_4_colors = { 0, 4, red4, green4, blue4, NULL };
-struct fb_cmap default_2_colors = { 0, 2, red2, green2, blue2, NULL };
+static struct fb_cmap default_16_colors = {
+ 0, 16, red16, green16, blue16, NULL
+};
+static struct fb_cmap default_4_colors = {
+ 0, 4, red4, green4, blue4, NULL
+};
+static struct fb_cmap default_2_colors = {
+ 0, 2, red2, green2, blue2, NULL
+};
static struct fb_cmap *
get_default_colormap(int bpp)
@@ -2899,6 +2905,12 @@ atafb_blank(int blank)
do_install_cmap(currcon);
}
+static int
+atafb_setcmap(struct fb_cmap *cmap, int con)
+{
+ return(atari_fb_set_cmap(cmap, 1, con));
+}
+
struct fb_info *
atari_fb_init(long *mem_start)
{
@@ -2993,6 +3005,7 @@ atari_fb_init(long *mem_start)
fb_info.switch_con=&atafb_switch;
fb_info.updatevar=&fb_update_var;
fb_info.blank=&atafb_blank;
+ fb_info.setcmap=&atafb_setcmap;
var=atari_fb_predefined+default_par-1;
do_fb_set_var(var,1);
strcat(fb_info.modename,fb_var_names[default_par-1][0]);
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index 642ff027b..b65beefb1 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -40,7 +40,6 @@
#include <linux/ptrace.h>
#include <linux/kernel_stat.h>
-#include <asm/setup.h>
#include <asm/system.h>
#include <asm/traps.h>
@@ -57,9 +56,7 @@
* All interrupt source have an internal number (defined in
* <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
* TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
- * be allocated by atari_register_vme_int(). Currently, all int source numbers
- * have the IRQ_MACHSPEC bit set, to keep the general int handling functions
- * in kernel/ints.c from them.
+ * be allocated by atari_register_vme_int().
*
* Each interrupt can be of three types:
*
@@ -181,7 +178,7 @@ asmlinkage void IRQ_NAME(n); \
void atari_slow_irq_##n##_dummy (void) { \
__asm__ (ALIGN_STR "\n" \
SYMBOL_NAME_STR(atari_slow_irq_) #n "_handler:\t" \
-" addql #1,"SYMBOL_NAME_STR(intr_count)"\n" \
+" addql #1,"SYMBOL_NAME_STR(local_irq_count)"\n" \
SAVE_ALL "\n" \
" andb #~(1<<(" #n "&7))," /* mask this interrupt */ \
"("MFP_MK_BASE"+(((" #n "&8)^8)>>2)+((" #n "&16)<<3)):w\n" \
@@ -193,7 +190,7 @@ SYMBOL_NAME_STR(atari_slow_irq_) #n "_handler:\t" \
" lea "SYMBOL_NAME_STR(irq_handler)"+("#n"+8)*8,%%a0\n" \
" pea %%sp@\n" /* push addr of frame */ \
" movel %%a0@(4),%%sp@-\n" /* push handler data */ \
-" pea (" #n "+0x10000008)\n" /* push int number */ \
+" pea (" #n "+8)\n" /* push int number */ \
" movel %%a0@,%%a0\n" \
" jbsr %%a0@\n" /* call the handler */ \
" addql #8,%%sp\n" \
@@ -284,7 +281,7 @@ __asm__ (ALIGN_STR "\n"
SYMBOL_NAME_STR(atari_fast_irq_handler) ":
orw #0x700,%%sr /* disable all interrupts */
"SYMBOL_NAME_STR(atari_prio_irq_handler) ":\t
- addql #1,"SYMBOL_NAME_STR(intr_count)"\n"
+ addql #1,"SYMBOL_NAME_STR(local_irq_count)"\n"
SAVE_ALL "
/* get vector number from stack frame and convert to source */
bfextu %%sp@(" FORMATVEC "){#4,#10},%%d0
@@ -297,7 +294,6 @@ SYMBOL_NAME_STR(atari_fast_irq_handler) ":
lea %%a0@(%%d0:l:8),%%a0
pea %%sp@ /* push frame address */
movel %%a0@(4),%%sp@- /* push handler data */
- bset #28,%%d0 /* set MACHSPEC bit */
movel %%d0,%%sp@- /* push int number */
movel %%a0@,%%a0
jsr %%a0@ /* and call the handler */
@@ -588,14 +584,12 @@ unsigned long atari_register_vme_int(void)
return 0;
free_vme_vec_bitmap |= 1 << i;
- return (VME_SOURCE_BASE + i) | IRQ_MACHSPEC;
+ return (VME_SOURCE_BASE + i);
}
void atari_unregister_vme_int(unsigned long irq)
{
- irq &= ~IRQ_MACHSPEC;
-
if(irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
irq -= VME_SOURCE_BASE;
free_vme_vec_bitmap &= ~(1 << irq);
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
index 95cc0245f..4f57cb928 100644
--- a/arch/m68k/atari/atakeyb.c
+++ b/arch/m68k/atari/atakeyb.c
@@ -14,6 +14,7 @@
*/
#include <linux/sched.h>
+#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/keyboard.h>
@@ -40,6 +41,15 @@ void (*atari_MIDI_interrupt_hook) (void);
/* Hook for mouse driver */
void (*atari_mouse_interrupt_hook) (char *);
+/* variables for IKBD self test: */
+
+/* state: 0: off; >0: in progress; >1: 0xf1 received */
+static volatile int ikbd_self_test;
+/* timestamp when last received a char */
+static volatile unsigned long self_test_last_rcv;
+/* bitmap of keys reported as broken */
+static unsigned long broken_keys[128/(sizeof(unsigned long)*8)] = { 0, };
+
#define BREAK_MASK (0x80)
/*
@@ -331,12 +341,15 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
/* a very fast typist or a slow system, give a warning */
/* ...happens often if interrupts were disabled for too long */
- printk( "Keyboard overrun\n" );
+ printk( KERN_DEBUG "Keyboard overrun\n" );
scancode = acia.key_data;
/* Turn off autorepeating in case a break code has been lost */
del_timer( &atakeyb_rep_timer );
rep_scancode = 0;
- if (IS_SYNC_CODE(scancode)) {
+ if (ikbd_self_test)
+ /* During self test, don't do resyncing, just process the code */
+ goto interpret_scancode;
+ else if (IS_SYNC_CODE(scancode)) {
/* This code seem already to be the start of a new packet or a
* single scancode */
kb_state.state = KEYBOARD;
@@ -386,10 +399,47 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
kb_state.buf[0] = scancode;
break;
+ case 0xF1:
+ /* during self-test, note that 0xf1 received */
+ if (ikbd_self_test) {
+ ++ikbd_self_test;
+ self_test_last_rcv = jiffies;
+ break;
+ }
+ /* FALL THROUGH */
+
default:
break_flag = scancode & BREAK_MASK;
scancode &= ~BREAK_MASK;
+ if (ikbd_self_test) {
+ /* Scancodes sent during the self-test stand for broken
+ * keys (keys being down). The code *should* be a break
+ * code, but nevertheless some AT keyboard interfaces send
+ * make codes instead. Therefore, simply ignore
+ * break_flag...
+ * */
+ int keyval = ataplain_map[scancode], keytyp;
+
+ set_bit( scancode, broken_keys );
+ self_test_last_rcv = jiffies;
+ keyval = ataplain_map[scancode];
+ keytyp = KTYP(keyval) - 0xf0;
+ keyval = KVAL(keyval);
+
+ printk( KERN_WARNING "Key with scancode %d ", scancode );
+ if (keytyp == KT_LATIN || keytyp == KT_LETTER) {
+ if (keyval < ' ')
+ printk( "('^%c') ", keyval + '@' );
+ else
+ printk( "('%c') ", keyval );
+ }
+ printk( "is broken -- will be ignored.\n" );
+ break;
+ }
+ else if (test_bit( scancode, broken_keys ))
+ break;
+
if (break_flag) {
del_timer( &atakeyb_rep_timer );
rep_scancode = 0;
@@ -815,7 +865,18 @@ int atari_keyb_init(void)
mfp.active_edge &= ~0x10;
atari_turnon_irq(IRQ_MFP_ACIA);
+ ikbd_self_test = 1;
ikbd_reset();
+ /* wait for a period of inactivity (here: 0.25s), then assume the IKBD's
+ * self-test is finished */
+ self_test_last_rcv = jiffies;
+ while( jiffies < self_test_last_rcv + HZ/4 )
+ barrier();
+ /* if not incremented: no 0xf1 received */
+ if (ikbd_self_test == 1)
+ printk( KERN_ERR "WARNING: keyboard self test failed!\n" );
+ ikbd_self_test = 0;
+
ikbd_mouse_disable();
ikbd_joystick_disable();
diff --git a/arch/m68k/atari/atari_ksyms.c b/arch/m68k/atari/atari_ksyms.c
new file mode 100644
index 000000000..c2a9da86e
--- /dev/null
+++ b/arch/m68k/atari/atari_ksyms.c
@@ -0,0 +1,35 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/ptrace.h>
+#include <asm/traps.h>
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/atarikb.h>
+#include <asm/atari_joystick.h>
+#include <asm/atari_stdma.h>
+
+extern void atari_microwire_cmd( int cmd );
+extern int atari_SCC_reset_done;
+
+EXPORT_SYMBOL(atari_mch_cookie);
+EXPORT_SYMBOL(atari_hw_present);
+EXPORT_SYMBOL(is_medusa);
+EXPORT_SYMBOL(is_hades);
+EXPORT_SYMBOL(atari_register_vme_int);
+EXPORT_SYMBOL(atari_unregister_vme_int);
+EXPORT_SYMBOL(stdma_lock);
+EXPORT_SYMBOL(stdma_release);
+EXPORT_SYMBOL(stdma_others_waiting);
+EXPORT_SYMBOL(stdma_islocked);
+
+EXPORT_SYMBOL(atari_mouse_buttons);
+EXPORT_SYMBOL(atari_mouse_interrupt_hook);
+EXPORT_SYMBOL(atari_MIDI_interrupt_hook);
+EXPORT_SYMBOL(atari_SCC_reset_done);
+EXPORT_SYMBOL(ikbd_write);
+EXPORT_SYMBOL(ikbd_mouse_y0_top);
+EXPORT_SYMBOL(ikbd_mouse_thresh);
+EXPORT_SYMBOL(ikbd_mouse_rel_pos);
+EXPORT_SYMBOL(ikbd_mouse_disable);
+
+EXPORT_SYMBOL(atari_microwire_cmd);
diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c
index 33f7f79c6..51f8b6823 100644
--- a/arch/m68k/atari/atasound.c
+++ b/arch/m68k/atari/atasound.c
@@ -21,7 +21,6 @@ for more details.
#include <linux/errno.h>
#include <linux/mm.h>
-#include <asm/setup.h>
#include <asm/atarihw.h>
#include <asm/system.h>
#include <asm/irq.h>
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index f314fcbbd..0d0607da0 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -33,6 +33,7 @@
#include <linux/console.h>
#include <linux/interrupt.h>
+#include <asm/bootinfo.h>
#include <asm/setup.h>
#include <asm/atarihw.h>
#include <asm/atarihdreg.h>
@@ -44,7 +45,16 @@
#include <asm/pgtable.h>
#include <asm/machdep.h>
-extern void atari_sched_init(void (*)(int, void *, struct pt_regs *));
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+#endif
+
+u_long atari_mch_cookie;
+struct atari_hw_present atari_hw_present;
+
+extern char m68k_debug_device[];
+
+static void atari_sched_init(void (*)(int, void *, struct pt_regs *));
/* atari specific keyboard functions */
extern int atari_keyb_init(void);
extern int atari_kbdrate (struct kbd_repeat *);
@@ -53,30 +63,38 @@ extern void atari_kbd_leds (unsigned int);
extern void atari_init_IRQ (void);
extern int atari_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id);
-extern int atari_free_irq (unsigned int irq, void *dev_id);
+extern void atari_free_irq (unsigned int irq, void *dev_id);
extern void atari_enable_irq (unsigned int);
extern void atari_disable_irq (unsigned int);
extern int atari_get_irq_list (char *buf);
+static void atari_get_model(char *model);
+static int atari_get_hardware_list(char *buffer);
/* atari specific timer functions */
-extern unsigned long atari_gettimeoffset (void);
-extern void atari_mste_gettod (int *, int *, int *, int *, int *, int *);
-extern void atari_gettod (int *, int *, int *, int *, int *, int *);
-extern int atari_mste_hwclk (int, struct hwclk_time *);
-extern int atari_hwclk (int, struct hwclk_time *);
-extern int atari_mste_set_clock_mmss (unsigned long);
-extern int atari_set_clock_mmss (unsigned long);
+static unsigned long atari_gettimeoffset (void);
+static void atari_mste_gettod (int *, int *, int *, int *, int *, int *);
+static void atari_gettod (int *, int *, int *, int *, int *, int *);
+static int atari_mste_hwclk (int, struct hwclk_time *);
+static int atari_hwclk (int, struct hwclk_time *);
+static int atari_mste_set_clock_mmss (unsigned long);
+static int atari_set_clock_mmss (unsigned long);
extern void atari_mksound( unsigned int count, unsigned int ticks );
-extern void atari_reset( void );
+static void atari_reset( void );
#ifdef CONFIG_BLK_DEV_FD
extern int atari_floppy_init (void);
extern void atari_floppy_setup(char *, int *);
#endif
-extern void atari_waitbut (void);
extern struct consw fb_con;
extern struct fb_info *atari_fb_init(long *);
-extern void atari_debug_init (void);
+static void atari_debug_init(void);
extern void atari_video_setup(char *, int *);
+static struct console atari_console_driver;
+
+/* Can be set somewhere, if a SCC master reset has already be done and should
+ * not be repeated; used by kgdb */
+int atari_SCC_reset_done = 0;
+
+
extern void (*kd_mksound)(unsigned int, unsigned int);
/* This function tests for the presence of an address, specially a
@@ -205,8 +223,36 @@ static int scc_test( volatile char *ctla )
return( 1 );
}
+
+ /*
+ * Parse an Atari-specific record in the bootinfo
+ */
+
+int atari_parse_bootinfo(const struct bi_record *record)
+{
+ int unknown = 0;
+ const u_long *data = record->data;
+
+ switch (record->tag) {
+ case BI_ATARI_MCH_COOKIE:
+ atari_mch_cookie = *data;
+ break;
+ default:
+ unknown = 1;
+ }
+ return(unknown);
+}
+
+ /*
+ * Setup the Atari configuration info
+ */
+
void config_atari(void)
{
+ memset(&atari_hw_present, 0, sizeof(atari_hw_present));
+
+ atari_debug_init();
+
mach_sched_init = atari_sched_init;
mach_keyb_init = atari_keyb_init;
mach_kbdrate = atari_kbdrate;
@@ -214,21 +260,20 @@ void config_atari(void)
mach_init_IRQ = atari_init_IRQ;
mach_request_irq = atari_request_irq;
mach_free_irq = atari_free_irq;
- mach_enable_irq = atari_enable_irq;
- mach_disable_irq = atari_disable_irq;
+ enable_irq = atari_enable_irq;
+ disable_irq = atari_disable_irq;
+ mach_get_model = atari_get_model;
+ mach_get_hardware_list = atari_get_hardware_list;
mach_get_irq_list = atari_get_irq_list;
mach_gettimeoffset = atari_gettimeoffset;
- mach_mksound = atari_mksound;
mach_reset = atari_reset;
#ifdef CONFIG_BLK_DEV_FD
mach_floppy_init = atari_floppy_init;
mach_floppy_setup = atari_floppy_setup;
#endif
conswitchp = &fb_con;
- waitbut = atari_waitbut;
mach_fb_init = atari_fb_init;
mach_max_dma_address = 0xffffff;
- mach_debug_init = atari_debug_init;
mach_video_setup = atari_video_setup;
kd_mksound = atari_mksound;
@@ -237,7 +282,7 @@ void config_atari(void)
*/
printk( "Atari hardware found: " );
- if (is_medusa) {
+ if (is_medusa || is_hades) {
/* There's no Atari video hardware on the Medusa, but all the
* addresses below generate a DTACK so no bus error occurs! */
}
@@ -279,7 +324,7 @@ void config_atari(void)
ATARIHW_SET(SCSI_DMA);
printk( "TT_SCSI_DMA " );
}
- if (hwreg_present( &st_dma.dma_hi )) {
+ if (!is_hades && hwreg_present( &st_dma.dma_hi )) {
ATARIHW_SET(STND_DMA);
printk( "STND_DMA " );
}
@@ -301,21 +346,25 @@ void config_atari(void)
ATARIHW_SET(YM_2149);
printk( "YM2149 " );
}
- if (!is_medusa && hwreg_present( &tt_dmasnd.ctrl )) {
+ if (!is_medusa && !is_hades && hwreg_present( &tt_dmasnd.ctrl )) {
ATARIHW_SET(PCM_8BIT);
printk( "PCM " );
}
- if (hwreg_present( (void *)(0xffff8940) )) {
+ if (!is_hades && hwreg_present( &codec.unused5 )) {
ATARIHW_SET(CODEC);
printk( "CODEC " );
}
+ if (hwreg_present( &dsp56k_host_interface.icr )) {
+ ATARIHW_SET(DSP56K);
+ printk( "DSP56K " );
+ }
if (hwreg_present( &tt_scc_dma.dma_ctrl ) &&
#if 0
/* This test sucks! Who knows some better? */
(tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
(tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
#else
- !is_medusa
+ !is_medusa && !is_hades
#endif
) {
ATARIHW_SET(SCC_DMA);
@@ -329,7 +378,12 @@ void config_atari(void)
ATARIHW_SET( ST_ESCC );
printk( "ST_ESCC " );
}
- if (hwreg_present( &tt_scu.sys_mask )) {
+ if (is_hades)
+ {
+ ATARIHW_SET( VME );
+ printk( "VME " );
+ }
+ else if (hwreg_present( &tt_scu.sys_mask )) {
ATARIHW_SET(SCU);
/* Assume a VME bus if there's a SCU */
ATARIHW_SET( VME );
@@ -339,7 +393,7 @@ void config_atari(void)
ATARIHW_SET(ANALOG_JOY);
printk( "ANALOG_JOY " );
}
- if (hwreg_present( blitter.halftone )) {
+ if (!is_hades && hwreg_present( blitter.halftone )) {
ATARIHW_SET(BLITTER);
printk( "BLITTER " );
}
@@ -348,7 +402,7 @@ void config_atari(void)
printk( "IDE " );
}
#if 1 /* This maybe wrong */
- if (!is_medusa &&
+ if (!is_medusa && !is_hades &&
hwreg_present( &tt_microwire.data ) &&
hwreg_present( &tt_microwire.mask ) &&
(tt_microwire.mask = 0x7ff,
@@ -366,20 +420,20 @@ void config_atari(void)
mach_hwclk = atari_hwclk;
mach_set_clock_mmss = atari_set_clock_mmss;
}
- if (hwreg_present( &mste_rtc.sec_ones)) {
+ if (!is_hades && hwreg_present( &mste_rtc.sec_ones)) {
ATARIHW_SET(MSTE_CLK);
printk( "MSTE_CLK ");
mach_gettod = atari_mste_gettod;
mach_hwclk = atari_mste_hwclk;
mach_set_clock_mmss = atari_mste_set_clock_mmss;
}
- if (!is_medusa &&
+ if (!is_medusa && !is_hades &&
hwreg_present( &dma_wd.fdc_speed ) &&
hwreg_write( &dma_wd.fdc_speed, 0 )) {
ATARIHW_SET(FDCSPEED);
printk( "FDC_SPEED ");
}
- if (!ATARIHW_PRESENT(ST_SCSI)) {
+ if (!is_hades && !ATARIHW_PRESENT(ST_SCSI)) {
ATARIHW_SET(ACSI);
printk( "ACSI " );
}
@@ -390,9 +444,11 @@ void config_atari(void)
* translation (the one that must not be turned off in
* head.S...)
*/
- __asm__ volatile ("moveq #0,%/d0;"
- ".long 0x4e7b0004;" /* movec d0,itt0 */
- ".long 0x4e7b0006;" /* movec d0,dtt0 */
+ __asm__ volatile ("moveq #0,%/d0\n\t"
+ ".chip 68040\n\t"
+ "movec %%d0,%%itt0\n\t"
+ "movec %%d0,%%dtt0\n\t"
+ ".chip 68k"
: /* no outputs */
: /* no inputs */
: "d0");
@@ -416,13 +472,18 @@ void config_atari(void)
tt1_val = 0xfe008543; /* Translate 0xfexxxxxx, enable, cache
* inhibit, read and write, FDC mask = 3,
* FDC val = 4 -> Supervisor only */
- __asm__ __volatile__ ( "pmove %0@,%/tt1" : : "a" (&tt1_val) );
+ __asm__ __volatile__ ( ".chip 68030\n\t"
+ "pmove %0@,%/tt1\n\t"
+ ".chip 68k"
+ : : "a" (&tt1_val) );
}
else {
__asm__ __volatile__
( "movel %0,%/d0\n\t"
- ".long 0x4e7b0005\n\t" /* movec d0,itt1 */
- ".long 0x4e7b0007" /* movec d0,dtt1 */
+ ".chip 68040\n\t"
+ "movec %%d0,%%itt1\n\t"
+ "movec %%d0,%%dtt1\n\t"
+ ".chip 68k"
:
: "g" (0xfe00a040) /* Translate 0xfexxxxxx, enable,
* supervisor only, non-cacheable/
@@ -432,7 +493,7 @@ void config_atari(void)
}
}
-void atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
+static void atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
{
/* set Timer C data Register */
mfp.tim_dt_c = INT_TICKS;
@@ -448,7 +509,7 @@ void atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
#define TICK_SIZE 10000
/* This is always executed with interrupts disabled. */
-unsigned long atari_gettimeoffset (void)
+static unsigned long atari_gettimeoffset (void)
{
unsigned long ticks, offset = 0;
@@ -511,8 +572,8 @@ mste_write(struct MSTE_RTC *val)
} while(0)
-void atari_mste_gettod (int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp)
+static void atari_mste_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
{
int hr24=0, hour;
struct MSTE_RTC val;
@@ -538,8 +599,8 @@ void atari_mste_gettod (int *yearp, int *monp, int *dayp,
}
-void atari_gettod (int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp)
+static void atari_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
{
unsigned char ctrl;
unsigned short tos_version;
@@ -585,13 +646,13 @@ void atari_gettod (int *yearp, int *monp, int *dayp,
we use the fact that in head.S we have set up a mapping
0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
in the last 16MB of the address space. */
- tos_version = is_medusa ? 0xfff : *(unsigned short *)0xFF000002;
+ tos_version = (is_medusa || is_hades) ? 0xfff : *(unsigned short *)0xFF000002;
*yearp += (tos_version < 0x306) ? 70 : 68;
}
#define HWCLK_POLL_INTERVAL 5
-int atari_mste_hwclk( int op, struct hwclk_time *t )
+static int atari_mste_hwclk( int op, struct hwclk_time *t )
{
int hour, year;
int hr24=0;
@@ -650,7 +711,7 @@ int atari_mste_hwclk( int op, struct hwclk_time *t )
return 0;
}
-int atari_hwclk( int op, struct hwclk_time *t )
+static int atari_hwclk( int op, struct hwclk_time *t )
{
int sec=0, min=0, hour=0, day=0, mon=0, year=0, wday=0;
unsigned long flags;
@@ -660,7 +721,7 @@ int atari_hwclk( int op, struct hwclk_time *t )
/* Tos version at Physical 2. See above for explanation why we
cannot use PTOV(2). */
- tos_version = is_medusa ? 0xfff : *(unsigned short *)0xff000002;
+ tos_version = (is_medusa || is_hades) ? 0xfff : *(unsigned short *)0xff000002;
ctrl = RTC_READ(RTC_CONTROL); /* control registers are
* independent from the UIP */
@@ -777,7 +838,7 @@ int atari_hwclk( int op, struct hwclk_time *t )
}
-int atari_mste_set_clock_mmss (unsigned long nowtime)
+static int atari_mste_set_clock_mmss (unsigned long nowtime)
{
short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
struct MSTE_RTC val;
@@ -800,7 +861,7 @@ int atari_mste_set_clock_mmss (unsigned long nowtime)
return 0;
}
-int atari_set_clock_mmss (unsigned long nowtime)
+static int atari_set_clock_mmss (unsigned long nowtime)
{
int retval = 0;
short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
@@ -839,13 +900,6 @@ int atari_set_clock_mmss (unsigned long nowtime)
return retval;
}
-
-void atari_waitbut (void)
-{
- /* sorry, no-op */
-}
-
-
static inline void ata_mfp_out (char c)
{
while (!(mfp.trn_stat & 0x80)) /* wait for tx buf empty */
@@ -853,12 +907,12 @@ static inline void ata_mfp_out (char c)
mfp.usart_dta = c;
}
-void ata_mfp_print (const char *str)
+static void atari_mfp_console_write (const char *str, unsigned int count)
{
- for( ; *str; ++str ) {
+ while (count--) {
if (*str == '\n')
ata_mfp_out( '\r' );
- ata_mfp_out( *str );
+ ata_mfp_out( *str++ );
}
}
@@ -871,12 +925,12 @@ static inline void ata_scc_out (char c)
scc.cha_b_data = c;
}
-void ata_scc_print (const char *str)
+static void atari_scc_console_write (const char *str, unsigned int count)
{
- for( ; *str; ++str ) {
+ while (count--) {
if (*str == '\n')
ata_scc_out( '\r' );
- ata_scc_out( *str );
+ ata_scc_out( *str++ );
}
}
@@ -901,20 +955,20 @@ static int ata_par_out (char c)
return( 1 );
}
-void ata_par_print (const char *str)
+static void atari_par_console_write (const char *str, unsigned int count)
{
static int printer_present = 1;
if (!printer_present)
return;
- for( ; *str; ++str ) {
+ while (count--) {
if (*str == '\n')
if (!ata_par_out( '\r' )) {
printer_present = 0;
return;
}
- if (!ata_par_out( *str )) {
+ if (!ata_par_out( *str++ )) {
printer_present = 0;
return;
}
@@ -922,15 +976,18 @@ void ata_par_print (const char *str)
}
-void atari_debug_init( void )
+static void atari_debug_init(void)
{
- extern void (*debug_print_proc)(const char *);
- extern char m68k_debug_device[];
-
+#ifdef CONFIG_KGDB
+ /* if the m68k_debug_device is used by the GDB stub, do nothing here */
+ if (kgdb_initialized)
+ return(NULL);
+#endif
+
if (!strcmp( m68k_debug_device, "ser" )) {
/* defaults to ser2 for a Falcon and ser1 otherwise */
strcpy( m68k_debug_device,
- ((boot_info.bi_atari.mch_cookie >> 16) == ATARI_MCH_FALCON) ?
+ ((atari_mch_cookie >> 16) == ATARI_MCH_FALCON) ?
"ser2" : "ser1" );
}
@@ -943,7 +1000,7 @@ void atari_debug_init( void )
mfp.tim_dt_d = 2; /* 9600 bps */
mfp.tim_ct_cd |= 0x01; /* start timer D, 1:4 */
mfp.trn_stat |= 0x01; /* enable TX */
- debug_print_proc = ata_mfp_print;
+ atari_console_driver.write = atari_mfp_console_write;
}
else if (!strcmp( m68k_debug_device, "ser2" )) {
/* SCC Modem2 serial port */
@@ -969,7 +1026,7 @@ void atari_debug_init( void )
scc.cha_b_ctrl = *p++;
MFPDELAY();
}
- debug_print_proc = ata_scc_print;
+ atari_console_driver.write = atari_scc_console_write;
}
else if (!strcmp( m68k_debug_device, "par" )) {
/* parallel printer */
@@ -980,29 +1037,10 @@ void atari_debug_init( void )
sound_ym.wd_data = 0; /* no char */
sound_ym.rd_data_reg_sel = 14; /* select port A */
sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
- debug_print_proc = ata_par_print;
- }
- else
- debug_print_proc = NULL;
-}
-
-
-void ata_serial_print (const char *str)
-{
- int c;
-
- while (c = *str++, c != 0)
- {
- if (c == '\n')
- {
- while (!(mfp.trn_stat & (1 << 7)))
- barrier ();
- mfp.usart_dta = '\r';
- }
- while (!(mfp.trn_stat & (1 << 7)))
- barrier ();
- mfp.usart_dta = c;
+ atari_console_driver.write = atari_par_console_write;
}
+ if (atari_console_driver.write)
+ register_console(&atari_console_driver);
}
/* ++roman:
@@ -1036,14 +1074,15 @@ void ata_serial_print (const char *str)
/* ++andreas: no need for complicated code, just depend on prefetch */
-void atari_reset (void)
+static void atari_reset (void)
{
long tc_val = 0;
long reset_addr;
/* On the Medusa, phys. 0x4 may contain garbage because it's no
ROM. See above for explanation why we cannot use PTOV(4). */
- reset_addr = is_medusa ? 0xe00030 : *(unsigned long *) 0xff000004;
+ reset_addr = is_hades ? 0x7fe00030 :
+ (is_medusa ? 0xe00030 : *(unsigned long *) 0xff000004);
acia.key_ctrl = ACIA_RESET; /* reset ACIA for switch off OverScan, if it's active */
@@ -1062,7 +1101,9 @@ void atari_reset (void)
/* 68060: clear PCR to turn off superscalar operation */
__asm__ __volatile__
("moveq #0,%/d0\n\t"
- ".long 0x4e7b0808" /* movec d0,pcr */
+ ".chip 68060\n\t"
+ "movec %%d0,%%pcr\n\t"
+ ".chip 68k"
: : : "d0" );
}
@@ -1070,8 +1111,10 @@ void atari_reset (void)
("movel %0,%/d0\n\t"
"andl #0xff000000,%/d0\n\t"
"orw #0xe020,%/d0\n\t" /* map 16 MB, enable, cacheable */
- ".long 0x4e7b0004\n\t" /* movec d0,itt0 */
- ".long 0x4e7b0006\n\t" /* movec d0,dtt0 */
+ ".chip 68040\n\t"
+ "movec %%d0,%%itt0\n\t"
+ "movec %%d0,%%dtt0\n\t"
+ ".chip 68k\n\t"
"jmp %0@\n\t"
: /* no outputs */
: "a" (jmp_addr040)
@@ -1080,9 +1123,11 @@ void atari_reset (void)
__asm__ __volatile__
("moveq #0,%/d0\n\t"
"nop\n\t"
- ".word 0xf4d8\n\t" /* cinva i/d */
- ".word 0xf518\n\t" /* pflusha */
- ".long 0x4e7b0003\n\t" /* movec d0,tc */
+ ".chip 68040\n\t"
+ "cinva %%bc\n\t"
+ "pflusha\n\t"
+ "movec %%d0,%%tc\n\t"
+ ".chip 68k\n\t"
"jmp %0@"
: /* no outputs */
: "a" (reset_addr)
@@ -1097,10 +1142,10 @@ void atari_reset (void)
}
-void atari_get_model(char *model)
+static void atari_get_model(char *model)
{
strcpy(model, "Atari ");
- switch (boot_info.bi_atari.mch_cookie >> 16) {
+ switch (atari_mch_cookie >> 16) {
case ATARI_MCH_ST:
if (ATARIHW_PRESENT(MSTE_CLK))
strcat (model, "Mega ST");
@@ -1108,7 +1153,7 @@ void atari_get_model(char *model)
strcat (model, "ST");
break;
case ATARI_MCH_STE:
- if ((boot_info.bi_atari.mch_cookie & 0xffff) == 0x10)
+ if ((atari_mch_cookie & 0xffff) == 0x10)
strcat (model, "Mega STE");
else
strcat (model, "STE");
@@ -1117,6 +1162,8 @@ void atari_get_model(char *model)
if (is_medusa)
/* Medusa has TT _MCH cookie */
strcat (model, "Medusa");
+ else if (is_hades)
+ strcat(model, "Hades");
else
strcat (model, "TT");
break;
@@ -1125,21 +1172,20 @@ void atari_get_model(char *model)
break;
default:
sprintf (model + strlen (model), "(unknown mach cookie 0x%lx)",
- boot_info.bi_atari.mch_cookie);
+ atari_mch_cookie);
break;
}
}
-int atari_get_hardware_list(char *buffer)
+static int atari_get_hardware_list(char *buffer)
{
int len = 0, i;
- for (i = 0; i < boot_info.num_memory; i++)
+ for (i = 0; i < m68k_num_memory; i++)
len += sprintf (buffer+len, "\t%3ld MB at 0x%08lx (%s)\n",
- boot_info.memory[i].size >> 20,
- boot_info.memory[i].addr,
- (boot_info.memory[i].addr & 0xff000000 ?
+ m68k_memory[i].size >> 20, m68k_memory[i].addr,
+ (m68k_memory[i].addr & 0xff000000 ?
"alternate RAM" : "ST-RAM"));
#define ATARIHW_ANNOUNCE(name,str) \
@@ -1174,6 +1220,7 @@ int atari_get_hardware_list(char *buffer)
ATARIHW_ANNOUNCE(SCU, "System Control Unit");
ATARIHW_ANNOUNCE(BLITTER, "Blitter");
ATARIHW_ANNOUNCE(VME, "VME Bus");
+ ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
return(len);
}
diff --git a/arch/m68k/atari/joystick.c b/arch/m68k/atari/joystick.c
index 67acec33b..de6014171 100644
--- a/arch/m68k/atari/joystick.c
+++ b/arch/m68k/atari/joystick.c
@@ -10,6 +10,7 @@
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/major.h>
+#include <linux/poll.h>
#include <asm/atarikb.h>
#include <asm/atari_joystick.h>
@@ -54,7 +55,7 @@ void atari_joystick_interrupt(char *buf)
/* ikbd_joystick_event_on(); */
}
-static void release_joystick(struct inode *inode, struct file *file)
+static int release_joystick(struct inode *inode, struct file *file)
{
int minor = DEVICE_NR(inode->i_rdev);
@@ -63,6 +64,7 @@ static void release_joystick(struct inode *inode, struct file *file)
if ((joystick[0].active == 0) && (joystick[1].active == 0))
ikbd_joystick_disable();
+ return 0;
}
static int open_joystick(struct inode *inode, struct file *file)
@@ -89,30 +91,28 @@ static long read_joystick(struct inode *inode, struct file *file,
char *buffer, unsigned long count)
{
int minor = DEVICE_NR(inode->i_rdev);
- int i;
if (count < 2)
return -EINVAL;
if (!joystick[minor].ready)
return -EAGAIN;
- put_user(joystick[minor].fire, buffer++);
- put_user(joystick[minor].dir, buffer++);
- for (i = 0; i < count; i++)
- put_user(0, buffer++);
joystick[minor].ready = 0;
-
- return i;
+ if (put_user(joystick[minor].fire, buffer++) ||
+ put_user(joystick[minor].dir, buffer++))
+ return -EFAULT;
+ if (count > 2)
+ if (clear_user(buffer, count - 2))
+ return -EFAULT;
+ return count;
}
-static int joystick_select(struct inode *inode, struct file *file, int sel_type, select_table *wait)
+static unsigned int joystick_poll(struct file *file, poll_table *wait)
{
- int minor = DEVICE_NR(inode->i_rdev);
+ int minor = DEVICE_NR(file->f_inode->i_rdev);
- if (sel_type != SEL_IN)
- return 0;
+ poll_wait(&joystick[minor].wait, wait);
if (joystick[minor].ready)
- return 1;
- select_wait(&joystick[minor].wait, wait);
+ return POLLIN | POLLRDNORM;
return 0;
}
@@ -121,7 +121,7 @@ struct file_operations atari_joystick_fops = {
read_joystick,
write_joystick,
NULL, /* joystick_readdir */
- joystick_select,
+ joystick_poll,
NULL, /* joystick_ioctl */
NULL, /* joystick_mmap */
open_joystick,
@@ -134,7 +134,7 @@ int atari_joystick_init(void)
joystick[0].ready = joystick[1].ready = 0;
joystick[0].wait = joystick[1].wait = NULL;
- if (register_chrdev(MAJOR_NR, "joystick", &atari_joystick_fops))
+ if (register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops))
printk("unable to get major %d for joystick devices\n", MAJOR_NR);
return 0;
diff --git a/arch/m68k/atari/ksyms.c b/arch/m68k/atari/ksyms.c
deleted file mode 100644
index 303babbe1..000000000
--- a/arch/m68k/atari/ksyms.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <linux/module.h>
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atarikb.h>
-#include <asm/atari_joystick.h>
-#include <asm/atari_stdma.h>
-
-extern void atari_microwire_cmd( int cmd );
-
-static struct symbol_table mach_atari_symbol_table = {
-#include <linux/symtab_begin.h>
-
- X(is_medusa),
- X(atari_register_vme_int),
- X(atari_unregister_vme_int),
- X(stdma_lock),
- X(stdma_release),
- X(stdma_others_waiting),
- X(stdma_islocked),
-
- X(atari_mouse_buttons),
- X(atari_mouse_interrupt_hook),
- X(atari_MIDI_interrupt_hook),
- X(ikbd_write),
- X(ikbd_mouse_y0_top),
- X(ikbd_mouse_thresh),
- X(ikbd_mouse_rel_pos),
- X(ikbd_mouse_disable),
-
- X(atari_microwire_cmd),
-
-#include <linux/symtab_end.h>
-};
-
-void mach_atari_syms_export(void)
-{
- register_symtab(&mach_atari_symbol_table);
-}
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index af4a6c7b6..247b9f684 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -32,7 +32,6 @@
#include <linux/types.h>
#include <linux/genhd.h>
#include <linux/sched.h>
-#include <asm/setup.h>
#include <asm/atari_stdma.h>
#include <asm/atariints.h>
#include <asm/atarihw.h>
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index a82988dae..565b20535 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -26,8 +26,8 @@ void
atari_stram_init (void)
{
struct stram_desc *dp;
- stramaddr = boot_info.bi_atari.stram_start;
- stramsize = boot_info.bi_atari.stram_size;
+ stramaddr = atari_stram_start;
+ stramsize = atari_stram_size;
/* initialize start boundary */
dp = DP (stramaddr);
@@ -194,11 +194,11 @@ void atari_stram_init( void )
{ int i;
- for( i = 0; i < boot_info.num_memory; ++i ) {
- if (boot_info.memory[i].addr == 0) {
+ for( i = 0; i < m68k_num_memory; ++i ) {
+ if (m68k_memory[i].addr == 0) {
rsvd_stram_beg = PTOV( 0x800 ); /* skip super-only first 2 KB! */
rsvd_stram_end = rsvd_stram_beg;
- stram_end = rsvd_stram_beg - 0x800 + boot_info.memory[i].size;
+ stram_end = rsvd_stram_beg - 0x800 + m68k_memory[i].size;
return;
}
}
diff --git a/arch/m68k/boot/Makefile b/arch/m68k/boot/Makefile
index e67a9c4d1..822030ebb 100644
--- a/arch/m68k/boot/Makefile
+++ b/arch/m68k/boot/Makefile
@@ -8,14 +8,16 @@
ifdef CONFIG_AMIGA
AMIGA_BOOTSTRAP = amiga_bootstrap
AMIGA_BOOTOBJS := amiga/bootstrap.o amiga/linuxboot.o
-AMIGA_HOSTCC = m68k-cbm-amigados-gcc -I$(TOPDIR)/include
+AMIGA_HOSTCC = m68k-cbm-amigados-gcc
+AMIGA_HOSTINC = -I$(TOPDIR)/include
AMIGA_HOSTFLAGS=-m68030 -O2 -Wall -Dlinux
endif
ifdef CONFIG_ATARI
ATARI_BOOTSTRAP = atari_bootstrap
ATARI_BOOTOBJS := atari/bootstrap.o
-ATARI_HOSTCC = m68k-mint-gcc -I$(TOPDIR)/include
+ATARI_HOSTCC = m68k-mint-gcc
+ATARI_HOSTINC = -I$(TOPDIR)/include
ATARI_HOSTFLAGS = -m68030 -m68881 -Dlinux -O2 -Wall
# BOOTP/TFTP support in bootstrap?
@@ -36,27 +38,28 @@ endif
ifdef CONFIG_ATARI
atari_bootstrap: $(ATARI_BOOTOBJS)
- $(ATARI_HOSTCC) $(ATARI_HOSTFLAGS) -o $@ $(ATARI_BOOTOBJS)
+ $(ATARI_HOSTCC) $(ATARI_HOSTINC) $(ATARI_HOSTFLAGS) -o $@ $(ATARI_BOOTOBJS)
rm -f ../../../bootstrap
ln $@ ../../../bootstrap
endif
ifdef CONFIG_AMIGA
amiga_bootstrap: $(AMIGA_BOOTOBJS)
- $(AMIGA_HOSTCC) $(AMIGA_HOSTFLAGS) -o $@ -s -noixemul $(AMIGA_BOOTOBJS)
+ $(AMIGA_HOSTCC) $(AMIGA_HOSTINC) $(AMIGA_HOSTFLAGS) -o $@ -s -noixemul $(AMIGA_BOOTOBJS)
rm -f ../../../bootstrap
ln $@ ../../../bootstrap
endif
$(AMIGA_BOOTOBJS): %.o: %.c
- $(AMIGA_HOSTCC) $(AMIGA_HOSTFLAGS) -c $< -o $@
+ $(AMIGA_HOSTCC) $(AMIGA_HOSTINC) $(AMIGA_HOSTFLAGS) -c $< -o $@
$(ATARI_BOOTOBJS): %.o: %.c
- $(ATARI_HOSTCC) $(ATARI_HOSTFLAGS) -c $< -o $@
+ $(ATARI_HOSTCC) $(ATARI_HOSTINC) $(ATARI_HOSTFLAGS) -c $< -o $@
bootstrap: $(AMIGA_BOOTSTRAP) $(ATARI_BOOTSTRAP)
clean:
- rm -f *.o amiga/*.o atari/*.o amiga_bootstrap atari_bootstrap
+ rm -f *.o amiga/*.o atari/*.o amiga_bootstrap atari_bootstrap \
+ ../../../bootstrap
dep:
diff --git a/arch/m68k/boot/amiga/bootstrap.c b/arch/m68k/boot/amiga/bootstrap.c
index 20ca0621f..b109466ed 100644
--- a/arch/m68k/boot/amiga/bootstrap.c
+++ b/arch/m68k/boot/amiga/bootstrap.c
@@ -21,6 +21,8 @@
** Modified 9-Sep-96 by Geert Uytterhoeven
** - Rewritten option parsing
** - New parameter passing to linuxboot() (linuxboot_args)
+** Modified 6-Oct-96 by Geert Uytterhoeven
+** - Updated for the new boot information structure
**
** 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
@@ -40,7 +42,7 @@
/* required Linux/m68k include files */
#include <linux/a.out.h>
#include <linux/elf.h>
-#include <asm/setup.h>
+#include <asm/amigahw.h>
#include <asm/page.h>
/* Amiga bootstrap include files */
@@ -49,9 +51,8 @@
/* Library Bases */
+long __oslibversion = 36;
extern const struct ExecBase *SysBase;
-const struct ExpansionBase *ExpansionBase;
-const struct GfxBase *GfxBase;
static const char *memfile_name = NULL;
@@ -78,23 +79,25 @@ static int Read(int fd, char *buf, int count);
static void Close(int fd);
static int FileSize(const char *path);
static void Sleep(u_long micros);
-static int ModifyBootinfo(struct bootinfo *bi);
static void Usage(void)
{
fprintf(stderr,
- "Linux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n\n"
- "Usage: %s [options] [kernel command line]\n\n"
- "Valid options are:\n"
- " -h, --help Display this usage information\n"
- " -k, --kernel file Use kernel image `file' (default is `vmlinux')\n"
- " -r, --ramdisk file Use ramdisk image `file'\n"
- " -d, --debug Enable debug mode\n"
- " -m, --memfile file Use memory file `file'\n"
- " -v, --keep-video Don't reset the video mode\n"
- " -t, --model id Set the Amiga model to `id'\n\n",
- ProgramName);
+ "Linux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n\n"
+ "Usage: %s [options] [kernel command line]\n\n"
+ "Basic options:\n"
+ " -h, --help Display this usage information\n"
+ " -k, --kernel file Use kernel image `file' (default is `vmlinux')\n"
+ " -r, --ramdisk file Use ramdisk image `file'\n"
+ "Advanced options:\n"
+ " -d, --debug Enable debug mode\n"
+ " -b, --baud speed Set the serial port speed (default is 9600)\n"
+ " -m, --memfile file Use memory file `file'\n"
+ " -v, --keep-video Don't reset the video mode\n"
+ " -t, --model id Set the Amiga model to `id'\n"
+ " -p, --processor cfm Set the processor type to `cfm\n\n",
+ ProgramName);
exit(EXIT_FAILURE);
}
@@ -102,7 +105,8 @@ static void Usage(void)
int main(int argc, char *argv[])
{
int i;
- int debugflag = 0, keep_video = 0;
+ int processor = 0, debugflag = 0, keep_video = 0;
+ u_int baud = 0;
const char *kernel_name = NULL;
const char *ramdisk_name = NULL;
char commandline[CL_SIZE] = "";
@@ -113,33 +117,45 @@ int main(int argc, char *argv[])
if (!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help"))
Usage();
else if (!strcmp(argv[0], "-k") || !strcmp(argv[0], "--kernel"))
- if (--argc && !kernel_name) {
- kernel_name = argv[1];
- argv++;
- } else
- Usage();
+ if (--argc && !kernel_name) {
+ kernel_name = argv[1];
+ argv++;
+ } else
+ Usage();
else if (!strcmp(argv[0], "-r") || !strcmp(argv[0], "--ramdisk"))
- if (--argc && !ramdisk_name) {
- ramdisk_name = argv[1];
- argv++;
- } else
- Usage();
+ if (--argc && !ramdisk_name) {
+ ramdisk_name = argv[1];
+ argv++;
+ } else
+ Usage();
else if (!strcmp(argv[0], "-d") || !strcmp(argv[0], "--debug"))
debugflag = 1;
+ else if (!strcmp(argv[0], "-b") || !strcmp(argv[0], "--baud"))
+ if (--argc && !baud) {
+ baud = atoi(argv[1]);
+ argv++;
+ } else
+ Usage();
else if (!strcmp(argv[0], "-m") || !strcmp(argv[0], "--memfile"))
- if (--argc && !memfile_name) {
- memfile_name = argv[1];
- argv++;
- } else
- Usage();
+ if (--argc && !memfile_name) {
+ memfile_name = argv[1];
+ argv++;
+ } else
+ Usage();
else if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--keep-video"))
keep_video = 1;
else if (!strcmp(argv[0], "-t") || !strcmp(argv[0], "--model"))
- if (--argc && !model) {
- model = atoi(argv[1]);
- argv++;
- } else
- Usage();
+ if (--argc && !model) {
+ model = atoi(argv[1]);
+ argv++;
+ } else
+ Usage();
+ else if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--processor"))
+ if (--argc && !processor) {
+ processor = atoi(argv[1]);
+ argv++;
+ } else
+ Usage();
else
break;
}
@@ -148,22 +164,6 @@ int main(int argc, char *argv[])
SysBase = *(struct ExecBase **)4;
- /* open Expansion Library */
- ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",
- 36);
- if (!ExpansionBase) {
- fputs("Unable to open expansion.library V36 or greater! Aborting...\n",
- stderr);
- exit(EXIT_FAILURE);
- }
-
- /* open Graphics Library */
- GfxBase = (struct GfxBase *)OpenLibrary ("graphics.library", 0);
- if (!GfxBase) {
- fputs("Unable to open graphics.library! Aborting...\n", stderr);
- exit(EXIT_FAILURE);
- }
-
/*
* Join command line options
*/
@@ -177,12 +177,56 @@ int main(int argc, char *argv[])
}
}
+ memset(&args.bi, 0, sizeof(args.bi));
+ if (processor) {
+ int cpu = processor/100%10;
+ int fpu = processor/10%10;
+ int mmu = processor%10;
+ if (cpu)
+ args.bi.cputype = 1<<(cpu-1);
+ if (fpu)
+ args.bi.fputype = 1<<(fpu-1);
+ if (mmu)
+ args.bi.mmutype = 1<<(mmu-1);
+ }
+ /*
+ * If we have a memory file, read the memory information from it
+ */
+ if (memfile_name) {
+ FILE *fp;
+ int i;
+
+ if ((fp = fopen(memfile_name, "r")) == NULL) {
+ perror("open memory file");
+ fprintf(stderr, "Cannot open memory file %s\n", memfile_name);
+ return(FALSE);
+ }
+
+ if (fscanf(fp, "%lu", &args.bi.chip_size) != 1) {
+ fprintf(stderr, "memory file does not contain chip memory size\n");
+ fclose(fp);
+ return(FALSE);
+ }
+
+ for (i = 0; i < NUM_MEMINFO; i++)
+ if (fscanf(fp, "%lx %lu", &args.bi.memory[i].addr,
+ &args.bi.memory[i].size) != 2)
+ break;
+
+ fclose(fp);
+ args.bi.num_memory = i;
+ }
+ strncpy(args.bi.command_line, commandline, CL_SIZE);
+ args.bi.command_line[CL_SIZE-1] = '\0';
+ if (model != AMI_UNKNOWN)
+ args.bi.model = model;
+
args.kernelname = kernel_name;
args.ramdiskname = ramdisk_name;
- args.commandline = commandline;
args.debugflag = debugflag;
args.keep_video = keep_video;
args.reset_boards = 1;
+ args.baud = baud;
args.puts = Puts;
args.getchar = GetChar;
args.putchar = PutChar;
@@ -193,14 +237,10 @@ int main(int argc, char *argv[])
args.close = Close;
args.filesize = FileSize;
args.sleep = Sleep;
- args.modify_bootinfo = ModifyBootinfo;
/* Do The Right Stuff */
linuxboot(&args);
- CloseLibrary((struct Library *)GfxBase);
- CloseLibrary((struct Library *)ExpansionBase);
-
/* if we ever get here, something went wrong */
exit(EXIT_FAILURE);
}
@@ -213,6 +253,7 @@ int main(int argc, char *argv[])
static void Puts(const char *str)
{
fputs(str, stderr);
+ fflush(stderr);
}
static long GetChar(void)
@@ -223,6 +264,7 @@ static long GetChar(void)
static void PutChar(char c)
{
fputc(c, stderr);
+ fflush(stderr);
}
static void Printf(const char *fmt, ...)
@@ -232,6 +274,7 @@ static void Printf(const char *fmt, ...)
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
+ fflush(stderr);
}
static int Open(const char *path)
@@ -260,8 +303,8 @@ static int FileSize(const char *path)
int fd, size = -1;
if ((fd = open(path, O_RDONLY)) != -1) {
- size = lseek(fd, 0, SEEK_END);
- close(fd);
+ size = lseek(fd, 0, SEEK_END);
+ close(fd);
}
return(size);
}
@@ -288,46 +331,3 @@ static void Sleep(u_long micros)
DeleteMsgPort(TimerPort);
}
}
-
-
-static int ModifyBootinfo(struct bootinfo *bi)
-{
- /*
- * if we have a memory file, read the memory information from it
- */
- if (memfile_name) {
- FILE *fp;
- int i;
-
- if ((fp = fopen(memfile_name, "r")) == NULL) {
- perror("open memory file");
- fprintf(stderr, "Cannot open memory file %s\n", memfile_name);
- return(FALSE);
- }
-
- if (fscanf(fp, "%lu", &bi->bi_amiga.chip_size) != 1) {
- fprintf(stderr, "memory file does not contain chip memory size\n");
- fclose(fp);
- return(FALSE);
- }
-
- for (i = 0; i < NUM_MEMINFO; i++) {
- if (fscanf(fp, "%lx %lu", &bi->memory[i].addr, &bi->memory[i].size)
- != 2)
- break;
- }
-
- fclose(fp);
-
- if (i != bi->num_memory && i > 0)
- bi->num_memory = i;
- }
-
- /*
- * change the Amiga model, if necessary
- */
- if (model != AMI_UNKNOWN)
- bi->bi_amiga.model = model;
-
- return(TRUE);
-}
diff --git a/arch/m68k/boot/amiga/bootstrap.h b/arch/m68k/boot/amiga/bootstrap.h
index d7a5c44fd..4d072cc75 100644
--- a/arch/m68k/boot/amiga/bootstrap.h
+++ b/arch/m68k/boot/amiga/bootstrap.h
@@ -20,8 +20,6 @@
**
*/
-#include <asm/amigatypes.h>
-
struct MsgPort {
u_char fill1[15];
@@ -61,30 +59,6 @@ struct Library;
struct IORequest;
-static __inline void CloseLibrary(struct Library *library)
-{
- register const struct ExecBase *a6 __asm("a6") = SysBase;
- register struct Library *a1 __asm("a1") = library;
- __asm __volatile ("jsr a6@(-0x19e)"
- : /* no output */
- : "r" (a6), "r" (a1)
- : "a0","a1","d0","d1", "memory");
-}
-
-static __inline struct Library *OpenLibrary(char *libName,
- unsigned long version)
-{
- register struct Library * _res __asm("d0");
- register const struct ExecBase *a6 __asm("a6") = SysBase;
- register u_char *a1 __asm("a1") = libName;
- register unsigned long d0 __asm("d0") = version;
- __asm __volatile ("jsr a6@(-0x228)"
- : "=r" (_res)
- : "r" (a6), "r" (a1), "r" (d0)
- : "a0","a1","d0","d1", "memory");
- return _res;
-}
-
static __inline char OpenDevice(u_char *devName, u_long unit,
struct IORequest *ioRequest, u_long flags)
{
diff --git a/arch/m68k/boot/amiga/linuxboot.c b/arch/m68k/boot/amiga/linuxboot.c
index 975868c45..d35966686 100644
--- a/arch/m68k/boot/amiga/linuxboot.c
+++ b/arch/m68k/boot/amiga/linuxboot.c
@@ -20,6 +20,24 @@
* 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.
+ *
+ * History:
+ * 03 Feb 1997 Implemented kernel decompression (Geert, based on Roman's
+ * code for ataboot)
+ * 30 Dec 1996 Reverted the CPU detection to the old scheme
+ * New boot parameter override scheme (Geert)
+ * 27 Nov 1996 Compatibility with bootinfo interface version 1.0 (Geert)
+ * 9 Sep 1996 Rewritten option parsing
+ * New parameter passing to linuxboot() (linuxboot_args)
+ * (Geert)
+ * 18 Aug 1996 Updated for the new boot information structure (Geert)
+ * 10 Jan 1996 The real Linux/m68k boot code moved to linuxboot.[ch]
+ * (Geert)
+ * 11 Jul 1995 Support for ELF kernel (untested!) (Andreas)
+ * 7 Mar 1995 Memory block sizes are rounded to a multiple of 256K
+ * instead of 1M (Geert)
+ * 31 May 1994 Memory thrash problem solved (Geert)
+ * 11 May 1994 A3640 MapROM check (Geert)
*/
@@ -28,6 +46,10 @@
#endif /* __GNUC__ */
+#define BOOTINFO_COMPAT_1_0 /* bootinfo interface version 1.0 compatible */
+/* support compressed kernels? */
+#define ZKERNEL
+
#include <stddef.h>
#include <string.h>
#include <errno.h>
@@ -36,8 +58,7 @@
#include <linux/a.out.h>
#include <linux/elf.h>
#include <linux/linkage.h>
-#include <asm/setup.h>
-#include <asm/amigatypes.h>
+#include <asm/bootinfo.h>
#include <asm/amigahw.h>
#include <asm/page.h>
@@ -48,22 +69,36 @@
#define custom ((*(volatile struct CUSTOM *)(CUSTOM_PHYSADDR)))
/* temporary stack size */
-#define TEMP_STACKSIZE (256)
+#define TEMP_STACKSIZE (256)
+
+#define DEFAULT_BAUD (9600)
extern char copyall, copyallend;
static struct exec kexec;
static Elf32_Ehdr kexec_elf;
-static struct bootinfo bi;
-
static const struct linuxboot_args *linuxboot_args;
+/* Bootinfo */
+struct amiga_bootinfo bi;
+
+#ifdef BOOTINFO_COMPAT_1_0
+static struct compat_bootinfo compat_bootinfo;
+#endif /* BOOTINFO_COMPAT_1_0 */
+
+#define MAX_BI_SIZE (4096)
+static u_long bi_size;
+static union {
+ struct bi_record record;
+ u_char fake[MAX_BI_SIZE];
+} bi_union;
+
#define kernelname linuxboot_args->kernelname
#define ramdiskname linuxboot_args->ramdiskname
-#define commandline linuxboot_args->commandline
#define debugflag linuxboot_args->debugflag
#define keep_video linuxboot_args->keep_video
#define reset_boards linuxboot_args->reset_boards
+#define baud linuxboot_args->baud
#define Puts linuxboot_args->puts
#define GetChar linuxboot_args->getchar
@@ -75,23 +110,38 @@ static const struct linuxboot_args *linuxboot_args;
#define Close linuxboot_args->close
#define FileSize linuxboot_args->filesize
#define Sleep linuxboot_args->sleep
-#define ModifyBootinfo linuxboot_args->modify_bootinfo
-
/*
* Function Prototypes
*/
static u_long get_chipset(void);
-static u_long get_cpu(void);
+static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu);
static u_long get_model(u_long chipset);
static int probe_resident(const char *name);
static int probe_resource(const char *name);
+static int create_bootinfo(void);
+#ifdef BOOTINFO_COMPAT_1_0
+static int create_compat_bootinfo(void);
+#endif /* BOOTINFO_COMPAT_1_0 */
+static int add_bi_record(u_short tag, u_short size, const void *data);
+static int add_bi_string(u_short tag, const u_char *s);
static int check_bootinfo_version(const char *memptr);
static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
u_long start_mem, u_long mem_size, u_long rd_size,
u_long kernel_size) __attribute__ ((noreturn));
asmlinkage u_long maprommed(void);
+asmlinkage u_long check346(void);
+#ifdef ZKERNEL
+static int load_zkernel(int fd);
+static int KRead(int fd, void *buf, int cnt);
+static int KSeek(int fd, int offset);
+static int KClose(int fd);
+#else
+#define KRead Read
+#define KSeek Seek
+#define KClose Close
+#endif
/*
@@ -126,7 +176,7 @@ static struct boardreset boardresetdb[] = {
};
#define NUM_BOARDRESET sizeof(boardresetdb)/sizeof(*boardresetdb)
-static void (*boardresetfuncs[NUM_AUTO])(const struct ConfigDev *cd);
+static void (*boardresetfuncs[ZORRO_NUM_AUTO])(const struct ConfigDev *cd);
const char *amiga_models[] = {
@@ -151,7 +201,7 @@ const u_long last_amiga_model = AMI_DRACO;
u_long linuxboot(const struct linuxboot_args *args)
{
- int kfd = -1, rfd = -1, elf_kernel = 0;
+ int kfd = -1, rfd = -1, elf_kernel = 0, do_fast, do_chip;
int i, j;
const struct MemHeader *mnp;
struct ConfigDev *cdp = NULL;
@@ -159,11 +209,13 @@ u_long linuxboot(const struct linuxboot_args *args)
u_long *stack = NULL;
u_long fast_total, model_mask, startcodesize, start_mem, mem_size, rd_size;
u_long kernel_size;
+ u_int realbaud;
u_long memreq = 0, text_offset = 0;
Elf32_Phdr *kernel_phdrs = NULL;
void (*startfunc)(void);
u_short manuf;
u_char prod;
+ void *bi_ptr;
linuxboot_args = args;
@@ -171,37 +223,42 @@ u_long linuxboot(const struct linuxboot_args *args)
Puts("\nLinux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n");
Puts("Copyright 1993,1994 by Hamish Macdonald and Greg Harp\n\n");
+ /* Note: Initial values in bi override detected values */
+ bi = args->bi;
+
/* machine is Amiga */
bi.machtype = MACH_AMIGA;
/* determine chipset */
- bi.bi_amiga.chipset = get_chipset();
+ if (!bi.chipset)
+ bi.chipset = get_chipset();
- /* determine CPU type */
- bi.cputype = get_cpu();
+ /* determine CPU, FPU and MMU type */
+ if (!bi.cputype)
+ get_processor(&bi.cputype, &bi.fputype, &bi.mmutype);
/* determine Amiga model */
- bi.bi_amiga.model = get_model(bi.bi_amiga.chipset);
- model_mask = (bi.bi_amiga.model != AMI_UNKNOWN) ? 1<<bi.bi_amiga.model : 0;
+ if (!bi.model)
+ bi.model = get_model(bi.chipset);
+ model_mask = (bi.model != AMI_UNKNOWN) ? 1<<bi.model : 0;
/* Memory & AutoConfig based on 'unix_boot.c' by C= */
/* find all of the autoconfig boards in the system */
- bi.bi_amiga.num_autocon = 0;
- for (i = 0; (cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1)); i++) {
- if (bi.bi_amiga.num_autocon < NUM_AUTO) {
- /* copy the contents of each structure into our boot info */
- memcpy(&bi.bi_amiga.autocon[bi.bi_amiga.num_autocon], cdp,
- sizeof(struct ConfigDev));
- /* count this device */
- bi.bi_amiga.num_autocon++;
- } else
- Printf("Warning: too many AutoConfig devices. Ignoring device at "
- "0x%08lx\n", cdp->cd_BoardAddr);
- }
-
+ if (!bi.num_autocon)
+ for (i = 0; (cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1)); i++)
+ if (bi.num_autocon < ZORRO_NUM_AUTO)
+ /* copy the contents of each structure into our boot info and
+ count this device */
+ memcpy(&bi.autocon[bi.num_autocon++], cdp,
+ sizeof(struct ConfigDev));
+ else
+ Printf("Warning: too many AutoConfig devices. Ignoring device at "
+ "0x%08lx\n", cdp->cd_BoardAddr);
+
+ do_fast = bi.num_memory ? 0 : 1;
+ do_chip = bi.chip_size ? 0 : 1;
/* find out the memory in the system */
- bi.num_memory = 0;
for (mnp = (struct MemHeader *)SysBase->MemList.lh_Head;
mnp->mh_Node.ln_Succ;
mnp = (struct MemHeader *)mnp->mh_Node.ln_Succ) {
@@ -240,7 +297,7 @@ u_long linuxboot(const struct linuxboot_args *args)
mh.mh_Lower = (void *)((u_long)mh.mh_Lower & 0xfffff000);
/* if fast memory */
- if (mh.mh_Attributes & MEMF_FAST) {
+ if (do_fast && mh.mh_Attributes & MEMF_FAST) {
/* set the size value to the size of this block and mask off to a
256K increment */
u_long size = ((u_long)mh.mh_Upper-(u_long)mh.mh_Lower)&0xfffc0000;
@@ -253,38 +310,36 @@ u_long linuxboot(const struct linuxboot_args *args)
bi.num_memory++;
} else
Printf("Warning: too many memory blocks. Ignoring block "
- "of %ldK at 0x%08x\n", size>>10,
+ "of %ldK at 0x%08x\n", size>>10,
(u_long)mh.mh_Lower);
- } else if (mh.mh_Attributes & MEMF_CHIP)
+ } else if (do_chip && mh.mh_Attributes & MEMF_CHIP)
/* if CHIP memory, record the size */
- bi.bi_amiga.chip_size = (u_long)mh.mh_Upper;
+ bi.chip_size = (u_long)mh.mh_Upper;
}
/* get info from ExecBase */
- bi.bi_amiga.vblank = SysBase->VBlankFrequency;
- bi.bi_amiga.psfreq = SysBase->PowerSupplyFrequency;
- bi.bi_amiga.eclock = SysBase->ex_EClockFrequency;
-
- /* copy command line options into the kernel command line */
- strncpy(bi.command_line, commandline, CL_SIZE);
- bi.command_line[CL_SIZE-1] = '\0';
-
-
- /* modify the bootinfo, e.g. to change the memory configuration */
- if (ModifyBootinfo && !ModifyBootinfo(&bi))
- goto Fail;
-
+ if (!bi.vblank)
+ bi.vblank = SysBase->VBlankFrequency;
+ if (!bi.psfreq)
+ bi.psfreq = SysBase->PowerSupplyFrequency;
+ if (!bi.eclock)
+ bi.eclock = SysBase->ex_EClockFrequency;
+
+ /* serial port */
+ if (!bi.serper) {
+ realbaud = baud ? baud : DEFAULT_BAUD;
+ bi.serper = (5*bi.eclock+realbaud/2)/realbaud-1;
+ }
/* display Amiga model */
- if (bi.bi_amiga.model >= first_amiga_model &&
- bi.bi_amiga.model <= last_amiga_model)
- Printf("%s ", amiga_models[bi.bi_amiga.model-first_amiga_model]);
+ if (bi.model >= first_amiga_model && bi.model <= last_amiga_model)
+ Printf("%s ", amiga_models[bi.model-first_amiga_model]);
else
Puts("Amiga ");
/* display the CPU type */
Puts("CPU: ");
- switch (bi.cputype & CPU_MASK) {
+ switch (bi.cputype) {
case CPU_68020:
Puts("68020 (Do you have an MMU?)");
break;
@@ -302,7 +357,7 @@ u_long linuxboot(const struct linuxboot_args *args)
Printf("SysBase->AttnFlags = 0x%08lx\n", SysBase->AttnFlags);
goto Fail;
}
- switch (bi.cputype & ~CPU_MASK) {
+ switch (bi.fputype) {
case FPU_68881:
Puts(" with 68881 FPU");
break;
@@ -319,7 +374,7 @@ u_long linuxboot(const struct linuxboot_args *args)
}
/* display the chipset */
- switch(bi.bi_amiga.chipset) {
+ switch (bi.chipset) {
case CS_STONEAGE:
Puts(", old or unknown chipset");
break;
@@ -340,21 +395,21 @@ u_long linuxboot(const struct linuxboot_args *args)
Printf("Command line is '%s'\n", bi.command_line);
/* display the clock statistics */
- Printf("Vertical Blank Frequency: %ldHz\n", bi.bi_amiga.vblank);
- Printf("Power Supply Frequency: %ldHz\n", bi.bi_amiga.psfreq);
- Printf("EClock Frequency: %ldHz\n\n", bi.bi_amiga.eclock);
+ Printf("Vertical Blank Frequency: %ldHz\n", bi.vblank);
+ Printf("Power Supply Frequency: %ldHz\n", bi.psfreq);
+ Printf("EClock Frequency: %ldHz\n\n", bi.eclock);
/* display autoconfig devices */
- if (bi.bi_amiga.num_autocon) {
- Printf("Found %ld AutoConfig Device%s\n", bi.bi_amiga.num_autocon,
- bi.bi_amiga.num_autocon > 1 ? "s" : "");
- for (i = 0; i < bi.bi_amiga.num_autocon; i++) {
+ if (bi.num_autocon) {
+ Printf("Found %ld AutoConfig Device%s\n", bi.num_autocon,
+ bi.num_autocon > 1 ? "s" : "");
+ for (i = 0; i < bi.num_autocon; i++) {
Printf("Device %ld: addr = 0x%08lx", i,
- (u_long)bi.bi_amiga.autocon[i].cd_BoardAddr);
+ (u_long)bi.autocon[i].cd_BoardAddr);
boardresetfuncs[i] = NULL;
if (reset_boards) {
- manuf = bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer;
- prod = bi.bi_amiga.autocon[i].cd_Rom.er_Product;
+ manuf = bi.autocon[i].cd_Rom.er_Manufacturer;
+ prod = bi.autocon[i].cd_Rom.er_Product;
for (j = 0; j < NUM_BOARDRESET; j++)
if ((manuf == boardresetdb[j].manuf) &&
(prod == boardresetdb[j].prod)) {
@@ -383,7 +438,7 @@ u_long linuxboot(const struct linuxboot_args *args)
}
/* display chip memory size */
- Printf("%ldK of CHIP memory\n", bi.bi_amiga.chip_size>>10);
+ Printf("%ldK of CHIP memory\n", bi.chip_size>>10);
start_mem = bi.memory[0].addr;
mem_size = bi.memory[0].size;
@@ -392,7 +447,7 @@ u_long linuxboot(const struct linuxboot_args *args)
Printf("\nThe kernel will be located at 0x%08lx\n", start_mem);
/* verify that there is enough Chip RAM */
- if (bi.bi_amiga.chip_size < 512*1024) {
+ if (bi.chip_size < 512*1024) {
Puts("Not enough Chip RAM in this system. Aborting...\n");
goto Fail;
}
@@ -414,22 +469,39 @@ u_long linuxboot(const struct linuxboot_args *args)
goto Fail;
}
/* record ramdisk size */
- bi.ramdisk_size = (size+1023)>>10;
+ bi.ramdisk.size = size;
} else
- bi.ramdisk_size = 0;
- rd_size = bi.ramdisk_size<<10;
- bi.ramdisk_addr = start_mem+mem_size-rd_size;
+ bi.ramdisk.size = 0;
+ rd_size = bi.ramdisk.size;
+ bi.ramdisk.addr = (u_long)start_mem+mem_size-rd_size;
+
+ /* create the bootinfo structure */
+ if (!create_bootinfo())
+ goto Fail;
/* open kernel executable and read exec header */
if ((kfd = Open(kernelname)) == -1) {
Printf("Unable to open kernel file `%s'\n", kernelname);
goto Fail;
}
- if (Read(kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
+ if (KRead(kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
Puts("Unable to read exec header from kernel file\n");
goto Fail;
}
+#ifdef ZKERNEL
+ if (((unsigned char *)&kexec)[0] == 037 &&
+ (((unsigned char *)&kexec)[1] == 0213 ||
+ ((unsigned char *)&kexec)[1] == 0236)) {
+ /* That's a compressed kernel */
+ Puts("Kernel is compressed\n");
+ if (load_zkernel(kfd)) {
+ Puts("Decompression error -- aborting\n");
+ goto Fail;
+ }
+ }
+#endif
+
switch (N_MAGIC(kexec)) {
case ZMAGIC:
if (debugflag)
@@ -447,8 +519,8 @@ u_long linuxboot(const struct linuxboot_args *args)
default:
/* Try to parse it as an ELF header */
- Seek(kfd, 0);
- if ((Read(kfd, (void *)&kexec_elf, sizeof(kexec_elf)) ==
+ KSeek(kfd, 0);
+ if ((KRead(kfd, (void *)&kexec_elf, sizeof(kexec_elf)) ==
sizeof(kexec_elf)) &&
(memcmp(&kexec_elf.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0)) {
elf_kernel = 1;
@@ -469,8 +541,8 @@ u_long linuxboot(const struct linuxboot_args *args)
Puts("Unable to allocate memory for program headers\n");
goto Fail;
}
- Seek(kfd, kexec_elf.e_phoff);
- if (Read(kfd, (void *)kernel_phdrs,
+ KSeek(kfd, kexec_elf.e_phoff);
+ if (KRead(kfd, (void *)kernel_phdrs,
kexec_elf.e_phnum*sizeof(*kernel_phdrs)) !=
kexec_elf.e_phnum*sizeof(*kernel_phdrs)) {
Puts("Unable to read program headers from kernel file\n");
@@ -511,7 +583,11 @@ u_long linuxboot(const struct linuxboot_args *args)
kernel_size = max_addr-min_addr;
} else
kernel_size = kexec.a_text+kexec.a_data+kexec.a_bss;
- memreq = kernel_size+sizeof(struct bootinfo)+rd_size;
+ memreq = kernel_size+bi_size+rd_size;
+#ifdef BOOTINFO_COMPAT_1_0
+ if (sizeof(compat_bootinfo) > bi_size)
+ memreq = kernel_size+sizeof(compat_bootinfo)+rd_size;
+#endif /* BOOTINFO_COMPAT_1_0 */
if (!(memptr = (char *)AllocMem(memreq, MEMF_FAST | MEMF_PUBLIC |
MEMF_CLEAR))) {
Puts("Unable to allocate memory\n");
@@ -521,48 +597,63 @@ u_long linuxboot(const struct linuxboot_args *args)
/* read the text and data segments from the kernel image */
if (elf_kernel)
for (i = 0; i < kexec_elf.e_phnum; i++) {
- if (Seek(kfd, kernel_phdrs[i].p_offset) == -1) {
+ if (KSeek(kfd, kernel_phdrs[i].p_offset) == -1) {
Printf("Failed to seek to segment %ld\n", i);
goto Fail;
}
- if (Read(kfd, memptr+kernel_phdrs[i].p_vaddr-PAGE_SIZE,
- kernel_phdrs[i].p_filesz) != kernel_phdrs[i].p_filesz) {
+ if (KRead(kfd, memptr+kernel_phdrs[i].p_vaddr-PAGE_SIZE,
+ kernel_phdrs[i].p_filesz) != kernel_phdrs[i].p_filesz) {
Printf("Failed to read segment %ld\n", i);
goto Fail;
}
}
else {
- if (Seek(kfd, text_offset) == -1) {
- Printf("Failed to seek to text\n");
+ if (KSeek(kfd, text_offset) == -1) {
+ Puts("Failed to seek to text\n");
goto Fail;
}
- if (Read(kfd, memptr, kexec.a_text) != kexec.a_text) {
- Printf("Failed to read text\n");
+ if (KRead(kfd, memptr, kexec.a_text) != kexec.a_text) {
+ Puts("Failed to read text\n");
goto Fail;
}
/* data follows immediately after text */
- if (Read(kfd, memptr+kexec.a_text, kexec.a_data) != kexec.a_data) {
- Printf("Failed to read data\n");
+ if (KRead(kfd, memptr+kexec.a_text, kexec.a_data) != kexec.a_data) {
+ Puts("Failed to read data\n");
goto Fail;
}
}
- Close(kfd);
+ KClose(kfd);
kfd = -1;
/* Check kernel's bootinfo version */
- if (!check_bootinfo_version(memptr))
- goto Fail;
+ switch (check_bootinfo_version(memptr)) {
+ case BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION):
+ bi_ptr = &bi_union.record;
+ break;
+
+#ifdef BOOTINFO_COMPAT_1_0
+ case BI_VERSION_MAJOR(COMPAT_AMIGA_BOOTI_VERSION):
+ if (!create_compat_bootinfo())
+ goto Fail;
+ bi_ptr = &compat_bootinfo;
+ bi_size = sizeof(compat_bootinfo);
+ break;
+#endif /* BOOTINFO_COMPAT_1_0 */
+
+ default:
+ goto Fail;
+ }
/* copy the bootinfo to the end of the kernel image */
- memcpy((void *)(memptr+kernel_size), &bi, sizeof(struct bootinfo));
+ memcpy((void *)(memptr+kernel_size), bi_ptr, bi_size);
if (ramdiskname) {
if ((rfd = Open(ramdiskname)) == -1) {
Printf("Unable to open ramdisk file `%s'\n", ramdiskname);
goto Fail;
}
- if (Read(rfd, memptr+kernel_size+sizeof(bi), rd_size) != rd_size) {
- Printf("Failed to read ramdisk file\n");
+ if (Read(rfd, memptr+kernel_size+bi_size, rd_size) != rd_size) {
+ Puts("Failed to read ramdisk file\n");
goto Fail;
}
Close(rfd);
@@ -587,9 +678,9 @@ u_long linuxboot(const struct linuxboot_args *args)
memcpy(startfunc, &copyall, startcodesize);
if (debugflag) {
- if (bi.ramdisk_size)
+ if (bi.ramdisk.size)
Printf("RAM disk at 0x%08lx, size is %ldK\n",
- (u_long)memptr+kernel_size, bi.ramdisk_size);
+ (u_long)memptr+kernel_size, bi.ramdisk.size>>10);
if (elf_kernel) {
PutChar('\n');
@@ -611,9 +702,10 @@ u_long linuxboot(const struct linuxboot_args *args)
kexec.a_entry);
Printf("ramdisk dest top is 0x%08lx\n", start_mem+mem_size);
- Printf("ramdisk lower limit is 0x%08lx\n", (u_long)memptr+kernel_size);
+ Printf("ramdisk lower limit is 0x%08lx\n",
+ (u_long)(memptr+kernel_size));
Printf("ramdisk src top is 0x%08lx\n",
- (u_long)memptr+kernel_size+rd_size);
+ (u_long)(memptr+kernel_size)+rd_size);
Puts("\nType a key to continue the Linux/m68k boot...");
GetChar();
@@ -631,9 +723,9 @@ u_long linuxboot(const struct linuxboot_args *args)
/* reset nasty Zorro boards */
if (reset_boards)
- for (i = 0; i < bi.bi_amiga.num_autocon; i++)
+ for (i = 0; i < bi.num_autocon; i++)
if (boardresetfuncs[i])
- boardresetfuncs[i](&bi.bi_amiga.autocon[i]);
+ boardresetfuncs[i](&bi.autocon[i]);
/* Turn off all DMA */
custom.dmacon = DMAF_ALL | DMAF_MASTER;
@@ -654,7 +746,7 @@ u_long linuxboot(const struct linuxboot_args *args)
/* Clean up and exit in case of a failure */
Fail:
if (kfd != -1)
- Close(kfd);
+ KClose(kfd);
if (rfd != -1)
Close(rfd);
if (memptr)
@@ -696,32 +788,29 @@ static u_long get_chipset(void)
* Determine the CPU Type
*/
-static u_long get_cpu(void)
+static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu)
{
- u_long cpu = 0;
-
- if (SysBase->AttnFlags & AFF_68060) {
- cpu = CPU_68060;
- if (SysBase->AttnFlags & AFF_FPU40)
- cpu |= FPU_68060;
- } else if (SysBase->AttnFlags & AFF_68040) {
- cpu = CPU_68040;
+ *cpu = *fpu = 0;
+ if (SysBase->AttnFlags & AFF_68060)
+ *cpu = CPU_68060;
+ else if (SysBase->AttnFlags & AFF_68040)
+ *cpu = CPU_68040;
+ else if (SysBase->AttnFlags & AFF_68030)
+ *cpu = CPU_68030;
+ else if (SysBase->AttnFlags & AFF_68020)
+ *cpu = CPU_68020;
+ if (*cpu == CPU_68040 || *cpu == CPU_68060) {
if (SysBase->AttnFlags & AFF_FPU40)
- cpu |= FPU_68040;
+ *fpu = *cpu;
} else {
- if (SysBase->AttnFlags & AFF_68030)
- cpu = CPU_68030;
- else if (SysBase->AttnFlags & AFF_68020)
- cpu = CPU_68020;
if (SysBase->AttnFlags & AFF_68882)
- cpu |= FPU_68882;
+ *fpu = FPU_68882;
else if (SysBase->AttnFlags & AFF_68881)
- cpu |= FPU_68881;
+ *fpu = FPU_68881;
}
- return(cpu);
+ *mmu = *cpu;
}
-
/*
* Determine the Amiga Model
*/
@@ -737,7 +826,7 @@ static u_long get_model(u_long chipset)
else {
if (debugflag)
Puts(" Chipset: ");
- switch(chipset) {
+ switch (chipset) {
case CS_STONEAGE:
if (debugflag)
Puts("Old or unknown\n");
@@ -810,7 +899,7 @@ static int probe_resident(const char *name)
if (res)
Printf("0x%08lx\n", res);
else
- Printf("not present\n");
+ Puts("not present\n");
return(res ? TRUE : FALSE);
}
@@ -830,12 +919,179 @@ static int probe_resource(const char *name)
if (res)
Printf("0x%08lx\n", res);
else
- Printf("not present\n");
+ Puts("not present\n");
return(res ? TRUE : FALSE);
}
/*
+ * Create the Bootinfo structure
+ */
+
+static int create_bootinfo(void)
+{
+ int i;
+ struct bi_record *record;
+
+ /* Initialization */
+ bi_size = 0;
+
+ /* Generic tags */
+ if (!add_bi_record(BI_MACHTYPE, sizeof(bi.machtype), &bi.machtype))
+ return(0);
+ if (!add_bi_record(BI_CPUTYPE, sizeof(bi.cputype), &bi.cputype))
+ return(0);
+ if (!add_bi_record(BI_FPUTYPE, sizeof(bi.fputype), &bi.fputype))
+ return(0);
+ if (!add_bi_record(BI_MMUTYPE, sizeof(bi.mmutype), &bi.mmutype))
+ return(0);
+ for (i = 0; i < bi.num_memory; i++)
+ if (!add_bi_record(BI_MEMCHUNK, sizeof(bi.memory[i]), &bi.memory[i]))
+ return(0);
+ if (bi.ramdisk.size)
+ if (!add_bi_record(BI_RAMDISK, sizeof(bi.ramdisk), &bi.ramdisk))
+ return(0);
+ if (!add_bi_string(BI_COMMAND_LINE, bi.command_line))
+ return(0);
+
+ /* Amiga tags */
+ if (!add_bi_record(BI_AMIGA_MODEL, sizeof(bi.model), &bi.model))
+ return(0);
+ for (i = 0; i < bi.num_autocon; i++)
+ if (!add_bi_record(BI_AMIGA_AUTOCON, sizeof(bi.autocon[i]),
+ &bi.autocon[i]))
+ return(0);
+ if (!add_bi_record(BI_AMIGA_CHIP_SIZE, sizeof(bi.chip_size), &bi.chip_size))
+ return(0);
+ if (!add_bi_record(BI_AMIGA_VBLANK, sizeof(bi.vblank), &bi.vblank))
+ return(0);
+ if (!add_bi_record(BI_AMIGA_PSFREQ, sizeof(bi.psfreq), &bi.psfreq))
+ return(0);
+ if (!add_bi_record(BI_AMIGA_ECLOCK, sizeof(bi.eclock), &bi.eclock))
+ return(0);
+ if (!add_bi_record(BI_AMIGA_CHIPSET, sizeof(bi.chipset), &bi.chipset))
+ return(0);
+ if (!add_bi_record(BI_AMIGA_SERPER, sizeof(bi.serper), &bi.serper))
+ return(0);
+
+ /* Trailer */
+ record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
+ record->tag = BI_LAST;
+ bi_size += sizeof(bi_union.record.tag);
+
+ return(1);
+}
+
+
+ /*
+ * Add a Record to the Bootinfo Structure
+ */
+
+static int add_bi_record(u_short tag, u_short size, const void *data)
+{
+ struct bi_record *record;
+ u_int size2;
+
+ size2 = (sizeof(struct bi_record)+size+3)&-4;
+ if (bi_size+size2+sizeof(bi_union.record.tag) > MAX_BI_SIZE) {
+ Puts("Can't add bootinfo record. Ask a wizard to enlarge me.\n");
+ return(0);
+ }
+ record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
+ record->tag = tag;
+ record->size = size2;
+ memcpy(record->data, data, size);
+ bi_size += size2;
+ return(1);
+}
+
+
+ /*
+ * Add a String Record to the Bootinfo Structure
+ */
+
+static int add_bi_string(u_short tag, const u_char *s)
+{
+ return(add_bi_record(tag, strlen(s)+1, (void *)s));
+}
+
+
+#ifdef BOOTINFO_COMPAT_1_0
+
+ /*
+ * Create the Bootinfo structure for backwards compatibility mode
+ */
+
+static int create_compat_bootinfo(void)
+{
+ u_int i;
+
+ compat_bootinfo.machtype = bi.machtype;
+ if (bi.cputype & CPU_68020)
+ compat_bootinfo.cputype = COMPAT_CPU_68020;
+ else if (bi.cputype & CPU_68030)
+ compat_bootinfo.cputype = COMPAT_CPU_68030;
+ else if (bi.cputype & CPU_68040)
+ compat_bootinfo.cputype = COMPAT_CPU_68040;
+ else if (bi.cputype & CPU_68060)
+ compat_bootinfo.cputype = COMPAT_CPU_68060;
+ else {
+ Printf("CPU type 0x%08lx not supported by kernel\n", bi.cputype);
+ return(0);
+ }
+ if (bi.fputype & FPU_68881)
+ compat_bootinfo.cputype |= COMPAT_FPU_68881;
+ else if (bi.fputype & FPU_68882)
+ compat_bootinfo.cputype |= COMPAT_FPU_68882;
+ else if (bi.fputype & FPU_68040)
+ compat_bootinfo.cputype |= COMPAT_FPU_68040;
+ else if (bi.fputype & FPU_68060)
+ compat_bootinfo.cputype |= COMPAT_FPU_68060;
+ else {
+ Printf("FPU type 0x%08lx not supported by kernel\n", bi.fputype);
+ return(0);
+ }
+ compat_bootinfo.num_memory = bi.num_memory;
+ if (compat_bootinfo.num_memory > COMPAT_NUM_MEMINFO) {
+ Printf("Warning: using only %ld blocks of memory\n",
+ COMPAT_NUM_MEMINFO);
+ compat_bootinfo.num_memory = COMPAT_NUM_MEMINFO;
+ }
+ for (i = 0; i < compat_bootinfo.num_memory; i++) {
+ compat_bootinfo.memory[i].addr = bi.memory[i].addr;
+ compat_bootinfo.memory[i].size = bi.memory[i].size;
+ }
+ if (bi.ramdisk.size) {
+ compat_bootinfo.ramdisk_size = (bi.ramdisk.size+1023)/1024;
+ compat_bootinfo.ramdisk_addr = bi.ramdisk.addr;
+ } else {
+ compat_bootinfo.ramdisk_size = 0;
+ compat_bootinfo.ramdisk_addr = 0;
+ }
+ strncpy(compat_bootinfo.command_line, bi.command_line, COMPAT_CL_SIZE);
+ compat_bootinfo.command_line[COMPAT_CL_SIZE-1] = '\0';
+
+ compat_bootinfo.bi_amiga.model = bi.model;
+ compat_bootinfo.bi_amiga.num_autocon = bi.num_autocon;
+ if (compat_bootinfo.bi_amiga.num_autocon > COMPAT_NUM_AUTO) {
+ Printf("Warning: using only %ld AutoConfig devices\n",
+ COMPAT_NUM_AUTO);
+ compat_bootinfo.bi_amiga.num_autocon = COMPAT_NUM_AUTO;
+ }
+ for (i = 0; i < compat_bootinfo.bi_amiga.num_autocon; i++)
+ compat_bootinfo.bi_amiga.autocon[i] = bi.autocon[i];
+ compat_bootinfo.bi_amiga.chip_size = bi.chip_size;
+ compat_bootinfo.bi_amiga.vblank = bi.vblank;
+ compat_bootinfo.bi_amiga.psfreq = bi.psfreq;
+ compat_bootinfo.bi_amiga.eclock = bi.eclock;
+ compat_bootinfo.bi_amiga.chipset = bi.chipset;
+ compat_bootinfo.bi_amiga.hw_present = 0;
+ return(1);
+}
+#endif /* BOOTINFO_COMPAT_1_0 */
+
+
+ /*
* Compare the Bootstrap and Kernel Versions
*/
@@ -852,7 +1108,7 @@ static int check_bootinfo_version(const char *memptr)
break;
}
if (!version)
- Printf("Kernel has no bootinfo version info, assuming 0.0\n");
+ Puts("Kernel has no bootinfo version info, assuming 0.0\n");
kernel_major = BI_VERSION_MAJOR(version);
kernel_minor = BI_VERSION_MINOR(version);
@@ -863,16 +1119,27 @@ static int check_bootinfo_version(const char *memptr)
Printf("Kernel's bootinfo version : %ld.%ld\n", kernel_major,
kernel_minor);
- if (kernel_major != boots_major) {
- Printf("\nThis bootstrap is too %s for this kernel!\n",
- boots_major < kernel_major ? "old" : "new");
- return(0);
- }
- if (kernel_minor > boots_minor) {
- Printf("Warning: Bootinfo version of bootstrap and kernel differ!\n" );
- Printf(" Certain features may not work.\n");
+ switch (kernel_major) {
+ case BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION):
+ if (kernel_minor > boots_minor) {
+ Puts("Warning: Bootinfo version of bootstrap and kernel "
+ "differ!\n");
+ Puts(" Certain features may not work.\n");
+ }
+ break;
+
+#ifdef BOOTINFO_COMPAT_1_0
+ case BI_VERSION_MAJOR(COMPAT_AMIGA_BOOTI_VERSION):
+ Puts("(using backwards compatibility mode)\n");
+ break;
+#endif /* BOOTINFO_COMPAT_1_0 */
+
+ default:
+ Printf("\nThis bootstrap is too %s for this kernel!\n",
+ boots_major < kernel_major ? "old" : "new");
+ return(0);
}
- return(1);
+ return(kernel_major);
}
@@ -891,7 +1158,7 @@ static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
register u_long d0 __asm("d0") = mem_size;
register u_long d1 __asm("d1") = rd_size;
register u_long d2 __asm("d2") = kernel_size;
- register u_long d3 __asm("d3") = sizeof(struct bootinfo);
+ register u_long d3 __asm("d3") = bi_size;
__asm __volatile ("movel a2,sp;"
"jmp a0@"
@@ -915,7 +1182,7 @@ static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
* d0 = mem_size
* d1 = rd_size
* d2 = kernel_size
- * d3 = sizeof(struct bootinfo)
+ * d3 = bi_size
*/
asm(".text\n"
@@ -931,10 +1198,10 @@ SYMBOL_NAME_STR(copyall) ":
moveb a0@+,a1@+ | *dest++ = *src++;
jra 1b
2:
- | /* copy early bootinfo to end of bss */
+ | /* copy bootinfo to end of bss */
movel a3,a0 | src = (u_long *)(memptr+kernel_size);
addl d2,a0 | dest = end of bss (already in a1)
- movel d3,d7 | count = sizeof(struct bootinfo)
+ movel d3,d7 | count = bi_size
subql #1,d7
1: moveb a0@+,a1@+ | while (--count > -1)
dbra d7,1b | *dest++ = *src++
@@ -944,7 +1211,7 @@ SYMBOL_NAME_STR(copyall) ":
movel a4,a1 | dest = (u_long *)(start_mem+mem_size);
addl d0,a1
movel a3,a2 | limit = (u_long *)(memptr+kernel_size +
- addl d2,a2 | sizeof(struct bootinfo));
+ addl d2,a2 | bi_size);
addl d3,a2
movel a2,a0 | src = (u_long *)((u_long)limit+rd_size);
addl d1,a0
@@ -1114,7 +1381,7 @@ static void reset_hydra(const struct ConfigDev *cd)
Disable();
*nic_cr = 0x21; /* nic command register: software reset etc. */
- while(((*nic_isr & 0x80) == 0) && --n) /* wait for reset to complete */
+ while (((*nic_isr & 0x80) == 0) && --n) /* wait for reset to complete */
;
Enable();
@@ -1126,3 +1393,294 @@ static void reset_a2060(const struct ConfigDev *cd)
#error reset_a2060: not yet implemented
}
#endif
+
+
+#ifdef ZKERNEL
+
+#define ZFILE_CHUNK_BITS 16 /* chunk is 64 KB */
+#define ZFILE_CHUNK_SIZE (1 << ZFILE_CHUNK_BITS)
+#define ZFILE_CHUNK_MASK (ZFILE_CHUNK_SIZE-1)
+#define ZFILE_N_CHUNKS (2*1024*1024/ZFILE_CHUNK_SIZE)
+
+/* variables for storing the uncompressed data */
+static char *ZFile[ZFILE_N_CHUNKS];
+static int ZFileSize = 0;
+static int ZFpos = 0;
+static int Zwpos = 0;
+
+static int Zinfd = 0; /* fd of compressed file */
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args) args
+
+#define memzero(s, n) memset ((s), 0, (n))
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+#define INBUFSIZ 4096
+#define WSIZE 0x8000 /* window size--must be a power of two, and */
+ /* at least 32K for zip's deflate method */
+
+static uch *inbuf;
+static uch *window;
+
+static unsigned insize = 0; /* valid bytes in inbuf */
+static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
+static unsigned outcnt = 0; /* bytes in output buffer */
+static int exit_code = 0;
+static long bytes_out = 0;
+
+#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+
+/* Diagnostic functions (stubbed out) */
+#define Assert(cond,msg)
+#define Trace(x)
+#define Tracev(x)
+#define Tracevv(x)
+#define Tracec(c,x)
+#define Tracecv(c,x)
+
+#define STATIC static
+
+static int fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+#define malloc(x) AllocVec(x, MEMF_FAST | MEMF_PUBLIC)
+#define free(x) FreeVec(x)
+
+#ifdef LILO
+#include "inflate.c"
+#else
+#include "../../../../lib/inflate.c"
+#endif
+
+static void gzip_mark(void **ptr)
+{
+}
+
+static void gzip_release(void **ptr)
+{
+}
+
+
+/*
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf(void)
+{
+ if (exit_code)
+ return -1;
+
+ insize = Read(Zinfd, inbuf, INBUFSIZ);
+ if (insize <= 0)
+ return -1;
+
+ inptr = 1;
+ return(inbuf[0]);
+}
+
+/*
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window(void)
+{
+ ulg c = crc; /* temporary variable */
+ unsigned n;
+ uch *in, ch;
+ int chunk = Zwpos >> ZFILE_CHUNK_BITS;
+
+ if (exit_code)
+ return;
+
+ if (chunk >= ZFILE_N_CHUNKS) {
+ error("Compressed image too large! Aborting.\n");
+ return;
+ }
+ if (!ZFile[chunk]) {
+ if (!(ZFile[chunk] = (char *)AllocMem(ZFILE_CHUNK_SIZE,
+ MEMF_FAST | MEMF_PUBLIC))) {
+ error("Out of memory for decompresing kernel image\n");
+ return;
+ }
+ }
+ memcpy(ZFile[chunk] + (Zwpos & ZFILE_CHUNK_MASK), window, outcnt);
+ Zwpos += outcnt;
+
+#define DISPLAY_BITS 10
+ if ((Zwpos & ((1 << DISPLAY_BITS)-1)) == 0)
+ PutChar('.');
+
+ in = window;
+ for (n = 0; n < outcnt; n++) {
+ ch = *in++;
+ c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+ }
+ crc = c;
+ bytes_out += (ulg)outcnt;
+ outcnt = 0;
+}
+
+static void error(char *x)
+{
+ Printf("\n%s", x);
+ exit_code = 1;
+}
+
+static inline int call_sub(int (*func)(void), void *stackp)
+{
+ register int _res __asm("d0");
+ register int (*a0)(void) __asm("a0") = func;
+ register int (*a1)(void) __asm("a1") = stackp;
+
+ __asm __volatile ("movel sp,a2;"
+ "movel a1,sp;"
+ "jsr a0@;"
+ "movel a2,sp"
+ : "=r" (_res)
+ : "r" (a0), "r" (a1)
+ : "a0", "a1", "a2", "d0", "d1", "memory");
+ return(_res);
+}
+
+static int load_zkernel(int fd)
+{
+ int i, err = -1;
+#define ZSTACKSIZE (16384)
+ u_long *zstack;
+
+ for (i = 0; i < ZFILE_N_CHUNKS; ++i)
+ ZFile[i] = NULL;
+ Zinfd = fd;
+ Seek(fd, 0);
+
+ if (!(inbuf = (uch *)AllocMem(INBUFSIZ, MEMF_FAST | MEMF_PUBLIC)))
+ Puts("Couldn't allocate gunzip buffer\n");
+ else {
+ if (!(window = (uch *)AllocMem(WSIZE, MEMF_FAST | MEMF_PUBLIC)))
+ Puts("Couldn't allocate gunzip window\n");
+ else {
+ if (!(zstack = (u_long *)AllocMem(ZSTACKSIZE,
+ MEMF_FAST | MEMF_PUBLIC)))
+ Puts("Couldn't allocate gunzip stack\n");
+ else {
+ Puts("Uncompressing kernel image ");
+ makecrc();
+ if (!(err = call_sub(gunzip, (char *)zstack+ZSTACKSIZE)))
+ Puts("done\n");
+ ZFileSize = Zwpos;
+ FreeMem(zstack, ZSTACKSIZE);
+ }
+ FreeMem(window, WSIZE);
+ window = NULL;
+ }
+ FreeMem(inbuf, INBUFSIZ);
+ inbuf = NULL;
+ }
+ Close(Zinfd); /* input file not needed anymore */
+ return(err);
+}
+
+
+/* Note about the read/lseek wrapper and its memory management: It assumes
+ * that all seeks are only forward, and thus data already read or skipped can
+ * be freed. This is true for current organization of bootstrap and kernels.
+ * Little exception: The struct kexec at the start of the file. After reading
+ * it, there may be a seek back to the end of the file. But this currently
+ * doesn't hurt. (Roman)
+ */
+
+static int KRead(int fd, void *buf, int cnt)
+{
+ unsigned done = 0;
+
+ if (!ZFileSize)
+ return(Read(fd, buf, cnt));
+
+ if (ZFpos + cnt > ZFileSize)
+ cnt = ZFileSize - ZFpos;
+
+ while (cnt > 0) {
+ unsigned chunk = ZFpos >> ZFILE_CHUNK_BITS;
+ unsigned endchunk = (chunk+1) << ZFILE_CHUNK_BITS;
+ unsigned n = cnt;
+
+ if (ZFpos + n > endchunk)
+ n = endchunk - ZFpos;
+ memcpy(buf, ZFile[chunk] + (ZFpos & ZFILE_CHUNK_MASK), n);
+ cnt -= n;
+ buf += n;
+ done += n;
+ ZFpos += n;
+
+ if (ZFpos == endchunk) {
+ FreeMem(ZFile[chunk], ZFILE_CHUNK_SIZE);
+ ZFile[chunk] = NULL;
+ }
+ }
+
+ return(done);
+}
+
+
+static int KSeek(int fd, int offset)
+{
+ unsigned oldpos, oldchunk, newchunk;
+
+ if (!ZFileSize)
+ return(Seek(fd, offset));
+
+ oldpos = ZFpos;
+ ZFpos = offset;
+ if (ZFpos < 0) {
+ ZFpos = 0;
+ return(-1);
+ } else if (ZFpos > ZFileSize) {
+ ZFpos = ZFileSize;
+ return(-1);
+ }
+
+ /* free memory of skipped-over data */
+ oldchunk = oldpos >> ZFILE_CHUNK_BITS;
+ newchunk = ZFpos >> ZFILE_CHUNK_BITS;
+ while(oldchunk < newchunk) {
+ if (ZFile[oldchunk]) {
+ FreeMem(ZFile[oldchunk], ZFILE_CHUNK_SIZE);
+ ZFile[oldchunk] = NULL;
+ }
+ ++oldchunk;
+ }
+ return(ZFpos);
+}
+
+
+static void free_zfile(void)
+{
+ int i;
+
+ for (i = 0; i < ZFILE_N_CHUNKS; ++i)
+ if (ZFile[i]) {
+ FreeMem(ZFile[i], ZFILE_CHUNK_SIZE);
+ ZFile[i] = NULL;
+ }
+}
+
+static int KClose(int fd)
+{
+ if (ZFileSize) {
+ free_zfile();
+ ZFileSize = 0;
+ } else
+ Close(fd);
+ return(0);
+}
+#endif /* ZKERNEL */
diff --git a/arch/m68k/boot/amiga/linuxboot.h b/arch/m68k/boot/amiga/linuxboot.h
index 2331a994d..8ebfe63b4 100644
--- a/arch/m68k/boot/amiga/linuxboot.h
+++ b/arch/m68k/boot/amiga/linuxboot.h
@@ -24,14 +24,42 @@
#include <asm/setup.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
/*
* Amiboot Version
*/
-#define AMIBOOT_VERSION "4.0"
+#define AMIBOOT_VERSION "5.4"
+
+
+ /*
+ * Amiga Bootinfo Definitions
+ *
+ * All limits herein are `soft' limits, i.e. they don't put constraints
+ * on the actual parameters in the kernel.
+ */
+
+struct amiga_bootinfo {
+ u_long machtype; /* machine type = MACH_AMIGA */
+ u_long cputype; /* system CPU */
+ u_long fputype; /* system FPU */
+ u_long mmutype; /* system MMU */
+ int num_memory; /* # of memory blocks found */
+ struct mem_info memory[NUM_MEMINFO];/* memory description */
+ struct mem_info ramdisk; /* ramdisk description */
+ char command_line[CL_SIZE]; /* kernel command line parameters */
+ u_long model; /* Amiga Model */
+ int num_autocon; /* # of autoconfig devices found */
+ struct ConfigDev autocon[ZORRO_NUM_AUTO]; /* autoconfig devices */
+ u_long chip_size; /* size of chip memory (bytes) */
+ u_char vblank; /* VBLANK frequency */
+ u_char psfreq; /* power supply frequency */
+ u_long eclock; /* EClock frequency */
+ u_long chipset; /* native chipset present */
+ u_short serper; /* serial port period */
+};
/*
@@ -39,12 +67,13 @@
*/
struct linuxboot_args {
+ struct amiga_bootinfo bi; /* Initial values override detected values */
const char *kernelname;
const char *ramdiskname;
- const char *commandline;
int debugflag;
int keep_video;
int reset_boards;
+ u_int baud;
void (*puts)(const char *str);
long (*getchar)(void);
void (*putchar)(char c);
@@ -55,7 +84,6 @@ struct linuxboot_args {
void (*close)(int fd);
int (*filesize)(const char *path);
void (*sleep)(u_long micros);
- int (*modify_bootinfo)(struct bootinfo *bi);
};
diff --git a/arch/m68k/boot/atari/bootp.c b/arch/m68k/boot/atari/bootp.c
index db4fc284f..affe636b8 100644
--- a/arch/m68k/boot/atari/bootp.c
+++ b/arch/m68k/boot/atari/bootp.c
@@ -203,18 +203,20 @@ static int eth_rcv( Packet *pkt, int *len );
/* get_remote_kernel():
* Perform all necessary steps to get the kernel image
* from the boot server. If successfull (retval == 0), subsequent calls to
- * kread() can access the data.
+ * kread() can access the data. Fatal errors (i.e., retrying is useless)
+ * return -2, others -1.
*/
int get_remote_kernel( const char *kname /* optional */ )
{ char image_name[256];
-
+ int rv;
+
/* Check if a Ethernet interface is present and determine the Ethernet
* address */
if (check_ethif() < 0) {
printf( "No Ethernet interface found -- no remote boot possible.\n" );
- return( -1 );
+ return( -2 );
}
/* Do a BOOTP request to find out our IP address and the kernel image's
@@ -223,23 +225,23 @@ int get_remote_kernel( const char *kname /* optional */ )
strcpy( image_name, kname );
else
*image_name = 0;
- if (bootp( image_name ) < 0)
- return( -1 );
+ if ((rv = bootp( image_name )) < 0)
+ return( rv );
/* Now start a TFTP connection to receive the kernel image */
- if (tftp( image_name ) < 0)
- return( -1 );
+ if ((rv = tftp( image_name )) < 0)
+ return( rv );
return( 0 );
}
-/* kread(), klseek(), kclose():
+/* ll_read(), ll_lseek(), ll_close():
* Functions for accessing the received kernel image like with read(),
* lseek(), close().
*/
-int kread( int fd, void *buf, unsigned cnt )
+int ll_read( int fd, void *buf, unsigned cnt )
{ unsigned done = 0;
@@ -261,18 +263,26 @@ int kread( int fd, void *buf, unsigned cnt )
buf += n;
done += n;
KFpos += n;
+
+ if (KFpos == endchunk) {
+ free( KFile[chunk] );
+ KFile[chunk] = NULL;
+ }
}
return( done );
}
-int klseek( int fd, int where, int whence )
+int ll_lseek( int fd, int where, int whence )
{
+ unsigned oldpos, oldchunk, newchunk;
+
if (!KFileSize)
return( lseek( fd, where, whence ) );
+ oldpos = KFpos;
switch( whence ) {
case SEEK_SET:
KFpos = where;
@@ -295,11 +305,22 @@ int klseek( int fd, int where, int whence )
return( -1 );
}
+ /* free memory of skipped-over data */
+ oldchunk = oldpos >> KFILE_CHUNK_BITS;
+ newchunk = KFpos >> KFILE_CHUNK_BITS;
+ while( oldchunk < newchunk ) {
+ if (KFile[oldchunk]) {
+ free( KFile[oldchunk] );
+ KFile[oldchunk] = NULL;
+ }
+ ++oldchunk;
+ }
+
return( KFpos );
}
-int kclose( int fd )
+int ll_close( int fd )
{
if (!KFileSize)
@@ -382,7 +403,7 @@ static int bootp( char *image_name )
}
if (retry >= BOOTP_RETRYS) {
printf( "No response from a bootp server\n" );
- return( -1 );
+ return( -2 );
}
ServerIPaddr = reply->bootp.siaddr;
@@ -433,7 +454,7 @@ static int tftp( char *image_name )
printf( "TFTP RREQ: %s\n", ErrStr[-err-1] );
if (--retries > 0)
goto repeat_req;
- return( -1 );
+ return( err == ETIMEO ? -2 : -1 );
}
retries = 5;
diff --git a/arch/m68k/boot/atari/bootp.h b/arch/m68k/boot/atari/bootp.h
index 02988edaf..0ee96cdcc 100644
--- a/arch/m68k/boot/atari/bootp.h
+++ b/arch/m68k/boot/atari/bootp.h
@@ -34,9 +34,9 @@ typedef unsigned long IPADDR;
/***************************** Prototypes *****************************/
int get_remote_kernel( const char *kname );
-int kread( int fd, void *buf, unsigned cnt );
-int klseek( int fd, int where, int whence );
-int kclose( int fd );
+int ll_read( int fd, void *buf, unsigned cnt );
+int ll_lseek( int fd, int where, int whence );
+int ll_close( int fd );
/************************* End of Prototypes **************************/
diff --git a/arch/m68k/boot/atari/bootstrap.c b/arch/m68k/boot/atari/bootstrap.c
index dbf5fada0..84c6a6e4b 100644
--- a/arch/m68k/boot/atari/bootstrap.c
+++ b/arch/m68k/boot/atari/bootstrap.c
@@ -8,7 +8,13 @@
** for more details.
**
** History:
-** 10 Dec 1995 BOOTP/TFTP support (Roman)
+** 01 Feb 1997 Implemented kernel decompression (Roman)
+** 28 Nov 1996 Fixed and tested previous change (James)
+** 27 Nov 1996 Compatibility with bootinfo interface version 1.0 (Geert)
+** 12 Nov 1996 Fixed and tested previous change (Andreas)
+** 18 Aug 1996 Updated for the new boot information structure (untested!)
+** (Geert)
+** 10 Dec 1995 BOOTP/TFTP support (Roman)
** 03 Oct 1995 Allow kernel to be loaded to TT ram again (Andreas)
** 11 Jul 1995 Add support for ELF format kernel (Andreas)
** 16 Jun 1995 Adapted to Linux 1.2: kernel always loaded into ST ram
@@ -26,6 +32,11 @@
** 14 Mar 1994 New mini-copy routine used (rdv)
*/
+
+#define BOOTINFO_COMPAT_1_0 /* bootinfo interface version 1.0 compatible */
+/* support compressed kernels? */
+#define ZKERNEL
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -43,6 +54,7 @@
#include <asm/page.h>
#define _LINUX_TYPES_H /* Hack to prevent including <linux/types.h> */
+#include <asm/bootinfo.h>
#include <asm/setup.h>
/* Atari bootstrap include file */
@@ -54,10 +66,29 @@
extern char *optarg;
extern int optind;
static void get_default_args( int *argc, char ***argv );
+static int create_bootinfo(void);
+#ifdef BOOTINFO_COMPAT_1_0
+static int create_compat_bootinfo(void);
+#endif /* BOOTINFO_COMPAT_1_0 */
+static int add_bi_record(u_short tag, u_short size, const void *data);
+static int add_bi_string(u_short tag, const u_char *s);
/* This is missing in <unistd.h> */
extern int sync (void);
-struct bootinfo bi;
+/* Bootinfo */
+static struct atari_bootinfo bi;
+
+#ifdef BOOTINFO_COMPAT_1_0
+static struct compat_bootinfo compat_bootinfo;
+#endif /* BOOTINFO_COMPAT_1_0 */
+
+#define MAX_BI_SIZE (4096)
+static u_long bi_size;
+static union {
+struct bi_record record;
+ u_char fake[MAX_BI_SIZE];
+} bi_union;
+
u_long *cookiejar;
u_long userstk;
@@ -132,6 +163,9 @@ extern char copyall, copyallend;
* ...err! On the Afterburner040 (for the Falcon) it's the same... So we do
* another test with 0x00ff82fe, that gives a bus error on the Falcon, but is
* in the range where the Medusa always asserts DTACK.
+ * On the Hades address 0 is writeable as well and it asserts DTACK on
+ * address 0x00ff82fe. To test if the machine is a Hades, address 0xb0000000
+ * is tested. On the Medusa this gives a bus error.
*/
int test_medusa( void )
@@ -150,7 +184,10 @@ int test_medusa( void )
"nop \n\t"
"tstb 0x00ff82fe\n\t"
"nop \n\t"
- "moveq #1,%0\n"
+ "moveq #1,%0\n\t"
+ "tstb 0xb0000000\n\t"
+ "nop \n\t"
+ "moveq #0,%0\n"
"Lberr:\t"
"movel a1,sp\n\t"
"movel a0,0x8"
@@ -303,27 +340,48 @@ static int check_bootinfo_version(char *memptr)
printf("Kernel's bootinfo version : %d.%d\n",
kernel_major, kernel_minor);
- if (kernel_major != boots_major) {
- printf("\nThis bootstrap is too %s for this kernel!\n",
- boots_major < kernel_major ? "old" : "new");
- return 0;
- }
- if (kernel_minor > boots_minor) {
- printf("Warning: Bootinfo version of bootstrap and kernel differ!\n");
- printf(" Certain features may not work.\n");
+ switch (kernel_major) {
+ case BI_VERSION_MAJOR(ATARI_BOOTI_VERSION):
+ if (kernel_minor > boots_minor) {
+ printf("Warning: Bootinfo version of bootstrap and kernel "
+ "differ!\n");
+ printf(" Certain features may not work.\n");
+ }
+ break;
+
+#ifdef BOOTINFO_COMPAT_1_0
+ case BI_VERSION_MAJOR(COMPAT_ATARI_BOOTI_VERSION):
+ printf("(using backwards compatibility mode)\n");
+ break;
+#endif /* BOOTINFO_COMPAT_1_0 */
+
+ default:
+ printf("\nThis bootstrap is too %s for this kernel!\n",
+ boots_major < kernel_major ? "old" : "new");
+ return 0;
}
- return 1;
+ return kernel_major;
}
#ifdef USE_BOOTP
# include "bootp.h"
#else
-# define kread read
-# define klseek lseek
-# define kclose close
+# define ll_read read
+# define ll_lseek lseek
+# define ll_close close
#endif
+#ifdef ZKERNEL
+static int load_zkernel( int fd );
+static int kread( int fd, void *buf, unsigned cnt );
+static int klseek( int fd, int where, int whence );
+static int kclose( int fd );
+#else
+# define kread read
+# define klseek lseek
+# define kclose close
+#endif
/* ++andreas: this must be inline due to Super */
static inline void boot_exit (int) __attribute__ ((noreturn));
@@ -347,15 +405,18 @@ int main(int argc, char *argv[])
Elf32_Ehdr kexec_elf;
Elf32_Phdr *kernel_phdrs = NULL;
u_long start_mem, mem_size, rd_size, text_offset = 0, kernel_size;
+ int prefer_bootp = 1, kname_set = 0, n_knames;
#ifdef USE_BOOTP
- int prefer_bootp = 1, kname_set = 0;
+ int err;
#endif
+ char kname_list[5][64];
+ void *bi_ptr;
ramdisk_name = NULL;
kernel_name = "vmlinux";
/* print the startup message */
- puts("\fLinux/68k Atari Bootstrap version 1.8"
+ puts("\fLinux/68k Atari Bootstrap version 2.2"
#ifdef USE_BOOTP
" (with BOOTP)"
#endif
@@ -371,11 +432,7 @@ int main(int argc, char *argv[])
bi.machtype = MACH_ATARI;
/* check arguments */
-#ifdef USE_BOOTP
while ((ch = getopt(argc, argv, "bdtsk:r:")) != EOF)
-#else
- while ((ch = getopt(argc, argv, "dtsk:r:")) != EOF)
-#endif
switch (ch) {
case 'd':
debugflag = 1;
@@ -388,18 +445,14 @@ int main(int argc, char *argv[])
break;
case 'k':
kernel_name = optarg;
-#ifdef USE_BOOTP
kname_set = 1;
-#endif
break;
case 'r':
ramdisk_name = optarg;
break;
-#ifdef USE_BOOTP
case 'b':
prefer_bootp = 0;
break;
-#endif
case '?':
default:
usage();
@@ -447,10 +500,10 @@ int main(int argc, char *argv[])
switch(cpu_type) {
case 0:
case 10: break;
- case 20: bi.cputype = CPU_68020; break;
- case 30: bi.cputype = CPU_68030; break;
- case 40: bi.cputype = CPU_68040; break;
- case 60: bi.cputype = CPU_68060; break;
+ case 20: bi.cputype = CPU_68020; bi.mmutype = MMU_68851; break;
+ case 30: bi.cputype = CPU_68030; bi.mmutype = MMU_68030; break;
+ case 40: bi.cputype = CPU_68040; bi.mmutype = MMU_68040; break;
+ case 60: bi.cputype = CPU_68060; bi.mmutype = MMU_68060; break;
default:
fprintf(stderr, "Error: Unknown CPU type. Aborting...\n");
boot_exit(EXIT_FAILURE);
@@ -463,11 +516,11 @@ int main(int argc, char *argv[])
/* check for FPU; in case of a '040 or '060, don't look at _FPU itself,
* some software may set it to wrong values (68882 or the like) */
if (cpu_type == 40) {
- bi.cputype |= FPU_68040;
+ bi.fputype = FPU_68040;
puts( "68040\n" );
}
else if (cpu_type == 60) {
- bi.cputype |= FPU_68060;
+ bi.fputype = FPU_68060;
puts( "68060\n" );
}
else {
@@ -484,12 +537,12 @@ int main(int argc, char *argv[])
goto m68882;
/* fall through */
case 4:
- bi.cputype |= FPU_68881;
+ bi.fputype = FPU_68881;
puts("68881\n");
break;
case 6:
m68882:
- bi.cputype |= FPU_68882;
+ bi.fputype = FPU_68882;
puts("68882\n");
break;
default:
@@ -499,15 +552,13 @@ int main(int argc, char *argv[])
}
/* ++roman: If an FPU was announced in the cookie, test
whether it is a real hardware FPU or a software emulator! */
- if (bi.cputype & FPU_MASK) {
+ if (bi.fputype) {
if (test_software_fpu()) {
- bi.cputype &= ~FPU_MASK;
+ bi.fputype = 0;
puts("FPU: software emulated. Assuming no FPU.");
}
}
- memset(&bi.bi_atari.hw_present, 0, sizeof(bi.bi_atari.hw_present));
-
/* Get the amounts of ST- and TT-RAM. */
/* The size must be a multiple of 1MB. */
i = 0;
@@ -678,7 +729,7 @@ int main(int argc, char *argv[])
#endif
/* Pass contents of the _MCH cookie to the kernel */
- bi.bi_atari.mch_cookie = mch_type;
+ bi.mch_cookie = mch_type;
/*
* Copy command line options into the kernel command line.
@@ -707,38 +758,60 @@ int main(int argc, char *argv[])
boot_exit(-1);
#endif /* TEST */
+ i = 0;
#ifdef USE_BOOTP
+ if (!kname_set)
+ kname_list[i++][0] = '\0'; /* default kernel which BOOTP server says */
+#endif
+#ifdef ZKERNEL
+ strcpy( kname_list[i], kernel_name );
+ strcat( kname_list[i], ".gz" );
+ ++i;
+#endif
+ strcpy( kname_list[i++], kernel_name );
+#ifdef ZKERNEL
+ if (!kname_set)
+ strcpy( kname_list[i++], "vmlinuz" );
+#endif
+ n_knames = i;
+
kfd = -1;
+#ifdef USE_BOOTP
if (prefer_bootp) {
- /* First try to get a remote kernel, then use a local kernel (if
- * present) */
- if (get_remote_kernel( kname_set ? kernel_name : NULL ) < 0) {
- printf( "\nremote boot failed; trying local kernel\n" );
- if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
- fprintf (stderr, "Unable to open kernel file %s\n",
- kernel_name);
- boot_exit (EXIT_FAILURE);
- }
+ for( i = 0; i < n_knames; ++i ) {
+ if ((err = get_remote_kernel( kname_list[i] )) >= 0)
+ goto kernel_open;
+ if (err < -1) /* fatal error; retries don't help... */
+ break;
}
+ printf( "\nremote boot failed; trying local kernel\n" );
}
- else {
- /* Try BOOTP if local kernel cannot be opened */
- if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
- printf( "\nlocal kernel failed; trying remote boot\n" );
- if (get_remote_kernel( kname_set ? kernel_name : NULL ) < 0) {
- fprintf (stderr, "Unable to remote boot and "
- "to open kernel file %s\n", kernel_name);
- boot_exit (EXIT_FAILURE);
- }
- }
+#endif
+ for( i = 0; i < n_knames; ++i ) {
+ if ((kfd = open( kname_list[i], O_RDONLY )) != -1)
+ goto kernel_open;
}
-#else
- /* open kernel executable and read exec header */
- if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
- fprintf (stderr, "Unable to open kernel file %s\n", kernel_name);
- boot_exit (EXIT_FAILURE);
+#ifdef USE_BOOTP
+ if (!prefer_bootp) {
+ printf( "\nlocal kernel failed; trying remote boot\n" );
+ for( i = 0; i < n_knames; ++i ) {
+ if ((err = get_remote_kernel( kname_list[i] )) >= 0)
+ goto kernel_open;
+ if (err < -1) /* fatal error; retries don't help... */
+ break;
+ }
}
#endif
+ fprintf( stderr, "Unable to open any kernel file\n(Tried " );
+ for( i = 0; i < n_knames; ++i ) {
+ fprintf( stderr, "%s%s", kname_list[i],
+ i < n_knames-2 ? ", " :
+ i == n_knames-2 ? ", and " :
+ ")\n" );
+ }
+ boot_exit( EXIT_FAILURE );
+
+ kernel_open:
if (kread (kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec))
{
@@ -746,6 +819,19 @@ int main(int argc, char *argv[])
boot_exit (EXIT_FAILURE);
}
+#ifdef ZKERNEL
+ if (((unsigned char *)&kexec)[0] == 037 &&
+ (((unsigned char *)&kexec)[1] == 0213 ||
+ ((unsigned char *)&kexec)[1] == 0236)) {
+ /* That's a compressed kernel */
+ printf( "Kernel is compressed\n" );
+ if (load_zkernel( kfd )) {
+ printf( "Decompression error -- aborting\n" );
+ boot_exit( EXIT_FAILURE );
+ }
+ }
+#endif
+
switch (N_MAGIC(kexec)) {
case ZMAGIC:
text_offset = N_TXTOFF(kexec);
@@ -806,19 +892,11 @@ int main(int argc, char *argv[])
ramdisk_name);
boot_exit(EXIT_FAILURE);
}
- bi.ramdisk_size = (lseek(rfd, 0, SEEK_END) + 1023) / 1024;
+ bi.ramdisk.size = lseek(rfd, 0, SEEK_END);
}
else
- bi.ramdisk_size = 0;
-
- rd_size = bi.ramdisk_size << 10;
- if (mem_size - rd_size < MB && bi.num_memory > 1)
- /* If running low on ST ram load ramdisk into alternate ram. */
- bi.ramdisk_addr = (u_long) bi.memory[1].addr + bi.memory[1].size - rd_size;
- else
- /* Else hopefully there is enough ST ram. */
- bi.ramdisk_addr = (u_long)start_mem + mem_size - rd_size;
-
+ bi.ramdisk.size = 0;
+
/* calculate the total required amount of memory */
if (elf_kernel)
{
@@ -844,7 +922,24 @@ int main(int argc, char *argv[])
}
else
kernel_size = kexec.a_text + kexec.a_data + kexec.a_bss;
- memreq = kernel_size + sizeof (bi);
+
+ rd_size = bi.ramdisk.size;
+ if (rd_size + kernel_size > mem_size - MB/2 && bi.num_memory > 1)
+ /* If running low on ST ram load ramdisk into alternate ram. */
+ bi.ramdisk.addr = (u_long) bi.memory[1].addr + bi.memory[1].size - rd_size;
+ else
+ /* Else hopefully there is enough ST ram. */
+ bi.ramdisk.addr = (u_long)start_mem + mem_size - rd_size;
+
+ /* create the bootinfo structure */
+ if (!create_bootinfo())
+ boot_exit (EXIT_FAILURE);
+
+ memreq = kernel_size + bi_size;
+#ifdef BOOTINFO_COMPAT_1_0
+ if (sizeof(compat_bootinfo) > bi_size)
+ memreq = kernel_size+sizeof(compat_bootinfo);
+#endif /* BOOTINFO_COMPAT_1_0 */
/* align load address of ramdisk image, read() is sloooow on odd addr. */
memreq = ((memreq + 3) & ~3) + rd_size;
@@ -905,14 +1000,29 @@ int main(int argc, char *argv[])
kclose (kfd);
/* Check kernel's bootinfo version */
- if (!check_bootinfo_version(memptr)) {
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
+ switch (check_bootinfo_version(memptr)) {
+ case BI_VERSION_MAJOR(ATARI_BOOTI_VERSION):
+ bi_ptr = &bi_union.record;
+ break;
+
+#ifdef BOOTINFO_COMPAT_1_0
+ case BI_VERSION_MAJOR(COMPAT_ATARI_BOOTI_VERSION):
+ if (!create_compat_bootinfo()) {
+ Mfree ((void *)memptr);
+ boot_exit (EXIT_FAILURE);
+ }
+ bi_ptr = &compat_bootinfo;
+ bi_size = sizeof(compat_bootinfo);
+ break;
+#endif /* BOOTINFO_COMPAT_1_0 */
+
+ default:
+ Mfree ((void *)memptr);
+ boot_exit (EXIT_FAILURE);
}
-
+
/* copy the boot_info struct to the end of the kernel image */
- memcpy ((void *)(memptr + kernel_size),
- &bi, sizeof(bi));
+ memcpy ((void *)(memptr + kernel_size), bi_ptr, bi_size);
/* read the ramdisk image */
if (rfd != -1)
@@ -936,10 +1046,10 @@ int main(int argc, char *argv[])
/* for those who want to debug */
if (debugflag)
{
- if (bi.ramdisk_size)
- printf ("RAM disk at %#lx, size is %ldK\n",
+ if (bi.ramdisk.size)
+ printf ("RAM disk at %#lx, size is %ld\n",
(u_long)(memptr + memreq - rd_size),
- bi.ramdisk_size);
+ bi.ramdisk.size);
if (elf_kernel)
{
@@ -963,7 +1073,7 @@ int main(int argc, char *argv[])
start_mem + kernel_size);
printf ("\nKernel entry is %#lx\n",
elf_kernel ? kexec_elf.e_entry : kexec.a_entry);
- printf ("ramdisk dest top is %#lx\n", bi.ramdisk_addr + rd_size);
+ printf ("ramdisk dest top is %#lx\n", bi.ramdisk.addr + rd_size);
printf ("ramdisk lower limit is %#lx\n",
(u_long)(memptr + memreq - rd_size));
printf ("ramdisk src top is %#lx\n", (u_long)(memptr + memreq));
@@ -1013,9 +1123,8 @@ int main(int argc, char *argv[])
*/
jump_to_mover((char *) start_mem, memptr,
- (char *) bi.ramdisk_addr + rd_size, memptr + memreq,
- kernel_size + sizeof (bi),
- rd_size,
+ (char *) bi.ramdisk.addr + rd_size, memptr + memreq,
+ kernel_size + bi_size, rd_size,
(void *) 0x400);
for (;;);
@@ -1081,3 +1190,413 @@ static void get_default_args( int *argc, char ***argv )
nargv[*argc] = 0;
}
+
+ /*
+ * Create the Bootinfo Structure
+ */
+
+static int create_bootinfo(void)
+{
+ int i;
+ struct bi_record *record;
+
+ /* Initialization */
+ bi_size = 0;
+
+ /* Generic tags */
+ if (!add_bi_record(BI_MACHTYPE, sizeof(bi.machtype), &bi.machtype))
+ return(0);
+ if (!add_bi_record(BI_CPUTYPE, sizeof(bi.cputype), &bi.cputype))
+ return(0);
+ if (!add_bi_record(BI_FPUTYPE, sizeof(bi.fputype), &bi.fputype))
+ return(0);
+ if (!add_bi_record(BI_MMUTYPE, sizeof(bi.mmutype), &bi.mmutype))
+ return(0);
+ for (i = 0; i < bi.num_memory; i++)
+ if (!add_bi_record(BI_MEMCHUNK, sizeof(bi.memory[i]), &bi.memory[i]))
+ return(0);
+ if (bi.ramdisk.size)
+ if (!add_bi_record(BI_RAMDISK, sizeof(bi.ramdisk), &bi.ramdisk))
+ return(0);
+ if (!add_bi_string(BI_COMMAND_LINE, bi.command_line))
+ return(0);
+
+ /* Atari tags */
+ if (!add_bi_record(BI_ATARI_MCH_COOKIE, sizeof(bi.mch_cookie),
+ &bi.mch_cookie))
+ return(0);
+
+ /* Trailer */
+ record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
+ record->tag = BI_LAST;
+ bi_size += sizeof(bi_union.record.tag);
+
+ return(1);
+}
+
+
+ /*
+ * Add a Record to the Bootinfo Structure
+ */
+
+static int add_bi_record(u_short tag, u_short size, const void *data)
+{
+ struct bi_record *record;
+ u_short size2;
+
+ size2 = (sizeof(struct bi_record)+size+3)&-4;
+ if (bi_size+size2+sizeof(bi_union.record.tag) > MAX_BI_SIZE) {
+ fprintf (stderr, "Can't add bootinfo record. Ask a wizard to enlarge me.\n");
+ return(0);
+ }
+ record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
+ record->tag = tag;
+ record->size = size2;
+ memcpy(record->data, data, size);
+ bi_size += size2;
+ return(1);
+}
+
+
+ /*
+ * Add a String Record to the Bootinfo Structure
+ */
+
+static int add_bi_string(u_short tag, const u_char *s)
+{
+ return add_bi_record(tag, strlen(s)+1, (void *)s);
+}
+
+
+#ifdef BOOTINFO_COMPAT_1_0
+
+ /*
+ * Create the Bootinfo structure for backwards compatibility mode
+ */
+
+static int create_compat_bootinfo(void)
+{
+ u_int i;
+
+ compat_bootinfo.machtype = bi.machtype;
+ if (bi.cputype & CPU_68020)
+ compat_bootinfo.cputype = COMPAT_CPU_68020;
+ else if (bi.cputype & CPU_68030)
+ compat_bootinfo.cputype = COMPAT_CPU_68030;
+ else if (bi.cputype & CPU_68040)
+ compat_bootinfo.cputype = COMPAT_CPU_68040;
+ else if (bi.cputype & CPU_68060)
+ compat_bootinfo.cputype = COMPAT_CPU_68060;
+ else {
+ printf("CPU type 0x%08lx not supported by kernel\n", bi.cputype);
+ return(0);
+ }
+ if (bi.fputype & FPU_68881)
+ compat_bootinfo.cputype |= COMPAT_FPU_68881;
+ else if (bi.fputype & FPU_68882)
+ compat_bootinfo.cputype |= COMPAT_FPU_68882;
+ else if (bi.fputype & FPU_68040)
+ compat_bootinfo.cputype |= COMPAT_FPU_68040;
+ else if (bi.fputype & FPU_68060)
+ compat_bootinfo.cputype |= COMPAT_FPU_68060;
+ else {
+ printf("FPU type 0x%08lx not supported by kernel\n", bi.fputype);
+ return(0);
+ }
+ compat_bootinfo.num_memory = bi.num_memory;
+ if (compat_bootinfo.num_memory > COMPAT_NUM_MEMINFO) {
+ printf("Warning: using only %d blocks of memory\n",
+ COMPAT_NUM_MEMINFO);
+ compat_bootinfo.num_memory = COMPAT_NUM_MEMINFO;
+ }
+ for (i = 0; i < compat_bootinfo.num_memory; i++) {
+ compat_bootinfo.memory[i].addr = bi.memory[i].addr;
+ compat_bootinfo.memory[i].size = bi.memory[i].size;
+ }
+ if (bi.ramdisk.size) {
+ compat_bootinfo.ramdisk_size = (bi.ramdisk.size+1023)/1024;
+ compat_bootinfo.ramdisk_addr = bi.ramdisk.addr;
+ } else {
+ compat_bootinfo.ramdisk_size = 0;
+ compat_bootinfo.ramdisk_addr = 0;
+ }
+ strncpy(compat_bootinfo.command_line, bi.command_line, COMPAT_CL_SIZE);
+ compat_bootinfo.command_line[COMPAT_CL_SIZE-1] = '\0';
+
+ compat_bootinfo.bi_atari.hw_present = 0;
+ compat_bootinfo.bi_atari.mch_cookie = bi.mch_cookie;
+ return(1);
+}
+#endif /* BOOTINFO_COMPAT_1_0 */
+
+
+#ifdef ZKERNEL
+
+#define ZFILE_CHUNK_BITS 16 /* chunk is 64 KB */
+#define ZFILE_CHUNK_SIZE (1 << ZFILE_CHUNK_BITS)
+#define ZFILE_CHUNK_MASK (ZFILE_CHUNK_SIZE-1)
+#define ZFILE_N_CHUNKS (2*1024*1024/ZFILE_CHUNK_SIZE)
+
+/* variables for storing the uncompressed data */
+static char *ZFile[ZFILE_N_CHUNKS];
+static int ZFileSize = 0;
+static int ZFpos = 0;
+static int Zwpos = 0;
+
+static int Zinfd = 0; /* fd of compressed file */
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args) args
+
+#define memzero(s, n) memset ((s), 0, (n))
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+#define INBUFSIZ 4096
+#define WSIZE 0x8000 /* window size--must be a power of two, and */
+ /* at least 32K for zip's deflate method */
+
+static uch *inbuf;
+static uch *window;
+
+static unsigned insize = 0; /* valid bytes in inbuf */
+static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
+static unsigned outcnt = 0; /* bytes in output buffer */
+static int exit_code = 0;
+static long bytes_out = 0;
+
+#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+
+/* Diagnostic functions (stubbed out) */
+#define Assert(cond,msg)
+#define Trace(x)
+#define Tracev(x)
+#define Tracevv(x)
+#define Tracec(c,x)
+#define Tracecv(c,x)
+
+#define STATIC static
+
+static int fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+#include "../../../../lib/inflate.c"
+
+static void gzip_mark( void **ptr )
+{
+}
+
+static void gzip_release( void **ptr )
+{
+}
+
+
+/*
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf( void )
+{
+ if (exit_code)
+ return -1;
+
+ insize = ll_read( Zinfd, inbuf, INBUFSIZ );
+ if (insize <= 0)
+ return -1;
+
+ inptr = 1;
+ return( inbuf[0] );
+}
+
+/*
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window( void )
+{
+ ulg c = crc; /* temporary variable */
+ unsigned n;
+ uch *in, ch;
+ int chunk = Zwpos >> ZFILE_CHUNK_BITS;
+
+ if (chunk >= ZFILE_N_CHUNKS) {
+ fprintf( stderr, "compressed image too large! Aborting.\n" );
+ boot_exit( EXIT_FAILURE );
+ }
+ if (!ZFile[chunk]) {
+ if (!(ZFile[chunk] = (char *)Malloc( ZFILE_CHUNK_SIZE ))) {
+ fprintf( stderr, "Out of memory for decompresing kernel image\n" );
+ boot_exit( EXIT_FAILURE );
+ }
+ }
+ memcpy( ZFile[chunk] + (Zwpos & ZFILE_CHUNK_MASK), window, outcnt );
+ Zwpos += outcnt;
+
+#define DISPLAY_BITS 13
+ if ((Zwpos & ((1 << DISPLAY_BITS)-1)) == 0) {
+ printf( "." );
+ fflush( stdout );
+ }
+
+ in = window;
+ for (n = 0; n < outcnt; n++) {
+ ch = *in++;
+ c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+ }
+ crc = c;
+ bytes_out += (ulg)outcnt;
+ outcnt = 0;
+}
+
+static void error( char *x )
+{
+ fprintf( stderr, "\n%s", x);
+ exit_code = 1;
+}
+
+static int load_zkernel( int fd )
+{
+ int i, err;
+
+ for( i = 0; i < ZFILE_N_CHUNKS; ++i )
+ ZFile[i] = NULL;
+ Zinfd = fd;
+ ll_lseek( fd, 0, SEEK_SET );
+
+ if (!(inbuf = (uch *)Malloc( INBUFSIZ ))) {
+ fprintf( stderr, "Couldn't allocate gunzip buffer\n" );
+ boot_exit( EXIT_FAILURE );
+ }
+ if (!(window = (uch *)Malloc( WSIZE ))) {
+ fprintf( stderr, "Couldn't allocate gunzip window\n" );
+ boot_exit( EXIT_FAILURE );
+ }
+
+ printf( "Uncompressing kernel image " );
+ fflush( stdout );
+ makecrc();
+ if (!(err = gunzip()))
+ printf( "done\n" );
+ ZFileSize = Zwpos;
+ ll_close( Zinfd ); /* input file not needed anymore */
+
+ Mfree( inbuf );
+ Mfree( window );
+ return( err );
+}
+
+/* Note about the read/lseek wrapper and its memory management: It assumes
+ * that all seeks are only forward, and thus data already read or skipped can
+ * be freed. This is true for current organization of bootstrap and kernels.
+ * Little exception: The struct kexec at the start of the file. After reading
+ * it, there may be a seek back to the end of the file. But this currently
+ * doesn't hurt. Same considerations apply to the TFTP file buffers. (Roman)
+ */
+
+static int kread( int fd, void *buf, unsigned cnt )
+{
+ unsigned done = 0;
+
+ if (!ZFileSize)
+ return( ll_read( fd, buf, cnt ) );
+
+ if (ZFpos + cnt > ZFileSize)
+ cnt = ZFileSize - ZFpos;
+
+ while( cnt > 0 ) {
+ unsigned chunk = ZFpos >> ZFILE_CHUNK_BITS;
+ unsigned endchunk = (chunk+1) << ZFILE_CHUNK_BITS;
+ unsigned n = cnt;
+
+ if (ZFpos + n > endchunk)
+ n = endchunk - ZFpos;
+ memcpy( buf, ZFile[chunk] + (ZFpos & ZFILE_CHUNK_MASK), n );
+ cnt -= n;
+ buf += n;
+ done += n;
+ ZFpos += n;
+
+ if (ZFpos == endchunk) {
+ Mfree( ZFile[chunk] );
+ ZFile[chunk] = NULL;
+ }
+ }
+
+ return( done );
+}
+
+
+static int klseek( int fd, int where, int whence )
+{
+ unsigned oldpos, oldchunk, newchunk;
+
+ if (!ZFileSize)
+ return( ll_lseek( fd, where, whence ) );
+
+ oldpos = ZFpos;
+ switch( whence ) {
+ case SEEK_SET:
+ ZFpos = where;
+ break;
+ case SEEK_CUR:
+ ZFpos += where;
+ break;
+ case SEEK_END:
+ ZFpos = ZFileSize + where;
+ break;
+ default:
+ return( -1 );
+ }
+ if (ZFpos < 0) {
+ ZFpos = 0;
+ return( -1 );
+ }
+ else if (ZFpos > ZFileSize) {
+ ZFpos = ZFileSize;
+ return( -1 );
+ }
+
+ /* free memory of skipped-over data */
+ oldchunk = oldpos >> ZFILE_CHUNK_BITS;
+ newchunk = ZFpos >> ZFILE_CHUNK_BITS;
+ while( oldchunk < newchunk ) {
+ if (ZFile[oldchunk]) {
+ Mfree( ZFile[oldchunk] );
+ ZFile[oldchunk] = NULL;
+ }
+ ++oldchunk;
+ }
+
+ return( ZFpos );
+}
+
+
+static void free_zfile( void )
+{
+ int i;
+
+ for( i = 0; i < ZFILE_N_CHUNKS; ++i )
+ if (ZFile[i]) Mfree( ZFile[i] );
+}
+
+static int kclose( int fd )
+{
+ if (ZFileSize) {
+ free_zfile();
+ return( 0 );
+ }
+ else
+ return( ll_close( fd ) );
+}
+
+
+
+#endif /* ZKERNEL */
diff --git a/arch/m68k/boot/atari/bootstrap.h b/arch/m68k/boot/atari/bootstrap.h
index 5f8644f44..594916dfe 100644
--- a/arch/m68k/boot/atari/bootstrap.h
+++ b/arch/m68k/boot/atari/bootstrap.h
@@ -4,7 +4,11 @@
** Copyright 1993 by Arjan Knor
**
** Modified by Andreas Schwab
-** - clear transparent translation registers
+** - clear transparent translation registers
+** Modified 18-Aug-96 by Geert Uytterhoeven
+** - Updated for the new boot information structure (untested!)
+** Modified 1996-11-12 by Andreas Schwab
+** - Fixed and tested previous change
**
** 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
@@ -15,6 +19,26 @@
#ifndef BOOTSTRAP_H
#define BOOTSTRAP_H
+ /*
+ * Atari Bootinfo Definitions
+ *
+ * All limits herein are `soft' limits, i.e. they don't put constraints
+ * on the actual parameters in the kernel.
+ */
+
+struct atari_bootinfo {
+ unsigned long machtype; /* machine type */
+ unsigned long cputype; /* system CPU */
+ unsigned long fputype; /* system FPU */
+ unsigned long mmutype; /* system MMU */
+ int num_memory; /* # of memory blocks found */
+ struct mem_info memory[NUM_MEMINFO]; /* memory description */
+ struct mem_info ramdisk; /* ramdisk description */
+ char command_line[CL_SIZE]; /* kernel command line parameters */
+ unsigned long mch_cookie; /* _MCH cookie from TOS */
+};
+
+
/* _MCH cookie values */
#define MACH_ST 0
#define MACH_STE 1
@@ -74,7 +98,7 @@ static __inline void disable_interrupts (void)
__asm__ volatile ("orw #0x700,sr":);
}
-extern struct bootinfo bi;
+extern struct atari_bootinfo bi;
static __inline void disable_cache (void)
{
__asm__ volatile ("movec %0,cacr" :: "d" (0));
diff --git a/arch/m68k/config.in b/arch/m68k/config.in
index a42e6557b..df6a45a9d 100644
--- a/arch/m68k/config.in
+++ b/arch/m68k/config.in
@@ -49,15 +49,18 @@ comment 'General setup'
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
+bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
-bool 'Compile kernel as ELF - if your GCC is ELF-GCC' CONFIG_KERNEL_ELF
if [ "$CONFIG_AMIGA" = "y" ]; then
bool 'Amiga AutoConfig Identification' CONFIG_ZORRO
bool 'Amiga OCS chipset support' CONFIG_AMIFB_OCS
bool 'Amiga ECS chipset support' CONFIG_AMIFB_ECS
bool 'Amiga AGA chipset support' CONFIG_AMIFB_AGA
bool 'Amiga Cybervision support' CONFIG_FB_CYBER
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool 'Amiga RetinaZ3 support' CONFIG_FB_RETINAZ3
+ fi
# bool 'Amiga GSP (TMS340x0) support' CONFIG_AMIGA_GSP
# if [ "$CONFIG_AMIGA_GSP" = "y" ]; then
# bool 'DMI Resolver support' CONFIG_GSP_RESOLVER
@@ -79,17 +82,18 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
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
fi
if [ "$CONFIG_AMIGA" = "y" ]; then
-tristate 'Amiga Zorro II ramdisk support' CONFIG_AMIGA_Z2RAM
+ 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
-fi
+ 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
+ fi
fi
comment 'Additional Block Devices'
@@ -122,6 +126,9 @@ comment 'SCSI support type (disk, tape, CD-ROM)'
dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
dep_tristate 'SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
+ bool ' Enable vendor-specific extentions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+fi
dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
@@ -134,17 +141,23 @@ mainmenu_option next_comment
comment 'SCSI low-level drivers'
if [ "$CONFIG_AMIGA" = "y" ]; then
-tristate 'A3000 WD33C93A support' CONFIG_A3000_SCSI
-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 'Blizzard 2060 SCSI support' CONFIG_BLZ2060_SCSI
-bool 'Blizzard 1230IV/1260 SCSI support' CONFIG_BLZ1230_SCSI
+ tristate 'A3000 WD33C93A support' CONFIG_A3000_SCSI
+ 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 '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
+ 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
+ dep_tristate 'Atari native SCSI support' CONFIG_ATARI_SCSI $CONFIG_SCSI
+ bool 'Long delays for Toshiba CD-ROMs' CONFIG_ATARI_SCSI_TOSHIBA_DELAY
fi
#dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
endmenu
@@ -196,6 +209,10 @@ source fs/Config.in
mainmenu_option next_comment
comment 'Character devices'
+define_bool CONFIG_VT y
+define_bool CONFIG_VT_CONSOLE y
+define_bool CONFIG_FB_CONSOLE y
+
tristate 'Parallel printer support' CONFIG_PRINTER
if [ "$CONFIG_AMIGA" = "y" ]; then
dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_PRINTER
@@ -207,13 +224,26 @@ fi
if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'Atari MFP serial support' CONFIG_ATARI_MFPSER
tristate 'Atari SCC serial support' CONFIG_ATARI_SCC
+ if [ "$CONFIG_ATARI_SCC" = "y" -o "$CONFIG_ATARI_SCC" = "m" ]; then
+ bool 'Atari SCC serial DMA support' CONFIG_ATARI_SCC_DMA
+ fi
tristate 'Atari MIDI serial support' CONFIG_ATARI_MIDI
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Atari DSP56k support (EXPERIMENTAL)' CONFIG_ATARI_DSP56K
+ fi
fi
if [ "$CONFIG_AMIGA" = "y" ]; then
tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL
- bool 'GVP IO-Extender support' CONFIG_GVPIOEXT
+ 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
+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
+ bool 'Serial console support' CONFIG_SERIAL_CONSOLE
+fi
bool 'Support for user serial device modules' CONFIG_USERIAL
bool 'Watchdog Timer Support' CONFIG_WATCHDOG
if [ "$CONFIG_WATCHDOG" != "n" ]; then
@@ -221,6 +251,9 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then
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
+fi
endmenu
mainmenu_option next_comment
@@ -240,4 +273,5 @@ bool 'Kernel profiling support' CONFIG_PROFILE
if [ "$CONFIG_PROFILE" = "y" ]; then
int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
fi
+bool 'Remote debugging support' CONFIG_KGDB
endmenu
diff --git a/arch/m68k/console/fbcon.c b/arch/m68k/console/fbcon.c
index ecb926f88..376249c90 100644
--- a/arch/m68k/console/fbcon.c
+++ b/arch/m68k/console/fbcon.c
@@ -61,7 +61,7 @@
#endif
#ifdef CONFIG_FB_CYBER
#include "../amiga/s3blit.h"
-#endif /* CONFIG_FB_CYBER */
+#endif
#include <linux/fb.h>
#include <asm/font.h>
#include <asm/machdep.h>
@@ -70,7 +70,7 @@
#include <asm/uaccess.h>
#include "../../../drivers/char/vt_kern.h" /* vt_cons and vc_resize_con() */
-
+#include "../../../drivers/char/console_struct.h"
/* Import console_blanked from console.c */
@@ -95,6 +95,7 @@ extern int console_blanked;
#undef CONFIG_FBCON_24PACKED
#undef CONFIG_FBCON_32PACKED
#undef CONFIG_FBCON_CYBER
+#undef CONFIG_FBCON_RETINAZ3
/* Monochrome is default */
@@ -117,7 +118,18 @@ extern int console_blanked;
#ifndef CONFIG_FBCON_CYBER
#define CONFIG_FBCON_CYBER
#endif
-#endif /* CONFIG_FB_CYBER */
+#endif
+
+/* RetinaZ3 Graphics Board */
+
+#ifdef CONFIG_FB_RETINAZ3
+#ifndef CONFIG_FBCON_RETINAZ3
+#define CONFIG_FBCON_RETINAZ3
+#endif
+#ifndef CONFIG_FBCON_8PACKED
+#define CONFIG_FBCON_8PACKED
+#endif
+#endif
#endif /* CONFIG_AMIGA */
@@ -151,17 +163,17 @@ extern int console_blanked;
#undef CONFIG_FBCON_IPLAN2
#endif
-#if defined(CONFIG_FBCON_CYBER) || defined(CONFIG_FBCON_8PACKED) || \
- defined(CONFIG_FBCON_16PACKED) || defined(CONFIG_FBCON_24PACKED) || \
- defined(CONFIG_FBCON_32PACKED)
+#if defined(CONFIG_FBCON_CYBER) || defined(CONFIG_FBCON_RETINAZ3) || \
+ defined(CONFIG_FBCON_8PACKED) || defined(CONFIG_FBCON_16PACKED) || \
+ defined(CONFIG_FBCON_24PACKED) || defined(CONFIG_FBCON_32PACKED)
#define CONFIG_FBCON_PACKED
#else
#undef CONFIG_FBCON_PACKED
#endif
-struct fb_info *fb_info;
-struct display *disp;
+static struct fb_info *fb_info;
+static struct display *disp;
/* ++Geert: Sorry, no hardware cursor support at the moment;
@@ -224,21 +236,24 @@ static __inline__ int CURSOR_UNDRAWN(void)
* Interface used by the world
*/
-static u_long fbcon_startup(u_long kmem_start, char **display_desc);
+static u_long fbcon_startup(u_long kmem_start, const char **display_desc);
static void fbcon_init(struct vc_data *conp);
static int fbcon_deinit(struct vc_data *conp);
static int fbcon_changevar(int con);
static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
int width);
-static int fbcon_putc(struct vc_data *conp, int c, int y, int x);
-static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
- int x);
+static int fbcon_putc(struct vc_data *conp, int c, int yy, int xx);
+static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int yy,
+ int xx);
static int fbcon_cursor(struct vc_data *conp, int mode);
static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count);
static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
int height, int width);
static int fbcon_switch(struct vc_data *conp);
static int fbcon_blank(int blank);
+static int fbcon_get_font(struct vc_data *conp, int *w, int *h, char *data);
+static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data);
+static int fbcon_set_palette(struct vc_data *conp, unsigned char *table);
/*
@@ -264,14 +279,22 @@ static __inline__ void memset_even_8p(void *d, size_t count, u_long val1,
u_long val2, u_long val3, u_long val4);
static __inline__ void memmove_8p_col(void *d, void *s, int h, int bpr);
static __inline__ void expand8dl(u_char c, u_long *ret1, u_long *ret2);
-static __inline__ void memclear_2p_col(void *d, size_t h, u_short val, int bpr);
+static __inline__ void memclear_2p_col(void *d, size_t h, u_short val,
+ int bpr);
static __inline__ void memset_even_2p(void *d, size_t count, u_long val);
static __inline__ void memmove_2p_col(void *d, void *s, int h, int bpr);
static __inline__ u_short expand2w(u_char c);
static __inline__ u_long expand2l(u_char c);
static __inline__ u_short dup2w(u_char c);
-static __inline__ int real_y(struct display *p, int y);
+static __inline__ int real_y(struct display *p, int yy);
static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp);
+static __inline__ void updatescrollmode(struct display *p);
+static __inline__ void ywrap_up(int unit, struct display *p, int count);
+static __inline__ void ywrap_down(int unit, struct display *p, int count);
+static __inline__ void ypan_up(int unit, struct vc_data *conp,
+ struct display *p, int count);
+static __inline__ void ypan_down(int unit, struct vc_data *conp,
+ struct display *p, int count);
static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,
int height, int width, u_int y_break);
@@ -285,11 +308,11 @@ static void bmove_mono(struct display *p, int sy, int sx, int dy, int dx,
int height, int width);
static void clear_mono(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width);
-static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
- int x);
+static void putc_mono(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx);
static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
- int count, int y, int x);
-static void rev_char_mono(struct display *p, int x, int y);
+ int count, int yy, int xx);
+static void rev_char_mono(struct display *p, int xx, int yy);
#endif /* CONFIG_FBCON_MONO */
@@ -302,11 +325,11 @@ static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx,
int height, int width);
static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width);
-static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
- int x);
+static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx);
static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
- int count, int y, int x);
-static void rev_char_ilbm(struct display *p, int x, int y);
+ int count, int yy, int xx);
+static void rev_char_ilbm(struct display *p, int xx, int yy);
#endif /* CONFIG_FBCON_ILBM */
@@ -319,11 +342,11 @@ static void bmove_plan(struct display *p, int sy, int sx, int dy, int dx,
int height, int width);
static void clear_plan(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width);
-static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
- int x);
+static void putc_plan(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx);
static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
- int count, int y, int x);
-static void rev_char_plan(struct display *p, int x, int y);
+ int count, int yy, int xx);
+static void rev_char_plan(struct display *p, int xx, int yy);
#endif /* CONFIG_FBCON_PLANES */
@@ -336,11 +359,11 @@ static void bmove_2_plane(struct display *p, int sy, int sx, int dy, int dx,
int height, int width);
static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width);
-static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
- int x);
+static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx);
static void putcs_2_plane(struct vc_data *conp, struct display *p,
- const char *s, int count, int y, int x);
-static void rev_char_2_plane(struct display *display, int x, int y);
+ const char *s, int count, int yy, int xx);
+static void rev_char_2_plane(struct display *display, int xx, int yy);
#endif /* CONFIG_FBCON_2PLANE */
@@ -353,11 +376,11 @@ static void bmove_4_plane(struct display *p, int sy, int sx, int dy, int dx,
int height, int width);
static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width);
-static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
- int x);
+static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx);
static void putcs_4_plane(struct vc_data *conp, struct display *p,
- const char *s, int count, int y, int x);
-static void rev_char_4_plane(struct display *p, int x, int y);
+ const char *s, int count, int yy, int xx);
+static void rev_char_4_plane(struct display *p, int xx, int yy);
#endif /* CONFIG_FBCON_4PLANE */
@@ -370,11 +393,11 @@ static void bmove_8_plane(struct display *p, int sy, int sx, int dy, int dx,
int height, int width);
static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width);
-static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
- int x);
+static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx);
static void putcs_8_plane(struct vc_data *conp, struct display *p,
- const char *s, int count, int y, int x);
-static void rev_char_8_plane(struct display *display, int x, int y);
+ const char *s, int count, int yy, int xx);
+static void rev_char_8_plane(struct display *display, int xx, int yy);
#endif /* CONFIG_FBCON_8PLANE */
@@ -387,11 +410,11 @@ static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
int height, int width);
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width);
-static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
- int x);
+static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx);
static void putcs_8_packed(struct vc_data *conp, struct display *p,
- const char *s, int count, int y, int x);
-static void rev_char_8_packed(struct display *p, int x, int y);
+ const char *s, int count, int yy, int xx);
+static void rev_char_8_packed(struct display *p, int xx, int yy);
#endif /* CONFIG_FBCON_8PACKED */
@@ -405,10 +428,10 @@ static void bmove_16_packed(struct display *p, int sy, int sx, int dy, int dx,
static void clear_16_packed(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width);
static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
- int y, int x);
+ int yy, int xx);
static void putcs_16_packed(struct vc_data *conp, struct display *p,
- const char *s, int count, int y, int x);
-static void rev_char_16_packed(struct display *p, int x, int y);
+ const char *s, int count, int yy, int xx);
+static void rev_char_16_packed(struct display *p, int xx, int yy);
#endif */ CONFIG_FBCON_8PACKED */
@@ -421,22 +444,38 @@ static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx,
int height, int width);
static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width);
-static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
- int x);
+static void putc_cyber(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx);
static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
- int count, int y, int x);
-static void rev_char_cyber(struct display *p, int x, int y);
+ int count, int yy, int xx);
+static void rev_char_cyber(struct display *p, int xx, int yy);
extern void Cyber_WaitQueue(u_short fifo);
extern void Cyber_WaitBlit(void);
extern void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
u_short desty, u_short width, u_short height,
u_short mode);
-extern void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
+extern void Cyber_RectFill(u_short xx, u_short yy, u_short width, u_short height,
u_short mode, u_short color);
-extern void Cyber_MoveCursor(u_short x, u_short y);
+extern void Cyber_MoveCursor(u_short xx, u_short yy);
#endif /* CONFIG_FBCON_CYBER */
+#ifdef CONFIG_FBCON_RETINAZ3
+static void clear_retz3(struct vc_data *conp, struct display *p, int
+ sy, int sx, int height, int width);
+static void bmove_retz3(struct display *p, int sy, int sx, int dy, int dx,
+ int height, int width);
+extern void retz3_bitblt(struct fb_var_screeninfo *scr,
+ unsigned short srcx, unsigned short srcy, unsigned
+ short destx, unsigned short desty, unsigned short
+ width, unsigned short height, unsigned short cmd,
+ unsigned short mask);
+static void putc_retz3(struct vc_data *conp, struct display *p, int c,
+ int yy, int xx);
+static void putcs_retz3(struct vc_data *conp, struct display *p, const
+ char *s, int count, int yy, int xx);
+static void rev_char_retz3(struct display *p, int xx, int yy);
+#endif
/*
* `switch' for the Low Level Operations
@@ -447,70 +486,77 @@ struct display_switch {
int width);
void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width);
- void (*putc)(struct vc_data *conp, struct display *p, int c, int y, int x);
+ void (*putc)(struct vc_data *conp, struct display *p, int c, int yy, int xx);
void (*putcs)(struct vc_data *conp, struct display *p, const char *s,
- int count, int y, int x);
- void (*rev_char)(struct display *p, int x, int y);
+ int count, int yy, int xx);
+ void (*rev_char)(struct display *p, int xx, int yy);
};
#ifdef CONFIG_FBCON_MONO
-struct display_switch dispsw_mono = {
+static struct display_switch dispsw_mono = {
bmove_mono, clear_mono, putc_mono, putcs_mono, rev_char_mono
};
#endif /* CONFIG_FBCON_MONO */
#ifdef CONFIG_FBCON_ILBM
-struct display_switch dispsw_ilbm = {
+static struct display_switch dispsw_ilbm = {
bmove_ilbm, clear_ilbm, putc_ilbm, putcs_ilbm, rev_char_ilbm
};
#endif /* CONFIG_FBCON_ILBM */
#ifdef CONFIG_FBCON_PLANES
-struct display_switch dispsw_plan = {
+static struct display_switch dispsw_plan = {
bmove_plan, clear_plan, putc_plan, putcs_plan, rev_char_plan
};
#endif /* CONFIG_FBCON_PLANES */
#ifdef CONFIG_FBCON_2PLANE
-struct display_switch dispsw_2_plane = {
+static struct display_switch dispsw_2_plane = {
bmove_2_plane, clear_2_plane, putc_2_plane, putcs_2_plane, rev_char_2_plane
};
#endif /* CONFIG_FBCON_2PLANE */
#ifdef CONFIG_FBCON_4PLANE
-struct display_switch dispsw_4_plane = {
+static struct display_switch dispsw_4_plane = {
bmove_4_plane, clear_4_plane, putc_4_plane, putcs_4_plane, rev_char_4_plane
};
#endif /* CONFIG_FBCON_4PLANE */
#ifdef CONFIG_FBCON_8PLANE
-struct display_switch dispsw_8_plane = {
+static struct display_switch dispsw_8_plane = {
bmove_8_plane, clear_8_plane, putc_8_plane, putcs_8_plane, rev_char_8_plane
};
#endif /* CONFIG_FBCON_8PLANE */
#ifdef CONFIG_FBCON_8PACKED
-struct display_switch dispsw_8_packed = {
+static struct display_switch dispsw_8_packed = {
bmove_8_packed, clear_8_packed, putc_8_packed, putcs_8_packed, rev_char_8_packed
};
#endif /* CONFIG_FBCON_8PACKED */
#ifdef CONFIG_FBCON_16PACKED
-struct display_switch dispsw_16_packed = {
+static struct display_switch dispsw_16_packed = {
bmove_16_packed, clear_16_packed, putc_16_packed, putcs_16_packed,
rev_char_16_packed
};
#endif /* CONFIG_FBCON_16PACKED */
#ifdef CONFIG_FBCON_CYBER
-struct display_switch dispsw_cyber = {
+static struct display_switch dispsw_cyber = {
bmove_cyber, clear_cyber, putc_cyber, putcs_cyber, rev_char_cyber
};
#endif /* CONFIG_FBCON_CYBER */
+#ifdef CONFIG_FBCON_RETINAZ3
+static struct display_switch dispsw_retz3 = {
+ bmove_retz3, clear_retz3, putc_retz3,
+ putcs_retz3, rev_char_retz3
+};
+#endif
+
-static u_long fbcon_startup(u_long kmem_start, char **display_desc)
+static u_long fbcon_startup(u_long kmem_start, const char **display_desc)
{
int irqres = 0;
@@ -566,6 +612,19 @@ static int fbcon_changevar(int con)
}
+static __inline__ void updatescrollmode(struct display *p)
+{
+ if (divides(p->ywrapstep, p->fontheight) &&
+ divides(p->fontheight, p->var.yres_virtual))
+ p->scrollmode = SCROLL_YWRAP;
+ else if (divides(p->ypanstep, p->fontheight) &&
+ p->var.yres_virtual >= p->var.yres+p->fontheight)
+ p->scrollmode = SCROLL_YPAN;
+ else
+ p->scrollmode = SCROLL_YMOVE;
+}
+
+
static void fbcon_setup(int con, int setcol, int init)
{
struct display *p = &disp[con];
@@ -579,16 +638,12 @@ static void fbcon_setup(int con, int setcol, int init)
&p->fontdata) || p->fontwidth != 8)
getdefaultfont(p->var.xres, p->var.yres, NULL, &p->fontwidth,
&p->fontheight, &p->fontdata);
- if (p->fontwidth != 8)
- panic("fbcon_setup: No support for fontwidth != 8");
-
- if (divides(p->ywrapstep, p->fontheight) && divides(p->fontheight, p->var.yres_virtual))
- p->scrollmode = SCROLL_YWRAP;
- else if (divides(p->ypanstep, p->fontheight) &&
- p->var.yres_virtual >= p->var.yres+p->fontheight)
- p->scrollmode = SCROLL_YPAN;
- else
- p->scrollmode = SCROLL_YMOVE;
+ if (p->fontwidth != 8) {
+ /* ++Geert: changed from panic() to `correct and continue' */
+ printk("fbcon_setup: No support for fontwidth != 8");
+ p->fontwidth = 8;
+ }
+ updatescrollmode(p);
nr_cols = p->var.xres/p->fontwidth;
nr_rows = p->var.yres/p->fontheight;
@@ -638,7 +693,8 @@ static void fbcon_setup(int con, int setcol, int init)
if (p->type == FB_TYPE_INTERLEAVED_PLANES && p->type_aux != 2) {
if (p->line_length) {
p->next_line = p->line_length*p->var.bits_per_pixel;
- p->next_plane = p->line_length;
+ p->next_plane = p->line_length
+;
} else {
p->next_line = p->type_aux;
p->next_plane = p->type_aux/p->var.bits_per_pixel;
@@ -658,13 +714,18 @@ static void fbcon_setup(int con, int setcol, int init)
#endif /* CONFIG_FBCON_PLANES */
#ifdef CONFIG_FBCON_PACKED
if (p->type == FB_TYPE_PACKED_PIXELS) {
- p->next_line = p->var.xres_virtual*p->var.bits_per_pixel>>3;
+ p->next_line = (p->var.xres_virtual*p->var.bits_per_pixel)>>3;
p->next_plane = 0;
#ifdef CONFIG_FBCON_CYBER
if (p->var.accel == FB_ACCEL_CYBERVISION)
p->dispsw = &dispsw_cyber;
else
-#endif /* CONFIG_FBCON_CYBER */
+#endif
+#ifdef CONFIG_FBCON_RETINAZ3
+ if (p->var.accel == FB_ACCEL_RETINAZ3)
+ p->dispsw = &dispsw_retz3;
+ else
+#endif
#ifdef CONFIG_FBCON_8PACKED
if (p->var.bits_per_pixel == 8)
p->dispsw = &dispsw_8_packed;
@@ -1399,12 +1460,12 @@ static __inline__ u_short dup2w(u_char c)
* restriction is simplicity & efficiency at the moment.
*/
-static __inline__ int real_y(struct display *p, int y)
+static __inline__ int real_y(struct display *p, int yy)
{
int rows = p->vrows;
- y += p->yscroll;
- return(y < rows ? y : y-rows);
+ yy += p->yscroll;
+ return(yy < rows ? yy : yy-rows);
}
@@ -1436,7 +1497,7 @@ static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
}
-static int fbcon_putc(struct vc_data *conp, int c, int y, int x)
+static int fbcon_putc(struct vc_data *conp, int c, int yy, int xx)
{
int unit = conp->vc_num;
struct display *p = &disp[unit];
@@ -1444,17 +1505,17 @@ static int fbcon_putc(struct vc_data *conp, int c, int y, int x)
if (!p->can_soft_blank && console_blanked)
return(0);
- if ((p->cursor_x == x) && (p->cursor_y == y))
+ if ((p->cursor_x == xx) && (p->cursor_y == yy))
CURSOR_UNDRAWN();
- p->dispsw->putc(conp, p, c, real_y(p, y), x);
+ p->dispsw->putc(conp, p, c, real_y(p, yy), xx);
return(0);
}
-static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
- int x)
+static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int yy,
+ int xx)
{
int unit = conp->vc_num;
struct display *p = &disp[unit];
@@ -1462,10 +1523,10 @@ static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
if (!p->can_soft_blank && console_blanked)
return(0);
- if ((p->cursor_y == y) && (x <= p->cursor_x) && (p->cursor_x < x+count))
+ if ((p->cursor_y == yy) && (xx <= p->cursor_x) && (p->cursor_x < xx+count))
CURSOR_UNDRAWN();
- p->dispsw->putcs(conp, p, s, count, real_y(p, y), x);
+ p->dispsw->putcs(conp, p, s, count, real_y(p, yy), xx);
return(0);
}
@@ -1520,6 +1581,62 @@ static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp)
}
+static __inline__ void ywrap_up(int unit, struct display *p, int count)
+{
+ p->yscroll += count;
+ if (p->yscroll >= p->vrows) /* Deal with wrap */
+ p->yscroll -= p->vrows;
+ p->var.xoffset = 0;
+ p->var.yoffset = p->yscroll*p->fontheight;
+ p->var.vmode |= FB_VMODE_YWRAP;
+ fb_info->updatevar(unit);
+}
+
+
+static __inline__ void ywrap_down(int unit, struct display *p, int count)
+{
+ p->yscroll -= count;
+ if (p->yscroll < 0) /* Deal with wrap */
+ p->yscroll += p->vrows;
+ p->var.xoffset = 0;
+ p->var.yoffset = p->yscroll*p->fontheight;
+ p->var.vmode |= FB_VMODE_YWRAP;
+ fb_info->updatevar(unit);
+}
+
+
+static __inline__ void ypan_up(int unit, struct vc_data *conp,
+ struct display *p, int count)
+{
+ p->yscroll += count;
+ if (p->yscroll+conp->vc_rows > p->vrows) {
+ p->dispsw->bmove(p, p->yscroll, 0, 0, 0, conp->vc_rows-count,
+ conp->vc_cols);
+ p->yscroll = 0;
+ }
+ p->var.xoffset = 0;
+ p->var.yoffset = p->yscroll*p->fontheight;
+ p->var.vmode &= ~FB_VMODE_YWRAP;
+ fb_info->updatevar(unit);
+}
+
+
+static __inline__ void ypan_down(int unit, struct vc_data *conp,
+ struct display *p, int count)
+{
+ p->yscroll -= count;
+ if (p->yscroll < 0) {
+ p->yscroll = p->vrows-conp->vc_rows;
+ p->dispsw->bmove(p, 0, 0, p->yscroll+count, 0, conp->vc_rows-count,
+ conp->vc_cols);
+ }
+ p->var.xoffset = 0;
+ p->var.yoffset = p->yscroll*p->fontheight;
+ p->var.vmode &= ~FB_VMODE_YWRAP;
+ fb_info->updatevar(unit);
+}
+
+
static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
{
int unit = conp->vc_num;
@@ -1536,84 +1653,98 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
switch (dir) {
case SM_UP:
- if (t == 0 && b == conp->vc_rows &&
- vt_cons[unit]->vc_mode == KD_TEXT) {
- if (count > conp->vc_rows) /* Maximum realistic size */
- count = conp->vc_rows;
- switch (p->scrollmode) {
- case SCROLL_YWRAP:
- p->yscroll += count;
- if (p->yscroll >= p->vrows) /* Deal with wrap */
- p->yscroll -= p->vrows;
- p->var.xoffset = 0;
- p->var.yoffset = p->yscroll*p->fontheight;
- p->var.vmode |= FB_VMODE_YWRAP;
- fb_info->updatevar(unit);
- break;
-
- case SCROLL_YPAN:
- p->yscroll += count;
- if (p->yscroll+conp->vc_rows > p->vrows) {
- p->dispsw->bmove(p, p->yscroll, 0, 0, 0, b-count,
- conp->vc_cols);
- p->yscroll = 0;
- }
- p->var.xoffset = 0;
- p->var.yoffset = p->yscroll*p->fontheight;
- p->var.vmode &= ~FB_VMODE_YWRAP;
- fb_info->updatevar(unit);
- break;
-
- case SCROLL_YMOVE:
- p->dispsw->bmove(p, count, 0, 0, 0, b-count, conp->vc_cols);
- break;
- }
- } else
- fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols);
- fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+ if (count > conp->vc_rows) /* Maximum realistic size */
+ count = conp->vc_rows;
+ if (vt_cons[unit]->vc_mode == KD_TEXT)
+ switch (p->scrollmode) {
+ case SCROLL_YWRAP:
+ if (b-t-count > 3*conp->vc_rows>>2) {
+ if (t > 0)
+ fbcon_bmove(conp, 0, 0, count, 0, t, conp->vc_cols);
+ ywrap_up(unit, p, count);
+ if (conp->vc_rows-b > 0)
+ fbcon_bmove(conp, b-count, 0, b, 0, conp->vc_rows-b,
+ conp->vc_cols);
+ } else
+ fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
+ conp->vc_cols);
+ fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+ break;
+
+ case SCROLL_YPAN:
+ if (b-t-count > 3*conp->vc_rows>>2) {
+ if (t > 0)
+ fbcon_bmove(conp, 0, 0, count, 0, t, conp->vc_cols);
+ ypan_up(unit, conp, p, count);
+ if (conp->vc_rows-b > 0)
+ fbcon_bmove(conp, b-count, 0, b, 0, conp->vc_rows-b,
+ conp->vc_cols);
+ } else
+ fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
+ conp->vc_cols);
+ fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+ break;
+
+ case SCROLL_YMOVE:
+ p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
+ conp->vc_cols);
+ p->dispsw->clear(conp, p, b-count, 0, count, conp->vc_cols);
+ break;
+ }
+ else {
+ fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols);
+ fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+ }
break;
case SM_DOWN:
- if (t == 0 && b == conp->vc_rows &&
- vt_cons[unit]->vc_mode == KD_TEXT) {
- if (count > conp->vc_rows) /* Maximum realistic size */
- count = conp->vc_rows;
- switch (p->scrollmode) {
- case SCROLL_YWRAP:
- p->yscroll -= count;
- if (p->yscroll < 0) /* Deal with wrap */
- p->yscroll += p->vrows;
- p->var.xoffset = 0;
- p->var.yoffset = p->yscroll*p->fontheight;
- p->var.vmode |= FB_VMODE_YWRAP;
- fb_info->updatevar(unit);
- break;
-
- case SCROLL_YPAN:
- p->yscroll -= count;
- if (p->yscroll < 0) {
- p->yscroll = p->vrows-conp->vc_rows;
- p->dispsw->bmove(p, 0, 0, p->yscroll+count, 0, b-count,
- conp->vc_cols);
- }
- p->var.xoffset = 0;
- p->var.yoffset = p->yscroll*p->fontheight;
- p->var.vmode &= ~FB_VMODE_YWRAP;
- fb_info->updatevar(unit);
- break;
-
- case SCROLL_YMOVE:
- p->dispsw->bmove(p, 0, 0, count, 0, b-count, conp->vc_cols);
- break;
- }
- } else
- fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols);
-
- /* Fixed bmove() should end Arno's frustration with copying?
- * Confucius says:
- * Man who copies in wrong direction, end up with trashed data
- */
- fbcon_clear(conp, t, 0, count, conp->vc_cols);
+ if (count > conp->vc_rows) /* Maximum realistic size */
+ count = conp->vc_rows;
+ if (vt_cons[unit]->vc_mode == KD_TEXT)
+ switch (p->scrollmode) {
+ case SCROLL_YWRAP:
+ if (b-t-count > 3*conp->vc_rows>>2) {
+ if (conp->vc_rows-b > 0)
+ fbcon_bmove(conp, b, 0, b-count, 0, conp->vc_rows-b,
+ conp->vc_cols);
+ ywrap_down(unit, p, count);
+ if (t > 0)
+ fbcon_bmove(conp, count, 0, 0, 0, t, conp->vc_cols);
+ } else
+ fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
+ conp->vc_cols);
+ fbcon_clear(conp, t, 0, count, conp->vc_cols);
+ break;
+
+ case SCROLL_YPAN:
+ if (b-t-count > 3*conp->vc_rows>>2) {
+ if (conp->vc_rows-b > 0)
+ fbcon_bmove(conp, b, 0, b-count, 0, conp->vc_rows-b,
+ conp->vc_cols);
+ ypan_down(unit, conp, p, count);
+ if (t > 0)
+ fbcon_bmove(conp, count, 0, 0, 0, t, conp->vc_cols);
+ } else
+ fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
+ conp->vc_cols);
+ fbcon_clear(conp, t, 0, count, conp->vc_cols);
+ break;
+
+ case SCROLL_YMOVE:
+ p->dispsw->bmove(p, t, 0, t+count, 0, b-t-count,
+ conp->vc_cols);
+ p->dispsw->clear(conp, p, t, 0, count, conp->vc_cols);
+ break;
+ }
+ else {
+ /*
+ * Fixed bmove() should end Arno's frustration with copying?
+ * Confucius says:
+ * Man who copies in wrong direction, end up with trashed data
+ */
+ fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols);
+ fbcon_clear(conp, t, 0, count, conp->vc_cols);
+ }
break;
case SM_LEFT:
@@ -1832,14 +1963,7 @@ static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data)
/* Adjust the virtual screen-size to fontheight*rows */
p->var.yres_virtual = (p->var.yres/h)*h;
p->vrows = p->var.yres_virtual/h;
- if (divides(p->ywrapstep, p->fontheight))
- p->scrollmode = SCROLL_YWRAP;
- else if (divides(p->ypanstep, p->fontheight) &&
- p->var.yres_virtual >= p->var.yres+p->fontheight)
- p->scrollmode = SCROLL_YPAN;
- else
- p->scrollmode = SCROLL_YMOVE;
-
+ updatescrollmode(p);
vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
}
else if (unit == fg_console)
@@ -1854,6 +1978,38 @@ static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data)
return( 0 );
}
+static unsigned short palette_red[16];
+static unsigned short palette_green[16];
+static unsigned short palette_blue[16];
+
+static struct fb_cmap palette_cmap = {
+ 0, 16, palette_red, palette_green, palette_blue, NULL
+};
+
+static int fbcon_set_palette(struct vc_data *conp, unsigned char *table)
+{
+ int unit = conp->vc_num;
+ struct display *p = &disp[unit];
+ int i, j, k;
+ u_char val;
+
+ if (!conp->vc_can_do_color || (!p->can_soft_blank && console_blanked))
+ return(-EINVAL);
+ for (i = j = 0; i < 16; i++) {
+ k = table[i];
+ val = conp->vc_palette[j++];
+ palette_red[k] = (val<<8)|val;
+ val = conp->vc_palette[j++];
+ palette_green[k] = (val<<8)|val;
+ val = conp->vc_palette[j++];
+ palette_blue[k] = (val<<8)|val;
+ }
+ palette_cmap.len = 1<<p->var.bits_per_pixel;
+ if (palette_cmap.len > 16)
+ palette_cmap.len = 16;
+ return(fb_info->setcmap(&palette_cmap, unit));
+}
+
/* ====================================================================== */
@@ -1882,8 +2038,8 @@ static void bmove_mono(struct display *p, int sy, int sx, int dy, int dx,
u_char *src, *dest;
u_int rows;
- if (sx == 0 && sy == 0 && width == p->next_line) {
- src = p->screen_base;
+ if (sx == 0 && dx == 0 && width == p->next_line) {
+ src = p->screen_base+sy*p->fontheight*width;
dest = p->screen_base+dy*p->fontheight*width;
mymemmove(dest, src, height*p->fontheight*width);
} else if (dy <= sy) {
@@ -1928,28 +2084,28 @@ static void clear_mono(struct vc_data *conp, struct display *p, int sy, int sx,
}
-static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
- int x)
+static void putc_mono(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx)
{
u_char *dest, *cdat;
- u_int rows, bold, reverse, underline;
+ u_int rows, bold, revs, underl;
u_char d;
c &= 0xff;
- dest = p->screen_base+y*p->fontheight*p->next_line+x;
+ dest = p->screen_base + yy*p->fontheight*p->next_line + xx;
cdat = p->fontdata+c*p->fontheight;
bold = attr_bold(p,conp);
- reverse = attr_reverse(p,conp);
- underline = attr_underline(p,conp);
+ revs = attr_reverse(p,conp);
+ underl = attr_underline(p,conp);
for (rows = p->fontheight; rows--; dest += p->next_line) {
d = *cdat++;
- if (underline && !rows)
+ if (underl && !rows)
d = 0xff;
else if (bold)
d |= d>>1;
- if (reverse)
+ if (revs)
d = ~d;
*dest = d;
}
@@ -1957,16 +2113,16 @@ static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
- int count, int y, int x)
+ int count, int yy, int xx)
{
u_char *dest, *dest0, *cdat;
- u_int rows, bold, reverse, underline;
+ u_int rows, bold, revs, underl;
u_char c, d;
- dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+ dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
bold = attr_bold(p,conp);
- reverse = attr_reverse(p,conp);
- underline = attr_underline(p,conp);
+ revs = attr_reverse(p,conp);
+ underl = attr_underline(p,conp);
while (count--) {
c = *s++;
@@ -1974,11 +2130,11 @@ static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
cdat = p->fontdata+c*p->fontheight;
for (rows = p->fontheight; rows--; dest += p->next_line) {
d = *cdat++;
- if (underline && !rows)
+ if (underl && !rows)
d = 0xff;
else if (bold)
d |= d>>1;
- if (reverse)
+ if (revs)
d = ~d;
*dest = d;
}
@@ -1986,12 +2142,12 @@ static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
}
-static void rev_char_mono(struct display *p, int x, int y)
+static void rev_char_mono(struct display *p, int xx, int yy)
{
u_char *dest;
u_int rows;
- dest = p->screen_base+y*p->fontheight*p->next_line+x;
+ dest = p->screen_base + yy*p->fontheight*p->next_line + xx;
for (rows = p->fontheight; rows--; dest += p->next_line)
*dest = ~*dest;
}
@@ -2017,8 +2173,9 @@ static void rev_char_mono(struct display *p, int x, int y)
static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
- if (sx == 0 && sy == 0 && width == p->next_plane)
- mymemmove(p->screen_base+dy*p->fontheight*p->next_line, p->screen_base,
+ if (sx == 0 && dx == 0 && width == p->next_plane)
+ mymemmove(p->screen_base+dy*p->fontheight*p->next_line,
+ p->screen_base+sy*p->fontheight*p->next_line,
height*p->fontheight*p->next_line);
else {
u_char *src, *dest;
@@ -2068,8 +2225,8 @@ static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx,
}
-static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
- int x)
+static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx)
{
u_char *dest, *cdat;
u_int rows, i;
@@ -2078,7 +2235,7 @@ static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
c &= 0xff;
- dest = p->screen_base+y*p->fontheight*p->next_line+x;
+ dest = p->screen_base + yy*p->fontheight*p->next_line + xx;
cdat = p->fontdata+c*p->fontheight;
fg0 = attr_fgcol(p,conp);
bg0 = attr_bgcol(p,conp);
@@ -2114,14 +2271,14 @@ static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
* address, to reduce the number of expensive Chip RAM
* accesses.
*
- * Experiments on my A4000/040 revealed that this makes a console switch on a
- * 640x400 screen with 256 colors about 3 times faster.
+ * Experiments on my A4000/040 revealed that this makes a console
+ * switch on a 640x400 screen with 256 colors about 3 times faster.
*
* Geert
*/
static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
- int count, int y, int x)
+ int count, int yy, int xx)
{
u_char *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4;
u_int rows, i;
@@ -2129,15 +2286,15 @@ static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
u_long d;
int fg0, bg0, fg, bg;
- dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+ dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
fg0 = attr_fgcol(p,conp);
bg0 = attr_bgcol(p,conp);
while (count--)
- if (x&3 || count < 3) { /* Slow version */
+ if (xx & 3 || count < 3) { /* Slow version */
c1 = *s++;
dest = dest0++;
- x++;
+ xx++;
cdat1 = p->fontdata+c1*p->fontheight;
for (rows = p->fontheight; rows--;) {
@@ -2191,19 +2348,19 @@ static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
}
s += 4;
dest0 += 4;
- x += 4;
+ xx += 4;
count -= 3;
}
}
-static void rev_char_ilbm(struct display *p, int x, int y)
+static void rev_char_ilbm(struct display *p, int xx, int yy)
{
u_char *dest, *dest0;
u_int rows, i;
int mask;
- dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+ dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
mask = p->fgcol ^ p->bgcol;
/*
@@ -2239,8 +2396,8 @@ static void bmove_plan(struct display *p, int sy, int sx, int dy, int dx,
u_char *src, *dest, *src0, *dest0;
u_int i, rows;
- if (sx == 0 && sy == 0 && width == p->next_line) {
- src = p->screen_base;
+ if (sx == 0 && dx == 0 && width == p->next_line) {
+ src = p->screen_base+sy*p->fontheight*width;
dest = p->screen_base+dy*p->fontheight*width;
for (i = p->var.bits_per_pixel; i--;) {
mymemmove(dest, src, height*p->fontheight*width);
@@ -2301,8 +2458,8 @@ static void clear_plan(struct vc_data *conp, struct display *p, int sy, int sx,
}
-static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
- int x)
+static void putc_plan(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx)
{
u_char *dest, *dest0, *cdat, *cdat0;
u_int rows, i;
@@ -2311,7 +2468,7 @@ static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
c &= 0xff;
- dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+ dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
cdat0 = p->fontdata+c*p->fontheight;
fg = attr_fgcol(p,conp);
bg = attr_bgcol(p,conp);
@@ -2344,7 +2501,7 @@ static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
*/
static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
- int count, int y, int x)
+ int count, int yy, int xx)
{
u_char *dest, *dest0, *dest1;
u_char *cdat1, *cdat2, *cdat3, *cdat4, *cdat10, *cdat20, *cdat30, *cdat40;
@@ -2353,15 +2510,15 @@ static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
u_long d;
int fg0, bg0, fg, bg;
- dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+ dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
fg0 = attr_fgcol(p,conp);
bg0 = attr_bgcol(p,conp);
while (count--)
- if (x&3 || count < 3) { /* Slow version */
+ if (xx & 3 || count < 3) { /* Slow version */
c1 = *s++;
dest1 = dest0++;
- x++;
+ xx++;
cdat10 = p->fontdata+c1*p->fontheight;
fg = fg0;
@@ -2424,19 +2581,19 @@ static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
}
s += 4;
dest0 += 4;
- x += 4;
+ xx += 4;
count -= 3;
}
}
-static void rev_char_plan(struct display *p, int x, int y)
+static void rev_char_plan(struct display *p, int xx, int yy)
{
u_char *dest, *dest0;
u_int rows, i;
int mask;
- dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+ dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
mask = p->fgcol ^ p->bgcol;
/*
@@ -2499,8 +2656,8 @@ static void bmove_2_plane(struct display *p, int sy, int sx, int dy, int dx,
* done with memmove()
*/
mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
- p->screen_base + sy * p->next_line * p->fontheight,
- p->next_line * height * p->fontheight);
+ p->screen_base + sy * p->next_line * p->fontheight,
+ p->next_line * height * p->fontheight);
} else {
int rows, cols;
u_char *src;
@@ -2607,8 +2764,8 @@ static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
int bytes = p->next_line;
int lines = height * p->fontheight;
ulong size;
- u_long cval;
- u_short pcval;
+ u_long cval;
+ u_short pcval;
cval = expand2l (COLOR_2P (attr_bgcol_ec(p,conp)));
@@ -2650,43 +2807,45 @@ static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
}
-static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
- int x)
+static void putc_2_plane(struct vc_data *conp, struct display *p, int
+ c, int yy, int xx)
{
- u_char *dest;
- u_char *cdat;
- int rows;
- int bytes = p->next_line;
- ulong eorx, fgx, bgx, fdx;
+ u_char *dest;
+ u_char *cdat;
+ int rows;
+ int bytes = p->next_line;
+ ulong eorx, fgx, bgx, fdx;
c &= 0xff;
- dest = p->screen_base + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
- cdat = p->fontdata + (c * p->fontheight);
+ dest = p->screen_base + yy * p->fontheight * bytes +
+ (xx >> 1)*4 + (xx & 1);
+ cdat = p->fontdata + (c * p->fontheight);
fgx = expand2w(COLOR_2P(attr_fgcol(p,conp)));
bgx = expand2w(COLOR_2P(attr_bgcol(p,conp)));
eorx = fgx ^ bgx;
- for(rows = p->fontheight ; rows-- ; dest += bytes) {
+ for(rows = p->fontheight ; rows-- ; dest += bytes) {
fdx = dup2w(*cdat++);
__asm__ __volatile__ ("movepw %1,%0@(0)" : /* no outputs */
- : "a" (dest), "d" ((fdx & eorx) ^ bgx));
+ : "a" (dest), "d" ((fdx & eorx) ^ bgx));
}
}
static void putcs_2_plane(struct vc_data *conp, struct display *p,
- const char *s, int count, int y, int x)
+ const char *s, int count, int yy, int xx)
{
u_char *dest, *dest0;
- u_char *cdat, c;
- int rows;
- int bytes;
- ulong eorx, fgx, bgx, fdx;
-
- bytes = p->next_line;
- dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
+ u_char *cdat, c;
+ int rows;
+ int bytes;
+ ulong eorx, fgx, bgx, fdx;
+
+ bytes = p->next_line;
+ dest0 = p->screen_base + yy * p->fontheight * bytes
+ + (xx >> 1)*4 + (xx & 1);
fgx = expand2w(COLOR_2P(attr_fgcol(p,conp)));
bgx = expand2w(COLOR_2P(attr_bgcol(p,conp)));
eorx = fgx ^ bgx;
@@ -2699,32 +2858,33 @@ static void putcs_2_plane(struct vc_data *conp, struct display *p,
for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
fdx = dup2w(*cdat++);
__asm__ __volatile__ ("movepw %1,%0@(0)" : /* no outputs */
- : "a" (dest), "d" ((fdx & eorx) ^ bgx));
+ : "a" (dest), "d" ((fdx & eorx) ^ bgx));
}
INC_2P(dest0);
}
}
-static void rev_char_2_plane(struct display *p, int x, int y)
+static void rev_char_2_plane(struct display *p, int xx, int yy)
{
- u_char *dest;
- int j;
- int bytes;
-
- dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*4 + (x & 1);
- j = p->fontheight;
- bytes = p->next_line;
- while (j--)
- {
- /* This should really obey the individual character's
- * background and foreground colors instead of simply
- * inverting.
- */
- dest[0] = ~dest[0];
- dest[2] = ~dest[2];
- dest += bytes;
- }
+ u_char *dest;
+ int j;
+ int bytes;
+
+ dest = p->screen_base + yy * p->fontheight * p->next_line +
+ (xx >> 1)*4 + (xx & 1);
+ j = p->fontheight;
+ bytes = p->next_line;
+ while (j--)
+ {
+ /* This should really obey the individual character's
+ * background and foreground colors instead of simply
+ * inverting.
+ */
+ dest[0] = ~dest[0];
+ dest[2] = ~dest[2];
+ dest += bytes;
+ }
}
#endif /* CONFIG_FBCON_2PLANE */
@@ -2763,8 +2923,8 @@ static void bmove_4_plane(struct display *p, int sy, int sx, int dy, int dx,
* done with memmove()
*/
mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
- p->screen_base + sy * p->next_line * p->fontheight,
- p->next_line * height * p->fontheight);
+ p->screen_base + sy * p->next_line * p->fontheight,
+ p->next_line * height * p->fontheight);
} else {
int rows, cols;
u_char *src;
@@ -2871,9 +3031,9 @@ static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
int bytes = p->next_line;
int lines = height * p->fontheight;
ulong size;
- u_long cval1, cval2, pcval;
+ u_long cval1, cval2, pcval;
- expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
+ expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
if (sx == 0 && width == bytes/4) {
@@ -2913,43 +3073,45 @@ static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
}
-static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
- int x)
+static void putc_4_plane(struct vc_data *conp, struct display *p, int
+ c, int yy, int xx)
{
u_char *dest;
- u_char *cdat;
- int rows;
- int bytes = p->next_line;
- ulong eorx, fgx, bgx, fdx;
+ u_char *cdat;
+ int rows;
+ int bytes = p->next_line;
+ ulong eorx, fgx, bgx, fdx;
c &= 0xff;
- dest = p->screen_base + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
- cdat = p->fontdata + (c * p->fontheight);
+ dest = p->screen_base + yy * p->fontheight * bytes +
+ (xx >> 1)*8 + (xx & 1);
+ cdat = p->fontdata + (c * p->fontheight);
fgx = expand4l(attr_fgcol(p,conp));
bgx = expand4l(attr_bgcol(p,conp));
eorx = fgx ^ bgx;
- for(rows = p->fontheight ; rows-- ; dest += bytes) {
+ for(rows = p->fontheight ; rows-- ; dest += bytes) {
fdx = dup4l(*cdat++);
__asm__ __volatile__ ("movepl %1,%0@(0)" : /* no outputs */
- : "a" (dest), "d" ((fdx & eorx) ^ bgx));
+ : "a" (dest), "d" ((fdx & eorx) ^ bgx));
}
}
static void putcs_4_plane(struct vc_data *conp, struct display *p,
- const char *s, int count, int y, int x)
+ const char *s, int count, int yy, int xx)
{
u_char *dest, *dest0;
- u_char *cdat, c;
- int rows;
- int bytes;
- ulong eorx, fgx, bgx, fdx;
-
- bytes = p->next_line;
- dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
+ u_char *cdat, c;
+ int rows;
+ int bytes;
+ ulong eorx, fgx, bgx, fdx;
+
+ bytes = p->next_line;
+ dest0 = p->screen_base + yy * p->fontheight * bytes
+ + (xx >> 1)*8 + (xx & 1);
fgx = expand4l(attr_fgcol(p,conp));
bgx = expand4l(attr_bgcol(p,conp));
eorx = fgx ^ bgx;
@@ -2969,20 +3131,21 @@ static void putcs_4_plane(struct vc_data *conp, struct display *p,
for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
fdx = dup4l(*cdat++);
__asm__ __volatile__ ("movepl %1,%0@(0)" : /* no outputs */
- : "a" (dest), "d" ((fdx & eorx) ^ bgx));
+ : "a" (dest), "d" ((fdx & eorx) ^ bgx));
}
INC_4P(dest0);
}
}
-static void rev_char_4_plane(struct display *p, int x, int y)
+static void rev_char_4_plane(struct display *p, int xx, int yy)
{
u_char *dest;
int j;
int bytes;
- dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*8 + (x & 1);
+ dest = p->screen_base + yy * p->fontheight * p->next_line +
+ (xx >> 1)*8 + (xx & 1);
j = p->fontheight;
bytes = p->next_line;
@@ -3150,15 +3313,16 @@ static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
int bytes = p->next_line;
int lines = height * p->fontheight;
ulong size;
- u_long cval1, cval2, cval3, cval4, pcval1, pcval2;
+ u_long cval1, cval2, cval3, cval4, pcval1, pcval2;
- expand8ql(attr_bgcol_ec(p,conp), cval1, cval2, cval3, cval4);
+ expand8ql(attr_bgcol_ec(p,conp), cval1, cval2, cval3, cval4);
if (sx == 0 && width == bytes/8) {
offset = sy * bytes * p->fontheight;
size = lines * bytes;
- memset_even_8p(p->screen_base+offset, size, cval1, cval2, cval3, cval4);
+ memset_even_8p(p->screen_base+offset, size, cval1,
+ cval2, cval3, cval4);
} else {
@@ -3193,48 +3357,50 @@ static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
}
-static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
- int x)
+static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx)
{
u_char *dest;
- u_char *cdat;
- int rows;
- int bytes = p->next_line;
- ulong eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
+ u_char *cdat;
+ int rows;
+ int bytes = p->next_line;
+ ulong eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
c &= 0xff;
- dest = p->screen_base + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
- cdat = p->fontdata + (c * p->fontheight);
+ dest = p->screen_base + yy * p->fontheight * bytes +
+ (xx >> 1)*16 + (xx & 1);
+ cdat = p->fontdata + (c * p->fontheight);
expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2);
expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2);
eorx1 = fgx1 ^ bgx1; eorx2 = fgx2 ^ bgx2;
- for(rows = p->fontheight ; rows-- ; dest += bytes) {
+ for(rows = p->fontheight ; rows-- ; dest += bytes) {
fdx = dup4l(*cdat++);
__asm__ __volatile__
("movepl %1,%0@(0)\n\t"
- "movepl %2,%0@(8)"
- : /* no outputs */
- : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
- "d" ((fdx & eorx2) ^ bgx2)
+ "movepl %2,%0@(8)"
+ : /* no outputs */
+ : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
+ "d" ((fdx & eorx2) ^ bgx2)
);
}
}
static void putcs_8_plane(struct vc_data *conp, struct display *p,
- const char *s, int count, int y, int x)
+ const char *s, int count, int yy, int xx)
{
u_char *dest, *dest0;
- u_char *cdat, c;
- int rows;
- int bytes;
- ulong eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
+ u_char *cdat, c;
+ int rows;
+ int bytes;
+ ulong eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
- bytes = p->next_line;
- dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
+ bytes = p->next_line;
+ dest0 = p->screen_base + yy * p->fontheight * bytes
+ + (xx >> 1)*16 + (xx & 1);
expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2);
expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2);
@@ -3267,30 +3433,31 @@ static void putcs_8_plane(struct vc_data *conp, struct display *p,
}
-static void rev_char_8_plane(struct display *p, int x, int y)
+static void rev_char_8_plane(struct display *p, int xx, int yy)
{
- u_char *dest;
- int j;
- int bytes;
-
- dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*16 + (x & 1);
- j = p->fontheight;
- bytes = p->next_line;
-
- while (j--)
- {
- /* This should really obey the individual character's
- * background and foreground colors instead of simply
- * inverting. For 8 plane mode, only the lower 4 bits of the
- * color are inverted, because only that color registers have
- * been set up.
- */
- dest[0] = ~dest[0];
- dest[2] = ~dest[2];
- dest[4] = ~dest[4];
- dest[6] = ~dest[6];
- dest += bytes;
- }
+ u_char *dest;
+ int j;
+ int bytes;
+
+ dest = p->screen_base + yy * p->fontheight * p->next_line
+ + (xx >> 1)*16 + (xx & 1);
+ j = p->fontheight;
+ bytes = p->next_line;
+
+ while (j--)
+ {
+ /* This should really obey the individual character's
+ * background and foreground colors instead of simply
+ * inverting. For 8 plane mode, only the lower 4 bits of the
+ * color are inverted, because only that color registers have
+ * been set up.
+ */
+ dest[0] = ~dest[0];
+ dest[2] = ~dest[2];
+ dest[4] = ~dest[4];
+ dest[6] = ~dest[6];
+ dest += bytes;
+ }
}
#endif /* CONFIG_FBCON_8PLANE */
@@ -3378,8 +3545,8 @@ static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
}
-static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
- int x)
+static void putc_8_packed(struct vc_data *conp, struct display *p, int c,
+ int yy, int xx)
{
u_char *dest,*cdat;
int bytes=p->next_line,rows;
@@ -3387,7 +3554,7 @@ static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
c &= 0xff;
- dest = p->screen_base + y * p->fontheight * bytes + x * 8;
+ dest = p->screen_base + yy * p->fontheight * bytes + xx * 8;
cdat = p->fontdata + c * p->fontheight;
fgx=attr_fgcol(p,conp);
@@ -3408,13 +3575,13 @@ static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
static void putcs_8_packed(struct vc_data *conp, struct display *p,
- const char *s, int count, int y, int x)
+ const char *s, int count, int yy, int xx)
{
u_char *cdat, c, *dest, *dest0;
int rows,bytes=p->next_line;
u_long eorx, fgx, bgx;
- dest0 = p->screen_base + y * p->fontheight * bytes + x * 8;
+ dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 8;
fgx=attr_fgcol(p,conp);
bgx=attr_bgcol(p,conp);
fgx |= (fgx << 8);
@@ -3437,12 +3604,12 @@ static void putcs_8_packed(struct vc_data *conp, struct display *p,
}
-static void rev_char_8_packed(struct display *p, int x, int y)
+static void rev_char_8_packed(struct display *p, int xx, int yy)
{
u_char *dest;
int bytes=p->next_line, rows;
- dest = p->screen_base + y * p->fontheight * bytes + x * 8;
+ dest = p->screen_base + yy * p->fontheight * bytes + xx * 8;
for (rows = p->fontheight ; rows-- ; dest += bytes) {
((u_long *)dest)[0] ^= 0x0f0f0f0f;
((u_long *)dest)[1] ^= 0x0f0f0f0f;
@@ -3539,7 +3706,7 @@ static void clear_16_packed(struct vc_data *conp, struct display *p, int sy,
static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
- int y, int x)
+ int yy, int xx)
{
u_char *dest,*cdat;
int bytes=p->next_line,rows;
@@ -3547,7 +3714,7 @@ static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
c &= 0xff;
- dest = p->screen_base + y * p->fontheight * bytes + x * 16;
+ dest = p->screen_base + yy * p->fontheight * bytes + xx * 16;
cdat = p->fontdata + c * p->fontheight;
fgx = attr_fgcol(p,conp);
@@ -3573,13 +3740,13 @@ static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
/* TODO */
static void putcs_16_packed(struct vc_data *conp, struct display *p,
- const char *s, int count, int y, int x)
+ const char *s, int count, int yy, int xx)
{
u_char *cdat, c, *dest, *dest0;
int rows,bytes=p->next_line;
u_long eorx, fgx, bgx;
- dest0 = p->screen_base + y * p->fontheight * bytes + x * 16;
+ dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 16;
fgx = attr_fgcol(p,conp);
fgx = packed16_cmap[fgx];
bgx = attr_bgcol(p,conp);
@@ -3606,12 +3773,12 @@ static void putcs_16_packed(struct vc_data *conp, struct display *p,
}
-static void rev_char_16_packed(struct display *p, int x, int y)
+static void rev_char_16_packed(struct display *p, int xx, int yy)
{
u_char *dest;
int bytes=p->next_line, rows;
- dest = p->screen_base + y * p->fontheight * bytes + x * 16;
+ dest = p->screen_base + yy * p->fontheight * bytes + xx * 16;
for (rows = p->fontheight ; rows-- ; dest += bytes) {
((u_long *)dest)[0] ^= 0xffffffff;
((u_long *)dest)[1] ^= 0xffffffff;
@@ -3641,87 +3808,90 @@ static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx,
}
-static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
- int height, int width)
+static void clear_cyber(struct vc_data *conp, struct display *p, int
+ sy, int sx, int height, int width)
{
- u_char bg;
+ unsigned char bg;
sx *= 8; width *= 8;
bg = attr_bgcol_ec(p,conp);
- Cyber_RectFill((u_short)sx, (u_short)(sy*p->fontheight), (u_short)width,
- (u_short)(height*p->fontheight), (u_short)S3_NEW,
- (u_short)bg);
+ Cyber_RectFill((u_short)sx,
+ (u_short)(sy*p->fontheight),
+ (u_short)width,
+ (u_short)(height*p->fontheight),
+ (u_short)S3_NEW,
+ (u_short)bg);
}
-static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
- int x)
+static void putc_cyber(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx)
{
u_char *dest, *cdat;
u_long tmp;
- u_int rows, reverse, underline;
+ u_int rows, revs, underl;
u_char d;
- u_char fg, bg;
+ u_char fg, bg;
- c &= 0xff;
+ c &= 0xff;
dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
cdat = p->fontdata+(c*p->fontheight);
- fg = disp->fgcol;
- bg = disp->bgcol;
- reverse = conp->vc_reverse;
- underline = conp->vc_underline;
+ fg = disp->fgcol;
+ bg = disp->bgcol;
+ revs = conp->vc_reverse;
+ underl = conp->vc_underline;
Cyber_WaitBlit();
for (rows = p->fontheight; rows--; dest += p->next_line) {
d = *cdat++;
- if (underline && !rows)
+ if (underl && !rows)
d = 0xff;
- if (reverse)
+ if (revs)
d = ~d;
- tmp = ((d & 0x80) ? fg : bg) << 24;
- tmp |= ((d & 0x40) ? fg : bg) << 16;
- tmp |= ((d & 0x20) ? fg : bg) << 8;
- tmp |= ((d & 0x10) ? fg : bg);
- *((u_long*) dest) = tmp;
- tmp = ((d & 0x8) ? fg : bg) << 24;
- tmp |= ((d & 0x4) ? fg : bg) << 16;
- tmp |= ((d & 0x2) ? fg : bg) << 8;
- tmp |= ((d & 0x1) ? fg : bg);
- *((u_long*) dest + 1) = tmp;
+ tmp = ((d & 0x80) ? fg : bg) << 24;
+ tmp |= ((d & 0x40) ? fg : bg) << 16;
+ tmp |= ((d & 0x20) ? fg : bg) << 8;
+ tmp |= ((d & 0x10) ? fg : bg);
+ *((u_long*) dest) = tmp;
+ tmp = ((d & 0x8) ? fg : bg) << 24;
+ tmp |= ((d & 0x4) ? fg : bg) << 16;
+ tmp |= ((d & 0x2) ? fg : bg) << 8;
+ tmp |= ((d & 0x1) ? fg : bg);
+ *((u_long*) dest + 1) = tmp;
}
}
static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
- int count, int y, int x)
+ int count, int yy, int xx)
{
u_char *dest, *dest0, *cdat;
- u_long tmp;
- u_int rows, reverse, underline;
+ u_long tmp;
+ u_int rows, revs, underl;
u_char c, d;
- u_char fg, bg;
+ u_char fg, bg;
dest0 = p->screen_base+y*p->fontheight*p->next_line+8*x;
- fg = disp->fgcol;
- bg = disp->bgcol;
- reverse = conp->vc_reverse;
- underline = conp->vc_underline;
+ fg = disp->fgcol;
+ bg = disp->bgcol;
+ revs = conp->vc_reverse;
+ underl = conp->vc_underline;
Cyber_WaitBlit();
while (count--) {
c = *s++;
dest = dest0;
- dest0 += 8;
+ dest0 += 8;
cdat = p->fontdata+(c*p->fontheight);
for (rows = p->fontheight; rows--; dest += p->next_line) {
d = *cdat++;
- if (underline && !rows)
+ if (underl && !rows)
d = 0xff;
- if (reverse)
+ if (revs)
d = ~d;
tmp = ((d & 0x80) ? fg : bg) << 24;
@@ -3739,32 +3909,208 @@ static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
}
-static void rev_char_cyber(struct display *p, int x, int y)
+static void rev_char_cyber(struct display *p, int xx, int yy)
{
- u_char *dest;
- u_int rows;
- u_char fg, bg;
+ unsigned char *dest;
+ unsigned int rows;
+ unsigned char fg, bg;
- fg = disp->fgcol;
- bg = disp->bgcol;
+ fg = disp->fgcol;
+ bg = disp->bgcol;
dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
Cyber_WaitBlit();
for (rows = p->fontheight; rows--; dest += p->next_line) {
*dest = (*dest == fg) ? bg : fg;
- *(dest+1) = (*(dest + 1) == fg) ? bg : fg;
- *(dest+2) = (*(dest + 2) == fg) ? bg : fg;
- *(dest+3) = (*(dest + 3) == fg) ? bg : fg;
- *(dest+4) = (*(dest + 4) == fg) ? bg : fg;
- *(dest+5) = (*(dest + 5) == fg) ? bg : fg;
- *(dest+6) = (*(dest + 6) == fg) ? bg : fg;
- *(dest+7) = (*(dest + 7) == fg) ? bg : fg;
+ *(dest+1) = (*(dest + 1) == fg) ? bg : fg;
+ *(dest+2) = (*(dest + 2) == fg) ? bg : fg;
+ *(dest+3) = (*(dest + 3) == fg) ? bg : fg;
+ *(dest+4) = (*(dest + 4) == fg) ? bg : fg;
+ *(dest+5) = (*(dest + 5) == fg) ? bg : fg;
+ *(dest+6) = (*(dest + 6) == fg) ? bg : fg;
+ *(dest+7) = (*(dest + 7) == fg) ? bg : fg;
}
}
#endif /* CONFIG_FBCON_CYBER */
+#ifdef CONFIG_FBCON_RETINAZ3
+
+/*
+ * RetinaZ3 (accelerated)
+ */
+
+#define Z3BLTcopy 0xc0
+#define Z3BLTset 0xf0
+
+static void clear_retz3(struct vc_data *conp, struct display *p, int
+ sy, int sx, int height, int width)
+{
+ unsigned short col;
+ int fontwidth = p->fontwidth;
+
+ sx *= fontwidth;
+ width *= fontwidth;
+
+ col = attr_bgcol_ec(p, conp);
+ col &= 0xff;
+ col |= (col << 8);
+
+ retz3_bitblt(&p->var,
+ (unsigned short)sx,
+ (unsigned short)(sy*p->fontheight),
+ (unsigned short)sx,
+ (unsigned short)(sy*p->fontheight),
+ (unsigned short)width,
+ (unsigned short)(height*p->fontheight),
+ Z3BLTset,
+ col);
+}
+
+static void bmove_retz3(struct display *p, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+ int fontwidth = p->fontwidth;
+
+ sx *= fontwidth;
+ dx *= fontwidth;
+ width *= fontwidth;
+
+ retz3_bitblt(&p->var,
+ (unsigned short)sx,
+ (unsigned short)(sy*p->fontheight),
+ (unsigned short)dx,
+ (unsigned short)(dy*p->fontheight),
+ (unsigned short)width,
+ (unsigned short)(height*p->fontheight),
+ Z3BLTcopy,
+ 0xffff);
+}
+
+static void putc_retz3(struct vc_data *conp, struct display *p,
+ int c, int yy, int xx)
+{
+ unsigned char *dest, *cdat;
+ unsigned long tmp;
+ unsigned int rows, revs, underl, bytes;
+ unsigned char d;
+ unsigned char fg, bg;
+
+ c &= 0xff;
+
+ bytes = p->next_line;
+
+ dest = p->screen_base + yy*p->fontheight*bytes
+ + xx*p->var.bits_per_pixel;
+ cdat = p->fontdata + c * p->fontheight;
+
+ fg = disp->fgcol;
+ bg = disp->bgcol;
+ revs = conp->vc_reverse;
+ underl = conp->vc_underline;
+
+ for (rows = p->fontheight; rows--; dest += bytes) {
+ d = *cdat++;
+
+ if (underl && !rows)
+ d = 0xff;
+ if (revs)
+ d = ~d;
+
+ tmp = ((d & 0x80) ? fg : bg) << 24;
+ tmp |= ((d & 0x40) ? fg : bg) << 16;
+ tmp |= ((d & 0x20) ? fg : bg) << 8;
+ tmp |= ((d & 0x10) ? fg : bg);
+ *((unsigned long*) dest) = tmp;
+ tmp = ((d & 0x8) ? fg : bg) << 24;
+ tmp |= ((d & 0x4) ? fg : bg) << 16;
+ tmp |= ((d & 0x2) ? fg : bg) << 8;
+ tmp |= ((d & 0x1) ? fg : bg);
+ *((unsigned long*) dest + 1) = tmp;
+ }
+}
+
+
+static void putcs_retz3(struct vc_data *conp, struct display *p,
+ const char *s, int count, int yy, int xx)
+{
+ unsigned char *dest, *dest0, *cdat;
+ unsigned long tmp;
+ unsigned int rows, revs, underl, bytes;
+ unsigned char c, d;
+ unsigned char fg, bg;
+
+ bytes = p->next_line;
+
+ dest0 = p->screen_base + yy*p->fontheight*bytes
+ + xx * p->var.bits_per_pixel;
+ fg = disp->fgcol;
+ bg = disp->bgcol;
+ revs = conp->vc_reverse;
+ underl = conp->vc_underline;
+
+ while (count--) {
+ c = *s++;
+ dest = dest0;
+ dest0 += 8;
+
+ cdat = p->fontdata + c * p->fontheight;
+ for (rows = p->fontheight; rows--; dest += bytes) {
+ d = *cdat++;
+
+ if (underl && !rows)
+ d = 0xff;
+ if (revs)
+ d = ~d;
+
+ tmp = ((d & 0x80) ? fg : bg) << 24;
+ tmp |= ((d & 0x40) ? fg : bg) << 16;
+ tmp |= ((d & 0x20) ? fg : bg) << 8;
+ tmp |= ((d & 0x10) ? fg : bg);
+ *((unsigned long*) dest) = tmp;
+ tmp = ((d & 0x8) ? fg : bg) << 24;
+ tmp |= ((d & 0x4) ? fg : bg) << 16;
+ tmp |= ((d & 0x2) ? fg : bg) << 8;
+ tmp |= ((d & 0x1) ? fg : bg);
+ *((unsigned long*) dest + 1) = tmp;
+ }
+ }
+}
+
+static void rev_char_retz3(struct display *p, int xx, int yy)
+{
+ unsigned char *dest;
+ int bytes=p->next_line, rows;
+ unsigned int bpp, mask;
+
+ bpp = p->var.bits_per_pixel;
+
+ switch (bpp){
+ case 8:
+ mask = 0x0f0f0f0f;
+ break;
+ case 16:
+ mask = 0xffffffff;
+ break;
+ case 24:
+ mask = 0xffffffff; /* ??? */
+ break;
+ default:
+ printk("illegal depth for rev_char_retz3(), bpp = %i\n", bpp);
+ return;
+ }
+
+ dest = p->screen_base + yy * p->fontheight * bytes + xx * bpp;
+
+ for (rows = p->fontheight ; rows-- ; dest += bytes) {
+ ((unsigned long *)dest)[0] ^= mask;
+ ((unsigned long *)dest)[1] ^= mask;
+ }
+}
+
+#endif
+
/* ====================================================================== */
/*
@@ -3774,5 +4120,5 @@ static void rev_char_cyber(struct display *p, int x, int y)
struct consw fb_con = {
fbcon_startup, fbcon_init, fbcon_deinit, fbcon_clear, fbcon_putc,
fbcon_putcs, fbcon_cursor, fbcon_scroll, fbcon_bmove, fbcon_switch,
- fbcon_blank, fbcon_get_font, fbcon_set_font
+ fbcon_blank, fbcon_get_font, fbcon_set_font, fbcon_set_palette
};
diff --git a/arch/m68k/console/txtcon.c b/arch/m68k/console/txtcon.c
index a080c12a7..b85808558 100644
--- a/arch/m68k/console/txtcon.c
+++ b/arch/m68k/console/txtcon.c
@@ -22,7 +22,7 @@
* Interface used by the world
*/
-static u_long txtcon_startup(u_long kmem_start, char **display_desc);
+static u_long txtcon_startup(u_long kmem_start, const char **display_desc);
static void txtcon_init(struct vc_data *conp);
static int txtcon_deinit(struct vc_data *conp);
static int txtcon_clear(struct vc_data *conp, int sy, int sx, int height,
@@ -36,10 +36,12 @@ static int txtcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
int height, int width);
static int txtcon_switch(struct vc_data *conp);
static int txtcon_blank(int blank);
+static int txtcon_get_font(struct vc_data *conp, int *w, int *h, char *data);
+static int txtcon_set_font(struct vc_data *conp, int w, int h, char *data);
+static int txtcon_set_palette(struct vc_data *conp, unsigned char *table);
-
-static u_long txtcon_startup(u_long kmem_start, char **display_desc)
+static u_long txtcon_startup(u_long kmem_start, const char **display_desc)
{
*display_desc = "Not yet implemented";
return(kmem_start);
@@ -113,6 +115,24 @@ static int txtcon_blank(int blank)
}
+static int txtcon_get_font(struct vc_data *conp, int *w, int *h, char *data)
+{
+ return(0);
+}
+
+
+static int txtcon_set_font(struct vc_data *conp, int w, int h, char *data)
+{
+ return(0);
+}
+
+
+static int txtcon_set_palette(struct vc_data *conp, unsigned char *table)
+{
+ return(0);
+}
+
+
/* ====================================================================== */
/*
@@ -122,6 +142,6 @@ static int txtcon_blank(int blank)
struct consw txt_con = {
txtcon_startup, txtcon_init, txtcon_deinit, txtcon_clear, txtcon_putc,
txtcon_putcs, txtcon_cursor, txtcon_scroll, txtcon_bmove, txtcon_switch,
- txtcon_blank
+ txtcon_blank, txtcon_get_font, txtcon_set_font, txtcon_set_palette
};
diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig
index e97326929..65f71d5a9 100644
--- a/arch/m68k/defconfig
+++ b/arch/m68k/defconfig
@@ -38,14 +38,15 @@ CONFIG_M68040=y
#
CONFIG_NET=y
CONFIG_SYSVIPC=y
+CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
CONFIG_ZORRO=y
CONFIG_AMIFB_OCS=y
CONFIG_AMIFB_ECS=y
CONFIG_AMIFB_AGA=y
# CONFIG_FB_CYBER is not set
+# CONFIG_FB_RETINAZ3 is not set
# CONFIG_AMIGA_GSP is not set
# CONFIG_GSP_RESOLVER is not set
# CONFIG_GSP_A2410 is not set
@@ -60,6 +61,7 @@ CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_AMIGA_Z2RAM is not set
# CONFIG_ATARI_ACSI is not set
# CONFIG_ACSI_MULTI_LUN is not set
@@ -74,21 +76,21 @@ CONFIG_BLK_DEV_INITRD=y
#
# Networking options
#
+# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
# CONFIG_NET_ALIAS is not set
CONFIG_INET=y
-# CONFIG_IP_FORWARD is not set
# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_FIREWALL is not set
# CONFIG_IP_ACCT is not set
+# CONFIG_IP_ROUTER is not set
+# CONFIG_NET_IPIP is not set
#
# (it is safe to leave these untouched)
#
# CONFIG_INET_PCTCP is not set
# CONFIG_INET_RARP is not set
-# CONFIG_NO_PATH_MTU_DISCOVERY is not set
-# CONFIG_TCP_NAGLE_OFF is not set
+CONFIG_PATH_MTU_DISCOVERY=y
CONFIG_IP_NOSR=y
# CONFIG_SKB_LARGE is not set
# CONFIG_IPV6 is not set
@@ -100,7 +102,6 @@ CONFIG_IP_NOSR=y
# CONFIG_ATALK is not set
# CONFIG_AX25 is not set
# CONFIG_BRIDGE is not set
-# CONFIG_NETLINK is not set
#
# SCSI support
@@ -124,18 +125,19 @@ CONFIG_BLK_DEV_SR=y
# SCSI low-level drivers
#
CONFIG_A3000_SCSI=y
-# CONFIG_A2091_SCSI is not set
-# CONFIG_GVP11_SCSI is not set
+CONFIG_A2091_SCSI=y
+CONFIG_GVP11_SCSI=y
# CONFIG_CYBERSTORM_SCSI is not set
# CONFIG_CYBERSTORMII_SCSI is not set
# CONFIG_BLZ2060_SCSI is not set
# CONFIG_BLZ1230_SCSI is not set
+# CONFIG_FASTLANE_SCSI is not set
CONFIG_ATARI_SCSI=y
#
# Network device support
#
-# CONFIG_NETDEVICES is not set
+CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_SLIP is not set
# CONFIG_PPP is not set
@@ -151,9 +153,7 @@ CONFIG_ATARI_SCSI=y
#
# CONFIG_QUOTA is not set
CONFIG_MINIX_FS=y
-# CONFIG_EXT_FS is not set
CONFIG_EXT2_FS=y
-# CONFIG_XIA_FS is not set
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
# CONFIG_VFAT_FS is not set
@@ -167,16 +167,21 @@ CONFIG_NFS_FS=y
# CONFIG_HPFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_AFFS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_UFS_FS is not set
#
# Character devices
#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
# CONFIG_PRINTER is not set
CONFIG_AMIGAMOUSE=y
CONFIG_ATARIMOUSE=y
CONFIG_AMIGA_BUILTIN_SERIAL=y
# CONFIG_GVPIOEXT is not set
+# CONFIG_GVPIOEXT_LP is not set
+# CONFIG_GVPIOEXT_PLIP is not set
# CONFIG_MULTIFACE_III_TTY is not set
# CONFIG_USERIAL is not set
# CONFIG_WATCHDOG is not set
diff --git a/arch/m68k/fpsp040/Makefile b/arch/m68k/fpsp040/Makefile
index b6a8c0279..d3ec21217 100644
--- a/arch/m68k/fpsp040/Makefile
+++ b/arch/m68k/fpsp040/Makefile
@@ -9,7 +9,6 @@
.S.o:
$(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
-# $(AS) -o $*.o $<
OS_TARGET := fpsp.o
diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S
index 4e4eab64e..5768516bd 100644
--- a/arch/m68k/fpsp040/skeleton.S
+++ b/arch/m68k/fpsp040/skeleton.S
@@ -513,9 +513,12 @@ copyout:
movel 12(%sp),%d0 | count
subl #1,%d0 | dec count by 1 for dbra
movel #1,%d1
- movec %d1,%DFC | set dfc for user data space
+
+| DFC is already set
+| movec %d1,%DFC | set dfc for user data space
moreout:
moveb (%a0)+,%d1 | fetch supervisor byte
+out_ea:
movesb %d1,(%a1)+ | write user byte
dbf %d0,moreout
rts
@@ -526,11 +529,24 @@ copyin:
movel 12(%sp),%d0 | count
subl #1,%d0 | dec count by 1 for dbra
movel #1,%d1
- movec %d1,%SFC | set sfc for user space
+| SFC is already set
+| movec %d1,%SFC | set sfc for user space
morein:
+in_ea:
movesb (%a0)+,%d1 | fetch user byte
moveb %d1,(%a1)+ | write supervisor byte
dbf %d0,morein
rts
+ .section .fixup,#alloc,#execinstr
+ .even
+1:
+ jbra SYMBOL_NAME(fpsp040_die)
+
+ .section __ex_table,#alloc
+ .align 4
+
+ .long in_ea,1b
+ .long out_ea,1b
+
|end
diff --git a/arch/m68k/ifpsp060/Makefile b/arch/m68k/ifpsp060/Makefile
index fe66cf033..94eea44a4 100644
--- a/arch/m68k/ifpsp060/Makefile
+++ b/arch/m68k/ifpsp060/Makefile
@@ -5,7 +5,6 @@
# for more details.
.S.o:
-# $(AS) -o $*.o $<
$(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
OS_TARGET := ifpsp.o
diff --git a/arch/m68k/ifpsp060/os.S b/arch/m68k/ifpsp060/os.S
index 3e0e30701..b58e0635b 100644
--- a/arch/m68k/ifpsp060/os.S
+++ b/arch/m68k/ifpsp060/os.S
@@ -153,7 +153,7 @@ _060_dmem_read_byte:
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmrbs | supervisor
dmrbu: clr.l %d0 | clear whole longword
- movs.b (%a0),%d0 | fetch user byte
+dmrbuae:movs.b (%a0),%d0 | fetch user byte
bras dmrbr
dmrbs: clr.l %d0 | clear whole longword
move.b (%a0),%d0 | fetch super byte
@@ -190,7 +190,7 @@ _060_imem_read_word:
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmrws | supervisor
dmrwu: clr.l %d0 | clear whole longword
- movs.w (%a0), %d0 | fetch user word
+dmrwuae:movs.w (%a0), %d0 | fetch user word
bras dmrwr
dmrws: clr.l %d0 | clear whole longword
move.w (%a0), %d0 | fetch super word
@@ -226,7 +226,8 @@ _060_dmem_read_long:
_060_imem_read_long:
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmrls | supervisor
-dmrlu: movs.l (%a0),%d0 | fetch user longword
+dmrlu:
+dmrluae:movs.l (%a0),%d0 | fetch user longword
bras dmrlr
dmrls: move.l (%a0),%d0 | fetch super longword
dmrlr: clr.l %d1 | return success
@@ -248,7 +249,8 @@ dmrlr: clr.l %d1 | return success
_060_dmem_write_byte:
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmwbs | supervisor
-dmwbu: movs.b %d0,(%a0) | store user byte
+dmwbu:
+dmwbuae:movs.b %d0,(%a0) | store user byte
bras dmwbr
dmwbs: move.b %d0,(%a0) | store super byte
dmwbr: clr.l %d1 | return success
@@ -270,7 +272,8 @@ dmwbr: clr.l %d1 | return success
_060_dmem_write_word:
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmwws | supervisor
-dmwwu: movs.w %d0,(%a0) | store user word
+dmwwu:
+dmwwuae:movs.w %d0,(%a0) | store user word
bras dmwwr
dmwws: move.w %d0,(%a0) | store super word
dmwwr: clr.l %d1 | return success
@@ -292,7 +295,8 @@ dmwwr: clr.l %d1 | return success
_060_dmem_write_long:
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmwls | supervisor
-dmwlu: movs.l %d0,(%a0) | store user longword
+dmwlu:
+dmwluae:movs.l %d0,(%a0) | store user longword
bra dmwlr
dmwls: move.l %d0,(%a0) | store super longword
dmwlr: clr.l %d1 | return success
@@ -322,9 +326,10 @@ _copyout:
subq.l #1,%d0
moreout:
move.b (%a0)+,%d1 | fetch supervisor byte
+copyoutae:
movs.b %d1,(%a1)+ | store user byte
dbra %d0,moreout | are we through yet?
- moveq #0,%d0 | return success
+ moveq #0,%d0 | return success
rts
|
@@ -337,11 +342,12 @@ _copyin:
move.l 12(%sp),%d0 | count
subq.l #1,%d0
morein:
+copyinae:
movs.b (%a0)+,%d1 | fetch user byte
move.b %d1,(%a1)+ | write supervisor byte
subq.l #0x1,%d0 | are we through yet?
dbra %d0,morein | are we through yet?
- moveq #0,%d0 | return success
+ moveq #0,%d0 | return success
rts
|###########################################################################
@@ -374,3 +380,22 @@ _060_real_trace:
.global _060_real_access
_060_real_access:
bral SYMBOL_NAME(buserr)
+
+
+
+| Execption handling for movs access to illegal memory
+ .section .fixup,#alloc,#execinstr
+ .even
+1: moveq #-1,%d1
+ rts
+.section __ex_table,#alloc
+ .align 4
+ .long dmrbuae,1b
+ .long dmrwuae,1b
+ .long dmrluae,1b
+ .long dmwbuae,1b
+ .long dmwwuae,1b
+ .long dmwluae,1b
+ .long copyoutae,1b
+ .long copyinae,1b
+ .text
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 339e1b5db..67d87c1b9 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -13,7 +13,15 @@
all: kernel.o head.o
O_TARGET := kernel.o
O_OBJS := entry.o process.o traps.o ints.o signal.o ptrace.o \
- setup.o bios32.o sys_m68k.o console.o time.o ksyms.o
+ setup.o bios32.o sys_m68k.o time.o
+ifdef CONFIG_VT
+O_OBJS += console.o
+endif
+OX_OBJS := m68k_ksyms.o
+
+ifdef CONFIG_KGDB
+O_OBJS += kgdb.o
+endif
head.o: head.S
diff --git a/arch/m68k/kernel/console.c b/arch/m68k/kernel/console.c
index cac94e7d4..468ae0b59 100644
--- a/arch/m68k/kernel/console.c
+++ b/arch/m68k/kernel/console.c
@@ -20,7 +20,7 @@
* 'unsigned long con_init(unsigned long)'
* 'int con_open(struct tty_struct *tty, struct file * filp)'
* 'void con_write(struct tty_struct * tty)'
- * 'void console_print(const char * b)'
+ * 'void vt_console_print(const char * b)'
* 'void update_screen(int new_console)'
*
* 'void do_blank_screen(int)'
@@ -103,11 +103,13 @@
* interrupt, as we use trap-gates. Hopefully all is well.
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
+#include <linux/console.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -127,6 +129,7 @@
#include "../../../drivers/char/vt_kern.h"
#include "../../../drivers/char/consolemap.h"
#include "../../../drivers/char/selection.h"
+#include "../../../drivers/char/console_struct.h"
#ifndef MIN
@@ -146,12 +149,13 @@ static void gotoxy(int currcons, int new_x, int new_y);
static void save_cur(int currcons);
static void blank_screen(void);
static void unblank_screen(void);
+static int con_open(struct tty_struct *, struct file *);
extern void change_console(unsigned int);
static inline void set_cursor(int currcons);
static void reset_terminal(int currcons, int do_clear);
extern void reset_vc(unsigned int new_console);
extern void vt_init(void);
-extern void register_console(void (*proc)(const char *));
+static void set_vesa_blanking(unsigned long arg);
extern void vesa_blank(void);
extern void vesa_unblank(void);
extern void compute_shiftstate(void);
@@ -170,6 +174,7 @@ int video_mode_512ch = 0; /* 512-character mode */
static unsigned short console_charmask = 0x0ff;
static unsigned short *vc_scrbuf[MAX_NR_CONSOLES];
+struct vc vc_cons [MAX_NR_CONSOLES];
/* used by kbd_bh - set by keyboard_interrupt */
int do_poke_blanked_console = 0;
@@ -178,13 +183,17 @@ static int blankinterval = 10*60*HZ;
static int vesa_off_interval = 0;
static int vesa_blank_mode = 0; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
-static struct vc {
- struct vc_data *d;
+/*
+ * fg_console is the current virtual console,
+ * last_console is the last used one,
+ * want_console is the console we want to switch to,
+ * kmsg_redirect is the console for kernel messages,
+ */
+int fg_console = 0;
+int last_console = 0;
+int want_console = -1;
+int kmsg_redirect = 0;
- /* might add scrmem, vt_struct, kbd at some time,
- to have everything in one place - the disadvantage
- would be that vc_cons etc can no longer be static */
-} vc_cons [MAX_NR_CONSOLES];
struct consw *conswitchp;
#define cols (vc_cons[currcons].d->vc_cols)
@@ -259,8 +268,6 @@ struct consw *conswitchp;
#define vtnewvt (vt_cons[currcons]->vt_newvt)
#endif
-#define structsize (sizeof(struct vc_data) + sizeof(struct vt_struct))
-
int vc_cons_allocated(unsigned int i)
{
return (i < MAX_NR_CONSOLES && vc_cons[i].d);
@@ -610,8 +617,7 @@ void scrollback(int l)
return;
}
-static void scrup(int currcons, unsigned int t, unsigned int b,
- int nr)
+static void scrup(int currcons, unsigned int t, unsigned int b, int nr)
{
unsigned short *p;
int i;
@@ -625,10 +631,10 @@ static void scrup(int currcons, unsigned int t, unsigned int b,
p = video_mem_start + (b - nr) * cols;
for (i = nr * cols; i > 0; i--)
- *p++ = video_erase_char;
+ *p++ = video_erase_char;
if (currcons != fg_console)
- return;
+ return;
/*
* Arno:
* Scrolling has now been moved to amicon.c where it should have
@@ -801,8 +807,8 @@ static void csi_X(int currcons, int vpar) /* erase the following vpar positions
if (!vpar)
vpar++;
- start=pos;
- count=(vpar > cols-x) ? (cols-x) : vpar;
+ start = pos;
+ count = (vpar > cols-x) ? (cols-x) : vpar;
if (currcons == fg_console)
sw->con_clear(vc_cons[currcons].d,y,x,1,count);
@@ -970,7 +976,7 @@ static void respond_string(const char * p, struct tty_struct * tty)
tty_schedule_flip(tty);
}
-static void cursor_report(int currcons, struct tty_struct * tty)
+static inline void cursor_report(int currcons, struct tty_struct * tty)
{
char buf[40];
@@ -997,7 +1003,7 @@ void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)
respond_string(buf, tty);
}
-/* invoked via ioctl(TIOCLINUX) */
+/* invoked via ioctl(TIOCLINUX) and through set_selection */
int mouse_reporting(void)
{
int currcons = fg_console;
@@ -1005,6 +1011,56 @@ int mouse_reporting(void)
return report_mouse;
}
+int tioclinux(struct tty_struct *tty, unsigned long arg)
+{
+ char type, data;
+
+ if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
+ return -EINVAL;
+ if (current->tty != tty && !suser())
+ return -EPERM;
+ if (get_user(type, (char *)arg))
+ return -EFAULT;
+ switch (type)
+ {
+ case 2:
+ return set_selection(arg, tty, 1);
+ case 3:
+ return paste_selection(tty);
+ case 4:
+ do_unblank_screen();
+ return 0;
+ case 5:
+ return sel_loadlut(arg);
+ case 6:
+
+ /*
+ * Make it possible to react to Shift+Mousebutton.
+ * Note that 'shift_state' is an undocumented
+ * kernel-internal variable; programs not closely
+ * related to the kernel should not use this.
+ */
+ data = shift_state;
+ return put_user(data, (char *) arg);
+ case 7:
+ data = mouse_reporting();
+ return put_user(data, (char *) arg);
+ case 10:
+ set_vesa_blanking(arg);
+ return 0;
+ case 11: /* set kmsg redirect */
+ if (!suser())
+ return -EPERM;
+ if (get_user(data, (char *)arg+1))
+ return -EFAULT;
+ kmsg_redirect = data;
+ return 0;
+ case 12: /* get fg_console */
+ return fg_console;
+ }
+ return -EINVAL;
+}
+
static inline unsigned short *screenpos(int currcons, int offset, int viewed)
{
unsigned short *p = (unsigned short *)(origin + offset);
@@ -1242,18 +1298,18 @@ static void setterm_command(int currcons)
}
}
-static void insert_char(int currcons)
+static inline void insert_char(int currcons)
{
int i;
unsigned short *p = pos;
for (i = cols - x - 2; i >= 0; i--)
- p[i + 1] = p[i];
+ p[i + 1] = p[i];
*pos = video_erase_char;
need_wrap = 0;
if (currcons != fg_console)
- return;
+ return;
/* Arno:
* Move the remainder of the line (-1 character) one spot to the right
@@ -1277,19 +1333,19 @@ static void csi_at(int currcons, unsigned int nr)
p = pos + cols - x - nr;
while (--p >= pos)
- p[nr] = *p;
+ p[nr] = *p;
for (i = 0; i < nr; i++)
- *++p = video_erase_char;
+ *++p = video_erase_char;
need_wrap = 0;
if (currcons != fg_console)
- return;
+ return;
sw->con_bmove (vc_cons[currcons].d, y, x, y, x + nr,
1, cols - x - nr);
while (nr--)
- sw->con_putc (vc_cons[currcons].d, video_erase_char & 0x00ff,
- y, x + nr);
+ sw->con_putc (vc_cons[currcons].d,
+ video_erase_char & 0x00ff, y, x + nr);
}
static void csi_L(int currcons, unsigned int nr)
@@ -1584,9 +1640,9 @@ static int do_con_write(struct tty_struct * tty, int from_user,
*/
/* Only use this for the foreground console,
- where we really draw the chars */
+ where we really draw the chars */
- if (count > 2 &&
+ if (count > 2 &&
!decim && !utf && currcons == fg_console) {
static char putcs_buf[256];
char *p = putcs_buf;
@@ -1599,13 +1655,11 @@ static int do_con_write(struct tty_struct * tty, int from_user,
if (nextx == cols) {
sw->con_putc(vc_cons[currcons].d,
*putcs_buf, y, x);
- pos--;
+ ((unsigned short *)pos)--;
need_wrap = decawm;
continue;
}
- /* TAB TAB TAB - Arghh!!!! */
-
while (count)
{
enable_bh(CONSOLE_BH);
@@ -2068,12 +2122,13 @@ void poke_blanked_console(void)
/* DPC: New version of console_print using putcs */
-void console_print(const char * b)
+#ifdef CONFIG_VT_CONSOLE
+void vt_console_print(const char * b, unsigned int count)
{
int currcons = fg_console;
unsigned char c;
const char *start = b;
- ushort count = 0;
+ ushort cnt = 0;
ushort myx = x;
static int printing = 0;
@@ -2086,7 +2141,7 @@ void console_print(const char * b)
if (!vc_cons_allocated(currcons)) {
/* impossible */
- printk("console_print: tty %d not allocated ??\n", currcons+1);
+ printk("vt_console_print: tty %d not allocated ??\n", currcons+1);
printing = 0;
return;
}
@@ -2096,52 +2151,51 @@ void console_print(const char * b)
/* Contrived structure to try to emulate original need_wrap behaviour
* Problems caused when we have need_wrap set on '\n' character */
-
- while ((c = *(b++)) != 0) {
- if (c == 10 || c == 13 || c == 8 || need_wrap) {
- if ((count = b - start - 1) > 0) {
- sw->con_putcs(vc_cons[currcons].d, start, count ,
- y, x);
- x += count;
- if (need_wrap)
- x--;
- }
-
- if (c == 8) { /* backspace */
- bs(currcons);
- start = b;
- myx = x;
- continue;
+
+ while (count-- > 0) {
+ c = *(b++);
+ if (c == 10 || c == 13 || c == 8 || need_wrap) {
+ if ((cnt = b - start - 1) > 0) {
+ sw->con_putcs(vc_cons[currcons].d,
+ start, cnt, y, x);
+ x += cnt;
+ if (need_wrap)
+ x--;
+ }
+
+ if (c == 8) { /* backspace */
+ bs(currcons);
+ start = b;
+ myx = x;
+ continue;
+ }
+ if (c != 13)
+ lf(currcons);
+ cr(currcons);
+
+ if (c == 10 || c == 13) {
+ start = b; myx = x; continue;
+ }
+
+ start = b-1; myx = x;
+ }
+
+ *pos = c | (attr << 8);
+ if (myx == cols - 1) {
+ need_wrap = 1;
+ continue;
}
- if (c != 13)
- lf(currcons);
- cr(currcons);
-
- if (c == 10 || c == 13) {
- start = b; myx = x; continue;
- }
-
- start = b-1; myx = x;
- }
-
- *pos = c | (attr << 8);
- if (myx == cols - 1) {
- need_wrap = 1;
- continue;
- }
- pos++;
- myx++;
+ pos++;
+ myx++;
}
- if ((count = b - start -1) > 0) {
- sw->con_putcs(vc_cons[currcons].d, start, count ,
- y, x);
- x += count;
- if (x == cols)
- {
- x--;
- need_wrap = 1;
- }
+ if ((cnt = b - start) > 0) {
+ sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
+ x += cnt;
+ if (x == cols){
+ x--;
+ need_wrap = 1;
+ }
}
set_cursor(currcons);
@@ -2149,6 +2203,18 @@ void console_print(const char * b)
printing = 0;
}
+static int vt_console_device(void)
+{
+ return MKDEV(TTY_MAJOR, fg_console + 1);
+}
+
+extern void keyboard_wait_for_keypress(void);
+
+struct console vt_console_driver = {
+ vt_console_print, do_unblank_screen,
+ keyboard_wait_for_keypress, vt_console_device
+};
+#endif
/*
* con_throttle and con_unthrottle are only used for
@@ -2219,7 +2285,7 @@ static void console_bh(void)
*/
unsigned long con_init(unsigned long kmem_start)
{
- char *display_desc = "????";
+ const char *display_desc = "????";
unsigned int currcons = 0;
extern int serial_debug;
@@ -2293,14 +2359,15 @@ unsigned long con_init(unsigned long kmem_start)
printable = 1;
/* If "serdebug" cmd line option was present, don't register for printk */
+#ifdef CONFIG_VT_CONSOLE
if (!serial_debug)
- register_console(console_print);
+ register_console(&vt_console_driver);
printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
can_do_color ? "colour":"mono",
display_desc,
cols,rows,
MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
-
+#endif
init_bh(CONSOLE_BH, console_bh);
return kmem_start;
}
@@ -2466,7 +2533,7 @@ static void unblank_screen(void)
/*
* Allocate the console screen memory.
*/
-int con_open(struct tty_struct *tty, struct file * filp)
+static int con_open(struct tty_struct *tty, struct file * filp)
{
unsigned int currcons;
int i;
@@ -2603,7 +2670,7 @@ int con_adjust_height(unsigned long fontheight)
return -EINVAL;
}
-void set_vesa_blanking(int arg)
+static void set_vesa_blanking(unsigned long arg)
{
char *argp = (char *)arg + 1;
unsigned int mode;
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 603afe9ab..2cb35e67f 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -52,6 +52,10 @@
#include <linux/linkage.h>
#include <asm/setup.h>
#include <asm/segment.h>
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+.globl SYMBOL_NAME(kgdb_registers)
+#endif
LENOSYS = 38
@@ -66,7 +70,7 @@ LTASK_BLOCKED = 16
LTASK_FLAGS = 20
/* the following macro is used when enabling interrupts */
-#if defined(CONFIG_ATARI_ONLY)
+#if defined(MACH_ATARI_ONLY)
/* block out HSYNC on the atari */
#define ALLOWINT 0xfbff
#define MAX_NOINT_IPL 3
@@ -87,11 +91,23 @@ LFORMATVEC = 0x2E
* regs are a2-a6 and d6-d7 preserved by C code
* the kernel doesn't mess with usp unless it needs to
*/
+#ifndef CONFIG_KGDB
#define SAVE_ALL \
clrl %sp@-; /* stk_adj */ \
movel %d0,%sp@-; /* orig d0 */ \
movel %d0,%sp@-; /* d0 */ \
moveml %d1-%d5/%a0-%a1,%sp@-
+#else
+/* Need to save the "missing" registers for kgdb...
+ */
+#define SAVE_ALL \
+ clrl %sp@-; /* stk_adj */ \
+ movel %d0,%sp@-; /* orig d0 */ \
+ movel %d0,%sp@-; /* d0 */ \
+ moveml %d1-%d5/%a0-%a1,%sp@-; \
+ moveml %d6-%d7,SYMBOL_NAME(kgdb_registers)+GDBOFFA_D6; \
+ moveml %a2-%a6,SYMBOL_NAME(kgdb_registers)+GDBOFFA_A2
+#endif
#define RESTORE_ALL \
moveml %sp@+,%a0-%a1/%d1-%d5; \
@@ -148,37 +164,18 @@ ENTRY(reschedule)
pea SYMBOL_NAME(ret_from_exception)
jmp SYMBOL_NAME(schedule)
-ENTRY(system_call)
- SAVE_ALL
- movel #-LENOSYS,LD0(%sp) | default return value in d0
- | original D0 is in orig_d0
- movel %d0,%d2
-
- | save top of frame
- pea %sp@
- jbsr SYMBOL_NAME(set_esp0)
- addql #4,%sp
-
- cmpl #NR_syscalls,%d2
- jcc SYMBOL_NAME(ret_from_exception)
- lea SYMBOL_NAME(sys_call_table),%a0
- movel %a0@(%d2:l:4),%d3
- jeq SYMBOL_NAME(ret_from_exception)
- movel SYMBOL_NAME(current_set),%a0
- btst #5,%a0@(LTASK_FLAGS+3) | PF_TRACESYS
- bnes 1f
- movel %d3,%a0
- jbsr %a0@
- movel %d0,%sp@(LD0) | save the return value
+badsys:
+ movel #-LENOSYS,LD0(%sp)
jra SYMBOL_NAME(ret_from_exception)
-1:
+
+do_trace:
+ movel #-LENOSYS,LD0(%sp) | needed for strace
subql #4,%sp
SAVE_SWITCH_STACK
jbsr SYMBOL_NAME(syscall_trace)
RESTORE_SWITCH_STACK
addql #4,%sp
- movel %d3,%a0
- jbsr %a0@
+ jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
movel %d0,%sp@(LD0) | save the return value
subql #4,%sp | dummy return address
SAVE_SWITCH_STACK
@@ -187,6 +184,24 @@ ENTRY(system_call)
SYMBOL_NAME_LABEL(ret_from_signal)
RESTORE_SWITCH_STACK
addql #4,%sp
+ jra SYMBOL_NAME(ret_from_exception)
+
+ENTRY(system_call)
+ SAVE_ALL
+ movel %d0,%d2
+
+ | save top of frame
+ pea %sp@
+ jbsr SYMBOL_NAME(set_esp0)
+ addql #4,%sp
+
+ cmpl #NR_syscalls,%d2
+ jcc badsys
+ movel SYMBOL_NAME(current_set),%a0
+ btst #5,%a0@(LTASK_FLAGS+3) | PF_TRACESYS
+ jne do_trace
+ jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
+ movel %d0,%sp@(LD0) | save the return value
SYMBOL_NAME_LABEL(ret_from_exception)
btst #5,%sp@(LSR) | check if returning to kernel
@@ -197,17 +212,8 @@ SYMBOL_NAME_LABEL(ret_from_exception)
cmpl #SYMBOL_NAME(task),%a0 | task[0] cannot have signals
jeq 2f
bclr #5,%a0@(LTASK_FLAGS+1) | check for delayed trace
- jeq 1f
- bclr #7,%sp@(LSR) | clear trace bit in SR
- pea 1 | send SIGTRAP
- movel %a0,%sp@-
- pea 5
- jbsr SYMBOL_NAME(send_sig)
- addql #8,%sp
- addql #4,%sp
- movel SYMBOL_NAME(current_set),%a0
-
-1:
+ jne do_delayed_trace
+5:
tstl %a0@(LTASK_STATE) | state
jne SYMBOL_NAME(reschedule)
tstl %a0@(LTASK_COUNTER) | counter
@@ -234,6 +240,17 @@ Lsignal_return:
addql #4,%sp
RESTORE_ALL
+do_delayed_trace:
+ bclr #7,%sp@(LSR) | clear trace bit in SR
+ pea 1 | send SIGTRAP
+ movel %a0,%sp@-
+ pea 5
+ jbsr SYMBOL_NAME(send_sig)
+ addql #8,%sp
+ addql #4,%sp
+ movel SYMBOL_NAME(current_set),%a0
+ jra 5b
+
/*
** This is the main interrupt handler, responsible for calling process_int()
*/
@@ -243,7 +260,7 @@ SYMBOL_NAME_LABEL(inthandler)
movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field
| signifies that the stack frame
| is NOT for syscall
- addql #1,SYMBOL_NAME(intr_count)
+ addql #1,SYMBOL_NAME(local_irq_count)
| put exception # in d0
bfextu %sp@(LFORMATVEC){#4,#10},%d0
@@ -254,27 +271,26 @@ SYMBOL_NAME_LABEL(inthandler)
SYMBOL_NAME_LABEL(ret_from_interrupt)
/* check if we need to do software interrupts */
-1:
- movel SYMBOL_NAME(intr_count),%d1
+ movel SYMBOL_NAME(local_irq_count),%d1
subql #1,%d1
jne 4f
- bfextu %sp@(LSR){#5,#3},%d0 | Check for nested interrupt.
+#if 0
+ bfextu %sp@(LSR){#5,#3},%d0 | Check for nested interrupt.
#if MAX_NOINT_IPL > 0
cmpiw #MAX_NOINT_IPL,%d0
#endif
jhi 4f
-2:
+#endif
movel SYMBOL_NAME(bh_active),%d0
andl SYMBOL_NAME(bh_mask),%d0
- jne 3f
+ jeq 3f
- clrl SYMBOL_NAME(intr_count) | deliver signals, reschedule etc..
- jra SYMBOL_NAME(ret_from_exception)
-3:
jbsr SYMBOL_NAME(do_bottom_half)
- jbra 2b
+3:
+ clrl SYMBOL_NAME(local_irq_count)
+ jra SYMBOL_NAME(ret_from_exception)
4:
- movel %d1,SYMBOL_NAME(intr_count)
+ movel %d1,SYMBOL_NAME(local_irq_count)
RESTORE_ALL
@@ -338,8 +354,10 @@ SYMBOL_NAME_LABEL(resume)
/* save sr */
movew %sr,%a0@(LTSS_SR)
+#if 0
/* disable interrupts */
oriw #0x0700,%sr
+#endif
/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
movec %sfc,%d0
@@ -360,18 +378,18 @@ SYMBOL_NAME_LABEL(resume)
fsave %a0@(LTSS_FPCTXT+27*4)
#if defined(CONFIG_M68060)
-#if !defined(CONFIG_M68060_ONLY)
- btst #3,SYMBOL_NAME(boot_info)+BI_cputype+3
+#if !defined(CPU_M68060_ONLY)
+ btst #3,SYMBOL_NAME(m68k_cputype)+3
beqs 1f
#endif
/* The 060 FPU keeps status in bits 15-8 of the first longword */
tstb %a0@(LTSS_FPCTXT+27*4+2)
jeq 3f
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
jra 2f
#endif
#endif /* CONFIG_M68060 */
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
1: tstb %a0@(LTSS_FPCTXT+27*4)
jeq 3f
#endif
@@ -387,12 +405,12 @@ SYMBOL_NAME_LABEL(resume)
tstb %d2
jne 4f
-#if defined(CONFIG_M68020_OR_M68030) && defined(CONFIG_M68040_OR_M68060)
+#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
/* 68040 or 68060 ? */
tstl SYMBOL_NAME(m68k_is040or060)
bnes 1f
#endif
-#if defined(CONFIG_M68020_OR_M68030)
+#if defined(CPU_M68020_OR_M68030)
/*
* switch address space
*/
@@ -406,49 +424,51 @@ SYMBOL_NAME_LABEL(resume)
pmove %a1@(LTSS_CRP),%crp
#endif
-#if defined(CONFIG_M68020_OR_M68030) && defined(CONFIG_M68040_OR_M68060)
+#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
jra 2f /* skip m68040 stuff */
1:
#endif
-#if defined(CONFIG_M68040_OR_M68060)
+#if defined(CPU_M68040_OR_M68060)
/*
* switch address space
*/
+ .chip 68040
/* flush address translation cache (user entries) */
- .word 0xf510 /* pflushan */
+ pflushan
/* switch the root pointer */
movel %a1@(LTSS_CRP+4),%d0
- .long 0x4e7b0806 /* movec d0,urp */
+ movec %d0,%urp
#if defined (CONFIG_M68060)
/* is it a '060 ? */
- btst #3,SYMBOL_NAME(boot_info)+BI_cputype+3
+ btst #3,SYMBOL_NAME(m68k_cputype)+3
beqs 2f
/* clear user entries in the branch cache */
movec %cacr,%d0
orl #0x00200000,%d0
movec %d0,%cacr
#endif /* CONFIG_M68060 */
-#endif /* CONFIG_M68040_OR_M68060 */
+ .chip 68k
+#endif /* CPU_M68040_OR_M68060 */
2:
4:
/* restore floating point context */
#if defined(CONFIG_M68060)
-#if !defined(CONFIG_M68060_ONLY)
- btst #3,SYMBOL_NAME(boot_info)+BI_cputype+3
+#if !defined(CPU_M68060_ONLY)
+ btst #3,SYMBOL_NAME(m68k_cputype)+3
beqs 1f
#endif
/* The 060 FPU keeps status in bits 15-8 of the first longword */
tstb %a1@(LTSS_FPCTXT+27*4+2)
jeq 3f
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
jra 2f
#endif
#endif /* CONFIG_M68060 */
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
1: tstb %a1@(LTSS_FPCTXT+27*4)
jeq 3f
#endif
@@ -592,7 +612,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall) /* iopl for i386 */ /* 110 */
.long SYMBOL_NAME(sys_vhangup)
.long SYMBOL_NAME(sys_idle)
- .long SYMBOL_NAME(sys_ni_syscall) /* vm86 for i386 */
+ .long SYMBOL_NAME(sys_ni_syscall) /* vm86old for i386 */
.long SYMBOL_NAME(sys_wait4)
.long SYMBOL_NAME(sys_swapoff) /* 115 */
.long SYMBOL_NAME(sys_sysinfo)
@@ -644,5 +664,11 @@ SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_nanosleep)
.long SYMBOL_NAME(sys_mremap)
.long SYMBOL_NAME(sys_setresuid)
- .long SYMBOL_NAME(sys_getresuid)
- .space (NR_syscalls-165)*4
+ .long SYMBOL_NAME(sys_getresuid) /* 165 */
+ .long SYMBOL_NAME(sys_ni_syscall) /* for vm86 */
+ .long SYMBOL_NAME(sys_query_module)
+ .long SYMBOL_NAME(sys_poll)
+ .long SYMBOL_NAME(sys_nfsservctl)
+ .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 3dab4b2eb..c2b72aa2d 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -67,11 +67,13 @@
#include <linux/config.h>
#include <linux/linkage.h>
+#include <asm/bootinfo.h>
#include <asm/setup.h>
#include <asm/pgtable.h>
.globl SYMBOL_NAME(kernel_pg_dir), SYMBOL_NAME(kpt)
.globl SYMBOL_NAME(availmem), SYMBOL_NAME(is_medusa)
+.globl SYMBOL_NAME(is_hades)
.globl SYMBOL_NAME(m68k_pgtable_cachemode)
.globl SYMBOL_NAME(kernel_pmd_table), SYMBOL_NAME(swapper_pg_dir)
@@ -178,21 +180,29 @@ ENTRY(_start)
lea %pc@(SYMBOL_NAME(_stext):w),%sp
/*
- * Copy bootinfo from position after BSS to final resting place
- */
- lea %pc@(SYMBOL_NAME(_end)),%a0
- lea %pc@(SYMBOL_NAME(boot_info)),%a1
- movel %pc@(SYMBOL_NAME(bisize)),%d0
- subql #1,%d0
-1: moveb %a0@+,%a1@+
- dbra %d0,1b
-
-/*
* Record the CPU and machine type.
*/
- lea %pc@(SYMBOL_NAME(boot_info)),%a0
- movel %a0@(BI_machtype),%d4
- movel %a0@(BI_cputype),%d0
+
+ movew #BI_MACHTYPE,%d0
+ jbsr Lget_bi_record
+ movel %a0@,%d4
+ lea %pc@(SYMBOL_NAME(m68k_machtype)),%a0
+ movel %d4,%a0@
+ movew #BI_FPUTYPE,%d0
+ jbsr Lget_bi_record
+ movel %a0@,%d0
+ lea %pc@(SYMBOL_NAME(m68k_fputype)),%a0
+ movel %d0,%a0@
+ movew #BI_MMUTYPE,%d0
+ jbsr Lget_bi_record
+ movel %a0@,%d0
+ lea %pc@(SYMBOL_NAME(m68k_mmutype)),%a0
+ movel %d0,%a0@
+ movew #BI_CPUTYPE,%d0
+ jbsr Lget_bi_record
+ movel %a0@,%d0
+ lea %pc@(SYMBOL_NAME(m68k_cputype)),%a0
+ movel %d0,%a0@
btst #CPUB_68060,%d0
jeq 1f
@@ -226,18 +236,68 @@ ENTRY(_start)
#endif
/*
+ If running on an Atari, determine the I/O base of the
+ serial port and test if we are running on a Medusa or Hades.
+ This test is necessary here, because on the Hades the serial
+ port is only accessible in the high I/O memory area.
+
+ The test whether it is a Medusa is done by writing to the byte at
+ phys. 0x0. This should result in a bus error on all other machines.
+
+ ...should, but doesn't. The Afterburner040 for the Falcon has the
+ same behaviour (0x0..0x7 are no ROM shadow). So we have to do
+ another test to distinguish Medusa and AB040. This is a
+ read attempt for 0x00ff82fe phys. that should bus error on a Falcon
+ (+AB040), but is in the range where the Medusa always asserts DTACK.
+
+ The test for the Hades is done by reading address 0xb0000000. This
+ should give a bus error on the Medusa.
+ */
+
+#ifdef CONFIG_ATARI
+ is_not_atari(Lnotypetest)
+
+ moveq #0,%d3 /* base addr for others: 0x00000000 */
+ moveq #0,%d2 /* no Hades */
+ movec %d3,%vbr
+ lea %pc@(Ltest_berr),%a0
+ movel %a0,0x8
+ movel %sp,%a0
+ moveb 0x0,%d1
+ clrb 0x0
+ nop
+ moveb %d1,0x0
+ nop
+ tstb 0x00ff82fe
+ nop
+ movel #0xff000000,%d3 /* Medusa base addr: 0xff000000 */
+ tstb 0xb0000000
+ nop
+ movel #0xff000000,%d2 /* Computer is a Hades */
+ moveq #0,%d3
+Ltest_berr:
+ movel %a0,%sp
+ lea %pc@(SYMBOL_NAME(is_hades)),%a0
+ movel %d2,%a0@
+ lea %pc@(SYMBOL_NAME(is_medusa)),%a0
+ movel %d3,%a0@
+Lnotypetest:
+#endif
+
+/*
* Initialize serial port
*/
+
jbsr Lserial_init
putr()
putc('A')
/*
- * Get address at end of kernel code/data/bss and
- * mask off at a page boundary.
+ * Get address at end of bootinfo and mask off at a page boundary.
*/
- lea %pc@(SYMBOL_NAME(_end)),%a0
+ moveq #0,%d0
+ jbsr Lget_bi_record
addw #PAGESIZE-1,%a0
movel %a0,%d0
andl #-PAGESIZE,%d0
@@ -250,10 +310,6 @@ ENTRY(_start)
*/
lea %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
movel %a0,%d5
-#ifdef HACKER_KERNEL
- lea %pc@(Lkernel_start),%a0
- movel %d5,%a0@
-#endif
/*
* initialize the kernel root table.
@@ -486,35 +542,16 @@ Lnotami:
For the Medusa it is better to map the I/O region transparently
(i.e. 0xffxxxxxx -> 0xffxxxxxx), because some I/O registers are
- accessible only in the high area. The test whether it is a Medusa
- is done by writing to the byte at phys. 0x0. This should result
- in a bus error on all other machines.
+ accessible only in the high area.
- ...should, but doesn't. The Afterburner040 for the Falcon has the
- same behaviour (0x0..0x7 are no ROM shadow). So we have to do
- another test to distinguish Medusa and AB040. This is a
- read attempt for 0x00ff82fe phys. that should bus error on a Falcon
- (+AB040), but is in the range where the Medusa always asserts DTACK.
+ On the Hades all I/O registers are only accessible in the high
+ area.
*/
- moveq #0,%d3 /* base addr for others: 0x00000000 */
- movec %d3,%vbr
- lea %pc@(Ltest_berr),%a0
- movel %a0,0x8
- movel %sp,%a0
- moveb 0x0,%d1
- clrb 0x0
- nop
- moveb %d1,0x0
- nop
- tstb 0x00ff82fe
- nop
- movel #0xff000000,%d3 /* Medusa base addr: 0xff000000 */
-Ltest_berr:
- movel %a0,%sp
- lea %pc@(SYMBOL_NAME(is_medusa)),%a0
- movel %d3,%a0@
-
+ movel %pc@(is_medusa),%d3
+ bne 1f
+ movel %pc@(is_hades),%d3
+1:
/* Let the root table point to the new pointer table */
lea %a4@(PTR_TABLE_SIZE<<2),%a4
movel %a4,%a0
@@ -637,45 +674,47 @@ Lmapphys:
/* no limit, 4byte descriptors */
movel #0x80000002,%a3@
movel %a5,%a3@(4)
- .long 0xf0134800 /* pmove %a3@,%srp */
- .long 0xf0134c00 /* pmove %a3@,%crp */
- .long 0xf0002400 /* pflusha */
+ 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@
- .long 0xf0134000 /* pmove %a3@,%tc (enable the MMU) */
+ pmove %a3@,%tc /* enable the MMU */
tstl %d0
jne 1f
jmp %pc@(2f+0x80000000)
1: jmp 2f:w
2: movel %d2,%a5@(%d0:w)
- .long 0xf0002400 /* pflusha */
+ pflusha
jmp LdoneMMUenable:w
Lamimmu68040:
+ .chip 68040
lea 2f:w,%a0
movel %d5,%d0
andl #0xff000000,%d0
jne 1f
lea %pc@(2f+0x80000000),%a0
1: orw #TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
- .long 0x4e7b0004 /* movec %d0,%itt0 */
- .long 0x4e7bd806 /* movec %a5,%urp */
- .long 0x4e7bd807 /* movec %a5,%srp */
- .word 0xf518 /* pflusha */
+ movec %d0,%itt0
+ movec %a5,%urp
+ movec %a5,%srp
+ pflusha
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) */
+ movec %d0,%tc /* enable the MMU */
jmp %a0@
2: moveq #0,%d0
- .long 0x4e7b0004 /* movec %d0,%itt0 */
+ movec %d0,%itt0
jmp LdoneMMUenable:w
+ .chip 68k
Lmapphysnotamiga:
#endif
@@ -696,6 +735,7 @@ Lmapphysnotamiga:
is_040_or_060(Latarimmu68040)
+ .chip 68030
lea %pc@(Lmmu),%a3
movel %d5,%d0
jne 1f
@@ -706,7 +746,7 @@ Lmapphysnotamiga:
jeq 2f
orw #TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0
movel %d0,%a3@
- .long 0xf0130800 /* pmove %a3@,%tt0 */
+ pmove %a3@,%tt0
jra 3f
/* tt0 doesn't work if physical and virtual address of kernel is in
* the same 16M area (Falcon with Magnum/FX, kernel in alternate ram)
@@ -729,23 +769,25 @@ Lmapphysnotamiga:
/* no limit, 4byte descriptors */
3: movel #0x80000002,%a3@
movel %a5,%a3@(4)
- .long 0xf0134800 /* pmove %a3@,%srp */
- .long 0xf0134c00 /* pmove %a3@,%crp */
- .long 0xf0002400 /* pflusha */
+ 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@
- .long 0xf0134000 /* pmove %a3@,%tc (enable the MMU) */
+ pmove %a3@,%tc /* enable the MMU */
jmp %a0@
4: clrl %a3@
- .long 0xf0130800 /* pmove %a3@,%tt0 */
+ pmove %a3@,%tt0
jra LdoneMMUenable
5: movel %d2,%a1@
jra LdoneMMUenable
+ .chip 68k
Latarimmu68040:
+ .chip 68040
movel %d5,%d0
jne 1f
lea LdoneMMUenable:w,%a0
@@ -753,22 +795,22 @@ Latarimmu68040:
1: lea 3f:w,%a0
andl #0xff000000,%d0 /* logical address base */
orw #TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
- .long 0x4e7b0004 /* movec %d0,%itt0 */
+ movec %d0,%itt0
2: nop
- .word 0xf518 /* pflusha */
- .long 0x4e7bd807 /* movec %a5,%srp */
- .long 0x4e7bd806 /* movec %a5,%urp */
+ pflusha
+ movec %a5,%srp
+ 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) */
+ movec %d0,%tc /* enable the MMU */
jmp %a0@
3: moveq #0,%d0
- .long 0x4e7b0004 /* movec %d0,%itt0 */
- tstl %a1
+ movec %d0,%itt0
jra LdoneMMUenable
+ .chip 68k
Lmapphysnotatari:
#endif
@@ -830,7 +872,9 @@ LdoneMMUenable:
jra 1f
Lcache680460:
- .word 0xf4f8 /* cpusha %bc */
+ .chip 68040
+ cpusha %bc
+ .chip 68k
is_060(Lcache68060)
@@ -840,12 +884,14 @@ Lcache680460:
jra 1f
Lcache68060:
+ .chip 68060
movel #CC6_ENABLE_D+CC6_ENABLE_I+CC6_ENABLE_SB+CC6_PUSH_DPI+CC6_ENABLE_B+CC6_CLRA_B,%d0
/* MMU stuff works in copyback mode now, so enable the cache */
movec %d0,%cacr
/* enable superscalar dispatch in PCR */
moveq #1,%d0
- .long 0x4e7b0808 /* movec d0,pcr */
+ movec %d0,%pcr
+ .chip 68k
1:
/*
@@ -859,43 +905,26 @@ Lcache68060:
jbsr SYMBOL_NAME(start_kernel)
/*
- * switch off mmu and exit
+ * Find a tag record in the bootinfo structure
+ * The bootinfo structure is located right after the kernel bss
+ * Returns: d0: size (-1 if not found)
+ * a0: data pointer (end-of-records if not found)
*/
-
-#ifdef HACKER_KERNEL
-ENTRY(kernel_exit)
- lea 2f:w,%a0
- movel %pc@(Lkernel_start),%a0
- lea %a0@(2f:w),%a1
- movel %a1,%d0
- andl #0xff000000,%d0
- jne 1f
- jmp %a0@(1f+0x80000000)
-1: orw #TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
- .long 0x4e7b0004 /* movec %d0,%itt0 */
- jmp %a1@
+Lget_bi_record:
+ lea %pc@(SYMBOL_NAME(_end)),%a0
+1: tstw %a0@(BIR_tag)
+ jeq 3f
+ cmpw %a0@(BIR_tag),%d0
+ jeq 2f
+ addw %a0@(BIR_size),%a0
+ jra 1b
2: moveq #0,%d0
- .long 0x4e7b0003 /* movec %d0,%tc (disable the MMU) */
- .word 0xf518 /* pflusha */
- .long 0x4e7b0004 /* movec %d0,%itt0 */
- movec %d0,%cacr
- .word 0xf4f8 /* cpusha %bc */
-
- lea %pc@(SYMBOL_NAME(boot_info)),%a0
- jmp %a0@(BI_amiga_exit_func:w)@(0:w)
-#endif
-
-/*
- * Serial port output support.
- */
-LSERPER = 0xdff032
-LSERDAT = 0xdff030
-LSERDATR = 0xdff018
-LNTSC_PERIOD = 371
-LPAL_PERIOD = 368
-LNTSC_ECLOCK = 7159090
-LSERIAL_CNTRL = 0xbfd000
-LSERIAL_DTR = 7
+ movew %a0@(BIR_size),%d0
+ lea %a0@(BIR_data),%a0
+ rts
+3: moveq #-1,%d0
+ lea %a0@(BIR_size),%a0
+ rts
/*
* Debug output support
@@ -953,8 +982,18 @@ LMFP_UDR = 0xfffa2f
#endif
/*
+ * Serial port output support.
+ */
+LSERPER = 0xdff032
+LSERDAT = 0xdff030
+LSERDATR = 0xdff018
+LSERIAL_CNTRL = 0xbfd000
+LSERIAL_DTR = 7
+
+/*
* Initialize serial port hardware for 9600/8/1
* a0 thrashed
+ * Amiga d0 trashed
* Atari d0 trashed (a1 in case of SCC)
*/
.even
@@ -962,31 +1001,30 @@ Lserial_init:
#ifdef CONFIG_AMIGA
cmpil #MACH_AMIGA,%d4
jne 1f
- lea %pc@(SYMBOL_NAME(boot_info)),%a0
bclr #LSERIAL_DTR,LSERIAL_CNTRL
- movew #LNTSC_PERIOD,LSERPER
- cmpl #LNTSC_ECLOCK,%a0@(BI_amiga_eclock)
- jeq 9f
- movew #LPAL_PERIOD,LSERPER
+ movew #BI_AMIGA_SERPER,%d0
+ jbsr Lget_bi_record
+ movew %a0@,LSERPER
jra 9f
1:
#endif
#ifdef CONFIG_ATARI
cmpil #MACH_ATARI,%d4
jne 4f
+ movel %pc@(Liobase),%a1
#ifdef USE_PRINTER
- bclr #0,LSTMFP_IERB
- bclr #0,LSTMFP_DDR
- moveb #LPSG_CONTROL,LPSG_SELECT
- moveb #0xff,LPSG_WRITE
- moveb #LPSG_IO_B,LPSG_SELECT
- clrb LPSG_WRITE
- moveb #LPSG_IO_A,LPSG_SELECT
- moveb LPSG_READ,%d0
+ bclr #0,%a1@(LSTMFP_IERB)
+ bclr #0,%a1@(LSTMFP_DDR)
+ moveb #LPSG_CONTROL,%a1@(LPSG_SELECT)
+ moveb #0xff,%a1@(LPSG_WRITE)
+ moveb #LPSG_IO_B,%a1@(LPSG_SELECT)
+ clrb %a1@(LPSG_WRITE)
+ moveb #LPSG_IO_A,%a1@(LPSG_SELECT)
+ moveb %a1@(LPSG_READ),%d0
bset #5,%d0
- moveb %d0,LPSG_WRITE
+ moveb %d0,%a1@(LPSG_WRITE)
#elif defined(USE_SCC)
- lea LSCC_CTRL_B,%a0
+ lea %a1@(LSCC_CTRL_B),%a0
lea %pc@(scc_initable:w),%a1
2: moveb %a1@+,%d0
jmi 3f
@@ -995,12 +1033,12 @@ Lserial_init:
jra 2b
3: clrb %a0@
#elif defined(USE_MFP)
- bclr #1,LMFP_TSR
- moveb #0x88,LMFP_UCR
- andb #0x70,LMFP_TDCDR
- moveb #2,LMFP_TDDR
- orb #1,LMFP_TDCDR
- bset #1,LMFP_TSR
+ bclr #1,%a1@(LMFP_TSR)
+ moveb #0x88,%a1@(LMFP_UCR)
+ andb #0x70,%a1@(LMFP_TDCDR)
+ moveb #2,%a1@(LMFP_TDDR)
+ orb #1,%a1@(LMFP_TDCDR)
+ bset #1,%a1@(LMFP_TSR)
#endif
4:
#endif
@@ -1073,8 +1111,6 @@ Lserial_puts:
/*
* Output number in d7 in hex notation on serial port.
- * d0-d2 trashed.
- * d7 trashed.
*/
Lserial_putnum:
@@ -1103,7 +1139,7 @@ Lshowtest:
putc('=')
putn(%a1)
- .long 0xf0119f15 | ptestr #5,%a1@,#7,%a0
+ ptestr #5,%a1@,#7,%a0
putc('D')
putc('A')
@@ -1117,7 +1153,7 @@ Lshowtest:
putc('S')
putc('=')
lea %pc@(Lmmu),%a0
- .long 0xf0106200 | pmove %psr,%a0@
+ pmove %psr,%a0@
clrl %d7
movew %a0@,%d7
jbsr Lserial_putnum
@@ -1128,10 +1164,6 @@ Lshowtest:
.data
.even
-#ifdef HACKER_KERNEL
-Lkernel_start:
- .long 0
-#endif
Lcustom:
Liobase:
.long 0
@@ -1142,5 +1174,7 @@ SYMBOL_NAME_LABEL(availmem)
.long 0
SYMBOL_NAME_LABEL(is_medusa)
.long 0
+SYMBOL_NAME_LABEL(is_hades)
+ .long 0
SYMBOL_NAME_LABEL(m68k_pgtable_cachemode)
.long 0
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 8656b2979..f49c38cd3 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -50,6 +50,24 @@ volatile unsigned int num_spurious;
#define NUM_IRQ_NODES 100
static irq_node_t nodes[NUM_IRQ_NODES];
+unsigned int local_irq_count[NR_CPUS];
+
+int __m68k_bh_counter;
+
+static void dummy_enable_irq(unsigned int irq);
+static void dummy_disable_irq(unsigned int irq);
+static int dummy_request_irq(unsigned int irq,
+ void (*handler) (int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id);
+static void dummy_free_irq(unsigned int irq, void *dev_id);
+
+void (*enable_irq) (unsigned int) = dummy_enable_irq;
+void (*disable_irq) (unsigned int) = dummy_disable_irq;
+
+int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
+ unsigned long, const char *, void *) = dummy_request_irq;
+void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
+
/*
* void init_IRQ(void)
*
@@ -92,14 +110,30 @@ irq_node_t *new_irq_node(void)
return NULL;
}
-int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
- unsigned long flags, const char *devname, void *dev_id)
+/*
+ * We will keep these functions until I have convinced Linus to move
+ * the declaration of them from include/linux/sched.h to
+ * include/asm/irq.h.
+ */
+int request_irq(unsigned int irq,
+ void (*handler) (int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
{
- if (irq & IRQ_MACHSPEC)
- return mach_request_irq(IRQ_IDX(irq), handler, flags, devname, dev_id);
+ return mach_request_irq(irq, handler, flags, devname, dev_id);
+}
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+ mach_free_irq(irq, dev_id);
+}
+int sys_request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
+{
if (irq < IRQ1 || irq > IRQ7) {
- printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
+ printk("%s: Incorrect IRQ %d from %s\n",
+ __FUNCTION__, irq, devname);
return -ENXIO;
}
@@ -109,7 +143,7 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
__FUNCTION__, irq, irq_list[irq].devname);
return -EBUSY;
}
- if (flags & IRQ_FLG_REPLACE) {
+ if (!(flags & IRQ_FLG_REPLACE)) {
printk("%s: %s can't replace IRQ %d from %s\n",
__FUNCTION__, devname, irq, irq_list[irq].devname);
return -EBUSY;
@@ -122,13 +156,8 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
return 0;
}
-void free_irq(unsigned int irq, void *dev_id)
+void sys_free_irq(unsigned int irq, void *dev_id)
{
- if (irq & IRQ_MACHSPEC) {
- mach_free_irq(IRQ_IDX(irq), dev_id);
- return;
- }
-
if (irq < IRQ1 || irq > IRQ7) {
printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
return;
@@ -157,31 +186,42 @@ int probe_irq_off (unsigned long irqs)
return 0;
}
-void enable_irq(unsigned int irq)
+static void dummy_enable_irq(unsigned int irq)
+{
+ printk("calling uninitialized enable_irq()\n");
+}
+
+static void dummy_disable_irq(unsigned int irq)
+{
+ printk("calling uninitialized disable_irq()\n");
+}
+
+static int dummy_request_irq(unsigned int irq,
+ void (*handler) (int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
{
- if ((irq & IRQ_MACHSPEC) && mach_enable_irq)
- mach_enable_irq(IRQ_IDX(irq));
+ printk("calling uninitialized request_irq()\n");
+ return 0;
}
-void disable_irq(unsigned int irq)
+static void dummy_free_irq(unsigned int irq, void *dev_id)
{
- if ((irq & IRQ_MACHSPEC) && mach_disable_irq)
- mach_disable_irq(IRQ_IDX(irq));
+ printk("calling uninitialized disable_irq()\n");
}
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) {
+ vec -= VEC_SPUR;
+ kstat.interrupts[vec]++;
+ irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
+ } else {
if (mach_process_int)
mach_process_int(vec, fp);
else
panic("Can't process interrupt vector %ld\n", vec);
return;
}
-
- vec -= VEC_SPUR;
- kstat.interrupts[vec]++;
- irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
}
int get_irq_list(char *buf)
diff --git a/arch/m68k/kernel/ksyms.c b/arch/m68k/kernel/ksyms.c
deleted file mode 100644
index bf067c782..000000000
--- a/arch/m68k/kernel/ksyms.c
+++ /dev/null
@@ -1,89 +0,0 @@
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/semaphore.h>
-
-asmlinkage long long __ashrdi3 (long long, int);
-extern char m68k_debug_device[];
-
-#ifdef CONFIG_ATARI
-extern void mach_atari_syms_export (void);
-#endif
-#ifdef CONFIG_AMIGA
-extern void mach_amiga_syms_export (void);
-#endif
-#ifdef CONFIG_MAC
-extern void mach_mac_syms_export (void);
-#endif
-
-extern void dump_thread(struct pt_regs *, struct user *);
-extern int dump_fpu(elf_fpregset_t *);
-
-static struct symbol_table arch_symbol_table = {
-#include <linux/symtab_begin.h>
- /* platform dependent support */
-
- X(memcmp),
- X(boot_info),
- X(m68k_is040or060),
- X(cache_push),
- X(cache_push_v),
- X(cache_clear),
- X(mm_vtop),
- X(mm_ptov),
- X(mm_end_of_chunk),
- X(m68k_debug_device),
- X(request_irq),
- X(free_irq),
- X(dump_fpu),
- X(dump_thread),
- X(strnlen),
- X(strrchr),
-
- /* The following are special because they're not called
- explicitly (the C compiler generates them). Fortunately,
- their interface isn't gonna change any time soon now, so
- it's OK to leave it out of version control. */
- XNOVERS(__ashrdi3),
- XNOVERS(memcpy),
- XNOVERS(memset),
-
- XNOVERS(__down_failed),
- XNOVERS(__up_wakeup),
-
-#include <linux/symtab_end.h>
-};
-
-void arch_syms_export(void)
-{
- register_symtab(&arch_symbol_table);
-
- switch (boot_info.machtype) {
-#ifdef CONFIG_ATARI
- case MACH_ATARI:
- mach_atari_syms_export();
- break;
-#endif
-#ifdef CONFIG_AMIGA
- case MACH_AMIGA:
- mach_amiga_syms_export();
- break;
-#endif
-#ifdef CONFIG_MAC
- case MACH_MAC:
- mach_mac_syms_export();
- break;
-#endif
- default:
- break;
- }
-}
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
new file mode 100644
index 000000000..3138d99df
--- /dev/null
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -0,0 +1,57 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/linkage.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+
+#include <asm/setup.h>
+#include <asm/machdep.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/semaphore.h>
+#include <asm/checksum.h>
+#include <asm/hardirq.h>
+
+asmlinkage long long __ashrdi3 (long long, int);
+extern char m68k_debug_device[];
+
+extern void dump_thread(struct pt_regs *, struct user *);
+extern int dump_fpu(elf_fpregset_t *);
+
+/* platform dependent support */
+
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(m68k_machtype);
+EXPORT_SYMBOL(m68k_cputype);
+EXPORT_SYMBOL(m68k_is040or060);
+EXPORT_SYMBOL(cache_push);
+EXPORT_SYMBOL(cache_push_v);
+EXPORT_SYMBOL(cache_clear);
+EXPORT_SYMBOL(mm_vtop);
+EXPORT_SYMBOL(mm_ptov);
+EXPORT_SYMBOL(mm_end_of_chunk);
+EXPORT_SYMBOL(m68k_debug_device);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(local_irq_count);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy);
+
+/* The following are special because they're not called
+ explicitly (the C compiler generates them). Fortunately,
+ their interface isn't gonna change any time soon now, so
+ it's OK to leave it out of version control. */
+EXPORT_SYMBOL_NOVERS(__ashrdi3);
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memset);
+
+EXPORT_SYMBOL_NOVERS(__down_failed);
+EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
+EXPORT_SYMBOL_NOVERS(__up_wakeup);
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index cc9664b5f..5422831a8 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -14,12 +14,15 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
#include <linux/user.h>
#include <linux/a.out.h>
+#include <linux/reboot.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -34,21 +37,40 @@ asmlinkage void ret_from_exception(void);
*/
asmlinkage int sys_idle(void)
{
+ int ret = -EPERM;
+
+ lock_kernel();
if (current->pid != 0)
- return -EPERM;
+ goto out;
/* endless idle loop with no priority at all */
+ current->priority = -100;
current->counter = -100;
for (;;)
schedule();
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
-void hard_reset_now(void)
+void machine_restart(char * __unused)
{
if (mach_reset)
mach_reset();
}
+void machine_halt(void)
+{
+}
+
+void machine_power_off(void)
+{
+#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
+ apm_set_power_state(APM_STATE_OFF);
+#endif
+}
+
void show_regs(struct pt_regs * regs)
{
printk("\n");
@@ -86,27 +108,36 @@ void flush_thread(void)
asmlinkage int m68k_fork(struct pt_regs *regs)
{
- return do_fork(SIGCHLD, rdusp(), regs);
+ int ret;
+
+ lock_kernel();
+ ret = do_fork(SIGCHLD, rdusp(), regs);
+ unlock_kernel();
+ return ret;
}
asmlinkage int m68k_clone(struct pt_regs *regs)
{
unsigned long clone_flags;
unsigned long newsp;
+ int ret;
+ lock_kernel();
/* syscall2 puts clone_flags in d1 and usp in d2 */
clone_flags = regs->d1;
newsp = regs->d2;
if (!newsp)
newsp = rdusp();
- return do_fork(clone_flags, newsp, regs);
+ ret = do_fork(clone_flags, newsp, regs);
+ unlock_kernel();
+ return ret;
}
void release_thread(struct task_struct *dead_task)
{
}
-void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct * p, struct pt_regs * regs)
{
struct pt_regs * childregs;
@@ -145,11 +176,13 @@ void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
: "memory");
/* Restore the state in case the fpu was busy */
asm volatile ("frestore %0" : : "m" (p->tss.fpstate[0]));
+
+ return 0;
}
/* Fill in the fpu structure for a core dump. */
-int dump_fpu (struct user_m68kfp_struct *fpu)
+int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
{
char fpustate[216];
@@ -187,7 +220,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
if (dump->start_stack < TASK_SIZE)
dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
- dump->u_ar0 = (struct pt_regs *)(((int)(&dump->regs)) -((int)(dump)));
+ dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
sw = ((struct switch_stack *)regs) - 1;
dump->regs.d1 = regs->d1;
dump->regs.d2 = regs->d2;
@@ -210,7 +243,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
dump->regs.pc = regs->pc;
dump->regs.fmtvec = (regs->format << 12) | regs->vector;
/* dump floating point stuff */
- dump->u_fpvalid = dump_fpu (&dump->m68kfp);
+ dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
}
/*
@@ -222,10 +255,13 @@ asmlinkage int sys_execve(char *name, char **argv, char **envp)
char * filename;
struct pt_regs *regs = (struct pt_regs *) &name;
+ lock_kernel();
error = getname(name, &filename);
if (error)
- return error;
+ goto out;
error = do_execve(filename, argv, envp, regs);
putname(filename);
+out:
+ unlock_kernel();
return error;
}
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index dc48a2ec5..70e341b31 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -14,6 +14,8 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
@@ -322,25 +324,28 @@ 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;
- struct user * dummy;
-
- dummy = NULL;
+ int ret;
+ lock_kernel();
+ ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->flags & PF_PTRACED)
- return -EPERM;
+ goto out;
/* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED;
- return 0;
+ ret = 0;
+ goto out;
}
if (pid == 1) /* you may not mess with init */
- return -EPERM;
+ goto out;
+ ret = -ESRCH;
if (!(child = get_task(pid)))
- return -ESRCH;
+ goto out;
+ ret = -EPERM;
if (request == PTRACE_ATTACH) {
if (child == current)
- return -EPERM;
+ goto out;
if ((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
@@ -348,10 +353,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(current->gid != child->gid)) && !suser())
- return -EPERM;
+ goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
- return -EPERM;
+ goto out;
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
REMOVE_LINKS(child);
@@ -359,39 +364,42 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
SET_LINKS(child);
}
send_sig(SIGSTOP, child, 1);
- return 0;
+ ret = 0;
+ goto out;
}
+ ret = -ESRCH;
if (!(child->flags & PF_PTRACED))
- return -ESRCH;
+ goto out;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
- return -ESRCH;
+ goto out;
}
if (child->p_pptr != current)
- return -ESRCH;
+ goto out;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
- int res;
- res = read_long(child, addr, &tmp);
- if (res < 0)
- return res;
- return put_user(tmp, (unsigned long *) data);
+ ret = read_long(child, addr, &tmp);
+ if (ret >= 0)
+ ret = put_user(tmp, (unsigned long *) data);
+ goto out;
}
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp;
+ ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
- return -EIO;
+ goto out;
tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
+ ret = -EIO;
if (addr < 19) {
tmp = get_reg(child, addr);
if (addr == PT_SR)
@@ -400,23 +408,26 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
else if (addr >= 21 && addr < 49)
tmp = child->tss.fp[addr - 21];
else
- return -EIO;
- return put_user(tmp,(unsigned long *) data);
+ goto out;
+ ret = put_user(tmp,(unsigned long *) data);
+ goto out;
}
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- return write_long(child,addr,data);
+ ret = write_long(child,addr,data);
+ goto out;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+ ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
- return -EIO;
+ goto out;
addr = addr >> 2; /* temporary hack. */
if (addr == PT_ORIG_D0)
- return -EIO;
+ goto out;
if (addr == PT_SR) {
data &= SR_MASK;
data <<= 16;
@@ -424,22 +435,24 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
}
if (addr < 19) {
if (put_reg(child, addr, data))
- return -EIO;
- return 0;
+ goto out;
+ ret = 0;
+ goto out;
}
if (addr >= 21 && addr < 48)
{
child->tss.fp[addr - 21] = data;
- return 0;
+ ret = 0;
}
- return -EIO;
+ goto out;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
long tmp;
+ ret = -EIO;
if ((unsigned long) data >= NSIG)
- return -EIO;
+ goto out;
if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS;
else
@@ -449,7 +462,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
- return 0;
+ ret = 0;
+ goto out;
}
/*
@@ -460,21 +474,23 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_KILL: {
long tmp;
+ ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */
- return 0;
+ goto out;
wake_up_process(child);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
- return 0;
+ goto out;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
long tmp;
+ ret = -EIO;
if ((unsigned long) data >= NSIG)
- return -EIO;
+ goto out;
child->flags &= ~PF_TRACESYS;
tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
@@ -482,14 +498,16 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
- return 0;
+ ret = 0;
+ goto out;
}
case PTRACE_DETACH: { /* detach a process that was attached. */
long tmp;
+ ret = -EIO;
if ((unsigned long) data >= NSIG)
- return -EIO;
+ goto out;
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child);
child->exit_code = data;
@@ -499,19 +517,25 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
- return 0;
+ ret = 0;
+ goto out;
}
default:
- return -EIO;
+ ret = -EIO;
+ goto out;
}
+out:
+ unlock_kernel();
+ return ret;
}
asmlinkage void syscall_trace(void)
{
+ lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS))
- return;
+ goto out;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
notify_parent(current);
@@ -524,5 +548,6 @@ asmlinkage void syscall_trace(void)
if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1));
current->exit_code = 0;
- return;
+out:
+ unlock_kernel();
}
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 58987d1cc..dfd91d0d4 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -19,19 +19,26 @@
#include <linux/errno.h>
#include <linux/string.h>
+#include <asm/bootinfo.h>
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/machdep.h>
-#include <asm/amigatypes.h>
+#ifdef CONFIG_AMIGA
#include <asm/amigahw.h>
+#endif
+#ifdef CONFIG_ATARI
+#include <asm/atarihw.h>
+#endif
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#include <asm/pgtable.h>
#endif
-struct bootinfo boot_info = {0,};
-int bisize = sizeof boot_info;
+u_long m68k_machtype;
+u_long m68k_cputype;
+u_long m68k_fputype;
+u_long m68k_mmutype;
int m68k_is040or060 = 0;
@@ -40,12 +47,13 @@ char m68k_debug_device[6] = "";
extern int end;
extern unsigned long availmem;
-char saved_command_line[CL_SIZE];
+int m68k_num_memory = 0;
+struct mem_info m68k_memory[NUM_MEMINFO];
-/* setup some dummy routines */
-static void dummy_waitbut(void)
-{
-}
+static struct mem_info m68k_ramdisk = { 0, 0 };
+
+static char m68k_command_line[CL_SIZE];
+char saved_command_line[CL_SIZE];
void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *));
/* machine dependent keyboard functions */
@@ -55,11 +63,8 @@ void (*mach_kbd_leds) (unsigned int) = NULL;
/* machine dependent irq functions */
void (*mach_init_IRQ) (void);
void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
-int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
- unsigned long, const char *, void *);
-int (*mach_free_irq) (unsigned int, void *);
-void (*mach_enable_irq) (unsigned int) = NULL;
-void (*mach_disable_irq) (unsigned int) = NULL;
+void (*mach_get_model) (char *model) = NULL;
+int (*mach_get_hardware_list) (char *buffer) = NULL;
int (*mach_get_irq_list) (char *) = NULL;
void (*mach_process_int) (int, struct pt_regs *) = NULL;
/* machine dependent timer functions */
@@ -67,12 +72,9 @@ unsigned long (*mach_gettimeoffset) (void);
void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
int (*mach_set_clock_mmss) (unsigned long) = NULL;
-void (*mach_mksound)( unsigned int count, unsigned int ticks );
void (*mach_reset)( void );
-void (*waitbut)(void) = dummy_waitbut;
struct fb_info *(*mach_fb_init)(long *);
long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
-void (*mach_debug_init)(void);
void (*mach_video_setup) (char *, int *);
#ifdef CONFIG_BLK_DEV_FD
int (*mach_floppy_init) (void) = NULL;
@@ -80,39 +82,75 @@ void (*mach_floppy_setup) (char *, int *) = NULL;
void (*mach_floppy_eject) (void) = NULL;
#endif
+extern int amiga_parse_bootinfo(const struct bi_record *);
+extern int atari_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 register_console(void (*proc)(const char *));
-extern void ami_serial_print (const char *str);
-extern void ata_serial_print (const char *str);
+#define MASK_256K 0xfffc0000
-extern void (*kd_mksound)(unsigned int, unsigned int);
-extern void amiga_get_model(char *model);
-extern void atari_get_model(char *model);
-extern void mac_get_model(char *model);
-extern int amiga_get_hardware_list(char *buffer);
-extern int atari_get_hardware_list(char *buffer);
-extern int mac_get_hardware_list(char *buffer);
+static void m68k_parse_bootinfo(const struct bi_record *record)
+{
+ while (record->tag != BI_LAST) {
+ int unknown = 0;
+ const u_long *data = record->data;
+ switch (record->tag) {
+ case BI_MACHTYPE:
+ case BI_CPUTYPE:
+ case BI_FPUTYPE:
+ case BI_MMUTYPE:
+ /* Already set up by head.S */
+ break;
-#define MASK_256K 0xfffc0000
+ case BI_MEMCHUNK:
+ if (m68k_num_memory < NUM_MEMINFO) {
+ m68k_memory[m68k_num_memory].addr = data[0];
+ m68k_memory[m68k_num_memory].size = data[1];
+ m68k_num_memory++;
+ } else
+ printk("m68k_parse_bootinfo: too many memory chunks\n");
+ break;
-void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p)
+ case BI_RAMDISK:
+ m68k_ramdisk.addr = data[0];
+ m68k_ramdisk.size = data[1];
+ break;
+
+ case BI_COMMAND_LINE:
+ strncpy(m68k_command_line, (const char *)data, CL_SIZE);
+ m68k_command_line[CL_SIZE-1] = '\0';
+ break;
+
+ default:
+ if (MACH_IS_AMIGA)
+ unknown = amiga_parse_bootinfo(record);
+ else if (MACH_IS_ATARI)
+ unknown = atari_parse_bootinfo(record);
+ else
+ unknown = 1;
+ }
+ if (unknown)
+ printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
+ record->tag);
+ record = (struct bi_record *)((u_long)record+record->size);
+ }
+}
+
+void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
+ unsigned long * memory_end_p)
{
unsigned long memory_start, memory_end;
extern int _etext, _edata, _end;
int i;
char *p, *q;
- if (MACH_IS_AMIGA)
- register_console(ami_serial_print);
-
- if (MACH_IS_ATARI)
- register_console(ata_serial_print);
+ /* The bootinfo is located right after the kernel bss */
+ m68k_parse_bootinfo((const struct bi_record *)&_end);
if (CPU_IS_040)
m68k_is040or060 = 4;
@@ -120,7 +158,7 @@ void setup_arch(char **cmdline_p,
m68k_is040or060 = 6;
/* clear the fpu if we have one */
- if (boot_info.cputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
+ if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
volatile int zero = 0;
asm __volatile__ ("frestore %0" : : "m" (zero));
}
@@ -128,15 +166,15 @@ void setup_arch(char **cmdline_p,
memory_start = availmem;
memory_end = 0;
- for (i = 0; i < boot_info.num_memory; i++)
- memory_end += boot_info.memory[i].size & MASK_256K;
+ for (i = 0; i < m68k_num_memory; i++)
+ memory_end += m68k_memory[i].size & MASK_256K;
init_task.mm->start_code = 0;
init_task.mm->end_code = (unsigned long) &_etext;
init_task.mm->end_data = (unsigned long) &_edata;
init_task.mm->brk = (unsigned long) &_end;
- *cmdline_p = boot_info.command_line;
+ *cmdline_p = m68k_command_line;
memcpy(saved_command_line, *cmdline_p, CL_SIZE);
/* Parse the command line for arch-specific options.
@@ -166,7 +204,7 @@ void setup_arch(char **cmdline_p,
*memory_start_p = memory_start;
*memory_end_p = memory_end;
- switch (boot_info.machtype) {
+ switch (m68k_machtype) {
#ifdef CONFIG_AMIGA
case MACH_AMIGA:
config_amiga();
@@ -187,21 +225,26 @@ void setup_arch(char **cmdline_p,
config_sun3();
break;
#endif
+#ifdef CONFIG_APOLLO
+ case MACH_APOLLO:
+ config_apollo();
+ break;
+#endif
default:
panic ("No configuration setup");
}
#ifdef CONFIG_BLK_DEV_INITRD
- if (boot_info.ramdisk_size) {
- initrd_start = PTOV (boot_info.ramdisk_addr);
- initrd_end = initrd_start + boot_info.ramdisk_size * 1024;
+ if (m68k_ramdisk.size) {
+ initrd_start = PTOV (m68k_ramdisk.addr);
+ initrd_end = initrd_start + m68k_ramdisk.size;
}
#endif
}
int get_cpuinfo(char * buffer)
{
- char *cpu, *mmu, *fpu;
+ const char *cpu, *mmu, *fpu;
u_long clockfreq, clockfactor;
#define LOOP_CYCLES_68020 (8)
@@ -211,33 +254,49 @@ int get_cpuinfo(char * buffer)
if (CPU_IS_020) {
cpu = "68020";
- mmu = "68851";
clockfactor = LOOP_CYCLES_68020;
} else if (CPU_IS_030) {
- cpu = mmu = "68030";
+ cpu = "68030";
clockfactor = LOOP_CYCLES_68030;
} else if (CPU_IS_040) {
- cpu = mmu = "68040";
+ cpu = "68040";
clockfactor = LOOP_CYCLES_68040;
} else if (CPU_IS_060) {
- cpu = mmu = "68060";
+ cpu = "68060";
clockfactor = LOOP_CYCLES_68060;
} else {
- cpu = mmu = "680x0";
+ cpu = "680x0";
clockfactor = 0;
}
- if (boot_info.cputype & FPU_68881)
+ if (m68k_fputype & FPU_68881)
fpu = "68881";
- else if (boot_info.cputype & FPU_68882)
+ else if (m68k_fputype & FPU_68882)
fpu = "68882";
- else if (boot_info.cputype & FPU_68040)
+ else if (m68k_fputype & FPU_68040)
fpu = "68040";
- else if (boot_info.cputype & FPU_68060)
+ else if (m68k_fputype & FPU_68060)
fpu = "68060";
+ else if (m68k_fputype & FPU_SUNFPA)
+ fpu = "Sun FPA";
else
fpu = "none";
+ if (m68k_mmutype & MMU_68851)
+ mmu = "68851";
+ else if (m68k_mmutype & MMU_68030)
+ mmu = "68030";
+ else if (m68k_mmutype & MMU_68040)
+ mmu = "68040";
+ else if (m68k_mmutype & MMU_68060)
+ mmu = "68060";
+ else if (m68k_mmutype & MMU_SUN3)
+ mmu = "Sun-3";
+ else if (m68k_mmutype & MMU_APOLLO)
+ mmu = "Apollo";
+ else
+ mmu = "unknown";
+
clockfreq = loops_per_sec*clockfactor;
return(sprintf(buffer, "CPU:\t\t%s\n"
@@ -260,48 +319,19 @@ int get_hardware_list(char *buffer)
u_long mem;
int i;
- switch (boot_info.machtype) {
-#ifdef CONFIG_AMIGA
- case MACH_AMIGA:
- amiga_get_model(model);
- break;
-#endif
-#ifdef CONFIG_ATARI
- case MACH_ATARI:
- atari_get_model(model);
- break;
-#endif
-#ifdef CONFIG_MAC
- case MACH_MAC:
- mac_get_model(model);
- break;
-#endif
- default:
- strcpy(model, "Unknown m68k");
- } /* boot_info.machtype */
+ if (mach_get_model)
+ mach_get_model(model);
+ else
+ strcpy(model, "Unknown m68k");
len += sprintf(buffer+len, "Model:\t\t%s\n", model);
len += get_cpuinfo(buffer+len);
- for (mem = 0, i = 0; i < boot_info.num_memory; i++)
- mem += boot_info.memory[i].size;
+ for (mem = 0, i = 0; i < m68k_num_memory; i++)
+ mem += m68k_memory[i].size;
len += sprintf(buffer+len, "System Memory:\t%ldK\n", mem>>10);
- switch (boot_info.machtype) {
-#ifdef CONFIG_AMIGA
- case MACH_AMIGA:
- len += amiga_get_hardware_list(buffer+len);
- break;
-#endif
-#ifdef CONFIG_ATARI
- case MACH_ATARI:
- len += atari_get_hardware_list(buffer+len);
- break;
-#endif
-#ifdef CONFIG_MAC
- case MACH_MAC:
- break;
-#endif
- } /* boot_info.machtype */
+ if (mach_get_hardware_list)
+ len += mach_get_hardware_list(buffer+len);
return(len);
}
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 0d2a372f9..c60e82b0b 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -127,26 +127,26 @@ asmlinkage int do_sigreturn(unsigned long __unused)
/* Verify the frame format. */
if (!CPU_IS_060 && (context.sc_fpstate[0] != fpu_version))
goto badframe;
- if (boot_info.cputype & FPU_68881)
+ if (m68k_fputype & FPU_68881)
{
if (context.sc_fpstate[1] != 0x18
&& context.sc_fpstate[1] != 0xb4)
goto badframe;
}
- else if (boot_info.cputype & FPU_68882)
+ else if (m68k_fputype & FPU_68882)
{
if (context.sc_fpstate[1] != 0x38
&& context.sc_fpstate[1] != 0xd4)
goto badframe;
}
- else if (boot_info.cputype & FPU_68040)
+ else if (m68k_fputype & FPU_68040)
{
if (!(context.sc_fpstate[1] == 0x00 ||
context.sc_fpstate[1] == 0x28 ||
context.sc_fpstate[1] == 0x60))
goto badframe;
}
- else if (boot_info.cputype & FPU_68060)
+ else if (m68k_fputype & FPU_68060)
{
if (!(context.sc_fpstate[3] == 0x00 ||
context.sc_fpstate[3] == 0x60 ||
@@ -174,7 +174,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
if (context.sc_usp != fp+fsize)
current->flags &= ~PF_ONSIGSTK;
-
+
/* OK. Make room on the supervisor stack for the extra junk,
* if necessary.
*/
@@ -200,7 +200,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
" .align 4\n"
" .long 2b,4b\n"
" .long 3b,4b\n"
- ".text"
+ ".previous"
: /* no outputs, it doesn't ever return */
: "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
"n" (frame_offset), "a" (fp)
@@ -261,8 +261,8 @@ badframe:
#define UFRAME_SIZE(fs) (sizeof(struct sigcontext)/4 + 6 + fs/4)
-static void setup_frame (struct sigaction * sa, struct pt_regs *regs,
- int signr, unsigned long oldmask)
+static inline void setup_frame (struct sigaction * sa, struct pt_regs *regs,
+ int signr, unsigned long oldmask)
{
struct sigcontext context;
unsigned long *frame, *tframe;
@@ -291,20 +291,23 @@ static void setup_frame (struct sigaction * sa, struct pt_regs *regs,
tframe = frame;
/* return address points to code on stack */
- put_user((ulong)(frame+4), tframe); tframe++;
+
+ if(put_user((ulong)(frame+4), tframe))
+ do_exit(SIGSEGV);
+ tframe++;
if (current->exec_domain && current->exec_domain->signal_invmap)
- put_user(current->exec_domain->signal_invmap[signr], tframe);
+ __put_user(current->exec_domain->signal_invmap[signr], tframe);
else
- put_user(signr, tframe);
+ __put_user(signr, tframe);
tframe++;
- put_user(regs->vector, tframe); tframe++;
+ __put_user(regs->vector, tframe); tframe++;
/* "scp" parameter. points to sigcontext */
- put_user((ulong)(frame+6), tframe); tframe++;
+ __put_user((ulong)(frame+6), tframe); tframe++;
/* set up the return code... */
- put_user(0xdefc0014,tframe); tframe++; /* addaw #20,sp */
- put_user(0x70774e40,tframe); tframe++; /* moveq #119,d0; trap #0 */
+ __put_user(0xdefc0014,tframe); tframe++; /* addaw #20,sp */
+ __put_user(0x70774e40,tframe); tframe++; /* moveq #119,d0; trap #0 */
/* Flush caches so the instructions will be correctly executed. (MA) */
cache_push_v ((unsigned long)frame, (int)tframe - (int)frame);
@@ -360,9 +363,9 @@ static void setup_frame (struct sigaction * sa, struct pt_regs *regs,
/*
* OK, we're invoking a handler
- */
-static void handle_signal(unsigned long signr, struct sigaction *sa,
- unsigned long oldmask, struct pt_regs *regs)
+ */
+static inline void handle_signal(unsigned long signr, struct sigaction *sa,
+ unsigned long oldmask, struct pt_regs *regs)
{
/* are we from a system call? */
if (regs->orig_d0 >= 0) {
@@ -482,7 +485,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs)
continue;
current->state = TASK_STOPPED;
current->exit_code = signr;
- if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
+ if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
notify_parent(current);
schedule();
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index d187e3d57..5acfd1cbd 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -9,6 +9,8 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
@@ -31,15 +33,14 @@ asmlinkage int sys_pipe(unsigned long * fildes)
int fd[2];
int error;
- error = verify_area(VERIFY_WRITE,fildes,8);
- if (error)
- return error;
+ lock_kernel();
error = do_pipe(fd);
- if (error)
- return error;
- put_user(fd[0],0+fildes);
- put_user(fd[1],1+fildes);
- return 0;
+ if (!error) {
+ if (copy_to_user(fildes, fd, 2*sizeof(int)))
+ error = -EFAULT;
+ }
+ unlock_kernel();
+ return error;
}
/*
@@ -64,16 +65,20 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg)
struct file * file = NULL;
struct mmap_arg_struct a;
- error = verify_area(VERIFY_READ, arg, sizeof(*arg));
- if (error)
- return error;
- copy_from_user(&a, arg, sizeof(a));
+ lock_kernel();
+ error = -EFAULT;
+ if (copy_from_user(&a, arg, sizeof(a)))
+ goto out;
+
if (!(a.flags & MAP_ANONYMOUS)) {
+ error = -EBADF;
if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
- return -EBADF;
+ goto out;
}
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
+out:
+ unlock_kernel();
return error;
}
@@ -92,6 +97,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg)
if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT;
+ /* sys_select() does the appropriate kernel locking */
return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
}
@@ -102,7 +108,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg)
*/
asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{
- int version;
+ int version, ret;
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
@@ -110,46 +116,57 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
if (call <= SEMCTL)
switch (call) {
case SEMOP:
- return sys_semop (first, (struct sembuf *)ptr, second);
+ ret = sys_semop (first, (struct sembuf *)ptr, second);
+ goto out;
case SEMGET:
- return sys_semget (first, second, third);
+ ret = sys_semget (first, second, third);
+ goto out;
case SEMCTL: {
union semun fourth;
- int err;
+ ret = -EINVAL;
if (!ptr)
- return -EINVAL;
- if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
- return err;
- get_user(fourth.__pad, (void **)ptr);
- return sys_semctl (first, second, third, fourth);
+ goto out;
+ if ((ret = get_user(fourth.__pad, (void **) ptr)))
+ goto out;
+ ret = sys_semctl (first, second, third, fourth);
+ goto out;
}
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
if (call <= MSGCTL)
switch (call) {
case MSGSND:
- return sys_msgsnd (first, (struct msgbuf *) ptr,
- second, third);
+ ret = sys_msgsnd (first, (struct msgbuf *) ptr,
+ second, third);
+ goto out;
case MSGRCV:
switch (version) {
case 0: {
struct ipc_kludge tmp;
+ ret = -EINVAL;
if (!ptr)
- return -EINVAL;
+ goto out;
+ ret = -EFAULT;
if (copy_from_user (&tmp, ptr, sizeof (tmp)))
- return -EFAULT;
- return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
+ goto out;
+ ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
+ goto out;
}
case 1: default:
- return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+ ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+ goto out;
}
case MSGGET:
- return sys_msgget ((key_t) first, second);
+ ret = sys_msgget ((key_t) first, second);
+ goto out;
case MSGCTL:
- return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+ ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
+ goto out;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
if (call <= SHMCTL)
switch (call) {
@@ -157,30 +174,30 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
switch (version) {
case 0: default: {
ulong raddr;
- int err;
- if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
- return err;
- err = sys_shmat (first, (char *) ptr, second, &raddr);
- if (err)
- return err;
- put_user (raddr, (ulong *) third);
- return 0;
- }
- case 1: /* iBCS2 emulator entry point */
- if (get_fs() != get_ds())
- return -EINVAL;
- return sys_shmat (first, (char *) ptr, second, (ulong *) third);
+ ret = sys_shmat (first, (char *) ptr, second, &raddr);
+ if (ret)
+ goto out;
+ ret = put_user (raddr, (ulong *) third);
+ goto out;
+ }
}
case SHMDT:
- return sys_shmdt ((char *)ptr);
+ ret = sys_shmdt ((char *)ptr);
+ goto out;
case SHMGET:
- return sys_shmget (first, second, third);
+ ret = sys_shmget (first, second, third);
+ goto out;
case SHMCTL:
- return sys_shmctl (first, second, (struct shmid_ds *) ptr);
+ ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
+ goto out;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
- return -EINVAL;
+ ret = -EINVAL;
+out:
+ unlock_kernel();
+ return ret;
}
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
@@ -192,15 +209,14 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
in VALID whether the virtual address is actually mapped. */
#define virt_to_phys_040(vaddr, paddr, valid) \
{ \
- register unsigned long _tmp1 __asm__ ("a0") = (vaddr); \
- register unsigned long _tmp2 __asm__ ("d0"); \
unsigned long _mmusr; \
\
- __asm__ __volatile__ (".word 0xf568 /* ptestr (%1) */\n\t" \
- ".long 0x4e7a0805 /* movec %%mmusr,%0 */" \
- : "=d" (_tmp2) \
- : "a" (_tmp1)); \
- _mmusr = _tmp2; \
+ __asm__ __volatile__ (".chip 68040\n\t" \
+ "ptestr (%1)\n\t" \
+ "movec %%mmusr,%0\n\t" \
+ ".chip 68k" \
+ : "=r" (_mmusr) \
+ : "a" (vaddr)); \
if (!(_mmusr & MMU_R_040)) \
(valid) = 0; \
else \
@@ -224,16 +240,22 @@ cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
case FLUSH_CACHE_DATA:
/* This nop is needed for some broken versions of the 68040. */
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf478 /* cpusha %%dc */");
+ ".chip 68040\n\t"
+ "cpusha %dc\n\t"
+ ".chip 68k");
break;
case FLUSH_CACHE_INSN:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4b8 /* cpusha %%ic */");
+ ".chip 68040\n\t"
+ "cpusha %ic\n\t"
+ ".chip 68k");
break;
default:
case FLUSH_CACHE_BOTH:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4f8 /* cpusha %%bc */");
+ ".chip 68040\n\t"
+ "cpusha %bc\n\t"
+ ".chip 68k");
break;
}
break;
@@ -254,23 +276,28 @@ cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
}
while (len--)
{
- register unsigned long tmp __asm__ ("a0") = paddr;
switch (cache)
{
case FLUSH_CACHE_DATA:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf468 /* cpushl %%dc,(%0) */"
- : : "a" (tmp));
+ ".chip 68040\n\t"
+ "cpushl %%dc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
case FLUSH_CACHE_INSN:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4a8 /* cpushl %%ic,(%0) */"
- : : "a" (tmp));
+ ".chip 68040\n\t"
+ "cpushl %%ic,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
default:
case FLUSH_CACHE_BOTH:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4e8 /* cpushl %%bc,(%0) */"
+ ".chip 68040\n\t"
+ "cpushl %%bc,(%0)\n\t"
+ ".chip 68k"
: : "a" (paddr));
break;
}
@@ -302,28 +329,32 @@ cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
case FLUSH_SCOPE_PAGE:
for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
{
- register unsigned long tmp __asm__ ("a0");
virt_to_phys_040 (addr, paddr, valid);
if (!valid)
continue;
- tmp = paddr;
switch (cache)
{
case FLUSH_CACHE_DATA:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf470 /* cpushp %%dc,(%0) */"
- : : "a" (tmp));
+ ".chip 68040\n\t"
+ "cpushp %%dc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
case FLUSH_CACHE_INSN:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4b0 /* cpushp %%ic,(%0) */"
- : : "a" (tmp));
+ ".chip 68040\n\t"
+ "cpushp %%ic,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
default:
case FLUSH_CACHE_BOTH:
__asm__ __volatile__ ("nop\n\t"
- ".word 0xf4f0 /* cpushp %%bc,(%0) */"
- : : "a" (tmp));
+ ".chip 68040\n\t"
+ "cpushp %%bc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
}
}
@@ -334,13 +365,12 @@ cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
#define virt_to_phys_060(vaddr, paddr, valid) \
{ \
- register unsigned long _tmp __asm__ ("a0") = (vaddr); \
- \
- __asm__ __volatile__ (".word 0xf5c8 /* plpar (%1) */" \
- : "=a" (_tmp) \
- : "0" (_tmp)); \
+ __asm__ __volatile__ (".chip 68060\n\t" \
+ "plpar (%0)\n\t" \
+ ".chip 68k" \
+ : "=a" (paddr) \
+ : "0" (vaddr)); \
(valid) = 1; /* XXX */ \
- (paddr) = _tmp; \
}
static inline int
@@ -355,17 +385,23 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
switch (cache)
{
case FLUSH_CACHE_DATA:
- __asm__ __volatile__ (".word 0xf478 /* cpusha %%dc */\n\t"
- ".word 0xf458 /* cinva %%dc */");
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpusha %dc\n\t"
+ "cinva %dc\n\t"
+ ".chip 68k");
break;
case FLUSH_CACHE_INSN:
- __asm__ __volatile__ (".word 0xf4b8 /* cpusha %%ic */\n\t"
- ".word 0xf498 /* cinva %%ic */");
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpusha %ic\n\t"
+ "cinva %ic\n\t"
+ ".chip 68k");
break;
default:
case FLUSH_CACHE_BOTH:
- __asm__ __volatile__ (".word 0xf4f8 /* cpusha %%bc */\n\t"
- ".word 0xf4d8 /* cinva %%bc */");
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpusha %bc\n\t"
+ "cinva %bc\n\t"
+ ".chip 68k");
break;
}
break;
@@ -386,23 +422,28 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
}
while (len--)
{
- register unsigned long tmp __asm__ ("a0") = paddr;
switch (cache)
{
case FLUSH_CACHE_DATA:
- __asm__ __volatile__ (".word 0xf468 /* cpushl %%dc,(%0) */\n\t"
- ".word 0xf448 /* cinv %%dc,(%0) */"
- : : "a" (tmp));
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushl %%dc,(%0)\n\t"
+ "cinvl %%dc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
case FLUSH_CACHE_INSN:
- __asm__ __volatile__ (".word 0xf4a8 /* cpushl %%ic,(%0) */\n\t"
- ".word 0xf488 /* cinv %%ic,(%0) */"
- : : "a" (tmp));
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushl %%ic,(%0)\n\t"
+ "cinvl %%ic,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
default:
case FLUSH_CACHE_BOTH:
- __asm__ __volatile__ (".word 0xf4e8 /* cpushl %%bc,(%0) */\n\t"
- ".word 0xf4c8 /* cinv %%bc,(%0) */"
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushl %%bc,(%0)\n\t"
+ "cinvl %%bc,(%0)\n\t"
+ ".chip 68k"
: : "a" (paddr));
break;
}
@@ -434,28 +475,32 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
case FLUSH_SCOPE_PAGE:
for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
{
- register unsigned long tmp __asm__ ("a0");
virt_to_phys_060 (addr, paddr, valid);
if (!valid)
continue;
- tmp = paddr;
switch (cache)
{
case FLUSH_CACHE_DATA:
- __asm__ __volatile__ (".word 0xf470 /* cpushp %%dc,(%0) */\n\t"
- ".word 0xf450 /* cinv %%dc,(%0) */"
- : : "a" (tmp));
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushp %%dc,(%0)\n\t"
+ "cinvp %%dc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
case FLUSH_CACHE_INSN:
- __asm__ __volatile__ (".word 0xf4b0 /* cpushp %%ic,(%0) */\n\t"
- ".word 0xf490 /* cinv %%ic,(%0) */"
- : : "a" (tmp));
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushp %%ic,(%0)\n\t"
+ "cinvp %%ic,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
default:
case FLUSH_CACHE_BOTH:
- __asm__ __volatile__ (".word 0xf4f0 /* cpushp %%bc,(%0) */\n\t"
- ".word 0xf4d0 /* cinv %%bc,(%0) */"
- : : "a" (tmp));
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushp %%bc,(%0)\n\t"
+ "cinvp %%bc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (paddr));
break;
}
}
@@ -468,41 +513,63 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
asmlinkage int
sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
{
- struct vm_area_struct *vma;
+ struct vm_area_struct *vma;
+ int ret = -EINVAL;
- if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL
- || cache & ~FLUSH_CACHE_BOTH)
- return -EINVAL;
+ lock_kernel();
+ if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
+ cache & ~FLUSH_CACHE_BOTH)
+ goto out;
- if (scope == FLUSH_SCOPE_ALL)
- {
- /* Only the superuser may flush the whole cache. */
- if (!suser ())
- return -EPERM;
- }
- else
- {
- /* Verify that the specified address region actually belongs to
- this process. */
- vma = find_vma (current->mm, addr);
- if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
- return -EINVAL;
- }
+ if (scope == FLUSH_SCOPE_ALL) {
+ /* Only the superuser may flush the whole cache. */
+ ret = -EPERM;
+ if (!suser ())
+ goto out;
+ } else {
+ /* Verify that the specified address region actually belongs to
+ * this process.
+ */
+ vma = find_vma (current->mm, addr);
+ ret = -EINVAL;
+ if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
+ goto out;
+ }
- if (CPU_IS_020_OR_030) {
- /* Always flush the whole cache, everything else would not be
- worth the hassle. */
- __asm__ __volatile__
- ("movec %%cacr, %%d0\n\t"
- "or %0, %%d0\n\t"
- "movec %%d0, %%cacr"
- : /* no outputs */
- : "di" ((cache & FLUSH_CACHE_INSN ? 8 : 0)
- | (cache & FLUSH_CACHE_DATA ? 0x800 : 0))
- : "d0");
- return 0;
- } else if (CPU_IS_040)
- return cache_flush_040 (addr, scope, cache, len);
- else if (CPU_IS_060)
- return cache_flush_060 (addr, scope, cache, len);
+ if (CPU_IS_020_OR_030) {
+ if (scope == FLUSH_SCOPE_LINE) {
+ unsigned long cacr;
+ __asm__ ("movec %%cacr, %0" : "=r" (cacr));
+ if (cache & FLUSH_CACHE_INSN)
+ cacr |= 4;
+ if (cache & FLUSH_CACHE_DATA)
+ cacr |= 0x400;
+ len >>= 4;
+ while (len--) {
+ __asm__ __volatile__ ("movec %1, %%caar\n\t"
+ "movec %0, %%cacr"
+ : /* no outputs */
+ : "r" (cacr), "r" (addr));
+ addr += 16;
+ }
+ } else {
+ /* Flush the whole cache, even if page granularity requested. */
+ unsigned long cacr;
+ __asm__ ("movec %%cacr, %0" : "=r" (cacr));
+ if (cache & FLUSH_CACHE_INSN)
+ cacr |= 8;
+ if (cache & FLUSH_CACHE_DATA)
+ cacr |= 0x800;
+ __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
+ }
+ ret = 0;
+ goto out;
+ } else if (CPU_IS_040) {
+ ret = cache_flush_040 (addr, scope, cache, len);
+ } else if (CPU_IS_060) {
+ ret = cache_flush_060 (addr, scope, cache, len);
+ }
+out:
+ unlock_kernel();
+ return ret;
}
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 39625f3b6..1cc547907 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -29,11 +29,15 @@
#include <linux/linkage.h>
#include <asm/setup.h>
+#include <asm/fpu.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/traps.h>
#include <asm/pgtable.h>
#include <asm/machdep.h>
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+#endif
/* assembler routines */
asmlinkage void system_call(void);
@@ -140,10 +144,9 @@ static inline void console_verbose(void)
{
extern int console_loglevel;
console_loglevel = 15;
- mach_debug_init();
}
-char *vec_names[] = {
+static char *vec_names[] = {
"RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
"ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
"PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
@@ -162,17 +165,17 @@ char *vec_names[] = {
"FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
"FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
"FPCP UNSUPPORTED OPERATION",
- "MMU CONFIGUATION ERROR"
+ "MMU CONFIGURATION ERROR"
};
-char *space_names[] = {
+static char *space_names[] = {
"Space 0", "User Data", "User Program", "Space 3",
"Space 4", "Super Data", "Super Program", "CPU"
};
-extern void die_if_kernel(char *,struct pt_regs *,int);
+void die_if_kernel(char *,struct pt_regs *,int);
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code);
@@ -184,7 +187,7 @@ static inline void access_error060 (struct frame *fp)
unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
#ifdef DEBUG
- printk("fslw=%#lx, fa=%#lx\n", ssw, fp->un.fmt4.effaddr);
+ printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
#endif
if (fslw & MMU060_BPE) {
@@ -194,7 +197,7 @@ static inline void access_error060 (struct frame *fp)
"movec %/d0,%/cacr"
: : : "d0" );
/* return if there's no other error */
- if (!(fslw & MMU060_ERR_BITS))
+ if ((!(fslw & MMU060_ERR_BITS)) && !(fslw & MMU060_SEE))
return;
}
@@ -209,8 +212,13 @@ static inline void access_error060 (struct frame *fp)
if (fslw & MMU060_MA)
addr = PAGE_ALIGN(addr);
do_page_fault(&fp->ptregs, addr, errorcode);
- }
- else {
+ } else if (fslw & (MMU060_SEE)){
+ /* Software Emulation Error. Probably an instruction
+ * using an unsupported addressing mode
+ */
+ send_sig (SIGSEGV, current, 1);
+ } else {
+ printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
printk( "68060 access error, fslw=%lx\n", fslw );
trap_c( fp );
}
@@ -218,7 +226,7 @@ static inline void access_error060 (struct frame *fp)
#endif /* CONFIG_M68060 */
#if defined (CONFIG_M68040)
-static unsigned long probe040 (int iswrite, int fc, unsigned long addr)
+static inline unsigned long probe040 (int iswrite, int fc, unsigned long addr)
{
unsigned long mmusr;
unsigned long fs = get_fs();
@@ -227,28 +235,26 @@ static unsigned long probe040 (int iswrite, int fc, unsigned long addr)
if (iswrite)
/* write */
- asm volatile ("movel %1,%/a0\n\t"
- ".word 0xf548\n\t" /* ptestw (a0) */
- ".long 0x4e7a8805\n\t" /* movec mmusr,a0 */
- "movel %/a0,%0"
- : "=g" (mmusr)
- : "g" (addr)
- : "a0");
+ asm volatile (".chip 68040\n\t"
+ "ptestw (%1)\n\t"
+ "movec %%mmusr,%0\n\t"
+ ".chip 68k"
+ : "=r" (mmusr)
+ : "a" (addr));
else
- asm volatile ("movel %1,%/a0\n\t"
- ".word 0xf568\n\t" /* ptestr (a0) */
- ".long 0x4e7a8805\n\t" /* movec mmusr,a0 */
- "movel %/a0,%0"
- : "=g" (mmusr)
- : "g" (addr)
- : "a0");
+ asm volatile (".chip 68040\n\t"
+ "ptestr (%1)\n\t"
+ "movec %%mmusr,%0\n\t"
+ ".chip 68k"
+ : "=r" (mmusr)
+ : "a" (addr));
set_fs (fs);
return mmusr;
}
-static void do_040writeback (unsigned short ssw,
+static inline void do_040writeback (unsigned short ssw,
unsigned short wbs,
unsigned long wba,
unsigned long wbd,
@@ -313,11 +319,9 @@ static inline void access_error040 (struct frame *fp)
/* MMU error, get the MMUSR info for this access */
mmusr = probe040 (!(ssw & RW_040), ssw & TM_040, addr);
- /*
#ifdef DEBUG
printk("mmusr = %lx\n", mmusr);
#endif
-*/
errorcode = ((mmusr & MMU_R_040) ? 1 : 0) |
((ssw & RW_040) ? 0 : 2);
do_page_fault (&fp->ptregs, addr, errorcode);
@@ -353,7 +357,7 @@ static inline void access_error040 (struct frame *fp)
}
#endif /* CONFIG_M68040 */
-#if defined(CONFIG_M68020_OR_M68030)
+#if defined(CPU_M68020_OR_M68030)
static inline void bus_error030 (struct frame *fp)
{
volatile unsigned short temp;
@@ -605,7 +609,7 @@ static inline void bus_error030 (struct frame *fp)
printk ("level 0 mmusr is %#x\n", mmusr);
#ifdef DEBUG
- if (boot_info.cputype & CPU_68030) {
+ if (m68k_cputype & CPU_68030) {
asm volatile ("pmove %/tt0,%0@"
: /* no outputs */
: "a" (&tlong));
@@ -632,7 +636,7 @@ create_atc_entry:
asm volatile ("ploadr #2,%0@" : /* no outputs */
: "a" (addr));
}
-#endif /* CONFIG_M68020_OR_M68030 */
+#endif /* CPU_M68020_OR_M68030 */
asmlinkage void buserr_c(struct frame *fp)
{
@@ -655,7 +659,7 @@ asmlinkage void buserr_c(struct frame *fp)
access_error040 (fp);
break;
#endif
-#if defined (CONFIG_M68020_OR_M68030)
+#if defined (CPU_M68020_OR_M68030)
case 0xa:
case 0xb:
bus_error030 (fp);
@@ -679,6 +683,11 @@ int kstack_depth_to_print = 48;
static void dump_stack(struct frame *fp)
{
+#ifdef CONFIG_KGDB
+ /* This will never return to here, if kgdb has been initialized. And if
+ * it returns from there, then to where the error happened... */
+ enter_kgdb( &fp->ptregs );
+#else
unsigned long *stack, *endstack, addr, module_start, module_end;
extern char _start, _etext;
int i;
@@ -776,10 +785,15 @@ static void dump_stack(struct frame *fp)
for (i = 0; i < 10; i++)
printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]);
printk ("\n");
+#endif
}
void bad_super_trap (struct frame *fp)
{
+#ifdef CONFIG_KGDB
+ /* Save the register dump if we'll enter kgdb anyways */
+ if (!kgdb_initialized) {
+#endif
console_verbose();
if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
printk ("*** %s *** FORMAT=%X\n",
@@ -809,6 +823,9 @@ void bad_super_trap (struct frame *fp)
fp->ptregs.pc);
}
printk ("Current process id is %d\n", current->pid);
+#ifdef CONFIG_KGDB
+ }
+#endif
die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
}
@@ -867,14 +884,18 @@ asmlinkage void trap_c(struct frame *fp)
case VEC_FPOVER:
case VEC_FPNAN:
{
- unsigned char fstate[216];
+ unsigned char fstate[FPSTATESIZE];
- __asm__ __volatile__ ("fsave %0@" : : "a" (fstate) : "memory");
+ __asm__ __volatile__ (".chip 68k/68881\n\t"
+ "fsave %0@\n\t"
+ ".chip 68k" : : "a" (fstate) : "memory");
/* Set the exception pending bit in the 68882 idle frame */
if (*(unsigned short *) fstate == 0x1f38)
{
fstate[fstate[1]] |= 1 << 3;
- __asm__ __volatile__ ("frestore %0@" : : "a" (fstate));
+ __asm__ __volatile__ (".chip 68k/68881\n\t"
+ "frestore %0@\n\t"
+ ".chip 68k" : : "a" (fstate));
}
}
/* fall through */
@@ -905,9 +926,13 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
if (!(fp->sr & PS_S))
return;
+#ifdef CONFIG_KGDB
+ /* Save the register dump if we'll enter kgdb anyways */
+ if (!kgdb_initialized) {
+#endif
console_verbose();
printk("%s: %08x\n",str,nr);
- printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp);
+ printk("PC: [<%08lx>]\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp);
printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
fp->d0, fp->d1, fp->d2, fp->d3);
printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
@@ -917,6 +942,18 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
printk("Corrupted stack page\n");
printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, current->kernel_stack_page);
+#ifdef CONFIG_KGDB
+ }
+#endif
dump_stack((struct frame *)fp);
do_exit(SIGSEGV);
}
+
+/*
+ * This function is called if an error occur while accessing
+ * user-space from the fpsp040 code.
+ */
+asmlinkage void fpsp040_die(void)
+{
+ do_exit(SIGSEGV);
+}
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c
index 786e80dd3..35bf38d1e 100644
--- a/arch/m68k/lib/checksum.c
+++ b/arch/m68k/lib/checksum.c
@@ -19,8 +19,8 @@
* (%1). Thanks to Roman Hodek for pointing this out.
* B: GCC seems to mess up if one uses too many
* data-registers to hold input values and one tries to
- * specify d0 and d1 as scratch registers. Letting gcc choose these
- * registers itself solves the problem.
+ * specify d0 and d1 as scratch registers. Letting gcc
+ * choose these registers itself solves the problem.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -124,13 +124,20 @@ csum_partial (const unsigned char *buff, int len, unsigned int sum)
/*
- * copy from user space while checksumming, otherwise like csum_partial
+ * copy from user space while checksumming, with exception handling.
*/
unsigned int
-csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum)
+csum_partial_copy_from_user(const char *src, char *dst, int len,
+ int sum, int *csum_err)
{
+ /*
+ * GCC doesn't like more than 10 operands for the asm
+ * statements so we have to use tmp2 for the error
+ * code.
+ */
unsigned long tmp1, tmp2;
+
__asm__("movel %2,%4\n\t"
"btst #1,%4\n\t" /* Check alignment */
"jeq 2f\n\t"
@@ -226,28 +233,50 @@ csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum)
"6:\t"
"addl %5,%0\n\t" /* now add rest long to sum */
"clrl %5\n\t"
- "addxl %5,%0\n" /* add X bit */
- "7:\n"
+ "addxl %5,%0\n\t" /* add X bit */
+ "7:\t"
+ "clrl %5\n" /* no error - clear return value */
+ "8:\n"
+ ".section .fixup,\"ax\"\n"
+ ".even\n"
+ "9:\t"
+ "moveq #-14,%5\n\t" /* -EFAULT, out of inputs to asm ;( */
+ "jra 8b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
- ".long 10b,7b\n"
- ".long 11b,7b\n"
- ".long 12b,7b\n"
- ".long 13b,7b\n"
- ".long 14b,7b\n"
- ".long 15b,7b\n"
- ".long 16b,7b\n"
- ".long 17b,7b\n"
- ".long 18b,7b\n"
- ".long 19b,7b\n"
- ".long 20b,7b\n"
- ".long 21b,7b\n"
- ".text"
+ ".long 10b,9b\n"
+ ".long 11b,9b\n"
+ ".long 12b,9b\n"
+ ".long 13b,9b\n"
+ ".long 14b,9b\n"
+ ".long 15b,9b\n"
+ ".long 16b,9b\n"
+ ".long 17b,9b\n"
+ ".long 18b,9b\n"
+ ".long 19b,9b\n"
+ ".long 20b,9b\n"
+ ".long 21b,9b\n"
+ ".previous"
: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
- "=&d" (tmp1), "=&d" (tmp2)
+ "=&d" (tmp1), "=d" (tmp2)
: "0" (sum), "1" (len), "2" (src), "3" (dst)
);
+
+ *csum_err = tmp2;
+
return(sum);
}
+
+/*
+ * This one will go away soon.
+ */
+unsigned int
+csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum)
+{
+ int dummy;
+
+ return csum_partial_copy_from_user(src, dst, len, sum, &dummy);
+}
/*
* copy from kernel space while checksumming, otherwise like csum_partial
*/
diff --git a/arch/m68k/lib/semaphore.S b/arch/m68k/lib/semaphore.S
index be5501f50..76ffc3cc5 100644
--- a/arch/m68k/lib/semaphore.S
+++ b/arch/m68k/lib/semaphore.S
@@ -9,21 +9,29 @@
#include <linux/linkage.h>
/*
- * "down_failed" is called with the eventual return address
- * in %a0, and the address of the semaphore in %a1. We need
- * to call "__down()", and then re-try until we succeed..
+ * The semaphore operations have a special calling sequence that
+ * allow us to do a simpler in-line version of them. These routines
+ * need to convert that sequence back into the C sequence when
+ * there is contention on the semaphore.
*/
ENTRY(__down_failed)
moveml %a0/%d0/%d1,-(%sp)
-1: movel %a1,-(%sp)
+ movel %a1,-(%sp)
jbsr SYMBOL_NAME(__down)
movel (%sp)+,%a1
- subql #1,(%a1)
- jmi 1b
movel (%sp)+,%d0
movel (%sp)+,%d1
rts
+ENTRY(__down_failed_interruptible)
+ movel %a0,-(%sp)
+ movel %d1,-(%sp)
+ movel %a1,-(%sp)
+ jbsr SYMBOL_NAME(__down_interruptible)
+ movel (%sp)+,%a1
+ movel (%sp)+,%d1
+ rts
+
ENTRY(__up_wakeup)
moveml %a0/%d0/%d1,-(%sp)
movel %a1,-(%sp)
diff --git a/arch/m68k/mm/extable.c b/arch/m68k/mm/extable.c
index 6104120b7..1f8d9e8c3 100644
--- a/arch/m68k/mm/extable.c
+++ b/arch/m68k/mm/extable.c
@@ -34,24 +34,22 @@ unsigned long
search_exception_table(unsigned long addr)
{
unsigned long ret;
-#ifdef CONFIG_MODULES
- struct module *mp;
-#endif
- /* Search the kernel's table first. */
+#ifndef CONFIG_MODULES
+ /* There is only the kernel to search. */
ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
- if (ret)
- return ret;
-
-#ifdef CONFIG_MODULES
+ if (ret) return ret;
+#else
+ /* The kernel is the last "module" -- no need to treat it special. */
+ struct module *mp;
for (mp = module_list; mp != NULL; mp = mp->next) {
- if (mp->exceptinfo.start != NULL) {
- ret = search_one_table(mp->exceptinfo.start,
- mp->exceptinfo.stop-1, addr);
- if (ret)
- return ret;
- }
+ if (mp->ex_table_start == NULL)
+ continue;
+ ret = search_one_table(mp->ex_table_start,
+ mp->ex_table_end-1, addr);
+ if (ret) return ret;
}
#endif
+
return 0;
}
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index 9da322208..71b46e2d9 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -96,7 +96,8 @@ good_area:
* Until I found it, this one cures the problem and makes
* 1.2 run on the 68040 (Martin Apel).
*/
- flush_tlb_page(vma, address);
+ if (CPU_IS_040_OR_060)
+ flush_tlb_page(vma, address);
return 0;
/*
@@ -107,13 +108,10 @@ bad_area:
up(&mm->mmap_sem);
/* Are we prepared to handle this fault? */
- if (CPU_IS_060 && regs->format == 4)
- fault_pc = ((struct frame *)regs)->un.fmt4.pc;
- else
- fault_pc = regs->pc;
+ fault_pc = regs->pc;
if ((fixup = search_exception_table(fault_pc)) != 0) {
struct pt_regs *tregs;
- printk("Exception at %lx (%lx)\n", fault_pc, fixup);
+ printk(KERN_DEBUG "Exception at [<%lx>] (%lx)\n", fault_pc, fixup);
/* Create a new four word stack frame, discarding the old
one. */
regs->stkadj = frame_extra_sizes[regs->format];
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index 3fcc2d904..01cd315dd 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -71,12 +71,12 @@ void show_mem(void)
total++;
if (PageReserved(mem_map+i))
reserved++;
- else if (!mem_map[i].count)
+ else if (!atomic_read(&mem_map[i].count))
free++;
- else if (mem_map[i].count == 1)
+ else if (atomic_read(&mem_map[i].count) == 1)
nonshared++;
else
- shared += mem_map[i].count-1;
+ shared += atomic_read(&mem_map[i].count) - 1;
}
printk("%d pages of RAM\n",total);
printk("%d free pages\n",free);
@@ -102,9 +102,15 @@ pte_t *kernel_page_table (unsigned long *memavailp)
{
pte_t *ptablep;
- ptablep = (pte_t *)*memavailp;
- *memavailp += PAGE_SIZE;
+ if (memavailp) {
+ ptablep = (pte_t *)*memavailp;
+ *memavailp += PAGE_SIZE;
+ }
+ else
+ ptablep = (pte_t *)__get_free_page(GFP_KERNEL);
+ flush_page_to_ram((unsigned long) ptablep);
+ flush_tlb_kernel_page((unsigned long) ptablep);
nocache_page ((unsigned long)ptablep);
return ptablep;
@@ -289,8 +295,6 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
{
int chunk;
unsigned long mem_avail = 0;
- /* pointer to page table for kernel stacks */
- extern unsigned long availmem;
#ifdef DEBUG
{
@@ -318,24 +322,14 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
* tables and thus modify availmem.
*/
- for (chunk = 0; chunk < boot_info.num_memory; chunk++) {
- mem_avail = map_chunk (boot_info.memory[chunk].addr,
- boot_info.memory[chunk].size,
- &availmem);
+ for (chunk = 0; chunk < m68k_num_memory; chunk++) {
+ mem_avail = map_chunk (m68k_memory[chunk].addr,
+ m68k_memory[chunk].size, &start_mem);
}
flush_tlb_all();
#ifdef DEBUG
printk ("memory available is %ldKB\n", mem_avail >> 10);
-#endif
-
- /*
- * virtual address after end of kernel
- * "availmem" is setup by the code in head.S.
- */
- start_mem = availmem;
-
-#ifdef DEBUG
printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
start_mem, end_mem);
#endif
@@ -374,17 +368,17 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
#endif
if (CPU_IS_040_OR_060)
- asm __volatile__ ("movel %0,%/d0\n\t"
- ".long 0x4e7b0806" /* movec d0,urp */
+ asm __volatile__ (".chip 68040\n\t"
+ "movec %0,%%urp\n\t"
+ ".chip 68k"
: /* no outputs */
- : "g" (task[0]->tss.crp[1])
- : "d0");
+ : "r" (task[0]->tss.crp[1]));
else
- asm __volatile__ ("movel %0,%/a0\n\t"
- ".long 0xf0104c00" /* pmove %/a0@,%/crp */
+ asm __volatile__ (".chip 68030\n\t"
+ "pmove %0,%%crp\n\t"
+ ".chip 68k"
: /* no outputs */
- : "g" (task[0]->tss.crp)
- : "a0");
+ : "m" (task[0]->tss.crp[0]));
#ifdef DEBUG
printk ("set crp\n");
#endif
@@ -398,7 +392,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
printk ("before free_area_init\n");
#endif
- return free_area_init (start_mem, end_mem);
+ return PAGE_ALIGN(free_area_init (start_mem, end_mem));
}
void mem_init(unsigned long start_mem, unsigned long end_mem)
@@ -410,7 +404,7 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
end_mem &= PAGE_MASK;
high_memory = (void *) end_mem;
- max_mapnr = MAP_NR(end_mem);
+ max_mapnr = num_physpages = MAP_NR(end_mem);
start_mem = PAGE_ALIGN(start_mem);
while (start_mem < end_mem) {
@@ -460,7 +454,7 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
datapages++;
continue;
}
- mem_map[MAP_NR(tmp)].count = 1;
+ atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
#ifdef CONFIG_BLK_DEV_INITRD
if (!initrd_start ||
(tmp < (initrd_start & PAGE_MASK) || tmp >= initrd_end))
@@ -474,6 +468,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
datapages << (PAGE_SHIFT-10));
}
+void free_initmem(void)
+{
+ /* To be written */
+}
+
void si_meminfo(struct sysinfo *val)
{
unsigned long i;
@@ -487,9 +486,9 @@ void si_meminfo(struct sysinfo *val)
if (PageReserved(mem_map+i))
continue;
val->totalram++;
- if (!mem_map[i].count)
+ if (!atomic_read(&mem_map[i].count))
continue;
- val->sharedram += mem_map[i].count-1;
+ val->sharedram += atomic_read(&mem_map[i].count) - 1;
}
val->totalram <<= PAGE_SHIFT;
val->sharedram <<= PAGE_SHIFT;
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
index 05aa8499d..55d5e98f3 100644
--- a/arch/m68k/mm/memory.c
+++ b/arch/m68k/mm/memory.c
@@ -63,11 +63,12 @@ pmd_t *get_pointer_table (void)
return 0;
}
- if (!(dp->page = __get_free_page (GFP_KERNEL))) {
+ if (!(dp->page = get_free_page (GFP_KERNEL))) {
kfree (dp);
return 0;
}
+ flush_tlb_kernel_page((unsigned long) dp->page);
nocache_page (dp->page);
dp->alloced = 0;
@@ -210,10 +211,11 @@ pmd_t *get_kpointer_table (void)
return NULL;
}
if (!(page = kptr_pages.page[i])) {
- if (!(page = (pmd_tablepage *)__get_free_page(GFP_KERNEL))) {
+ if (!(page = (pmd_tablepage *)get_free_page(GFP_KERNEL))) {
printk("No space for kernel pointer table!\n");
return NULL;
}
+ flush_tlb_kernel_page((unsigned long) page);
nocache_page((u_long)(kptr_pages.page[i] = page));
}
asm volatile("bfset %0@{%1,#1}"
@@ -250,31 +252,94 @@ void free_kpointer_table (pmd_t *pmdp)
}
}
+static unsigned long transp_transl_matches( unsigned long regval,
+ unsigned long vaddr )
+{
+ unsigned long base, mask;
+
+ /* enabled? */
+ if (!(regval & 0x8000))
+ return( 0 );
+
+ if (CPU_IS_030) {
+ /* function code match? */
+ base = (regval >> 4) & 7;
+ mask = ~(regval & 7);
+ if ((SUPER_DATA & mask) != (base & mask))
+ return( 0 );
+ }
+ else {
+ /* must not be user-only */
+ if ((regval & 0x6000) == 0)
+ return( 0 );
+ }
+
+ /* address match? */
+ base = regval & 0xff000000;
+ mask = ~((regval << 8) & 0xff000000);
+ return( (vaddr & mask) == (base & mask) );
+}
+
/*
* The following two routines map from a physical address to a kernel
* virtual address and vice versa.
*/
unsigned long mm_vtop (unsigned long vaddr)
{
- int i;
+ int i=0;
unsigned long voff = vaddr;
unsigned long offset = 0;
- for (i = 0; i < boot_info.num_memory; i++)
- {
- if (voff < offset + boot_info.memory[i].size) {
+ do{
+ if (voff < offset + m68k_memory[i].size) {
#ifdef DEBUGPV
printk ("VTOP(%lx)=%lx\n", vaddr,
- boot_info.memory[i].addr + voff - offset);
+ m68k_memory[i].addr + voff - offset);
#endif
- return boot_info.memory[i].addr + voff - offset;
+ return m68k_memory[i].addr + voff - offset;
} else
- offset += boot_info.memory[i].size;
+ offset += m68k_memory[i].size;
+ i++;
+ }while (i < m68k_num_memory);
+
+ /* not in one of the memory chunks; test for applying transparent
+ * translation */
+
+ if (CPU_IS_030) {
+ unsigned long ttreg;
+
+ asm volatile( ".chip 68030\n\t"
+ "pmove %/tt0,%0@\n\t"
+ ".chip 68k"
+ : : "a" (&ttreg) );
+ if (transp_transl_matches( ttreg, vaddr ))
+ return vaddr;
+ asm volatile( ".chip 68030\n\t"
+ "pmove %/tt1,%0@\n\t"
+ ".chip 68k"
+ : : "a" (&ttreg) );
+ if (transp_transl_matches( ttreg, vaddr ))
+ return vaddr;
+ }
+ else if (CPU_IS_040_OR_060) {
+ unsigned long ttreg;
+
+ asm volatile( ".chip 68040\n\t"
+ "movec %%dtt0,%0\n\t"
+ ".chip 68k"
+ : "=d" (ttreg) );
+ if (transp_transl_matches( ttreg, vaddr ))
+ return vaddr;
+ asm volatile( ".chip 68040\n\t"
+ "movec %%dtt1,%0\n\t"
+ ".chip 68k"
+ : "=d" (ttreg) );
+ if (transp_transl_matches( ttreg, vaddr ))
+ return vaddr;
}
- /* not in one of the memory chunks; get the actual
- * physical address from the MMU.
- */
+ /* no match, too, so get the actual physical address from the MMU. */
+
if (CPU_IS_060) {
unsigned long fs = get_fs();
unsigned long paddr;
@@ -284,12 +349,11 @@ unsigned long mm_vtop (unsigned long vaddr)
/* The PLPAR instruction causes an access error if the translation
* is not possible. We don't catch that here, so a bad kernel trap
* will be reported in this case. */
- asm volatile ("movel %1,%/a0\n\t"
- ".word 0xf5c8\n\t" /* plpar (a0) */
- "movel %/a0,%0"
- : "=g" (paddr)
- : "g" (vaddr)
- : "a0" );
+ asm volatile (".chip 68060\n\t"
+ "plpar (%0)\n\t"
+ ".chip 68k"
+ : "=a" (paddr)
+ : "0" (vaddr));
set_fs (fs);
return paddr;
@@ -300,13 +364,12 @@ unsigned long mm_vtop (unsigned long vaddr)
set_fs (SUPER_DATA);
- asm volatile ("movel %1,%/a0\n\t"
- ".word 0xf568\n\t" /* ptestr (a0) */
- ".long 0x4e7a8805\n\t" /* movec mmusr, a0 */
- "movel %/a0,%0"
- : "=g" (mmusr)
- : "g" (vaddr)
- : "a0", "d0");
+ asm volatile (".chip 68040\n\t"
+ "ptestr (%1)\n\t"
+ "movec %%mmusr, %0\n\t"
+ ".chip 68k"
+ : "=r" (mmusr)
+ : "a" (vaddr));
set_fs (fs);
if (mmusr & MMU_R_040)
@@ -347,22 +410,22 @@ unsigned long mm_vtop (unsigned long vaddr)
unsigned long mm_ptov (unsigned long paddr)
{
- int i;
+ int i = 0;
unsigned long offset = 0;
- for (i = 0; i < boot_info.num_memory; i++)
- {
- if (paddr >= boot_info.memory[i].addr &&
- paddr < (boot_info.memory[i].addr
- + boot_info.memory[i].size)) {
+ do{
+ if (paddr >= m68k_memory[i].addr &&
+ paddr < (m68k_memory[i].addr
+ + m68k_memory[i].size)) {
#ifdef DEBUGPV
printk ("PTOV(%lx)=%lx\n", paddr,
- (paddr - boot_info.memory[i].addr) + offset);
+ (paddr - m68k_memory[i].addr) + offset);
#endif
- return (paddr - boot_info.memory[i].addr) + offset;
+ return (paddr - m68k_memory[i].addr) + offset;
} else
- offset += boot_info.memory[i].size;
- }
+ offset += m68k_memory[i].size;
+ i++;
+ }while (i < m68k_num_memory);
/*
* assume that the kernel virtual address is the same as the
@@ -389,62 +452,67 @@ unsigned long mm_ptov (unsigned long paddr)
}
/* invalidate page in both caches */
-#define clear040(paddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
- "nop\n\t"\
- ".word 0xf4d0"\
- /* CINVP I/D (a0) */\
- : : "g" ((paddr))\
- : "a0")
+#define clear040(paddr) \
+ __asm__ __volatile__ ("nop\n\t" \
+ ".chip 68040\n\t" \
+ "cinvp %%bc,(%0)\n\t" \
+ ".chip 68k" \
+ : : "a" (paddr))
/* invalidate page in i-cache */
-#define cleari040(paddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
- /* CINVP I (a0) */\
- "nop\n\t"\
- ".word 0xf490"\
- : : "g" ((paddr))\
- : "a0")
+#define cleari040(paddr) \
+ __asm__ __volatile__ ("nop\n\t" \
+ ".chip 68040\n\t" \
+ "cinvp %%ic,(%0)\n\t" \
+ ".chip 68k" \
+ : : "a" (paddr))
/* push page in both caches */
-#define push040(paddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
- "nop\n\t"\
- ".word 0xf4f0"\
- /* CPUSHP I/D (a0) */\
- : : "g" ((paddr))\
- : "a0")
+#define push040(paddr) \
+ __asm__ __volatile__ ("nop\n\t" \
+ ".chip 68040\n\t" \
+ "cpushp %%bc,(%0)\n\t" \
+ ".chip 68k" \
+ : : "a" (paddr))
/* push and invalidate page in both caches */
-#define pushcl040(paddr) do { push040((paddr));\
- if (CPU_IS_060) clear040((paddr));\
- } while(0)
+#define pushcl040(paddr) \
+ do { push040(paddr); \
+ if (CPU_IS_060) clear040(paddr); \
+ } while(0)
/* push page in both caches, invalidate in i-cache */
-#define pushcli040(paddr) do { push040((paddr));\
- if (CPU_IS_060) cleari040((paddr));\
- } while(0)
+#define pushcli040(paddr) \
+ do { push040(paddr); \
+ if (CPU_IS_060) cleari040(paddr); \
+ } while(0)
/* push page defined by virtual address in both caches */
-#define pushv040(vaddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
- /* ptestr (a0) */\
- "nop\n\t"\
- ".word 0xf568\n\t"\
- /* movec mmusr,d0 */\
- ".long 0x4e7a0805\n\t"\
- "andw #0xf000,%/d0\n\t"\
- "movel %/d0,%/a0\n\t"\
- /* CPUSHP I/D (a0) */\
- "nop\n\t"\
- ".word 0xf4f0"\
- : : "g" ((vaddr))\
- : "a0", "d0")
+#define pushv040(vaddr) \
+ do { unsigned long _tmp1, _tmp2; \
+ __asm__ __volatile__ ("nop\n\t" \
+ ".chip 68040\n\t" \
+ "ptestr (%2)\n\t" \
+ "movec %%mmusr,%0\n\t" \
+ "andw #0xf000,%0\n\t" \
+ "movel %0,%1\n\t" \
+ "nop\n\t" \
+ "cpushp %%bc,(%1)\n\t" \
+ ".chip 68k" \
+ : "=d" (_tmp1), "=a" (_tmp2) \
+ : "a" (vaddr)); \
+ } while (0)
/* push page defined by virtual address in both caches */
-#define pushv060(vaddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
- /* plpar (a0) */\
- ".word 0xf5c8\n\t"\
- /* CPUSHP I/D (a0) */\
- ".word 0xf4f0"\
- : : "g" ((vaddr))\
- : "a0")
+#define pushv060(vaddr) \
+ do { unsigned long _tmp; \
+ __asm__ __volatile__ (".chip 68060\n\t" \
+ "plpar (%0)\n\t" \
+ "cpushp %%bc,(%0)\n\t" \
+ ".chip 68k" \
+ : "=a" (_tmp) \
+ : "0" (vaddr)); \
+ } while (0)
/*
@@ -633,9 +701,8 @@ int mm_end_of_chunk (unsigned long addr, int len)
{
int i;
- for (i = 0; i < boot_info.num_memory; i++)
- if (boot_info.memory[i].addr + boot_info.memory[i].size
- == addr + len)
+ for (i = 0; i < m68k_num_memory; i++)
+ if (m68k_memory[i].addr + m68k_memory[i].size == addr + len)
return 1;
return 0;
}