Also, don't forget http://www.linuxhq.com/ for all your Linux kernel
needs.
-Last updated: April 15, 1997.
+Last updated: April 17, 1997.
Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
Current Minimal Requirements
Binutils: ld -v
Gnu C: gcc -v or gcc --version
-Kbd: loadkeys -h
+Kbd: dumpkeys -h
Ld.so: ldd -v
Libc: ls -l /lib/libc.so.*
Libc++: ls -l /usr/lib/libg++.so.*
The 2.1.34 release:
ftp://ftp.redhat.com/pub/alphabits/modutils-2.1.34.tar.gz
-ftp://ftp.kernel.org/pub/linux/kernel/modutils-2.1.34.tar.gz
+ftp://ftp.kernel.org/pub/linux/kernel/v2.1/modutils-2.1.34.tar.gz
Procps utilities
================
Documentation/networking/net-modules.txt. The module will be called
pt.o.
-WaveLAN support
+AT&T WaveLAN & DEC RoamAbout DS support
CONFIG_WAVELAN
- These are cards for wireless ethernet-like networking. Supported are
- AT&T GIS and NCR WaveLAN cards. If you want to use a card of this
- type under Linux, say Y and read the Ethernet-HOWTO, available via
- ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Some
- more specific information is contained in
- drivers/net/README.wavelan. This driver is also available as a
- module ( = code which can be inserted in and removed from the
- running kernel whenever you want). The module will be called
- wavelan.o. If you want to compile it as a module, say M here and
- read Documentation/modules.txt as well as
- Documentation/networking/net-modules.txt. If you plan to use more
- than one network card under linux, read the
- Multiple-Ethernet-mini-HOWTO, available from
- sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
+ The Lucent Wavelan (formerly NCR and AT&T ; or DEC RoamAbout DS)
+ is a Radio LAN (wireless ethernet-like) at 900 MHz and 2.4 GHz.
+ This driver support the ISA version of the Wavelan. A driver for
+ the pcmcia hardware is available in David Hinds's pcmcia package.
+ This driver is fairly stable and may be compiled as a module
+ (wavelan.o). It implements many nice feature and the Wireless
+ Extensions (you must get the Wireless tools from the net).
+ For documentation, refer to :
+ o the wavelan man page, wireless tools man pages
+ o wavelan.p.h and the source code
+ o Ethernet-HOWTO, Multiple-Ethernet-mini-HOWTO, Module-HOWTO
+ o More documentation to come when I will have the time :-)
HP PCLAN+ (27247B and 27252A) support
CONFIG_HPLAN_PLUS
Also:
* If you selected the device autoprobe at compile time, you can say
-`lp=auto' on the kernel command line, and lp will create devices only
-for those ports that seem to have printers attached.
+ `lp=auto' on the kernel command line, and lp will create devices
+ only for those ports that seem to have printers attached.
* If you give PLIP the `timid' parameter, either with `plip=timid' on
-the command line, or with `insmod plip timid=1' when using modules, it
-will avoid any ports that seem to be in use by other devices.
+ the command line, or with `insmod plip timid=1' when using modules,
+ it will avoid any ports that seem to be in use by other devices.
+
+ * If your BIOS allows you to engage "ECP mode", you may find that
+ your port's IRQ can be autoprobed, without having to specify any
+ parameters.
VERSION = 2
PATCHLEVEL = 1
-SUBLEVEL = 35
+SUBLEVEL = 36
ARCH := $(shell uname -m | sed s/i.86/i386/)
FILESYSTEMS =fs/filesystems.a
NETWORKS =net/network.a
DRIVERS =drivers/block/block.a \
- drivers/char/char.a
+ drivers/char/char.a \
+ drivers/pnp/pnp.a
LIBS =$(TOPDIR)/lib/lib.a
SUBDIRS =kernel drivers mm fs net ipc lib
DRIVERS := $(DRIVERS) drivers/pci/pci.a
endif
-ifdef CONFIG_PNP
-DRIVERS := $(DRIVERS) drivers/pnp/pnp.a
-endif
-
ifdef CONFIG_SBUS
DRIVERS := $(DRIVERS) drivers/sbus/sbus.a
endif
int prio;
/*
- * We don't need to aquire the kernel lock here, because
+ * We don't need to acquire the kernel lock here, because
* all of these operations are local. sys_getpriority
* will get the lock as required..
*/
}
/*
- * No need to aquire the kernel lock, we're local..
+ * No need to acquire the kernel lock, we're local..
*/
asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5,
struct pt_regs regs)
/*
* This isn't strictly "local" any more and we should actually
- * aquire the kernel lock. The "p_opptr" pointer might change
+ * acquire the kernel lock. The "p_opptr" pointer might change
* if the parent goes away (or due to ptrace). But any race
* isn't actually going to matter, as if the parent happens
* to change we can happily return either of the pids.
#include <asm/io.h>
/*
- * No need to aquire the kernel lock, we're entirely local..
+ * No need to acquire the kernel lock, we're entirely local..
*/
asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
unsigned long a3, unsigned long a4, unsigned long a5,
* We change the range to -1 .. 1 in order to let gcc easily
* use the conditional move instructions.
*
- * Note that we don't need to aquire the kernel lock for SMP
+ * Note that we don't need to acquire the kernel lock for SMP
* operation, as all of this is local to this thread.
*/
asmlinkage unsigned long osf_sigprocmask(int how, unsigned long newmask,
CPP=$(CC) -E
OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
LDFLAGS=-e stext
-LINKFLAGS =-T arch/i386/vmlinux.lds $(LDFLAGS)
+LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinux.lds $(LDFLAGS)
CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce
cp $(TOPDIR)/System.map $(INSTALL_PATH)/
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-install: $(CONFIGURE) zImage
- sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
+install: $(CONFIGURE) $(BOOTIMAGE)
+ sh -x ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) $(BOOTIMAGE) $(TOPDIR)/System.map "$(INSTALL_PATH)"
tools/build: tools/build.c
$(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include
outb (0x00, 0xCFB);
outb (0x00, 0xCF8);
outb (0x00, 0xCFA);
- if (inb (0xCF8) == 0x00 && inb (0xCFC) == 0x00) {
+ if (inb (0xCF8) == 0x00 && inb (0xCFB) == 0x00) {
restore_flags(flags);
printk("pcibios_init: Using configuration type 2\n");
return &pci_direct_conf2;
#include <linux/mca.h>
#include <linux/sched.h>
#include <linux/in6.h>
+#include <linux/interrupt.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
EXPORT_SYMBOL_NOVERS(__up_wakeup);
-
+EXPORT_SYMBOL(__intel_bh_counter);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy);
EXPORT_SYMBOL(active_kernel_processor);
EXPORT_SYMBOL(smp_invalidate_needed);
EXPORT_SYMBOL_NOVERS(__lock_kernel);
+
+/* Global SMP irq stuff */
+EXPORT_SYMBOL(global_irq_holder);
+EXPORT_SYMBOL(__global_cli);
+EXPORT_SYMBOL(__global_sti);
+EXPORT_SYMBOL(__global_save_flags);
+EXPORT_SYMBOL(__global_restore_flags);
#endif
#ifdef CONFIG_MCA
* other interrupts would have to avoid using the jiffies variable for delay
* and interval timing operations to avoid hanging the system.
*/
+
+#if NR_IRQS != 16
+#error make irq stub building NR_IRQS dependent and remove me.
+#endif
+
BUILD_TIMER_IRQ(FIRST,0,0x01)
BUILD_IRQ(FIRST,1,0x02)
BUILD_IRQ(FIRST,2,0x04)
int i, len = 0;
struct irqaction * action;
- for (i = 0 ; i < 16 ; i++) {
+ for (i = 0 ; i < NR_IRQS ; i++) {
action = irq_action[i];
if (!action)
continue;
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
- for (i = 0; i < 16 ; i++)
+ for (i = 0; i < NR_IRQS ; i++)
set_intr_gate(0x20+i,bad_interrupt[i]);
- /*
- * This bit is a hack because we don't send timer messages to all
- * processors yet. It has to be here .. it doesn't work if you put
- * it down the bottom - assembler explodes 8)
- */
-
#ifdef __SMP__
/*
* NOTE! The local APIC isn't very good at handling
* want to spread these out a bit so that they don't
* all fall in the same interrupt level
*/
+
+ /*
+ * The reschedule interrupt slowly changes it's functionality,
+ * while so far it was a kind of broadcasted timer interrupt,
+ * in the future it should become a CPU-to-CPU rescheduling IPI,
+ * driven by schedule() ?
+ *
+ * [ It has to be here .. it doesn't work if you put
+ * it down the bottom - assembler explodes 8) ]
+ */
/* IRQ '16' (trap 0x30) - IPI for rescheduling */
set_intr_gate(0x20+i, reschedule_interrupt);
+
/* IRQ '17' (trap 0x31) - IPI for invalidation */
set_intr_gate(0x21+i, invalidate_interrupt);
UNBLK_##chip(mask) \
"jmp ret_from_intr\n");
+/*
+ * x86 profiling function, SMP safe. We might want to do this in
+ * assembly totally?
+ */
+static inline void x86_do_profile (unsigned long eip)
+{
+ if (prof_buffer && current->pid) {
+ extern int _stext;
+ eip -= (unsigned long) &_stext;
+ eip >>= prof_shift;
+ if (eip < prof_len)
+ atomic_inc((atomic_t *)&prof_buffer[eip]);
+ else
+ /*
+ * Dont ignore out-of-bounds EIP values silently,
+ * put them into the last histogram slot, so if
+ * present, they will show up as a sharp peak.
+ */
+ atomic_inc((atomic_t *)&prof_buffer[prof_len-1]);
+ }
+}
+
#endif
asmlinkage void syscall_trace(void)
{
- lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS))
- goto out;
+ return;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
notify_parent(current);
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
- if (current->exit_code)
+ if (current->exit_code) {
+ spin_lock_irq(¤t->sigmask_lock);
current->signal |= (1 << (current->exit_code - 1));
+ spin_unlock_irq(¤t->sigmask_lock);
+ }
current->exit_code = 0;
-out:
- unlock_kernel();
}
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
-asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
+asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
+ int options, unsigned long *ru);
+
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs);
/*
*/
asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
{
+ struct pt_regs * regs = (struct pt_regs *) &restart;
unsigned long mask;
- struct pt_regs * regs;
- int res = -EINTR;
- lock_kernel();
- regs = (struct pt_regs *) &restart;
+ spin_lock_irq(¤t->sigmask_lock);
mask = current->blocked;
current->blocked = set & _BLOCKABLE;
+ spin_unlock_irq(¤t->sigmask_lock);
+
regs->eax = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(mask,regs))
- goto out;
+ if (do_signal(mask, regs))
+ return -EINTR;
}
-out:
- unlock_kernel();
- return res;
}
static inline void restore_i387_hard(struct _fpstate *buf)
__asm__("mov %w0,%%" #seg: :"r" (tmp)); }
struct sigcontext * context;
struct pt_regs * regs;
- int res;
- lock_kernel();
regs = (struct pt_regs *) &__unused;
context = (struct sigcontext *) regs->esp;
if (verify_area(VERIFY_READ, context, sizeof(*context)))
goto badframe;
restore_i387(buf);
}
- res = context->eax;
- unlock_kernel();
- return res;
+ return context->eax;
+
badframe:
+ lock_kernel();
do_exit(SIGSEGV);
+ unlock_kernel();
}
static inline struct _fpstate * save_i387_hard(struct _fpstate * buf)
frame = (unsigned long *) sa->sa_restorer;
frame -= 64;
if (!access_ok(VERIFY_WRITE,frame,64*4))
- do_exit(SIGSEGV);
+ goto segv_and_exit;
/* set up the "normal" stack seen by the signal handler (iBCS2) */
#define __CODE ((unsigned long)(frame+24))
We use __put_user() here because the access_ok() call was already
done earlier. */
if (__put_user(__CODE,frame))
- do_exit(SIGSEGV);
+ goto segv_and_exit;
if (current->exec_domain && current->exec_domain->signal_invmap)
__put_user(current->exec_domain->signal_invmap[signr], frame+1);
else
regs->xcs = USER_CS;
}
regs->eflags &= ~TF_MASK;
+ return;
+
+segv_and_exit:
+ lock_kernel();
+ do_exit(SIGSEGV);
+ unlock_kernel();
}
/*
if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
- if (!(sa->sa_flags & SA_NOMASK))
+ if (!(sa->sa_flags & SA_NOMASK)) {
+ spin_lock_irq(¤t->sigmask_lock);
current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE;
+ spin_unlock_irq(¤t->sigmask_lock);
+ }
}
/*
unsigned long mask;
unsigned long signr;
struct sigaction * sa;
- int res;
- lock_kernel();
mask = ~current->blocked;
while ((signr = current->signal & mask)) {
/*
*/
struct task_struct *t=current;
__asm__("bsf %3,%1\n\t"
+#ifdef __SMP__
+ "lock ; "
+#endif
"btrl %1,%0"
:"=m" (t->signal),"=r" (signr)
:"0" (t->signal), "1" (signr));
if (signr == SIGSTOP)
continue;
if (_S(signr) & current->blocked) {
+ spin_lock_irq(¤t->sigmask_lock);
current->signal |= _S(signr);
+ spin_unlock_irq(¤t->sigmask_lock);
continue;
}
sa = current->sig->action + signr - 1;
if (signr != SIGCHLD)
continue;
/* check for SIGCHLD: it's special */
- while (sys_waitpid(-1,NULL,WNOHANG) > 0)
+ while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
}
/* fall through */
default:
+ spin_lock_irq(¤t->sigmask_lock);
current->signal |= _S(signr & 0x7f);
+ spin_unlock_irq(¤t->sigmask_lock);
+
current->flags |= PF_SIGNALED;
+
+ lock_kernel(); /* 8-( */
do_exit(signr);
+ unlock_kernel();
}
}
handle_signal(signr, sa, oldmask, regs);
- res = 1;
- goto out;
+ return 1;
}
/* Did we come from a system call? */
regs->eip -= 2;
}
}
- res = 0;
-out:
- unlock_kernel();
- return res;
+ return 0;
}
#include "irq.h"
extern unsigned long start_kernel, _etext;
+extern void update_one_process( struct task_struct *p,
+ unsigned long ticks, unsigned long user,
+ unsigned long system);
void setup_APIC_clock (void);
/*
/* printk("SMID\n");*/
}
-/*
- * Platform specific profiling function.
- * it builds a 'prof_shift' resolution EIP distribution histogram
- *
- * it's SMP safe.
- */
-
-static inline void x86_do_profile (unsigned long eip)
-{
- if (prof_buffer && current->pid) {
- extern int _stext;
- eip -= (unsigned long) &_stext;
- eip >>= prof_shift;
- if (eip < prof_len)
- atomic_inc(&prof_buffer[eip]);
- else
- /*
- * Dont ignore out-of-bounds EIP values silently,
- * put them into the last histogram slot, so if
- * present, they will show up as a sharp peak.
- */
- atomic_inc(&prof_buffer[prof_len-1]);
- }
-}
-
-unsigned int prof_multiplier[NR_CPUS];
-unsigned int prof_counter[NR_CPUS];
-
-extern void update_one_process( struct task_struct *p,
- unsigned long ticks, unsigned long user,
- unsigned long system);
/*
* Local timer interrupt handler. It does both profiling and
* process statistics/rescheduling.
* multiplier is 1 and it can be changed by writing a 4 bytes multiplier
* value into /proc/profile.
*/
+
+unsigned int prof_multiplier[NR_CPUS];
+unsigned int prof_counter[NR_CPUS];
+
static inline void smp_local_timer_interrupt(struct pt_regs * regs)
{
int cpu = smp_processor_id();
+
/*
- * Both the profiling function and the statistics
- * counters are SMP safe. We leave the APIC irq
- * unacked while updating the profiling info, thus
- * we cannot be interrupted by the same APIC interrupt.
+ * The profiling function is SMP safe. (nothing can mess
+ * around with "current", and the profiling counters are
+ * updated with atomic operations). This is especially
+ * useful with a profiling multiplier != 1
*/
if (!user_mode(regs))
x86_do_profile (regs->eip);
struct task_struct * p = current;
/*
- * We mess around with thread statistics, but
- * since we are the CPU running it, we dont
- * have to lock it. We assume that switch_to()
- * protects 'current' against local irqs via __cli.
- *
- * kernel statistics counters are updated via atomic
- * operations.
+ * After doing the above, we need to make like
+ * a normal interrupt - otherwise timer interrupts
+ * ignore the global interrupt lock, which is the
+ * WrongThing (tm) to do.
*/
if (user_mode(regs))
else
system=1;
+ irq_enter(cpu, 0);
if (p->pid) {
+
update_one_process(p, 1, user, system);
p->counter -= 1;
need_resched = 1;
}
if (p->priority < DEF_PRIORITY)
- atomic_add (user, &kstat.cpu_nice);
+ kstat.cpu_nice += user;
else
- atomic_add (user, &kstat.cpu_user);
+ kstat.cpu_user += user;
- atomic_add (system, &kstat.cpu_system);
+ kstat.cpu_system += system;
} else {
#ifdef __SMP_PROF__
if (test_bit(cpu,&smp_idle_map))
smp_idle_count[cpu]++;
#endif
- /*
- * This is a hack until we have need_resched[]
- */
- if (read_smp_counter(&smp_process_available))
- need_resched=1;
}
-
prof_counter[cpu]=prof_multiplier[cpu];
+
+ irq_exit(cpu, 0);
}
#ifdef __SMP_PROF__
*/
void smp_apic_timer_interrupt(struct pt_regs * regs)
{
- int cpu = smp_processor_id();
-
/*
* NOTE! We'd better ACK the irq immediately,
* because timer handling can be slow, and we
*/
ack_APIC_irq ();
- /*
- * After doing the above, we need to make like
- * a normal interrupt - otherwise timer interrupts
- * ignore the global interrupt lock, which is the
- * WrongThing (tm) to do.
- */
- irq_enter(cpu, 0);
smp_local_timer_interrupt(regs);
- irq_exit(cpu, 0);
}
/*
#include <linux/timex.h>
#include <linux/config.h>
+/*
+ * for x86_do_profile()
+ */
+#include "irq.h"
+
extern int setup_x86_irq(int, struct irqaction *);
extern volatile unsigned long lost_ticks;
/* last time the cmos clock got updated */
static long last_rtc_update = 0;
-
-/*
- * Move this to a header file - right now it shows
- * up both here and in smp.c
- */
-static inline void x86_do_profile (unsigned long eip)
-{
- if (prof_buffer && current->pid) {
- extern int _stext;
- eip -= (unsigned long) &_stext;
- eip >>= prof_shift;
- if (eip < prof_len)
- atomic_inc(&prof_buffer[eip]);
- else
- /*
- * Dont ignore out-of-bounds EIP values silently,
- * put them into the last histogram slot, so if
- * present, they will show up as a sharp peak.
- */
- atomic_inc(&prof_buffer[prof_len-1]);
- }
-}
-
/*
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
atomic_set(&mem_map[MAP_NR(addr)].count, 1);
free_page(addr);
}
+ printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
}
void si_meminfo(struct sysinfo *val)
LINKFLAGS = -Ttext 0x1000
-CFLAGS := $(CFLAGS) -pipe
+CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce
ifdef CONFIG_OPTIMIZE_040
CFLAGS := $(CFLAGS) -m68040
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/lib
-ARCHIVES := arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o $(ARCHIVES)
+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
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:
O_OBJS := $(O_OBJS) cyberfb.o
endif
+ifdef CONFIG_FB_RETINAZ3
+O_OBJS := $(O_OBJS) retz3fb.o
+endif
+
include $(TOPDIR)/Rules.make
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
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);
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,
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()) {
#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 |
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;
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);
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)
{
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) {
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();
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) {
-#include <linux/types.h>
+#include <linux/config.h>
#include <linux/module.h>
-#include <asm/zorro.h>
+#include <linux/types.h>
+#include <linux/zorro.h>
#include <asm/amigahw.h>
extern volatile u_short amiga_audio_min_period;
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]) {
__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;
}
/* 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;
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)
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;
}
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;
}
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]++;
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--;
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) {
/* 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);
}
}
/* 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)
/* 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);
}
}
/* 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);
}
}
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}
};
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;
}
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;
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++) {
{
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,
#include <asm/amigaints.h>
#include <asm/irq.h>
#include <asm/machdep.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
u_long amiga_model;
u_long amiga_eclock;
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);
extern void amiga_floppy_setup(char *, int *);
#endif
static void amiga_reset (void);
-static void amiga_waitbut(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);
+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 *);
-extern void amiga_syms_export(void);
+
+static struct console amiga_console_driver = {
+ NULL, NULL, amiga_wait_key
+};
extern void (*kd_mksound)(unsigned int, unsigned int);
memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
+ amiga_debug_init();
+
printk("Amiga hardware found: ");
if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
printk("[%s] ", amiga_models[amiga_model-AMI_500]);
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_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;
- mach_syms_export = amiga_syms_export;
kd_mksound = amiga_mksound;
/* Fill in the clock values (based on the 700 kHz E-Clock) */
/* 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
return 0;
}
-static void amiga_waitbut (void)
+static void amiga_wait_key (void)
{
int i;
}
}
-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))
- ;
- }
-}
-
-static 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];
("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));
/* 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");
}
-extern void *amiga_chip_alloc(long size);
+ /*
+ * Debugging
+ */
#define SAVEKMSG_MAXMEM 128*1024
-
#define SAVEKMSG_MAGIC1 0x53415645 /* 'SAVE' */
#define SAVEKMSG_MAGIC2 0x4B4D5347 /* 'KMSG' */
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;
savekmsg->size = 0;
}
+static void amiga_serial_putc(char c)
+{
+ custom.serdat = (unsigned char)c | 0x100;
+ while (!(custom.serdatr & 0x2000))
+ ;
+}
+
+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));
+}
-static void ami_mem_print(const char *b)
+void amiga_serial_gets(char *s, int len)
{
- int len;
+ int ch, cnt = 0;
- for (len = 0; b[len]; len++);
- if (savekmsg->size+len <= SAVEKMSG_MAXMEM) {
- memcpy(savekmsg->data+savekmsg->size, b, len);
- savekmsg->size += len;
+ 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);
}
+ /*
+ * Amiga specific parts of /proc
+ */
+
static void amiga_get_model(char *model)
{
strcpy(model, "Amiga ");
#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"
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);
/*
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);
}
+ /*
+ * 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
*/
#include <asm/setup.h>
#include <asm/bitops.h>
#include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
#ifdef CONFIG_ZORRO
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)
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)
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)
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
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)
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)
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
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
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
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)
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)
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
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
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)
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
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)
BEGIN_PROD(APOLLO2)
PROD("A620 68020 Accelerator", A620)
+ PROD("A620 68020 Accelerator", A620_2)
END
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
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
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)
MANUF("Pacific Peripherals", PACIFIC)
MANUF("Kupke", KUPKE)
MANUF("Memphis", MEMPHIS)
+ MANUF("3-State", 3_STATE)
MANUF("Commodore", COMMODORE2)
MANUF("Commodore", COMMODORE)
MANUF("Commodore", COMMODORE3)
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)
MANUF("Synergy", SYNERGY)
MANUF("Xetec", XETEC)
MANUF("Progressive Peripherals", PPI)
+ MANUF("Xebec", XEBEC)
MANUF("Spirit", SPIRIT)
MANUF("BSC", BSC)
MANUF("BSC", BSC3)
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)
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)
MANUF("DPS", DPS)
MANUF("Apollo", APOLLO2)
MANUF("Apollo", APOLLO)
+ MANUF("Petsoff LP", PETSOFF)
MANUF("Uwe Gerlach", UWE_GERLACH)
MANUF("MacroSystems", MACROSYSTEMS2)
MANUF("Combitec", COMBITEC)
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) {
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)
{
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]);
* 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:
*
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" \
" 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" \
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
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 */
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);
*/
#include <linux/sched.h>
+#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/keyboard.h>
/* 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)
/*
{
/* 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;
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;
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();
+#include <linux/config.h>
#include <linux/module.h>
#include <asm/ptrace.h>
#include <asm/traps.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(atari_mouse_buttons);
EXPORT_SYMBOL(atari_mouse_interrupt_hook);
EXPORT_SYMBOL(atari_MIDI_interrupt_hook);
-EXPORT_SYMBOL(atari_mch_cookie);
+EXPORT_SYMBOL(atari_SCC_reset_done);
EXPORT_SYMBOL(ikbd_write);
EXPORT_SYMBOL(ikbd_mouse_y0_top);
EXPORT_SYMBOL(ikbd_mouse_thresh);
#include <asm/pgtable.h>
#include <asm/machdep.h>
+#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 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);
extern int atari_floppy_init (void);
extern void atari_floppy_setup(char *, int *);
#endif
-static void atari_waitbut (void);
extern struct consw fb_con;
extern struct fb_info *atari_fb_init(long *);
-static void atari_debug_init (void);
+static void atari_debug_init(void);
extern void atari_video_setup(char *, int *);
-extern void atari_syms_export(void);
+
+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);
{
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;
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;
- mach_syms_export = atari_syms_export;
kd_mksound = atari_mksound;
/* ++bjoern:
*/
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! */
}
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 " );
}
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);
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 );
ATARIHW_SET(ANALOG_JOY);
printk( "ANALOG_JOY " );
}
- if (hwreg_present( blitter.halftone )) {
+ if (!is_hades && hwreg_present( blitter.halftone )) {
ATARIHW_SET(BLITTER);
printk( "BLITTER " );
}
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,
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 " );
}
* 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");
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/
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;
}
/* 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 */
return retval;
}
-
-static 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 */
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++ );
}
}
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++ );
}
}
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;
}
}
-static 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,
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 */
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 */
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:
/* 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 */
if (is_medusa)
/* Medusa has TT _MCH cookie */
strcat (model, "Medusa");
+ else if (is_hades)
+ strcat(model, "Hades");
else
strcat (model, "TT");
break;
ATARIHW_ANNOUNCE(SCU, "System Control Unit");
ATARIHW_ANNOUNCE(BLITTER, "Blitter");
ATARIHW_ANNOUNCE(VME, "VME Bus");
+ ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
return(len);
}
#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>
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;
}
read_joystick,
write_joystick,
NULL, /* joystick_readdir */
- joystick_select,
+ joystick_poll,
NULL, /* joystick_ioctl */
NULL, /* joystick_mmap */
open_joystick,
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;
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?
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:
/* Library Bases */
+long __oslibversion = 36;
extern const struct ExecBase *SysBase;
-const struct ExpansionBase *ExpansionBase;
-const struct GfxBase *GfxBase;
static const char *memfile_name = NULL;
static void Close(int fd);
static int FileSize(const char *path);
static void Sleep(u_long micros);
-static int ModifyBootinfo(struct amiga_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"
- " -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\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);
}
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;
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"))
} 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;
}
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
*/
}
}
+ 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.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);
}
static void Puts(const char *str)
{
fputs(str, stderr);
+ fflush(stderr);
}
static long GetChar(void)
static void PutChar(char c)
{
fputc(c, stderr);
+ fflush(stderr);
}
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)
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);
}
DeleteMsgPort(TimerPort);
}
}
-
-
-static int ModifyBootinfo(struct amiga_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->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->model = model;
-
- return(TRUE);
-}
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)
{
* 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)
*/
#define BOOTINFO_COMPAT_1_0 /* bootinfo interface version 1.0 compatible */
+/* support compressed kernels? */
+#define ZKERNEL
#include <stddef.h>
#include <string.h>
static const struct linuxboot_args *linuxboot_args;
/* Bootinfo */
-static struct amiga_bootinfo bi;
+struct amiga_bootinfo bi;
#ifdef BOOTINFO_COMPAT_1_0
static struct compat_bootinfo compat_bootinfo;
#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 Close linuxboot_args->close
#define FileSize linuxboot_args->filesize
#define Sleep linuxboot_args->sleep
-#define ModifyBootinfo linuxboot_args->modify_bootinfo
-
/*
* Function Prototypes
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
/*
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;
Puts("\nLinux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n");
Puts("Copyright 1993,1994 by Hamish Macdonald and Greg Harp\n\n");
- memset(&bi, 0, sizeof(bi));
+ /* Note: Initial values in bi override detected values */
+ bi = args->bi;
/* machine is Amiga */
bi.machtype = MACH_AMIGA;
/* determine chipset */
- bi.chipset = get_chipset();
+ if (!bi.chipset)
+ bi.chipset = get_chipset();
/* determine CPU, FPU and MMU type */
- get_processor(&bi.cputype, &bi.fputype, &bi.mmutype);
+ if (!bi.cputype)
+ get_processor(&bi.cputype, &bi.fputype, &bi.mmutype);
/* determine Amiga model */
- bi.model = get_model(bi.chipset);
+ 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.num_autocon = 0;
- 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 */
- memcpy(&bi.autocon[bi.num_autocon], cdp, sizeof(struct ConfigDev));
- /* count this device */
- bi.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) {
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;
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.chip_size = (u_long)mh.mh_Upper;
}
/* get info from ExecBase */
- bi.vblank = SysBase->VBlankFrequency;
- bi.psfreq = SysBase->PowerSupplyFrequency;
- bi.eclock = SysBase->ex_EClockFrequency;
+ if (!bi.vblank)
+ bi.vblank = SysBase->VBlankFrequency;
+ if (!bi.psfreq)
+ bi.psfreq = SysBase->PowerSupplyFrequency;
+ if (!bi.eclock)
+ bi.eclock = SysBase->ex_EClockFrequency;
/* serial port */
- realbaud = baud ? baud : DEFAULT_BAUD;
- bi.serper = (5*bi.eclock+realbaud/2)/realbaud-1;
-
- /* 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.serper) {
+ realbaud = baud ? baud : DEFAULT_BAUD;
+ bi.serper = (5*bi.eclock+realbaud/2)/realbaud-1;
+ }
/* display Amiga model */
if (bi.model >= first_amiga_model && bi.model <= last_amiga_model)
}
/* display the chipset */
- switch(bi.chipset) {
+ switch (bi.chipset) {
case CS_STONEAGE:
Puts(", old or unknown chipset");
break;
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)
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;
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");
/* 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) {
+ 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) {
+ 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) {
+ 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 */
/* Clean up and exit in case of a failure */
Fail:
if (kfd != -1)
- Close(kfd);
+ KClose(kfd);
if (rfd != -1)
Close(rfd);
if (memptr)
* Determine the CPU Type
*/
-/* Dectection of 68030 and up is unreliable, so we check ourself */
-/* Keep consistent with asm/setup.h! */
-/* 24.11.1996 Joerg Dorchain */
-asm( ".text\n"
-ALIGN_STR "\n"
-SYMBOL_NAME_STR(check346) ":
- orw #0x700,%sr | disable ints
- movec %vbr,%a0 | get vbr
- movel %a0@(11*4),%a1 | save old trap vector (Line F)
- movel #L1,%a0@(11*4) | set L1 as new vector
- movel %sp,%d1 | save stack pointer
- moveq #2,%d0 | value with exception (030)
- .long 0xf6208000 | move16 %a0@+,%a0@+, the 030 test instruction
- nop | clear instruction pipeline
- movel %d1,%sp | restore stack pointer
- movec %vbr,%a0 | get vbr again
- moveq #4,%d0 | value with exception (040)
- .word 0xf5c8 | plpar %a0@, the 040 test instruction
- nop | clear instruction pipeline
- moveq #8,%d0 | value if we come here
-L1: movel %d1,%sp | restore stack pointer
- movel %a1,%a0@(11*4) | restore vector
- rte"
-);
-
static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu)
{
- if (SysBase->AttnFlags & (AFF_68030|AFF_68040|AFF_68060))
- *cpu = Supervisor(check346);
+ *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;
+ *cpu = CPU_68020;
if (*cpu == CPU_68040 || *cpu == CPU_68060) {
if (SysBase->AttnFlags & AFF_FPU40)
*fpu = *cpu;
if (SysBase->AttnFlags & AFF_68882)
*fpu = FPU_68882;
else if (SysBase->AttnFlags & AFF_68881)
- *cpu = FPU_68881;
+ *fpu = FPU_68881;
}
*mmu = *cpu;
}
else {
if (debugflag)
Puts(" Chipset: ");
- switch(chipset) {
+ switch (chipset) {
case CS_STONEAGE:
if (debugflag)
Puts("Old or unknown\n");
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();
#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 */
#include <asm/setup.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
/*
* Amiboot Version
*/
-#define AMIBOOT_VERSION "5.1"
+#define AMIBOOT_VERSION "5.4"
/*
*/
struct amiga_bootinfo {
- u_long machtype; /* machine type */
+ u_long machtype; /* machine type = MACH_AMIGA */
u_long cputype; /* system CPU */
u_long fputype; /* system FPU */
u_long mmutype; /* system MMU */
*/
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;
void (*close)(int fd);
int (*filesize)(const char *path);
void (*sleep)(u_long micros);
- int (*modify_bootinfo)(struct amiga_bootinfo *bi);
};
/* 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
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;
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;
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)
}
if (retry >= BOOTP_RETRYS) {
printf( "No response from a bootp server\n" );
- return( -1 );
+ return( -2 );
}
ServerIPaddr = reply->bootp.siaddr;
printf( "TFTP RREQ: %s\n", ErrStr[-err-1] );
if (--retries > 0)
goto repeat_req;
- return( -1 );
+ return( err == ETIMEO ? -2 : -1 );
}
retries = 5;
/***************************** 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 **************************/
** for more details.
**
** History:
+** 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!)
#define BOOTINFO_COMPAT_1_0 /* bootinfo interface version 1.0 compatible */
+/* support compressed kernels? */
+#define ZKERNEL
#include <stdio.h>
#include <stdlib.h>
* ...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 )
"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"
#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));
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 2.0"
+ puts("\fLinux/68k Atari Bootstrap version 2.2"
#ifdef USE_BOOTP
" (with BOOTP)"
#endif
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;
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();
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))
{
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);
}
else
bi.ramdisk.size = 0;
-
- rd_size = bi.ramdisk.size;
- 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;
-
- /* create the bootinfo structure */
- if (!create_bootinfo())
- boot_exit (EXIT_FAILURE);
/* calculate the total required amount of memory */
if (elf_kernel)
}
else
kernel_size = kexec.a_text + kexec.a_data + kexec.a_bss;
+
+ 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)
if (debugflag)
{
if (bi.ramdisk.size)
- printf ("RAM disk at %#lx, size is %ldK\n",
+ printf ("RAM disk at %#lx, size is %ld\n",
(u_long)(memptr + memreq - rd_size),
bi.ramdisk.size);
static int add_bi_record(u_short tag, u_short size, const void *data)
{
struct bi_record *record;
- u_int size2;
+ u_short size2;
size2 = (sizeof(struct bi_record)+size+3)&-4;
if (bi_size+size2+sizeof(bi_union.record.tag) > MAX_BI_SIZE) {
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);
+ printf("CPU type 0x%08lx not supported by kernel\n", bi.cputype);
return(0);
}
if (bi.fputype & FPU_68881)
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);
+ 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",
+ printf("Warning: using only %d blocks of memory\n",
COMPAT_NUM_MEMINFO);
compat_bootinfo.num_memory = COMPAT_NUM_MEMINFO;
}
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 */
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
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'
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
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
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
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
if [ "$CONFIG_PROFILE" = "y" ]; then
int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
fi
+bool 'Remote debugging support' CONFIG_KGDB
endmenu
#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>
#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 */
#undef CONFIG_FBCON_24PACKED
#undef CONFIG_FBCON_32PACKED
#undef CONFIG_FBCON_CYBER
+#undef CONFIG_FBCON_RETINAZ3
/* Monochrome is default */
#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 */
#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
* 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);
/*
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);
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
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);
};
};
#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;
}
+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];
&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;
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;
#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;
* 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);
}
}
-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];
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];
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);
}
}
+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;
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:
/* 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)
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));
+}
+
/* ====================================================================== */
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) {
}
-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;
}
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++;
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;
}
}
-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;
}
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;
}
-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;
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);
* 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;
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--;) {
}
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;
/*
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);
}
-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;
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);
*/
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;
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;
}
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;
/*
* 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;
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)));
}
-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;
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 */
* 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;
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) {
}
-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;
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;
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 {
}
-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);
}
-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 */
}
-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;
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);
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);
}
-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;
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;
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);
/* 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);
}
-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;
}
-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;
}
-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
+
/* ====================================================================== */
/*
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
};
* 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,
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);
}
+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);
+}
+
+
/* ====================================================================== */
/*
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
};
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
# 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_ACCT is not set
+# CONFIG_IP_ROUTER is not set
+# CONFIG_NET_IPIP is not set
#
# (it is safe to leave these untouched)
# 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
# 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
#
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
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
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
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
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
_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
_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
_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
_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
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
|
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
|###########################################################################
.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
endif
OX_OBJS := m68k_ksyms.o
+ifdef CONFIG_KGDB
+O_OBJS += kgdb.o
+endif
+
head.o: head.S
include $(TOPDIR)/Rules.make
* '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)'
* 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>
#include "../../../drivers/char/vt_kern.h"
#include "../../../drivers/char/consolemap.h"
#include "../../../drivers/char/selection.h"
+#include "../../../drivers/char/console_struct.h"
#ifndef MIN
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);
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;
int want_console = -1;
int kmsg_redirect = 0;
-static struct vc {
- struct vc_data *d;
-
- /* 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)
#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);
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;
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
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);
respond_string(buf, tty);
}
-/* invoked via ioctl(TIOCLINUX) */
+/* invoked via ioctl(TIOCLINUX) and through set_selection */
int mouse_reporting(void)
{
int currcons = fg_console;
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
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)
*/
/* 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;
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);
/* 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;
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;
}
/* 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;
}
- 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 = c | (attr << 8);
+ if (myx == cols - 1) {
+ need_wrap = 1;
+ continue;
+ }
+ 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);
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
*/
unsigned long con_init(unsigned long kmem_start)
{
- char *display_desc = "????";
+ const char *display_desc = "????";
unsigned int currcons = 0;
extern int serial_debug;
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;
}
/*
* 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;
return -EINVAL;
}
-void set_vesa_blanking(int arg)
+static void set_vesa_blanking(unsigned long arg)
{
char *argp = (char *)arg + 1;
unsigned int mode;
#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
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
* 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; \
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
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
/* 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
fsave %a0@(LTSS_FPCTXT+27*4)
#if defined(CONFIG_M68060)
-#if !defined(CONFIG_M68060_ONLY)
+#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
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
*/
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
*/
movec %d0,%cacr
#endif /* CONFIG_M68060 */
.chip 68k
-#endif /* CONFIG_M68040_OR_M68060 */
+#endif /* CPU_M68040_OR_M68060 */
2:
4:
/* restore floating point context */
#if defined(CONFIG_M68060)
-#if !defined(CONFIG_M68060_ONLY)
+#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
.long SYMBOL_NAME(sys_nanosleep)
.long SYMBOL_NAME(sys_mremap)
.long SYMBOL_NAME(sys_setresuid)
- .long SYMBOL_NAME(sys_getresuid)
+ .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_ni_syscall) /* will be sys_nfsservctl */
.rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
.long SYMBOL_NAME(sys_ni_syscall)
.endr
.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)
movew #0x2700,%sr
#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()
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
#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
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
.long 0
SYMBOL_NAME_LABEL(is_medusa)
.long 0
+SYMBOL_NAME_LABEL(is_hades)
+ .long 0
SYMBOL_NAME_LABEL(m68k_pgtable_cachemode)
.long 0
#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)
*
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;
}
__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;
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;
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)
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/linkage.h>
#include <linux/sched.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[];
EXPORT_SYMBOL(mm_ptov);
EXPORT_SYMBOL(mm_end_of_chunk);
EXPORT_SYMBOL(m68k_debug_device);
-EXPORT_SYMBOL(request_irq);
-EXPORT_SYMBOL(free_irq);
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,
#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>
goto out;
/* endless idle loop with no priority at all */
+ current->priority = -100;
current->counter = -100;
for (;;)
schedule();
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");
/* 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];
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;
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);
}
/*
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
- struct user * dummy = NULL;
int ret;
lock_kernel();
static char m68k_command_line[CL_SIZE];
char saved_command_line[CL_SIZE];
-/* setup some dummy routines */
-static void dummy_waitbut(void)
-{
-}
-
void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *));
/* machine dependent keyboard functions */
int (*mach_keyb_init) (void);
/* 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_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;
void (*mach_floppy_setup) (char *, int *) = NULL;
void (*mach_floppy_eject) (void) = NULL;
#endif
-void (*mach_syms_export)(void) = NULL;
extern int amiga_parse_bootinfo(const struct bi_record *);
extern int atari_parse_bootinfo(const struct bi_record *);
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
int i;
char *p, *q;
- /* machtype is set up by head.S, thus we know our gender */
- 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);
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);
int error;
lock_kernel();
- error = verify_area(VERIFY_WRITE,fildes,8);
- if (error)
- goto out;
error = do_pipe(fd);
- if (error)
- goto out;
- put_user(fd[0],0+fildes);
- put_user(fd[1],1+fildes);
-out:
+ if (!error) {
+ if (copy_to_user(fildes, fd, 2*sizeof(int)))
+ error = -EFAULT;
+ }
unlock_kernel();
return error;
}
struct mmap_arg_struct a;
lock_kernel();
- error = verify_area(VERIFY_READ, arg, sizeof(*arg));
- if (error)
+ error = -EFAULT;
+ if (copy_from_user(&a, arg, sizeof(a)))
goto out;
- copy_from_user(&a, arg, sizeof(a));
+
if (!(a.flags & MAP_ANONYMOUS)) {
error = -EBADF;
if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
asmlinkage int old_select(struct sel_arg_struct *arg)
{
struct sel_arg_struct a;
- int ret = -EFAULT;
- lock_kernel();
if (copy_from_user(&a, arg, sizeof(a)))
- goto out;
- ret = sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
-out:
- unlock_kernel();
- return ret;
+ return -EFAULT;
+ /* sys_select() does the appropriate kernel locking */
+ return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
}
/*
ret = -EINVAL;
if (!ptr)
goto out;
- if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))))
+ if ((ret = get_user(fourth.__pad, (void **) ptr)))
goto out;
- get_user(fourth.__pad, (void **)ptr);
ret = sys_semctl (first, second, third, fourth);
goto out;
}
switch (version) {
case 0: default: {
ulong raddr;
- if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
- goto out;
ret = sys_shmat (first, (char *) ptr, second, &raddr);
if (ret)
goto out;
- put_user (raddr, (ulong *) third);
- ret = 0;
- goto out;
- }
- case 1: /* iBCS2 emulator entry point */
- ret = -EINVAL;
- if (get_fs() != get_ds())
- goto out;
- ret = sys_shmat (first, (char *) ptr, second, (ulong *) third);
+ ret = put_user (raddr, (ulong *) third);
goto out;
}
+ }
case SHMDT:
ret = sys_shmdt ((char *)ptr);
goto out;
ret = -EINVAL;
goto out;
}
- else
- ret = -EINVAL;
+ ret = -EINVAL;
out:
unlock_kernel();
return ret;
#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);
{
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",
"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);
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) {
"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;
}
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 );
}
}
#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;
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)
{
access_error040 (fp);
break;
#endif
-#if defined (CONFIG_M68020_OR_M68030)
+#if defined (CPU_M68020_OR_M68030)
case 0xa:
case 0xb:
bus_error030 (fp);
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;
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",
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);
}
case VEC_FPOVER:
case VEC_FPNAN:
{
- unsigned char fstate[216];
+ unsigned char fstate[FPSTATESIZE];
__asm__ __volatile__ (".chip 68k/68881\n\t"
"fsave %0@\n\t"
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",
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);
+}
* (%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
/*
- * 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"
"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"
+ ".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
*/
#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)
if (mp->ex_table_start == NULL)
continue;
ret = search_one_table(mp->ex_table_start,
- mp->ex_table_stop-1, addr);
+ mp->ex_table_end-1, addr);
if (ret) return ret;
}
#endif
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(KERN_DEBUG "Exception at [<%lx>] (%lx)\n", fault_pc, fixup);
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;
{
int chunk;
unsigned long mem_avail = 0;
- /* pointer to page table for kernel stacks */
- extern unsigned long availmem;
#ifdef DEBUG
{
for (chunk = 0; chunk < m68k_num_memory; chunk++) {
mem_avail = map_chunk (m68k_memory[chunk].addr,
- m68k_memory[chunk].size, &availmem);
+ 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
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)
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;
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}"
if (CPU_IS_030) {
unsigned long ttreg;
- asm volatile( "pmove %/tt0,%0@" : : "a" (&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( "pmove %/tt1,%0@" : : "a" (&ttreg) );
+ asm volatile( ".chip 68030\n\t"
+ "pmove %/tt1,%0@\n\t"
+ ".chip 68k"
+ : : "a" (&ttreg) );
if (transp_transl_matches( ttreg, vaddr ))
return vaddr;
}
- else {
- register unsigned long ttreg __asm__( "d0" );
+ else if (CPU_IS_040_OR_060) {
+ unsigned long ttreg;
- asm volatile( ".long 0x4e7a0006" /* movec %dtt0,%d0 */
+ 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( ".long 0x4e7a0007" /* movec %dtt1,%d0 */
+ asm volatile( ".chip 68040\n\t"
+ "movec %%dtt1,%0\n\t"
+ ".chip 68k"
: "=d" (ttreg) );
if (transp_transl_matches( ttreg, vaddr ))
return vaddr;
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
#
-/* $Id: entry.S,v 1.137 1997/04/14 05:38:17 davem Exp $
+/* $Id: entry.S,v 1.138 1997/04/15 09:00:50 davem Exp $
* arch/sparc/kernel/entry.S: Sparc trap low-level entry points.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
mov %l7, %o0 ! irq level
call C_LABEL(handler_irq)
add %sp, REGWIN_SZ, %o1 ! pt_regs ptr
-
-#if 1 /* ndef __SMP__ */ /* You don't want to know... -DaveM */
wr %l0, PSR_ET, %psr
WRITE_PAUSE
-#endif
RESTORE_ALL
#ifdef __SMP__
+ /* SMP per-cpu ticker interrupts are handled specially. */
+smp_ticker:
+ bne real_irq_continue
+ or %l0, PSR_PIL, %g2
+ wr %g2, 0x0, %psr
+ WRITE_PAUSE
+ wr %g2, PSR_ET, %psr
+ WRITE_PAUSE
+ call C_LABEL(smp_percpu_timer_interrupt)
+ add %sp, REGWIN_SZ, %o0
+ wr %l0, PSR_ET, %psr
+ WRITE_PAUSE
+ RESTORE_ALL
+
/* Here is where we check for possible SMP IPI passed to us
* on some level other than 15 which is the NMI and only used
* for cross calls. That has a seperate entry point below.
sll %o3, 12, %o3
ld [%o5 + %o3], %o1
andcc %o1, %o4, %g0
- be real_irq_continue
- cmp %l7, 13
+ be,a smp_ticker
+ cmp %l7, 14
+ cmp %l7, 13
add %o5, %o3, %o5
bne,a 1f
sethi %hi(0x40000000), %o2
-/* $Id: head.S,v 1.79 1997/03/04 16:26:31 jj Exp $
+/* $Id: head.S,v 1.81 1997/04/16 07:15:48 davem Exp $
* head.S: The initial boot code for the Sparc port of Linux.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: irq.c,v 1.66 1997/04/14 05:38:21 davem Exp $
+/* $Id: irq.c,v 1.68 1997/04/16 05:55:58 davem Exp $
* arch/sparc/kernel/irq.c: Interrupt request handling routines. On the
* Sparc the IRQ's are basically 'cast in stone'
* and you are supposed to probe the prom's device
#include <asm/hardirq.h>
#include <asm/softirq.h>
+#ifdef __SMP_PROF__
+extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS];
+#endif
+
/*
* Dave Redman (djhr@tadpole.co.uk)
*
void (*disable_irq)(unsigned int) = (void (*)(unsigned int)) irq_panic;
void (*enable_pil_irq)(unsigned int) = (void (*)(unsigned int)) irq_panic;
void (*disable_pil_irq)(unsigned int) = (void (*)(unsigned int)) irq_panic;
-void (*clear_clock_irq)( void ) = irq_panic;
-void (*clear_profile_irq)( void ) = irq_panic;
-void (*load_profile_irq)( unsigned int ) = (void (*)(unsigned int)) irq_panic;
-void (*init_timers)( void (*)(int, void *,struct pt_regs *)) =
- (void (*)( void (*)(int, void *,struct pt_regs *))) irq_panic;
+void (*clear_clock_irq)(void) = irq_panic;
+void (*clear_profile_irq)(int) = (void (*)(int)) irq_panic;
+void (*load_profile_irq)(int, unsigned int) = (void (*)(int, unsigned int)) irq_panic;
+void (*init_timers)(void (*)(int, void *,struct pt_regs *)) =
+ (void (*)(void (*)(int, void *,struct pt_regs *))) irq_panic;
#ifdef __SMP__
void (*set_cpu_int)(int, int);
return len;
}
+#ifdef __SMP_PROF__
+
+static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},};
+
+extern unsigned int prof_multiplier[NR_CPUS];
+extern unsigned int prof_counter[NR_CPUS];
+
+int get_smp_prof_list(char *buf) {
+ int i,j, len = 0;
+ struct irqaction * action;
+ unsigned long sum_spins = 0;
+ unsigned long sum_spins_syscall = 0;
+ unsigned long sum_spins_sys_idle = 0;
+ unsigned long sum_smp_idle_count = 0;
+ unsigned long sum_local_timer_ticks = 0;
+
+ for (i=0;i<smp_num_cpus;i++) {
+ int cpunum = cpu_logical_map[i];
+ sum_spins+=smp_spins[cpunum];
+ sum_spins_syscall+=smp_spins_syscall[cpunum];
+ sum_spins_sys_idle+=smp_spins_sys_idle[cpunum];
+ sum_smp_idle_count+=smp_idle_count[cpunum];
+ sum_local_timer_ticks+=smp_local_timer_ticks[cpunum];
+ }
+
+ len += sprintf(buf+len,"CPUS: %10i \n", smp_num_cpus);
+ len += sprintf(buf+len," SUM ");
+ for (i=0;i<smp_num_cpus;i++)
+ len += sprintf(buf+len," P%1d ",cpu_logical_map[i]);
+ len += sprintf(buf+len,"\n");
+ for (i = 0 ; i < NR_IRQS ; i++) {
+ action = *(i + irq_action);
+ if (!action || !action->handler)
+ continue;
+ len += sprintf(buf+len, "%3d: %10d ",
+ i, kstat.interrupts[i]);
+ for (j=0;j<smp_num_cpus;j++)
+ len+=sprintf(buf+len, "%10d ",
+ int_count[cpu_logical_map[j]][i]);
+ len += sprintf(buf+len, "%c %s",
+ (action->flags & SA_INTERRUPT) ? '+' : ' ',
+ action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ",%s %s",
+ (action->flags & SA_INTERRUPT) ? " +" : "",
+ action->name);
+ }
+ len += sprintf(buf+len, "\n");
+ }
+ len+=sprintf(buf+len, "LCK: %10lu",
+ sum_spins);
+
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10lu",smp_spins[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," spins from int\n");
+
+ len+=sprintf(buf+len, "LCK: %10lu",
+ sum_spins_syscall);
+
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10lu",smp_spins_syscall[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," spins from syscall\n");
+
+ len+=sprintf(buf+len, "LCK: %10lu",
+ sum_spins_sys_idle);
+
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10lu",smp_spins_sys_idle[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," spins from sysidle\n");
+ len+=sprintf(buf+len,"IDLE %10lu",sum_smp_idle_count);
+
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10lu",smp_idle_count[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," idle ticks\n");
+
+ len+=sprintf(buf+len,"TICK %10lu",sum_local_timer_ticks);
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10lu",smp_local_timer_ticks[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," local APIC timer ticks\n");
+
+ len+=sprintf(buf+len,"MULT: ");
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10u",prof_multiplier[cpu_logical_map[i]]);
+ len +=sprintf(buf+len," profiling multiplier\n");
+
+ len+=sprintf(buf+len,"COUNT: ");
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10u",prof_counter[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," profiling counter\n");
+
+ len+=sprintf(buf+len, "IPI: %10lu received\n",
+ ipi_count);
+
+ return len;
+}
+#endif
+
void free_irq(unsigned int irq, void *dev_id)
{
struct irqaction * action;
/* Per-processor IRQ locking depth, both SMP and non-SMP code use this. */
unsigned int local_irq_count[NR_CPUS];
-atomic_t __sparc_bh_counter;
+atomic_t __sparc_bh_counter = ATOMIC_INIT(0);
#ifdef __SMP__
/* SMP interrupt locking on Sparc. */
spinlock_t global_bh_lock = SPIN_LOCK_UNLOCKED;
/* Global IRQ locking depth. */
-atomic_t global_irq_count = ATOMIC_INIT;
+atomic_t global_irq_count = ATOMIC_INIT(0);
#define irq_active(cpu) \
(atomic_read(&global_irq_count) != local_irq_count[cpu])
extern void smp_irq_rotate(int cpu);
int stuck = INIT_STUCK;
+#ifdef __SMP_PROF__
+ int_count[cpu][irq]++;
+#endif
+
smp_irq_rotate(cpu);
hardirq_enter(cpu);
while(global_irq_lock) {
int cpu = smp_processor_id();
disable_pil_irq(cpu_irq);
- irq_enter(cpu, irq);
+ irq_enter(cpu, cpu_irq);
action = *(cpu_irq + irq_action);
kstat.interrupts[cpu_irq]++;
do {
action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
- irq_exit(cpu, irq);
+ irq_exit(cpu, cpu_irq);
enable_pil_irq(cpu_irq);
}
asmlinkage void syscall_trace(void)
{
- lock_kernel();
#ifdef DEBUG_PTRACE
printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
#endif
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS))
- goto out;
+ return;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
current->tss.flags ^= MAGIC_CONSTANT;
current->pid, current->exit_code);
#endif
if (current->exit_code) {
+ spin_lock_irq(¤t->sigmask_lock);
current->signal |= (1 << (current->exit_code - 1));
+ spin_unlock_irq(¤t->sigmask_lock);
}
current->exit_code = 0;
-out:
- unlock_kernel();
}
-/* $Id: signal.c,v 1.72 1997/03/03 16:51:43 jj Exp $
+/* $Id: signal.c,v 1.73 1997/04/16 05:56:05 davem Exp $
* linux/arch/sparc/kernel/signal.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
-asmlinkage int sys_waitpid(pid_t pid, unsigned long *stat_addr, int options);
+asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
+ int options, unsigned long *ru);
extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
void *fpqueue, unsigned long *fpqdepth);
* atomically swap in the new signal mask, and wait for a signal.
* This is really tricky on the Sparc, watch out...
*/
-asmlinkage inline void _sigpause_common(unsigned int set, struct pt_regs *regs)
+asmlinkage void _sigpause_common(unsigned int set, struct pt_regs *regs)
{
unsigned long mask;
+ spin_lock_irq(¤t->sigmask_lock);
mask = current->blocked;
current->blocked = set & _BLOCKABLE;
+ spin_unlock_irq(¤t->sigmask_lock);
+
regs->pc = regs->npc;
regs->npc += 4;
asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
{
- lock_kernel();
_sigpause_common(set, regs);
- unlock_kernel();
}
asmlinkage void do_sigsuspend (struct pt_regs *regs)
{
- lock_kernel();
_sigpause_common(regs->u_regs[UREG_I0], regs);
- unlock_kernel();
}
struct new_signal_frame *sf;
unsigned long up_psr, pc, npc, mask;
- lock_kernel();
sf = (struct new_signal_frame *) regs->u_regs [UREG_FP];
/* 1. Make sure we are not getting garbage from the user */
- if (verify_area (VERIFY_READ, sf, sizeof (*sf))){
- do_exit (SIGSEGV);
- goto out;
- }
- if (((uint) sf) & 3){
- do_exit (SIGSEGV);
- goto out;
- }
+ if (verify_area (VERIFY_READ, sf, sizeof (*sf)))
+ goto segv_and_exit;
+
+ if (((uint) sf) & 3)
+ goto segv_and_exit;
__get_user(pc, &sf->info.si_regs.pc);
__get_user(npc, &sf->info.si_regs.npc);
- if ((pc | npc) & 3) {
- do_exit (SIGSEGV);
- goto out;
- }
+ if ((pc | npc) & 3)
+ goto segv_and_exit;
/* 2. Restore the state */
up_psr = regs->psr;
if (sf->fpu_save)
restore_fpu_state(regs, sf->fpu_save);
+ /* This is pretty much atomic, no amount locking would prevent
+ * the races which exist anyways.
+ */
__get_user(mask, &sf->info.si_mask);
current->blocked = (mask & _BLOCKABLE);
-out:
+ return;
+
+segv_and_exit:
+ /* Ugh, we need to grab master lock in these rare cases ;-( */
+ lock_kernel();
+ do_exit(SIGSEGV);
unlock_kernel();
}
asmlinkage void do_sigreturn(struct pt_regs *regs)
{
struct sigcontext *scptr;
- unsigned long pc, npc, psr;
+ unsigned long pc, npc, psr, mask;
- lock_kernel();
synchronize_user_stack();
- if (current->tss.new_signal){
- do_new_sigreturn (regs);
- goto out;
- }
+
+ if (current->tss.new_signal)
+ return do_new_sigreturn (regs);
+
scptr = (struct sigcontext *) regs->u_regs[UREG_I0];
+
/* Check sanity of the user arg. */
if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext)) ||
- (((unsigned long) scptr) & 3)) {
- printk("%s [%d]: do_sigreturn, scptr is invalid at "
- "pc<%08lx> scptr<%p>\n",
- current->comm, current->pid, regs->pc, scptr);
- do_exit(SIGSEGV);
- }
+ (((unsigned long) scptr) & 3))
+ goto segv_and_exit;
+
__get_user(pc, &scptr->sigc_pc);
__get_user(npc, &scptr->sigc_npc);
+
if((pc | npc) & 3)
- do_exit(SIGSEGV); /* Nice try. */
+ goto segv_and_exit;
+
+ /* This is pretty much atomic, no amount locking would prevent
+ * the races which exist anyways.
+ */
+ __get_user(mask, &scptr->sigc_mask);
+ current->blocked = (mask & _BLOCKABLE);
- __get_user(current->blocked, &scptr->sigc_mask);
- current->blocked &= _BLOCKABLE;
__get_user(current->tss.sstk_info.cur_status, &scptr->sigc_onstack);
current->tss.sstk_info.cur_status &= 1;
+
regs->pc = pc;
regs->npc = npc;
+
__get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp);
__get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0);
__get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1);
__get_user(psr, &scptr->sigc_psr);
regs->psr &= ~(PSR_ICC);
regs->psr |= (psr & PSR_ICC);
-out:
+ return;
+
+segv_and_exit:
+ /* Ugh, we need to grab master lock in these rare cases ;-( */
+ lock_kernel();
+ do_exit(SIGSEGV);
unlock_kernel();
}
return 0;
}
-static inline void
-setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
- struct pt_regs *regs, int signr, unsigned long oldmask)
+static void setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
+ struct pt_regs *regs, int signr, unsigned long oldmask)
{
struct signal_sframe *sframep;
struct sigcontext *sc;
/* Don't change signal code and address, so that
* post mortem debuggers can have a look.
*/
- do_exit(SIGILL);
- return;
+ goto sigill_and_return;
}
sc = &sframep->sig_context;
regs->u_regs[UREG_FP] = (unsigned long) sframep;
regs->pc = (unsigned long) sa->sa_handler;
regs->npc = (regs->pc + 4);
+ return;
+
+sigill_and_return:
+ /* Ugh, we need to grab master lock in these rare cases ;-( */
+ lock_kernel();
+ do_exit(SIGILL);
+ unlock_kernel();
}
current->used_math = 0;
}
-
-static inline void
-new_setup_frame(struct sigaction *sa, struct pt_regs *regs, int signo, unsigned long oldmask)
+static void new_setup_frame(struct sigaction *sa, struct pt_regs *regs,
+ int signo, unsigned long oldmask)
{
struct new_signal_frame *sf;
int sigframe_size;
sf = (struct new_signal_frame *)(regs->u_regs[UREG_FP] - sigframe_size);
- if (invalid_frame_pointer (sf, sigframe_size)){
- do_exit(SIGILL);
- return;
- }
+ if (invalid_frame_pointer (sf, sigframe_size))
+ goto sigill_and_return;
- if (current->tss.w_saved != 0){
+ if (current->tss.w_saved != 0) {
printk ("%s [%d]: Invalid user stack frame for "
"signal delivery.\n", current->comm, current->pid);
- do_exit (SIGILL);
- return;
+ goto sigill_and_return;
}
/* 2. Save the current process state */
/* Flush instruction space. */
flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
+ return;
+
+sigill_and_return:
+ lock_kernel();
+ do_exit(SIGILL);
+ unlock_kernel();
}
#ifdef DEBUG_SIGNALS
printk ("Invalid stack frame\n");
#endif
- do_exit(SIGILL);
- return;
+ goto sigill_and_return;
}
/* Start with a clean frame pointer and fill it */
regs->u_regs[UREG_I1] = (uint) si;
regs->u_regs[UREG_I2] = (uint) uc;
}
+ return;
+
+sigill_and_return:
+ lock_kernel();
+ do_exit(SIGILL);
+ unlock_kernel();
}
-asmlinkage int
-svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs)
+asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs)
{
svr4_gregset_t *gr;
svr4_mcontext_t *mc;
- int ret = -EFAULT;
- lock_kernel();
synchronize_user_stack();
- if (current->tss.w_saved){
- printk ("Uh oh, w_saved is not zero (%ld)\n", current->tss.w_saved);
- do_exit (SIGSEGV);
- }
+
+ if (current->tss.w_saved)
+ goto sigsegv_and_return;
+
if(clear_user(uc, sizeof (*uc)))
- goto out;
+ return -EFAULT;
/* Setup convenience variables */
mc = &uc->mcontext;
/* The register file is not saved
* we have already stuffed all of it with sync_user_stack
*/
- ret = 0;
-out:
+ return 0;
+
+sigsegv_and_return:
+ lock_kernel();
+ do_exit(SIGSEGV);
unlock_kernel();
- return ret;
+ return -EFAULT;
}
-
/* Set the context for a svr4 application, this is Solaris way to sigreturn */
asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs)
{
struct thread_struct *tp = ¤t->tss;
svr4_gregset_t *gr;
- unsigned long pc, npc, psr;
- int ret = -EINTR;
+ unsigned long pc, npc, psr, mask;
- lock_kernel();
/* Fixme: restore windows, or is this already taken care of in
* svr4_setup_frame when sync_user_windows is done?
*/
flush_user_windows();
- if (tp->w_saved){
- printk ("Uh oh, w_saved is: 0x%lx\n", tp->w_saved);
- do_exit(SIGSEGV);
- goto out;
- }
- if (((uint) c) & 3){
- printk ("Unaligned structure passed\n");
- do_exit (SIGSEGV);
- goto out;
- }
+ if (tp->w_saved)
+ goto sigsegv_and_return;
- if(!__access_ok((unsigned long)c, sizeof(*c))) {
- /* Miguel, add nice debugging msg _here_. ;-) */
- do_exit(SIGSEGV);
- goto out;
- }
+ if (((uint) c) & 3)
+ goto sigsegv_and_return;
+
+ if(!__access_ok((unsigned long)c, sizeof(*c)))
+ goto sigsegv_and_return;
/* Check for valid PC and nPC */
gr = &c->mcontext.greg;
__get_user(pc, &((*gr)[SVR4_PC]));
__get_user(npc, &((*gr)[SVR4_NPC]));
- if((pc | npc) & 3) {
- printk ("setcontext, PC or nPC were bogus\n");
- do_exit (SIGSEGV);
- goto out;
- }
+
+ if((pc | npc) & 3)
+ goto sigsegv_and_return;
+
/* Retrieve information from passed ucontext */
- /* note that nPC is ored a 1, this is used to inform entry.S */
- /* that we don't want it to mess with our PC and nPC */
- __get_user(current->blocked, &c->sigmask.sigbits [0]);
- current->blocked &= _BLOCKABLE;
+ /* note that nPC is ored a 1, this is used to inform entry.S */
+ /* that we don't want it to mess with our PC and nPC */
+
+ /* This is pretty much atomic, no amount locking would prevent
+ * the races which exist anyways.
+ */
+ __get_user(mask, &c->sigmask.sigbits [0]);
+ current->blocked = (mask & _BLOCKABLE);
regs->pc = pc;
regs->npc = npc | 1;
__get_user(regs->y, &((*gr) [SVR4_Y]));
/* Restore g[1..7] and o[0..7] registers */
copy_from_user(®s->u_regs [UREG_G1], &(*gr)[SVR4_G1], sizeof (long) * 7);
copy_from_user(®s->u_regs [UREG_I0], &(*gr)[SVR4_O0], sizeof (long) * 8);
-out:
+ return 0;
+
+sigsegv_and_return:
+ lock_kernel();
+ do_exit(SIGSEGV);
unlock_kernel();
- return ret;
+ return -EFAULT;
}
static inline void handle_signal(unsigned long signr, struct sigaction *sa,
}
if(sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
- if(!(sa->sa_flags & SA_NOMASK))
+ if(!(sa->sa_flags & SA_NOMASK)) {
+ spin_lock_irq(¤t->sigmask_lock);
current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE;
+ spin_unlock_irq(¤t->sigmask_lock);
+ }
}
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
unsigned long signr, mask = ~current->blocked;
struct sigaction *sa;
int svr4_signal = current->personality == PER_SVR4;
- int ret;
- lock_kernel();
while ((signr = current->signal & mask) != 0) {
signr = ffz(~signr);
- clear_bit(signr, ¤t->signal);
+
+ spin_lock_irq(¤t->sigmask_lock);
+ current->signal &= ~(1 << signr);
+ spin_unlock_irq(¤t->sigmask_lock);
+
sa = current->sig->action + signr;
signr++;
if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
current->state = TASK_STOPPED;
+
+ /* This happens to be SMP safe so no need to
+ * grab master kernel lock even in this case.
+ */
notify_parent(current);
schedule();
if (!(signr = current->exit_code))
if (signr == SIGSTOP)
continue;
if (_S(signr) & current->blocked) {
+ spin_lock_irq(¤t->sigmask_lock);
current->signal |= _S(signr);
+ spin_unlock_irq(¤t->sigmask_lock);
continue;
}
sa = current->sig->action + signr - 1;
if(sa->sa_handler == SIG_IGN) {
if(signr != SIGCHLD)
continue;
- while(sys_waitpid(-1,NULL,WNOHANG) > 0);
+
+ /* sys_wait4() grabs the master kernel lock, so
+ * we need not do so, that sucker should be
+ * threaded and would not be that difficult to
+ * do anyways.
+ */
+ while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+ ;
continue;
}
if(sa->sa_handler == SIG_DFL) {
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ /* The operations performed by is_orphaned_pgrp()
+ * are protected by the tasklist_lock.
+ */
if (is_orphaned_pgrp(current->pgrp))
continue;
continue;
current->state = TASK_STOPPED;
current->exit_code = signr;
+
+ /* notify_parent() is SMP safe */
if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
notify_parent(current);
#endif
/* fall through */
default:
+ spin_lock_irq(¤t->sigmask_lock);
current->signal |= _S(signr & 0x7f);
+ spin_unlock_irq(¤t->sigmask_lock);
+
current->flags |= PF_SIGNALED;
+
+ lock_kernel(); /* 8-( */
do_exit(signr);
+ unlock_kernel();
}
}
if(restart_syscall)
syscall_restart(orig_i0, regs, sa);
handle_signal(signr, sa, oldmask, regs, svr4_signal);
- ret = 1;
- goto out;
+ return 1;
}
if(restart_syscall &&
(regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
regs->pc -= 4;
regs->npc -= 4;
}
- ret = 0;
-out:
- unlock_kernel();
- return ret;
+ return 0;
}
asmlinkage int
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
#include <asm/delay.h>
#include <asm/irq.h>
local_flush_tlb_all();
}
+static void smp_setup_percpu_timer(void);
+
void smp_callin(void)
{
int cpuid = smp_processor_id();
local_flush_cache_all();
local_flush_tlb_all();
set_irq_udt(mid_xlate[boot_cpu_id]);
+
+ /* Get our local ticker going. */
+ smp_setup_percpu_timer();
+
calibrate_delay();
smp_store_cpu_info(cpuid);
local_flush_cache_all();
klock_info.akp = boot_cpu_id;
smp_store_cpu_info(boot_cpu_id);
set_irq_udt(mid_xlate[boot_cpu_id]);
+ smp_setup_percpu_timer();
local_flush_cache_all();
if(linux_num_cpus == 1)
return; /* Not an MP box. */
while(1)
barrier();
}
+
+/* Protects counters touched during level14 ticker */
+spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
+
+/* 32-bit Sparc specific profiling function. */
+static inline void sparc_do_profile(unsigned long pc)
+{
+ if(prof_buffer && current->pid) {
+ extern int _stext;
+
+ pc -= (unsigned long) &_stext;
+ pc >>= prof_shift;
+
+ spin_lock(&ticker_lock);
+ if(pc < prof_len)
+ prof_buffer[pc]++;
+ else
+ prof_buffer[prof_len - 1]++;
+ spin_unlock(&ticker_lock);
+ }
+}
+
+volatile unsigned long smp_local_timer_ticks[1+NR_CPUS]={0,};
+
+unsigned int prof_multiplier[NR_CPUS];
+unsigned int prof_counter[NR_CPUS];
+
+extern void update_one_process(struct task_struct *p, unsigned long ticks,
+ unsigned long user, unsigned long system);
+
+void smp_percpu_timer_interrupt(struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+
+ clear_profile_irq(mid_xlate[cpu]);
+ if(!user_mode(regs))
+ sparc_do_profile(regs->pc);
+ if(!--prof_counter[cpu]) {
+ int user = user_mode(regs);
+ if(current->pid) {
+ update_one_process(current, 1, user, !user);
+
+ if(--current->counter < 0) {
+ current->counter = 0;
+ need_resched = 1;
+ }
+
+ spin_lock(&ticker_lock);
+ if(user) {
+ if(current->priority < DEF_PRIORITY)
+ kstat.cpu_nice++;
+ else
+ kstat.cpu_user++;
+ } else {
+ kstat.cpu_system++;
+ }
+ spin_unlock(&ticker_lock);
+ }
+ prof_counter[cpu] = prof_multiplier[cpu];
+ }
+#ifdef __SMP_PROF__
+ smp_local_timer_ticks[cpu]++;
+#endif
+}
+
+extern unsigned int lvl14_resolution;
+
+static void smp_setup_percpu_timer(void)
+{
+ int cpu = smp_processor_id();
+
+ prof_counter[cpu] = prof_multiplier[cpu] = 1;
+ load_profile_irq(mid_xlate[cpu], lvl14_resolution);
+
+ if(cpu == boot_cpu_id)
+ enable_pil_irq(14);
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+ int i;
+ unsigned long flags;
+
+ /* Prevent level14 ticker IRQ flooding. */
+ if((!multiplier) || (lvl14_resolution / multiplier) < 500)
+ return -EINVAL;
+
+ save_and_cli(flags);
+ for(i = 0; i < NR_CPUS; i++) {
+ if(cpu_present_map & (1 << i)) {
+ load_profile_irq(mid_xlate[i], lvl14_resolution / multiplier);
+ prof_multiplier[i] = multiplier;
+ }
+ }
+ restore_flags(flags);
+
+ return 0;
+}
-/* $Id: sparc_ksyms.c,v 1.54 1997/04/14 05:38:25 davem Exp $
+/* $Id: sparc_ksyms.c,v 1.55 1997/04/17 03:28:56 davem Exp $
* arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
EXPORT_SYMBOL_PRIVATE(_lock_kernel);
EXPORT_SYMBOL_PRIVATE(_unlock_kernel);
EXPORT_SYMBOL_PRIVATE(_spinlock_waitfor);
+EXPORT_SYMBOL_PRIVATE(_rw_read_enter);
+EXPORT_SYMBOL_PRIVATE(_rw_read_exit);
+EXPORT_SYMBOL_PRIVATE(_rw_write_enter);
EXPORT_SYMBOL(__sparc_bh_counter);
EXPORT_SYMBOL(page_offset);
EXPORT_SYMBOL(stack_top);
clear_intr = sun4c_timers->timer_limit10;
}
-static void sun4c_clear_profile_irq(void)
+static void sun4c_clear_profile_irq(int cpu)
{
/* Errm.. not sure how to do this.. */
}
-static void sun4c_load_profile_irq(unsigned int limit)
+static void sun4c_load_profile_irq(int cpu, unsigned int limit)
{
/* Errm.. not sure how to do this.. */
}
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/traps.h>
+#include <asm/pgtable.h>
#include <asm/smp.h>
#include <asm/irq.h>
#include <asm/io.h>
/*11*/ SUN4M_INT_SBUS(5) | SUN4M_INT_VME(5) | SUN4M_INT_FLOPPY,
/*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS,
/*13*/ SUN4M_INT_AUDIO,
-/*14*/ 0x00000000,
+/*14*/ SUN4M_INT_E14,
/*15*/ 0x00000000
};
clear_intr = sun4m_timers->l10_timer_limit;
}
-static void sun4m_clear_profile_irq(void)
+static void sun4m_clear_profile_irq(int cpu)
{
volatile unsigned int clear;
- clear = sun4m_timers->cpu_timers[0].l14_timer_limit;
+ clear = sun4m_timers->cpu_timers[cpu].l14_timer_limit;
}
-static void sun4m_load_profile_irq(unsigned int limit)
+static void sun4m_load_profile_irq(int cpu, unsigned int limit)
{
- sun4m_timers->cpu_timers[0].l14_timer_limit = limit;
+ sun4m_timers->cpu_timers[cpu].l14_timer_limit = limit;
}
-#if HANDLE_LVL14_IRQ
-static void sun4m_lvl14_handler(int irq, void *dev_id, struct pt_regs * regs)
-{
- volatile unsigned int clear;
-
- printk("CPU[%d]: TOOK A LEVEL14!\n", smp_processor_id());
- /* we do nothing with this at present
- * this is purely to prevent OBP getting its mucky paws
- * in linux.
- */
- clear = sun4m_timers->cpu_timers[0].l14_timer_limit; /* clear interrupt */
-
- /* reload with value, this allows on the fly retuning of the level14
- * timer
- */
- sun4m_timers->cpu_timers[0].l14_timer_limit = lvl14_resolution;
-}
-#endif /* HANDLE_LVL14_IRQ */
-
__initfunc(static void sun4m_init_timers(void (*counter_fn)(int, void *, struct pt_regs *)))
{
int reg_count, irq, cpu;
prom_halt();
}
- /* Can't cope with multiple CPUS yet so no level14 tick events */
-#if HANDLE_LVL14_IRQ
- if (linux_num_cpus > 1)
- claim_ticker14(NULL, PROFILE_IRQ, 0);
- else
- claim_ticker14(sun4m_lvl14_handler, PROFILE_IRQ, lvl14_resolution);
-#endif /* HANDLE_LVL14_IRQ */
if(linux_num_cpus > 1) {
for(cpu = 0; cpu < 4; cpu++)
sun4m_timers->cpu_timers[cpu].l14_timer_limit = 0;
} else {
sun4m_timers->cpu_timers[0].l14_timer_limit = 0;
}
+#ifdef __SMP__
+ {
+ unsigned long flags;
+ extern unsigned long lvl14_save[4];
+ struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
+
+ /* For SMP we use the level 14 ticker, however the bootup code
+ * has copied the firmwares level 14 vector into boot cpu's
+ * trap table, we must fix this now or we get squashed.
+ */
+ __save_and_cli(flags);
+ trap_table->inst_one = lvl14_save[0];
+ trap_table->inst_two = lvl14_save[1];
+ trap_table->inst_three = lvl14_save[2];
+ trap_table->inst_four = lvl14_save[3];
+ local_flush_cache_all();
+ __restore_flags(flags);
+ }
+#endif
}
__initfunc(void sun4m_init_IRQ(void))
* Not sure, but writing here on SLAVIO systems may puke
* so I don't do it unless there is more than 1 cpu.
*/
-#if 0
- printk("Warning:"
- "sun4m multiple CPU interrupt code requires work\n");
-#endif
irq_rcvreg = (unsigned long *)
&sun4m_interrupts->undirected_target;
sun4m_interrupts->undirected_target = 0;
-/* $Id: sys_sparc.c,v 1.34 1997/01/06 06:52:35 davem Exp $
+/* $Id: sys_sparc.c,v 1.35 1997/04/16 05:56:09 davem Exp $
* linux/arch/sparc/kernel/sys_sparc.c
*
* This file contains various random system calls that
sparc_sigaction (int signum, const struct sigaction *action, struct sigaction *oldaction)
{
struct sigaction new_sa, *p;
- int err = -EINVAL;
- lock_kernel();
if(signum < 0) {
current->tss.new_signal = 1;
signum = -signum;
}
+ if(signum<1 || signum>32)
+ return -EINVAL;
- if (signum<1 || signum>32)
- goto out;
p = signum - 1 + current->sig->action;
- if (action) {
- err = verify_area(VERIFY_READ,action,sizeof(struct sigaction));
- if (err)
- goto out;
- err = -EINVAL;
+ if(action) {
+ if(verify_area(VERIFY_READ,action,sizeof(struct sigaction)))
+ return -EFAULT;
if (signum==SIGKILL || signum==SIGSTOP)
- goto out;
- err = -EFAULT;
+ return -EINVAL;
if(copy_from_user(&new_sa, action, sizeof(struct sigaction)))
- goto out;
+ return -EFAULT;
if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
- err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
- if (err)
- goto out;
+ if(verify_area(VERIFY_READ, new_sa.sa_handler, 1))
+ return -EFAULT;
}
}
if (oldaction) {
- err = -EFAULT;
+ /* In the clone() case we could copy half consistant
+ * state to the user, however this could sleep and
+ * deadlock us if we held the signal lock on SMP. So for
+ * now I take the easy way out and do no locking.
+ */
if (copy_to_user(oldaction, p, sizeof(struct sigaction)))
- goto out;
+ return -EFAULT;
}
if (action) {
+ spin_lock_irq(¤t->sig->siglock);
*p = new_sa;
check_pending(signum);
+ spin_unlock_irq(¤t->sig->siglock);
}
-
- err = 0;
-out:
- unlock_kernel();
- return err;
+ return 0;
}
#ifndef CONFIG_AP1000
-/* $Id: sys_sunos.c,v 1.77 1997/02/15 01:17:04 davem Exp $
+/* $Id: sys_sunos.c,v 1.78 1997/04/16 05:56:12 davem Exp $
* sys_sunos.c: SunOS specific syscall compatibility support.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
struct sigaction *oldaction)
{
struct sigaction new_sa, *p;
- const int sigaction_size = sizeof (struct sigaction) - sizeof (void *);
- int err = -EINVAL;
+ const int sigaction_size = sizeof (struct sigaction) - sizeof (void *);
- lock_kernel();
current->personality |= PER_BSD;
-
- if (signum<1 || signum>32)
- goto out;
+ if(signum < 1 || signum > 32)
+ return -EINVAL;
p = signum - 1 + current->sig->action;
- if (action) {
- err = -EFAULT;
+
+ if(action) {
if(copy_from_user(&new_sa, action, sigaction_size))
- goto out;
- err = -EINVAL;
+ return -EFAULT;
if (signum==SIGKILL || signum==SIGSTOP)
- goto out;
+ return -EINVAL;
memset(&new_sa, 0, sizeof(struct sigaction));
- err = -EFAULT;
if(copy_from_user(&new_sa, action, sigaction_size))
- goto out;
+ return -EFAULT;
if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
- err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
- if (err)
- goto out;
+ if(verify_area(VERIFY_READ, new_sa.sa_handler, 1))
+ return -EFAULT;
}
new_sa.sa_flags ^= SUNOS_SV_INTERRUPT;
}
if (oldaction) {
- err = -EFAULT;
+ /* In the clone() case we could copy half consistant
+ * state to the user, however this could sleep and
+ * deadlock us if we held the signal lock on SMP. So for
+ * now I take the easy way out and do no locking.
+ * But then again we don't support SunOS lwp's anyways ;-)
+ */
if (copy_to_user(oldaction, p, sigaction_size))
- goto out;
+ return -EFAULT;
+
if (oldaction->sa_flags & SA_RESTART)
oldaction->sa_flags &= ~SA_RESTART;
else
}
if (action) {
+ spin_lock_irq(¤t->sig->siglock);
*p = new_sa;
check_pending(signum);
+ spin_unlock_irq(¤t->sig->siglock);
}
- err = 0;
-out:
- unlock_kernel();
- return err;
+ return 0;
}
void claim_ticker14(void (*handler)(int, void *, struct pt_regs *),
int irq_nr, unsigned int timeout )
{
+ int cpu = smp_processor_id();
+
/* first we copy the obp handler instructions
*/
disable_irq(irq_nr);
"counter14",
NULL)) {
install_linux_ticker();
- load_profile_irq(timeout);
+ load_profile_irq(cpu, timeout);
enable_irq(irq_nr);
}
}
-/* $Id: time.c,v 1.27 1997/04/14 05:38:31 davem Exp $
+/* $Id: time.c,v 1.28 1997/04/15 09:01:10 davem Exp $
* linux/arch/sparc/kernel/time.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
last_rtc_update = xtime.tv_sec;
else
last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-
-#ifdef __SMP__
- /* I really think it should not be done this way... -DaveM */
- smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0);
-#endif
}
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
-/* $Id: locks.S,v 1.9 1997/04/14 05:38:41 davem Exp $
+/* $Id: locks.S,v 1.11 1997/04/17 03:29:03 davem Exp $
* locks.S: SMP low-level lock primitives on Sparc.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
#include <asm/cprefix.h>
#include <asm/ptrace.h>
#include <asm/psr.h>
+#include <asm/smp.h>
#include <asm/spinlock.h>
.text
* itself in %g1, %g4 must be restored into %o7 when we return,
* and the caller wants us to return to him at three instructions
* previous to the call instruction which got us here. See how
- * this is used in asm-sparc/smp_lock.h if what I just said
- * confuses you to no end.
+ * this is used in asm/smp_lock.h and asm/spinlock.h if what I
+ * just said confuses you to no end.
*/
.globl ___spinlock_waitfor
___spinlock_waitfor:
9: jmpl %o7 + 0x8, %g0
mov %g4, %o7
- .globl ___lock_reaquire_kernel
-___lock_reaquire_kernel:
+ .globl ___lock_reacquire_kernel
+___lock_reacquire_kernel:
rd %psr, %g3
or %g3, PSR_PIL, %g7
wr %g7, 0x0, %psr
jmpl %o7 + 0x8, %g0
mov %g4, %o7
-#undef NO_PROC_ID
-#define NO_PROC_ID 0xff
-
.globl ___unlock_kernel
___unlock_kernel:
addcc %g2, 1, %g2
nop; nop; nop;
1: jmpl %o7 + 0x8, %g0
mov %g4, %o7
+
+ /* Read/writer locks, as usual this is overly clever to make it
+ * as fast as possible.
+ */
+
+ /* caches... */
+___rw_read_enter_spin_on_wlock:
+ orcc %g2, 0x0, %g0
+ be,a ___rw_read_enter
+ ldstub [%g1 + 3], %g2
+ b ___rw_read_enter_spin_on_wlock
+ ldub [%g1 + 3], %g2
+___rw_write_enter_spin_on_wlock:
+ orcc %g2, 0x0, %g0
+ be,a ___rw_write_enter
+ ldstub [%g1 + 3], %g2
+ b ___rw_write_enter_spin_on_wlock
+ ldub [%g1 + 3], %g2
+
+ .globl ___rw_read_enter
+___rw_read_enter:
+ orcc %g2, 0x0, %g0
+ bne,a ___rw_read_enter_spin_on_wlock
+ ldub [%g1 + 3], %g2
+1:
+ ldstub [%g1 + 2], %g7
+ orcc %g7, 0x0, %g0
+ bne 1b
+ ldsh [%g1], %g2
+ add %g2, 1, %g2
+ sth %g2, [%g1]
+ sth %g0, [%g1 + 2]
+ retl
+ mov %g4, %o7
+
+ /* We must be careful here to not blow away wlock. */
+ .globl ___rw_read_exit
+___rw_read_exit_spin:
+ ldstub [%g1 + 2], %g2
+___rw_read_exit:
+ orcc %g2, 0x0, %g0
+ bne ___rw_read_exit_spin
+ ldsh [%g1], %g7
+ sub %g7, 1, %g7
+ sth %g7, [%g1]
+ stb %g0, [%g1 + 2]
+ retl
+ mov %g4, %o7
+
+ .globl ___rw_write_enter
+___rw_write_enter:
+ orcc %g2, 0x0, %g0
+ bne,a ___rw_write_enter_spin_on_wlock
+ ldub [%g1 + 3], %g2
+ ld [%g1], %g2
+1:
+ andncc %g2, 0xff, %g0
+ bne,a 1b
+ ld [%g1], %g2
+ retl
+ mov %g4, %o7
-# $Id: Makefile,v 1.14 1997/04/10 23:32:33 davem Exp $
+# $Id: Makefile,v 1.15 1997/04/14 17:04:49 jj Exp $
# sparc64/Makefile
#
# Makefile for the architecture dependent flags and dependencies on the
# debugging of the kernel to get the proper debugging information.
#CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7
-CFLAGS := $(CFLAGS) -pipe -fno-sibling-call \
+CFLAGS := $(CFLAGS) -pipe \
-fcall-used-g5 -fcall-used-g7 -Wno-sign-compare
LINKFLAGS = -T arch/sparc64/vmlinux.lds
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
#
-/* $Id: etrap.S,v 1.10 1997/04/03 13:03:49 davem Exp $
+/* $Id: etrap.S,v 1.11 1997/04/14 17:04:45 jj Exp $
* etrap.S: Preparing for entry into the kernel on Sparc V9.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
etrap:
rdpr %pil, %g4
etrap_irq:
- rdpr %wstate, %g5
- sllx %g4, 20, %g4
rdpr %tstate, %g1
+ sllx %g4, 20, %g4
rdpr %tpc, %g2
or %g1, %g4, %g1
rdpr %tnpc, %g3
* trap level until PRIMARY_CONTEXT is set to zero, else
* we fall out of NUCLEUS too soon and crash hard.
*/
+ rdpr %wstate, %g5
mov PRIMARY_CONTEXT, %g7
ldxa [%g7] ASI_DMMU, %g4
mov SECONDARY_CONTEXT, %g6
-/* $Id: idprom.c,v 1.1 1996/12/28 18:39:38 davem Exp $
+/* $Id: idprom.c,v 1.2 1997/04/17 02:28:10 miguel Exp $
* idprom.c: Routines to load the idprom into kernel addresses and
* interpret the data contained within.
*
idprom = &idprom_buffer;
if (idprom->id_format != 0x01) {
- prom_printf("IDPROM: Unknown format type!\n");
- prom_halt();
+ prom_printf("IDPROM: Warning, unknown format type!\n");
}
if (idprom->id_cksum != calc_idprom_cksum(idprom)) {
- prom_printf("IDPROM: Checksum failure (nvram=%x, calc=%x)!\n",
+ prom_printf("IDPROM: Warning, checksum failure (nvram=%x, calc=%x)!\n",
idprom->id_cksum, calc_idprom_cksum(idprom));
- prom_halt();
}
printk("Ethernet address: %02x:%02x:%02x:%02x:%02x:%02x\n",
-/* $Id: irq.c,v 1.11 1997/04/14 05:38:59 davem Exp $
+/* $Id: irq.c,v 1.12 1997/04/16 05:56:20 davem Exp $
* irq.c: UltraSparc IRQ handling/init/registry.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
/* Per-processor IRQ locking depth, both SMP and non-SMP code use this. */
unsigned int local_irq_count[NR_CPUS];
-atomic_t __sparc64_bh_counter;
+atomic_t __sparc64_bh_counter = ATOMIC_INIT(0);
#ifdef __SMP__
#error SMP not supported on sparc64 just yet
-/* $Id: signal32.c,v 1.5 1997/04/07 18:57:09 jj Exp $
+/* $Id: signal32.c,v 1.6 1997/04/16 10:27:17 jj Exp $
* arch/sparc64/kernel/signal32.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
#define synchronize_user_stack() do { } while (0)
-asmlinkage int sys_waitpid(pid_t pid, unsigned long *stat_addr, int options);
+asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
+ int options, unsigned long *ru);
asmlinkage int do_signal32(unsigned long oldmask, struct pt_regs * regs,
unsigned long orig_o0, int ret_from_syscall);
* atomically swap in the new signal mask, and wait for a signal.
* This is really tricky on the Sparc, watch out...
*/
-asmlinkage inline void _sigpause32_common(unsigned int set, struct pt_regs *regs)
+asmlinkage void _sigpause32_common(unsigned int set, struct pt_regs *regs)
{
unsigned int mask;
+ spin_lock_irq(¤t->sigmask_lock);
mask = current->blocked;
current->blocked = set & _BLOCKABLE;
+ spin_unlock_irq(¤t->sigmask_lock);
+
regs->tpc = regs->tnpc;
regs->tnpc += 4;
asmlinkage void do_sigpause32(unsigned int set, struct pt_regs *regs)
{
- lock_kernel ();
_sigpause32_common(set, regs);
- unlock_kernel ();
}
asmlinkage void do_sigsuspend32(struct pt_regs *regs)
{
- lock_kernel ();
_sigpause32_common(regs->u_regs[UREG_I0], regs);
- unlock_kernel ();
}
sf = (struct new_signal_frame32 *) regs->u_regs [UREG_FP];
/* 1. Make sure we are not getting garbage from the user */
if (verify_area (VERIFY_READ, sf, sizeof (*sf))){
- do_exit (SIGSEGV);
+ goto segv;
}
if (((unsigned long) sf) & 3){
- do_exit (SIGSEGV);
+ goto segv;
}
get_user(pc, &sf->info.si_regs.pc);
__get_user(npc, &sf->info.si_regs.npc);
if ((pc | npc) & 3){
- do_exit (SIGSEGV);
+ goto segv;
}
regs->tpc = pc;
regs->tnpc = npc;
restore_fpu_state32(regs, &sf->fpu_state);
__get_user(mask, &sf->info.si_mask);
current->blocked = mask & _BLOCKABLE;
- unlock_kernel();
+ return;
+segv:
+ lock_kernel();
+ do_exit(SIGSEGV);
}
asmlinkage void do_sigreturn32(struct pt_regs *regs)
{
struct sigcontext32 *scptr;
unsigned pc, npc, psr;
+ unsigned long mask;
- lock_kernel ();
synchronize_user_stack();
if (current->tss.new_signal)
return do_new_sigreturn32(regs);
/* Check sanity of the user arg. */
if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||
(((unsigned long) scptr) & 3)) {
- printk("%s [%d]: do_sigreturn, scptr is invalid at "
- "pc<%016lx> scptr<%p>\n",
- current->comm, current->pid, regs->tpc, scptr);
- do_exit(SIGSEGV);
+ goto segv;
}
__get_user(pc, &scptr->sigc_pc);
__get_user(npc, &scptr->sigc_npc);
if((pc | npc) & 3)
- do_exit(SIGSEGV); /* Nice try. */
+ goto segv; /* Nice try. */
- __get_user(current->blocked, &scptr->sigc_mask);
- current->blocked &= _BLOCKABLE;
+ __get_user(mask, &scptr->sigc_mask);
+ current->blocked = (mask & _BLOCKABLE);
__get_user(current->tss.sstk_info.cur_status, &scptr->sigc_onstack);
current->tss.sstk_info.cur_status &= 1;
regs->tpc = pc;
__get_user(psr, &scptr->sigc_psr);
regs->tstate &= ~(TSTATE_ICC);
regs->tstate |= psr_to_tstate_icc(psr);
- unlock_kernel ();
+ return;
+segv:
+ lock_kernel ();
+ do_exit (SIGSEGV);
}
/* Checks if the fp is valid */
return 0;
}
-static inline void
+static void
setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
struct pt_regs *regs, int signr, unsigned long oldmask)
{
/* Don't change signal code and address, so that
* post mortem debuggers can have a look.
*/
+ lock_kernel ();
do_exit(SIGILL);
- return;
}
sc = &sframep->sig_context;
sf = (struct new_signal_frame32 *)(regs->u_regs[UREG_FP] - sigframe_size);
if (invalid_frame_pointer (sf, sigframe_size)){
+ lock_kernel ();
do_exit(SIGILL);
- return;
}
if (current->tss.w_saved != 0){
printk ("%s[%d]: Invalid user stack frame for "
"signal delivery.\n", current->comm, current->pid);
+ lock_kernel ();
do_exit (SIGILL);
- return;
}
/* 2. Save the current process state */
#ifdef DEBUG_SIGNALS
printk ("Invalid stack frame\n");
#endif
+ lock_kernel ();
do_exit(SIGILL);
- return;
}
/* Start with a clean frame pointer and fill it */
if(sa->sa_handler == SIG_IGN) {
if(signr != SIGCHLD)
continue;
- while(sys_waitpid(-1,NULL,WNOHANG) > 0);
+
+ /* sys_wait4() grabs the master kernel lock, so
+ * we need not do so, that sucker should be
+ * threaded and would not be that difficult to
+ * do anyways.
+ */
+ while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+ ;
continue;
}
if(sa->sa_handler == SIG_DFL) {
-/* $Id: sparc64_ksyms.c,v 1.3 1997/03/18 17:59:10 jj Exp $
+/* $Id: sparc64_ksyms.c,v 1.4 1997/04/14 17:04:43 jj Exp $
* arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
EXPORT_SYMBOL(__csum_partial_copy_sparc_generic);
/* Moving data to/from userspace. */
-EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(__copy_to_user);
+EXPORT_SYMBOL(__copy_from_user);
EXPORT_SYMBOL(__strncpy_from_user);
/* No version information on this, heavily used in inline asm,
#include <linux/shm.h>
#include <linux/personality.h>
#include <linux/elfcore.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
sp -= argc+1;
argv = (__u32 *) sp;
if (!ibcs) {
- __put_user(((__u32) envp),--sp);
- __put_user(((__u32) argv),--sp);
+ __put_user(((__u32)(long) envp),--sp);
+ __put_user(((__u32)(long) argv),--sp);
}
__put_user((__u32)argc,--sp);
current->mm->arg_start = (unsigned long) p;
while (argc-->0) {
- __put_user(((__u32)p),argv++);
+ __put_user(((__u32)(long)p),argv++);
p += strlen_user(p);
}
__put_user(NULL, argv);
current->mm->arg_end = current->mm->env_start = (unsigned long) p;
while (envc-->0) {
- __put_user(((__u32)p),envp++);
+ __put_user(((__u32)(long)p),envp++);
p += strlen_user(p);
}
__put_user(NULL, envp);
#else
if (sizeof(elf_gregset_t) != sizeof(struct pt_regs))
{
- printk("sizeof(elf_gregset_t) (%d) != sizeof(struct pt_regs) (%d)\n",
+ printk("sizeof(elf_gregset_t) (%ld) != sizeof(struct pt_regs) (%ld)\n",
sizeof(elf_gregset_t), sizeof(struct pt_regs));
}
else
}
#endif /* USE_ELF_CORE_DUMP */
-int init_elf32_binfmt(void)
+__initfunc(int init_elf32_binfmt(void))
{
return register_binfmt(&elf32_format);
}
-/* $Id: sys_sparc32.c,v 1.3 1997/04/09 08:25:17 jj Exp $
+/* $Id: sys_sparc32.c,v 1.6 1997/04/16 14:52:29 jj Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
#include <linux/resource.h>
#include <linux/sched.h>
#include <linux/times.h>
+#include <linux/utime.h>
#include <linux/utsname.h>
#include <linux/timex.h>
#include <linux/smp.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
+#include <linux/malloc.h>
+#include <linux/uio.h>
#include <asm/types.h>
#include <asm/poll.h>
* produce warnings */
#define A(x) ((unsigned long)x)
-/* FIXME: All struct * etc. stuff should be examined and proper structure conversions
- * added ASAP -JJ */
-
extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
extern asmlinkage unsigned long sys_brk(unsigned long brk);
extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off);
extern asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count);
extern asmlinkage long sys_readv(unsigned long fd, const struct iovec * vector, unsigned long count);
extern asmlinkage long sys_writev(unsigned long fd, const struct iovec * vector, unsigned long count);
-extern asmlinkage int sys_getdents(unsigned int fd, void * dirent, unsigned int count);
extern asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp);
extern asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout);
extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
return sys_ioperm((unsigned long)from, (unsigned long)num, on);
}
+struct msgbuf32 { s32 mtype; char mtext[1]; };
+
+struct ipc_perm32
+{
+ key_t key;
+ __kernel_uid_t32 uid;
+ __kernel_gid_t32 gid;
+ __kernel_uid_t32 cuid;
+ __kernel_gid_t32 cgid;
+ __kernel_mode_t32 mode;
+ unsigned short seq;
+};
+
+struct msqid_ds32
+{
+ struct ipc_perm32 msg_perm;
+ u32 msg_first;
+ u32 msg_last;
+ __kernel_time_t32 msg_stime;
+ __kernel_time_t32 msg_rtime;
+ __kernel_time_t32 msg_ctime;
+ u32 wwait;
+ u32 rwait;
+ unsigned short msg_cbytes;
+ unsigned short msg_qnum;
+ unsigned short msg_qbytes;
+ __kernel_ipc_pid_t32 msg_lspid;
+ __kernel_ipc_pid_t32 msg_lrpid;
+};
+
+struct shmid_ds32 {
+ struct ipc_perm32 shm_perm;
+ int shm_segsz;
+ __kernel_time_t32 shm_atime;
+ __kernel_time_t32 shm_dtime;
+ __kernel_time_t32 shm_ctime;
+ __kernel_ipc_pid_t32 shm_cpid;
+ __kernel_ipc_pid_t32 shm_lpid;
+ unsigned short shm_nattch;
+ unsigned short shm_npages;
+ u32 shm_pages;
+ u32 attaches;
+};
+
/*
* sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
*
if (call <= MSGCTL)
switch (call) {
case MSGSND:
- /* XXX struct msgbuf has a long first :(( */
- err = sys_msgsnd (first, (struct msgbuf *) A(ptr),
- second, third);
+ {
+ struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf), GFP_KERNEL);
+
+ if (!p) err = -ENOMEM;
+ else {
+ if (get_user(p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
+ __copy_from_user(p->mtext, &(((struct msgbuf32 *)A(ptr))->mtext), second))
+ err = -EFAULT;
+ else {
+ unsigned long old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ err = sys_msgsnd (first, p, second, third);
+ set_fs (old_fs);
+ }
+ kfree (p);
+ }
+ }
goto out;
case MSGRCV:
- switch (version) {
- case 0: {
- struct ipc_kludge tmp;
- err = -EINVAL;
- if (!ptr)
- goto out;
- err = -EFAULT;
- if(copy_from_user(&tmp,(struct ipc_kludge *) ptr, sizeof (tmp)))
+ {
+ struct msgbuf *p;
+ unsigned long old_fs;
+
+ if (!version) {
+ struct ipc_kludge tmp;
+ err = -EINVAL;
+ if (!ptr)
+ goto out;
+ err = -EFAULT;
+ if(copy_from_user(&tmp,(struct ipc_kludge *)A(ptr), sizeof (tmp)))
+ goto out;
+ ptr = tmp.msgp;
+ fifth = tmp.msgtyp;
+ }
+ p = kmalloc (second + sizeof (struct msgbuf), GFP_KERNEL);
+ if (!p) {
+ err = -EFAULT;
goto out;
- err = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
- goto out;
}
- case 1: default:
- err = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+ old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ err = sys_msgrcv (first, p, second, fifth, third);
+ set_fs (old_fs);
+ if (put_user (p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
+ __copy_to_user(&(((struct msgbuf32 *)A(ptr))->mtext), p->mtext, second))
+ err = -EFAULT;
+ kfree (p);
goto out;
}
case MSGGET:
err = sys_msgget ((key_t) first, second);
goto out;
case MSGCTL:
- err = sys_msgctl (first, second, (struct msqid_ds *) ptr);
+ {
+ struct msqid_ds m;
+ unsigned long old_fs;
+
+ switch (second) {
+ case IPC_INFO:
+ case MSG_INFO:
+ /* struct msginfo is the same */
+ case IPC_RMID:
+ /* and this doesn't care about ptr */
+ err = sys_msgctl (first, second, (struct msqid_ds *)A(ptr));
+ goto out;
+
+ case IPC_SET:
+ if (get_user (m.msg_perm.uid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.uid)) ||
+ __get_user (m.msg_perm.gid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.gid)) ||
+ __get_user (m.msg_perm.mode, &(((struct msqid_ds32 *)A(ptr))->msg_perm.mode)) ||
+ __get_user (m.msg_qbytes, &(((struct msqid_ds32 *)A(ptr))->msg_qbytes))) {
+ err = -EFAULT;
+ goto out;
+ }
+ default:
+ break;
+ }
+ old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ err = sys_msgctl (first, second, &m);
+ set_fs (old_fs);
+ switch (second) {
+ case MSG_STAT:
+ case IPC_STAT:
+ if (put_user (m.msg_perm.key, &(((struct msqid_ds32 *)A(ptr))->msg_perm.key)) ||
+ __put_user (m.msg_perm.uid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.uid)) ||
+ __put_user (m.msg_perm.gid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.gid)) ||
+ __put_user (m.msg_perm.cuid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.cuid)) ||
+ __put_user (m.msg_perm.cgid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.cgid)) ||
+ __put_user (m.msg_perm.mode, &(((struct msqid_ds32 *)A(ptr))->msg_perm.mode)) ||
+ __put_user (m.msg_perm.seq, &(((struct msqid_ds32 *)A(ptr))->msg_perm.seq)) ||
+ __put_user (m.msg_stime, &(((struct msqid_ds32 *)A(ptr))->msg_stime)) ||
+ __put_user (m.msg_rtime, &(((struct msqid_ds32 *)A(ptr))->msg_rtime)) ||
+ __put_user (m.msg_ctime, &(((struct msqid_ds32 *)A(ptr))->msg_ctime)) ||
+ __put_user (m.msg_cbytes, &(((struct msqid_ds32 *)A(ptr))->msg_cbytes)) ||
+ __put_user (m.msg_qnum, &(((struct msqid_ds32 *)A(ptr))->msg_qnum)) ||
+ __put_user (m.msg_qbytes, &(((struct msqid_ds32 *)A(ptr))->msg_qbytes)) ||
+ __put_user (m.msg_lspid, &(((struct msqid_ds32 *)A(ptr))->msg_lspid)) ||
+ __put_user (m.msg_lrpid, &(((struct msqid_ds32 *)A(ptr))->msg_lrpid)))
+ err = -EFAULT;
+ break;
+ default:
+ break;
+ }
+ }
goto out;
default:
err = -EINVAL;
case SHMAT:
switch (version) {
case 0: default: {
- ulong raddr;
- err = sys_shmat (first, (char *) ptr, second, &raddr);
+ unsigned long raddr;
+ err = sys_shmat (first, (char *)A(ptr), second, &raddr);
if (err)
goto out;
err = -EFAULT;
- if(put_user (raddr, (ulong *) third))
+ if(put_user (raddr, ((u32 *)A(third))))
goto out;
err = 0;
goto out;
}
- case 1: /* iBCS2 emulator entry point */
- err = sys_shmat (first, (char *) ptr, second, (ulong *) third);
+ case 1: /* If iBCS2 should ever run, then for sure in 64bit mode, not 32bit... */
+ err = -EINVAL;
goto out;
}
case SHMDT:
- err = sys_shmdt ((char *)ptr);
+ err = sys_shmdt ((char *)A(ptr));
goto out;
case SHMGET:
err = sys_shmget (first, second, third);
goto out;
case SHMCTL:
- err = sys_shmctl (first, second, (struct shmid_ds *) ptr);
+ {
+ struct shmid_ds s;
+ unsigned long old_fs;
+
+ switch (second) {
+ case IPC_INFO:
+ /* struct shminfo is the same */
+ case SHM_LOCK:
+ case SHM_UNLOCK:
+ case IPC_RMID:
+ /* and these three aren't using ptr at all */
+ err = sys_shmctl (first, second, (struct shmid_ds *)A(ptr));
+ goto out;
+
+ case IPC_SET:
+ if (get_user (s.shm_perm.uid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.uid)) ||
+ __get_user (s.shm_perm.gid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.gid)) ||
+ __get_user (s.shm_perm.mode, &(((struct shmid_ds32 *)A(ptr))->shm_perm.mode))) {
+ err = -EFAULT;
+ goto out;
+ }
+ default:
+ break;
+ }
+ old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ err = sys_shmctl (first, second, &s);
+ set_fs (old_fs);
+ switch (second) {
+ case SHM_INFO:
+ {
+ struct shm_info32 { int used_ids; u32 shm_tot; u32 shm_rss; u32 shm_swp; u32 swap_attempts; u32 swap_successes; };
+ struct shm_info *si = (struct shm_info *)&s;
+
+ if (put_user (si->used_ids, &(((struct shm_info32 *)A(ptr))->used_ids)) ||
+ __put_user (si->shm_tot, &(((struct shm_info32 *)A(ptr))->shm_tot)) ||
+ __put_user (si->shm_rss, &(((struct shm_info32 *)A(ptr))->shm_rss)) ||
+ __put_user (si->shm_swp, &(((struct shm_info32 *)A(ptr))->shm_swp)) ||
+ __put_user (si->swap_attempts, &(((struct shm_info32 *)A(ptr))->swap_attempts)) ||
+ __put_user (si->swap_successes, &(((struct shm_info32 *)A(ptr))->swap_successes)))
+ err = -EFAULT;
+ }
+ break;
+ case SHM_STAT:
+ case IPC_STAT:
+ if (put_user (s.shm_perm.key, &(((struct shmid_ds32 *)A(ptr))->shm_perm.key)) ||
+ __put_user (s.shm_perm.uid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.uid)) ||
+ __put_user (s.shm_perm.gid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.gid)) ||
+ __put_user (s.shm_perm.cuid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.cuid)) ||
+ __put_user (s.shm_perm.cgid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.cgid)) ||
+ __put_user (s.shm_perm.mode, &(((struct shmid_ds32 *)A(ptr))->shm_perm.mode)) ||
+ __put_user (s.shm_perm.seq, &(((struct shmid_ds32 *)A(ptr))->shm_perm.seq)) ||
+ __put_user (s.shm_atime, &(((struct shmid_ds32 *)A(ptr))->shm_atime)) ||
+ __put_user (s.shm_dtime, &(((struct shmid_ds32 *)A(ptr))->shm_dtime)) ||
+ __put_user (s.shm_ctime, &(((struct shmid_ds32 *)A(ptr))->shm_ctime)) ||
+ __put_user (s.shm_segsz, &(((struct shmid_ds32 *)A(ptr))->shm_segsz)) ||
+ __put_user (s.shm_nattch, &(((struct shmid_ds32 *)A(ptr))->shm_nattch)) ||
+ __put_user (s.shm_lpid, &(((struct shmid_ds32 *)A(ptr))->shm_cpid)) ||
+ __put_user (s.shm_cpid, &(((struct shmid_ds32 *)A(ptr))->shm_lpid)))
+ err = -EFAULT;
+ break;
+ default:
+ break;
+ }
+ }
goto out;
default:
err = -EINVAL;
asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg)
{
- return sys_fcntl(fd, cmd, (unsigned long)arg);
+ switch (cmd) {
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ {
+ struct flock f;
+ unsigned long old_fs;
+ long ret;
+
+ if (get_user (f.l_type, &(((struct flock32 *)A(arg))->l_type)) ||
+ __get_user (f.l_whence, &(((struct flock32 *)A(arg))->l_whence)) ||
+ __get_user (f.l_start, &(((struct flock32 *)A(arg))->l_start)) ||
+ __get_user (f.l_len, &(((struct flock32 *)A(arg))->l_len)) ||
+ __get_user (f.l_pid, &(((struct flock32 *)A(arg))->l_pid)))
+ return -EFAULT;
+ old_fs = get_fs(); set_fs (KERNEL_DS);
+ ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+ set_fs (old_fs);
+ if (__put_user (f.l_type, &(((struct flock32 *)A(arg))->l_type)) ||
+ __put_user (f.l_whence, &(((struct flock32 *)A(arg))->l_whence)) ||
+ __put_user (f.l_start, &(((struct flock32 *)A(arg))->l_start)) ||
+ __put_user (f.l_len, &(((struct flock32 *)A(arg))->l_len)) ||
+ __put_user (f.l_pid, &(((struct flock32 *)A(arg))->l_pid)))
+ return -EFAULT;
+ return ret;
+ }
+ default:
+ return sys_fcntl(fd, cmd, (unsigned long)arg);
+ }
}
+/* Conversion of args should be probably done in all the locations where it is handled,
+ using if (current->tss.flags & SPARC_FLAG_32BIT */
asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
{
return sys_ioctl(fd, cmd, (unsigned long)arg);
}
-asmlinkage int sys32_mknod(u32 filename, int mode, dev_t dev)
+asmlinkage int sys32_mknod(u32 filename, int mode, __kernel_dev_t32 dev)
{
return sys_mknod((const char *)A(filename), mode, dev);
}
return sys_rename((const char *)A(oldname), (const char *)A(newname));
}
+/* XXX: Play with the addr, it will be ugly :(( */
asmlinkage int sys32_quotactl(int cmd, u32 special, int id, u32 addr)
{
return sys_quotactl(cmd, (const char *)A(special), id, (caddr_t)A(addr));
}
+static int put_statfs (u32 buf, struct statfs *s)
+{
+ if (put_user (s->f_type, &(((struct statfs32 *)A(buf))->f_type)) ||
+ __put_user (s->f_bsize, &(((struct statfs32 *)A(buf))->f_bsize)) ||
+ __put_user (s->f_blocks, &(((struct statfs32 *)A(buf))->f_blocks)) ||
+ __put_user (s->f_bfree, &(((struct statfs32 *)A(buf))->f_bfree)) ||
+ __put_user (s->f_bavail, &(((struct statfs32 *)A(buf))->f_bavail)) ||
+ __put_user (s->f_files, &(((struct statfs32 *)A(buf))->f_files)) ||
+ __put_user (s->f_ffree, &(((struct statfs32 *)A(buf))->f_ffree)) ||
+ __put_user (s->f_namelen, &(((struct statfs32 *)A(buf))->f_namelen)) ||
+ __put_user (s->f_fsid.val[0], &(((struct statfs32 *)A(buf))->f_fsid.val[0])) ||
+ __put_user (s->f_fsid.val[1], &(((struct statfs32 *)A(buf))->f_fsid.val[1])))
+ return -EFAULT;
+ return 0;
+}
+
asmlinkage int sys32_statfs(u32 path, u32 buf)
{
- return sys_statfs((const char *)A(path), (struct statfs *)A(buf));
+ int ret;
+ struct statfs s;
+ unsigned long old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+ ret = sys_statfs((const char *)A(path), &s);
+ set_fs (old_fs);
+ if (put_statfs(buf, &s)) return -EFAULT;
+ return ret;
}
asmlinkage int sys32_fstatfs(unsigned int fd, u32 buf)
{
- return sys_fstatfs(fd, (struct statfs *)A(buf));
+ int ret;
+ struct statfs s;
+ unsigned long old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+ ret = sys_fstatfs(fd, &s);
+ set_fs (old_fs);
+ if (put_statfs(buf, &s)) return -EFAULT;
+ return ret;
}
asmlinkage int sys32_truncate(u32 path, u32 length)
asmlinkage int sys32_utime(u32 filename, u32 times)
{
- return sys_utime((char *)A(filename), (struct utimbuf *)A(times));
+ struct utimbuf32 { __kernel_time_t32 actime, modtime; };
+ struct utimbuf t;
+ unsigned long old_fs;
+ int ret;
+
+ if (get_user (t.actime, &(((struct utimbuf32 *)A(times))->actime)) ||
+ __get_user (t.modtime, &(((struct utimbuf32 *)A(times))->modtime)))
+ return -EFAULT;
+ old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ ret = sys_utime((char *)A(filename), &t);
+ set_fs (old_fs);
+ return ret;
}
asmlinkage int sys32_utimes(u32 filename, u32 utimes)
{
+ /* struct timeval is the same :)) */
return sys_utimes((char *)A(filename), (struct timeval *)A(utimes));
}
return sys_chroot((const char *)A(filename));
}
-asmlinkage int sys32_chmod(u32 filename, mode_t mode)
+asmlinkage int sys32_chmod(u32 filename, __kernel_mode_t32 mode)
{
return sys_chmod((const char *)A(filename), mode);
}
-asmlinkage int sys32_chown(u32 filename, uid_t user, gid_t group)
+asmlinkage int sys32_chown(u32 filename, __kernel_uid_t32 user, __kernel_gid_t32 group)
{
return sys_chown((const char *)A(filename), user, group);
}
asmlinkage int sys32_llseek(unsigned int fd, u32 offset_high, u32 offset_low, u32 result, unsigned int origin)
{
+ /* loff_t is the same :)) */
return sys_llseek(fd, (unsigned long)offset_high, (unsigned long)offset_low, (loff_t *)A(result), origin);
}
asmlinkage long sys32_readv(u32 fd, u32 vector, u32 count)
{
- return sys_readv((unsigned long)fd, (const struct iovec *)A(vector), (unsigned long)count);
+ struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
+ struct iovec *v;
+ u32 i;
+ long ret;
+ unsigned long old_fs;
+
+ if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL;
+ v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL); if (!v) return -ENOMEM;
+ for (i = 0; i < count; i++) {
+ if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) ||
+ __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) {
+ kfree (v);
+ return -EFAULT;
+ }
+ }
+ old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ ret = sys_readv((unsigned long)fd, v, (unsigned long)count);
+ set_fs (old_fs);
+ kfree (v);
+ return ret;
}
asmlinkage long sys32_writev(u32 fd, u32 vector, u32 count)
{
- return sys_writev((unsigned long)fd, (const struct iovec *)A(vector), (unsigned long)count);
+ struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
+ struct iovec *v;
+ u32 i;
+ long ret;
+ unsigned long old_fs;
+
+ if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL;
+ v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL); if (!v) return -ENOMEM;
+ for (i = 0; i < count; i++) {
+ if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) ||
+ __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) {
+ kfree (v);
+ return -EFAULT;
+ }
+ }
+ old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ ret = sys_writev((unsigned long)fd, v, (unsigned long)count);
+ set_fs (old_fs);
+ kfree (v);
+ return ret;
+}
+
+/* readdir & getdents */
+
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
+
+struct old_linux_dirent32 {
+ u32 d_ino;
+ u32 d_offset;
+ unsigned short d_namlen;
+ char d_name[1];
+};
+
+struct readdir_callback32 {
+ struct old_linux_dirent32 * dirent;
+ int count;
+};
+
+static int fillonedir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
+{
+ struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
+ struct old_linux_dirent32 * dirent;
+
+ if (buf->count)
+ return -EINVAL;
+ buf->count++;
+ dirent = buf->dirent;
+ put_user(ino, &dirent->d_ino);
+ put_user(offset, &dirent->d_offset);
+ put_user(namlen, &dirent->d_namlen);
+ copy_to_user(dirent->d_name, name, namlen);
+ put_user(0, dirent->d_name + namlen);
+ return 0;
+}
+
+asmlinkage int old32_readdir(unsigned int fd, u32 dirent, unsigned int count)
+{
+ int error = -EBADF;
+ struct file * file;
+ struct readdir_callback32 buf;
+
+ lock_kernel();
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ goto out;
+ error = -ENOTDIR;
+ if (!file->f_op || !file->f_op->readdir)
+ goto out;
+ error = verify_area(VERIFY_WRITE, (void *)A(dirent), sizeof(struct old_linux_dirent32));
+ if (error)
+ goto out;
+ buf.count = 0;
+ buf.dirent = (struct old_linux_dirent32 *)A(dirent);
+ error = file->f_op->readdir(file->f_inode, file, &buf, fillonedir);
+ if (error < 0)
+ goto out;
+ error = buf.count;
+out:
+ unlock_kernel();
+ return error;
+}
+
+struct linux_dirent32 {
+ u32 d_ino;
+ u32 d_off;
+ unsigned short d_reclen;
+ char d_name[1];
+};
+
+struct getdents_callback32 {
+ struct linux_dirent32 * current_dir;
+ struct linux_dirent32 * previous;
+ int count;
+ int error;
+};
+
+static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
+{
+ struct linux_dirent32 * dirent;
+ struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
+ int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
+ dirent = buf->previous;
+ if (dirent)
+ put_user(offset, &dirent->d_off);
+ dirent = buf->current_dir;
+ buf->previous = dirent;
+ put_user(ino, &dirent->d_ino);
+ put_user(reclen, &dirent->d_reclen);
+ copy_to_user(dirent->d_name, name, namlen);
+ put_user(0, dirent->d_name + namlen);
+ ((char *) dirent) += reclen;
+ buf->current_dir = dirent;
+ buf->count -= reclen;
+ return 0;
}
asmlinkage int sys32_getdents(unsigned int fd, u32 dirent, unsigned int count)
{
- return sys_getdents(fd, (void *)A(dirent), count);
+ struct file * file;
+ struct linux_dirent32 * lastdirent;
+ struct getdents_callback32 buf;
+ int error = -EBADF;
+
+ lock_kernel();
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ goto out;
+ error = -ENOTDIR;
+ if (!file->f_op || !file->f_op->readdir)
+ goto out;
+ error = verify_area(VERIFY_WRITE, (void *)A(dirent), count);
+ if (error)
+ goto out;
+ buf.current_dir = (struct linux_dirent32 *) A(dirent);
+ buf.previous = NULL;
+ buf.count = count;
+ buf.error = 0;
+ error = file->f_op->readdir(file->f_inode, file, &buf, filldir);
+ if (error < 0)
+ goto out;
+ lastdirent = buf.previous;
+ if (!lastdirent) {
+ error = buf.error;
+ } else {
+ put_user(file->f_pos, &lastdirent->d_off);
+ error = count - buf.count;
+ }
+out:
+ unlock_kernel();
+ return error;
}
+/* end of readdir & getdents */
+
asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp)
{
- return sys_select(n, (fd_set *)A(inp), (fd_set *)A(outp), (fd_set *)A(exp), (struct timeval *)A(tvp));
+ unsigned long old_fs;
+ char *p;
+ u32 *q;
+ int i, ret = -EINVAL, nn;
+ u32 *Inp, *Outp, *Exp;
+
+ if (n < 0 || n > PAGE_SIZE*2) return -EINVAL;
+ lock_kernel ();
+ p = (char *)__get_free_page (GFP_KERNEL);
+ if (!p) goto out;
+ q = (u32 *)p;
+ nn = (n + 8 * sizeof(unsigned long) - 1) / (8 * sizeof (unsigned long));
+ Inp = (u32 *)A(inp); Outp = (u32 *)A(outp); Exp = (u32 *)A(exp);
+ ret = -EFAULT;
+ for (i = 0; i < ret; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) {
+ if (__get_user (q[1], Inp) ||
+ __get_user (q[0], Inp+1) ||
+ __get_user (q[1+PAGE_SIZE/4], Outp) ||
+ __get_user (q[PAGE_SIZE/4], Outp+1) ||
+ __get_user (q[1+PAGE_SIZE/2], Exp) ||
+ __get_user (q[PAGE_SIZE/2], Exp+1))
+ goto out;
+ }
+ old_fs = get_fs ();
+ set_fs (KERNEL_DS);
+ ret = sys_select(n, (fd_set *)p, (fd_set *)(p + PAGE_SIZE/4), (fd_set *)(p + PAGE_SIZE/2), (struct timeval *)A(tvp));
+ set_fs (old_fs);
+ q = (u32 *)p;
+ Inp = (u32 *)A(inp); Outp = (u32 *)A(outp); Exp = (u32 *)A(exp);
+ for (i = 0; i < ret; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) {
+ if (__put_user (q[1], Inp) ||
+ __put_user (q[0], Inp+1) ||
+ __put_user (q[1+PAGE_SIZE/4], Outp) ||
+ __put_user (q[PAGE_SIZE/4], Outp+1) ||
+ __put_user (q[1+PAGE_SIZE/2], Exp) ||
+ __put_user (q[PAGE_SIZE/2], Exp+1)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ }
+out:
+ free_page ((unsigned long)p);
+ return ret;
}
asmlinkage int sys32_poll(u32 ufds, unsigned int nfds, int timeout)
return sys_poll((struct pollfd *)A(ufds), nfds, timeout);
}
+static inline int putstat(u32 statbuf, struct stat *s)
+{
+ if (put_user (s->st_dev, &(((struct stat32 *)A(statbuf))->st_dev)) ||
+ __put_user (s->st_ino, &(((struct stat32 *)A(statbuf))->st_ino)) ||
+ __put_user (s->st_mode, &(((struct stat32 *)A(statbuf))->st_mode)) ||
+ __put_user (s->st_nlink, &(((struct stat32 *)A(statbuf))->st_nlink)) ||
+ __put_user (s->st_uid, &(((struct stat32 *)A(statbuf))->st_uid)) ||
+ __put_user (s->st_gid, &(((struct stat32 *)A(statbuf))->st_gid)) ||
+ __put_user (s->st_rdev, &(((struct stat32 *)A(statbuf))->st_rdev)) ||
+ __put_user (s->st_size, &(((struct stat32 *)A(statbuf))->st_size)) ||
+ __put_user (s->st_atime, &(((struct stat32 *)A(statbuf))->st_atime)) ||
+ __put_user (s->st_mtime, &(((struct stat32 *)A(statbuf))->st_mtime)) ||
+ __put_user (s->st_ctime, &(((struct stat32 *)A(statbuf))->st_ctime)) ||
+ __put_user (s->st_blksize, &(((struct stat32 *)A(statbuf))->st_blksize)) ||
+ __put_user (s->st_blocks, &(((struct stat32 *)A(statbuf))->st_blocks)))
+ return -EFAULT;
+ return 0;
+}
+
asmlinkage int sys32_newstat(u32 filename, u32 statbuf)
{
- return sys_newstat((char *)A(filename), (struct stat *)A(statbuf));
+ int ret;
+ struct stat s;
+ unsigned long old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+ ret = sys_newstat((char *)A(filename), &s);
+ set_fs (old_fs);
+ if (putstat (statbuf, &s)) return -EFAULT;
+ return ret;
}
asmlinkage int sys32_newlstat(u32 filename, u32 statbuf)
{
- return sys_newlstat((char *)A(filename), (struct stat *)A(statbuf));
+ int ret;
+ struct stat s;
+ unsigned long old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+ ret = sys_newlstat((char *)A(filename), &s);
+ set_fs (old_fs);
+ if (putstat (statbuf, &s)) return -EFAULT;
+ return ret;
}
asmlinkage int sys32_newfstat(unsigned int fd, u32 statbuf)
{
- return sys_newfstat(fd, (struct stat *)A(statbuf));
+ int ret;
+ struct stat s;
+ unsigned long old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+ ret = sys_newfstat(fd, &s);
+ set_fs (old_fs);
+ if (putstat (statbuf, &s)) return -EFAULT;
+ return ret;
}
asmlinkage int sys32_readlink(u32 path, u32 buf, int bufsiz)
{
va_list args;
unsigned int x;
- int ret;
+ int ret = -EINVAL;
va_start(args, option);
switch (option) {
return ret;
}
+/* Continue here */
asmlinkage int sys32_ustat(dev_t dev, u32 ubuf)
{
return sys_ustat(dev, (struct ustat *)A(ubuf));
-/* $Id: systbls.S,v 1.5 1997/04/09 08:25:16 jj Exp $
+/* $Id: systbls.S,v 1.6 1997/04/16 10:27:15 jj Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
.xword sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname
/*190*/ .xword sys_nis_syscall, sys32_personality, sys_prof, sys_break, sys_lock
.xword sys_mpx, sys_ulimit, sys_getppid, sparc32_sigaction, sys_sgetmask
-/*200*/ .xword sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys32_uselib, old_readdir
+/*200*/ .xword sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys32_uselib, old32_readdir
.xword sys_nis_syscall, sys32_socketcall, sys32_syslog, sys32_olduname, sys_nis_syscall
/*210*/ .xword sys_idle, sys_nis_syscall, sys32_waitpid, sys32_swapoff, sys32_sysinfo
.xword sys32_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
-/* $Id: init.c,v 1.22 1997/04/12 04:28:48 davem Exp $
+/* $Id: init.c,v 1.23 1997/04/16 10:27:18 jj Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
unsigned long tlb_context_cache = CTX_FIRST_VERSION;
+/* References to section boundaries */
+extern char __init_begin, __init_end, etext, __p1275_loc, __bss_start;
+
/*
* BAD_PAGE is the page that is used for page faults when linux
* is out-of-memory. Older versions of linux just did a
char *mmu_info(void)
{
+ /* XXX */
return "MMU Type: Spitfire\n\tFIXME: Write this\n";
}
else
pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __DIRTY_BITS));
-#if 0
- prom_printf("IOMAP: vaddr[%016lx]paddr[%016lx]ptep[%016lx]pte[%016lx])\n",
- virt_addr, physaddr, (unsigned long) ptep, pte_val(pte));
- prom_printf("IOMAP: pgd[%016lx,%016lx]\n",
- (unsigned long) pgdp, pgd_val(*pgdp));
- prom_printf("IOMAP: pmd[%016lx,%016lx]\n",
- (unsigned long) pmdp, pmd_val(*pmdp));
-#endif
-
set_pte(ptep, pte);
}
pte_clear(ptep);
}
+#ifdef DEBUG_MMU
void sparc_ultra_dump_itlb(void)
{
int slot;
slot+1, spitfire_get_dtlb_tag(slot+1), spitfire_get_dtlb_data(slot+1));
}
}
+#endif
/* paging_init() sets up the page tables */
__initfunc(unsigned long
paging_init(unsigned long start_mem, unsigned long end_mem))
{
- extern unsigned long __p1275_loc;
extern unsigned long phys_base;
extern void setup_tba(unsigned long kpgdir);
extern void __bfill64(void *, unsigned long);
{
int codepages = 0;
int datapages = 0;
+ int initpages = 0;
+ int prompages = 0;
unsigned long tmp2, addr;
unsigned long data_end;
- extern char etext;
end_mem &= PAGE_MASK;
max_mapnr = MAP_NR(end_mem);
if(PageReserved(mem_map + MAP_NR(addr))) {
if ((addr < (unsigned long) &etext) && (addr >= PAGE_OFFSET))
codepages++;
+ else if((addr >= (unsigned long)&__init_begin && addr < (unsigned long)&__init_end))
+ initpages++;
+ else if((addr >= (unsigned long)&__p1275_loc && addr < (unsigned long)&__bss_start))
+ prompages++;
else if((addr < data_end) && (addr >= PAGE_OFFSET))
datapages++;
continue;
tmp2 = nr_free_pages << PAGE_SHIFT;
- printk("Memory: %luk available (%dk kernel code, %dk data) [%016lx,%016lx]\n",
+ printk("Memory: %luk available (%dk kernel code, %dk data, %dk init, %dk prom) [%016lx,%016lx]\n",
tmp2 >> 10,
codepages << (PAGE_SHIFT-10),
- datapages << (PAGE_SHIFT-10), PAGE_OFFSET, end_mem);
+ datapages << (PAGE_SHIFT-10),
+ initpages << (PAGE_SHIFT-10),
+ prompages << (PAGE_SHIFT-10),
+ PAGE_OFFSET, end_mem);
min_free_pages = nr_free_pages >> 7;
if(min_free_pages < 16)
min_free_pages = 16;
free_pages_low = min_free_pages + (min_free_pages >> 1);
free_pages_high = min_free_pages + min_free_pages;
-
-#if 0
- printk("Done in mem_init() halting\n");
- prom_cmdline();
-#endif
}
void free_initmem (void)
{
- extern char __init_begin, __init_end;
unsigned long addr;
addr = (unsigned long)(&__init_begin);
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-SUB_DIRS := block char net #streams
+SUB_DIRS := block char net pnp #streams
MOD_SUB_DIRS := $(SUB_DIRS) sbus
ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus sound cdrom isdn pnp
SUB_DIRS += pci
endif
-ifdef CONFIG_PNP
-SUB_DIRS += pnp
-MOD_SUB_DIRS += pnp
-endif
-
ifdef CONFIG_SBUS
SUB_DIRS += sbus
endif
*
*/
-#include <linux/module.h>
-
#define MAJOR_NR ACSI_MAJOR
#include <linux/config.h>
* ACSI disks...
*/
case BLKGETSIZE: /* Return device size */
- if (put_user(acsi_part[MINOR(inode->i_rdev)].nr_sects,
- (long *)arg))
- return -EFAULT;
+ return put_user(acsi_part[MINOR(inode->i_rdev)].nr_sects,
+ (long *) arg);
case BLKFLSBUF:
if(!suser()) return -EACCES;
if(!inode->i_rdev) return -EINVAL;
return DEV_SUPPORTED;
}
-#ifdef CONFIG_ATARI_SLM_MODULE
-void acsi_attach_SLMs( int (*attach_func)( int, int ) );
-#endif
+EXPORT_SYMBOL(acsi_delay_start);
+EXPORT_SYMBOL(acsi_delay_end);
+EXPORT_SYMBOL(acsi_wait_for_IRQ);
+EXPORT_SYMBOL(acsi_wait_for_noIRQ);
+EXPORT_SYMBOL(acsicmd_nodma);
+EXPORT_SYMBOL(acsi_getstatus);
+EXPORT_SYMBOL(acsi_buffer);
+EXPORT_SYMBOL(phys_acsi_buffer);
-static struct symbol_table acsi_symbol_table =
-{
-#include <linux/symtab_begin.h>
-
- X(acsi_delay_start),
- X(acsi_delay_end),
- X(acsi_wait_for_IRQ),
- X(acsi_wait_for_noIRQ),
- X(acsicmd_nodma),
- X(acsi_getstatus),
- X(acsi_buffer),
- X(phys_acsi_buffer),
#ifdef CONFIG_ATARI_SLM_MODULE
- X(acsi_extstatus),
- X(acsi_end_extstatus),
- X(acsi_extcmd),
- X(acsi_attach_SLMs),
-#endif
+void acsi_attach_SLMs( int (*attach_func)( int, int ) );
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(acsi_extstatus);
+EXPORT_SYMBOL(acsi_end_extstatus);
+EXPORT_SYMBOL(acsi_extcmd);
+EXPORT_SYMBOL(acsi_attach_SLMs);
-#ifdef CONFIG_ATARI_SLM_MODULE
/* to remember IDs of SLM devices, SLM module is loaded later
* (index is target#, contents is lun#, -1 means "no SLM") */
int SLM_devices[8];
for( i = 0; i < (MAX_DEV << 4); i++ )
acsi_blocksizes[i] = 1024;
blksize_size[MAJOR_NR] = acsi_blocksizes;
- register_symtab (&acsi_symbol_table);
}
#ifdef CONFIG_ATARI_SLM_MODULE
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/fd.h>
+#include <linux/hdreg.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/delay.h>
restore_flags(flags);
if (on_attempts == 0) {
+ on_attempts = -1;
#if 0
printk (KERN_ERR "motor_on failed, turning motor off\n");
fd_motor_off (nr);
int error;
unsigned long flags;
- switch(cmd)
- {
- case FDFMTBEG:
- get_hw(drive);
- if (fd_ref[drive] > 1) {
- rel_hw();
- return -EBUSY;
- }
- fsync_dev(inode->i_rdev);
- if (motor_on(drive) == 0) {
- rel_hw();
- return -ENODEV;
- }
- if (fd_calibrate(drive) == 0) {
- rel_hw();
- return -ENXIO;
- }
- floppy_off(drive);
- rel_hw();
- break;
- case FDFMTTRK:
- if (param < unit[drive].type->tracks * unit[drive].type->heads)
- {
- get_fdc(drive);
- get_hw(drive);
- fd_select(drive);
- if (fd_seek(drive,param)!=0)
- {
- savedtrack=param;
- memset(trackdata,FD_FILL_BYTE,unit[drive].sects*512);
- non_int_flush_track(drive);
- }
- floppy_off(drive);
- rel_hw();
- rel_fdc();
- }
- else
- return -EINVAL;
- break;
- case FDFMTEND:
- floppy_off(drive);
- invalidate_inodes(inode->i_rdev);
- invalidate_buffers(inode->i_rdev);
- break;
- case FDGETPRM:
- error = verify_area(VERIFY_WRITE, (void *)param,
- sizeof(struct floppy_struct));
- if (error)
- return error;
- memset((void *)&getprm, 0, sizeof (getprm));
- getprm.track=unit[drive].type->tracks;
- getprm.head=unit[drive].type->heads;
- getprm.sect=unit[drive].sects;
- getprm.size=unit[drive].blocks;
- copy_to_user((void *)param,(void *)&getprm,sizeof(struct floppy_struct));
+ switch(cmd){
+ case HDIO_GETGEO:
+ {
+ struct hd_geometry loc;
+ loc.heads = unit[drive].type->heads;
+ loc.sectors = unit[drive].sects;
+ loc.cylinders = unit[drive].type->tracks;
+ loc.start = 0;
+ if ((error = copy_to_user((void *)param, (void *)&loc,
+ sizeof(struct hd_geometry))))
+ return error;
+ break;
+ }
+ case FDFMTBEG:
+ get_hw(drive);
+ if (fd_ref[drive] > 1) {
+ rel_hw();
+ return -EBUSY;
+ }
+ fsync_dev(inode->i_rdev);
+ if (motor_on(drive) == 0) {
+ rel_hw();
+ return -ENODEV;
+ }
+ if (fd_calibrate(drive) == 0) {
+ rel_hw();
+ return -ENXIO;
+ }
+ floppy_off(drive);
+ rel_hw();
+ break;
+ case FDFMTTRK:
+ if (param < unit[drive].type->tracks * unit[drive].type->heads)
+ {
+ get_fdc(drive);
+ get_hw(drive);
+ fd_select(drive);
+ if (fd_seek(drive,param)!=0){
+ savedtrack=param;
+ memset(trackdata, FD_FILL_BYTE,
+ unit[drive].sects*512);
+ non_int_flush_track(drive);
+ }
+ floppy_off(drive);
+ rel_hw();
+ rel_fdc();
+ }
+ else
+ return -EINVAL;
+ break;
+ case FDFMTEND:
+ floppy_off(drive);
+ invalidate_inodes(inode->i_rdev);
+ invalidate_buffers(inode->i_rdev);
+ break;
+ case FDGETPRM:
+ memset((void *)&getprm, 0, sizeof (getprm));
+ getprm.track=unit[drive].type->tracks;
+ getprm.head=unit[drive].type->heads;
+ getprm.sect=unit[drive].sects;
+ getprm.size=unit[drive].blocks;
+ if ((error = copy_to_user((void *)param,
+ (void *)&getprm,
+ sizeof(struct floppy_struct))))
+ return error;
break;
- case BLKGETSIZE:
- if (put_user(unit[drive].blocks,(long *)param))
- return -EFAULT;
- break;
- case FDSETPRM:
- case FDDEFPRM:
- return -EINVAL;
- case FDFLUSH:
- save_flags(flags);
- cli();
- if ((drive == selected) && (writepending)) {
- del_timer (&flush_track_timer);
- restore_flags(flags);
- non_int_flush_track(selected);
- }
- else
- restore_flags(flags);
- break;
+ case BLKGETSIZE:
+ if (put_user(unit[drive].blocks,(long *)param))
+ return -EFAULT;
+ break;
+ case FDSETPRM:
+ case FDDEFPRM:
+ return -EINVAL;
+ case FDFLUSH:
+ save_flags(flags);
+ cli();
+ if ((drive == selected) && (writepending)) {
+ del_timer (&flush_track_timer);
+ restore_flags(flags);
+ non_int_flush_track(selected);
+ }
+ else
+ restore_flags(flags);
+ break;
#ifdef RAW_IOCTL
- case IOCTL_RAW_TRACK:
- error = verify_area(VERIFY_WRITE, (void *)param,
- unit[drive].type->read_size);
- if (error)
- return error;
- copy_to_user((void *)param, raw_buf, unit[drive].type->read_size);
- return unit[drive].type->read_size;
+ case IOCTL_RAW_TRACK:
+ error = copy_to_user((void *)param, raw_buf,
+ unit[drive].type->read_size);
+ if (error)
+ return error;
+ else
+ return unit[drive].type->read_size;
#endif
- default:
- printk(KERN_DEBUG "fd_ioctl: unknown cmd %d for drive %d.",cmd,drive);
- return -ENOSYS;
- }
+ default:
+ printk(KERN_DEBUG "fd_ioctl: unknown cmd %d for drive %d.",cmd,drive);
+ return -ENOSYS;
+ }
return 0;
}
* Michael (MSch) 11/07/96:
* - implemented FDSETPRM and FDDEFPRM ioctl
*
+ * Andreas (97/03/19):
+ * - implemented missing BLK* ioctls
+ *
* Things left to do:
* - Formatting
* - Maybe a better strategy for disk change detection (does anyone
static unsigned long PhysDMABuffer; /* physical address */
static int UseTrackbuffer = -1; /* Do track buffering? */
+MODULE_PARM(UseTrackbuffer, "i");
unsigned char *TrackBuffer; /* buffer for reads */
static unsigned long PhysTrackBuffer; /* physical address */
static int IsFormatting = 0, FormatError;
static int UserSteprate[FD_MAX_UNITS] = { -1, -1 };
+MODULE_PARM(UserSteprate, "1-" __MODULE_STRING(FD_MAX_UNITS) "i");
/* Synchronization of FDC access. */
static volatile int fdc_busy = 0;
static int fd_test_drive_present( int drive );
static void config_types( void );
static int floppy_open( struct inode *inode, struct file *filp );
-static void floppy_release( struct inode * inode, struct file * filp );
+static int floppy_release( struct inode * inode, struct file * filp );
/************************* End of Prototypes **************************/
drive &= 3;
switch (cmd) {
case FDGETPRM:
+ case BLKGETSIZE:
if (type) {
if (--type >= NUM_DISK_MINORS)
return -ENODEV;
else
dtp = UDT;
}
+ if (cmd == BLKGETSIZE)
+ return put_user(dtp->blocks, (long *)param);
+
memset((void *)&getprm, 0, sizeof(getprm));
getprm.size = dtp->blocks;
getprm.sect = dtp->spt;
if (copy_to_user((void *)param, &getprm, sizeof(getprm)))
return -EFAULT;
return 0;
+ case BLKRASET:
+ if (!suser())
+ return -EACCES;
+ if (param > 0xff)
+ return -EINVAL;
+ read_ahead[MAJOR(inode->i_rdev)] = param;
+ return 0;
+ case BLKRAGET:
+ return put_user(read_ahead[MAJOR(inode->i_rdev)],
+ (int *) param);
+ case BLKFLSBUF:
+ if (!suser())
+ return -EACCES;
+ fsync_dev(inode->i_rdev);
+ invalidate_buffers(inode->i_rdev);
+ return 0;
}
if (!IOCTL_ALLOWED)
return -EPERM;
} while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
}
if (handler) {
- if (in_interrupt())
- schedule_bh( (void *)(void *) handler);
- else
+ if(softirq_trylock()) {
+ /* got the lock, call the handler immediately */
handler();
+ softirq_endlock();
+ } else
+ /* we interrupted a bottom half. Defer handler */
+ schedule_bh( (void *)(void *) handler);
} else
FDCS->reset = 1;
is_alive("normal interrupt end");
#include <linux/major.h>
#include <linux/string.h>
#include <linux/blk.h>
+#include <linux/init.h>
#include <asm/system.h>
}
}
-static void setup_dev(struct gendisk *dev)
+static inline void setup_dev(struct gendisk *dev)
{
int i, drive;
int end_minor = dev->max_nr * dev->max_p;
}
}
-void device_setup(void)
+__initfunc(void device_setup(void))
{
extern void console_map_init(void);
#ifdef CONFIG_PNP_PARPORT
#include <linux/config.h>
#include <linux/locks.h>
#include <linux/mm.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/io.h>
extern void bpcd_init( void );
#endif
-int blk_dev_init(void)
+__initfunc(int blk_dev_init(void))
{
struct request * req;
struct blk_dev_struct *dev;
{
unsigned long i;
- if (--initrd_users) return;
+ if (--initrd_users) return 0;
for (i = initrd_start; i < initrd_end; i += PAGE_SIZE)
free_page(i);
initrd_start = 0;
}
/* Try ext2 */
- if (ext2sb->s_magic == EXT2_SUPER_MAGIC) {
+ if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) {
printk(KERN_NOTICE
"RAMDISK: Ext2 filesystem found at block %d\n",
start_block);
- nblocks = ext2sb->s_blocks_count;
+ nblocks = le32_to_cpu(ext2sb->s_blocks_count);
goto done;
}
#include <asm/setup.h>
#include <asm/bitops.h>
#include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
#define TRUE (1)
#define FALSE (0)
endif
endif
+ifeq ($(CONFIG_ATARI_DSP56K),y)
+L_OBJS += dsp56k.o
+S = y
+else
+ ifeq ($(CONFIG_ATARI_DSP56K),m)
+ M_OBJS += dsp56k.o
+ SM = y
+ endif
+endif
+
ifeq ($(CONFIG_DIGI),y)
L_OBJS += pcxx.o
else
* close access to the mouse
*/
-static int close_mouse(struct inode * inode, struct file * file)
+static int release_mouse(struct inode * inode, struct file * file)
{
fasync_mouse(inode, file, 0);
if (--mouse.active)
- return;
+ return 0;
free_irq(IRQ_AMIGA_VERTB, mouse_interrupt);
MSE_INT_OFF();
MOD_DEC_USE_COUNT;
NULL, /* mouse_ioctl */
NULL, /* mouse_mmap */
open_mouse,
- close_mouse,
+ release_mouse,
NULL,
fasync_mouse,
};
#include <asm/uaccess.h>
static struct mouse_status mouse;
-static int atari_mouse_x_threshold = 2, atari_mouse_y_threshold = 2;
+static int mouse_threshold[2] = {2,2};
+MODULE_PARM(mouse_threshold, "2i");
extern int atari_mouse_buttons;
static void atari_mouse_interrupt(char *buf)
mouse.dx = mouse.dy = 0;
atari_mouse_buttons = 0;
ikbd_mouse_y0_top ();
- ikbd_mouse_thresh (atari_mouse_x_threshold, atari_mouse_y_threshold);
+ ikbd_mouse_thresh (mouse_threshold[0], mouse_threshold[1]);
ikbd_mouse_rel_pos();
MOD_INC_USE_COUNT;
atari_mouse_interrupt_hook = atari_mouse_interrupt;
char *buffer, unsigned long count)
{
int dx, dy, buttons;
- int r;
if (count < 3)
return -EINVAL;
- if ((r = verify_area(VERIFY_WRITE, buffer, count)))
- return r;
if (!mouse.ready)
return -EAGAIN;
/* ikbd_mouse_disable */
if (mouse.dx == 0 && mouse.dy == 0)
mouse.ready = 0;
/* ikbd_mouse_rel_pos(); */
- put_user(buttons | 0x80, buffer);
- put_user((char) dx, buffer + 1);
- put_user((char) dy, buffer + 2);
- for (r = 3; r < count; r++)
- put_user (0, buffer + r);
- return r;
+ if (put_user(buttons | 0x80, buffer++) ||
+ put_user((char) dx, buffer++) ||
+ put_user((char) dy, buffer++))
+ return -EFAULT;
+ if (count > 3)
+ if (clear_user(buffer, count - 3))
+ return -EFAULT;
+ return count;
}
static unsigned int mouse_poll(struct file *file, poll_table *wait)
if (ints[1] < MIN_THRESHOLD || ints[1] > MAX_THRESHOLD)
printk( "atari_mouse_setup: bad threshold value (ignored)\n" );
else {
- atari_mouse_x_threshold = ints[1];
- atari_mouse_y_threshold = ints[1];
+ mouse_threshold[0] = ints[1];
+ mouse_threshold[1] = ints[1];
if (ints[0] > 1) {
if (ints[2] < MIN_THRESHOLD || ints[2] > MAX_THRESHOLD)
printk("atari_mouse_setup: bad threshold value (ignored)\n" );
else
- atari_mouse_y_threshold = ints[2];
+ mouse_threshold[1] = ints[2];
}
}
pb = parport_enumerate();
while (pb) {
- if (parport[0] == -1 || lp_searchfor(parport, count) ||
- (parport[0] == -3 &&
- pb->probe_info.class == PARPORT_CLASS_PRINTER)) {
- lp_table[count].dev =
- parport_register_device(pb, dev_name, NULL,
- lp_wakeup,
- lp_interrupt, PARPORT_DEV_TRAN,
- (void *) &lp_table[count]);
- lp_table[count].flags |= LP_EXIST;
- printk(KERN_INFO "lp%d: using %s at 0x%x, ", count,
- pb->name, pb->base);
- if (pb->irq == -1)
- printk("polling.\n");
- else
- printk("irq %d.\n", pb->irq);
+ /* We only understand PC-style ports. */
+ if (pb->modes & PARPORT_MODE_SPP) {
+ if (parport[0] == -1 || lp_searchfor(parport, count) ||
+ (parport[0] == -3 &&
+ pb->probe_info.class == PARPORT_CLASS_PRINTER)) {
+ lp_table[count].dev =
+ parport_register_device(pb, dev_name, NULL,
+ lp_wakeup,
+ lp_interrupt, PARPORT_DEV_TRAN,
+ (void *) &lp_table[count]);
+ lp_table[count].flags |= LP_EXIST;
+ printk(KERN_INFO "lp%d: using %s at 0x%x, ",
+ count, pb->name, pb->base);
+ if (pb->irq == -1)
+ printk("polling.\n");
+ else
+ printk("irq %d.\n", pb->irq);
+ }
+ if (++count == LP_NO)
+ break;
}
- if (++count == LP_NO)
- break;
pb = pb->next;
}
*
*/
-#include <linux/module.h>
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
static int lp_error;
-void lp_interrupt(int irq, void *dummy, struct pt_regs *fp)
+void lp_interrupt(int dev)
{
- unsigned long flags;
- int dev;
-
- for (dev = 0; dev < MAX_LP; dev++) {
- if ((lp_table[dev] != NULL) && (lp_table[dev]->lp_my_interrupt(dev) != 0))
- if (lp_table[dev]->do_print)
- {
- if (lp_table[dev]->copy_size)
- {
- save_flags(flags);
- cli();
- if (lp_char_interrupt(lp_table[dev]->lp_buffer[lp_table[dev]->bytes_written], dev)) {
- --lp_table[dev]->copy_size;
- ++lp_table[dev]->bytes_written;
- restore_flags(flags);
- }
- else
- {
- lp_table[dev]->do_print = 0;
- restore_flags(flags);
- lp_error = 1;
- wake_up_interruptible(&lp_table[dev]->lp_wait_q);
- }
- }
- else
- {
- lp_table[dev]->do_print = 0;
- lp_error = 0;
- wake_up_interruptible(&lp_table[dev]->lp_wait_q);
- }
-
- }
+ if (dev >= 0 && dev < MAX_LP && lp_table[dev]->do_print)
+ {
+ if (lp_table[dev]->copy_size)
+ {
+ unsigned long flags;
+ save_flags(flags);
+ cli();
+ if (lp_char_interrupt(lp_table[dev]->lp_buffer[lp_table[dev]->bytes_written], dev)) {
+ --lp_table[dev]->copy_size;
+ ++lp_table[dev]->bytes_written;
+ restore_flags(flags);
+ }
+ else
+ {
+ lp_table[dev]->do_print = 0;
+ restore_flags(flags);
+ lp_error = 1;
+ wake_up_interruptible(&lp_table[dev]->lp_wait_q);
+ }
+ }
+ else
+ {
+ lp_table[dev]->do_print = 0;
+ lp_error = 0;
+ wake_up_interruptible(&lp_table[dev]->lp_wait_q);
+ }
+
}
}
static int lp_open(struct inode *inode, struct file *file)
{
int dev = MINOR(inode->i_rdev);
+ int ret;
if (dev >= MAX_LP)
return -ENODEV;
lp_table[dev]->flags |= LP_BUSY;
- MOD_INC_USE_COUNT;
- lp_table[dev]->lp_open();
-
- return 0;
+ ret = lp_table[dev]->lp_open(dev);
+ if (ret != 0) {
+ lp_table[dev]->flags &= ~LP_BUSY;
+ }
+ else {
+ MOD_INC_USE_COUNT;
+ }
+ return ret;
}
static int lp_release(struct inode *inode, struct file *file)
int dev =MINOR(inode->i_rdev);
lp_table[dev]->flags &= ~LP_BUSY;
- lp_table[dev]->lp_release();
+ lp_table[dev]->lp_release(dev);
MOD_DEC_USE_COUNT;
return 0;
}
lp_release
};
-#ifdef CONFIG_MODULES
-static struct symbol_table parallel_syms = {
-#include <linux/symtab_begin.h>
- X(lp_table),
- X(lp_irq),
- X(lp_interrupt),
- X(lp_init),
- X(register_parallel),
- X(unregister_parallel),
-#include <linux/symtab_end.h>
-};
-#endif
+EXPORT_SYMBOL(lp_table);
+EXPORT_SYMBOL(lp_irq);
+EXPORT_SYMBOL(lp_interrupt);
+EXPORT_SYMBOL(lp_init);
+EXPORT_SYMBOL(register_parallel);
+EXPORT_SYMBOL(unregister_parallel);
int lp_init(void)
{
return -ENXIO;
}
-#ifdef CONFIG_MODULES
- if (register_symtab(¶llel_syms)) {
- unregister_chrdev(LP_MAJOR, "lp");
- printk(KERN_CRIT "unable to register parallel symtab\n");
- return -ENXIO;
- }
-#endif
-
#if WHICH_DRIVER == FORCE_POLLING
lp_irq = 0;
printk(KERN_INFO "lp_init: lp using polling driver\n");
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/random.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>
NULL /* fsync */
};
-int chr_dev_init(void)
+__initfunc(int chr_dev_init(void))
{
if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
int sz;
int delta;
char *first_free, *fj, *fnw;
- int j, k, i = 0;
+ int i, j, k;
/* we mostly copy too much here (512bytes), but who cares ;) */
if (copy_from_user(&tmp, user_kdgkb, sizeof(struct kbsentry)))
tmp.kb_string[sizeof(tmp.kb_string)-1] = '\0';
if (tmp.kb_func >= MAX_NR_FUNC)
return -EINVAL;
+ i = tmp.kb_func;
switch (cmd) {
case KDGKBSENT:
/*
* No interrupt could be used
*/
- pr_debug("Failed to aquire an IRQ line\n");
+ pr_debug("Failed to acquire an IRQ line\n");
continue;
}
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200
fi
-
+
tristate 'Apricot Xen-II on board ethernet' CONFIG_APRICOT
tristate 'CS89x0 support' CONFIG_CS89x0
tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
#include <linux/config.h>
#include <linux/netdevice.h>
#include <linux/errno.h>
+#include <linux/init.h>
#define NEXT_DEV NULL
extern int de600_probe(struct device *);
extern int de620_probe(struct device *);
-static int ethif_probe(struct device *dev)
+__initfunc(static int ethif_probe(struct device *dev))
{
u_long base_addr = dev->base_addr;
#include <asm/amigaints.h>
#include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
lp->stats.rx_errors++;
continue;
} else if (bits & LE_R1_ERR) {
- /* Count only the end frame as a tx error, not the beginning */
+ /* Count only the end frame as a rx error,
+ * not the beginning
+ */
if (bits & LE_R1_BUF) lp->stats.rx_fifo_errors++;
if (bits & LE_R1_CRC) lp->stats.rx_crc_errors++;
if (bits & LE_R1_OFL) lp->stats.rx_over_errors++;
if (bits & LE_R1_FRA) lp->stats.rx_frame_errors++;
if (bits & LE_R1_EOP) lp->stats.rx_errors++;
} else {
- len = rd->mblength;
+ len = (rd->mblength & 0xfff) - 4;
skb = dev_alloc_skb (len+2);
if (skb == 0) {
return status;
}
+ if (skb == NULL) {
+ dev_tint (dev);
+ printk ("skb is NULL\n");
+ return 0;
+ }
+
+ if (skb->len <= 0) {
+ printk ("skb len is %d\n", skb->len);
+ return 0;
+ }
/* Block a timer-based transmit from overlapping. */
#ifdef OLD_METHOD
dev->tbusy = 1;
struct lance_private *lp = (struct lance_private *) dev->priv;
volatile struct lance_init_block *ib = lp->init_block;
volatile struct lance_regs *ll = lp->ll;
- char shown;
- shown = 0;
while (dev->tbusy)
- if (!shown++)
- printk ("Waiting for tbusy to go down\n");
+ schedule();
set_bit (0, (void *) &dev->tbusy);
- shown = 0;
while (lp->tx_old != lp->tx_new)
- if (!shown)
- printk ("Waiting for buffer to empty\n");
+ schedule();
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
#include <asm/bitops.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
#include <asm/io.h>
#include <asm/irq.h>
if (ariadne_debug > 1) {
printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name,
board->Lance.RDP);
- printk("%s: %d packets missed\n", dev->name,
+ printk("%s: %lu packets missed\n", dev->name,
priv->stats.rx_missed_errors);
}
static char *version =
"bionet.c:v1.0 06-feb-96 (c) Hartmut Laue.\n";
-#ifdef MODULE
#include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
#include <linux/errno.h>
#include <linux/kernel.h>
#ifdef MODULE
-#include <linux/version.h>
-
-/* We should include the kernel identification string in the module.
- */
-static char kernel_version[] = UTS_RELEASE;
-
-#undef NEXT_DEV
-#define NEXT_DEV (&bio_dev)
-
static char bio_name[16];
static struct device bio_dev =
{
bio_name, /* filled in by register_netdev() */
0, 0, 0, 0, /* memory */
0, 0, /* base, irq */
- 0, 0, 0, NEXT_DEV, bionet_probe,
+ 0, 0, 0, NULL, bionet_probe,
};
int
static char *version =
"pamsnet.c:v0.2beta 30-mar-96 (c) Torsten Lang.\n";
-#ifdef MODULE
#include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
#include <linux/kernel.h>
#include <linux/sched.h>
#ifdef MODULE
-#include <linux/version.h>
-
-/* We should include the kernel identification string in the module.
- */
-static char kernel_version[] = UTS_RELEASE;
-
-#undef NEXT_DEV
-#define NEXT_DEV (&pam_dev)
-
static struct device pam_dev =
{
" ", /* filled in by register_netdev() */
0, 0, 0, 0, /* memory */
0, 0, /* base, irq */
- 0, 0, 0, NEXT_DEV, pamsnet_probe,
+ 0, 0, 0, NULL, pamsnet_probe,
};
int
* based on original code by Donald Becker, with changes by
* Alan Cox and Pauline Middelink.
*
+ * Support for 8-bit mode by Zoltan Szilagyi <zoltans@cs.arizona.edu>
+ *
* Many modifications, and currently maintained, by
* Philip Blundell <Philip.Blundell@pobox.com>
*/
* things seem to be getting better slowly.
*/
-/* It would be nice to seperate out all the 82586-specific code, so that it
- * could be shared between drivers (as with 8390.c). But this would be quite
- * a messy job. The main motivation for doing this would be to bring 3c507
- * support back up to scratch.
- */
-
/* If your card is confused about what sort of interface it has (eg it
* persistently reports "10baseT" when none is fitted), running 'SOFTSET /BART'
* or 'SOFTSET /LISA' from DOS seems to help.
/* Known bugs:
*
- * - 8-bit mode is not supported, and makes things go wrong.
- * - Multicast and promiscuous modes are not supported.
* - The card seems to want to give us two interrupts every time something
* happens, where just one would be better.
- * - The statistics may not be getting reported properly.
*/
+/*
+ *
+ * Note by Zoltan Szilagyi 10-12-96:
+ *
+ * I've succeeded in eliminating the "CU wedged" messages, and hence the
+ * lockups, which were only occuring with cards running in 8-bit mode ("force
+ * 8-bit operation" in Intel's SoftSet utility). This version of the driver
+ * sets the 82586 and the ASIC to 8-bit mode at startup; it also stops the
+ * CU before submitting a packet for transmission, and then restarts it as soon
+ * as the process of handing the packet is complete. This is definitely an
+ * unnecessary slowdown if the card is running in 16-bit mode; therefore one
+ * should detect 16-bit vs 8-bit mode from the EEPROM settings and act
+ * accordingly. In 8-bit mode with this bugfix I'm getting about 150 K/s for
+ * ftp's, which is significantly better than I get in DOS, so the overhead of
+ * stopping and restarting the CU with each transmit is not prohibitive in
+ * practice.
+ */
+
#include <linux/module.h>
#include <linux/kernel.h>
struct net_local
{
struct net_device_stats stats;
+ unsigned long last_tx; /* jiffies when last transmit started */
unsigned long init_time; /* jiffies when eexp_hw_init586 called */
unsigned short rx_first; /* first rx buf, same as RX_BUF_START */
unsigned short rx_last; /* last rx buf */
+ unsigned short rx_ptr; /* first rx buf to look at */
unsigned short tx_head; /* next free tx buf */
unsigned short tx_reap; /* first in-use tx buf */
unsigned short tx_tail; /* previous tx buf to tx_head */
unsigned short last_tx_restart; /* set to tx_link when we
restart the CU */
unsigned char started;
- unsigned char promisc;
unsigned short rx_buf_start;
unsigned short rx_buf_end;
unsigned short num_tx_bufs;
unsigned short num_rx_bufs;
+ unsigned char width; /* 0 for 16bit, 1 for 8bit */
+ unsigned char was_promisc;
+ unsigned char old_mc_count;
};
/* This is the code and data that is downloaded to the EtherExpress card's
*/
static unsigned short start_code[] = {
-/* 0xfff6 */
- 0x0000, /* set bus to 16 bits */
- 0x0000,0x0000,
- 0x0000,0x0000, /* address of ISCP (lo,hi) */
-
/* 0x0000 */
0x0001, /* ISCP: busy - cleared after reset */
0x0008,0x0000,0x0000, /* offset,address (lo,hi) of SCB */
0x0000,0x0000, /* pad */
0x0000,0x0000,
-/* 0x0020 -- start of 82586 CU program */
-#define CONF_LINK 0x0020
- 0x0000,Cmd_Config,
+/* 0x20 -- start of 82586 CU program */
+#define CONF_LINK 0x20
+ 0x0000,Cmd_Config,
0x0032, /* link to next command */
0x080c, /* 12 bytes follow : fifo threshold=8 */
0x2e40, /* don't rx bad frames
*/
0x6000, /* default backoff method & priority
* interframe spacing = 0x60 */
- 0xf200, /* slot time=0x200
+ 0xf200, /* slot time=0x200
* max collision retry = 0xf */
- 0x0000, /* no HDLC : normal CRC : enable broadcast
+#define CONF_PROMISC 0x2e
+ 0x0000, /* no HDLC : normal CRC : enable broadcast
* disable promiscuous/multicast modes */
0x003c, /* minimum frame length = 60 octets) */
- 0x0000,Cmd_INT|Cmd_SetAddr,
+ 0x0000,Cmd_SetAddr,
0x003e, /* link to next command */
+#define CONF_HWADDR 0x38
0x0000,0x0000,0x0000, /* hardware address placed here */
- 0x0000,Cmd_TDR,0x0048,
-/* 0x0044 -- TDR result placed here */
- 0x0000, 0x0000,
-
-/* Eventually, a set-multicast will go in here */
+ 0x0000,Cmd_MCast,
+ 0x0076, /* link to next command */
+#define CONF_NR_MULTICAST 0x44
+ 0x0000, /* number of multicast addresses */
+#define CONF_MULTICAST 0x46
+ 0x0000, 0x0000, 0x0000, /* some addresses */
+ 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000,
+
+#define CONF_DIAG_RESULT 0x76
+ 0x0000, Cmd_Diag,
+ 0x007c, /* link to next command */
+
+ 0x0000,Cmd_TDR|Cmd_INT,
+ 0x0084,
+#define CONF_TDR_RESULT 0x82
+ 0x0000,
0x0000,Cmd_END|Cmd_Nop, /* end of configure sequence */
- 0x0048,
-
- 0x0000
-
+ 0x0084 /* dummy link */
};
/* maps irq number to EtherExpress magic value */
static void eexp_hw_rxinit (struct device *dev);
static void eexp_hw_init586 (struct device *dev);
+static void eexp_setup_filter (struct device *dev);
+
+static char *eexp_ifmap[]={"AUI", "BNC", "RJ45"};
+enum eexp_iftype {AUI=0, BNC=1, TPE=2};
+
+#define STARTED_RU 2
+#define STARTED_CU 1
/*
* Primitive hardware access functions.
int express_probe(struct device *dev)
{
- unsigned short *port,ports[] = { 0x0300,0x0270,0x0320,0x0340,0 };
+ unsigned short *port;
+ static unsigned short ports[] = { 0x300,0x310,0x270,0x320,0x340,0 };
unsigned short ioaddr = dev->base_addr;
if (ioaddr&0xfe00)
{
int irq = dev->irq;
unsigned short ioaddr = dev->base_addr;
+ struct net_local *lp = (struct net_local *)dev->priv;
#if NET_DEBUG > 6
printk(KERN_DEBUG "%s: eexp_open()\n", dev->name);
return -EAGAIN;
request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress");
+ request_region(ioaddr+0x4000, 16, "EtherExpress shadow");
+ request_region(ioaddr+0x8000, 16, "EtherExpress shadow");
+ request_region(ioaddr+0xc000, 16, "EtherExpress shadow");
dev->tbusy = 0;
dev->interrupt = 0;
+
+ if (lp->width) {
+ printk("%s: forcing ASIC to 8-bit mode\n", dev->name);
+ outb(inb(dev->base_addr+Config)&~4, dev->base_addr+Config);
+ }
eexp_hw_init586(dev);
dev->start = 1;
/*
* close and disable the interface, leaving the 586 in reset.
*/
+
static int eexp_close(struct device *dev)
{
unsigned short ioaddr = dev->base_addr;
/* If dev->tbusy is set, all our tx buffers are full but the kernel
* is calling us anyway. Check that nothing bad is happening.
*/
- if (dev->tbusy)
- unstick_cu(dev);
-
+ if (dev->tbusy) {
+ int status = scb_status(dev);
+ unstick_cu(dev);
+ if ((jiffies - lp->last_tx) < HZ)
+ return 1;
+ printk(KERN_INFO "%s: transmit timed out, %s?", dev->name,
+ (SCB_complete(status)?"lost interrupt":
+ "board on fire"));
+ lp->stats.tx_errors++;
+ dev->tbusy = 0;
+ lp->last_tx = jiffies;
+ if (!SCB_complete(status)) {
+ scb_command(dev, SCB_CUabort);
+ outb(0,dev->base_addr+SIGNAL_CA);
+ }
+ }
+
if (set_bit(0,(void *)&dev->tbusy))
{
lp->stats.tx_dropped++;
ETH_ZLEN;
unsigned short *data = (unsigned short *)buf->data;
+ lp->stats.tx_bytes += length;
+
eexp_hw_tx_pio(dev,data,length);
}
dev_kfree_skb(buf, FREE_WRITE);
* check to make sure we've not become wedged.
*/
+/*
+ * Handle an EtherExpress interrupt
+ * If we've finished initializing, start the RU and CU up.
+ * If we've already started, reap tx buffers, handle any received packets,
+ * check to make sure we've not become wedged.
+ */
+
+static unsigned short eexp_start_irq(struct device *dev,
+ unsigned short status)
+{
+ unsigned short ack_cmd = SCB_ack(status);
+ struct net_local *lp = (struct net_local *)dev->priv;
+ unsigned short ioaddr = dev->base_addr;
+ if ((dev->flags & IFF_UP) && !(lp->started & STARTED_CU)) {
+ short diag_status, tdr_status;
+ while (SCB_CUstat(status)==2)
+ status = scb_status(dev);
+#if NET_DEBUG > 4
+ printk("%s: CU went non-active (status %04x)\n",
+ dev->name, status);
+#endif
+
+ outw(CONF_DIAG_RESULT & ~31, ioaddr + SM_PTR);
+ diag_status = inw(ioaddr + SHADOW(CONF_DIAG_RESULT));
+ if (diag_status & 1<<11) {
+ printk(KERN_WARNING "%s: 82586 failed self-test\n",
+ dev->name);
+ } else if (!(diag_status & 1<<13)) {
+ printk(KERN_WARNING "%s: 82586 self-test failed to complete\n", dev->name);
+ }
+
+ outw(CONF_TDR_RESULT & ~31, ioaddr + SM_PTR);
+ tdr_status = inw(ioaddr + SHADOW(CONF_TDR_RESULT));
+ if (tdr_status & (TDR_SHORT|TDR_OPEN)) {
+ printk(KERN_WARNING "%s: TDR reports cable %s at %d tick%s\n", dev->name, (tdr_status & TDR_SHORT)?"short":"broken", tdr_status & TDR_TIME, ((tdr_status & TDR_TIME) != 1) ? "s" : "");
+ }
+ else if (tdr_status & TDR_XCVRPROBLEM) {
+ printk(KERN_WARNING "%s: TDR reports transceiver problem\n", dev->name);
+ }
+ else if (tdr_status & TDR_LINKOK) {
+#if NET_DEBUG > 4
+ printk(KERN_DEBUG "%s: TDR reports link OK\n", dev->name);
+#endif
+ } else {
+ printk("%s: TDR is ga-ga (status %04x)\n", dev->name,
+ tdr_status);
+ }
+
+ lp->started |= STARTED_CU;
+ scb_wrcbl(dev, lp->tx_link);
+ /* if the RU isn't running, start it now */
+ if (!(lp->started & STARTED_RU)) {
+ ack_cmd |= SCB_RUstart;
+ scb_wrrfa(dev, lp->rx_buf_start);
+ lp->rx_ptr = lp->rx_buf_start;
+ }
+ ack_cmd |= SCB_CUstart | 0x2000;
+ }
+
+ if ((dev->flags & IFF_UP) && !(lp->started & STARTED_RU) && SCB_RUstat(status)==4)
+ lp->started|=STARTED_RU;
+
+ return ack_cmd;
+}
+
+static void eexp_cmd_clear(struct device *dev)
+{
+ unsigned long int oldtime = jiffies;
+ while (scb_rdcmd(dev) && ((jiffies-oldtime)<10));
+ if (scb_rdcmd(dev)) {
+ printk("%s: command didn't clear\n", dev->name);
+ }
+}
+
static void eexp_irq(int irq, void *dev_info, struct pt_regs *regs)
{
struct device *dev = irq2dev_map[irq];
struct net_local *lp;
unsigned short ioaddr,status,ack_cmd;
+ unsigned short old_read_ptr, old_write_ptr;
if (dev==NULL)
{
lp = (struct net_local *)dev->priv;
ioaddr = dev->base_addr;
+ old_read_ptr = inw(ioaddr+READ_PTR);
+ old_write_ptr = inw(ioaddr+WRITE_PTR);
+
outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ);
dev->interrupt = 1;
printk(KERN_DEBUG "%s: interrupt (status %x)\n", dev->name, status);
#endif
- ack_cmd = SCB_ack(status);
+ if (lp->started == (STARTED_CU | STARTED_RU)) {
- if (lp->started==0 && SCB_complete(status))
- {
- while (SCB_CUstat(status)==2)
- status = scb_status(dev);
-#if NET_DEBUG > 4
- printk(KERN_DEBUG "%s: CU went non-active (status = %08x)\n",
- dev->name, status);
-#endif
+ do {
+ eexp_cmd_clear(dev);
- /* now get the TDR status */
- {
- short tdr_status;
- outw(0x40, dev->base_addr + SM_PTR);
- tdr_status = inw(dev->base_addr + 0x8004);
- if (tdr_status & TDR_SHORT) {
- printk(KERN_WARNING "%s: TDR reports cable short at %d tick%s\n", dev->name, tdr_status & TDR_TIME, ((tdr_status & TDR_TIME) != 1) ? "s" : "");
- }
- else if (tdr_status & TDR_OPEN) {
- printk(KERN_WARNING "%s: TDR reports cable broken at %d tick%s\n", dev->name, tdr_status & TDR_TIME, ((tdr_status & TDR_TIME) != 1) ? "s" : "");
- }
- else if (tdr_status & TDR_XCVRPROBLEM) {
- printk(KERN_WARNING "%s: TDR reports transceiver problem\n", dev->name);
- }
-#if NET_DEBUG > 4
- else if (tdr_status & TDR_LINKOK) {
- printk(KERN_DEBUG "%s: TDR reports link OK\n", dev->name);
- }
-#endif
- }
+ ack_cmd = SCB_ack(status);
+ scb_command(dev, ack_cmd);
+ outb(0,ioaddr+SIGNAL_CA);
- lp->started=1;
- scb_wrcbl(dev, lp->tx_link);
- scb_wrrfa(dev, lp->rx_buf_start);
- ack_cmd |= SCB_CUstart | SCB_RUstart | 0x2000;
- }
- else if (lp->started)
- {
- unsigned short txstatus;
- txstatus = eexp_hw_lasttxstat(dev);
- }
+ eexp_cmd_clear(dev);
- if (SCB_rxdframe(status))
- {
- eexp_hw_rx_pio(dev);
- }
+ if (SCB_complete(status)) {
+ if (!eexp_hw_lasttxstat(dev)) {
+ printk("%s: tx interrupt but no status\n", dev->name);
+ }
+ }
+
+ if (SCB_rxdframe(status))
+ eexp_hw_rx_pio(dev);
- if ((lp->started&2)!=0 && SCB_RUstat(status)!=4)
- {
- printk(KERN_WARNING "%s: RU stopped: status %04x\n",
- dev->name,status);
- lp->stats.rx_errors++;
- eexp_hw_rxinit(dev);
- scb_wrrfa(dev, lp->rx_buf_start);
- ack_cmd |= SCB_RUstart;
+ status = scb_status(dev);
+ } while (status & 0xc000);
+
+ if (SCB_RUdead(status))
+ {
+ printk(KERN_WARNING "%s: RU stopped: status %04x\n",
+ dev->name,status);
+#if 0
+ printk(KERN_WARNING "%s: cur_rfd=%04x, cur_rbd=%04x\n", dev->name, lp->cur_rfd, lp->cur_rbd);
+ outw(lp->cur_rfd, ioaddr+READ_PTR);
+ printk(KERN_WARNING "%s: [%04x]\n", dev->name, inw(ioaddr+DATAPORT));
+ outw(lp->cur_rfd+6, ioaddr+READ_PTR);
+ printk(KERN_WARNING "%s: rbd is %04x\n", dev->name, rbd= inw(ioaddr+DATAPORT));
+ outw(rbd, ioaddr+READ_PTR);
+ printk(KERN_WARNING "%s: [%04x %04x] ", dev->name, inw(ioaddr+DATAPORT), inw(ioaddr+DATAPORT));
+ outw(rbd+8, ioaddr+READ_PTR);
+ printk("[%04x]\n", inw(ioaddr+DATAPORT));
+#endif
+ lp->stats.rx_errors++;
+#if 1
+ eexp_hw_rxinit(dev);
+#else
+ lp->cur_rfd = lp->first_rfd;
+#endif
+ scb_wrrfa(dev, lp->rx_buf_start);
+ scb_command(dev, SCB_RUstart);
+ outb(0,ioaddr+SIGNAL_CA);
+ }
+ } else {
+ if (status & 0x8000)
+ ack_cmd = eexp_start_irq(dev, status);
+ else
+ ack_cmd = SCB_ack(status);
+ scb_command(dev, ack_cmd);
+ outb(0,ioaddr+SIGNAL_CA);
}
- else if (lp->started==1 && SCB_RUstat(status)==4)
- lp->started|=2;
- scb_command(dev, ack_cmd);
- outb(0,ioaddr+SIGNAL_CA);
+ eexp_cmd_clear(dev);
- outb(SIRQ_en|irqrmap[irq],ioaddr+SET_IRQ);
+ outb(SIRQ_en|irqrmap[irq],ioaddr+SET_IRQ);
dev->interrupt = 0;
-#if NET_DEBUG > 6
- printk(KERN_DEBUG "%s: leaving eexp_irq()\n", dev->name);
+#if NET_DEBUG > 6
+ printk("%s: leaving eexp_irq()\n", dev->name);
#endif
+ outw(old_read_ptr, ioaddr+READ_PTR);
+ outw(old_write_ptr, ioaddr+WRITE_PTR);
return;
}
* Hardware access functions
*/
+/*
+ * Set the cable type to use.
+ */
+
+static void eexp_hw_set_interface(struct device *dev)
+{
+ unsigned char oldval = inb(dev->base_addr + 0x300e);
+ oldval &= ~0x82;
+ switch (dev->if_port) {
+ case TPE:
+ oldval |= 0x2;
+ case BNC:
+ oldval |= 0x80;
+ break;
+ }
+ outb(oldval, dev->base_addr+0x300e);
+ udelay(20000);
+}
+
/*
* Check all the receive buffers, and hand any received packets
* to the upper levels. Basic sanity check on each frame
static void eexp_hw_rx_pio(struct device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
- unsigned short rx_block = lp->rx_first;
+ unsigned short rx_block = lp->rx_ptr;
unsigned short boguscount = lp->num_rx_bufs;
unsigned short ioaddr = dev->base_addr;
+ unsigned short status;
#if NET_DEBUG > 6
printk(KERN_DEBUG "%s: eexp_hw_rx()\n", dev->name);
#endif
- while (boguscount--)
- {
- unsigned short status, rfd_cmd, rx_next, pbuf, pkt_len;
-
+ do {
+ unsigned short rfd_cmd, rx_next, pbuf, pkt_len;
+
outw(rx_block, ioaddr + READ_PTR);
status = inw(ioaddr + DATAPORT);
- rfd_cmd = inw(ioaddr + DATAPORT);
- rx_next = inw(ioaddr + DATAPORT);
- pbuf = inw(ioaddr + DATAPORT);
if (FD_Done(status))
{
+ rfd_cmd = inw(ioaddr + DATAPORT);
+ rx_next = inw(ioaddr + DATAPORT);
+ pbuf = inw(ioaddr + DATAPORT);
+
outw(pbuf, ioaddr + READ_PTR);
pkt_len = inw(ioaddr + DATAPORT);
- if (rfd_cmd!=0x0000 || pbuf!=rx_block+0x16
- || (pkt_len & 0xc000)!=0xc000)
+ if (rfd_cmd!=0x0000)
+ {
+ printk(KERN_WARNING "%s: rfd_cmd not zero:0x%04x\n",
+ dev->name, rfd_cmd);
+ continue;
+ }
+ else if (pbuf!=rx_block+0x16)
{
- /* This should never happen. If it does,
- * we almost certainly have a driver bug.
- */
- printk(KERN_WARNING "%s: Rx frame at %04x corrupted, status %04x, cmd %04x, "
- "next %04x, pbuf %04x, len %04x\n",dev->name,rx_block,
- status,rfd_cmd,rx_next,pbuf,pkt_len);
+ printk(KERN_WARNING "%s: rfd and rbd out of sync 0x%04x 0x%04x\n",
+ dev->name, rx_block+0x16, pbuf);
continue;
}
- else if (!FD_OK(status))
+ else if ((pkt_len & 0xc000)!=0xc000)
+ {
+ printk(KERN_WARNING "%s: EOF or F not set on received buffer (%04x)\n",
+ dev->name, pkt_len & 0xc000);
+ continue;
+ }
+ else if (!FD_OK(status))
{
lp->stats.rx_errors++;
if (FD_CRC(status))
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
lp->stats.rx_packets++;
+ lp->stats.rx_bytes += pkt_len;
}
outw(rx_block, ioaddr+WRITE_PTR);
outw(0, ioaddr+DATAPORT);
outw(0, ioaddr+DATAPORT);
+ rx_block = rx_next;
}
- rx_block = rx_next;
- }
+ } while (FD_Done(status) && boguscount--);
+ lp->rx_ptr = rx_block;
}
/*
struct net_local *lp = (struct net_local *)dev->priv;
unsigned short ioaddr = dev->base_addr;
- outw(lp->tx_head, ioaddr + WRITE_PTR);
+ if (lp->width) {
+ /* Stop the CU so that there is no chance that it
+ jumps off to a bogus address while we are writing the
+ pointer to the next transmit packet in 8-bit mode --
+ this eliminates the "CU wedged" errors in 8-bit mode.
+ (Zoltan Szilagyi 10-12-96) */
+ scb_command(dev, SCB_CUsuspend);
+ outw(0xFFFF, ioaddr+SIGNAL_CA);
+ }
+
+ outw(lp->tx_head, ioaddr + WRITE_PTR);
outw(0x0000, ioaddr + DATAPORT);
outw(Cmd_INT|Cmd_Xmit, ioaddr + DATAPORT);
lp->tx_head += TX_BUF_SIZE;
if (lp->tx_head != lp->tx_reap)
dev->tbusy = 0;
+
+ if (lp->width) {
+ /* Restart the CU so that the packet can actually
+ be transmitted. (Zoltan Szilagyi 10-12-96) */
+ scb_command(dev, SCB_CUresume);
+ outw(0xFFFF, ioaddr+SIGNAL_CA);
+ }
+
+ lp->stats.tx_packets++;
+ lp->last_tx = jiffies;
}
/*
static int eexp_hw_probe(struct device *dev, unsigned short ioaddr)
{
unsigned short hw_addr[3];
+ unsigned char buswidth;
unsigned int memory_size;
- static char *ifmap[]={"AUI", "BNC", "RJ45"};
- enum iftype {AUI=0, BNC=1, TP=2};
int i;
unsigned short xsum = 0;
struct net_local *lp;
- printk("%s: EtherExpress 16 at %#x",dev->name,ioaddr);
+ printk("%s: EtherExpress 16 at %#x ",dev->name,ioaddr);
outb(ASIC_RST, ioaddr+EEPROM_Ctrl);
outb(0, ioaddr+EEPROM_Ctrl);
dev->dev_addr[i] = ((unsigned char *)hw_addr)[5-i];
{
- char irqmap[]={0, 9, 3, 4, 5, 10, 11, 0};
+ static char irqmap[]={0, 9, 3, 4, 5, 10, 11, 0};
unsigned short setupval = eexp_hw_readeeprom(ioaddr,0);
/* Use the IRQ from EEPROM if none was given */
dev->irq = irqmap[setupval>>13];
dev->if_port = !(setupval & 0x1000) ? AUI :
- eexp_hw_readeeprom(ioaddr,5) & 0x1 ? TP : BNC;
+ eexp_hw_readeeprom(ioaddr,5) & 0x1 ? TPE : BNC;
+
+ buswidth = !((setupval & 0x400) >> 10);
}
dev->priv = lp = kmalloc(sizeof(struct net_local), GFP_KERNEL);
memset(dev->priv, 0, sizeof(struct net_local));
- printk("; using IRQ %d, %s connector", dev->irq,ifmap[dev->if_port]);
-
+ printk("(IRQ %d, %s connector, %d-bit bus", dev->irq,
+ eexp_ifmap[dev->if_port], buswidth?8:16);
+
+ eexp_hw_set_interface(dev);
+
/* Find out how much RAM we have on the card */
outw(0, dev->base_addr + WRITE_PTR);
for (i = 0; i < 32768; i++)
for (memory_size = 0; memory_size < 64; memory_size++)
{
- outw(memory_size<<10, dev->base_addr + WRITE_PTR);
outw(memory_size<<10, dev->base_addr + READ_PTR);
if (inw(dev->base_addr+DATAPORT))
break;
+ outw(memory_size<<10, dev->base_addr + WRITE_PTR);
outw(memory_size | 0x5000, dev->base_addr+DATAPORT);
outw(memory_size<<10, dev->base_addr + READ_PTR);
if (inw(dev->base_addr+DATAPORT) != (memory_size | 0x5000))
case 32:
lp->rx_buf_end += 0x4000;
case 16:
- printk(", %dk RAM.\n", memory_size);
+ printk(", %dk RAM)\n", memory_size);
break;
default:
- printk("; bad memory size (%dk).\n", memory_size);
+ printk(") bad memory size (%dk).\n", memory_size);
kfree(dev->priv);
return ENODEV;
break;
}
lp->rx_buf_start = TX_BUF_START + (lp->num_tx_bufs*TX_BUF_SIZE);
+ lp->width = buswidth;
dev->open = eexp_open;
dev->stop = eexp_close;
do
{
- outw(tx_block, dev->base_addr + SM_PTR);
- status = inw(SHADOW(tx_block));
+ outw(tx_block & ~31, dev->base_addr + SM_PTR);
+ status = inw(dev->base_addr + SHADOW(tx_block));
if (!Stat_Done(status))
{
lp->tx_link = tx_block;
lp->stats.collisions += Stat_NoColl(status);
if (!Stat_OK(status))
{
- if (Stat_Abort(status))
- lp->stats.tx_aborted_errors++;
- if (Stat_TNoCar(status) || Stat_TNoCTS(status))
+ char *whatsup = NULL;
+ lp->stats.tx_errors++;
+ if (Stat_Abort(status))
+ lp->stats.tx_aborted_errors++;
+ if (Stat_TNoCar(status)) {
+ whatsup = "aborted, no carrier";
lp->stats.tx_carrier_errors++;
- if (Stat_TNoDMA(status))
- lp->stats.tx_fifo_errors++;
+ }
+ if (Stat_TNoCTS(status)) {
+ whatsup = "aborted, lost CTS";
+ lp->stats.tx_carrier_errors++;
+ }
+ if (Stat_TNoDMA(status)) {
+ whatsup = "FIFO underran";
+ lp->stats.tx_fifo_errors++;
+ }
+ if (Stat_TXColl(status)) {
+ whatsup = "aborted, too many collisions";
+ lp->stats.tx_aborted_errors++;
+ }
+ if (whatsup)
+ printk(KERN_INFO "%s: transmit %s\n",
+ dev->name, whatsup);
}
else
lp->stats.tx_packets++;
unsigned short ioaddr = dev->base_addr;
lp->num_rx_bufs = 0;
- lp->rx_first = rx_block;
+ lp->rx_first = lp->rx_ptr = rx_block;
do
{
lp->num_rx_bufs++;
outw(0, ioaddr + DATAPORT); outw(0, ioaddr+DATAPORT);
outw(rx_block + RX_BUF_SIZE, ioaddr+DATAPORT);
- outw(rx_block + 0x16, ioaddr+DATAPORT);
+ outw(0xffff, ioaddr+DATAPORT);
- outw(0xdead, ioaddr+DATAPORT);
+ outw(0x0000, ioaddr+DATAPORT);
outw(0xdead, ioaddr+DATAPORT);
outw(0xdead, ioaddr+DATAPORT);
outw(0xdead, ioaddr+DATAPORT);
outw(0xdead, ioaddr+DATAPORT);
outw(0xdead, ioaddr+DATAPORT);
- outw(0x8000, ioaddr+DATAPORT);
- outw(0xffff, ioaddr+DATAPORT);
+ outw(0x0000, ioaddr+DATAPORT);
+ outw(rx_block + RX_BUF_SIZE + 0x16, ioaddr+DATAPORT);
outw(rx_block + 0x20, ioaddr+DATAPORT);
outw(0, ioaddr+DATAPORT);
- outw(0x8000 | (RX_BUF_SIZE-0x20), ioaddr+DATAPORT);
+ outw(RX_BUF_SIZE-0x20, ioaddr+DATAPORT);
lp->rx_last = rx_block;
rx_block += RX_BUF_SIZE;
} while (rx_block <= lp->rx_buf_end-RX_BUF_SIZE);
- outw(lp->rx_last + 4, ioaddr+WRITE_PTR);
- outw(lp->rx_first, ioaddr+DATAPORT);
+ /* Make first Rx frame descriptor point to first Rx buffer
+ descriptor */
+ outw(lp->rx_first + 6, ioaddr+WRITE_PTR);
+ outw(lp->rx_first + 0x16, ioaddr+DATAPORT);
+
+ /* Close Rx frame descriptor ring */
+ outw(lp->rx_last + 4, ioaddr+WRITE_PTR);
+ outw(lp->rx_first, ioaddr+DATAPORT);
+
+ /* Close Rx buffer descriptor ring */
+ outw(lp->rx_last + 0x16 + 2, ioaddr+WRITE_PTR);
+ outw(lp->rx_first + 0x16, ioaddr+DATAPORT);
+
}
/*
* us. We can't start the receive/transmission system up before we know that
* the hardware is configured correctly.
*/
+
static void eexp_hw_init586(struct device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
set_loopback(dev);
- /* Bash the startup code a bit */
- start_code[28] = (dev->flags & IFF_PROMISC)?(start_code[28] | 1):
- (start_code[28] & ~1);
- lp->promisc = dev->flags & IFF_PROMISC;
- memcpy(&start_code[33], &dev->dev_addr[0], 6);
-
outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);
/* Download the startup code */
outw(lp->rx_buf_end & ~31, ioaddr + SM_PTR);
- outw(start_code[0], ioaddr + 0x8006);
- outw(start_code[1], ioaddr + 0x8008);
- outw(start_code[2], ioaddr + 0x800a);
- outw(start_code[3], ioaddr + 0x800c);
- outw(start_code[4], ioaddr + 0x800e);
- for (i = 10; i < (sizeof(start_code)); i+=32) {
+ outw(lp->width?0x0001:0x0000, ioaddr + 0x8006);
+ outw(0x0000, ioaddr + 0x8008);
+ outw(0x0000, ioaddr + 0x800a);
+ outw(0x0000, ioaddr + 0x800c);
+ outw(0x0000, ioaddr + 0x800e);
+
+ for (i = 0; i < (sizeof(start_code)); i+=32) {
int j;
- outw(i-10, ioaddr + SM_PTR);
+ outw(i, ioaddr + SM_PTR);
for (j = 0; j < 16; j+=2)
outw(start_code[(i+j)/2],
ioaddr+0x4000+j);
ioaddr+0x8000+j);
}
+ /* Do we want promiscuous mode or multicast? */
+ outw(CONF_PROMISC & ~31, ioaddr+SM_PTR);
+ i = inw(ioaddr+SHADOW(CONF_PROMISC));
+ outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1),
+ ioaddr+SHADOW(CONF_PROMISC));
+ lp->was_promisc = dev->flags & IFF_PROMISC;
+#if 0
+ eexp_setup_filter(dev);
+#endif
+
+ /* Write our hardware address */
+ outw(CONF_HWADDR & ~31, ioaddr+SM_PTR);
+ outw(((unsigned short *)dev->dev_addr)[0], ioaddr+SHADOW(CONF_HWADDR));
+ outw(((unsigned short *)dev->dev_addr)[1],
+ ioaddr+SHADOW(CONF_HWADDR+2));
+ outw(((unsigned short *)dev->dev_addr)[2],
+ ioaddr+SHADOW(CONF_HWADDR+4));
+
eexp_hw_txinit(dev);
eexp_hw_rxinit(dev);
return;
}
+static void eexp_setup_filter(struct device *dev)
+{
+ struct dev_mc_list *dmi = dev->mc_list;
+ unsigned short ioaddr = dev->base_addr;
+ int count = dev->mc_count;
+ int i;
+ if (count > 8) {
+ printk(KERN_INFO "%s: too many multicast addresses (%d)\n",
+ dev->name, count);
+ count = 8;
+ }
+
+ outw(CONF_NR_MULTICAST & ~31, ioaddr+SM_PTR);
+ outw(count, ioaddr+SHADOW(CONF_NR_MULTICAST));
+ for (i = 0; i < count; i++) {
+ unsigned short *data = (unsigned short *)dmi->dmi_addr;
+ if (!dmi) {
+ printk(KERN_INFO "%s: too few multicast addresses\n", dev->name);
+ break;
+ }
+ if (dmi->dmi_addrlen != ETH_ALEN) {
+ printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name);
+ continue;
+ }
+ outw((CONF_MULTICAST+(6*i)) & ~31, ioaddr+SM_PTR);
+ outw(data[0], ioaddr+SHADOW(CONF_MULTICAST+(6*i)));
+ outw((CONF_MULTICAST+(6*i)+2) & ~31, ioaddr+SM_PTR);
+ outw(data[1], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+2));
+ outw((CONF_MULTICAST+(6*i)+4) & ~31, ioaddr+SM_PTR);
+ outw(data[2], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+4));
+ }
+}
/*
* Set or clear the multicast filter for this adaptor.
static void
eexp_set_multicast(struct device *dev)
{
+ unsigned short ioaddr = dev->base_addr;
+ struct net_local *lp = (struct net_local *)dev->priv;
+ int kick = 0, i;
+ if ((dev->flags & IFF_PROMISC) != lp->was_promisc) {
+ outw(CONF_PROMISC & ~31, ioaddr+SM_PTR);
+ i = inw(ioaddr+SHADOW(CONF_PROMISC));
+ outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1),
+ ioaddr+SHADOW(CONF_PROMISC));
+ lp->was_promisc = dev->flags & IFF_PROMISC;
+ kick = 1;
+ }
+ if (!(dev->flags & IFF_PROMISC)) {
+ eexp_setup_filter(dev);
+ if (lp->old_mc_count != dev->mc_count) {
+ kick = 1;
+ lp->old_mc_count = dev->mc_count;
+ }
+ }
+ if (kick) {
+ unsigned long oj;
+ scb_command(dev, SCB_CUsuspend);
+ outb(0, ioaddr+SIGNAL_CA);
+ outb(0, ioaddr+SIGNAL_CA);
+#if 0
+ printk("%s: waiting for CU to go suspended\n", dev->name);
+#endif
+ oj = jiffies;
+ while ((SCB_CUstat(scb_status(dev)) == 2) &&
+ ((jiffies-oj) < 100));
+ if (SCB_CUstat(scb_status(dev)) == 2)
+ printk("%s: warning, CU didn't stop\n", dev->name);
+ lp->started &= ~(STARTED_CU);
+ scb_wrcbl(dev, CONF_LINK);
+ scb_command(dev, SCB_CUstart);
+ outb(0, ioaddr+SIGNAL_CA);
+ }
}
/*
* MODULE stuff
*/
+
#ifdef MODULE
#define EEXP_MAX_CARDS 4 /* max number of cards to support */
#include <asm/amigaints.h>
#include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
#include "hydra.h"
dev->stop = &hydra_close;
dev->hard_start_xmit = &hydra_start_xmit;
dev->get_stats = &hydra_get_stats;
- dev->set_multicast_list = &hydra_set_multicast_list;
+#ifdef HAVE_MULTICAST
+ dev->set_multicast_list = &set_multicast_list;
+#endif
/*
* Cannot yet do multicast
return(&priv->stats);
}
+#ifdef HAVE_MULTICAST
static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
{
struct hydra_private *priv = (struct hydra_private *)dev->priv;
/* (personally i don't care about multicasts at all :) */
return;
}
+#endif
#ifdef MODULE
/* Generated by cat $MYRI_HOME/lib/lanai/mcp4.dat > myri_code4.h */
static unsigned int lanai4_code_off = 0x0000; /* half-word offset */
-static unsigned char lanai4_code[76256] = {
+static unsigned char lanai4_code[76256] __initdata = {
0xF2,0x0E,
0xFE,0x00, 0xC2,0x90, 0x00,0x00, 0x07,0x88, 0x00,0x08, 0xE0,0x01, 0x01,0x4C, 0x97,0x93,
0xFF,0xFC, 0xE0,0x00, 0x00,0x14, 0x00,0x00, 0x00,0x01, 0x00,0x00, 0x00,0x00, 0x92,0x93,
/* This is the LANai data */
static unsigned int lanai4_data_off = 0x94F0; /* half-word offset */
-static unsigned char lanai4_data[20472] = {
+static unsigned char lanai4_data[20472] __initdata = {
0x00,0x00,
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,
#include <linux/in.h>
#include <linux/malloc.h>
#include <linux/string.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
return 0;
}
-static int myri_load_lanai(struct myri_eth *mp)
+static inline int myri_load_lanai(struct myri_eth *mp)
{
struct device *dev = mp->dev;
struct myri_shmem *shmem = mp->shmem;
}
#endif
-static int myri_ether_init(struct device *dev, struct linux_sbus_device *sdev, int num)
+static inline int myri_ether_init(struct device *dev, struct linux_sbus_device *sdev, int num)
{
static unsigned version_printed = 0;
struct myri_eth *mp;
return 0;
}
-int myri_sbus_probe(struct device *dev)
+__initfunc(int myri_sbus_probe(struct device *dev))
{
struct linux_sbus *bus;
struct linux_sbus_device *sdev = 0;
-/* $Id: plip.c,v 1.1.1.1.2.6 1997/03/26 17:52:20 phil Exp $ */
+/* $Id: plip.c,v 1.3.6.2 1997/04/16 15:07:56 phil Exp $ */
/* PLIP: A parallel port "network" driver for Linux. */
/* This driver is for parallel port with 5-bit cable (LapLink (R) cable). */
/*
return 0;
}
+static int
+plip_init_one(int i, struct parport *pb)
+{
+ if (i == PLIP_MAX) {
+ printk(KERN_ERR "plip: too many devices\n");
+ return 1;
+ }
+ dev_plip[i] = kmalloc(sizeof(struct device),
+ GFP_KERNEL);
+ if (!dev_plip[i]) {
+ printk(KERN_ERR "plip: memory squeeze\n");
+ return 1;
+ }
+ memset(dev_plip[i], 0, sizeof(struct device));
+ dev_plip[i]->name = kmalloc(strlen("plipXXX"), GFP_KERNEL);
+ if (!dev_plip[i]->name) {
+ printk(KERN_ERR "plip: memory squeeze.\n");
+ kfree(dev_plip[i]);
+ return 1;
+ }
+ sprintf(dev_plip[i]->name, "plip%d", i);
+ dev_plip[i]->priv = pb;
+ if (plip_init_dev(dev_plip[i],pb) || register_netdev(dev_plip[i])) {
+ kfree(dev_plip[i]->name);
+ kfree(dev_plip[i]);
+ return 1;
+ }
+ return 0;
+}
+
int
plip_init(void)
{
/* When user feeds parameters, use them */
while (pb) {
- if ((parport[0] == -1 && (!timid || !pb->devices)) ||
- plip_searchfor(parport, i)) {
- if (i == PLIP_MAX) {
- printk(KERN_ERR "plip: too many devices\n");
- break;
- }
- dev_plip[i] = kmalloc(sizeof(struct device),
- GFP_KERNEL);
- if (!dev_plip[i]) {
- printk(KERN_ERR "plip: memory squeeze\n");
- break;
- }
- memset(dev_plip[i], 0, sizeof(struct device));
- dev_plip[i]->name =
- kmalloc(strlen("plipXXX"), GFP_KERNEL);
- if (!dev_plip[i]->name) {
- printk(KERN_ERR "plip: memory squeeze.\n");
- kfree(dev_plip[i]);
- break;
- }
- sprintf(dev_plip[i]->name, "plip%d", i);
- dev_plip[i]->priv = pb;
- if (plip_init_dev(dev_plip[i],pb) || register_netdev(dev_plip[i])) {
- kfree(dev_plip[i]->name);
- kfree(dev_plip[i]);
- } else {
+ if (pb->modes & PARPORT_MODE_SPP) {
+ if ((parport[0] == -1 && (!timid || !pb->devices)) ||
+ plip_searchfor(parport, i)) {
+ if (plip_init_one(i, pb))
+ continue;
devices++;
}
+ i++;
}
- i++;
pb = pb->next;
- }
+ }
if (devices == 0) {
printk(KERN_INFO "plip: no devices registered\n");
#include <linux/in.h>
#include <linux/malloc.h>
#include <linux/string.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
dev->tbusy = 0;
}
-static int happy_meal_ether_init(struct device *dev, struct linux_sbus_device *sdev)
+static inline int happy_meal_ether_init(struct device *dev, struct linux_sbus_device *sdev)
{
static unsigned version_printed = 0;
struct happy_meal *hp;
return 0;
}
-int happy_meal_probe(struct device *dev)
+__initfunc(int happy_meal_probe(struct device *dev))
{
struct linux_sbus *bus;
struct linux_sbus_device *sdev = 0;
-/* $Id: sunlance.c,v 1.61 1997/04/10 06:40:54 davem Exp $
+/* $Id: sunlance.c,v 1.62 1997/04/16 10:27:25 jj Exp $
* lance.c: Linux/Sparc/Lance driver
*
* Written 1995, 1996 by Miguel de Icaza
#include <linux/in.h>
#include <linux/malloc.h>
#include <linux/string.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
dev->tbusy = 0;
}
-int sparc_lance_init (struct device *dev, struct linux_sbus_device *sdev,
- struct Linux_SBus_DMA *ledma,
- struct linux_sbus_device *lebuffer)
+__initfunc(static int
+sparc_lance_init (struct device *dev, struct linux_sbus_device *sdev,
+ struct Linux_SBus_DMA *ledma,
+ struct linux_sbus_device *lebuffer))
{
static unsigned version_printed = 0;
int i;
}
/* On 4m, find the associated dma for the lance chip */
-static struct Linux_SBus_DMA *
+static inline struct Linux_SBus_DMA *
find_ledma (struct linux_sbus_device *dev)
{
struct Linux_SBus_DMA *p;
}
/* Find all the lance cards on the system and initialize them */
-int sparc_lance_probe (struct device *dev)
+__initfunc(int sparc_lance_probe (struct device *dev))
{
struct linux_sbus *bus;
struct linux_sbus_device *sdev = 0;
#include <linux/in.h>
#include <linux/malloc.h>
#include <linux/string.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
}
/* Four QE's per QEC card. */
-static int qec_ether_init(struct device *dev, struct linux_sbus_device *sdev)
+static inline int qec_ether_init(struct device *dev, struct linux_sbus_device *sdev)
{
static unsigned version_printed = 0;
struct device *qe_devs[4];
return res;
}
-int qec_probe(struct device *dev)
+__initfunc(int qec_probe(struct device *dev))
{
struct linux_sbus *bus;
struct linux_sbus_device *sdev = 0;
* Read from card's Host Adaptor Status Register.
*/
static inline u_short
-hasr_read(u_short ioaddr)
+hasr_read(u_long ioaddr)
{
return(inw(HASR(ioaddr)));
} /* hasr_read */
* Write to card's Host Adapter Command Register.
*/
static inline void
-hacr_write(u_short ioaddr,
+hacr_write(u_long ioaddr,
u_short hacr)
{
outw(hacr, HACR(ioaddr));
* those times when it is needed.
*/
static inline void
-hacr_write_slow(u_short ioaddr,
+hacr_write_slow(u_long ioaddr,
u_short hacr)
{
hacr_write(ioaddr, hacr);
* Set the channel attention bit.
*/
static inline void
-set_chan_attn(u_short ioaddr,
+set_chan_attn(u_long ioaddr,
u_short hacr)
{
hacr_write(ioaddr, hacr | HACR_CA);
* Reset, and then set host adaptor into default mode.
*/
static inline void
-wv_hacr_reset(u_short ioaddr)
+wv_hacr_reset(u_long ioaddr)
{
hacr_write_slow(ioaddr, HACR_RESET);
hacr_write(ioaddr, HACR_DEFAULT);
* Set the i/o transfer over the ISA bus to 8 bits mode
*/
static inline void
-wv_16_off(u_short ioaddr,
+wv_16_off(u_long ioaddr,
u_short hacr)
{
hacr &= ~HACR_16BITS;
* Set the i/o transfer over the ISA bus to 8 bits mode
*/
static inline void
-wv_16_on(u_short ioaddr,
+wv_16_on(u_long ioaddr,
u_short hacr)
{
hacr |= HACR_16BITS;
wv_ints_off(device * dev)
{
net_local * lp = (net_local *)dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_long x;
x = wv_splhi();
wv_ints_on(device * dev)
{
net_local * lp = (net_local *)dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_long x;
x = wv_splhi();
* Read bytes from the PSA.
*/
static void
-psa_read(u_short ioaddr,
+psa_read(u_long ioaddr,
u_short hacr,
int o, /* offset in PSA */
u_char * b, /* buffer to fill */
* Write the Paramter Storage Area to the WaveLAN card's memory
*/
static void
-psa_write(u_short ioaddr,
+psa_write(u_long ioaddr,
u_short hacr,
int o, /* Offset in psa */
u_char * b, /* Buffer in memory */
* Write 1 byte to the MMC.
*/
static inline void
-mmc_out(u_short ioaddr,
+mmc_out(u_long ioaddr,
u_short o,
u_char d)
{
* We start by the end because it is the way it should be !
*/
static inline void
-mmc_write(u_short ioaddr,
+mmc_write(u_long ioaddr,
u_char o,
u_char * b,
int n)
* Optimised version for 1 byte, avoid using memory...
*/
static inline u_char
-mmc_in(u_short ioaddr,
+mmc_in(u_long ioaddr,
u_short o)
{
while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
* We start by the end because it is the way it should be !
*/
static inline void
-mmc_read(u_short ioaddr,
+mmc_read(u_long ioaddr,
u_char o,
u_char * b,
int n)
*(--b) = mmc_in(ioaddr, --o);
} /* mmc_read */
+/*------------------------------------------------------------------*/
+/*
+ * Get the type of encryption available...
+ */
+static inline int
+mmc_encr(u_long ioaddr) /* i/o port of the card */
+{
+ int temp;
+
+ temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail));
+ if((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES))
+ return 0;
+ else
+ return temp;
+}
+
/*------------------------------------------------------------------*/
/*
* Wait for the frequency EEprom to complete a command...
* I hope this one will be optimally inlined...
*/
static inline void
-fee_wait(u_short ioaddr, /* i/o port of the card */
+fee_wait(u_long ioaddr, /* i/o port of the card */
int delay, /* Base delay to wait for */
int number) /* Number of time to wait */
{
* Read bytes from the Frequency EEprom (frequency select cards).
*/
static void
-fee_read(u_short ioaddr, /* i/o port of the card */
+fee_read(u_long ioaddr, /* i/o port of the card */
u_short o, /* destination offset */
u_short * b, /* data buffer */
int n) /* number of registers */
}
}
+#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
+
/*------------------------------------------------------------------*/
/*
* Write bytes from the Frequency EEprom (frequency select cards).
* Jean II
*/
static void
-fee_write(u_short ioaddr, /* i/o port of the card */
+fee_write(u_long ioaddr, /* i/o port of the card */
u_short o, /* destination offset */
u_short * b, /* data buffer */
int n) /* number of registers */
fee_wait(ioaddr, 10, 100);
#endif /* EEPROM_IS_PROTECTED */
}
+#endif /* WIRELESS_EXT */
/************************ I82586 SUBROUTINES *************************/
/*
* Why inlining this function make it fail ???
*/
static /*inline*/ void
-obram_read(u_short ioaddr,
+obram_read(u_long ioaddr,
u_short o,
u_char * b,
int n)
* Write bytes to the on-board RAM.
*/
static inline void
-obram_write(u_short ioaddr,
+obram_write(u_long ioaddr,
u_short o,
u_char * b,
int n)
wv_ack(device * dev)
{
net_local * lp = (net_local *)dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_short scb_cs;
int i;
const char * str)
{
net_local * lp = (net_local *)dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_short scb_cmd;
ach_t cb;
int i;
*/
static inline int
wv_config_complete(device * dev,
- u_short ioaddr,
+ u_long ioaddr,
net_local * lp)
{
unsigned short mcs_addr;
*/
static int
wv_complete(device * dev,
- u_short ioaddr,
+ u_long ioaddr,
net_local * lp)
{
int nreaped = 0;
static void
wv_mmc_show(device * dev)
{
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
net_local * lp = (net_local *)dev->priv;
mmr_t m;
* Print the last block of the i82586 memory
*/
static void
-wv_scb_show(unsigned short ioaddr)
+wv_scb_show(u_long ioaddr)
{
scb_t scb;
int i,
u_short p)
{
- unsigned short ioaddr;
+ u_long ioaddr;
ac_tx_t actx;
ioaddr = dev->base_addr;
* (called in wavelan_ioctl)
*/
static inline int
-wv_set_frequency(u_short ioaddr, /* i/o port of the card */
+wv_set_frequency(u_long ioaddr, /* i/o port of the card */
iw_freq * frequency)
{
const int BAND_NUM = 10; /* Number of bands */
}
/* Setting by channel (same as wfreqsel) */
- /* Warning : each channel is 11MHz wide, so some of the channels
+ /* Warning : each channel is 22MHz wide, so some of the channels
* will interfere... */
if((frequency->e == 0) &&
(frequency->m >= 0) && (frequency->m < BAND_NUM))
* Give the list of available frequencies
*/
static inline int
-wv_frequency_list(u_short ioaddr, /* i/o port of the card */
+wv_frequency_list(u_long ioaddr, /* i/o port of the card */
iw_freq * list, /* List of frequency to fill */
int max) /* Maximum number of frequencies */
{
struct ifreq * rq, /* Data passed */
int cmd) /* Ioctl number */
{
- unsigned short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
net_local * lp = (net_local *)dev->priv; /* lp is not unused */
struct iwreq * wrq = (struct iwreq *) rq;
psa_t psa;
m.w.mmw_netw_id_h = (wrq->u.nwid.nwid & 0xFF00) >> 8;
mmc_write(ioaddr, (char *)&m.w.mmw_netw_id_l - (char *)&m,
(unsigned char *)&m.w.mmw_netw_id_l, 2);
- m.w.mmw_loopt_sel = 0x00;
- mmc_write(ioaddr, (char *)&m.w.mmw_loopt_sel - (char *)&m,
- (unsigned char *)&m.w.mmw_loopt_sel, 1);
+ mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
}
else
{
(char *)&psa.psa_nwid_select - (char *)&psa,
(unsigned char *)&psa.psa_nwid_select, 1);
- /* Disable nwid in the mmc (no check) */
- m.w.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID;
- mmc_write(ioaddr, (char *)&m.w.mmw_loopt_sel - (char *)&m,
- (unsigned char *)&m.w.mmw_loopt_sel, 1);
+ /* Disable nwid in the mmc (no filtering) */
+ mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID);
}
break;
wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F;
break;
+ case SIOCSIWENCODE:
+ /* Set encryption key */
+ if(!mmc_encr(ioaddr))
+ {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ if(wrq->u.encoding.method)
+ { /* enable encryption */
+ int i;
+ long long key = wrq->u.encoding.code;
+
+ for(i = 7; i >= 0; i--)
+ {
+ psa.psa_encryption_key[i] = key & 0xFF;
+ key >>= 8;
+ }
+ psa.psa_encryption_select = 1;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_encryption_select - (char *) &psa,
+ (unsigned char *) &psa.psa_encryption_select, 8+1);
+
+ mmc_out(ioaddr, mmwoff(0, mmw_encr_enable),
+ MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
+ mmc_write(ioaddr, mmwoff(0, mmw_encr_key),
+ (unsigned char *) &psa.psa_encryption_key, 8);
+ }
+ else
+ { /* disable encryption */
+ psa.psa_encryption_select = 0;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_encryption_select - (char *) &psa,
+ (unsigned char *) &psa.psa_encryption_select, 1);
+
+ mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);
+ }
+ break;
+
+ case SIOCGIWENCODE:
+ /* Read the encryption key */
+ if(!mmc_encr(ioaddr))
+ {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ /* only super-user can see encryption key */
+ if(!suser())
+ {
+ ret = -EPERM;
+ break;
+ }
+ else
+ {
+ int i;
+ long long key = 0;
+
+ psa_read(ioaddr, lp->hacr,
+ (char *) &psa.psa_encryption_select - (char *) &psa,
+ (unsigned char *) &psa.psa_encryption_select, 1+8);
+ for(i = 0; i < 8; i++)
+ {
+ key <<= 8;
+ key += psa.psa_encryption_key[i];
+ }
+ wrq->u.encoding.code = key;
+
+ /* encryption is enabled */
+ if(psa.psa_encryption_select)
+ wrq->u.encoding.method = mmc_encr(ioaddr);
+ else
+ wrq->u.encoding.method = 0;
+ }
+ break;
+
case SIOCGIWRANGE:
/* Basic checking... */
if(wrq->u.data.pointer != (caddr_t) 0)
static iw_stats *
wavelan_get_wireless_stats(device * dev)
{
- unsigned short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
net_local * lp = (net_local *) dev->priv;
mmr_t m;
iw_stats * wstats;
int sksize)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
struct sk_buff * skb;
#ifdef DEBUG_RX_TRACE
*/
netif_rx(skb);
+ /* Keep stats up to date */
lp->stats.rx_packets++;
- lp->stats.rx_bytes+=sksize;
+ lp->stats.rx_bytes += skb->len;
#ifdef DEBUG_RX_TRACE
printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name);
static inline void
wv_receive(device * dev)
{
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
net_local * lp = (net_local *)dev->priv;
int nreaped = 0;
short length)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
unsigned short txblock;
unsigned short txpred;
unsigned short tx_addr;
(unsigned char *) &nop.nop_h.ac_link,
sizeof(nop.nop_h.ac_link));
+ /* Keep stats up to date */
+ lp->stats.tx_bytes += length;
+
/* If watchdog not already active, activate it... */
if(lp->watchdog.prev == (timer_list *) NULL)
{
if(dev->tbusy)
return 1;
- /*
- * If some higher layer thinks we've missed
- * a tx-done interrupt we are passed NULL.
- * Caution: dev_tint() handles the cli()/sti() itself.
- */
- if(skb == (struct sk_buff *)0)
- {
-#ifdef DEBUG_TX_ERROR
- printk(KERN_INFO "%s: wavelan_packet_xmit(): skb == NULL\n", dev->name);
-#endif
- dev_tint(dev);
- return 0;
- }
-
/*
* Block a timer-based transmit from overlapping.
* In other words, prevent reentering this routine.
static inline int
wv_mmc_init(device * dev)
{
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
net_local * lp = (net_local *)dev->priv;
psa_t psa;
mmw_t m;
/* As NWID is not set : no NWID checking */
psa.psa_nwid_select = 0;
+ /* Disable encryption */
+ psa.psa_encryption_select = 0;
+
/* Set to standard values
* 0x04 for AT,
* 0x01 for MCA,
#ifdef USE_PSA_CONFIG
/* Write the psa */
psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
- (unsigned char *)psa.psa_nwid, 3);
+ (unsigned char *)psa.psa_nwid, 4);
psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
(unsigned char *)&psa.psa_thr_pre_set, 1);
psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
else
m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID;
+ memcpy(&m.mmw_encr_key, &psa.psa_encryption_key,
+ sizeof(m.mmw_encr_key));
+
+ if(psa.psa_encryption_select)
+ m.mmw_encr_enable = MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE;
+ else
+ m.mmw_encr_enable = 0;
+
m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F;
m.mmw_quality_thr = psa.psa_quality_thr & 0x0F;
wv_ru_start(device * dev)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_short scb_cs;
fd_t fd;
rbd_t rbd;
wv_cu_start(device * dev)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
int i;
u_short txblock;
u_short first_nop;
wv_82586_start(device * dev)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
scp_t scp; /* system configuration pointer */
iscp_t iscp; /* intermediate scp */
scb_t scb; /* system control block */
wv_82586_config(device * dev)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
unsigned short txblock;
unsigned short txpred;
unsigned short tx_addr;
wv_82586_stop(device * dev)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_short scb_cmd;
#ifdef DEBUG_CONFIG_TRACE
wv_hw_reset(device * dev)
{
net_local * lp = (net_local *)dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name,
* (called in wavelan_probe() and init_module())
*/
static int
-wv_check_ioaddr(u_short ioaddr,
+wv_check_ioaddr(u_long ioaddr,
u_char * mac)
{
int i; /* Loop counter */
struct pt_regs * regs)
{
device * dev;
- u_short ioaddr;
+ u_long ioaddr;
net_local * lp;
u_short hasr;
u_short status;
{
device * dev;
net_local * lp;
- unsigned short ioaddr;
+ u_long ioaddr;
unsigned long x;
unsigned int nreaped;
static int
wavelan_config(device * dev)
{
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_char irq_mask;
int irq;
net_local * lp;
/* ------------------------ SPECIFIC NOTES ------------------------ */
/*
+ * wavelan.o is darn too big
+ * -------------------------
+ * That's true ! There is a very simple way to reduce the driver
+ * object by 33% (yes !). Comment out the following line :
+ * #include <linux/wireless.h>
+ *
* MAC address and hardware detection :
* ----------------------------------
* The detection code of the wavelan chech that the first 3
* caracteristics of the hardware in a standard way and support for
* applications for taking advantage of it (like Mobile IP).
*
- * By default, these wireless extensions are disabled, because they
- * need a patch to the Linux Kernel. This simple patch may be found
- * with the driver + some utilities to access those wireless
- * extensions (iwconfig...). Hopefully, those wireless extensions will
- * make their way in the kernel someday.
+ * You will need to enable the CONFIG_NET_RADIO define in the kernel
+ * configuration to enable the wireless extensions (this is the one
+ * giving access to the radio network device choice).
*
- * You also will need to enable the CONFIG_NET_RADIO in the kernel
- * configuration to enable the wireless extensions.
+ * It might also be a good idea as well to fetch the wireless tools to
+ * configure the device and play a bit.
*/
/* ---------------------------- FILES ---------------------------- */
* Ajay Bakre (bakre@paul.rutgers.edu),
* Donald Becker (becker@cesdis.gsfc.nasa.gov),
* Loeke Brederveld (Loeke.Brederveld@Utrecht.NCR.com),
+ * Brent Elphick <belphick@uwaterloo.ca>,
* Anders Klemets (klemets@it.kth.se),
* Vladimir V. Kolpakov (w@stier.koenig.ru),
* Marc Meertens (Marc.Meertens@Utrecht.NCR.com),
* John Rosenberg (johnr@cs.usyd.edu.au),
* George Rossi (george@phm.gov.au),
* Arthur Scott (arthur@cs.usyd.edu.au),
+ * Stanislav Sinyagin <stas@isf.ru>
* Peter Storey,
* for their assistance and advice.
*
* - Update to wireless extensions changes
* - Silly bug in card initial configuration (psa_conf_status)
*
- * Changes made for release in 2.1.27 :
- * ----------------------------------
+ * Changes made for release in 2.1.27 & 2.0.30 :
+ * -------------------------------------------
* - Small bug in debug code (probably not the last one...)
* - Remove extern kerword for wavelan_probe()
* - Level threshold is now a standard wireless extension (version 4 !)
* - modules parameters types (new module interface)
*
+ * Changes made for release in 2.1.36 :
+ * ----------------------------------
+ * - byte count stats (courtesy of David Hinds)
+ * - Remove dev_tint stuff (courtesy of David Hinds)
+ * - Encryption setting from Brent Elphick (thanks a lot !)
+ * - 'ioaddr' to 'u_long' for the Alpha (thanks to Stanislav Sinyagin)
+ *
* Wishes & dreams :
* ---------------
- * - Encryption stuff
* - Roaming
*/
/************************ CONSTANTS & MACROS ************************/
#ifdef DEBUG_VERSION_SHOW
-static const char *version = "wavelan.c : v15 (wireless extensions) 12/2/97\n";
+static const char *version = "wavelan.c : v16 (wireless extensions) 17/4/97\n";
#endif
/* Watchdog temporisation */
wv_psa_to_irq(u_char);
/* ------------------- HOST ADAPTER SUBROUTINES ------------------- */
static inline u_short /* data */
- hasr_read(u_short); /* Read the host interface : base address */
+ hasr_read(u_long); /* Read the host interface : base address */
static inline void
- hacr_write(u_short, /* Write to host interface : base address */
+ hacr_write(u_long, /* Write to host interface : base address */
u_short), /* data */
- hacr_write_slow(u_short,
+ hacr_write_slow(u_long,
u_short),
- set_chan_attn(u_short, /* ioaddr */
+ set_chan_attn(u_long, /* ioaddr */
u_short), /* hacr */
- wv_hacr_reset(u_short), /* ioaddr */
- wv_16_off(u_short, /* ioaddr */
+ wv_hacr_reset(u_long), /* ioaddr */
+ wv_16_off(u_long, /* ioaddr */
u_short), /* hacr */
- wv_16_on(u_short, /* ioaddr */
+ wv_16_on(u_long, /* ioaddr */
u_short), /* hacr */
wv_ints_off(device *),
wv_ints_on(device *);
/* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
static void
- psa_read(u_short, /* Read the Parameter Storage Area */
+ psa_read(u_long, /* Read the Parameter Storage Area */
u_short, /* hacr */
int, /* offset in PSA */
u_char *, /* buffer to fill */
int), /* size to read */
- psa_write(u_short, /* Write to the PSA */
+ psa_write(u_long, /* Write to the PSA */
u_short, /* hacr */
int, /* Offset in psa */
u_char *, /* Buffer in memory */
int); /* Length of buffer */
static inline void
- mmc_out(u_short, /* Write 1 byte to the Modem Manag Control */
+ mmc_out(u_long, /* Write 1 byte to the Modem Manag Control */
u_short,
u_char),
- mmc_write(u_short, /* Write n bytes to the MMC */
+ mmc_write(u_long, /* Write n bytes to the MMC */
u_char,
u_char *,
int);
static inline u_char /* Read 1 byte from the MMC */
- mmc_in(u_short,
+ mmc_in(u_long,
u_short);
static inline void
- mmc_read(u_short, /* Read n bytes from the MMC */
+ mmc_read(u_long, /* Read n bytes from the MMC */
u_char,
u_char *,
int),
- fee_wait(u_short, /* Wait for frequency EEprom : base address */
+ fee_wait(u_long, /* Wait for frequency EEprom : base address */
int, /* Base delay to wait for */
int); /* Number of time to wait */
static void
- fee_read(u_short, /* Read the frequency EEprom : base address */
+ fee_read(u_long, /* Read the frequency EEprom : base address */
u_short, /* destination offset */
u_short *, /* data buffer */
- int), /* number of registers */
- fee_write(u_short, /* Write to frequency EEprom : base address */
- u_short, /* destination offset */
- u_short *, /* data buffer */
- int); /* number of registers */
+ int); /* number of registers */
/* ---------------------- I82586 SUBROUTINES ----------------------- */
static /*inline*/ void
- obram_read(u_short, /* ioaddr */
+ obram_read(u_long, /* ioaddr */
u_short, /* o */
u_char *, /* b */
int); /* n */
static inline void
- obram_write(u_short, /* ioaddr */
+ obram_write(u_long, /* ioaddr */
u_short, /* o */
u_char *, /* b */
int); /* n */
wv_synchronous_cmd(device *,
const char *),
wv_config_complete(device *,
- u_short,
+ u_long,
net_local *);
static int
wv_complete(device *,
- u_short,
+ u_long,
net_local *);
static inline void
wv_82586_reconfig(device *);
wv_82586_stop(device *);
static int
wv_hw_reset(device *), /* Reset the wavelan hardware */
- wv_check_ioaddr(u_short, /* ioaddr */
+ wv_check_ioaddr(u_long, /* ioaddr */
u_char *); /* mac address (read) */
/* ---------------------- INTERRUPT HANDLING ---------------------- */
static void
Currently known (or at least suspected) bugs in parport:
-o /proc/parport is buggy under 2.0.29 (ls /proc/parport/0 gives no such
- file or directory). David has suggested a fix for this. [/proc/parport
- has been temporarily taken out]
+o /proc/parport is untested under 2.0.XX
o SCSI aborts for PPA under 2.0.29 [reported by jmr]. Under investigation.
MIX_OBJS :=
ifeq ($(CONFIG_PNP_PARPORT),y)
- L_OBJS += parport_share.o parport_procfs.o
+ L_OBJS += parport_share.o
+ ifeq ($(CONFIG_PROC_FS),y)
+ L_OBJS += parport_procfs.o
+ endif
ifeq ($(CONFIG_PNP_PARPORT_AUTOPROBE),y)
L_OBJS += parport_probe.o
endif
LX_OBJS += parport_init.o
else
ifeq ($(CONFIG_PNP_PARPORT),m)
- MI_OBJS += parport_share.o parport_procfs.o
+ MI_OBJS += parport_share.o
+ ifneq ($(CONFIG_PROC_FS),n)
+ MI_OBJS += parport_procfs.o
+ endif
ifeq ($(CONFIG_PNP_PARPORT_AUTOPROBE),y)
MI_OBJS += parport_probe.o
endif
0. Fix the bugs (see BUGS-parport).
-1. Write a /proc interface for parport. As a starting point, we could
- probably have something like this:
+1. Proper documentation.
- /proc/parport/N/hardware
-
- Details of the port hardware - chipset, capabilities and so on.
- Read-only.
-
- /proc/parport/N/irq
-
- IRQ number of the port. Read-write.
-
- /proc/parport/N/devices
-
- List of devices connected to this bus, with the currently active
- one marked in some way. Probably you'd have the device in the
- first column, and '*' (for the current device) or '-' (for a
- lurker) in the second column.
-
- NOTE: The directory structure has been coded -- but the files are
- missing ...
-
-2. Proper documentation.
-
-3. Overhaul lp.c:
+2. Overhaul lp.c:
a) It's a mess, and there is a lot of code duplication.
bits when they have something to say. We should read out and deal
with (maybe just log) whatever the printer wants to tell the world.
-4. Assimilate more drivers.
+3. Assimilate more drivers.
-/* $Id: parport_init.c,v 1.1.2.4 1997/04/01 18:19:10 phil Exp $
+/* $Id: parport_init.c,v 1.3.2.4 1997/04/16 21:20:44 phil Exp $
* Parallel-port initialisation code.
*
* Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
#include "parport_ll_io.h"
static int io[PARPORT_MAX] = { 0, };
-static int irq[PARPORT_MAX] = { -1, };
-static int dma[PARPORT_MAX] = { -1, };
+static int irq[PARPORT_MAX] = { PARPORT_IRQ_NONE, };
+static int dma[PARPORT_MAX] = { PARPORT_DMA_NONE, };
/******************************************************
* DMA detection section:
return dma;
}
-static int parport_detect_dma_transfer(int dma,int size)
+static int parport_detect_dma_transfer(int dma,int size,int *resid)
{
int i,n,retv;
int count=0;
clear_dma_ff(i);
n = get_dma_residue(i);
if (n != size) {
+ *resid = n;
retv = i;
if (count > 0) {
retv = -1; /* Multiple DMA's */
- printk("Multiple DMA detected.\n");
+ printk(KERN_ERR "parport: multiple DMA detected. Huh?\n");
}
count++;
}
return dma;
}
-/* Only called if port support ECP mode.
+/* Only called if port supports ECP mode.
*
* The only restriction on DMA channels is that it has to be
* between 0 to 7 (inclusive). Used only in an ECP mode, DMAs are
char *buff;
retv = programmable_dma_support(pb);
- if( retv != -1 )
+ if (retv != -1)
return retv;
- buff = kmalloc(16, GFP_KERNEL | GFP_DMA);
- if( !buff ){
- printk("parport: memory squezze\n");
+ if (!(buff = kmalloc(2048, GFP_KERNEL | GFP_DMA))) {
+ printk(KERN_ERR "parport: memory squeeze\n");
return -1;
}
w_ecr(pb, 0xc0); /* ECP MODE */
w_ctr(pb, dsr_read );
- dma=parport_prepare_dma(buff,8);
+ dma=parport_prepare_dma(buff,1000);
w_ecr(pb, 0xd8); /* ECP FIFO + enable DMA */
parport_enable_dma(dma);
- udelay(30); /* Give some for DMA tranfer */
- retv = parport_detect_dma_transfer(dma,8);
+ udelay(500); /* Give some for DMA tranfer */
+ retv = parport_detect_dma_transfer(dma,1000,&pb->speed);
+ pb->speed = pb->speed * 2000; /* 500uSec * 2000 = 1sec */
/*
* National Semiconductors only supports DMA tranfers
* in ECP MODE
*/
- if( retv == -1 ){
+ if (retv == -1) {
w_ecr(pb, 0x60); /* ECP MODE */
w_ctr(pb, dsr_read );
- dma=parport_prepare_dma(buff,8);
+ dma=parport_prepare_dma(buff,1000);
w_ecr(pb, 0x68); /* ECP FIFO + enable DMA */
parport_enable_dma(dma);
- udelay(30); /* Give some for DMA tranfer */
- retv = parport_detect_dma_transfer(dma,8);
+ udelay(500); /* Give some for DMA tranfer */
+ retv = parport_detect_dma_transfer(dma,1000,&pb->speed);
+ pb->speed = pb->speed * 2000; /* 500uSec * 2000 = 1sec */
}
kfree(buff);
{
int r;
- if( !(r_str(pb) & 0x01) )
+ if (!(r_str(pb) & 0x01))
return 1;
- /* To clear timeout some chip requiere double read */
+ /* To clear timeout some chips require double read */
r_str(pb);
r = r_str(pb);
w_str(pb, r | 0x01); /* Some reset by writing 1 */
/*
- * Checks for por existence, all ports support SPP MODE
+ * Checks for port existence, all ports support SPP MODE
*/
static int parport_SPP_supported(struct parport *pb)
{
- int r,rr;
-
/* Do a simple read-write test to make sure the port exists. */
+
w_dtr(pb, 0xaa);
- r = r_dtr(pb);
+ if (r_dtr(pb) != 0xaa) return 0;
w_dtr(pb, 0x55);
- rr = r_dtr(pb);
-
- if (r != 0xaa || rr != 0x55) {
- return 0;
- }
-
+ if (r_dtr(pb) != 0x55) return 0;
+
return PARPORT_MODE_SPP;
}
{
int r;
- if( pb->base == 0x3BC )
- return 0;
-
r= r_ctr(pb);
- if( (r_ecr(pb) & 0x03) == (r & 0x03) ){
+ if ((r_ecr(pb) & 0x03) == (r & 0x03)) {
w_ctr(pb, r ^ 0x03 ); /* Toggle bits 0-1 */
r= r_ctr(pb);
- if( (r_ecr(pb) & 0x03) == (r & 0x03) )
+ if ((r_ecr(pb) & 0x03) == (r & 0x03))
return 0; /* Sure that no ECR register exists */
}
- if( (r_ecr(pb) & 0x03 ) != 0x01 )
+ if ((r_ecr(pb) & 0x03 ) != 0x01)
return 0;
w_ecr(pb,0x34);
- if( r_ecr(pb) != 0x35 )
+ if (r_ecr(pb) != 0x35)
return 0;
w_ecr(pb,pb->ecr);
{
int i;
- if( !(pb->modes & PARPORT_MODE_ECR) )
+ /* If there is no ECR, we have no hope of supporting ECP. */
+ if (!(pb->modes & PARPORT_MODE_ECR))
return 0;
+
/*
- * Usign LGS chipset it uses ECR register, but
+ * Using LGS chipset it uses ECR register, but
* it doesn't support ECP or FIFO MODE
*/
- w_ecr(pb,0xc0); /* TEST FIFO */
- for( i=0 ; i < 1024 && (r_ecr(pb) & 0x01) ; i++ )
+ w_ecr(pb, 0xc0); /* TEST FIFO */
+ for (i=0; i < 1024 && (r_ecr(pb) & 0x01); i++)
w_fifo(pb, 0xaa);
- w_ecr(pb,pb->ecr);
+ w_ecr(pb, pb->ecr);
- if( i >= 1024 )
+ if (i == 1024)
return 0;
return PARPORT_MODE_ECP;
*/
static int parport_EPP_supported(struct parport *pb)
{
- if( pb->base == 0x3BC )
- return 0;
-
/* If EPP timeout bit clear then EPP available */
- if( !epp_clear_timeout(pb) )
+ if (!epp_clear_timeout(pb))
return 0; /* No way to clear timeout */
w_ctr(pb, r_ctr(pb) | 0x20);
r_epp(pb);
udelay(30); /* Wait for possible EPP timeout */
- if( r_str(pb) & 0x01 ){
+ if (r_str(pb) & 0x01) {
epp_clear_timeout(pb);
return PARPORT_MODE_EPP;
}
{
int mode;
- if( !(pb->modes & PARPORT_MODE_ECR) )
+ if (!(pb->modes & PARPORT_MODE_ECR))
return 0;
/* Search for SMC style EPP+ECP mode */
mode = parport_EPP_supported(pb);
- w_ecr(pb,pb->ecr);
+ w_ecr(pb, pb->ecr);
- if( mode )
+ if (mode)
return PARPORT_MODE_ECPEPP;
return 0;
}
-/* Detect LP_PS2 support
- * Bit 5 (0x20) sets the PS/2 data direction, setting this high
- * allows us to read data from the data lines, old style SPP ports
- * will return 0xff. This may not be reliable if there is a
- * peripheral attached to the port.
+/* Detect PS/2 support.
+ *
+ * Bit 5 (0x20) sets the PS/2 data direction; setting this high
+ * allows us to read data from the data lines. In theory we would get back
+ * 0xff but any peripheral attached to the port may drag some or all of the
+ * lines down to zero. So if we get back anything that isn't the contents
+ * of the data register we deem PS/2 support to be present.
+ *
+ * Some SPP ports have "half PS/2" ability - you can't turn off the line
+ * drivers, but an external peripheral with sufficiently beefy drivers of
+ * its own can overpower them and assert its own levels onto the bus, from
+ * where they can then be read back as normal. Ports with this property
+ * and the right type of device attached are likely to fail the SPP test,
+ * (as they will appear to have stuck bits) and so the fact that they might
+ * be misdetected here is rather academic.
*/
+
static int parport_PS2_supported(struct parport *pb)
{
- int r,rr;
-
+ int ok = 0;
+
epp_clear_timeout(pb);
- w_ctr(pb, pb->ctr | 0x20); /* Tri-state the buffer */
+ w_ctr(pb, pb->ctr | 0x20); /* try to tri-state the buffer */
- w_dtr(pb, 0xAA);
- r = r_dtr(pb);
-
w_dtr(pb, 0x55);
- rr = r_dtr(pb);
-
- w_ctr(pb, pb->ctr); /* Reset CTR register */
+ if (r_dtr(pb) != 0x55) ok++;
- if (r != 0xAA || rr != 0x55 )
- return PARPORT_MODE_PS2;
+ w_dtr(pb, 0xaa);
+ if (r_dtr(pb) != 0xaa) ok++;
- return 0;
+ w_ctr(pb, pb->ctr); /* cancel input mode */
+
+ return ok?PARPORT_MODE_PS2:0;
}
static int parport_ECPPS2_supported(struct parport *pb)
{
int mode;
- if( !(pb->modes & PARPORT_MODE_ECR) )
+ if (!(pb->modes & PARPORT_MODE_ECR))
return 0;
w_ecr(pb, 0x20);
/******************************************************
* IRQ detection section:
- */
-/*
+ *
* This code is for detecting ECP interrupts (due to problems with the
* monolithic interrupt probing routines).
*
* In short this is a voting system where the interrupt with the most
* "votes" is the elected interrupt (it SHOULD work...)
+ *
+ * This is horribly x86-specific at the moment. I'm not convinced it
+ * belongs at all.
*/
+
static int intr_vote[16];
+
static void parport_vote_intr_func(int irq, void *dev_id, struct pt_regs *regs)
{
intr_vote[irq]++;
static int close_intr_election(long tmp)
{
- long max_vote = 0;
- int irq = -1;
+ int irq = PARPORT_IRQ_NONE;
int i;
/* We ignore the timer - irq 0 */
for (i = 1; i < 16; i++)
if (tmp & (1 << i)) {
- if (intr_vote[i] > max_vote) {
- if (max_vote)
- return -1;
- max_vote = intr_vote[i];
+ if (intr_vote[i]) {
+ if (irq != PARPORT_IRQ_NONE)
+ /* More than one interrupt */
+ return PARPORT_IRQ_NONE;
irq = i;
}
free_irq(i, intr_vote);
irqs = open_intr_election();
w_ecr(pb, 0x00); /* Reset FIFO */
- w_ctr(pb, pb->ctr ); /* Force direction = 0 */
+ w_ctr(pb, pb->ctr ); /* Force direction = 0 */
w_ecr(pb, 0xd0); /* TEST FIFO + nErrIntrEn */
/* If Full FIFO sure that WriteIntrThresold is generated */
}
pb->irq = close_intr_election(irqs);
- if (pb->irq == 0)
- pb->irq = -1; /* No interrupt detected */
w_ecr(pb, pb->ecr);
}
/*
- * It's called only if supports EPP on National Semiconductors
+ * This detection seems that only works in National Semiconductors
* This doesn't work in SMC, LGS, and Winbond
*/
static int irq_probe_EPP(struct parport *pb)
udelay(20);
pb->irq = close_intr_election(irqs);
- if (pb->irq == 0)
- pb->irq = -1; /* No interrupt detected */
w_ctr(pb,pb->ctr);
pb->irq = probe_irq_off(irqs);
if (pb->irq <= 0)
- pb->irq = -1; /* No interrupt detected */
+ pb->irq = PARPORT_IRQ_NONE; /* No interrupt detected */
w_ctr(pb,pb->ctr);
* such as sound cards and network cards seem to like using the
* printer IRQs.
*
- * When LP_ECP is available we can autoprobe for IRQs.
+ * When ECP is available we can autoprobe for IRQs.
* NOTE: If we can autoprobe it, we can register the IRQ.
*/
static int parport_irq_probe(struct parport *pb)
{
- if( pb->modes & PARPORT_MODE_ECR )
+ if (pb->modes & PARPORT_MODE_ECR)
pb->irq = programmable_irq_support(pb);
- if( pb->modes & PARPORT_MODE_ECP )
+ if (pb->modes & PARPORT_MODE_ECP)
pb->irq = irq_probe_ECP(pb);
- if( pb->irq == -1 && (pb->modes & PARPORT_MODE_ECPEPP)){
+ if (pb->irq == PARPORT_IRQ_NONE && (pb->modes & PARPORT_MODE_ECPEPP)) {
w_ecr(pb,0x80);
pb->irq = irq_probe_EPP(pb);
w_ecr(pb,pb->ecr);
epp_clear_timeout(pb);
- if( pb->irq == -1 && (pb->modes & PARPORT_MODE_EPP))
+ if (pb->irq == PARPORT_IRQ_NONE && (pb->modes & PARPORT_MODE_EPP))
pb->irq = irq_probe_EPP(pb);
epp_clear_timeout(pb);
- if( pb->irq == -1 )
+ if (pb->irq == PARPORT_IRQ_NONE)
pb->irq = irq_probe_SPP(pb);
return pb->irq;
{
/* Check some parameters */
if (dma < -2) {
- printk("parport: Invalid DMA[%d] at base 0x%lx\n",dma,base);
+ printk(KERN_ERR "parport: Invalid DMA[%d] at base 0x%lx\n",dma,base);
return 0;
}
if (irq < -2) {
- printk("parport: Invalid IRQ[%d] at base 0x%lx\n",irq,base);
+ printk(KERN_ERR "parport: Invalid IRQ[%d] at base 0x%lx\n",irq,base);
return 0;
}
pb->name = kmalloc(15, GFP_KERNEL);
if (!pb->name) {
- printk("parport: memory squeeze\n");
+ printk(KERN_ERR "parport: memory squeeze\n");
return 0;
}
sprintf(pb->name, "parport%d", count);
}
pb->modes |= PARPORT_MODE_SPP; /* All ports support SPP mode. */
- pb->modes |= parport_ECR_present(pb);
- pb->modes |= parport_ECP_supported(pb);
pb->modes |= parport_PS2_supported(pb);
- pb->modes |= parport_ECPPS2_supported(pb);
- pb->modes |= parport_EPP_supported(pb);
- pb->modes |= parport_ECPEPP_supported(pb);
+
+ if (pb->base != 0x3bc) {
+ pb->modes |= parport_ECR_present(pb);
+ pb->modes |= parport_ECP_supported(pb);
+ pb->modes |= parport_ECPPS2_supported(pb);
+ pb->modes |= parport_EPP_supported(pb);
+ pb->modes |= parport_ECPEPP_supported(pb);
+ }
/* Now register regions */
if ((pb->modes & (PARPORT_MODE_EPP | PARPORT_MODE_ECPEPP)) &&
/* DMA check */
if (pb->modes & PARPORT_MODE_ECP) {
- if (pb->dma == -1)
+ if (pb->dma == PARPORT_DMA_NONE)
pb->dma = parport_dma_probe(pb);
else if (pb->dma == -2)
- pb->dma = -1;
+ pb->dma = PARPORT_DMA_NONE;
}
/* IRQ check */
- if (pb->irq == -1)
+ if (pb->irq == PARPORT_IRQ_NONE)
pb->irq = parport_irq_probe(pb);
else if (pb->irq == -2)
- pb->irq = -1;
+ pb->irq = PARPORT_IRQ_NONE;
return 1;
}
{
if (ints[0] == 0 || ints[1] == 0) {
/* Disable parport if "parport=" or "parport=0" in cmdline */
- io[0] = -2;
+ io[0] = PARPORT_DISABLE;
return;
}
if (parport_setup_ptr < PARPORT_MAX) {
struct parport *pb;
printk(KERN_INFO "Parallel port sharing: %s\n",
- "$Revision: 1.1.2.4 $");
+ "$Revision: 1.3.2.4 $");
- if (io[0] == -2) return 1;
+ if (io[0] == PARPORT_DISABLE) return 1;
- /* Register /proc/parport */
+#ifdef CONFIG_PROC_FS
parport_proc_register(NULL);
+#endif
/* Run probes to ensure parport does exist */
#define PORT(a,b,c) \
if ((pb = parport_register_port((a), (b), (c)))) \
parport_destroy(pb);
+
+
if (io[0]) {
/* If the user specified any ports, use them */
int i;
}
} else {
/* Go for the standard ports. */
- PORT(0x378, -1, -1);
- PORT(0x278, -1, -1);
- PORT(0x3bc, -1, -1);
+ PORT(0x378, PARPORT_IRQ_NONE, PARPORT_DMA_NONE);
+ PORT(0x278, PARPORT_IRQ_NONE, PARPORT_DMA_NONE);
+ PORT(0x3bc, PARPORT_IRQ_NONE, PARPORT_DMA_NONE);
#undef PORT
}
+#if defined(CONFIG_PNP_PARPORT_AUTOPROBE) || defined(CONFIG_PROC_FS)
+ for (pb = parport_enumerate(); pb; pb = pb->next) {
#ifdef CONFIG_PNP_PARPORT_AUTOPROBE
- for (pb = parport_enumerate(); pb; pb = pb->next)
parport_probe_one(pb);
#endif
+#ifdef CONFIG_PROC_FS
+ parport_proc_register(pb);
+#endif
+ }
+#endif
return 0;
}
kfree(port);
}
- parport_proc_unregister(NULL);
+ parport_proc_cleanup();
}
#endif
-/* $Id: parport_procfs.c,v 1.1.2.2 1997/03/26 17:50:36 phil Exp $
+/* $Id: parport_procfs.c,v 1.3.2.6 1997/04/16 21:30:38 phil Exp $
* Parallel port /proc interface code.
*
* Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
#include <linux/kernel.h>
#include <linux/malloc.h>
-#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
-#endif
#include <linux/parport.h>
+#include "parport_ll_io.h"
+
+#undef PARPORT_INCLUDE_BENCH
+
+struct proc_dir_entry *base=NULL;
-#if defined(CONFIG_PROC_FS) && defined(NOT_DEFINED)
+void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs);
-/************************************************/
-static long proc_readparport(struct inode * inode, struct file * file,
- char * buf, unsigned long count)
+static int irq_write_proc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
{
- printk("proc_readparport\n");
- return 0;
+ int newirq;
+ struct parport *pp = (struct parport *)data;
+
+ if (count > 4 ) /* more than 4 digits for a irq 0x?? 0?? ?? */
+ return(-EOVERFLOW);
+
+ if (buffer[0] < 32 || !strncmp(buffer, "none", 4)) {
+ newirq = PARPORT_IRQ_NONE;
+ } else {
+ if (buffer[0] == '0') {
+ if( buffer[1] == 'x' )
+ newirq = simple_strtoul(&buffer[2],0,16);
+ else
+ newirq = simple_strtoul(&buffer[1],0,8);
+ } else {
+ newirq = simple_strtoul(buffer,0,10);
+ }
+ }
+
+ if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA))
+ free_irq(pp->irq, pp);
+
+ pp->irq = newirq;
+
+ if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) {
+ struct ppd *pd = pp->cad;
+
+ if (pd == NULL) {
+ pd = pp->devices;
+ if (pd != NULL)
+ request_irq(pp->irq, pd->irq_func ?
+ pd->irq_func :
+ parport_null_intr_func,
+ SA_INTERRUPT, pd->name, pd->port);
+ } else {
+ request_irq(pp->irq, pd->irq_func ? pd->irq_func :
+ parport_null_intr_func,
+ SA_INTERRUPT, pp->name, pd->port);
+ }
+ }
+
+ return count;
}
-static long proc_writeparport(struct inode * inode, struct file * file,
- const char * buf, unsigned long count)
+static int irq_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- printk("proc_writeparport\n");
+ struct parport *pp = (struct parport *)data;
+ int len;
- return 0;
+ if (pp->irq == PARPORT_IRQ_NONE)
+ len = sprintf(page, "none\n");
+ else
+ len = sprintf(page, "%d\n", pp->irq);
+
+ *start = 0;
+ *eof = 1;
+ return len;
}
-static long long proc_parportlseek(struct inode * inode, struct file * file,
- long long offset, int orig)
+static int devices_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- switch (orig) {
- case 0:
- file->f_pos = offset;
- return(file->f_pos);
- case 1:
- file->f_pos += offset;
- return(file->f_pos);
- case 2:
- return(-EINVAL);
- default:
- return(-EINVAL);
- }
+ struct parport *pp = (struct parport *)data;
+ struct ppd *pd1;
+ int len=0;
+
+ for (pd1 = pp->devices; pd1 ; pd1 = pd1->next) {
+ if (pd1 == pp->cad)
+ len += sprintf(page+len, "+");
+ else
+ len += sprintf(page+len, " ");
+
+ len += sprintf(page+len, "%s",pd1->name);
+
+ if (pd1 == pp->lurker)
+ len += sprintf(page+len, " LURK");
+
+ len += sprintf(page+len,"\n");
+ }
+
+ *start = 0;
+ *eof = 1;
+ return len;
}
-static struct file_operations proc_dir_operations = {
- proc_parportlseek, /* lseek */
- proc_readparport, /* read */
- proc_writeparport, /* write */
- proc_readdir, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* no special release code */
- NULL /* can't fsync */
-};
-
-/************************************************/
-static struct inode_operations parport_proc_dir_inode_operations = {
- &proc_dir_operations, /* default net directory file-ops */
- NULL, /* create */
- proc_lookup, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
-
-static struct proc_dir_entry proc_root_parport = {
- PROC_PARPORT, 7, "parport",
- S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
- 0, &parport_proc_dir_inode_operations,
- NULL, NULL,
- NULL, &proc_root, NULL,
- NULL, NULL
-};
+static int hardware_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ struct parport *pp = (struct parport *)data;
+ int len=0;
+
+ len += sprintf(page+len, "base:\t0x%x\n",pp->base);
+ if (pp->irq == PARPORT_IRQ_NONE)
+ len += sprintf(page+len, "irq:\tnone\n");
+ else
+ len += sprintf(page+len, "irq:\t%d\n",pp->irq);
+ len += sprintf(page+len, "dma:\t%d\n",pp->dma);
+
+ len += sprintf(page+len, "modes:\t");
+ {
+#define printmode(x) {if(pp->modes&PARPORT_MODE_##x){len+=sprintf(page+len,"%s%s",f?",":"",#x);f++;}}
+ int f = 0;
+ printmode(SPP);
+ printmode(PS2);
+ printmode(EPP);
+ printmode(ECP);
+ printmode(ECPEPP);
+ printmode(ECPPS2);
+#undef printmode
+ }
+ len += sprintf(page+len, "\n");
+
+ len += sprintf(page+len, "mode:\t");
+ if (pp->modes & PARPORT_MODE_ECR) {
+ switch (r_ecr(pp) >> 5) {
+ case 0:
+ len += sprintf(page+len, "SPP");
+ if( pp->modes & PARPORT_MODE_PS2 )
+ len += sprintf(page+len, ",PS2");
+ if( pp->modes & PARPORT_MODE_EPP )
+ len += sprintf(page+len, ",EPP");
+ break;
+ case 1:
+ len += sprintf(page+len, "ECPPS2");
+ break;
+ case 2:
+ len += sprintf(page+len, "DATAFIFO");
+ break;
+ case 3:
+ len += sprintf(page+len, "ECP");
+ break;
+ case 4:
+ len += sprintf(page+len, "ECPEPP");
+ break;
+ case 5:
+ len += sprintf(page+len, "Reserved?");
+ break;
+ case 6:
+ len += sprintf(page+len, "TEST");
+ break;
+ case 7:
+ len += sprintf(page+len, "Configuration");
+ break;
+ }
+ } else {
+ len += sprintf(page+len, "SPP");
+ if (pp->modes & PARPORT_MODE_PS2)
+ len += sprintf(page+len, ",PS2");
+ if (pp->modes & PARPORT_MODE_EPP)
+ len += sprintf(page+len, ",EPP");
+ }
+ len += sprintf(page+len, "\n");
+
+#if 0
+ /* Now no detection, please fix with an external function */
+ len += sprintf(page+len, "chipset:\tunknown\n");
#endif
+#ifdef PARPORT_INCLUDE_BENCHMARK
+ if (pp->speed)
+ len += sprintf(page+len, "bench:\t%d Bytes/s\n",pp->speed);
+ else
+ len += sprintf(page+len, "bench:\tunknown\n");
+#endif
+
+ *start = 0;
+ *eof = 1;
+ return len;
+}
+
+static struct proc_dir_entry *new_proc_entry(const char *name, mode_t mode,
+ struct proc_dir_entry *parent,
+ unsigned short ino)
+{
+ struct proc_dir_entry *ent;
+
+ ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
+ if (!ent)
+ return NULL;
+ memset(ent, 0, sizeof(struct proc_dir_entry));
+
+ if (mode == S_IFDIR)
+ mode |= S_IRUGO | S_IXUGO;
+ else if (mode == 0)
+ mode = S_IFREG | S_IRUGO;
+
+
+ ent->low_ino = ino;
+ ent->name = name;
+ ent->namelen = strlen(name);
+ ent->mode = mode;
+ if (S_ISDIR(mode))
+ ent->nlink = 2;
+ else
+ ent->nlink = 1;
+
+ proc_register(parent, ent);
+
+ return ent;
+}
+
+
+int parport_proc_init()
+{
+ base = new_proc_entry("parport", S_IFDIR, &proc_root,PROC_PARPORT);
+
+ if (base)
+ return 1;
+ else {
+ printk(KERN_ERR "parport: Error creating proc entry /proc/parport\n");
+ return 0;
+ }
+}
+
+int parport_proc_cleanup()
+{
+ if (base)
+ proc_unregister(&proc_root,base->low_ino);
+
+ base = NULL;
+
+ return 0;
+}
int parport_proc_register(struct parport *pp)
{
-#if defined(CONFIG_PROC_FS) && defined(NOT_DEFINED)
- return proc_register(&proc_root, &proc_root_parport);
-#else
+ struct proc_dir_entry *ent;
+ static int conta=0;
+ char *name;
+
+ memset(&pp->pdir,0,sizeof(struct parport_dir));
+
+ if (!base) {
+ printk(KERN_ERR "parport: Error entry /proc/parport, not generated?\n");
+ return 1;
+ }
+
+ name = pp->pdir.name;
+ sprintf(name,"%d",conta++);
+
+ ent = new_proc_entry(name, S_IFDIR, base,0);
+ if (!ent) {
+ printk(KERN_ERR "parport: Error registering proc_entry /proc/%s\n",name);
+ return 1;
+ }
+ pp->pdir.entry = ent;
+
+ ent = new_proc_entry("irq", S_IFREG | S_IRUGO | S_IWUSR, pp->pdir.entry,0);
+ if (!ent) {
+ printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/irq\n",name);
+ return 1;
+ }
+ ent->read_proc = irq_read_proc;
+ ent->write_proc= irq_write_proc;
+ ent->data = pp;
+ pp->pdir.irq = ent;
+
+ ent = new_proc_entry("devices", 0, pp->pdir.entry,0);
+ if (!ent) {
+ printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/devices\n",name);
+ return 1;
+ }
+ ent->read_proc = devices_read_proc;
+ ent->data = pp;
+ pp->pdir.devices = ent;
+
+ ent = new_proc_entry("hardware", 0, pp->pdir.entry,0);
+ if (!ent) {
+ printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/hardware\n",name);
+ return 1;
+ }
+ ent->read_proc = hardware_read_proc;
+ ent->data = pp;
+ pp->pdir.hardware = ent;
return 0;
-#endif
}
-void parport_proc_unregister(struct parport *pp)
+int parport_proc_unregister(struct parport *pp)
{
-#if defined(CONFIG_PROC_FS) && defined(NOT_DEFINED)
- if( pp ){
- proc_unregister(&proc_root_parport, pp->proc_dir->low_ino);
- kfree(pp->proc_dir);
- }else{
- proc_unregister(&proc_root, proc_root_parport.low_ino);
+ if (pp->pdir.entry) {
+ if (pp->pdir.irq) {
+ proc_unregister(pp->pdir.entry, pp->pdir.irq->low_ino);
+ kfree(pp->pdir.irq);
+ }
+
+ if (pp->pdir.devices) {
+ proc_unregister(pp->pdir.entry,
+ pp->pdir.devices->low_ino);
+ kfree(pp->pdir.devices);
+ }
+
+ if (pp->pdir.hardware) {
+ proc_unregister(pp->pdir.entry,
+ pp->pdir.hardware->low_ino);
+ kfree(pp->pdir.hardware);
+ }
+
+ proc_unregister(base, pp->pdir.entry->low_ino);
+ kfree(pp->pdir.entry);
}
-#endif
+
+ return 0;
}
-/* $Id: parport_share.c,v 1.1.2.4 1997/04/01 18:19:11 phil Exp $
+/* $Id: parport_share.c,v 1.3.2.5 1997/04/16 21:20:44 phil Exp $
* Parallel-port resource manager code.
*
* Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
#include <linux/kernel.h>
#include <linux/malloc.h>
+#undef PARPORT_PARANOID
+
#include "parport_ll_io.h"
static struct parport *portlist = NULL, *portlist_tail = NULL;
return portlist;
}
-static void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
+void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
{
/* NULL function - Does nothing */
return;
}
memcpy(tmp, &new, sizeof(struct parport));
- if (new.irq != -1) {
+ if (new.irq != PARPORT_IRQ_NONE) {
if (request_irq(new.irq, parport_null_intr_func,
SA_INTERRUPT, new.name, tmp) != 0) {
printk(KERN_INFO "%s: unable to claim IRQ %d\n",
return NULL;
}
}
- if (port->irq != -1) {
- if (request_irq(port->irq,
- parport_null_intr_func,
- SA_INTERRUPT, port->name,
- port) != 0) {
+ if (port->irq != PARPORT_IRQ_NONE) {
+ if (request_irq(port->irq, parport_null_intr_func,
+ SA_INTERRUPT, port->name,
+ port) != 0) {
release_region(port->base, port->size);
if( port->modes & PARPORT_MODE_ECR )
release_region(port->base+0x400, 3);
port->flags &= ~PARPORT_FLAG_COMA;
}
-
tmp = kmalloc(sizeof(struct ppd), GFP_KERNEL);
tmp->name = (char *) name;
tmp->port = port;
port = dev->port;
if (port->cad == dev) {
- printk(KERN_INFO "%s: refused to unregister currently active device %s\n",
- port->name, dev->name);
+ printk(KERN_INFO "%s: refused to unregister currently active device %s\n", port->name, dev->name);
return;
}
if (dev->port->modes & PARPORT_MODE_ECR)
dev->port->cad->ecr = dev->port->ecr =
r_ecr(dev->port);
- dev->port->cad->ctr = dev->port->ctr =
- r_ctr(dev->port);
+ if (dev->port->modes & PARPORT_MODE_SPP)
+ dev->port->cad->ctr = dev->port->ctr =
+ r_ctr(dev->port);
} else
return -EAGAIN;
}
/* Restore control registers */
if (dev->port->modes & PARPORT_MODE_ECR)
if (dev->ecr != dev->port->ecr) w_ecr(dev->port, dev->ecr);
- if (dev->ctr != dev->port->ctr) w_ctr(dev->port, dev->ctr);
+ if (dev->port->modes & PARPORT_MODE_SPP)
+ if (dev->ctr != dev->port->ctr) w_ctr(dev->port, dev->ctr);
return 0;
}
/* Make sure that dev is the current device */
if (dev->port->cad != dev) {
- printk(KERN_WARNING "%s: %s tried to release parport when not owner\n",
- dev->port->name, dev->name);
+ printk(KERN_WARNING "%s: %s tried to release parport when not owner\n", dev->port->name, dev->name);
return;
}
dev->port->cad = NULL;
/* Save control registers */
if (dev->port->modes & PARPORT_MODE_ECR)
dev->ecr = dev->port->ecr = r_ecr(dev->port);
- dev->ctr = dev->port->ctr = r_ctr(dev->port);
+ if (dev->port->modes & PARPORT_MODE_SPP)
+ dev->ctr = dev->port->ctr = r_ctr(dev->port);
if (dev->port->irq >= 0) {
free_irq(dev->port->irq, dev->port);
request_irq(dev->port->irq, parport_null_intr_func,
- SA_INTERRUPT, dev->port->name, dev->port);
+ SA_INTERRUPT, dev->port->name, dev->port);
}
/* Walk the list, offering a wakeup callback to everybody other
if (dev->port->lurker && (dev->port->lurker != dev)) {
if (dev->port->lurker->wakeup) {
dev->port->lurker->wakeup(dev->port->lurker->private);
- return;
+ }
+#ifdef PARPORT_PARANOID
+ else { /* can't happen */
+ printk(KERN_DEBUG
+ "%s (%s): lurker's wakeup callback went away!\n",
+ dev->port->name, dev->name);
}
- printk(KERN_DEBUG
- "%s (%s): lurker's wakeup callback went away!\n",
- dev->port->name, dev->name);
+#endif
}
}
/* The following read funktions are an implementation of a status readback
* and device id request confirming to IEEE1284-1994.
+ *
+ * These probably ought to go in some seperate file, so people like the SPARC
+ * don't have to pull them in.
*/
/* Wait for Status line(s) to change in 35 ms - see IEEE1284-1994 page 24 to
bool 'bwtwo support' SUN_FB_BWTWO
bool 'leo/zx support' SUN_FB_LEO
bool 'weitek P9X00 support' TADPOLE_FB_WEITEK
+ bool 'creator support' SUN_FB_CREATOR
if [ "$TADPOLE_FB_WEITEK" = "n" ]; then
fbs=$SUN_FB_CGSIX
fbs=$fbs$SUN_FB_TCX
define_bool SUN_FB_BWTWO y
define_bool SUN_FB_LEO y
define_bool TADPOLE_FB_WEITEK y
+ define_bool SUN_FB_CREATOR y
fi
comment 'Misc Linux/SPARC drivers'
ifdef TADPOLE_FB_WEITEK
FB_OBJS += weitek.o
endif
+ifdef SUN_FB_CREATOR
+ FB_OBJS += creator.o
+endif
#ifdef SUN_FB_FAST_ONE
# FB_OBJS += sun_8bit_fast1.o
#endif
#endif
#if defined(__sparc__)
+# include <linux/init.h>
# include <linux/delay.h> /* udelay() */
# include <asm/oplib.h> /* OpenProm Library */
-/* $Id: bwtwo.c,v 1.12 1997/04/10 03:02:40 davem Exp $
+/* $Id: bwtwo.c,v 1.13 1997/04/14 17:04:55 jj Exp $
* bwtwo.c: bwtwo console driver
*
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
/* This routine should also map the register if asked for,
* but we don't do that yet.
*/
- map_offset = get_phys ((uint) fb->base);
+ map_offset = get_phys ((unsigned long) fb->base);
r = io_remap_page_range (vma->vm_start, map_offset, map_size,
vma->vm_page_prot, fb->space);
if (r) return -EAGAIN;
0x10, 0x20, 0
};
-__initfunc(void bwtwo_setup (fbinfo_t *fb, int slot, unsigned long bwtwo, int bw2_io,
+__initfunc(void bwtwo_setup (fbinfo_t *fb, int slot, u32 bwtwo, int bw2_io,
struct linux_sbus_device *sbdp))
{
- printk ("bwtwo%d at 0x%8.8x\n", slot, (uint)bwtwo);
+ printk ("bwtwo%d at 0x%8.8x\n", slot, bwtwo);
fb->type.fb_cmsize = 0;
fb->mmap = bwtwo_mmap;
fb->loadcmap = 0;
fb->unblank = bwtwo_unblank;
fb->info.bwtwo.regs =
- sparc_alloc_io ((u32)(bwtwo + BWTWO_REGISTER_OFFSET),
+ sparc_alloc_io (bwtwo + BWTWO_REGISTER_OFFSET,
0, sizeof (struct bwtwo_regs),
"bwtwo_regs", bw2_io, 0);
}
if(!fb->base)
- fb->base = (unsigned long) sparc_alloc_io((u32)bwtwo, 0,
+ fb->base = (unsigned long) sparc_alloc_io(bwtwo, 0,
((fb->type.fb_depth*fb->type.fb_height*fb->type.fb_width)/8),
"bwtwo_fbase", bw2_io, 0);
-/* $Id: cgfourteen.c,v 1.18 1997/03/24 17:44:27 jj Exp $
+/* $Id: cgfourteen.c,v 1.19 1997/04/14 17:04:57 jj Exp $
* cgfourteen.c: Sun SparcStation console support.
*
* Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
printk ("Wee! They are mapping the register, report this to miguel@gnu.ai.mit.edu\n");
printk ("Mapping fb->info.regs!\n");
map_size = 0x7000;
- map_offset = get_phys ((uint) fb->info.cg14.regs);
+ map_offset = get_phys ((unsigned long) fb->info.cg14.regs);
break;
case CG3_MMAP_OFFSET:
map_size = size-page;
- map_offset = get_phys ((uint) fb->base);
+ map_offset = get_phys ((unsigned long) fb->base);
break;
case MDI_PLANAR_X16_MAP:
map_size = ram_size/2;
- map_offset = get_phys ((uint) fb->base) | 0x2000000;
+ map_offset = get_phys ((unsigned long) fb->base) | 0x2000000;
break;
case MDI_PLANAR_C16_MAP:
map_size = ram_size/2;
- map_offset = get_phys ((uint) fb->base) | 0x2800000;
+ map_offset = get_phys ((unsigned long) fb->base) | 0x2800000;
break;
case MDI_CHUNKY_XBGR_MAP:
case MDI_CHUNKY_BGR_MAP:
map_size = ram_size;
- map_offset = get_phys ((uint) fb->base) | 0x1000000;
+ map_offset = get_phys ((unsigned long) fb->base) | 0x1000000;
break;
case MDI_PLANAR_X32_MAP:
map_size = ram_size/4;
- map_offset = get_phys ((uint) fb->base) | 0x3000000;
+ map_offset = get_phys ((unsigned long) fb->base) | 0x3000000;
break;
case MDI_PLANAR_B32_MAP:
map_size = ram_size/4;
- map_offset = get_phys ((uint) fb->base) | 0x3400000;
+ map_offset = get_phys ((unsigned long) fb->base) | 0x3400000;
break;
case MDI_PLANAR_G32_MAP:
map_size = ram_size/4;
- map_offset = get_phys ((uint) fb->base) | 0x3800000;
+ map_offset = get_phys ((unsigned long) fb->base) | 0x3800000;
break;
case MDI_PLANAR_R32_MAP:
map_size = ram_size/4;
- map_offset = get_phys ((uint) fb->base) | 0x3c00000;
+ map_offset = get_phys ((unsigned long) fb->base) | 0x3c00000;
break;
case MDI_CURSOR_MAP:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint) fb->info.cg14.cursor_regs);
+ map_offset = get_phys ((unsigned long) fb->info.cg14.cursor_regs);
break;
case CG14_REGS:
printk ("Wee! They are mapping the register, report this to miguel@gnu.ai.mit.edu\n");
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint) fb->info.cg14.regs);
+ map_offset = get_phys ((unsigned long) fb->info.cg14.regs);
break;
case CG14_XLUT:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint) fb->info.cg14.regs+0x3000);
+ map_offset = get_phys ((unsigned long) fb->info.cg14.regs+0x3000);
break;
case CG14_CLUT1:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint) fb->info.cg14.regs+0x4000);
+ map_offset = get_phys ((unsigned long) fb->info.cg14.regs+0x4000);
break;
case CG14_CLUT2:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint) fb->info.cg14.regs+0x5000);
+ map_offset = get_phys ((unsigned long) fb->info.cg14.regs+0x5000);
break;
default:
*mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK));
}
-__initfunc(void cg14_setup (fbinfo_t *fb, int slot, int con_node, unsigned long cg14, int cg14_io))
+__initfunc(void cg14_setup (fbinfo_t *fb, int slot, int con_node, u32 cg14, int cg14_io))
{
struct cg14_info *cg14info;
uint bases [2];
- uint cg14regs = 0;
+ unsigned long cg14regs = 0;
struct cg14_regs *regs = 0;
if (!cg14) {
/* If the bit is turned on, the card has 8 mb of ram, otherwise just 4 */
cg14info->ramsize = (regs->vca & CG14_VCA_8MB_MASK ? 8 : 4) * 1024 * 1024;
printk ("cgfourteen%d at 0x%8.8x with %d megs of RAM rev=%d, impl=%d\n",
- slot, (uint)cg14, cg14info->ramsize/(1024*1024), regs->rev >> 4, regs->rev & 0xf);
+ slot, cg14, cg14info->ramsize/(1024*1024), regs->rev >> 4, regs->rev & 0xf);
}
-/* $Id: cgsix.c,v 1.26 1997/04/10 03:02:40 davem Exp $
+/* $Id: cgsix.c,v 1.27 1997/04/14 17:04:55 jj Exp $
* cgsix.c: cgsix frame buffer driver
*
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
map_size = PAGE_SIZE;
map_offset = get_phys ((unsigned long)fb->info.cg6.bt);
break;
-
case CG6_DHC:
map_size = PAGE_SIZE * 40;
map_offset = get_phys ((unsigned long)fb->info.cg6.dhc);
break;
-
case CG6_ROM:
map_size = PAGE_SIZE * 16;
map_offset = get_phys ((unsigned long)fb->info.cg6.rom);
break;
-
case CG6_RAM:
map_size = size-page;
map_offset = get_phys ((unsigned long) fb->base);
cg6->bt->control |= 0x03 << 24;
}
-__initfunc(void cg6_setup (fbinfo_t *fb, int slot, unsigned long cg6, int cg6_io))
+__initfunc(void cg6_setup (fbinfo_t *fb, int slot, u32 cg6, int cg6_io))
{
struct cg6_info *cg6info;
unsigned int rev, cpu, conf;
- printk ("cgsix%d at 0x%8.8x ", slot, (uint) cg6);
+ printk ("cgsix%d at 0x%8.8x ", slot, cg6);
/* Fill in parameters we left out */
fb->type.fb_cmsize = 256;
cg6info = (struct cg6_info *) &fb->info.cg6;
/* Map the hardware registers */
- cg6info->bt = sparc_alloc_io ((u32)(cg6+CG6_BROOKTREE_OFFSET), 0,
+ cg6info->bt = sparc_alloc_io (cg6+CG6_BROOKTREE_OFFSET, 0,
sizeof (struct bt_regs), "cgsix_dac", cg6_io, 0);
- cg6info->fhc = sparc_alloc_io ((u32)(cg6+CG6_FHC_OFFSET), 0,
+ cg6info->fhc = sparc_alloc_io (cg6+CG6_FHC_OFFSET, 0,
sizeof (int), "cgsix_fhc", cg6_io, 0);
- cg6info->thc = sparc_alloc_io ((u32)(cg6+CG6_THC_OFFSET), 0,
+ cg6info->thc = sparc_alloc_io (cg6+CG6_THC_OFFSET, 0,
sizeof (struct cg6_thc), "cgsix_thc", cg6_io, 0);
- cg6info->tec = sparc_alloc_io ((u32)(cg6+CG6_TEC_OFFSET), 0,
+ cg6info->tec = sparc_alloc_io (cg6+CG6_TEC_OFFSET, 0,
sizeof (struct cg6_tec), "cgsix_tec", cg6_io, 0);
- cg6info->dhc = sparc_alloc_io ((u32)(cg6+CG6_DHC_OFFSET), 0,
+ cg6info->dhc = sparc_alloc_io (cg6+CG6_DHC_OFFSET, 0,
0x40000, "cgsix_dhc", cg6_io, 0);
- cg6info->fbc = sparc_alloc_io ((u32)(cg6+CG6_FBC_OFFSET), 0,
+ cg6info->fbc = sparc_alloc_io (cg6+CG6_FBC_OFFSET, 0,
0x1000, "cgsix_fbc", cg6_io, 0);
- cg6info->rom = sparc_alloc_io ((u32)(cg6+CG6_ROM_OFFSET), 0,
+ cg6info->rom = sparc_alloc_io (cg6+CG6_ROM_OFFSET, 0,
0x10000, "cgsix_rom", cg6_io, 0);
if (!fb->base) {
fb->base = (unsigned long)
- sparc_alloc_io ((u32)(cg6+CG6_RAM_OFFSET), 0,
+ sparc_alloc_io (cg6+CG6_RAM_OFFSET, 0,
fb->type.fb_size, "cgsix_ram", cg6_io, 0);
}
if (slot == sun_prom_console_id)
-/* $Id: cgthree.c,v 1.16 1997/04/10 03:02:41 davem Exp $
+/* $Id: cgthree.c,v 1.18 1997/04/16 17:51:09 jj Exp $
* cgtree.c: cg3 frame buffer driver
*
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
switch (vma->vm_offset+page){
case CG3_MMAP_OFFSET:
map_size = size-page;
- map_offset = get_phys ((uint) fb->base);
+ map_offset = get_phys ((unsigned long) fb->base);
if (map_size > fb->type.fb_size)
map_size = fb->type.fb_size;
break;
};
-__initfunc(void cg3_setup (fbinfo_t *fb, int slot, unsigned long cg3, int cg3_io,
+__initfunc(void cg3_setup (fbinfo_t *fb, int slot, u32 cg3, int cg3_io,
struct linux_sbus_device *sbdp))
{
struct cg3_info *cg3info = (struct cg3_info *) &fb->info.cg3;
}
}
}
- printk ("cgRDI%d at 0x%8.8x\n", slot, (uint)cg3);
+ printk ("cgRDI%d at 0x%8.8x\n", slot, cg3);
cg3info->cgrdi = 1;
} else {
- printk ("cgthree%d at 0x%8.8x\n", slot, (uint)cg3);
+ printk ("cgthree%d at 0x%8.8x\n", slot, cg3);
cg3info->cgrdi = 0;
}
fb->unblank = cg3_unblank;
/* Map the card registers */
- cg3info->regs = sparc_alloc_io ((u32)(cg3+CG3_REGS), 0,
+ cg3info->regs = sparc_alloc_io (cg3+CG3_REGS, 0,
sizeof (struct cg3_regs),"cg3_regs", cg3_io, 0);
if (!prom_getbool(sbdp->prom_node, "width")) {
}
if (!fb->base){
- fb->base=(uint) sparc_alloc_io ((u32)(cg3+CG3_RAM), 0,
- fb->type.fb_size, "cg3_ram", cg3_io, 0);
+ fb->base=(unsigned long) sparc_alloc_io (cg3+CG3_RAM, 0,
+ fb->type.fb_size, "cg3_ram", cg3_io, 0);
}
}
-/* $Id: fb.h,v 1.24 1997/03/24 17:44:15 jj Exp $
+/* $Id: fb.h,v 1.26 1997/04/17 02:29:33 miguel Exp $
* fb.h: contains the definitions of the structures that various sun
* frame buffer can use to do console driver stuff.
*
extern int ints_per_line;
/* used in the mmap routines */
-extern unsigned int get_phys (unsigned int addr);
-extern int get_iospace (unsigned int addr);
+extern unsigned int get_phys (unsigned long addr);
+extern int get_iospace (unsigned long addr);
extern void render_screen(void);
extern void sun_hw_hide_cursor(void);
#define FB_DEV(x) (MINOR(x) / 32)
-extern void cg3_setup (fbinfo_t *, int, unsigned long, int, struct linux_sbus_device *);
-extern void cg6_setup (fbinfo_t *, int, unsigned long, int);
-extern void cg14_setup (fbinfo_t *, int, int, unsigned long, int);
-extern void bwtwo_setup (fbinfo_t *, int, unsigned long, int,
+extern void cg3_setup (fbinfo_t *, int, u32, int, struct linux_sbus_device *);
+extern void cg6_setup (fbinfo_t *, int, u32, int);
+extern void cg14_setup (fbinfo_t *, int, int, u32, int);
+extern void bwtwo_setup (fbinfo_t *, int, u32, int,
struct linux_sbus_device *);
-extern void leo_setup (fbinfo_t *, int, unsigned long, int);
-extern void tcx_setup (fbinfo_t *, int, int, unsigned long, struct linux_sbus_device *);
+extern void leo_setup (fbinfo_t *, int, u32, int);
+extern void tcx_setup (fbinfo_t *, int, int, u32, struct linux_sbus_device *);
+extern void creator_setup (fbinfo_t *, int, int, unsigned long, int);
+extern int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space);
#endif __SPARC_FB_H_
-/* $Id: leo.c,v 1.14 1997/04/10 17:06:09 jj Exp $
+/* $Id: leo.c,v 1.15 1997/04/14 17:04:54 jj Exp $
* leo.c: SUNW,leo 24/8bit frame buffer driver
*
* Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
switch (vma->vm_offset+page){
case LEO_SS0_MAP:
map_size = 0x800000;
- map_offset = get_phys ((uint)fb->base);
+ map_offset = get_phys ((unsigned long)fb->base);
break;
case LEO_LC_SS0_USR_MAP:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.leo.lc_ss0_usr);
+ map_offset = get_phys ((unsigned long)fb->info.leo.lc_ss0_usr);
break;
case LEO_LD_SS0_MAP:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.leo.ld_ss0);
+ map_offset = get_phys ((unsigned long)fb->info.leo.ld_ss0);
break;
case LEO_LX_CURSOR_MAP:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.leo.cursor);
+ map_offset = get_phys ((unsigned long)fb->info.leo.cursor);
break;
case LEO_SS1_MAP:
map_size = 0x800000;
break;
case LEO_LC_SS1_USR_MAP:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.leo.lc_ss1_usr);
+ map_offset = get_phys ((unsigned long)fb->info.leo.lc_ss1_usr);
break;
case LEO_LD_SS1_MAP:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.leo.ld_ss1);
+ map_offset = get_phys ((unsigned long)fb->info.leo.ld_ss1);
break;
case LEO_UNK_MAP:
map_size = PAGE_SIZE;
break;
case LEO_LX_KRN_MAP:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.leo.lx_krn);
+ map_offset = get_phys ((unsigned long)fb->info.leo.lx_krn);
break;
case LEO_LC_SS0_KRN_MAP:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.leo.lc_ss0_krn);
+ map_offset = get_phys ((unsigned long)fb->info.leo.lc_ss0_krn);
break;
case LEO_LC_SS1_KRN_MAP:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.leo.lc_ss1_krn);
+ map_offset = get_phys ((unsigned long)fb->info.leo.lc_ss1_krn);
break;
case LEO_LD_GBL_MAP:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.leo.ld_gbl);
+ map_offset = get_phys ((unsigned long)fb->info.leo.ld_gbl);
break;
case LEO_UNK2_MAP:
map_size = 0x100000;
return memory_start + (256*4*3) + 256 + 256*3;
}
-__initfunc(void leo_setup (fbinfo_t *fb, int slot, unsigned long leo, int leo_io))
+__initfunc(void leo_setup (fbinfo_t *fb, int slot, u32 leo, int leo_io))
{
struct leo_info *leoinfo;
int i;
struct fb_wid_item wi;
struct fb_wid_list wl;
- printk ("leo%d at 0x%8.8x ", slot, (uint) leo);
+ printk ("leo%d at 0x%8.8x ", slot, leo);
/* Fill in parameters we left out */
fb->type.fb_size = 0x800000; /* 8MB */
leoinfo->offset = leo;
/* Map the hardware registers */
- leoinfo->lc_ss0_krn = sparc_alloc_io((u32)(leo + LEO_OFF_LC_SS0_KRN), 0,
+ leoinfo->lc_ss0_krn = sparc_alloc_io(leo + LEO_OFF_LC_SS0_KRN, 0,
PAGE_SIZE,"leo_lc_ss0_krn", fb->space, 0);
- leoinfo->lc_ss0_usr = sparc_alloc_io((u32)(leo + LEO_OFF_LC_SS0_USR), 0,
+ leoinfo->lc_ss0_usr = sparc_alloc_io(leo + LEO_OFF_LC_SS0_USR, 0,
PAGE_SIZE,"leo_lc_ss0_usr", fb->space, 0);
- leoinfo->lc_ss1_krn = sparc_alloc_io((u32)(leo + LEO_OFF_LC_SS1_KRN), 0,
+ leoinfo->lc_ss1_krn = sparc_alloc_io(leo + LEO_OFF_LC_SS1_KRN, 0,
PAGE_SIZE,"leo_lc_ss1_krn", fb->space, 0);
- leoinfo->lc_ss1_usr = sparc_alloc_io((u32)(leo + LEO_OFF_LC_SS1_USR), 0,
+ leoinfo->lc_ss1_usr = sparc_alloc_io(leo + LEO_OFF_LC_SS1_USR, 0,
PAGE_SIZE,"leo_lc_ss1_usr", fb->space, 0);
- leoinfo->ld_ss0 = sparc_alloc_io((u32)(leo + LEO_OFF_LD_SS0), 0,
+ leoinfo->ld_ss0 = sparc_alloc_io(leo + LEO_OFF_LD_SS0, 0,
PAGE_SIZE,"leo_ld_ss0", fb->space, 0);
- leoinfo->ld_ss1 = sparc_alloc_io((u32)(leo + LEO_OFF_LD_SS1), 0,
+ leoinfo->ld_ss1 = sparc_alloc_io(leo + LEO_OFF_LD_SS1, 0,
PAGE_SIZE,"leo_ld_ss1", fb->space, 0);
- leoinfo->ld_gbl = sparc_alloc_io((u32)(leo + LEO_OFF_LD_GBL), 0,
+ leoinfo->ld_gbl = sparc_alloc_io(leo + LEO_OFF_LD_GBL, 0,
PAGE_SIZE,"leo_ld_gbl", fb->space, 0);
- leoinfo->lx_krn = sparc_alloc_io((u32)(leo + LEO_OFF_LX_KRN), 0,
+ leoinfo->lx_krn = sparc_alloc_io(leo + LEO_OFF_LX_KRN, 0,
PAGE_SIZE,"leo_lx_krn", fb->space, 0);
- leoinfo->cursor = sparc_alloc_io((u32)(leo + LEO_OFF_LX_CURSOR), 0,
+ leoinfo->cursor = sparc_alloc_io(leo + LEO_OFF_LX_CURSOR, 0,
sizeof(struct leo_cursor),"leo_lx_crsr", fb->space, 0);
- fb->base = (long)sparc_alloc_io((u32)(leo + LEO_OFF_SS0), 0,
+ fb->base = (long)sparc_alloc_io(leo + LEO_OFF_SS0, 0,
0x800000,"leo_ss0", fb->space, 0);
leoinfo->ld_ss0->unk = 0xffff;
-/* $Id: suncons.c,v 1.58 1997/04/04 00:50:04 davem Exp $
+/* $Id: suncons.c,v 1.61 1997/04/17 02:29:36 miguel Exp $
*
* suncons.c: Sun SparcStation console support.
*
#define cmapsz 8192
#include "suncons_font.h"
-#include "linux_logo.h"
+#include <asm/linux_logo.h>
fbinfo_t *fbinfo;
int fbinfos;
count = video_num_columns * video_num_lines;
contents = (unsigned short *) video_mem_base;
-
+
for (;count--; contents++)
sun_blitc (*contents, (unsigned long) contents);
}
putconsxy(0, q);
ush = (unsigned short *) video_mem_base + video_num_columns * 2 + 20 + 11 * (linux_num_cpus - 1);
-#ifdef __sparc_v9__
- p = "Linux/UltraSPARC version " UTS_RELEASE;
-#else
- p = "Linux/SPARC version " UTS_RELEASE;
-#endif
+ p = linux_logo_banner;
for (; *p; p++, ush++) {
*ush = (attr << 8) + *p;
sun_blitc (*ush, (unsigned long) ush);
}
unsigned int
-get_phys (unsigned int addr)
+get_phys (unsigned long addr)
{
- switch (sparc_cpu_model){
- case sun4c:
- return sun4c_get_pte (addr) << PAGE_SHIFT;
- case sun4m:
- return ((srmmu_get_pte (addr) & 0xffffff00) << 4);
- case sun4u:
- /* FIXME: */ return 0;
- default:
- panic ("get_phys called for unsupported cpu model\n");
- return 0;
- }
+ return __get_phys(addr);
}
int
-get_iospace (unsigned int addr)
+get_iospace (unsigned long addr)
{
- switch (sparc_cpu_model){
- case sun4c:
- return -1; /* Don't check iospace on sun4c */
- case sun4m:
- return (srmmu_get_pte (addr) >> 28);
- case sun4u:
- /* FIXME: */ return 0;
- default:
- panic ("get_iospace called for unsupported cpu model\n");
- return -1;
- }
+ return __get_iospace(addr);
}
__initfunc(unsigned long sun_cg_postsetup(fbinfo_t *fb, unsigned long start_mem))
static char *known_cards [] __initdata = {
"cgsix", "cgthree", "cgRDI", "cgthree+", "bwtwo", "SUNW,tcx",
- "cgfourteen", "SUNW,leo", 0
+ "cgfourteen", "SUNW,leo", "SUNW,ffb", 0
};
static char *v0_known_cards [] __initdata = {
"cgsix", "cgthree", "cgRDI", "cgthree+", "bwtwo", 0
return n;
}
+__initfunc(static int creator_present (void))
+{
+ int root, n;
+
+ root = prom_getchild (prom_root_node);
+ if ((n = prom_searchsiblings (root, "SUNW,ffb")) == 0)
+ return 0;
+ return n;
+}
+
__initfunc(static void
sparc_framebuffer_setup(int primary, int con_node,
int type, struct linux_sbus_device *sbdp,
case FBTYPE_SUNLEO:
leo_setup (&fbinfo [n], n, base, io);
break;
+#endif
+#ifdef SUN_FB_CREATOR
+ case FBTYPE_CREATOR:
+ creator_setup (&fbinfo [n], n, con_node, base, io);
+ break;
#endif
default:
fbinfo [n].type.fb_type = FBTYPE_NOTYPE;
return;
}
- if (!n) {
- con_type = type;
- con_height = fbinfo [n].type.fb_height;
- con_width = fbinfo [n].type.fb_width;
- con_depth = (type == FBTYPE_SUN2BW) ? 1 : 8;
- for (i = 0; scr_def [i].depth; i++){
- if ((scr_def [i].resx != con_width) ||
- (scr_def [i].resy != con_height))
- continue;
- if (scr_def [i].depth != con_depth)
- continue;
- x_margin = scr_def [i].x_margin;
- y_margin = scr_def [i].y_margin;
- chars_per_line = (con_width * con_depth) / 8;
- skip_bytes = chars_per_line * y_margin + x_margin;
- ints_per_line = chars_per_line / 4;
- ints_per_cursor = 14 * ints_per_line;
- bytes_per_row = CHAR_HEIGHT * chars_per_line;
- ORIG_VIDEO_COLS = con_width / 8 -
- 2 * x_margin / con_depth;
- ORIG_VIDEO_LINES = (con_height - 2 * y_margin) / 16;
- switch (chars_per_line) {
- case 1280:
- if (ORIG_VIDEO_COLS == 144)
- color_fbuf_offset =
- color_fbuf_offset_1280_144;
- break;
- case 1152:
- if (ORIG_VIDEO_COLS == 128)
- color_fbuf_offset =
- color_fbuf_offset_1152_128;
- break;
- case 1024:
- if (ORIG_VIDEO_COLS == 128)
- color_fbuf_offset =
- color_fbuf_offset_1024_128;
- break;
- case 800:
- if (ORIG_VIDEO_COLS == 96)
- color_fbuf_offset =
- color_fbuf_offset_800_96;
- break;
- case 640:
- if (ORIG_VIDEO_COLS == 80)
- color_fbuf_offset =
- color_fbuf_offset_640_80;
- break;
- }
- break;
- }
-
- if (!scr_def [i].depth){
- x_margin = y_margin = 0;
- prom_printf ("console: unknown video resolution %dx%d,"
- " depth %d\n",
- con_width, con_height, con_depth);
- prom_halt ();
- }
- /* P3: I fear this strips 15inch 1024/768 PC-like
- * monitors out. */
- if ((linebytes*8) / con_depth != con_width) {
- prom_printf("console: unusual video, linebytes=%d, "
- "width=%d, height=%d depth=%d\n",
- linebytes, con_width, con_height,
- con_depth);
- prom_halt ();
+ if (n)
+ return;
+
+ /* Code below here is just executed for the first frame buffer */
+ con_type = type;
+ con_height = fbinfo [n].type.fb_height;
+ con_width = fbinfo [n].type.fb_width;
+ con_depth = (type == FBTYPE_SUN2BW) ? 1 : 8;
+ for (i = 0; scr_def [i].depth; i++){
+ if ((scr_def [i].resx != con_width) ||
+ (scr_def [i].resy != con_height))
+ continue;
+ if (scr_def [i].depth != con_depth)
+ continue;
+ x_margin = scr_def [i].x_margin;
+ y_margin = scr_def [i].y_margin;
+ chars_per_line = (con_width * con_depth) / 8;
+ skip_bytes = chars_per_line * y_margin + x_margin;
+ ints_per_line = chars_per_line / 4;
+ ints_per_cursor = 14 * ints_per_line;
+ bytes_per_row = CHAR_HEIGHT * chars_per_line;
+ ORIG_VIDEO_COLS = con_width / 8 -
+ 2 * x_margin / con_depth;
+ ORIG_VIDEO_LINES = (con_height - 2 * y_margin) / 16;
+ switch (chars_per_line) {
+ case 1280:
+ if (ORIG_VIDEO_COLS == 144)
+ color_fbuf_offset =
+ color_fbuf_offset_1280_144;
+ break;
+ case 1152:
+ if (ORIG_VIDEO_COLS == 128)
+ color_fbuf_offset =
+ color_fbuf_offset_1152_128;
+ break;
+ case 1024:
+ if (ORIG_VIDEO_COLS == 128)
+ color_fbuf_offset =
+ color_fbuf_offset_1024_128;
+ break;
+ case 800:
+ if (ORIG_VIDEO_COLS == 96)
+ color_fbuf_offset =
+ color_fbuf_offset_800_96;
+ break;
+ case 640:
+ if (ORIG_VIDEO_COLS == 80)
+ color_fbuf_offset =
+ color_fbuf_offset_640_80;
+ break;
}
+ break;
+ }
+
+ if (!scr_def [i].depth){
+ x_margin = y_margin = 0;
+ prom_printf ("console: unknown video resolution %dx%d,"
+ " depth %d\n",
+ con_width, con_height, con_depth);
+ prom_halt ();
+ }
+
+ /* P3: I fear this strips 15inch 1024/768 PC-like
+ * monitors out. */
+ if ((linebytes*8) / con_depth != con_width) {
+ prom_printf("console: unusual video, linebytes=%d, "
+ "width=%d, height=%d depth=%d\n",
+ linebytes, con_width, con_height,
+ con_depth);
+ prom_halt ();
}
}
char prop[16];
struct linux_sbus_device *sbdp, *sbdprom;
struct linux_sbus *sbus;
- int cg14 = 0;
+ int creator = 0, cg14 = 0;
char prom_name[40];
- int type;
+ int type, card_found = 0;
unsigned long con_base;
u32 tmp;
u32 prom_console_node = 0;
break;
}
}
- if (!sbdprom) /* I'm just wondering if this if shouldn't be deleted.
- Is /obio/cgfourteen present only if /sbus/cgfourteen
- is not? If so, then the test here should be deleted.
- Otherwise, this comment should be deleted. */
- cg14 = cg14_present ();
- if (!sbdprom && !cg14) {
+ if (sbdprom)
+ card_found = 1;
+ if (!card_found)
+ card_found = cg14 = cg14_present ();
+ if (!card_found){
+ prom_printf ("Searching for a creator\n");
+ card_found = creator = creator_present ();
+ }
+ if (!card_found){
prom_printf ("Could not find a known video card on this machine\n");
prom_halt ();
}
for_all_sbusdev(sbdp, sbus) {
- if (!known_card (sbdp->prom_name, known_cards)) continue;
+ if (!known_card (sbdp->prom_name, known_cards))
+ continue;
con_node = sbdp->prom_node;
prom_apply_sbus_ranges (sbdp->my_bus, &sbdp->reg_addrs [0],
sbdp->num_registers, sbdp);
0, 0, 0, prom_console_node == cg14,
prom_searchsiblings (prom_getchild (prom_root_node), "obio"));
}
+ if (creator){
+ sparc_framebuffer_setup (!sbdprom, creator, FBTYPE_CREATOR,
+ 0, 0, 0, prom_console_node == creator,
+ prom_getchild (prom_root_node));
+ }
break;
default:
return -1;
-/* $Id: sunserial.c,v 1.37 1997/04/12 23:33:14 ecd Exp $
+/* $Id: sunserial.c,v 1.38 1997/04/14 17:05:00 jj Exp $
* serial.c: Serial port driver for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
static void show_serial_version(void)
{
- char *revision = "$Revision: 1.37 $";
+ char *revision = "$Revision: 1.38 $";
char *version, *p;
version = strchr(revision, ' ');
if(!vaddr[0])
panic("get_zs whee no serial chip mappable");
- return (struct sun_zslayout *) vaddr[0];
+ return (struct sun_zslayout *)(unsigned long) vaddr[0];
}
static inline void
for (info = zs_chain, i=0; info; info = info->zs_next, i++) {
info->magic = SERIAL_MAGIC;
- info->port = (int) info->zs_channel;
+ info->port = (long) info->zs_channel;
info->line = i;
info->tty = 0;
info->irq = zilog_irq;
-/* $Id: tcx.c,v 1.11 1997/04/10 03:02:43 davem Exp $
+/* $Id: tcx.c,v 1.12 1997/04/14 17:04:51 jj Exp $
* tcx.c: SUNW,tcx 24/8bit frame buffer driver
*
* Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
switch (vma->vm_offset+page){
case TCX_RAM8BIT:
map_size = fb->type.fb_size;
- map_offset = get_phys ((uint) fb->base);
+ map_offset = get_phys ((unsigned long) fb->base);
break;
case TCX_TEC:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.tcx.tec);
+ map_offset = get_phys ((unsigned long)fb->info.tcx.tec);
break;
case TCX_BTREGS:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.tcx.bt);
+ map_offset = get_phys ((unsigned long)fb->info.tcx.bt);
break;
case TCX_THC:
map_size = PAGE_SIZE;
- map_offset = get_phys ((uint)fb->info.tcx.thc);
+ map_offset = get_phys ((unsigned long)fb->info.tcx.thc);
break;
case TCX_CONTROLPLANE:
if (fb->info.tcx.tcx_cplane) {
map_size = fb->info.tcx.tcx_sizes [TCX_CONTROLPLANE_OFFSET];
- map_offset = get_phys ((uint)fb->info.tcx.tcx_cplane);
+ map_offset = get_phys ((unsigned long)fb->info.tcx.tcx_cplane);
} else
map_size = 0;
break;
tcx->bt->control |= 0x03 << 24;
}
-__initfunc(void tcx_setup (fbinfo_t *fb, int slot, int node, unsigned long tcx, struct linux_sbus_device *sbdp))
+__initfunc(void tcx_setup (fbinfo_t *fb, int slot, int node, u32 tcx, struct linux_sbus_device *sbdp))
{
struct tcx_info *tcxinfo;
int i;
- printk ("tcx%d at 0x%8.8x ", slot, (uint) tcx);
+ printk ("tcx%d at 0x%8.8x ", slot, tcx);
/* Fill in parameters we left out */
fb->type.fb_cmsize = 256;
-/* $Id: weitek.c,v 1.8 1997/03/24 17:44:26 jj Exp $
+/* $Id: weitek.c,v 1.9 1997/04/14 17:04:57 jj Exp $
* weitek.c: Tadpole P9100/P9000 console driver
*
* Copyright (C) 1996 David Redman (djhr@tadpole.co.uk)
switch (vma->vm_offset+page){
case WEITEK_VRAM_OFFSET:
map_size = size-page;
- map_offset = get_phys ((uint) fb->base);
+ map_offset = get_phys ((unsigned long) fb->base);
if (map_size > fb->type.fb_size)
map_size = fb->type.fb_size;
break;
case WEITEK_GX_REG_OFFSET:
map_size = size-page;
- map_offset = get_phys ((uint) fb->base);
+ map_offset = get_phys ((unsigned long) fb->base);
if (map_size > fb->type.fb_size)
map_size = fb->type.fb_size;
break;
}
#endif
-__initfunc(void weitek_setup(fbinfo_t *fb, int slot, unsigned long addr, int io))
+__initfunc(void weitek_setup(fbinfo_t *fb, int slot, u32 addr, int io))
{
extern struct screen_info screen_info;
- printk ("weitek%d at 0x%8.8x\n", slot, (uint)addr);
+ printk ("weitek%d at 0x%8.8x\n", slot, addr);
/* Fill in parameters we left out */
fb->type.fb_type = FBTYPE_NOTSUN1;
sbus_dev->slot = sbus_dev->reg_addrs[0].which_io;
sbus_dev->offset = base;
sbus_dev->reg_addrs[0].phys_addr =
- (char *) sbus_devaddr(sbus_dev->slot, base);
+ sbus_devaddr(sbus_dev->slot, base);
for(grrr=1; grrr<sbus_dev->num_registers; grrr++) {
base = (unsigned long) sbus_dev->reg_addrs[grrr].phys_addr;
- sbus_dev->reg_addrs[grrr].phys_addr = (char *)
+ sbus_dev->reg_addrs[grrr].phys_addr =
sbus_devaddr(sbus_dev->slot, base);
}
/* That surely sucked */
#include <asm/pgtable.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
#include <asm/irq.h>
#include "scsi.h"
address = cd->cd_BoardAddr;
instance = scsi_register (tpnt, sizeof (struct WD33C93_hostdata));
instance->base = (unsigned char *)ZTWO_VADDR(address);
- instance->irq = IRQ_AMIGA_PORTS & ~IRQ_MACHSPEC;
+ instance->irq = IRQ_AMIGA_PORTS;
instance->unique_id = key;
DMA(instance)->DAWR = DAWR_A2091;
wd33c93_init(instance, (wd33c93_regs *)&(DMA(instance)->SASR),
a3000_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata));
a3000_host->base = (unsigned char *)ZTWO_VADDR(0xDD0000);
- a3000_host->irq = IRQ_AMIGA_PORTS & ~IRQ_MACHSPEC;
+ a3000_host->irq = IRQ_AMIGA_PORTS;
DMA(a3000_host)->DAWR = DAWR_A3000;
wd33c93_init(a3000_host, (wd33c93_regs *)&(DMA(a3000_host)->SASR),
dma_setup, dma_stop, WD33C93_FS_12_15);
pos += sprintf(pos, fmt , ## args); } while(0)
static
char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
-static
-char *lprint_command (unsigned char *cmd, char *pos, char *buffer, int len);
-static
-char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
#ifndef NCR5380_proc_info
static
struct NCR5380_hostdata *hostdata;
Scsi_Cmnd *ptr;
unsigned long flags;
+ off_t begin = 0;
+#define check_offset() \
+ do { \
+ if (pos - buffer < offset - begin) { \
+ begin += pos - buffer; \
+ pos = buffer; \
+ } \
+ } while (0)
for (instance = first_instance; instance && HOSTNO != hostno;
instance = instance->next)
return(-ENOSYS); /* Currently this is a no-op */
}
SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
+ check_offset();
save_flags(flags);
cli();
SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't");
+ check_offset();
if (!hostdata->connected)
SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
else
pos = lprint_Scsi_Cmnd ((Scsi_Cmnd *) hostdata->connected,
pos, buffer, length);
SPRINTF("scsi%d: issue_queue\n", HOSTNO);
- for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+ check_offset();
+ for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
+ check_offset();
+ }
SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
+ check_offset();
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
- ptr = NEXT(ptr))
+ ptr = NEXT(ptr)) {
pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
+ check_offset();
+ }
restore_flags(flags);
- *start = buffer;
- if (pos - buffer < offset)
+ *start = buffer + (offset - begin);
+ if (pos - buffer < offset - begin)
return 0;
- else if (pos - buffer - offset < length)
- return pos - buffer - offset;
+ else if (pos - buffer - (offset - begin) < length)
+ return pos - buffer - (offset - begin);
return length;
}
static char *
lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
{
+ int i, s;
+ unsigned char *command;
SPRINTF("scsi%d: destination target %d, lun %d\n",
H_NO(cmd), cmd->target, cmd->lun);
SPRINTF(" command = ");
- pos = lprint_command (cmd->cmnd, pos, buffer, length);
- return (pos);
-}
-
-static char *
-lprint_command (unsigned char *command, char *pos, char *buffer, int length)
-{
- int i, s;
- pos = lprint_opcode(command[0], pos, buffer, length);
+ command = cmd->cmnd;
+ SPRINTF("%2d (0x%02x)", command[0], command[0]);
for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
- SPRINTF("%02x ", command[i]);
+ SPRINTF(" %02x", command[i]);
SPRINTF("\n");
- return(pos);
-}
-
-static
-char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
-{
- SPRINTF("%2d (0x%02x)", opcode, opcode);
- return(pos);
+ return pos;
}
static int atari_read_overruns = 0;
#endif
-int setup_can_queue = -1;
-int setup_cmd_per_lun = -1;
-int setup_sg_tablesize = -1;
+static int setup_can_queue = -1;
+MODULE_PARM(setup_can_queue, "i");
+static int setup_cmd_per_lun = -1;
+MODULE_PARM(setup_cmd_per_lun, "i");
+static int setup_sg_tablesize = -1;
+MODULE_PARM(setup_sg_tablesize, "i");
#ifdef SUPPORT_TAGS
-int setup_use_tagged_queuing = -1;
+static int setup_use_tagged_queuing = -1;
+MODULE_PARM(setup_use_tagged_queuing, "i");
#endif
-int setup_hostid = -1;
+static int setup_hostid = -1;
+MODULE_PARM(setup_hostid, "i");
#if defined(REAL_DMA)
if (setup_use_tagged_queuing < 0)
setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
#endif
-
+#ifdef REAL_DMA
/* If running on a Falcon and if there's TT-Ram (i.e., more than one
* memory block, since there's always ST-Ram in a Falcon), then allocate a
* STRAM_BUFFER_SIZE byte dribble buffer for transfers from/to alternative
atari_dma_phys_buffer = VTOP( atari_dma_buffer );
atari_dma_orig_addr = 0;
}
-
+#endif
instance = scsi_register (host, sizeof (struct NCR5380_hostdata));
atari_scsi_host = instance;
- instance->irq = IS_A_TT() ? IRQ_TT_MFP_SCSI : IRQ_MFP_FSCSI;
+ /* Set irq to 0, to avoid that the mid-level code disables our interrupt
+ * during queue_command calls. This is completely unnecessary, and even
+ * worse causes bad problems on the Falcon, where the int is shared with
+ * IDE and floppy! */
+ instance->irq = 0;
atari_scsi_reset_boot();
NCR5380_init (instance, 0);
tt_scsi_dma.dma_ctrl = 0;
atari_dma_residual = 0;
#endif /* REAL_DMA */
-
- if (is_medusa) {
+#ifdef REAL_DMA
+ if (is_medusa || is_hades) {
/* While the read overruns (described by Drew Eckhardt in
* NCR5380.c) never happened on TTs, they do in fact on the Medusa
* (This was the cause why SCSI didn't work right for so long
*/
atari_read_overruns = 4;
}
+#endif
}
else { /* ! IS_A_TT */
#include <linux/blk.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/init.h>
#include "scsi.h"
#include "hosts.h"
/* Detecting ESP chips on the machine. This is the simple and easy
* version.
*/
-int esp_detect(Scsi_Host_Template *tpnt)
+__initfunc(int esp_detect(Scsi_Host_Template *tpnt))
{
struct Sparc_ESP *esp, *elink;
struct Scsi_Host *esp_host;
#include <asm/pgtable.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
#include <asm/irq.h>
#include "scsi.h"
struct Scsi_Host *instance;
caddr_t address;
enum GVP_ident epc;
- int key;
+ int key = 0;
struct ConfigDev *cd;
if (!MACH_IS_AMIGA || called)
tpnt->proc_dir = &proc_scsi_gvp11;
tpnt->proc_info = &wd33c93_proc_info;
- while ((key = zorro_find(MANUF_GVP, PROD_GVPIISCSI, 0, 0))) {
+ while ((key = zorro_find(MANUF_GVP, PROD_GVPIISCSI, 0, key))) {
cd = zorro_get_board(key);
address = cd->cd_BoardAddr;
+
+ /*
+ * Rumors state that some GVP ram boards use the same product
+ * code as the SCSI controllers. Therefore if the board-size
+ * is not 64KB we asume it is a ram board and bail out.
+ */
+ if (cd->cd_BoardSize != 0x10000)
+ continue;
+
/* check extended product code */
epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
epc = epc & GVP_PRODMASK;
instance = scsi_register (tpnt, sizeof (struct WD33C93_hostdata));
instance->base = (unsigned char *)ZTWO_VADDR(address);
- instance->irq = IRQ_AMIGA_PORTS & ~IRQ_MACHSPEC;
+ instance->irq = IRQ_AMIGA_PORTS;
instance->unique_id = key;
if (gvp11_xfer_mask)
int gvp11_release(struct Scsi_Host *instance)
{
#ifdef MODULE
-DMA(instance)->CNTR = 0;
-zorro_unconfig_board(instance->unique_id, 0);
-if (--num_gvp11 == 0)
- free_irq(IRQ_AMIGA_PORTS, gvp11_intr);
- wd33c93_release();
+ DMA(instance)->CNTR = 0;
+ zorro_unconfig_board(instance->unique_id, 0);
+ if (--num_gvp11 == 0)
+ free_irq(IRQ_AMIGA_PORTS, gvp11_intr);
+ wd33c93_release();
#endif
-return 1;
+ return 1;
}
*/
/*
-** 6 April 1997, version 1.18d
+** 16 April 1997, version 1.18e
**
** Supported SCSI-II features:
** Synchronous negotiation
**
**==========================================================
*/
-int ncr_reset_bus (Scsi_Cmnd *cmd)
+int ncr_reset_bus (Scsi_Cmnd *cmd, int sync_reset)
{
struct Scsi_Host *host = cmd->host;
/* Scsi_Device *device = cmd->device; */
*/
ncr_wakeup(np, HS_RESET);
/*
- * If the involved command was not in a driver queue, and is
- * not in the waiting list, complete it with DID_RESET status,
+ * If the involved command was not in a driver queue, and the
+ * scsi driver told us reset is synchronous, and the command is not
+ * currently in the waiting list, complete it with DID_RESET status,
* in order to keep it alive.
*/
- if (!found && cmd && !remove_from_waiting_list(np, cmd)) {
+ if (!found && sync_reset && !retrieve_from_waiting_list(0, np, cmd)) {
cmd->result = ScsiResult(DID_RESET, 0);
cmd->scsi_done(cmd);
}
((INL(nc_dbc) & 0xf8000000) == SCR_WAIT_DISC)) {
/*
** Unexpected data cycle while waiting for disconnect.
+ ** LDSC and CON bits may help in order to understand
+ ** what really happened. Print some info message and let
+ ** the reset function reset the BUS and the NCR.
*/
- if (INB(nc_sstat2) & LDSC) {
- /*
- ** It's an early reconnect.
- ** Let's continue ...
- */
- OUTONB (nc_dcntl, (STD|NOCOM));
- /*
- ** info message
- */
- printf ("%s: INFO: LDSC while IID.\n",
- ncr_name (np));
- return;
- };
- printf ("%s: target %d doesn't release the bus.\n",
- ncr_name (np), (int)INB (nc_ctest0)&0x0f);
- /*
- ** return without restarting the NCR.
- ** timeout will do the real work.
- */
- return;
+ printf("%s:%d: data cycle while waiting for disconnect, LDSC=%d CON=%d\n",
+ ncr_name (np), (int)(INB(nc_ctest0)&0x0f),
+ (0!=(INB(nc_sstat2)&LDSC)), (0!=(INB(nc_scntl1)&ISCON)));
};
/*----------------------------------------
/*==========================================================
**
**
-** Aquire a control block
+** Acquire a control block
**
**
**==========================================================
** Linux entry point of reset() function
*/
-#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,98)
+#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
+
int ncr53c8xx_reset(Scsi_Cmnd *cmd, unsigned int reset_flags)
+{
+ int sts;
+ unsigned long flags;
+
+ printk("ncr53c8xx_reset: pid=%lu reset_flags=%x serial_number=%ld serial_number_at_timeout=%ld\n",
+ cmd->pid, reset_flags, cmd->serial_number, cmd->serial_number_at_timeout);
+
+ save_flags(flags); cli();
+
+ /*
+ * We have to just ignore reset requests in some situations.
+ */
+#if defined SCSI_RESET_NOT_RUNNING
+ if (cmd->serial_number != cmd->serial_number_at_timeout) {
+ sts = SCSI_RESET_NOT_RUNNING;
+ goto out;
+ }
+#endif
+ /*
+ * If the mid-level driver told us reset is synchronous, it seems
+ * that we must call the done() callback for the involved command,
+ * even if this command was not queued to the low-level driver,
+ * before returning SCSI_RESET_SUCCESS.
+ */
+
+ sts = ncr_reset_bus(cmd,
+ (reset_flags & (SCSI_RESET_SYNCHRONOUS | SCSI_RESET_ASYNCHRONOUS)) == SCSI_RESET_SYNCHRONOUS);
+ /*
+ * Since we always reset the controller, when we return success,
+ * we add this information to the return code.
+ */
+#if defined SCSI_RESET_HOST_RESET
+ if (sts == SCSI_RESET_SUCCESS)
+ sts |= SCSI_RESET_HOST_RESET;
+#endif
+
+out:
+ restore_flags(flags);
+ return sts;
+}
#else
int ncr53c8xx_reset(Scsi_Cmnd *cmd)
-#endif
{
printk("ncr53c8xx_reset: command pid %lu\n", cmd->pid);
- return ncr_reset_bus(cmd);
+ return ncr_reset_bus(cmd, 1);
}
+#endif
/*
** Linux entry point of abort() function
*/
+#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
+
+int ncr53c8xx_abort(Scsi_Cmnd *cmd)
+{
+ int sts;
+ unsigned long flags;
+
+ printk("ncr53c8xx_abort: pid=%lu serial_number=%ld serial_number_at_timeout=%ld\n",
+ cmd->pid, cmd->serial_number, cmd->serial_number_at_timeout);
+
+ save_flags(flags); cli();
+
+ /*
+ * We have to just ignore abort requests in some situations.
+ */
+ if (cmd->serial_number != cmd->serial_number_at_timeout) {
+ sts = SCSI_ABORT_NOT_RUNNING;
+ goto out;
+ }
+
+ sts = ncr_abort_command(cmd);
+out:
+ restore_flags(flags);
+ return sts;
+}
+#else
int ncr53c8xx_abort(Scsi_Cmnd *cmd)
{
printk("ncr53c8xx_abort: command pid %lu\n", cmd->pid);
return ncr_abort_command(cmd);
}
+#endif
#ifdef MODULE
int ncr53c8xx_release(struct Scsi_Host *host)
/*
** Name and revision of the driver
*/
-#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 1.18d"
+#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 1.18e"
/*
** If SCSI_NCR_SETUP_SPECIAL_FEATURES is defined,
nhosts = 0;
for (i = 0; pb; i++, pb=pb->next) {
- int modes;
-
- /* transfer global values here */
- if (ppa_speed >= 0)
- ppa_hosts[i].speed = ppa_speed;
- if (ppa_speed_fast >= 0)
- ppa_hosts[i].speed_fast = ppa_speed_fast;
-
- ppa_hosts[i].dev =
- parport_register_device(pb, "ppa", NULL, ppa_wakeup,
- NULL, PARPORT_DEV_TRAN, (void *) &ppa_hosts[i]);
-
- /* Claim the bus so it remembers what we do to the control
- * registers. [ CTR and ECP ]
- */
- ppa_pb_claim(i);
- w_ctr(i, 0x0c);
- modes = ppa_hosts[i].dev->port->modes;
-
- ppa_hosts[i].mode = PPA_NIBBLE;
- if (modes & (PARPORT_MODE_EPP | PARPORT_MODE_ECPEPP)) {
- ppa_hosts[i].mode = PPA_EPP_32;
- printk("PPA: Parport [ EPP ]\n");
- } else if (modes & PARPORT_MODE_ECP) {
- w_ecr(i, 0x20);
- ppa_hosts[i].mode = PPA_PS2;
- printk("PPA: Parport [ ECP in PS2 submode ]\n");
- } else if (modes & PARPORT_MODE_PS2) {
- ppa_hosts[i].mode = PPA_PS2;
- printk("PPA: Parport [ PS2 ]\n");
- }
- /* Done configuration */
- ppa_pb_release(i);
+ int modes = pb->modes;
+
+ /* We only understand PC-style ports */
+ if (modes & PARPORT_MODE_SPP) {
+
+ /* transfer global values here */
+ if (ppa_speed >= 0)
+ ppa_hosts[i].speed = ppa_speed;
+ if (ppa_speed_fast >= 0)
+ ppa_hosts[i].speed_fast = ppa_speed_fast;
+
+ ppa_hosts[i].dev = parport_register_device(pb, "ppa",
+ NULL, ppa_wakeup, NULL,
+ PARPORT_DEV_TRAN, (void *) &ppa_hosts[i]);
+
+ /* Claim the bus so it remembers what we do to the
+ * control registers. [ CTR and ECP ]
+ */
+ ppa_pb_claim(i);
+ w_ctr(i, 0x0c);
+
+ ppa_hosts[i].mode = PPA_NIBBLE;
+ if (modes & (PARPORT_MODE_EPP | PARPORT_MODE_ECPEPP)) {
+ ppa_hosts[i].mode = PPA_EPP_32;
+ printk("PPA: Parport [ EPP ]\n");
+ } else if (modes & PARPORT_MODE_ECP) {
+ w_ecr(i, 0x20);
+ ppa_hosts[i].mode = PPA_PS2;
+ printk("PPA: Parport [ ECP in PS2 submode ]\n");
+ } else if (modes & PARPORT_MODE_PS2) {
+ ppa_hosts[i].mode = PPA_PS2;
+ printk("PPA: Parport [ PS2 ]\n");
+ }
+ /* Done configuration */
+ ppa_pb_release(i);
- rs = ppa_init(i);
- if (rs) {
- parport_unregister_device(ppa_hosts[i].dev);
- continue;
- }
- /* now the glue ... */
- switch (ppa_hosts[i].mode) {
- case PPA_NIBBLE:
- case PPA_PS2:
- ports = 3;
- break;
- case PPA_EPP_8:
- case PPA_EPP_16:
- case PPA_EPP_32:
- ports = 8;
- break;
- default: /* Never gets here */
- continue;
+ rs = ppa_init(i);
+ if (rs) {
+ parport_unregister_device(ppa_hosts[i].dev);
+ continue;
+ }
+ /* now the glue ... */
+ switch (ppa_hosts[i].mode) {
+ case PPA_NIBBLE:
+ case PPA_PS2:
+ ports = 3;
+ break;
+ case PPA_EPP_8:
+ case PPA_EPP_16:
+ case PPA_EPP_32:
+ ports = 8;
+ break;
+ default: /* Never gets here */
+ continue;
+ }
+
+ host->can_queue = PPA_CAN_QUEUE;
+ host->sg_tablesize = ppa_sg;
+ hreg = scsi_register(host, 0);
+ hreg->io_port = pb->base;
+ hreg->n_io_port = ports;
+ hreg->dma_channel = -1;
+ hreg->unique_id = i;
+ ppa_hosts[i].host = hreg->host_no;
+ nhosts++;
}
-
- host->can_queue = PPA_CAN_QUEUE;
- host->sg_tablesize = ppa_sg;
- hreg = scsi_register(host, 0);
- hreg->io_port = pb->base;
- hreg->n_io_port = ports;
- hreg->dma_channel = -1;
- hreg->unique_id = i;
- ppa_hosts[i].host = hreg->host_no;
- nhosts++;
}
if (nhosts == 0)
return 0;
#include <linux/blk.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/init.h>
#include <asm/byteorder.h>
#define PTI_RESET_LIMIT 400
-static int qlogicpti_load_firmware(struct qlogicpti *qpti)
+__initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
{
struct qlogicpti_regs *qregs = qpti->qregs;
unsigned short csum = 0;
static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs);
/* Detect all PTI Qlogic ISP's in the machine. */
-int qlogicpti_detect(Scsi_Host_Template *tpnt)
+__initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
{
struct qlogicpti *qpti, *qlink;
struct Scsi_Host *qpti_host;
unsigned short risc_code_addr01 = 0x1000;
-unsigned short risc_code01[] = {
+unsigned short risc_code01[] __initdata = {
0x0078, 0x1030, 0x0000, 0x231f, 0x0000, 0x12ff, 0x2043, 0x4f50,
0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932,
0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749,
*
* - Target Disconnection/Reconnection is now supported. Any
* system with more than one device active on the SCSI bus
- * will benefit from this. The driver defaults to what I'm
- * 'adaptive disconnect' - meaning that each command is
- * evaluated individually as to whether or not it should
+ * will benefit from this. The driver defaults to what I
+ * call 'adaptive disconnect' - meaning that each command
+ * is evaluated individually as to whether or not it should
* be run with the option to disconnect/reselect (if the
* device chooses), or as a "SCSI-bus-hog".
*
#include "hosts.h"
-#define PROC_INTERFACE /* add code for /proc/scsi/wd33c93/xxx interface */
-#ifdef PROC_INTERFACE
-#define PROC_STATISTICS /* add code for keeping various real time stats */
-#endif
-
-#define SYNC_DEBUG /* extra info on sync negotiation printed */
-#undef DEBUGGING_ON /* enable command-line debugging bitmask */
-#define DEBUG_DEFAULTS 0 /* default debugging bitmask */
-
-#define WD33C93_VERSION "1.23"
-#define WD33C93_DATE "04/Nov/1996"
+#define WD33C93_VERSION "1.24"
+#define WD33C93_DATE "29/Jan/1997"
-#ifdef DEBUGGING_ON
-#define DB(f,a) if (hostdata->args & (f)) a;
-#else
-#define DB(f,a)
-#endif
+/*
+ * Note - the following defines have been moved to 'wd33c93.h':
+ *
+ * PROC_INTERFACE
+ * PROC_STATISTICS
+ * SYNC_DEBUG
+ * DEBUGGING_ON
+ * DEBUG_DEFAULTS
+ *
+ */
#include "wd33c93.h"
* keywords (lower case required) and arguments:
*
* - nosync:bitmask -bitmask is a byte where the 1st 7 bits correspond with
- * the 7 possible SCSI devices. Set a bit to prevent sync
- * negotiation on that device. To maintain backwards
- * compatibility, a command-line such as "wd33c93=255" will
- * be automatically translated to "wd33c93=nosync:0xff".
+ * the 7 possible SCSI devices. Set a bit to negotiate for
+ * asynchronous transfers on that device. To maintain
+ * backwards compatibility, a command-line such as
+ * "wd33c93=255" will be automatically translated to
+ * "wd33c93=nosync:0xff".
* - nodma:x -x = 1 to disable DMA, x = 0 to enable it. Argument is
* optional - if not present, same as "nodma:1".
* - period:ns -ns is the minimum # of nanoseconds in a SCSI data transfer
-inline uchar read_wd33c93(wd33c93_regs *regp,uchar reg_num)
+static inline uchar read_wd33c93(wd33c93_regs *regp,uchar reg_num)
{
regp->SASR = reg_num;
return(regp->SCMD);
#define READ_AUX_STAT() (regp->SASR)
-inline void write_wd33c93(wd33c93_regs *regp,uchar reg_num, uchar value)
+static inline void write_wd33c93(wd33c93_regs *regp,uchar reg_num, uchar value)
{
regp->SASR = reg_num;
regp->SCMD = value;
}
-inline void write_wd33c93_cmd(wd33c93_regs *regp, uchar cmd)
+static inline void write_wd33c93_cmd(wd33c93_regs *regp, uchar cmd)
{
regp->SASR = WD_COMMAND;
regp->SCMD = cmd;
}
-inline uchar read_1_byte(wd33c93_regs *regp)
+static inline uchar read_1_byte(wd33c93_regs *regp)
{
uchar asr;
uchar x = 0;
}
-void write_wd33c93_count(wd33c93_regs *regp,unsigned long value)
+static void write_wd33c93_count(wd33c93_regs *regp,unsigned long value)
{
regp->SASR = WD_TRANSFER_COUNT_MSB;
regp->SCMD = value >> 16;
}
-unsigned long read_wd33c93_count(wd33c93_regs *regp)
+static unsigned long read_wd33c93_count(wd33c93_regs *regp)
{
unsigned long value;
{1000,0x00},
{0, 0} };
-int round_period(unsigned int period)
+static int round_period(unsigned int period)
{
int x;
return 7;
}
-uchar calc_sync_xfer(unsigned int period, unsigned int offset)
+static uchar calc_sync_xfer(unsigned int period, unsigned int offset)
{
uchar result;
-void wd33c93_execute(struct Scsi_Host *instance);
+static void wd33c93_execute(struct Scsi_Host *instance);
int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
{
-struct WD33C93_hostdata *hostdata;
-Scsi_Cmnd *tmp;
-
- disable_irq(cmd->host->irq);
+ struct WD33C93_hostdata *hostdata;
+ Scsi_Cmnd *tmp;
+ unsigned long flags;
hostdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
* sense data is not lost before REQUEST_SENSE executes.
*/
+ save_flags(flags);
+ cli();
+
if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
cmd->host_scribble = (uchar *)hostdata->input_Q;
hostdata->input_Q = cmd;
DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
- enable_irq(cmd->host->irq);
+ restore_flags(flags);
return 0;
}
* already connected, we give up immediately. Otherwise, look through
* the input_Q, using the first command we find that's intended
* for a currently non-busy target/lun.
+ *
+ * wd33c93_execute() is always called with interrupts disabled or from
+ * the wd33c93_intr itself, which means that a wd33c93 interrupt
+ * cannot occur while we are in here.
*/
-void wd33c93_execute (struct Scsi_Host *instance)
+static void wd33c93_execute (struct Scsi_Host *instance)
{
struct WD33C93_hostdata *hostdata;
wd33c93_regs *regp;
Scsi_Cmnd *cmd, *prev;
int i;
- disable_irq(instance->irq);
hostdata = (struct WD33C93_hostdata *)instance->hostdata;
regp = hostdata->regp;
DB(DB_EXECUTE,printk(")EX-0 "))
- enable_irq(instance->irq);
return;
}
DB(DB_EXECUTE,printk(")EX-1 "))
- enable_irq(instance->irq);
return;
}
#endif
no:
+
write_wd33c93(regp, WD_SOURCE_ID, ((cmd->SCp.phase)?SRCID_ER:0));
write_wd33c93(regp, WD_TARGET_LUN, cmd->lun);
* sync_xfer[] entry is initialized to the default/safe value. SS_UNSET
* means that the parameters are undetermined as yet, and that we
* need to send an SDTR message to this device after selection is
- * complete. We set SS_FIRST to tell the interrupt routine to do so,
- * unless we've been asked not to try synchronous transfers on this
- * target (and _all_ luns within it): In this case we set SS_SET to
- * make the defaults final.
+ * complete: We set SS_FIRST to tell the interrupt routine to do so.
+ * If we've been asked not to try synchronous transfers on this
+ * target (and _all_ luns within it), we'll still send the SDTR message
+ * later, but at that time we'll negotiate for async by specifying a
+ * sync fifo depth of 0.
*/
- if (hostdata->sync_stat[cmd->target] == SS_UNSET) {
- if (hostdata->no_sync & (1 << cmd->target))
- hostdata->sync_stat[cmd->target] = SS_SET;
- else
+ if (hostdata->sync_stat[cmd->target] == SS_UNSET)
hostdata->sync_stat[cmd->target] = SS_FIRST;
- }
hostdata->state = S_SELECTING;
write_wd33c93_count(regp,0); /* guarantee a DATA_PHASE interrupt */
write_wd33c93_cmd(regp, WD_CMD_SEL_ATN);
*/
DB(DB_EXECUTE,printk("%s%ld)EX-2 ",(cmd->SCp.phase)?"d:":"",cmd->pid))
-
- enable_irq(instance->irq);
}
-void transfer_pio(wd33c93_regs *regp, uchar *buf, int cnt,
+static void transfer_pio(wd33c93_regs *regp, uchar *buf, int cnt,
int data_in_dir, struct WD33C93_hostdata *hostdata)
{
uchar asr;
-void transfer_bytes(wd33c93_regs *regp, Scsi_Cmnd *cmd, int data_in_dir)
+static void transfer_bytes(wd33c93_regs *regp, Scsi_Cmnd *cmd, int data_in_dir)
{
struct WD33C93_hostdata *hostdata;
unsigned long length;
Scsi_Cmnd *patch, *cmd;
wd33c93_regs *regp;
uchar asr, sr, phs, id, lun, *ucp, msg;
-unsigned long length;
+unsigned long length, flags;
hostdata = (struct WD33C93_hostdata *)instance->hostdata;
regp = hostdata->regp;
if (!(asr & ASR_INT) || (asr & ASR_BSY))
return;
+ save_flags(flags);
+
#ifdef PROC_STATISTICS
hostdata->int_cnt++;
#endif
case CSR_TIMEOUT:
DB(DB_INTR,printk("TIMEOUT"))
- disable_irq(instance->irq);
if (hostdata->state == S_RUNNING_LEVEL2)
hostdata->connected = NULL;
else {
hostdata->state = S_UNCONNECTED;
cmd->scsi_done(cmd);
+ /* From esp.c:
+ * There is a window of time within the scsi_done() path
+ * of execution where interrupts are turned back on full
+ * blast and left that way. During that time we could
+ * reconnect to a disconnected command, then we'd bomb
+ * out below. We could also end up executing two commands
+ * at _once_. ...just so you know why the restore_flags()
+ * is here...
+ */
+
+ restore_flags(flags);
+
/* We are not connected to a target - check to see if there
* are commands waiting to be executed.
*/
- enable_irq(instance->irq);
wd33c93_execute(instance);
break;
/* Note: this interrupt should not occur in a LEVEL2 command */
case CSR_SELECT:
- disable_irq(instance->irq);
DB(DB_INTR,printk("SELECT"))
hostdata->connected = cmd = (Scsi_Cmnd *)hostdata->selecting;
hostdata->sync_stat[cmd->target] = SS_WAITING;
- /* tack on a 2nd message to ask about synchronous transfers */
+/* Tack on a 2nd message to ask about synchronous transfers. If we've
+ * been asked to do only asynchronous transfers on this device, we
+ * request a fifo depth of 0, which is equivalent to async - should
+ * solve the problems some people have had with GVP's Guru ROM.
+ */
hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;
hostdata->outgoing_msg[2] = 3;
hostdata->outgoing_msg[3] = EXTENDED_SDTR;
+ if (hostdata->no_sync & (1 << cmd->target)) {
+ hostdata->outgoing_msg[4] = hostdata->default_sx_per/4;
+ hostdata->outgoing_msg[5] = 0;
+ }
+ else {
hostdata->outgoing_msg[4] = OPTIMUM_SX_PER/4;
hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;
+ }
hostdata->outgoing_len = 6;
}
else
case CSR_SRV_REQ |PHS_MESS_IN:
DB(DB_INTR,printk("MSG_IN="))
- disable_irq(instance->irq);
msg = read_1_byte(regp);
sr = read_wd33c93(regp, WD_SCSI_STATUS); /* clear interrupt */
write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
hostdata->state = S_CONNECTED;
}
+ restore_flags(flags);
break;
/* Note: this interrupt will occur only after a LEVEL2 command */
case CSR_SEL_XFER_DONE:
- disable_irq(instance->irq);
/* Make sure that reselection is enabled at this point - it may
* have been turned off for the command that just completed.
/* We are no longer connected to a target - check to see if
* there are commands waiting to be executed.
*/
- enable_irq(instance->irq);
+ restore_flags(flags);
wd33c93_execute(instance);
}
else {
* so we treat it as a normal command-complete-disconnect.
*/
- disable_irq(instance->irq);
-
/* Make sure that reselection is enabled at this point - it may
* have been turned off for the command that just completed.
*/
/* We are no longer connected to a target - check to see if
* there are commands waiting to be executed.
*/
- enable_irq(instance->irq);
+ /* look above for comments on scsi_done() */
+ restore_flags(flags);
wd33c93_execute(instance);
break;
case CSR_DISC:
- disable_irq(instance->irq);
/* Make sure that reselection is enabled at this point - it may
* have been turned off for the command that just completed.
else if (cmd->SCp.Status != GOOD)
cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
cmd->scsi_done(cmd);
+ restore_flags(flags);
break;
case S_PRE_TMP_DISC:
case S_RUNNING_LEVEL2:
/* We are no longer connected to a target - check to see if
* there are commands waiting to be executed.
*/
- enable_irq(instance->irq);
wd33c93_execute(instance);
break;
case CSR_RESEL_AM:
DB(DB_INTR,printk("RESEL"))
- disable_irq(instance->irq);
-
/* First we have to make sure this reselection didn't */
/* happen during Arbitration/Selection of some other device. */
/* If yes, put losing command back on top of input_Q. */
printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--",asr,sr,phs);
}
- enable_irq(instance->irq);
-
DB(DB_INTR,printk("} "))
}
-void reset_wd33c93(struct Scsi_Host *instance)
+static void reset_wd33c93(struct Scsi_Host *instance)
{
struct WD33C93_hostdata *hostdata;
wd33c93_regs *regp;
/* check_setup_strings() returns index if key found, 0 if not
*/
-int check_setup_strings(char *key, int *flags, int *val, char *buf)
+static int check_setup_strings(char *key, int *flags, int *val, char *buf)
{
int x;
char *cp;
reset_wd33c93(instance);
sti();
- printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d\n",instance->host_no,
+ printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d",instance->host_no,
(hostdata->chip==C_WD33C93)?"WD33c93":
(hostdata->chip==C_WD33C93A)?"WD33c93A":
(hostdata->chip==C_WD33C93B)?"WD33c93B":"unknown",
hostdata->microcode,hostdata->no_sync,hostdata->no_dma);
#ifdef DEBUGGING_ON
- printk(" debug_flags=0x%02x setup_strings=",hostdata->args);
+ printk(" debug_flags=0x%02x\n",hostdata->args);
#else
- printk(" debugging=OFF setup_strings=");
+ printk(" debugging=OFF\n");
#endif
+ printk(" setup_strings=");
for (i=0; i<MAX_SETUP_STRINGS; i++)
printk("%s,",setup_strings[i]);
printk("\n");
* wd33c93.h - Linux device driver definitions for the
* Commodore Amiga A2091/590 SCSI controller card
*
- * IMPORTANT: This file is for version 1.23 - 04/Nov/1996
+ * IMPORTANT: This file is for version 1.24 - 29/Jan/1997
*
* Copyright (c) 1996 John Shifflett, GeoLog Consulting
* john@geolog.com
#define WD33C93_H
+#define PROC_INTERFACE /* add code for /proc/scsi/wd33c93/xxx interface */
+#ifdef PROC_INTERFACE
+#define PROC_STATISTICS /* add code for keeping various real time stats */
+#endif
+
+#define SYNC_DEBUG /* extra info on sync negotiation printed */
+#define DEBUGGING_ON /* enable command-line debugging bitmask */
+#define DEBUG_DEFAULTS 0 /* default debugging bitmask */
+
+
+#ifdef DEBUGGING_ON
+#define DB(f,a) if (hostdata->args & (f)) a;
+#else
+#define DB(f,a)
+#endif
+
#define uchar unsigned char
uchar sync_stat[8]; /* status of sync negotiation per target */
uchar no_sync; /* bitmask: don't do sync on these targets */
uchar no_dma; /* set this flag to disable DMA */
+#ifdef PROC_INTERFACE
uchar proc; /* bitmask: what's in proc output */
+#ifdef PROC_STATISTICS
unsigned long cmd_cnt[8]; /* # of commands issued per target */
unsigned long int_cnt; /* # of interrupts serviced */
unsigned long pio_cnt; /* # of pio data transfers */
unsigned long dma_cnt; /* # of DMA data transfers */
unsigned long disc_allowed_cnt[8]; /* # of disconnects allowed per target */
unsigned long disc_done_cnt[8]; /* # of disconnects done per target*/
+#endif
+#endif
};
#include <linux/amigaffs.h>
#include <linux/major.h>
#include <linux/blkdev.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
NULL
};
-int
-init_affs_fs(void)
+__initfunc(int init_affs_fs(void))
{
return register_filesystem(&affs_fs_type);
}
*
* ------------------------------------------------------------------------- */
-#include <linux/modversions.h>
#include <linux/module.h>
#include <linux/auto_fs.h>
#include <linux/malloc.h>
#include <linux/binfmts.h>
#include <linux/personality.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
# define START_DATA(u) (u.start_data)
#elif defined(__sparc__)
# define START_DATA(u) (u.u_tsize)
-#elif defined(__i386__)
+#elif defined(__i386__) || defined(__mc68000__)
# define START_DATA(u) (u.u_tsize << PAGE_SHIFT)
#endif
#ifdef __sparc__
}
-int init_aout_binfmt(void) {
+__initfunc(int init_aout_binfmt(void))
+{
return register_binfmt(&aout_format);
}
#include <linux/shm.h>
#include <linux/personality.h>
#include <linux/elfcore.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#else
if (sizeof(elf_gregset_t) != sizeof(struct pt_regs))
{
- printk("sizeof(elf_gregset_t) (%d) != sizeof(struct pt_regs) (%d)\n",
+ printk("sizeof(elf_gregset_t) (%ld) != sizeof(struct pt_regs) (%ld)\n",
sizeof(elf_gregset_t), sizeof(struct pt_regs));
}
else
}
#endif /* USE_ELF_CORE_DUMP */
-int init_elf_binfmt(void)
+__initfunc(int init_elf_binfmt(void))
{
return register_binfmt(&elf_format);
}
#ifndef MODULE
NULL, 0, load_em86, NULL, NULL
#else
- NULL, &mod_use_count_, load_em86, NULL, NULL
+ NULL, &__this_module, load_em86, NULL, NULL
#endif
};
-int init_em86_binfmt(void) {
+__initfunc(int init_em86_binfmt(void))
+{
return register_binfmt(&em86_format);
}
#include <linux/stat.h>
#include <linux/malloc.h>
#include <linux/binfmts.h>
+#include <linux/init.h>
#define _PATH_JAVA "/usr/bin/java"
#define _PATH_APPLET "/usr/bin/appletviewer"
#endif
};
-int init_java_binfmt(void) {
+__initfunc(int init_java_binfmt(void))
+{
register_binfmt(&java_format);
return register_binfmt(&applet_format);
}
#include <linux/stat.h>
#include <linux/malloc.h>
#include <linux/binfmts.h>
+#include <linux/init.h>
static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
{
#endif
};
-int init_script_binfmt(void) {
+__initfunc(int init_script_binfmt(void))
+{
return register_binfmt(&script_format);
}
#include <linux/personality.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
static struct linux_binfmt *formats = (struct linux_binfmt *) NULL;
-void binfmt_setup(void)
+__initfunc(void binfmt_setup(void))
{
#ifdef CONFIG_BINFMT_ELF
init_elf_binfmt();
if (IS_NOSUID(bprm->inode)
|| (current->flags & PF_PTRACED)
|| (current->fs->count > 1)
- || (current->sig->count > 1)
+ || (atomic_read(¤t->sig->count) > 1)
|| (current->files->count > 1)) {
if (!suser())
return -EPERM;
#include <linux/string.h>
#include <linux/locks.h>
#include <linux/blkdev.h>
+#include <linux/init.h>
static char error_buf[1024];
ext2_read_super, "ext2", 1, NULL
};
-int init_ext2_fs(void)
+__initfunc(int init_ext2_fs(void))
{
return register_filesystem(&ext2_fs_type);
}
#include <linux/locks.h>
#include <linux/stat.h>
#include <linux/string.h>
+#include <linux/init.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
hpfs_read_super, "hpfs", 1, NULL
};
-int init_hpfs_fs(void)
+__initfunc(int init_hpfs_fs(void))
{
return register_filesystem(&hpfs_fs_type);
}
filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
+ ISOFS_BLOCK_SIZE);
offset = 0;
+ if( filp->f_pos >= inode->i_size )
+ {
+ return 0;
+ }
+
block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
if (!block)
return 0;
#include <linux/malloc.h>
#include <linux/errno.h>
#include <linux/cdrom.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
isofs_read_super, "iso9660", 1, NULL
};
-int init_iso9660_fs(void)
+__initfunc(int init_iso9660_fs(void))
{
return register_filesystem(&iso9660_fs_type);
}
offset = 0;
f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1))
+ ISOFS_BLOCK_SIZE);
+
+ if( f_pos >= dir->i_size )
+ {
+ return 0;
+ }
+
block = isofs_bmap(dir,f_pos>>bufbits);
if (!block || !(bh = bread(dir->i_dev,block,bufsize)))
return 0;
#define NLM_HOST_MAX 64
#define NLM_HOST_NRHASH 32
#define NLM_ADDRHASH(addr) (ntohl(addr) & (NLM_HOST_NRHASH-1))
-#define NLM_PTRHASH(ptr) ((((u32) ptr) / 32) & (NLM_HOST_NRHASH-1))
+#define NLM_PTRHASH(ptr) ((((u32)(unsigned long) ptr) / 32) & (NLM_HOST_NRHASH-1))
#define NLM_HOST_REBIND (60 * HZ)
#define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
#define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ)
return NULL;
}
- dprintk("lockd: nlm_lookup_host(%08lx, p=%d, v=%d)\n",
- sin? ntohl(sin->sin_addr.s_addr) : 0, proto, version);
+ dprintk("lockd: nlm_lookup_host(%08x, p=%d, v=%d)\n",
+ (unsigned)(sin? ntohl(sin->sin_addr.s_addr) : 0), proto, version);
if (clnt)
hash = NLM_PTRHASH(clnt);
struct rpc_clnt *clnt;
struct rpc_xprt *xprt;
- dprintk("lockd: nlm_bind_host(%08lx)\n",
- ntohl(host->h_addr.sin_addr.s_addr));
+ dprintk("lockd: nlm_bind_host(%08x)\n",
+ (unsigned)ntohl(host->h_addr.sin_addr.s_addr));
/* Lock host handle */
down(&host->h_sema);
break;
}
- dprintk("lockd: request from %08lx\n",
- ntohl(rqstp->rq_addr.sin_addr.s_addr));
+ dprintk("lockd: request from %08x\n",
+ (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
/*
* Look up the NFS client handle. The handle is needed for
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/locks.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
minix_read_super, "minix", 1, NULL
};
-int init_minix_fs(void)
+__initfunc(int init_minix_fs(void))
{
return register_filesystem(&minix_fs_type);
}
#include <linux/mm.h>
#include <linux/msdos_fs.h>
+#include <linux/init.h>
/*
* Support for umsdos fs
msdos_read_super, "msdos", 1, NULL
};
-int init_msdos_fs(void)
+__initfunc(int init_msdos_fs(void))
{
return register_filesystem(&msdos_fs_type);
}
#include <linux/locks.h>
#include <linux/fcntl.h>
#include <linux/malloc.h>
+#include <linux/init.h>
#ifdef CONFIG_KERNELD
#include <linux/kerneld.h>
#endif
ncp_read_super, "ncpfs", 0, NULL
};
-int init_ncp_fs(void)
+__initfunc(int init_ncp_fs(void))
{
return register_filesystem(&ncp_fs_type);
}
}
if (entry) {
dfprintk(DIRCACHE, "NFS: found dircache entry %d\n",
- cache - dircache);
+ (int)(cache - dircache));
cache->locked = 1;
break;
}
goto again;
}
dfprintk(DIRCACHE, "NFS: using free dircache entry %d\n",
- free - dircache);
+ (int)(free - dircache));
cache->cookie = cookie;
cache->locked = 1;
cache->valid = 0;
ino_t ino = inode->i_ino;
int i;
- dfprintk(DIRCACHE, "NFS: invalidate dircache for %x/%ld\n", dev, ino);
+ dfprintk(DIRCACHE, "NFS: invalidate dircache for %x/%ld\n", dev, (long)ino);
for (i = 0, cache = dircache; i < NFS_MAX_DIRCACHE; i++, cache++) {
if (!cache->locked && cache->dev == dev && cache->ino == ino)
cache->valid = 0; /* brute force */
return;
dfprintk(LOOKUPCACHE, "NFS: lookup_cache_remove(%x/%ld)\n",
- dev, fileid);
+ dev, (long)fileid);
for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
entry = nfs_lookup_cache + i;
char hostname[32];
int status;
- dprintk("NFS: nfs_mount(%08lx:%s)\n",
- ntohl(addr->sin_addr.s_addr), path);
+ dprintk("NFS: nfs_mount(%08x:%s)\n",
+ (unsigned)ntohl(addr->sin_addr.s_addr), path);
strcpy(hostname, in_ntoa(addr->sin_addr.s_addr));
if (!(mnt_clnt = mnt_create(hostname, addr)))
struct iovec *iov = req->rq_rvec;
int status, count, recvd, hdrlen;
- dprintk("RPC: readres OK status %lx\n", ntohl(*p));
+ dprintk("RPC: readres OK status %lx\n", (long)ntohl(*p));
if ((status = ntohl(*p++)))
return -nfs_stat_to_errno(status);
p = xdr_decode_fattr(p, res->fattr);
}
string -= len;
if ((void *) (entry+1) > (void *) string) {
+ /* This may actually happen because an nfs_entry
+ * will take up more space than the XDR data. On
+ * 32bit machines that's due to 8byte alignment,
+ * on 64bit machines that's because the char * takes
+ * up 2 longs.
+ *
+ * THIS IS BAD!
+ */
printk(KERN_NOTICE "NFS: should not happen in %s!\n",
- __FUNCTION__);
- printk(KERN_NOTICE "NFS: len = %d, entry+1=%p, string=%p\n", len, entry+1, string);
+ __FUNCTION__);
break;
}
{
int status;
- dprintk("RPC: attrstat status %lx\n", ntohl(*p));
+ dprintk("RPC: attrstat status %lx\n", (long)ntohl(*p));
if ((status = ntohl(*p++)))
return -nfs_stat_to_errno(status);
xdr_decode_fattr(p, fattr);
{
int status;
- dprintk("RPC: diropres status %lx\n", ntohl(*p));
+ dprintk("RPC: diropres status %lx\n", (long)ntohl(*p));
if ((status = ntohl(*p++)))
return -nfs_stat_to_errno(status);
p = xdr_decode_fhandle(p, res->fh);
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/net.h>
-#include <linux/in.h>
#include <linux/unistd.h>
#include <linux/malloc.h>
#include <linux/in.h>
char tmp[30];
iput(inode);
- len = 1 + sprintf(tmp, "%d", current->pid);
+ len = sprintf(tmp, "%d", current->pid);
if (buflen < len)
len = buflen;
copy_to_user(buffer, tmp, len);
#include <linux/romfs_fs.h>
#include <linux/fs.h>
#include <linux/locks.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
romfs_read_super, "romfs", 1, NULL
};
-int
-init_romfs_fs(void)
+__initfunc(int init_romfs_fs(void))
{
return register_filesystem(&romfs_fs_type);
}
#include <linux/locks.h>
#include <linux/fcntl.h>
#include <linux/malloc.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
smb_read_super, "smbfs", 0, NULL
};
-int
-init_smb_fs(void)
+__initfunc(int init_smb_fs(void))
{
return register_filesystem(&smb_fs_type);
}
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/locks.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
{sysv_read_super, "coherent", 1, NULL}
};
-int init_sysv_fs(void)
+__initfunc(int init_sysv_fs(void))
{
int i;
int ouch;
*
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
*
- * $Id: ufs_super.c,v 1.22 1997/01/16 14:17:41 davem Exp $
+ * $Id: ufs_super.c,v 1.23 1997/04/16 04:53:39 tdyas Exp $
*
*/
#include <linux/fs.h>
#include <linux/ufs_fs.h>
#include <linux/locks.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
ufs_read_super, "ufs", 1, NULL
};
-int
-init_ufs_fs(void)
+__initfunc(int init_ufs_fs(void))
{
return(register_filesystem(&ufs_fs_type));
}
#include <linux/module.h>
+#include <linux/init.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
#include <linux/kernel.h>
UMSDOS_read_super, "umsdos", 1, NULL
};
-int init_umsdos_fs(void)
+__initfunc(int init_umsdos_fs(void))
{
return register_filesystem(&umsdos_fs_type);
}
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/mm.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
EXPORT_SYMBOL(vfat_read_inode);
EXPORT_SYMBOL(vfat_lookup);
-int init_vfat_fs(void)
+__initfunc(int init_vfat_fs(void))
{
return register_filesystem(&vfat_fs_type);
}
typedef struct { int counter; } atomic_t;
#endif
-#define ATOMIC_INIT { 0 }
+#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) ((v)->counter = (i))
struct wait_queue * wait;
};
-#define MUTEX ((struct semaphore) { { 1 }, { 0 }, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { { 0 }, { 0 }, NULL })
+#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
+#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
extern void __down(struct semaphore * sem);
extern int __down_interruptible(struct semaphore * sem);
#define lock_kernel() do { } while(0)
#define unlock_kernel() do { } while(0)
#define release_kernel_lock(task, cpu, depth) ((depth) = 1)
-#define reaquire_kernel_lock(task, cpu, depth) do { } while (0)
+#define reacquire_kernel_lock(task, cpu, depth) do { } while (0)
#else
typedef struct { } spinlock_t;
#define SPIN_LOCK_UNLOCKED { }
-#define spin_lock_init(lock) do { } while(0)
+/*
+ * Basic spinlocks - one can enter at a time
+ */
+
#define spin_lock(lock) do { } while(0)
#define spin_trylock(lock) do { } while(0)
#define spin_unlock(lock) do { } while(0)
#define spin_lock_irq(lock) setipl(7)
#define spin_unlock_irq(lock) setipl(0)
-
#define spin_lock_irqsave(lock, flags) swpipl(flags,7)
#define spin_unlock_irqrestore(lock, flags) setipl(flags)
+/*
+ * Read-write locks: we can have multiple readers, but
+ * only one writer
+ */
+
+#define read_lock(lock) do { } while(0)
+#define read_unlock(lock) do { } while(0)
+#define read_lock_irq(lock) setipl(7)
+#define read_unlock_irq(lock) setipl(0)
+#define read_lock_irqsave(lock, flags) swpipl(flags,7)
+#define read_unlock_irqrestore(lock, flags) setipl(flags)
+
+#define write_lock(lock) do { } while(0)
+#define write_unlock(lock) do { } while(0)
+#define write_lock_irq(lock) setipl(7)
+#define write_unlock_irq(lock) setipl(0)
+#define write_lock_irqsave(lock, flags) swpipl(flags,7)
+#define write_unlock_irqrestore(lock, flags) setipl(flags)
+
#else
/* Simple spin lock operations. There are two variants, one clears IRQ's
#define SPIN_LOCK_UNLOCKED { 0, 0 }
+#define spin_lock_init(lock) do { (lock)->lock = 0; (lock)->previous = 0; } while(0)
+
typedef struct { unsigned long a[100]; } __dummy_lock_t;
#define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
typedef struct { int counter; } atomic_t;
#endif
-#define ATOMIC_INIT { 0 }
+#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
#ifndef _I386_INIT_H
#define _I386_INIT_H
-#ifndef MODULE
#define __init __attribute__ ((__section__ (".text.init")))
#define __initdata __attribute__ ((__section__ (".data.init")))
#define __initfunc(__arginit) \
#define __INIT .section ".text.init",#alloc,#execinstr
#define __FINIT .previous
#define __INITDATA .section ".data.init",#alloc,#write
-#else
-#define __init
-#define __initdata
-#define __initfunc(__arginit) __arginit
-/* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
-#endif
#endif
struct wait_queue * wait;
};
-#define MUTEX ((struct semaphore) { { 1 }, 0, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { { 0 }, 0, NULL })
+#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, NULL })
+#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, NULL })
asmlinkage void __down_failed(void /* special register calling convention */);
asmlinkage int __down_failed_interruptible(void /* params in registers */);
return GET_APIC_ID(*(unsigned long *)(apic_reg+APIC_ID));
}
-/* These read/change the "processes available" counter in the scheduler. */
-extern __inline__ __volatile__ void inc_smp_counter(volatile int *ctr)
-{
- int cpu = smp_processor_id();
- while(set_bit(31, ctr))
- {
- while(test_bit(31,ctr))
- {
- if(clear_bit(cpu,&smp_invalidate_needed))
- {
- unsigned long tmpreg;
- __asm__ __volatile__("movl %%cr3,%0\n\tmovl %0,%%cr3"
- : "=r" (tmpreg) : : "memory");
- set_bit(cpu,&cpu_callin_map[0]);
- }
- }
- }
- *ctr = (*ctr + 1);
- clear_bit(31, ctr);
-}
-
-extern __inline__ __volatile__ void dec_smp_counter(volatile int *ctr)
-{
- int cpu = smp_processor_id();
- while(set_bit(31, ctr))
- {
- while(test_bit(31,ctr))
- {
- if(clear_bit(cpu,&smp_invalidate_needed))
- {
- unsigned long tmpreg;
- __asm__ __volatile__("movl %%cr3,%0\n\tmovl %0,%%cr3"
- : "=r" (tmpreg) : : "memory");
- set_bit(cpu,&cpu_callin_map[0]);
- }
- }
- }
- *ctr = (*ctr - 1);
- clear_bit(31, ctr);
-}
-
-extern __inline__ __volatile__ int read_smp_counter(volatile int *ctr)
-{
- return (*ctr & 0x7fffffff);
-}
-
#endif /* !ASSEMBLY */
#define NO_PROC_ID 0xFF /* No processor magic marker */
#define lock_kernel() do { } while(0)
#define unlock_kernel() do { } while(0)
#define release_kernel_lock(task, cpu, depth) ((depth) = 1)
-#define reaquire_kernel_lock(task, cpu, depth) do { } while(0)
+#define reacquire_kernel_lock(task, cpu, depth) do { } while(0)
#else
__sti(); \
} while (0)
-/* Re-aquire the kernel lock */
-#define reaquire_kernel_lock(task, cpu, depth) \
+/* Re-acquire the kernel lock */
+#define reacquire_kernel_lock(task, cpu, depth) \
do { if (depth) __asm__ __volatile__( \
"cli\n\t" \
"movl $0f,%%eax\n\t" \
#ifndef __SMP__
+/*
+ * Your basic spinlocks, allowing only a single CPU anywhere
+ */
typedef struct { } spinlock_t;
#define SPIN_LOCK_UNLOCKED { }
#define spin_unlock_irqrestore(lock, flags) \
restore_flags(flags)
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+typedef struct { } rwlock_t;
+#define RW_LOCK_UNLOCKED { }
+
+#define read_lock(lock) do { } while(0)
+#define read_unlock(lock) do { } while(0)
+#define write_lock(lock) do { } while(0)
+#define write_unlock(lock) do { } while(0)
+#define read_lock_irq(lock) cli()
+#define read_unlock_irq(lock) sti()
+#define write_lock_irq(lock) cli()
+#define write_unlock_irq(lock) sti()
+
+#define read_lock_irqsave(lock, flags) \
+ do { save_flags(flags); cli(); } while (0)
+#define read_unlock_irqrestore(lock, flags) \
+ restore_flags(flags)
+#define write_lock_irqsave(lock, flags) \
+ do { save_flags(flags); cli(); } while (0)
+#define write_unlock_irqrestore(lock, flags) \
+ restore_flags(flags)
+
#else
-/* Simple spin lock operations. There are two variants, one clears IRQ's
+/*
+ * Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not.
*
* We make no fairness assumptions. They have a cost.
#define SPIN_LOCK_UNLOCKED { 0, 0 }
+#define spin_lock_init(x) do { (x)->lock = 0; (x)->previous = 0; } while(0)
+
typedef struct { unsigned long a[100]; } __dummy_lock_t;
#define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
#define spin_unlock_irqrestore(lock, flags) \
do { spin_unlock(lock); __restore_flags(flags); } while (0)
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+typedef struct {
+ volatile unsigned int lock;
+ unsigned long previous;
+} rwlock_t;
+
+#define RW_LOCK_UNLOCKED { 0, 0 }
+
+/*
+ * On x86, we implement read-write locks as a 32-bit counter
+ * with the high bit (sign) being the "write" bit.
+ *
+ * The inline assembly is non-obvious. Think about it.
+ */
+#define read_lock(rw) \
+ asm volatile("\n1:\t" \
+ "lock ; incl %0\n\t" \
+ "js 2f\n" \
+ ".text 2\n" \
+ "2:\tlock ; decl %0\n" \
+ "3:\tcmpl $0,%0\n\t" \
+ "js 3b\n\t" \
+ "jmp 1b\n" \
+ ".text" \
+ :"=m" (__dummy_lock(&(rw)->lock)))
+
+#define read_unlock(rw) \
+ asm volatile("lock ; decl %0" \
+ :"=m" (__dummy_lock(&(rw)->lock)))
+
+#define write_lock(rw) \
+ asm volatile("\n1:\t" \
+ "lock ; btsl $31,%0\n\t" \
+ "jc 3f\n\t" \
+ "testl $0x7fffffff,%0\n\t" \
+ "jne 4f\n" \
+ "2:\n" \
+ ".text 2\n" \
+ "3:\ttestl $-1,%0\n\t" \
+ "js 3b\n\t" \
+ "lock ; btsl $31,%0\n\t" \
+ "jc 3b\n" \
+ "4:\ttestl $0x7fffffff,%0\n\t" \
+ "jne 4b\n\t" \
+ "jmp 2b\n" \
+ ".text" \
+ :"=m" (__dummy_lock(&(rw)->lock)))
+
+#define write_unlock(rw) \
+ asm volatile("lock ; btrl $31,%0":"=m" (__dummy_lock(&(rw)->lock)))
+
+#define read_lock_irq(lock) do { __cli(); read_lock(lock); } while (0)
+#define read_unlock_irq(lock) do { read_unlock(lock); __sti(); } while (0)
+#define write_lock_irq(lock) do { __cli(); write_lock(lock); } while (0)
+#define write_unlock_irq(lock) do { write_unlock(lock); __sti(); } while (0)
+
+#define read_lock_irqsave(lock, flags) \
+ do { __save_flags(flags); __cli(); read_lock(lock); } while (0)
+#define read_unlock_irqrestore(lock, flags) \
+ do { read_unlock(lock); __restore_flags(flags); } while (0)
+#define write_lock_irqsave(lock, flags) \
+ do { __save_flags(flags); __cli(); write_lock(lock); } while (0)
+#define write_unlock_irqrestore(lock, flags) \
+ do { write_unlock(lock); __restore_flags(flags); } while (0)
+
#endif /* SMP */
#endif /* __ASM_SPINLOCK_H */
**
*/
-#define AMI_IRQS (24)
+#define AUTO_IRQS (8)
#define AMI_STD_IRQS (14)
#define CIA_IRQS (5)
+#define AMI_IRQS (32) /* AUTO_IRQS+AMI_STD_IRQS+2*CIA_IRQS */
/* vertical blanking interrupt */
-#define IRQ_AMIGA_VERTB (IRQ_MACHSPEC | 0)
+#define IRQ_AMIGA_VERTB 0
/* copper interrupt */
-#define IRQ_AMIGA_COPPER (IRQ_MACHSPEC | 1)
+#define IRQ_AMIGA_COPPER 1
/* Audio interrupts */
-#define IRQ_AMIGA_AUD0 (IRQ_MACHSPEC | 2)
-#define IRQ_AMIGA_AUD1 (IRQ_MACHSPEC | 3)
-#define IRQ_AMIGA_AUD2 (IRQ_MACHSPEC | 4)
-#define IRQ_AMIGA_AUD3 (IRQ_MACHSPEC | 5)
+#define IRQ_AMIGA_AUD0 2
+#define IRQ_AMIGA_AUD1 3
+#define IRQ_AMIGA_AUD2 4
+#define IRQ_AMIGA_AUD3 5
/* Blitter done interrupt */
-#define IRQ_AMIGA_BLIT (IRQ_MACHSPEC | 6)
+#define IRQ_AMIGA_BLIT 6
/* floppy disk interrupts */
-#define IRQ_AMIGA_DSKSYN (IRQ_MACHSPEC | 7)
-#define IRQ_AMIGA_DSKBLK (IRQ_MACHSPEC | 8)
+#define IRQ_AMIGA_DSKSYN 7
+#define IRQ_AMIGA_DSKBLK 8
/* builtin serial port interrupts */
-#define IRQ_AMIGA_RBF (IRQ_MACHSPEC | 9)
-#define IRQ_AMIGA_TBE (IRQ_MACHSPEC | 10)
+#define IRQ_AMIGA_RBF 9
+#define IRQ_AMIGA_TBE 10
/* software interrupts */
-#define IRQ_AMIGA_SOFT (IRQ_MACHSPEC | 11)
+#define IRQ_AMIGA_SOFT 11
/* interrupts from external hardware */
-#define IRQ_AMIGA_PORTS (IRQ_MACHSPEC | 12)
-#define IRQ_AMIGA_EXTER (IRQ_MACHSPEC | 13)
+#define IRQ_AMIGA_PORTS 12
+#define IRQ_AMIGA_EXTER 13
/* CIA interrupt sources */
-#define IRQ_AMIGA_CIAA (IRQ_MACHSPEC | 14)
-#define IRQ_AMIGA_CIAA_TA (IRQ_MACHSPEC | 14)
-#define IRQ_AMIGA_CIAA_TB (IRQ_MACHSPEC | 15)
-#define IRQ_AMIGA_CIAA_ALRM (IRQ_MACHSPEC | 16)
-#define IRQ_AMIGA_CIAA_SP (IRQ_MACHSPEC | 17)
-#define IRQ_AMIGA_CIAA_FLG (IRQ_MACHSPEC | 18)
-#define IRQ_AMIGA_CIAB (IRQ_MACHSPEC | 19)
-#define IRQ_AMIGA_CIAB_TA (IRQ_MACHSPEC | 19)
-#define IRQ_AMIGA_CIAB_TB (IRQ_MACHSPEC | 20)
-#define IRQ_AMIGA_CIAB_ALRM (IRQ_MACHSPEC | 21)
-#define IRQ_AMIGA_CIAB_SP (IRQ_MACHSPEC | 22)
-#define IRQ_AMIGA_CIAB_FLG (IRQ_MACHSPEC | 23)
+#define IRQ_AMIGA_CIAA 14
+#define IRQ_AMIGA_CIAA_TA 14
+#define IRQ_AMIGA_CIAA_TB 15
+#define IRQ_AMIGA_CIAA_ALRM 16
+#define IRQ_AMIGA_CIAA_SP 17
+#define IRQ_AMIGA_CIAA_FLG 18
+#define IRQ_AMIGA_CIAB 19
+#define IRQ_AMIGA_CIAB_TA 19
+#define IRQ_AMIGA_CIAB_TB 20
+#define IRQ_AMIGA_CIAB_ALRM 21
+#define IRQ_AMIGA_CIAB_SP 22
+#define IRQ_AMIGA_CIAB_FLG 23
+
+/* auto-vector interrupts */
+#define IRQ_AMIGA_AUTO 24
+#define IRQ_AMIGA_AUTO_0 24 /* This is just a dummy */
+#define IRQ_AMIGA_AUTO_1 25
+#define IRQ_AMIGA_AUTO_2 26
+#define IRQ_AMIGA_AUTO_3 27
+#define IRQ_AMIGA_AUTO_4 28
+#define IRQ_AMIGA_AUTO_5 29
+#define IRQ_AMIGA_AUTO_6 30
+#define IRQ_AMIGA_AUTO_7 31
#define IRQ_FLOPPY IRQ_AMIGA_DSKBLK
ATARIHW_DECLARE(SCU); /* System Control Unit */
ATARIHW_DECLARE(BLITTER); /* Blitter */
ATARIHW_DECLARE(VME); /* VME Bus */
+ ATARIHW_DECLARE(DSP56K); /* DSP56k processor in Falcon */
};
extern struct atari_hw_present atari_hw_present;
void atari_stram_free (void *);
extern int is_medusa;
+extern int is_hades;
/* Do cache push/invalidate for DMA read/write. This function obeys the
* snooping on some machines (Medusa) and processors: The Medusa itself can
{
u_char tracks;
u_char input_source;
-#define CODEC_SOURCE_MATRIX 1
-#define CODEC_SOURCE_ADC 2
+#define CODEC_SOURCE_ADC 1
+#define CODEC_SOURCE_MATRIX 2
u_char adc_source;
#define ADC_SOURCE_RIGHT_PSG 1
#define ADC_SOURCE_LEFT_PSG 2
};
# define tt_dmasnd ((*(volatile struct TT_DMASND *)TT_DMASND_BAS))
-#define DMASND_CTRL_OFF 0x00
-#define DMASND_CTRL_ON 0x01
-#define DMASND_CTRL_REPEAT 0x02
-#define DMASND_MODE_MONO 0x80
-#define DMASND_MODE_STEREO 0x00
-#define DMASND_MODE_8BIT 0x00
-#define DMASND_MODE_16BIT 0x40 /* Falcon only */
-#define DMASND_MODE_6KHZ 0x00 /* Falcon: mute */
-#define DMASND_MODE_12KHZ 0x01
-#define DMASND_MODE_25KHZ 0x02
-#define DMASND_MODE_50KHZ 0x03
+#define DMASND_MFP_INT_REPLAY 0x01
+#define DMASND_MFP_INT_RECORD 0x02
+#define DMASND_TIMERA_INT_REPLAY 0x04
+#define DMASND_TIMERA_INT_RECORD 0x08
+
+#define DMASND_CTRL_OFF 0x00
+#define DMASND_CTRL_ON 0x01
+#define DMASND_CTRL_REPEAT 0x02
+#define DMASND_CTRL_RECORD_ON 0x10
+#define DMASND_CTRL_RECORD_OFF 0x00
+#define DMASND_CTRL_RECORD_REPEAT 0x20
+#define DMASND_CTRL_SELECT_REPLAY 0x00
+#define DMASND_CTRL_SELECT_RECORD 0x80
+#define DMASND_MODE_MONO 0x80
+#define DMASND_MODE_STEREO 0x00
+#define DMASND_MODE_8BIT 0x00
+#define DMASND_MODE_16BIT 0x40 /* Falcon only */
+#define DMASND_MODE_6KHZ 0x00 /* Falcon: mute */
+#define DMASND_MODE_12KHZ 0x01
+#define DMASND_MODE_25KHZ 0x02
+#define DMASND_MODE_50KHZ 0x03
+
#define DMASNDSetBase(bufstart) \
do { \
**
*/
-#define STMFP_SOURCE_BASE 8
-#define TTMFP_SOURCE_BASE 24
-#define SCC_SOURCE_BASE 40
-#define VME_SOURCE_BASE 56
-#define VME_MAX_SOURCES 16
+#define STMFP_SOURCE_BASE 8
+#define TTMFP_SOURCE_BASE 24
+#define SCC_SOURCE_BASE 40
+#define VME_SOURCE_BASE 56
+#define VME_MAX_SOURCES 16
#define NUM_ATARI_SOURCES (VME_SOURCE_BASE+VME_MAX_SOURCES-STMFP_SOURCE_BASE)
#define IRQ_TYPE_FAST 1
#define IRQ_TYPE_PRIO 2
-#define IRQ_SPURIOUS (IRQ_MACHSPEC | 0)
+#define IRQ_SPURIOUS (0)
/* auto-vector interrupts */
-#define IRQ_AUTO_1 (IRQ_MACHSPEC | 1)
-#define IRQ_AUTO_2 (IRQ_MACHSPEC | 2)
-#define IRQ_AUTO_3 (IRQ_MACHSPEC | 3)
-#define IRQ_AUTO_4 (IRQ_MACHSPEC | 4)
-#define IRQ_AUTO_5 (IRQ_MACHSPEC | 5)
-#define IRQ_AUTO_6 (IRQ_MACHSPEC | 6)
-#define IRQ_AUTO_7 (IRQ_MACHSPEC | 7)
+#define IRQ_AUTO_1 (1)
+#define IRQ_AUTO_2 (2)
+#define IRQ_AUTO_3 (3)
+#define IRQ_AUTO_4 (4)
+#define IRQ_AUTO_5 (5)
+#define IRQ_AUTO_6 (6)
+#define IRQ_AUTO_7 (7)
/* ST-MFP interrupts */
-#define IRQ_MFP_BUSY (IRQ_MACHSPEC | 8)
-#define IRQ_MFP_DCD (IRQ_MACHSPEC | 9)
-#define IRQ_MFP_CTS (IRQ_MACHSPEC | 10)
-#define IRQ_MFP_GPU (IRQ_MACHSPEC | 11)
-#define IRQ_MFP_TIMD (IRQ_MACHSPEC | 12)
-#define IRQ_MFP_TIMC (IRQ_MACHSPEC | 13)
-#define IRQ_MFP_ACIA (IRQ_MACHSPEC | 14)
-#define IRQ_MFP_FDC (IRQ_MACHSPEC | 15)
+#define IRQ_MFP_BUSY (8)
+#define IRQ_MFP_DCD (9)
+#define IRQ_MFP_CTS (10)
+#define IRQ_MFP_GPU (11)
+#define IRQ_MFP_TIMD (12)
+#define IRQ_MFP_TIMC (13)
+#define IRQ_MFP_ACIA (14)
+#define IRQ_MFP_FDC (15)
#define IRQ_MFP_ACSI IRQ_MFP_FDC
#define IRQ_MFP_FSCSI IRQ_MFP_FDC
#define IRQ_MFP_IDE IRQ_MFP_FDC
-#define IRQ_MFP_TIMB (IRQ_MACHSPEC | 16)
-#define IRQ_MFP_SERERR (IRQ_MACHSPEC | 17)
-#define IRQ_MFP_SEREMPT (IRQ_MACHSPEC | 18)
-#define IRQ_MFP_RECERR (IRQ_MACHSPEC | 19)
-#define IRQ_MFP_RECFULL (IRQ_MACHSPEC | 20)
-#define IRQ_MFP_TIMA (IRQ_MACHSPEC | 21)
-#define IRQ_MFP_RI (IRQ_MACHSPEC | 22)
-#define IRQ_MFP_MMD (IRQ_MACHSPEC | 23)
+#define IRQ_MFP_TIMB (16)
+#define IRQ_MFP_SERERR (17)
+#define IRQ_MFP_SEREMPT (18)
+#define IRQ_MFP_RECERR (19)
+#define IRQ_MFP_RECFULL (20)
+#define IRQ_MFP_TIMA (21)
+#define IRQ_MFP_RI (22)
+#define IRQ_MFP_MMD (23)
/* TT-MFP interrupts */
-#define IRQ_TT_MFP_IO0 (IRQ_MACHSPEC | 24)
-#define IRQ_TT_MFP_IO1 (IRQ_MACHSPEC | 25)
-#define IRQ_TT_MFP_SCC (IRQ_MACHSPEC | 26)
-#define IRQ_TT_MFP_RI (IRQ_MACHSPEC | 27)
-#define IRQ_TT_MFP_TIMD (IRQ_MACHSPEC | 28)
-#define IRQ_TT_MFP_TIMC (IRQ_MACHSPEC | 29)
-#define IRQ_TT_MFP_DRVRDY (IRQ_MACHSPEC | 30)
-#define IRQ_TT_MFP_SCSIDMA (IRQ_MACHSPEC | 31)
-#define IRQ_TT_MFP_TIMB (IRQ_MACHSPEC | 32)
-#define IRQ_TT_MFP_SERERR (IRQ_MACHSPEC | 33)
-#define IRQ_TT_MFP_SEREMPT (IRQ_MACHSPEC | 34)
-#define IRQ_TT_MFP_RECERR (IRQ_MACHSPEC | 35)
-#define IRQ_TT_MFP_RECFULL (IRQ_MACHSPEC | 36)
-#define IRQ_TT_MFP_TIMA (IRQ_MACHSPEC | 37)
-#define IRQ_TT_MFP_RTC (IRQ_MACHSPEC | 38)
-#define IRQ_TT_MFP_SCSI (IRQ_MACHSPEC | 39)
+#define IRQ_TT_MFP_IO0 (24)
+#define IRQ_TT_MFP_IO1 (25)
+#define IRQ_TT_MFP_SCC (26)
+#define IRQ_TT_MFP_RI (27)
+#define IRQ_TT_MFP_TIMD (28)
+#define IRQ_TT_MFP_TIMC (29)
+#define IRQ_TT_MFP_DRVRDY (30)
+#define IRQ_TT_MFP_SCSIDMA (31)
+#define IRQ_TT_MFP_TIMB (32)
+#define IRQ_TT_MFP_SERERR (33)
+#define IRQ_TT_MFP_SEREMPT (34)
+#define IRQ_TT_MFP_RECERR (35)
+#define IRQ_TT_MFP_RECFULL (36)
+#define IRQ_TT_MFP_TIMA (37)
+#define IRQ_TT_MFP_RTC (38)
+#define IRQ_TT_MFP_SCSI (39)
/* SCC interrupts */
-#define IRQ_SCCB_TX (IRQ_MACHSPEC | 40)
-#define IRQ_SCCB_STAT (IRQ_MACHSPEC | 42)
-#define IRQ_SCCB_RX (IRQ_MACHSPEC | 44)
-#define IRQ_SCCB_SPCOND (IRQ_MACHSPEC | 46)
-#define IRQ_SCCA_TX (IRQ_MACHSPEC | 48)
-#define IRQ_SCCA_STAT (IRQ_MACHSPEC | 50)
-#define IRQ_SCCA_RX (IRQ_MACHSPEC | 52)
-#define IRQ_SCCA_SPCOND (IRQ_MACHSPEC | 54)
+#define IRQ_SCCB_TX (40)
+#define IRQ_SCCB_STAT (42)
+#define IRQ_SCCB_RX (44)
+#define IRQ_SCCB_SPCOND (46)
+#define IRQ_SCCA_TX (48)
+#define IRQ_SCCA_STAT (50)
+#define IRQ_SCCA_RX (52)
+#define IRQ_SCCA_SPCOND (54)
#define INT_CLK 24576 /* CLK while int_clk =2.456MHz and divide = 100 */
static inline void atari_enable_irq( unsigned irq )
{
- irq &= ~IRQ_MACHSPEC;
if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return;
set_mfp_bit( irq, MFP_MASK );
}
static inline void atari_disable_irq( unsigned irq )
{
- irq &= ~IRQ_MACHSPEC;
if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return;
clear_mfp_bit( irq, MFP_MASK );
}
extern inline void atari_turnon_irq( unsigned irq )
{
- irq &= ~IRQ_MACHSPEC;
if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return;
set_mfp_bit( irq, MFP_ENABLE );
}
extern inline void atari_turnoff_irq( unsigned irq )
{
- irq &= ~IRQ_MACHSPEC;
if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return;
clear_mfp_bit( irq, MFP_ENABLE );
clear_mfp_bit( irq, MFP_PENDING );
extern inline void atari_clear_pending_irq( unsigned irq )
{
- irq &= ~IRQ_MACHSPEC;
if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return;
clear_mfp_bit( irq, MFP_PENDING );
}
extern inline int atari_irq_pending( unsigned irq )
{
- irq &= ~IRQ_MACHSPEC;
if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return( 0 );
return( get_mfp_bit( irq, MFP_PENDING ) );
}
#define ATOMIC_INIT { 0 }
#define atomic_read(v) ((v)->counter)
-#define atomic_set(v) (((v)->counter) = i)
+#define atomic_set(v, i) (((v)->counter) = i)
static __inline__ void atomic_add(int i, atomic_t *v)
{
__asm__ __volatile__("subl %1,%0" : : "m" (*v), "id" (i));
}
-static __inline__ void atomic_inc(atomic_t *v)
+static __inline__ void atomic_inc(volatile atomic_t *v)
{
__asm__ __volatile__("addql #1,%0" : : "m" (*v));
}
-static __inline__ void atomic_dec(atomic_t *v)
+static __inline__ void atomic_dec(volatile atomic_t *v)
{
__asm__ __volatile__("subql #1,%0" : : "m" (*v));
}
-static __inline__ int atomic_dec_and_test(atomic_t *v)
+static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
{
char c;
__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c) : "m" (*v));
return c != 0;
}
+#define atomic_clear_mask(mask, v) \
+ __asm__ __volatile__("andl %1,%0" : : "m" (*v), "id" (~(mask)))
+
+#define atomic_set_mask(mask, v) \
+ __asm__ __volatile__("orl %1,%0" : : "m" (*v), "id" (mask));
+
#endif /* __ARCH_M68K_ATOMIC __ */
#define COMPAT_AMIGA_BOOTI_VERSION MK_BI_VERSION( 1, 0 )
#define COMPAT_ATARI_BOOTI_VERSION MK_BI_VERSION( 1, 0 )
-#include <linux/config.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
#define COMPAT_NUM_AUTO 16
#endif
#ifdef __KERNEL__
-#include <linux/config.h>
#include <asm/types.h>
/*
#define __ARCH_M68K_CACHE_H
/* bytes per L1 cache line */
-#define L1_CACHE_BYTES 32 /* a guess */
+#define L1_CACHE_BYTES 16
#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
unsigned int csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum);
+extern unsigned int
+csum_partial_copy_from_user ( const char *src, char *dst,
+ int len, int sum, int *csum_err);
/*
* This is a version of ip_compute_csum() optimized for IP headers,
#endif /* CONFIG_AMIGA */
#ifdef CONFIG_ATARI
+#include <linux/interrupt.h> /* intr_count */
#include <asm/atarihw.h>
#include <asm/atarihdreg.h>
#include <asm/atariints.h>
-/* $Id: ioctl.h,v 1.1 1996/08/24 12:43:44 root Exp $
+/* $Id: ioctl.h,v 1.3 1997/04/16 15:10:07 jes Exp $
*
* linux/ioctl.h for Linux by H.H. Bergman.
*/
#ifndef _M68K_IRQ_H_
#define _M68K_IRQ_H_
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
#include <linux/config.h>
/*
* Adding an interrupt service routine for a source with this bit
* set indicates a special machine specific interrupt source.
* The machine specific files define these sources.
+ *
+ * The IRQ_MACHSPEC bit is now gone - the only thing it did was to
+ * introduce unnecessary overhead.
+ *
+ * All interrupt handling is actually machine specific so it is better
+ * to use function pointers, as used by the Sparc port, and select the
+ * interrupt handling functions when initializing the kernel. This way
+ * we save some unnecessary overhead at run-time.
+ * 01/11/97 - Jes
*/
-#define IRQ_MACHSPEC (0x10000000L)
-#define IRQ_IDX(irq) ((irq) & ~IRQ_MACHSPEC)
+extern void (*enable_irq)(unsigned int);
+extern void (*disable_irq)(unsigned int);
+
+extern int sys_request_irq(unsigned int,
+ void (*)(int, void *, struct pt_regs *),
+ unsigned long, const char *, void *);
+extern void sys_free_irq(unsigned int, void *);
/*
* various flags for request_irq()
extern void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
extern int (*mach_request_irq) (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id);
-extern int (*mach_free_irq) (unsigned int irq, void *dev_id);
-extern void (*mach_enable_irq) (unsigned int irq);
-extern void (*mach_disable_irq) (unsigned int irq);
+extern void (*mach_free_irq) (unsigned int irq, void *dev_id);
extern void (*mach_get_model) (char *model);
extern int (*mach_get_hardware_list) (char *buffer);
extern int (*mach_get_irq_list) (char *buf);
int *min, int *sec);
extern int (*mach_hwclk)(int, struct hwclk_time*);
extern int (*mach_set_clock_mmss)(unsigned long);
-extern void (*mach_mksound)( unsigned int count, unsigned int ticks );
extern void (*mach_reset)( void );
extern int (*mach_floppy_init) (void);
extern unsigned long (*mach_hd_init) (unsigned long, unsigned long);
extern void (*mach_hd_setup)(char *, int *);
-extern void (*waitbut)(void);
extern struct fb_info *(*mach_fb_init)(long *);
extern long mach_max_dma_address;
-extern void (*mach_debug_init)(void);
extern void (*mach_video_setup)(char *, int *);
extern void (*mach_floppy_setup)(char *, int *);
extern void (*mach_floppy_eject)(void);
-extern void (*mach_syms_export)(void);
#endif /* _M68K_MACHDEP_H */
#ifdef __KERNEL__
+#include<linux/config.h>
+
#define STRICT_MM_TYPECHECKS
+/*
+ * We don't need to check for alignment etc.
+ */
+#if defined(CONFIG_OPTIMIZE_040) || defined(CONFIG_OPTIMIZE_060)
+static inline void copy_page(unsigned long to, unsigned long from)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__("1:\t"
+ ".chip 68040\n\t"
+ "move16 %1@+,%0@+\n\t"
+ "move16 %1@+,%0@+\n\t"
+ ".chip 68k\n\t"
+ "dbra %2,1b\n\t"
+ : "=a" (to), "=a" (from), "=d" (tmp)
+ : "0" (to), "1" (from) , "2" (PAGE_SIZE / 32 - 1)
+ );
+}
+
+static inline void clear_page(unsigned long page)
+{
+ unsigned long data, sp, tmp;
+
+ sp = page;
+
+ data = 0;
+
+ *((unsigned long *)(page))++ = 0;
+ *((unsigned long *)(page))++ = 0;
+ *((unsigned long *)(page))++ = 0;
+ *((unsigned long *)(page))++ = 0;
+
+ __asm__ __volatile__("1:\t"
+ ".chip 68040\n\t"
+ "move16 %2@+,%0@+\n\t"
+ ".chip 68k\n\t"
+ "subqw #8,%2\n\t"
+ "subqw #8,%2\n\t"
+ "dbra %1,1b\n\t"
+ : "=a" (page), "=d" (tmp)
+ : "a" (sp), "0" (page),
+ "1" ((PAGE_SIZE - 16) / 16 - 1));
+}
+
+#else
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+#endif
#ifdef STRICT_MM_TYPECHECKS
/*
* the m68k page table tree.
*/
+/* For virtual address to physical address conversion */
+extern unsigned long mm_vtop(unsigned long addr) __attribute__ ((const));
+extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const));
+#define VTOP(addr) (mm_vtop((unsigned long)(addr)))
+#define PTOV(addr) (mm_ptov((unsigned long)(addr)))
+
+/*
+ * Cache handling functions
+ */
+
+#define flush_icache() \
+do { \
+ if (CPU_IS_040_OR_060) \
+ asm __volatile__ ("nop\n\t" \
+ ".chip 68040\n\t" \
+ "cinva %%ic\n\t" \
+ ".chip 68k"); \
+ else { \
+ unsigned long _tmp; \
+ asm __volatile__ ("movec %%cacr,%0\n\t" \
+ "orw %1,%0\n\t" \
+ "movec %0,%%cacr" \
+ : "=&d" (_tmp) \
+ : "id" (FLUSH_I)); \
+ } \
+} while (0)
+
+/*
+ * invalidate the cache for the specified memory range.
+ * It starts at the physical address specified for
+ * the given number of bytes.
+ */
+extern void cache_clear (unsigned long paddr, int len);
+/*
+ * push any dirty cache in the specified memory range.
+ * It starts at the physical address specified for
+ * the given number of bytes.
+ */
+extern void cache_push (unsigned long paddr, int len);
+
+/*
+ * push and invalidate pages in the specified user virtual
+ * memory range.
+ */
+extern void cache_push_v (unsigned long vaddr, int len);
+
+/* cache code */
+#define FLUSH_I_AND_D (0x00000808)
+#define FLUSH_I (0x00000008)
+
+/* This is needed whenever the virtual mapping of the current
+ process changes. */
+#define __flush_cache_all() \
+ do { \
+ if (CPU_IS_040_OR_060) \
+ __asm__ __volatile__ ("nop\n\t" \
+ ".chip 68040\n\t" \
+ "cpusha %dc\n\t" \
+ ".chip 68k"); \
+ else { \
+ unsigned long _tmp; \
+ __asm__ __volatile__ ("movec %%cacr,%0\n\t" \
+ "orw %1,%0\n\t" \
+ "movec %0,%%cacr" \
+ : "=&d" (_tmp) \
+ : "di" (FLUSH_I_AND_D)); \
+ } \
+ } while (0)
+
+#define __flush_cache_030() \
+ do { \
+ if (CPU_IS_020_OR_030) { \
+ unsigned long _tmp; \
+ __asm__ __volatile__ ("movec %%cacr,%0\n\t" \
+ "orw %1,%0\n\t" \
+ "movec %0,%%cacr" \
+ : "=&d" (_tmp) \
+ : "di" (FLUSH_I_AND_D)); \
+ } \
+ } while (0)
+
+#define flush_cache_all() __flush_cache_all()
+
+extern inline void flush_cache_mm(struct mm_struct *mm)
+{
+#if FLUSH_VIRTUAL_CACHE_040
+ if (mm == current->mm) __flush_cache_all();
+#else
+ if (mm == current->mm) __flush_cache_030();
+#endif
+}
+
+extern inline void flush_cache_range(struct mm_struct *mm,
+ unsigned long start,
+ unsigned long end)
+{
+ if (mm == current->mm){
+#if FLUSH_VIRTUAL_CACHE_040
+ if (CPU_IS_040_OR_060)
+ cache_push_v(start, end-start);
+ else
+#endif
+ __flush_cache_030();
+ }
+}
+
+extern inline void flush_cache_page(struct vm_area_struct *vma,
+ unsigned long vmaddr)
+{
+ if (vma->vm_mm == current->mm){
+#if FLUSH_VIRTUAL_CACHE_040
+ if (CPU_IS_040_OR_060)
+ cache_push_v(vmaddr, PAGE_SIZE);
+ else
+#endif
+ __flush_cache_030();
+ }
+}
+
+/* Push the page at kernel virtual address and clear the icache */
+extern inline void flush_page_to_ram (unsigned long address)
+{
+ if (CPU_IS_040_OR_060) {
+ __asm__ __volatile__ ("nop\n\t"
+ ".chip 68040\n\t"
+ "cpushp %%dc,(%0)\n\t"
+ "cinvp %%ic,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (VTOP(address)));
+ }
+ else {
+ unsigned long _tmp;
+ __asm volatile ("movec %%cacr,%0\n\t"
+ "orw %1,%0\n\t"
+ "movec %0,%%cacr"
+ : "=&d" (_tmp)
+ : "di" (FLUSH_I));
+ }
+}
+
+/* Push n pages at kernel virtual address and clear the icache */
+extern inline void flush_pages_to_ram (unsigned long address, int n)
+{
+ if (CPU_IS_040_OR_060) {
+ while (n--) {
+ __asm__ __volatile__ ("nop\n\t"
+ ".chip 68040\n\t"
+ "cpushp %%dc,(%0)\n\t"
+ "cinvp %%ic,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (VTOP(address)));
+ address += PAGE_SIZE;
+ }
+ }
+ else {
+ unsigned long _tmp;
+ __asm volatile ("movec %%cacr,%0\n\t"
+ "orw %1,%0\n\t"
+ "movec %0,%%cacr"
+ : "=&d" (_tmp)
+ : "di" (FLUSH_I));
+ }
+}
+
/*
* flush all atc entries (user-space entries only for the 680[46]0).
*/
".chip 68k"
: : "a" (addr));
} else
- __asm__ __volatile__("pflush #0,#0,(%0)" : : "a" (addr));
+ __asm__ __volatile__("pflush #0,#4,(%0)" : : "a" (addr));
}
#define flush_tlb() __flush_tlb()
__flush_tlb();
}
+extern inline void flush_tlb_kernel_page(unsigned long addr)
+{
+ if (CPU_IS_040_OR_060) {
+ unsigned long old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ __asm__ __volatile__(".chip 68040\n\t"
+ "pflush (%0)\n\t"
+ ".chip 68k"
+ : : "a" (addr));
+ set_fs(old_fs);
+ } else
+ __asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr));
+}
+
/* Certain architectures need to do special things when pte's
* within a page table are directly modified. Thus, the following
* hook is made available.
*/
#define set_pte(pteptr, pteval) \
do{ \
- *(pteptr) = (pteval); \
- if (CPU_IS_060) \
- __asm__ __volatile__(".chip 68060\n\t" \
- "pflusha\n\t" \
- ".chip 68k"); \
+ *(pteptr) = (pteval); \
} while(0)
* and initialized in head.S */
extern int m68k_pgtable_cachemode;
-#if defined(CONFIG_M68040_OR_M68060_ONLY)
+#if defined(CPU_M68040_OR_M68060_ONLY)
#define mm_cachebits _PAGE_CACHE040
-#elif defined(CONFIG_M68020_OR_M68030_ONLY)
+#elif defined(CPU_M68020_OR_M68030_ONLY)
#define mm_cachebits 0
#else
extern unsigned long mm_cachebits;
#define PAGE_PTR(address) \
((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-/* For virtual address to physical address conversion */
-extern unsigned long mm_vtop(unsigned long addr) __attribute__ ((const));
-extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const));
-#define VTOP(addr) (mm_vtop((unsigned long)(addr)))
-#define PTOV(addr) (mm_ptov((unsigned long)(addr)))
-
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
* if any.
*/
-extern inline void nocache_page (unsigned long vaddr)
+/* Prior to calling these routines, the page should have been flushed
+ * from both the cache and ATC, or the CPU might not notice that the
+ * cache setting for the page has been changed. -jskov
+ */
+static inline void nocache_page (unsigned long vaddr)
{
if (CPU_IS_040_OR_060) {
pgd_t *dir;
pmd_t *pmdp;
pte_t *ptep;
- if(CPU_IS_060)
- __asm__ __volatile__ (".chip 68060\n\t"
- "cpushp (%0)\n\t"
- ".chip 68k"
- : : "a" (VTOP(vaddr)));
-
dir = pgd_offset_k(vaddr);
pmdp = pmd_offset(dir,vaddr);
ptep = pte_offset(pmdp,vaddr);
if (pmd_none(*pmd)) {
if (page) {
memset((void *) page, 0, PAGE_SIZE);
+ flush_page_to_ram((unsigned long)page);
+ flush_tlb_kernel_page((unsigned long)page);
nocache_page((unsigned long)page);
pmd_set(pmd,page);
return page + address;
pte_t * page = (pte_t *) get_free_page(GFP_KERNEL);
if (pmd_none(*pmd)) {
if (page) {
+ flush_tlb_kernel_page((unsigned long)page);
nocache_page((unsigned long)page);
pmd_set(pmd, page);
return page + address;
return (pgd_t *)get_pointer_table ();
}
-#define flush_icache() \
-do { \
- if (CPU_IS_040_OR_060) \
- asm __volatile__ ("nop\n\t" \
- ".chip 68040\n\t" \
- "cinva %%ic\n\t" \
- ".chip 68k"); \
- else { \
- unsigned long _tmp; \
- asm __volatile__ ("movec %%cacr,%0\n\t" \
- "orw %1,%0\n\t" \
- "movec %0,%%cacr" \
- : "=&d" (_tmp) \
- : "id" (FLUSH_I)); \
- } \
-} while (0)
-
-/*
- * invalidate the cache for the specified memory range.
- * It starts at the physical address specified for
- * the given number of bytes.
- */
-extern void cache_clear (unsigned long paddr, int len);
-/*
- * push any dirty cache in the specified memory range.
- * It starts at the physical address specified for
- * the given number of bytes.
- */
-extern void cache_push (unsigned long paddr, int len);
-
-/*
- * push and invalidate pages in the specified user virtual
- * memory range.
- */
-extern void cache_push_v (unsigned long vaddr, int len);
-
-/* cache code */
-#define FLUSH_I_AND_D (0x00000808)
-#define FLUSH_I (0x00000008)
-
-/* This is needed whenever the virtual mapping of the current
- process changes. */
-#define __flush_cache_all() \
- do { \
- if (CPU_IS_040_OR_060) \
- __asm__ __volatile__ ("nop\n\t" \
- ".chip 68040\n\t" \
- "cpusha %dc\n\t" \
- ".chip 68k"); \
- else { \
- unsigned long _tmp; \
- __asm__ __volatile__ ("movec %%cacr,%0\n\t" \
- "orw %1,%0\n\t" \
- "movec %0,%%cacr" \
- : "=&d" (_tmp) \
- : "di" (FLUSH_I_AND_D)); \
- } \
- } while (0)
-
-#define __flush_cache_030() \
- do { \
- if (CPU_IS_020_OR_030) { \
- unsigned long _tmp; \
- __asm__ __volatile__ ("movec %%cacr,%0\n\t" \
- "orw %1,%0\n\t" \
- "movec %0,%%cacr" \
- : "=&d" (_tmp) \
- : "di" (FLUSH_I_AND_D)); \
- } \
- } while (0)
-
-#define flush_cache_all() __flush_cache_all()
-
-extern inline void flush_cache_mm(struct mm_struct *mm)
-{
-#if FLUSH_VIRTUAL_CACHE_040
- if (mm == current->mm) __flush_cache_all();
-#else
- if (mm == current->mm) __flush_cache_030();
-#endif
-}
-
-extern inline void flush_cache_range(struct mm_struct *mm,
- unsigned long start,
- unsigned long end)
-{
- if (mm == current->mm){
-#if FLUSH_VIRTUAL_CACHE_040
- if (CPU_IS_040_OR_060)
- cache_push_v(start, end-start);
- else
-#endif
- __flush_cache_030();
- }
-}
-
-extern inline void flush_cache_page(struct vm_area_struct *vma,
- unsigned long vmaddr)
-{
- if (vma->vm_mm == current->mm){
-#if FLUSH_VIRTUAL_CACHE_040
- if (CPU_IS_040_OR_060)
- cache_push_v(vmaddr, PAGE_SIZE);
- else
-#endif
- __flush_cache_030();
- }
-}
-
-/* Push the page at kernel virtual address and clear the icache */
-extern inline void flush_page_to_ram (unsigned long address)
-{
- if (CPU_IS_040_OR_060) {
- __asm__ __volatile__ ("nop\n\t"
- ".chip 68040\n\t"
- "cpushp %%dc,(%0)\n\t"
- "cinvp %%ic,(%0)\n\t"
- ".chip 68k"
- : : "a" (VTOP(address)));
- }
- else {
- unsigned long _tmp;
- __asm volatile ("movec %%cacr,%0\n\t"
- "orw %1,%0\n\t"
- "movec %0,%%cacr"
- : "=&d" (_tmp)
- : "di" (FLUSH_I));
- }
-}
-
-/* Push n pages at kernel virtual address and clear the icache */
-extern inline void flush_pages_to_ram (unsigned long address, int n)
-{
- if (CPU_IS_040_OR_060) {
- while (n--) {
- __asm__ __volatile__ ("nop\n\t"
- ".chip 68040\n\t"
- "cpushp %%dc,(%0)\n\t"
- "cinvp %%ic,(%0)\n\t"
- ".chip 68k"
- : : "a" (VTOP(address)));
- address += PAGE_SIZE;
- }
- }
- else {
- unsigned long _tmp;
- __asm volatile ("movec %%cacr,%0\n\t"
- "orw %1,%0\n\t"
- "movec %0,%%cacr"
- : "=&d" (_tmp)
- : "di" (FLUSH_I));
- }
-}
-
/*
* Check if the addr/len goes up to the end of a physical
* memory chunk. Used for DMA functions.
#define __ASM_M68K_PROCESSOR_H
#include <asm/segment.h>
+#include <asm/fpu.h>
/*
* User space process size: 3.75GB. This is hardcoded into a few places,
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE 0xC0000000UL
/*
* Bus types
#define EISA_bus 0
#define MCA_bus 0
-/* MAX floating point unit state size (FSAVE/FRESTORE) */
-#define FPSTATESIZE (216/sizeof(unsigned char))
-
/*
* if you change this structure, you must change the code and offsets
* in m68k/machasm.S
char * alt_address; /* Location of actual if address is a
* dma indirect buffer. NULL otherwise */
unsigned int length;
-
-#ifdef __sparc__
- char * dvma_address; /* A place to hang host-specific addresses at. */
-#endif
};
+/* This is bogus and should go away. */
#define ISA_DMA_THRESHOLD (0x00ffffff)
#endif /* !(_M68K_SCATTERLIST_H) */
#define _M68K_SEMAPHORE_H
#include <linux/linkage.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
/*
* SMP- and interrupt-safe semaphores..
*/
struct semaphore {
- int count;
- int waiting;
+ atomic_t count;
+ atomic_t waking;
struct wait_queue * wait;
};
-#define MUTEX ((struct semaphore) { 1, 0, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { 0, 0, NULL })
+#define MUTEX ((struct semaphore) { { 1 }, { 0 }, NULL })
+#define MUTEX_LOCKED ((struct semaphore) { { 0 }, { 0 }, NULL })
asmlinkage void __down_failed(void /* special register calling convention */);
+asmlinkage int __down_failed_interruptible(void /* params in registers */);
asmlinkage void __up_wakeup(void /* special register calling convention */);
extern void __down(struct semaphore * sem);
extern void __up(struct semaphore * sem);
-#define sema_init(sem, val) ((sem)->count = val)
+#define sema_init(sem, val) atomic_set(&((sem)->count), val)
+
+static inline void wake_one_more(struct semaphore * sem)
+{
+ atomic_inc(&sem->waking);
+}
static inline int waking_non_zero(struct semaphore *sem)
{
__asm__ __volatile__(
"| atomic down operation\n\t"
"lea %%pc@(1f),%%a0\n\t"
- "subql #1,%0\n\t"
+ "subql #1,%0@\n\t"
"jmi " SYMBOL_NAME_STR(__down_failed) "\n"
"1:"
: /* no outputs */
- : "m" (sem->count), "a" (sem1)
+ : "a" (sem1)
: "%a0", "memory");
}
+/*
+ * This version waits in interruptible state so that the waiting
+ * process can be killed. The down_failed_interruptible routine
+ * returns negative for signalled and zero for semaphore acquired.
+ */
+extern inline int down_interruptible(struct semaphore * sem)
+{
+ register int ret __asm__ ("%d0");
+ register struct semaphore *sem1 __asm__ ("%a1") = sem;
+ __asm__ __volatile__(
+ "| atomic interruptible down operation\n\t"
+ "lea %%pc@(1f),%%a0\n\t"
+ "subql #1,%1@\n\t"
+ "jmi " SYMBOL_NAME_STR(__down_failed_interruptible) "\n\t"
+ "clrl %0\n"
+ "1:"
+ : "=d" (ret)
+ : "a" (sem1)
+ : "%d0", "%a0", "memory");
+ return ret;
+}
+
/*
* Note! This is subtle. We jump to wake people up only if
* the semaphore was negative (== somebody was waiting on it).
*/
struct serial_icounter_struct {
int cts, dsr, rng, dcd;
- int reserved[16];
+ int rx, tx;
+ int frame, overrun, parity, brk;
+ int buf_overrun;
+ int reserved[9];
};
* Counters of the input lines (CTS, DSR, RI, CD) interrupts
*/
struct async_icount {
- __u32 cts, dsr, rng, dcd;
+ __u32 cts, dsr, rng, dcd, tx, rx;
+ __u32 frame, parity, overrun, brk;
+ __u32 buf_overrun;
};
struct async_struct {
static __inline__ void rs_sched_event(struct async_struct *info, int event)
{
info->event |= 1 << event;
- queue_task_irq(&info->tqueue, &tq_serial);
+ queue_task(&info->tqueue, &tq_serial);
mark_bh(SERIAL_BH);
}
}
*tty->flip.flag_buf_ptr++ = err;
*tty->flip.char_buf_ptr++ = ch;
- queue_task_irq(&tty->flip.tqueue, &tq_timer);
+ info->icount.rx++;
+ queue_task(&tty->flip.tqueue, &tq_timer);
}
static __inline__ int rs_get_tx_char( struct async_struct *info )
if (info->x_char) {
ch = info->x_char;
+ info->icount.tx++;
info->x_char = 0;
return( ch );
}
ch = info->xmit_buf[info->xmit_tail++];
info->xmit_tail &= SERIAL_XMIT_SIZE - 1;
+ info->icount.tx++;
if (--info->xmit_cnt < WAKEUP_CHARS)
rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
return( ch );
#ifdef SERIAL_DEBUG_OPEN
printk("scheduling hangup...");
#endif
- queue_task_irq(&info->tqueue_hangup,
- &tq_scheduler);
+ queue_task(&info->tqueue_hangup, &tq_scheduler);
}
}
}
#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
# define MACH_IS_AMIGA (m68k_machtype == MACH_AMIGA)
#else
-# define CONFIG_AMIGA_ONLY
+# define MACH_AMIGA_ONLY
# define MACH_IS_AMIGA (1)
# define MACH_TYPE (MACH_AMIGA)
#endif
#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
# define MACH_IS_ATARI (m68k_machtype == MACH_ATARI)
#else
-# define CONFIG_ATARI_ONLY
+# define MACH_ATARI_ONLY
# define MACH_IS_ATARI (1)
# define MACH_TYPE (MACH_ATARI)
#endif
#elif defined(CONFIG_M68030) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
# define CPU_IS_020 (m68k_cputype & CPU_68020)
#else
-# define CONFIG_M68020_ONLY
+# define CPU_M68020_ONLY
# define CPU_IS_020 (1)
#endif
#elif defined(CONFIG_M68020) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
# define CPU_IS_030 (m68k_cputype & CPU_68030)
#else
-# define CONFIG_M68030_ONLY
+# define CPU_M68030_ONLY
# define CPU_IS_030 (1)
#endif
#elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68060)
# define CPU_IS_040 (m68k_cputype & CPU_68040)
#else
-# define CONFIG_M68040_ONLY
+# define CPU_M68040_ONLY
# define CPU_IS_040 (1)
#endif
#elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68040)
# define CPU_IS_060 (m68k_cputype & CPU_68060)
#else
-# define CONFIG_M68060_ONLY
+# define CPU_M68060_ONLY
# define CPU_IS_060 (1)
#endif
#if !defined(CONFIG_M68020) && !defined(CONFIG_M68030)
# define CPU_IS_020_OR_030 (0)
#else
-# define CONFIG_M68020_OR_M68030
+# define CPU_M68020_OR_M68030
# if defined(CONFIG_M68040) || defined(CONFIG_M68060)
# define CPU_IS_020_OR_030 (!m68k_is040or060)
# else
-# define CONFIG_M68020_OR_M68030_ONLY
+# define CPU_M68020_OR_M68030_ONLY
# define CPU_IS_020_OR_030 (1)
# endif
#endif
#if !defined(CONFIG_M68040) && !defined(CONFIG_M68060)
# define CPU_IS_040_OR_060 (0)
#else
-# define CONFIG_M68040_OR_M68060
+# define CPU_M68040_OR_M68060
# if defined(CONFIG_M68020) || defined(CONFIG_M68030)
# define CPU_IS_040_OR_060 (m68k_is040or060)
# else
-# define CONFIG_M68040_OR_M68060_ONLY
+# define CPU_M68040_OR_M68060_ONLY
# define CPU_IS_040_OR_060 (1)
# endif
#endif
#ifndef _ASM_M68k_SIGCONTEXT_H
#define _ASM_M68k_SIGCONTEXT_H
+#include<asm/fpu.h>
+
struct sigcontext {
unsigned long sc_mask; /* old sigmask */
unsigned long sc_usp; /* old user stack pointer */
unsigned short sc_formatvec;
unsigned long sc_fpregs[2*3]; /* room for two fp registers */
unsigned long sc_fpcntl[3];
- unsigned char sc_fpstate[216];
+ unsigned char sc_fpstate[FPSTATESIZE];
};
#endif
#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC)
/* block out HSYNC on the atari */
-#define sti() __asm__ __volatile__ ("andiw #0xfbff,%/sr": : : "memory")
+#define __sti() __asm__ __volatile__ ("andiw #0xfbff,%/sr": : : "memory")
#else /* portable version */
-#define sti() __asm__ __volatile__ ("andiw #0xf8ff,%/sr": : : "memory")
+#define __sti() __asm__ __volatile__ ("andiw #0xf8ff,%/sr": : : "memory")
#endif /* machine compilation types */
-#define cli() __asm__ __volatile__ ("oriw #0x0700,%/sr": : : "memory")
+#define __cli() __asm__ __volatile__ ("oriw #0x0700,%/sr": : : "memory")
#define nop() __asm__ __volatile__ ("nop"::)
#define mb() __asm__ __volatile__ ("" : : :"memory")
-#define save_flags(x) \
+#define __save_flags(x) \
__asm__ __volatile__("movew %/sr,%0":"=d" (x) : /* no input */ :"memory")
-#define restore_flags(x) \
+#define __restore_flags(x) \
__asm__ __volatile__("movew %0,%/sr": /* no outputs */ :"d" (x) : "memory")
-#define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
+#define cli() __cli()
+#define sti() __sti()
+#define save_flags(x) __save_flags(x)
+#define restore_flags(x) __restore_flags(x)
#ifndef CONFIG_RMW_INSNS
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
#define B230400 0010003
#define B460800 0010004
#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define N_PPP 3
#define N_STRIP 4
#define N_AX25 5
+#define N_X25 6 /* X.25 async */
#ifdef __KERNEL__
__constant_copy_to_user(to, from, n) : \
__generic_copy_to_user(to, from, n))
+#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
+#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
+
/*
* Copy a null terminated string from userspace.
*/
#define __NR_mremap 163
#define __NR_setresuid 164
#define __NR_getresuid 165
-#define __NR_nfsservctl 166
+#define __NR_query_module 167
+#define __NR_poll 168
+#define __NR_nfsservctl 169
/* user-visible error numbers are in the range -1 - -122: see
<asm-m68k/errno.h> */
#define __syscall_return(type, res) \
do { \
if ((unsigned long)(res) >= (unsigned long)(-125)) { \
- errno = -(res); \
+ /* avoid using res which is declared to be in register d0; \
+ errno might expand to a function call and clobber it. */ \
+ int __err = -(res); \
+ errno = __err; \
res = -1; \
} \
return (type) (res); \
#define _M68K_USER_H
#include <asm/page.h>
-#include <linux/ptrace.h>
+
/* Core file format: The core file is written in such a way that gdb
can understand it and provide useful information to the user (under
linux we use the 'trad-core' bfd). There are quite a number of
esp register. */
long int signal; /* Signal that caused the core dump. */
int reserved; /* No longer used */
- struct pt_regs * u_ar0; /* Used by gdb to help find the values for */
+ struct user_regs_struct *u_ar0;
+ /* Used by gdb to help find the values for */
/* the registers. */
struct user_m68kfp_struct* u_fpstate; /* Math Co-processor pointer. */
unsigned long magic; /* To uniquely identify a core file */
#define _ASM_PPC_ATOMIC_H_
typedef struct { int counter; } atomic_t;
-#define ATOMIC_INIT { 0 }
+#define ATOMIC_INIT(i) { (i) }
/*
* Make sure gcc doesn't try to be clever and move things around
struct wait_queue * wait;
};
-#define MUTEX ((struct semaphore) { 1, 0, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { 0, 0, NULL })
+#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
+#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
extern void __down(struct semaphore * sem);
extern void __up(struct semaphore * sem);
typedef struct { int counter; } atomic_t;
#endif
-#define ATOMIC_INIT { 0 }
+#define ATOMIC_INIT(i) { (i << 8) }
#ifdef __KERNEL__
#include <asm/system.h>
-/* $Id: errno.h,v 1.5 1996/07/13 02:05:13 tridge Exp $ */
+/* $Id: errno.h,v 1.6 1997/04/15 09:03:38 davem Exp $ */
#ifndef _SPARC_ERRNO_H
#define _SPARC_ERRNO_H
#define ELIBMAX 123 /* Atmpt to link in too many shared libs */
#define ELIBSCN 124 /* .lib section in a.out corrupted */
+#define ENOMEDIUM 125 /* No medium found */
+#define EMEDIUMTYPE 126 /* Wrong medium type */
+
#endif
#define FBTYPE_LASTPLUSONE 21 /* This is not last + 1 in fact... */
+/* Does not seem to be listed in the Sun file either */
+#define FBTYPE_CREATOR 22
+
/* fbio ioctls */
/* Returned by FBIOGTYPE */
struct fbtype {
#ifndef _SPARC_INIT_H
#define _SPARC_INIT_H
-#ifndef __init
-#if (defined (__svr4__) || defined (__ELF__)) && !defined (MODULE)
+#if (defined (__svr4__) || defined (__ELF__))
#define __init __attribute__ ((__section__ (".text.init")))
#define __initdata __attribute__ ((__section__ (".data.init")))
#define __initfunc(__arginit) \
#define __FINIT
#define __INITDATA
#endif
-#endif
#endif
-/* $Id: irq.h,v 1.15 1997/04/14 05:39:28 davem Exp $
+/* $Id: irq.h,v 1.16 1997/04/15 09:03:40 davem Exp $
* irq.h: IRQ registers on the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
extern void (*enable_irq)(unsigned int);
extern void (*disable_pil_irq)(unsigned int);
extern void (*enable_pil_irq)(unsigned int);
-extern void (*clear_clock_irq)( void );
-extern void (*clear_profile_irq)( void );
-extern void (*load_profile_irq)( unsigned int timeout );
+extern void (*clear_clock_irq)(void);
+extern void (*clear_profile_irq)(int);
+extern void (*load_profile_irq)(int cpu, unsigned int timeout);
extern void (*init_timers)(void (*lvl10_irq)(int, void *, struct pt_regs *));
extern void claim_ticker14(void (*irq_handler)(int, void *, struct pt_regs *),
int irq,
-/* $Id: pgtable.h,v 1.59 1997/04/10 05:13:23 davem Exp $ */
+/* $Id: pgtable.h,v 1.60 1997/04/14 17:05:16 jj Exp $ */
#ifndef _SPARC_PGTABLE_H
#define _SPARC_PGTABLE_H
#define add_to_free_ctxlist(entry) add_to_ctx_list(&ctx_free, entry)
#define add_to_used_ctxlist(entry) add_to_ctx_list(&ctx_used, entry)
+extern __inline__ unsigned int
+__get_phys (unsigned long addr)
+{
+ switch (sparc_cpu_model){
+ case sun4c:
+ return sun4c_get_pte (addr) << PAGE_SHIFT;
+ case sun4m:
+ return ((srmmu_get_pte (addr) & 0xffffff00) << 4);
+ default:
+ return 0;
+ }
+}
+
+extern __inline__ int
+__get_iospace (unsigned long addr)
+{
+ switch (sparc_cpu_model){
+ case sun4c:
+ return -1; /* Don't check iospace on sun4c */
+ case sun4m:
+ return (srmmu_get_pte (addr) >> 28);
+ default:
+ return -1;
+ }
+}
+
#endif /* !(_SPARC_PGTABLE_H) */
struct wait_queue * wait;
};
-#define MUTEX ((struct semaphore) { { (1 << 8) }, { 0 }, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { { 0 }, { 0 }, NULL })
+#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
+#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
extern void __down(struct semaphore * sem);
extern int __down_interruptible(struct semaphore * sem);
#define sema_init(sem, val) atomic_set(&((sem)->count), val)
+#define wake_one_more(sem) atomic_inc(&sem->waking);
+
+/* XXX Put this in raw assembler for SMP case so that the atomic_t
+ * XXX spinlock can allow this to be done without grabbing the IRQ
+ * XXX global lock.
+ */
static inline int waking_non_zero(struct semaphore *sem)
{
unsigned long flags;
return cpuid;
}
-extern __volatile__ int smp_process_available;
-
-extern __inline__ int smp_swap(volatile int *addr, int value)
-{
- __asm__ __volatile__("swap [%2], %0\n\t" :
- "=&r" (value) :
- "0" (value), "r" (addr));
- return value;
-}
-
-extern __inline__ __volatile__ void inc_smp_counter(volatile int *ctr)
-{
- int tmp;
-
- while((tmp = smp_swap(ctr, -1)) == -1)
- while(*ctr == -1)
- ;
-
- *ctr = (tmp + 1);
-}
-
-extern __inline__ __volatile__ void dec_smp_counter(volatile int *ctr)
-{
- int tmp;
-
- while((tmp = smp_swap(ctr, -1)) == -1)
- while(*ctr == -1)
- ;
-
- *ctr = (tmp - 1);
-}
-
-extern __inline__ __volatile__ int read_smp_counter(volatile int *ctr)
-{
- int value;
-
- while((value = *ctr) == -1)
- ;
-
- return value;
-}
-
#endif /* !(__ASSEMBLY__) */
/* Sparc specific messages. */
#define MBOX_IDLECPU2 0xFD
#define MBOX_STOPCPU2 0xFE
-#define NO_PROC_ID 0xFF
-
#define PROC_CHANGE_PENALTY 20
#define SMP_FROM_INT 1
#endif /* !(__SMP__) */
+#define NO_PROC_ID 0xFF
+
#endif /* !(_SPARC_SMP_H) */
#define lock_kernel() do { } while(0)
#define unlock_kernel() do { } while(0)
#define release_kernel_lock(task, cpu, depth) ((depth) = 1)
-#define reaquire_kernel_lock(task, cpu, depth) do { } while(0)
+#define reacquire_kernel_lock(task, cpu, depth) do { } while(0)
#else
} while(0)
/* Do not fuck with this without consulting arch/sparc/lib/locks.S first! */
-#define reaquire_kernel_lock(task, cpu, depth) \
+#define reacquire_kernel_lock(task, cpu, depth) \
do { \
if(depth) { \
register struct klock_info *klip asm("g1"); \
klip = &klock_info; \
proc = cpu; \
__asm__ __volatile__("mov %%o7, %%g4\n\t" \
- "call ___lock_reaquire_kernel\n\t" \
+ "call ___lock_reacquire_kernel\n\t" \
" mov %2, %%g2" \
: /* No outputs. */ \
: "r" (klip), "r" (proc), "r" (depth) \
#define spin_lock_irqsave(lock, flags) save_and_cli(flags)
#define spin_unlock_irqrestore(lock, flags) restore_flags(flags)
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+typedef struct { } rwlock_t;
+#define RW_LOCK_UNLOCKED { }
+
+#define read_lock(lock) do { } while(0)
+#define read_unlock(lock) do { } while(0)
+#define write_lock(lock) do { } while(0)
+#define write_unlock(lock) do { } while(0)
+#define read_lock_irq(lock) cli()
+#define read_unlock_irq(lock) sti()
+#define write_lock_irq(lock) cli()
+#define write_unlock_irq(lock) sti()
+
+#define read_lock_irqsave(lock, flags) save_and_cli(flags)
+#define read_unlock_irqrestore(lock, flags) restore_flags(flags)
+#define write_lock_irqsave(lock, flags) save_and_cli(flags)
+#define write_unlock_irqrestore(lock, flags) restore_flags(flags)
+
#else /* !(__SMP__) */
#include <asm/psr.h>
typedef unsigned char spinlock_t;
#define SPIN_LOCK_UNLOCKED 0
+#define spin_lock_init(lock) (*(lock) = 0)
+
extern __inline__ void spin_lock(spinlock_t *lock)
{
register spinlock_t *lp asm("g1");
: "memory", "cc");
}
+/* Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ *
+ * XXX This might create some problems with my dual spinlock
+ * XXX scheme, deadlocks etc. -DaveM
+ */
+typedef struct { volatile unsigned int lock; } rwlock_t;
+
+#define RW_LOCK_UNLOCKED { 0 }
+
+/* Sort of like atomic_t's on Sparc, but even more clever.
+ *
+ * ------------------------------------
+ * | 16-bit counter | clock | wlock | rwlock_t
+ * ------------------------------------
+ * 31 16 15 8 7 0
+ *
+ * wlock signifies the one writer is in, the clock protects
+ * counter bumping, however a reader must acquire wlock
+ * before he can bump the counter on a read_lock().
+ * Similarly a writer, once he has the wlock, must await
+ * for the top 24 bits to all clear before he can finish
+ * going in (this includes the clock of course).
+ *
+ * Unfortunately this scheme limits us to ~65,000 cpus.
+ */
+extern __inline__ void read_lock(rwlock_t *rw)
+{
+ register rwlock_t *lp asm("g1");
+ lp = rw;
+ __asm__ __volatile__("
+ mov %%o7, %%g4
+ call ___rw_read_enter
+ ldstub [%%g1 + 3], %%g2
+" : /* no outputs */
+ : "r" (lp)
+ : "g2", "g4", "g7", "memory", "cc");
+}
+
+extern __inline__ void read_unlock(rwlock_t *rw)
+{
+ register rwlock_t *lp asm("g1");
+ lp = rw;
+ __asm__ __volatile__("
+ mov %%o7, %%g4
+ call ___rw_read_exit
+ ldstub [%%g1 + 2], %%g2
+" : /* no outputs */
+ : "r" (lp)
+ : "g2", "g4", "g7", "memory", "cc");
+}
+
+extern __inline__ void write_lock(rwlock_t *rw)
+{
+ register rwlock_t *lp asm("g1");
+ lp = rw;
+ __asm__ __volatile__("
+ mov %%o7, %%g4
+ call ___rw_write_enter
+ ldstub [%%g1 + 3], %%g2
+" : /* no outputs */
+ : "r" (lp)
+ : "g2", "g4", "g7", "memory", "cc");
+}
+
+#define write_unlock(rw) do { (rw)->lock = 0; } while(0)
+#define read_lock_irq(lock) do { __cli(); read_lock(lock); } while (0)
+#define read_unlock_irq(lock) do { read_unlock(lock); __sti(); } while (0)
+#define write_lock_irq(lock) do { __cli(); write_lock(lock); } while (0)
+#define write_unlock_irq(lock) do { write_unlock(lock); __sti(); } while (0)
+
+#define read_lock_irqsave(lock, flags) \
+ do { __save_and_cli(flags); read_lock(lock); } while (0)
+#define read_unlock_irqrestore(lock, flags) \
+ do { read_unlock(lock); __restore_flags(flags); } while (0)
+#define write_lock_irqsave(lock, flags) \
+ do { __save_and_cli(flags); write_lock(lock); } while (0)
+#define write_unlock_irqrestore(lock, flags) \
+ do { write_unlock(lock); __restore_flags(flags); } while (0)
+
#endif /* __SMP__ */
#endif /* !(__ASSEMBLY__) */
-/* $Id: system.h,v 1.56 1997/04/14 05:39:30 davem Exp $ */
+/* $Id: system.h,v 1.57 1997/04/15 09:03:45 davem Exp $ */
#ifndef __SPARC_SYSTEM_H
#define __SPARC_SYSTEM_H
"rd %%wim, %%g5\n\t" \
"wr %%g4, 0x20, %%psr\n\t" \
"nop\n\t" \
- "mov %5, %%g7\n\t" \
"std %%g4, [%%g6 + %2]\n\t" \
- "st %%g7, [%%g6 + %6]\n\t" \
"ldd [%1 + %2], %%g4\n\t" \
"mov %1, %%g6\n\t" \
"st %1, [%0]\n\t" \
" nop\n\t" : : "r" (&(current_set[smp_processor_id()])), "r" (next), \
"i" ((const unsigned long)(&((struct task_struct *)0)->tss.kpsr)), \
"i" ((const unsigned long)(&((struct task_struct *)0)->tss.ksp)), \
- "r" (task_pc), "i" (255), \
- "i" ((const unsigned long)(&((struct task_struct *)0)->processor)) \
+ "r" (task_pc) \
: "g1", "g2", "g3", "g4", "g5", "g7", "l2", "l3", \
"l4", "l5", "l6", "l7", "i0", "i1", "i2", "i3", "i4", "i5", "o0", "o1", "o2", \
"o3"); \
-/* $Id: atomic.h,v 1.13 1997/04/14 06:56:57 davem Exp $
+/* $Id: atomic.h,v 1.14 1997/04/16 05:57:06 davem Exp $
* atomic.h: Thankfully the V9 is at least reasonable for this
* stuff.
*
#define __atomic_fool_gcc(x) ((struct { int a[100]; } *)x)
typedef struct { int counter; } atomic_t;
-#define ATOMIC_INIT { 0 }
+#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter)
#define atomic_set(v, i) (((v)->counter) = i)
-/* $Id: errno.h,v 1.1 1996/11/20 15:27:39 davem Exp $ */
+/* $Id: errno.h,v 1.2 1997/04/15 12:46:11 jj Exp $ */
#ifndef _SPARC64_ERRNO_H
#define _SPARC64_ERRNO_H
#define ELIBMAX 123 /* Atmpt to link in too many shared libs */
#define ELIBSCN 124 /* .lib section in a.out corrupted */
+#define ENOMEDIUM 125 /* No medium found */
+#define EMEDIUMTYPE 126 /* Wrong medium type */
+
#endif /* !(_SPARC64_ERRNO_H) */
#define FBTYPE_LASTPLUSONE 21 /* This is not last + 1 in fact... */
+/* Does not seem to be listed in the Sun file either */
+#define FBTYPE_CREATOR 22
+
/* fbio ioctls */
/* Returned by FBIOGTYPE */
struct fbtype {
-/* $Id: fcntl.h,v 1.2 1997/04/04 00:50:15 davem Exp $ */
+/* $Id: fcntl.h,v 1.3 1997/04/14 17:05:20 jj Exp $ */
#ifndef _SPARC64_FCNTL_H
#define _SPARC64_FCNTL_H
blocking */
#define LOCK_UN 8 /* remove lock */
-/* XXX 32-bit binary compatability item... -DaveM */
struct flock {
short l_type;
short l_whence;
short __unused;
};
+#ifdef __KERNEL__
+struct flock32 {
+ short l_type;
+ short l_whence;
+ __kernel_off_t32 l_start;
+ __kernel_off_t32 l_len;
+ __kernel_pid_t32 l_pid;
+ short __unused;
+};
+#endif
+
#endif /* !(_SPARC64_FCNTL_H) */
-#ifndef _SPARC64_INIT_H
-#define _SPARC64_INIT_H
+#ifndef _SPARC_INIT_H
+#define _SPARC_INIT_H
-#ifndef __init
-/* 'cause of buggy linker, we don't use this for now... */
-#if 0 && !defined (MODULE)
#define __init __attribute__ ((__section__ (".text.init")))
#define __initdata __attribute__ ((__section__ (".data.init")))
#define __initfunc(__arginit) \
#define __INIT .section ".text.init",#alloc,#execinstr
#define __FINIT .previous
#define __INITDATA .section ".data.init",#alloc,#write
-#else
-#define __init
-#define __initdata
-#define __initfunc(__arginit) __arginit
-/* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
-#endif
-#endif
#endif
/*
* These are used to wrap system calls on the sparc.
*
- * See arch/sparc64/kernel/sys_sparc.c for ugly details..
+ * See arch/sparc64/kernel/sys_sparc32.c for ugly details..
*/
-/* XXX 32-bit binary compatability... */
struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
+ u32 msgp;
+ s32 msgtyp;
};
#define SEMOP 1
#define SHMGET 23
#define SHMCTL 24
-#define IPCCALL(version,op) ((version)<<16 | (op))
+/* We don't need to maintain backward compatibility on 64bit, we've started fresh */
+#define IPCCALL(version,op) (op)
#endif
-/* $Id: pgtable.h,v 1.27 1997/04/10 23:32:46 davem Exp $
+/* $Id: pgtable.h,v 1.28 1997/04/14 17:05:19 jj Exp $
* pgtable.h: SpitFire page table operations.
*
* Copyright 1996 David S. Miller (davem@caip.rutgers.edu)
#define SWP_OFFSET(entry) ((entry) >> (PAGE_SHIFT+8))
#define SWP_ENTRY(type,offset) pte_val(mk_swap_pte((type),(offset)))
+extern __inline__ unsigned long
+sun4u_get_pte (unsigned long addr)
+{
+ pgd_t *pgdp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+
+ pgdp = pgd_offset (current->mm, addr);
+ pmdp = pmd_offset (pgdp, addr);
+ ptep = pte_offset (pmdp, addr);
+ return pte_val (*ptep) & _PAGE_PADDR;
+}
+
+extern __inline__ unsigned int
+__get_phys (unsigned long addr)
+{
+ return (sun4u_get_pte (addr) & 0x0fffffff);
+}
+
+extern __inline__ int
+__get_iospace (unsigned long addr)
+{
+ return ((sun4u_get_pte (addr) & 0xf0000000) >> 28);
+}
+
#endif /* !(__ASSEMBLY__) */
#endif /* !(_SPARC64_PGTABLE_H) */
int val[2];
} __kernel_fsid_t;
+/* Now 32bit compatibility types */
+typedef unsigned int __kernel_size_t32;
+typedef int __kernel_ssize_t32;
+typedef int __kernel_ptrdiff_t32;
+typedef int __kernel_time_t32;
+typedef int __kernel_clock_t32;
+typedef int __kernel_pid_t32;
+typedef unsigned short __kernel_ipc_pid_t32;
+typedef unsigned short __kernel_uid_t32;
+typedef unsigned short __kernel_gid_t32;
+typedef unsigned short __kernel_dev_t32;
+typedef unsigned int __kernel_ino_t32;
+typedef unsigned short __kernel_mode_t32;
+typedef unsigned short __kernel_umode_t32;
+typedef short __kernel_nlink_t32;
+typedef int __kernel_daddr_t32;
+typedef int __kernel_off_t32;
+typedef unsigned int __kernel_caddr_t32;
+typedef long __kernel_loff_t32;
+typedef __kernel_fsid_t __kernel_fsid_t32;
+
#undef __FD_SET
static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
{
-/* $Id: processor.h,v 1.20 1997/04/11 22:34:54 davem Exp $
+/* $Id: processor.h,v 1.21 1997/04/14 17:05:18 jj Exp $
* include/asm-sparc64/processor.h
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
"stx %%g0, [%0 + %2 + 0x68]\n\t" \
"stx %1, [%0 + %2 + 0x70]\n\t" \
"stx %%g0, [%0 + %2 + 0x78]\n\t" \
+ "wrpr %%g0, 1, %%wstate\n\t" \
: \
: "r" (regs), "r" (sp - REGWIN_SZ), \
"i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
"stx %%g0, [%0 + %2 + 0x68]\n\t" \
"stx %1, [%0 + %2 + 0x70]\n\t" \
"stx %%g0, [%0 + %2 + 0x78]\n\t" \
+ "wrpr %%g0, 2, %%wstate\n\t" \
: \
: "r" (regs), "r" (sp - REGWIN32_SZ), \
"i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0])), \
#define _SPARC64_SEMAPHORE_H
/* These are actually reasonable on the V9. */
+#ifdef __KERNEL__
#include <asm/atomic.h>
+#include <asm/system.h>
struct semaphore {
atomic_t count;
struct wait_queue * wait;
};
-#define MUTEX ((struct semaphore) { { 1 }, { 0 }, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { { 0 }, { 0 }, NULL })
+#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
+#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
extern void __down(struct semaphore * sem);
extern int __down_interruptible(struct semaphore * sem);
#define sema_init(sem, val) atomic_set(&((sem)->count), val)
+#define wake_one_more(sem) atomic_inc(&sem->waking);
+
+extern __inline__ int waking_non_zero(struct semaphore *sem)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ save_flags(flags);
+ cli();
+ if (atomic_read(&sem->waking) > 0) {
+ atomic_dec(&sem->waking);
+ ret = 1;
+ }
+ restore_flags(flags);
+ return ret;
+}
+
extern __inline__ void down(struct semaphore * sem)
{
if (atomic_dec_return(&sem->count) < 0)
__up(sem);
}
+#endif /* __KERNEL__ */
+
#endif /* !(_SPARC64_SEMAPHORE_H) */
extern __volatile__ unsigned long smp_proc_in_lock[NR_CPUS]; /* for computing process time */
-extern __volatile__ int smp_process_available;
-
-extern __inline__ __volatile__ void inc_smp_counter(volatile int *ctr)
-{
- unsigned long temp0, temp1;
-
- __asm__ __volatile__("
- lduw [%2], %0
-1:
- add %0, 1, %1
- cas [%2], %0, %1
- cmp %0, %1
- bne,a,pn %%icc, 1b
- lduw [%2], %0
-2:
- membar #StoreStore | #StoreLoad
-" : "=&r" (temp0), "=&r" (temp1), "=r" (ctr)
- : "ir" (i), "r" (ctr)
- : "cc");
-}
-
-extern __inline__ __volatile__ void dec_smp_counter(volatile int *ctr)
-{
- unsigned long temp0, temp1;
-
- __asm__ __volatile__("
- lduw [%2], %0
-1:
- sub %0, 1, %1
- cas [%2], %0, %1
- cmp %0, %1
- bne,a,pn %%icc, 1b
- lduw [%2], %0
-2:
- membar #StoreStore | #StoreLoad
-" : "=&r" (temp0), "=&r" (temp1), "=r" (ctr)
- : "ir" (i), "r" (ctr)
- : "cc");
-}
-
-extern __inline__ __volatile__ int read_smp_counter(volatile int *ctr)
-{
- return *ctr;
-}
-
#endif /* !(__ASSEMBLY__) */
/* Sparc specific messages. */
#define lock_kernel() do { } while(0)
#define unlock_kernel() do { } while(0)
#define release_kernel_lock(task, cpu, depth) ((depth) = 1)
-#define reaquire_kernel_lock(task, cpu, depth) do { } while(0)
+#define reacquire_kernel_lock(task, cpu, depth) do { } while(0)
#else
#error SMP on sparc64 not supported yet
-/* $Id: stat.h,v 1.1 1996/12/26 14:22:31 davem Exp $ */
+/* $Id: stat.h,v 1.2 1997/04/16 14:52:34 jj Exp $ */
#ifndef _SPARC64_STAT_H
#define _SPARC64_STAT_H
unsigned long st_ctime;
};
-/* XXX Fix this for full backwards 32-bit compat. */
struct stat32 {
- dev_t st_dev;
- ino_t st_ino;
- mode_t st_mode;
- short st_nlink;
- uid_t st_uid;
- gid_t st_gid;
- dev_t st_rdev;
- off_t st_size;
- time_t st_atime;
- unsigned int __unused1;
- time_t st_mtime;
- unsigned int __unused2;
- time_t st_ctime;
- unsigned int __unused3;
- off_t st_blksize;
- off_t st_blocks;
+ __kernel_dev_t32 st_dev;
+ __kernel_ino_t32 st_ino;
+ __kernel_mode_t32 st_mode;
+ short st_nlink;
+ __kernel_uid_t32 st_uid;
+ __kernel_gid_t32 st_gid;
+ __kernel_dev_t32 st_rdev;
+ __kernel_off_t32 st_size;
+ __kernel_time_t32 st_atime;
+ unsigned int __unused1;
+ __kernel_time_t32 st_mtime;
+ unsigned int __unused2;
+ __kernel_time_t32 st_ctime;
+ unsigned int __unused3;
+ __kernel_off_t32 st_blksize;
+ __kernel_off_t32 st_blocks;
unsigned int __unused4[2];
};
-/* $Id: statfs.h,v 1.1 1996/12/26 14:22:40 davem Exp $ */
+/* $Id: statfs.h,v 1.2 1997/04/14 17:05:22 jj Exp $ */
#ifndef _SPARC64_STATFS_H
#define _SPARC64_STATFS_H
#endif
-/* XXX Fix this for full backwards 32-bit compat. */
struct statfs32 {
int f_type;
int f_bsize;
int f_bavail;
int f_files;
int f_ffree;
- __kernel_fsid_t f_fsid;
+ __kernel_fsid_t32 f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_spare[6];
};
* static char linux_logo[] __initdata = { 0x32, 0x36, ... };
*/
+/*
+ * Disable the __initfunc macros if a file that is a part of a
+ * module attempts to use them. We do not want to interfere
+ * with module linking.
+ */
+
+#ifndef MODULE
#include <asm/init.h>
+#else
+#define __init
+#define __initdata
+#define __initfunc(__arginit) __arginit
+/* For assembly routines */
+#define __INIT
+#define __FINIT
+#define __INITDATA
+#endif
#endif
-/* $Id: parport.h,v 1.1.2.5 1997/03/29 21:08:31 phil Exp $ */
+/* $Id: parport.h,v 1.2.6.3 1997/04/16 21:21:03 phil Exp $ */
#ifndef _PARPORT_H_
#define _PARPORT_H_
#include <asm/system.h>
#include <asm/ptrace.h>
+#include <linux/proc_fs.h>
/* Maximum of 8 ports per machine */
#define PARPORT_MAX 8
+/* Magic numbers */
+#define PARPORT_IRQ_NONE -1
+#define PARPORT_DMA_NONE -1
+#define PARPORT_DISABLE -2
+
/* Type classes for Plug-and-Play probe */
typedef enum {
struct ppd *prev;
};
+struct parport_dir{
+ struct proc_dir_entry *entry; /* Directory /proc/parport/X */
+ struct proc_dir_entry *irq; /* IRQ entry /proc/parport/X/irq */
+ struct proc_dir_entry *devices; /* /proc/parport/X/devices */
+ struct proc_dir_entry *hardware; /* /proc/parport/X/hardware */
+ char name[4]; /* /proc/parport/"XXXX" */
+};
+
/* A parallel port */
struct parport {
unsigned int base; /* base address */
unsigned int ecr; /* ECP ECR register */
struct parport *next;
unsigned int flags;
- struct proc_dir_entry *proc_dir;
+ struct parport_dir pdir;
struct parport_device_info probe_info;
+ int speed; /* Max Write in Bytes/s */
};
/* parport_register_port registers a new parallel port at the given address (if
char);
/* Prototypes from parport_procfs */
+extern int parport_proc_init(void);
+extern int parport_proc_cleanup(void);
extern int parport_proc_register(struct parport *pp);
-extern void parport_proc_unregister(struct parport *pp);
+extern int parport_proc_unregister(struct parport *pp);
/* Prototypes from parport_ksyms.c */
extern void dec_parport_count(void);
* _adding_ to the beginning of the run-queue has
* a separate lock).
*/
+extern rwlock_t tasklist_lock;
extern spinlock_t scheduler_lock;
-extern spinlock_t tasklist_lock;
extern void sched_init(void);
extern void show_state(void);
&init_mmap, &init_mmap, MUTEX }
struct signal_struct {
- int count;
- struct sigaction action[32];
+ atomic_t count;
+ struct sigaction action[32];
+ spinlock_t siglock;
};
#define INIT_SIGNALS { \
- 1, \
- { {0,}, } }
+ ATOMIC_INIT(1), \
+ { {0,}, }, \
+ SPIN_LOCK_UNLOCKED }
struct task_struct {
/* these are hardcoded - don't touch */
int processor;
int last_processor;
int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */
+ /* Spinlocks for various pieces or per-task state. */
+ spinlock_t sigmask_lock; /* Protects signal and blocked */
};
/*
p->nr++;
}
-#define REMOVE_LINKS(p) do { \
- spin_lock(&tasklist_lock); \
+#define REMOVE_LINKS(p) do { unsigned long flags; \
+ write_lock_irqsave(&tasklist_lock, flags); \
(p)->next_task->prev_task = (p)->prev_task; \
(p)->prev_task->next_task = (p)->next_task; \
- spin_unlock(&tasklist_lock); \
+ write_unlock_irqrestore(&tasklist_lock, flags); \
if ((p)->p_osptr) \
(p)->p_osptr->p_ysptr = (p)->p_ysptr; \
if ((p)->p_ysptr) \
(p)->p_pptr->p_cptr = (p)->p_osptr; \
} while (0)
-#define SET_LINKS(p) do { \
- spin_lock(&tasklist_lock); \
+#define SET_LINKS(p) do { unsigned long flags; \
+ write_lock_irqsave(&tasklist_lock, flags); \
(p)->next_task = &init_task; \
(p)->prev_task = init_task.prev_task; \
init_task.prev_task->next_task = (p); \
init_task.prev_task = (p); \
- spin_unlock(&tasklist_lock); \
+ write_unlock_irqrestore(&tasklist_lock, flags); \
(p)->p_ysptr = NULL; \
if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \
(p)->p_osptr->p_ysptr = p; \
* (there is some stuff that will be added in the future...)
* I just plan to increment with each new version.
*/
-#define WIRELESS_EXT 4
+#define WIRELESS_EXT 5
/*
* Changes :
*
* V2 to V3
* --------
- * Alan Cox start some imcompatibles changes. I've integrated a bit more.
+ * Alan Cox start some incompatibles changes. I've integrated a bit more.
* - Encryption renamed to Encode to avoid US regulation problems
* - Frequency changed from float to struct to avoid problems on old 386
*
* V3 to V4
* --------
* - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ * - Missing encoding definitions in range
+ * - Access points stuff
*/
/* -------------------------- IOCTL LIST -------------------------- */
#define SIOCSIWSPY 0x8B10 /* set spy addresses */
#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
+/* Access Point manipulation */
+#define SIOCSIWAP 0x8B14 /* set access point hardware addresses */
+#define SIOCGIWAP 0x8B15 /* get access point hardware addresses */
+#define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */
+
/* ------------------------- IOCTL STUFF ------------------------- */
/* The first and the last (range) */
#define SIOCIWFIRST 0x8B00
-#define SIOCIWLAST 0x8B13
+#define SIOCIWLAST 0x8B17
/* Even : get (world access), odd : set (root access) */
#define IW_IS_SET(cmd) (!((cmd) & 0x1))
__u32 misc; /* Others cases */
};
+/*
+ * Encoding information (setting and so on)
+ * Encoding might be hardware encryption, scrambing or others
+ */
+struct iw_encoding
+{
+ __u8 method; /* Algorithm number / key used */
+ __u64 code; /* Data/key used for algorithm */
+};
+
+
/* ------------------------ WIRELESS STATS ------------------------ */
/*
* Wireless statistics (used for /proc/net/wireless)
* 0-1000 = channel
* > 1000 = frequency in Hz */
- struct /* Encoding stuff */
- {
- __u8 method; /* Algorithm number / off */
- __u64 code; /* Data used for algorithm */
- } encoding;
+ struct iw_encoding encoding; /* Encoding stuff */
- __u32 sensitivity; /* signal level threshold */
+ __u32 sensitivity; /* signal level threshold */
+
+ struct sockaddr ap_addr; /* Access point address */
struct /* For all data bigger than 16 octets */
{
__u16 num_channels; /* Number of channels [0; num - 1] */
__u8 num_frequency; /* Number of entry in the list */
struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
-
/* Note : this frequency list doesn't need to fit channel numbers */
- /* Encoder stuff */
-
/* signal level threshold range */
__u32 sensitivity;
/* Quality of link & SNR stuff */
struct iw_quality max_qual; /* Quality of the link */
+
+ /* Encoder stuff */
+ struct iw_encoding max_encoding; /* Encoding max range */
};
/*
unsigned short cong_window;
unsigned short cong_count;
- atomic_t packets_out;
+ int packets_out;
unsigned short shutdown;
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
}
#ifdef CONFIG_BLK_DEV_INITRD
-__initfunc(static int do_linuxrc(void * shell))
+static int do_linuxrc(void * shell)
{
static char *argv[] = { "linuxrc", NULL, };
* be handled immediately (ie non-blocked and untraced)
* and that is ignored (either explicitly or by default)
*/
+ spin_lock_irq(&p->sig->siglock);
if (!(mask & p->blocked) && !(p->flags & PF_PTRACED)) {
/* don't bother with ignored signals (but SIGCHLD is special) */
if (sa->sa_handler == SIG_IGN && sig != SIGCHLD)
- return;
+ goto out;
/* some signals are ignored by default.. (but SIGCONT already did its deed) */
if ((sa->sa_handler == SIG_DFL) &&
(sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH || sig == SIGURG))
- return;
+ goto out;
}
+ spin_lock(&p->sigmask_lock);
p->signal |= mask;
+ spin_unlock(&p->sigmask_lock);
if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
wake_up_process(p);
+out:
+ spin_unlock_irq(&p->sig->siglock);
}
/*
if (p->sig) {
unsigned long mask = 1UL << sig;
struct sigaction *sa = p->sig->action + sig;
+
+ spin_lock_irq(&p->sig->siglock);
+
+ spin_lock(&p->sigmask_lock);
p->signal |= mask;
p->blocked &= ~mask;
+ spin_unlock(&p->sigmask_lock);
+
if (sa->sa_handler == SIG_IGN)
sa->sa_handler = SIG_DFL;
if (p->state == TASK_INTERRUPTIBLE)
wake_up_process(p);
+
+ spin_unlock_irq(&p->sig->siglock);
}
}
-
int send_sig(unsigned long sig,struct task_struct * p,int priv)
{
if (!p || sig > 32)
(current->uid ^ p->suid) && (current->uid ^ p->uid) &&
!suser())
return -EPERM;
- if (!sig)
- return 0;
- /*
- * Forget it if the process is already zombie'd.
- */
- if (!p->sig)
- return 0;
- if ((sig == SIGKILL) || (sig == SIGCONT)) {
- if (p->state == TASK_STOPPED)
- wake_up_process(p);
- p->exit_code = 0;
- p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
- (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
+
+ if (sig && p->sig) {
+ spin_lock_irq(&p->sigmask_lock);
+ if ((sig == SIGKILL) || (sig == SIGCONT)) {
+ if (p->state == TASK_STOPPED)
+ wake_up_process(p);
+ p->exit_code = 0;
+ p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
+ (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
+ }
+ if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
+ p->signal &= ~(1<<(SIGCONT-1));
+ spin_unlock_irq(&p->sigmask_lock);
+
+ /* Actually generate the signal */
+ generate(sig,p);
}
- if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
- p->signal &= ~(1<<(SIGCONT-1));
- /* Actually generate the signal */
- generate(sig,p);
return 0;
}
int fallback;
fallback = -1;
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->session <= 0)
continue;
- if (p->pgrp == pgrp)
- return p->session;
+ if (p->pgrp == pgrp) {
+ fallback = p->session;
+ break;
+ }
if (p->pid == pgrp)
fallback = p->session;
}
+ read_unlock(&tasklist_lock);
return fallback;
}
*/
int kill_pg(int pgrp, int sig, int priv)
{
- struct task_struct *p;
- int err,retval = -ESRCH;
- int found = 0;
+ int retval;
- if (sig<0 || sig>32 || pgrp<=0)
- return -EINVAL;
- for_each_task(p) {
- if (p->pgrp == pgrp) {
- if ((err = send_sig(sig,p,priv)) != 0)
- retval = err;
- else
- found++;
+ retval = -EINVAL;
+ if (sig >= 0 && sig <= 32 && pgrp > 0) {
+ struct task_struct *p;
+ int found = 0;
+
+ retval = -ESRCH;
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (p->pgrp == pgrp) {
+ int err = send_sig(sig,p,priv);
+ if (err != 0)
+ retval = err;
+ else
+ found++;
+ }
}
+ read_unlock(&tasklist_lock);
+ if (found)
+ retval = 0;
}
- return(found ? 0 : retval);
+ return retval;
}
/*
*/
int kill_sl(int sess, int sig, int priv)
{
- struct task_struct *p;
- int err,retval = -ESRCH;
- int found = 0;
+ int retval;
- if (sig<0 || sig>32 || sess<=0)
- return -EINVAL;
- for_each_task(p) {
- if (p->session == sess && p->leader) {
- if ((err = send_sig(sig,p,priv)) != 0)
- retval = err;
- else
- found++;
+ retval = -EINVAL;
+ if (sig >= 0 && sig <= 32 && sess > 0) {
+ struct task_struct *p;
+ int found = 0;
+
+ retval = -ESRCH;
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (p->leader && p->session == sess) {
+ int err = send_sig(sig,p,priv);
+
+ if (err)
+ retval = err;
+ else
+ found++;
+ }
}
+ read_unlock(&tasklist_lock);
+ if (found)
+ retval = 0;
}
- return(found ? 0 : retval);
+ return retval;
}
int kill_proc(int pid, int sig, int priv)
{
- struct task_struct *p;
+ int retval;
- if (sig<0 || sig>32)
- return -EINVAL;
- for_each_task(p) {
- if (p && p->pid == pid)
- return send_sig(sig,p,priv);
+ retval = -EINVAL;
+ if (sig >= 0 && sig <= 32) {
+ struct task_struct *p;
+
+ retval = -ESRCH;
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (p->pid != pid)
+ continue;
+ retval = send_sig(sig,p,priv);
+ break;
+ }
+ read_unlock(&tasklist_lock);
}
- return(-ESRCH);
+ return retval;
}
/*
*/
asmlinkage int sys_kill(int pid,int sig)
{
- int err, retval = 0, count = 0;
+ if (!pid)
+ return kill_pg(current->pgrp,sig,0);
- lock_kernel();
- if (!pid) {
- err = kill_pg(current->pgrp,sig,0);
- goto out;
- }
if (pid == -1) {
+ int retval = 0, count = 0;
struct task_struct * p;
+
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->pid > 1 && p != current) {
+ int err;
++count;
if ((err = send_sig(sig,p,0)) != -EPERM)
retval = err;
}
}
- err = count ? retval : -ESRCH;
- goto out;
- }
- if (pid < 0) {
- err = kill_pg(-pid,sig,0);
- goto out;
+ read_unlock(&tasklist_lock);
+ return count ? retval : -ESRCH;
}
+ if (pid < 0)
+ return kill_pg(-pid,sig,0);
+
/* Normal kill */
- err = kill_proc(pid,sig,0);
-out:
- unlock_kernel();
- return err;
+ return kill_proc(pid,sig,0);
}
/*
{
struct task_struct *p;
+ read_lock(&tasklist_lock);
for_each_task(p) {
if ((p == ignored_task) || (p->pgrp != pgrp) ||
(p->state == TASK_ZOMBIE) ||
(p->p_pptr->pid == 1))
continue;
if ((p->p_pptr->pgrp != pgrp) &&
- (p->p_pptr->session == p->session))
- return 0;
+ (p->p_pptr->session == p->session)) {
+ read_unlock(&tasklist_lock);
+ return 0;
+ }
}
- return(1); /* (sighing) "Often!" */
+ read_unlock(&tasklist_lock);
+ return 1; /* (sighing) "Often!" */
}
int is_orphaned_pgrp(int pgrp)
static inline int has_stopped_jobs(int pgrp)
{
+ int retval = 0;
struct task_struct * p;
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->pgrp != pgrp)
continue;
- if (p->state == TASK_STOPPED)
- return(1);
+ if (p->state != TASK_STOPPED)
+ continue;
+ retval = 1;
+ break;
}
- return(0);
+ read_unlock(&tasklist_lock);
+ return retval;
}
static inline void forget_original_parent(struct task_struct * father)
{
struct task_struct * p;
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->p_opptr == father)
if (task[smp_num_cpus]) /* init */
else
p->p_opptr = task[0];
}
+ read_unlock(&tasklist_lock);
}
static inline void close_files(struct files_struct * files)
if (sig) {
tsk->sig = NULL;
- if (!--sig->count) {
+ if (atomic_dec_and_test(&sig->count))
kfree(sig);
- }
}
}
struct wait_queue wait = { current, NULL };
struct task_struct *p;
- lock_kernel();
if (stat_addr) {
- retval = verify_area(VERIFY_WRITE, stat_addr, sizeof(*stat_addr));
- if (retval)
- goto out;
+ if(verify_area(VERIFY_WRITE, stat_addr, sizeof(*stat_addr)))
+ return -EFAULT;
}
if (ru) {
- retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
- if (retval)
- goto out;
+ if(verify_area(VERIFY_WRITE, ru, sizeof(*ru)))
+ return -EFAULT;
}
- retval = -EINVAL;
+
if (options & ~(WNOHANG|WUNTRACED|__WCLONE))
- goto out;
+ return -EINVAL;
+ lock_kernel();
add_wait_queue(¤t->wait_chldexit,&wait);
repeat:
- flag=0;
+ flag = retval = 0;
for (p = current->p_cptr ; p ; p = p->p_osptr) {
if (pid>0) {
if (p->pid != pid)
retval = -ECHILD;
end_wait4:
remove_wait_queue(¤t->wait_chldexit,&wait);
-out:
unlock_kernel();
return retval;
}
*/
asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options)
{
- int ret;
-
- lock_kernel();
- ret = sys_wait4(pid, stat_addr, options, NULL);
- unlock_kernel();
- return ret;
+ return sys_wait4(pid, stat_addr, options, NULL);
}
#endif
static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk)
{
if (clone_flags & CLONE_SIGHAND) {
- current->sig->count++;
+ atomic_inc(¤t->sig->count);
return 0;
}
tsk->sig = kmalloc(sizeof(*tsk->sig), GFP_KERNEL);
if (!tsk->sig)
return -1;
- tsk->sig->count = 1;
+ spin_lock_init(&tsk->sig->siglock);
+ atomic_set(&tsk->sig->count, 1);
memcpy(tsk->sig->action, current->sig->action, sizeof(tsk->sig->action));
return 0;
}
#include <linux/kernel_stat.h>
#include <linux/mm.h>
#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/ptrace.h>
#include <linux/sys.h>
EXPORT_SYMBOL(num_physpages);
EXPORT_SYMBOL(high_memory);
EXPORT_SYMBOL(update_vm_cache);
+EXPORT_SYMBOL(kmem_cache_create);
+EXPORT_SYMBOL(kmem_cache_destroy);
+EXPORT_SYMBOL(kmem_cache_alloc);
+EXPORT_SYMBOL(kmem_cache_free);
/* filesystem internal functions */
EXPORT_SYMBOL(getname);
EXPORT_SYMBOL(tq_scheduler);
EXPORT_SYMBOL(timer_active);
EXPORT_SYMBOL(timer_table);
+
#ifdef __SMP__
+/* Various random spinlocks we want to export */
+EXPORT_SYMBOL(tqueue_lock);
EXPORT_SYMBOL(waitqueue_lock);
#endif
(p->prev_run = init_task.prev_run)->next_run = p;
p->next_run = &init_task;
init_task.prev_run = p;
-#if 0 /* def __SMP__ */
- /* this is safe only if called with cli()*/
- inc_smp_counter(&smp_process_available);
- if ((0!=p->pid) && smp_threads_ready)
- {
- int i;
- for (i=0;i<smp_num_cpus;i++)
- {
- if (0==current_set[cpu_logical_map[i]]->pid)
- {
- smp_message_pass(cpu_logical_map[i], MSG_RESCHEDULE, 0L, 0);
- break;
- }
- }
- }
-#endif
}
static inline void del_from_runqueue(struct task_struct * p)
}
/*
- * The tasklist_lock protects the linked list of processes
- * and doesn't need to be interrupt-safe as interrupts never
- * use the task-list.
+ * The tasklist_lock protects the linked list of processes.
*
* The scheduler lock is protecting against multiple entry
* into the scheduling code, and doesn't need to worry
* The run-queue lock locks the parts that actually access
* and change the run-queues, and have to be interrupt-safe.
*/
-spinlock_t tasklist_lock = SPIN_LOCK_UNLOCKED;
+rwlock_t tasklist_lock = RW_LOCK_UNLOCKED;
spinlock_t scheduler_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t runqueue_lock = SPIN_LOCK_UNLOCKED;
/* Do we need to re-calculate counters? */
if (!c) {
struct task_struct *p;
- spin_lock(&tasklist_lock);
+ read_lock(&tasklist_lock);
for_each_task(p)
p->counter = (p->counter >> 1) + p->priority;
- spin_unlock(&tasklist_lock);
+ read_unlock(&tasklist_lock);
}
}
}
}
spin_unlock(&scheduler_lock);
- reaquire_kernel_lock(prev, smp_processor_id(), lock_depth);
+ reacquire_kernel_lock(prev, smp_processor_id(), lock_depth);
}
#ifndef __alpha__
* We don't need to get the kernel lock - this is all local to this
* particular thread.. (and that's good, because this is _heavily_
* used by various programs)
+ *
+ * No SMP locking would prevent the inherent races present in this
+ * routine, thus we do not perform any locking at all.
*/
asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
{
if (set) {
sigset_t new_set;
- int error = get_user(new_set, set);
- if (error)
- return error;
+
+ if(get_user(new_set, set))
+ return -EFAULT;
+
new_set &= _BLOCKABLE;
switch (how) {
default:
current->blocked = new_set;
}
if (oset) {
- int error = put_user(old_set, oset);
- if (error)
- return error;
+ if(put_user(old_set, oset))
+ return -EFAULT;
}
return 0;
}
*/
asmlinkage int sys_sgetmask(void)
{
- int ret;
-
/* SMP safe */
- ret = current->blocked;
- return ret;
+ return current->blocked;
}
asmlinkage int sys_ssetmask(int newmask)
{
int old;
- lock_kernel();
+ spin_lock_irq(¤t->sigmask_lock);
old = current->blocked;
current->blocked = newmask & _BLOCKABLE;
- unlock_kernel();
+ spin_unlock_irq(¤t->sigmask_lock);
+
return old;
}
* Note the silly behaviour of SIGCHLD: SIG_IGN means that the signal
* isn't actually ignored, but does automatic child reaping, while
* SIG_DFL is explicitly said by POSIX to force the signal to be ignored..
+ *
+ * All callers of check_pending must be holding current->sig->siglock.
*/
inline void check_pending(int signum)
{
struct sigaction *p;
p = signum - 1 + current->sig->action;
+ spin_lock(¤t->sigmask_lock);
if (p->sa_handler == SIG_IGN) {
current->signal &= ~_S(signum);
- return;
- }
- if (p->sa_handler == SIG_DFL) {
- if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH)
- return;
- current->signal &= ~_S(signum);
- return;
+ } else if (p->sa_handler == SIG_DFL) {
+ if (signum == SIGCONT ||
+ signum == SIGCHLD ||
+ signum != SIGWINCH)
+ current->signal &= ~_S(signum);
}
+ spin_unlock(¤t->sigmask_lock);
}
#ifndef __alpha__
*/
asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler)
{
- unsigned long err;
struct sigaction tmp;
- lock_kernel();
- err = -EINVAL;
if (signum<1 || signum>32)
- goto out;
+ return -EINVAL;
if (signum==SIGKILL || signum==SIGSTOP)
- goto out;
+ return -EINVAL;
if (handler != SIG_DFL && handler != SIG_IGN) {
- err = verify_area(VERIFY_READ, handler, 1);
- if (err)
- goto out;
+ if(verify_area(VERIFY_READ, handler, 1))
+ return -EFAULT;
}
+
memset(&tmp, 0, sizeof(tmp));
tmp.sa_handler = handler;
tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
+
+ spin_lock_irq(¤t->sig->siglock);
handler = current->sig->action[signum-1].sa_handler;
current->sig->action[signum-1] = tmp;
check_pending(signum);
- err = (unsigned long) handler;
-out:
- unlock_kernel();
- return err;
+ spin_unlock_irq(¤t->sig->siglock);
+
+ return (unsigned long) handler;
}
#endif
{
struct sigaction new_sa, *p;
- if (signum<1 || signum>32)
+ if (signum < 1 || signum > 32)
return -EINVAL;
+
p = signum - 1 + current->sig->action;
+
if (action) {
if (copy_from_user(&new_sa, action, sizeof(struct sigaction)))
return -EFAULT;
if (signum==SIGKILL || signum==SIGSTOP)
return -EINVAL;
}
+
if (oldaction) {
+ /* In the clone() case we could copy half consistant
+ * state to the user, however this could sleep and
+ * deadlock us if we held the signal lock on SMP. So for
+ * now I take the easy way out and do no locking.
+ */
if (copy_to_user(oldaction, p, sizeof(struct sigaction)))
return -EFAULT;
}
+
if (action) {
+ spin_lock_irq(¤t->sig->siglock);
*p = new_sa;
check_pending(signum);
+ spin_unlock_irq(¤t->sig->siglock);
}
return 0;
}
if (!pid) {
ret = current->session;
} else {
- /* Walking the process table needs locks */
- lock_kernel();
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->pid == pid) {
ret = p->session;
}
ret = -ESRCH;
out:
- unlock_kernel();
+ read_unlock(&tasklist_lock);
}
return ret;
}
struct task_struct * p;
int err = -EPERM;
- lock_kernel();
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->pgrp == current->pid)
goto out;
current->tty_old_pgrp = 0;
err = current->pgrp;
out:
- unlock_kernel();
+ read_unlock(&tasklist_lock);
return err;
}
/* We track the number of pages currently being asynchronously swapped
out, so that we don't try to swap TOO many pages out at once */
-atomic_t nr_async_pages = ATOMIC_INIT;
+atomic_t nr_async_pages = ATOMIC_INIT(0);
/*
* Constants for the page aging mechanism: the maximum age (actually,
#include <linux/stat.h>
#include <net/br.h>
#include <linux/net_alias.h>
+#include <linux/init.h>
#ifdef CONFIG_KERNELD
#include <linux/kerneld.h>
#endif
* Device list lock
*/
-atomic_t dev_lockct = ATOMIC_INIT;
+atomic_t dev_lockct = ATOMIC_INIT(0);
/*
* Our notifier list
#endif /* CONFIG_PROC_FS */
#endif /* CONFIG_NET_RADIO */
-int net_dev_init(void)
+__initfunc(int net_dev_init(void))
{
struct device *dev, **dp;
#include <net/dst.h>
struct dst_entry * dst_garbage_list;
-atomic_t dst_total = ATOMIC_INIT;
+atomic_t dst_total = ATOMIC_INIT(0);
static unsigned long dst_gc_timer_expires;
static unsigned long dst_gc_timer_inc = DST_GC_MAX;
* Resource tracking variables
*/
-static atomic_t net_skbcount = ATOMIC_INIT;
-static atomic_t net_allocs = ATOMIC_INIT;
-static atomic_t net_fails = ATOMIC_INIT;
+static atomic_t net_skbcount = ATOMIC_INIT(0);
+static atomic_t net_allocs = ATOMIC_INIT(0);
+static atomic_t net_fails = ATOMIC_INIT(0);
extern atomic_t ip_frag_mem;
* is best
*/
- if(val > SK_WMEM_MAX*2 || val < 2048)
+ if(val > SK_WMEM_MAX*2)
return -EINVAL;
/*
* Once this is all 32bit values we can
*/
if(val > 65535)
return -EINVAL;
- sk->sndbuf = val;
+ sk->sndbuf = max(val,2048);
/*
* Wake up sending tasks if we
* upped the value.
break;
case SO_RCVBUF:
- if(val > SK_RMEM_MAX*2 || val < 256)
+ if(val > SK_RMEM_MAX*2)
return -EINVAL;
/* Can go soon: FIXME */
if(val > 65535)
return -EINVAL;
- sk->rcvbuf = val;
+ sk->rcvbuf = max(val,256);
break;
case SO_KEEPALIVE:
int sysctl_arp_dead_res_time = ARP_DEAD_RES_TIME;
-/* This should be completely nuked... -DaveM */
-#if RT_CACHE_DEBUG >= 1
-#define ASSERT_BH() if (!in_interrupt()) printk(KERN_CRIT __FUNCTION__ " called from SPL=0\n");
-#else
-#define ASSERT_BH()
-#endif
-
static void arp_neigh_destroy(struct neighbour *neigh);
/*
};
-static atomic_t arp_size = ATOMIC_INIT;
-static atomic_t arp_unres_size = ATOMIC_INIT;
+static atomic_t arp_size = ATOMIC_INIT(0);
+static atomic_t arp_unres_size = ATOMIC_INIT(0);
#ifdef CONFIG_ARPD
static int arpd_not_running;
{
struct sk_buff *skb;
- ASSERT_BH();
-
/* Release the list of `skb' pointers. */
while ((skb = skb_dequeue(&entry->u.neigh.arp_queue)) != NULL)
kfree_skb(skb, FREE_WRITE);
- return;
}
static void arp_free(struct arp_table **entryp)
struct arp_table *entry = *entryp;
*entryp = entry->u.next;
- ASSERT_BH();
-
if (!(entry->flags&ATF_PUBL)) {
atomic_dec(&arp_size);
if (!(entry->flags&ATF_COM))
struct arp_table *entry = (struct arp_table*)neigh;
struct hh_cache *hh, *next;
- ASSERT_BH();
-
del_timer(&entry->timer);
arp_purge_send_q(entry);
{
struct sk_buff *skb;
- ASSERT_BH();
-
- while((skb = skb_dequeue(&entry->u.neigh.arp_queue)) != NULL) {
+ while((skb = skb_dequeue(&entry->u.neigh.arp_queue)) != NULL)
dev_queue_xmit(skb);
- }
}
*/
static struct wait_queue *fib_wait;
-static atomic_t fib_users = ATOMIC_INIT;
+static atomic_t fib_users = ATOMIC_INIT(0);
static void fib_lock(void)
{
static struct ipq *ipqueue = NULL; /* IP fragment queue */
-atomic_t ip_frag_mem = ATOMIC_INIT; /* Memory used for fragments */
+atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */
char *in_ntoa(unsigned long in);
* Route cache.
*/
-static atomic_t rt_cache_size = ATOMIC_INIT;
+static atomic_t rt_cache_size = ATOMIC_INIT(0);
static struct rtable *rt_hash_table[RT_HASH_DIVISOR];
static struct rtable * rt_intern_hash(unsigned hash, struct rtable * rth, u16 protocol);
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.55 1997/04/13 10:31:45 davem Exp $
+ * Version: $Id: tcp.c,v 1.56 1997/04/16 09:18:42 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
tmp = MAX_HEADER + sk->prot->max_header +
sizeof(struct sk_buff) + 15;
if (copy < min(sk->mss, sk->max_window >> 1) &&
- !(flags & MSG_OOB) && atomic_read(&sk->packets_out))
+ !(flags & MSG_OOB) && sk->packets_out)
{
tmp += min(sk->mss, sk->max_window);
}
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_input.c,v 1.42 1997/04/12 04:32:24 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.43 1997/04/16 09:18:47 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* The packet acked data after high_seq;
*/
- if (ack == tp->snd_una && atomic_read(&sk->packets_out) && (not_dup == 0))
+ if (ack == tp->snd_una && sk->packets_out && (not_dup == 0))
{
/*
* 1. When the third duplicate ack is received, set ssthresh
* do packet "repackaging" for stacks that don't
* like overlapping packets.
*/
- atomic_dec(&sk->packets_out);
+ sk->packets_out--;
*seq = skb->seq;
*seq_rtt = now - skb->when;
if (atomic_read(&sk->retransmits))
{
- if (atomic_read(&sk->packets_out) == 0)
+ if (sk->packets_out == 0)
atomic_set(&sk->retransmits, 0);
}
else
}
}
- if (atomic_read(&sk->packets_out))
+ if (sk->packets_out)
{
if (flag & FLAG_DATA_ACKED)
{
if ((skb = tp->send_head))
{
if (!after(skb->end_seq, tp->snd_una + tp->snd_wnd) &&
- atomic_read(&sk->packets_out) < tp->snd_cwnd )
+ sk->packets_out < tp->snd_cwnd )
{
/*
* Add more data to the send queue.
if(!sk->dead)
sk->write_space(sk);
}
- else if (atomic_read(&sk->packets_out) == 0 && !tp->pending)
+ else if (sk->packets_out == 0 && !tp->pending)
{
/*
* Data to queue but no room.
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_ipv4.c,v 1.30 1997/04/13 10:31:44 davem Exp $
+ * Version: $Id: tcp_ipv4.c,v 1.31 1997/04/16 09:18:50 davem Exp $
*
* IPv4 specific functions
*
skb_queue_tail(&sk->write_queue, buff);
- atomic_inc(&sk->packets_out);
+ sk->packets_out++;
buff->when = jiffies;
skb1 = skb_clone(buff, GFP_KERNEL);
return;
}
- mss = (skb->dst->pmtu - sizeof(struct iphdr) + sizeof(struct tcphdr));
+ mss = (skb->dst->pmtu - sizeof(struct iphdr) - sizeof(struct tcphdr));
if (sk->user_mss)
mss = min(mss, sk->user_mss);
skb->h.th = th = (struct tcphdr *) skb_put(skb, sizeof(struct tcphdr));
newtp->snd_nxt = newsk->write_seq;
newsk->urg_data = 0;
- atomic_set(&newsk->packets_out, 0);
+ newsk->packets_out = 0;
atomic_set(&newsk->retransmits, 0);
newsk->linger=0;
newsk->destroy = 0;
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_output.c,v 1.34 1997/04/12 04:32:33 davem Exp $
+ * Version: $Id: tcp_output.c,v 1.35 1997/04/16 09:18:53 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
len = skb->end_seq - skb->seq;
- if (!sk->nonagle && len < (sk->mss >> 1) && atomic_read(&sk->packets_out))
+ if (!sk->nonagle && len < (sk->mss >> 1) && sk->packets_out)
{
nagle_check = 0;
}
- return (nagle_check && atomic_read(&sk->packets_out) < tp->snd_cwnd &&
+ return (nagle_check && sk->packets_out < tp->snd_cwnd &&
!after(skb->end_seq, tp->snd_una + tp->snd_wnd) &&
atomic_read(&sk->retransmits) == 0);
}
skb_set_owner_w(buff, sk);
tp->snd_nxt = skb->end_seq;
- atomic_inc(&sk->packets_out);
+ sk->packets_out++;
skb->when = jiffies;
if (tp->send_head == NULL)
tp->send_head = skb;
- if (atomic_read(&sk->packets_out) == 0 && !tp->pending)
+ if (sk->packets_out == 0 && !tp->pending)
{
tp->pending = TIME_PROBE0;
tcp_reset_xmit_timer(sk, TIME_PROBE0, tp->rto);
{
/* !tcp_frament Failed! */
tp->send_head = skb;
- atomic_dec(&sk->packets_out);
+ sk->packets_out--;
return -1;
}
else
update_send_head(sk);
clear_delayed_acks(sk);
- atomic_inc(&sk->packets_out);
+ sk->packets_out++;
skb_set_owner_w(buff, sk);
tp->snd_nxt = skb->end_seq;
*/
kfree_skb(buff, FREE_WRITE);
- atomic_dec(&sk->packets_out);
+ sk->packets_out--;
/*
* Header checksum will be set by the retransmit procedure
printk(KERN_DEBUG "tcp_fragment failed\n");
return;
}
- atomic_inc(&sk->packets_out);
+ sk->packets_out++;
}
if (!th->syn &&
{
struct sk_buff *skb1;
- atomic_inc(&sk->packets_out);
+ sk->packets_out++;
tp->snd_nxt = sk->write_seq;
buff->when = jiffies;
{
skb_set_owner_w(buff, sk);
- atomic_inc(&sk->packets_out);
+ sk->packets_out++;
skb->when = jiffies;
tp->af_specific->queue_xmit(buff);
return;
}
skb_set_owner_w(buff, sk);
- atomic_inc(&sk->packets_out);
+ sk->packets_out++;
clear_delayed_acks(sk);
struct tcp_sl_timer tcp_slt_array[TCP_SLT_MAX] = {
- {ATOMIC_INIT, TCP_SYNACK_PERIOD, 0, tcp_syn_recv_timer},/* SYNACK */
- {ATOMIC_INIT, TCP_KEEPALIVE_PERIOD, 0, tcp_keepalive} /* KEEPALIVE */
+ {ATOMIC_INIT(0), TCP_SYNACK_PERIOD, 0, tcp_syn_recv_timer},/* SYNACK */
+ {ATOMIC_INIT(0), TCP_KEEPALIVE_PERIOD, 0, tcp_keepalive} /* KEEPALIVE */
};
/*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: addrconf.c,v 1.16 1997/04/12 04:32:44 davem Exp $
+ * $Id: addrconf.c,v 1.18 1997/04/16 05:58:03 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
*/
struct inet6_dev *inet6_dev_lst[IN6_ADDR_HSIZE];
-static atomic_t addr_list_lock = ATOMIC_INIT;
+static atomic_t addr_list_lock = ATOMIC_INIT(0);
void addrconf_verify(unsigned long);
*
* Based on linux/net/ipv4/ip_sockglue.c
*
- * $Id: ipv6_sockglue.c,v 1.9 1997/04/07 06:55:51 davem Exp $
+ * $Id: ipv6_sockglue.c,v 1.10 1997/04/15 09:06:33 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: route.c,v 1.10 1997/04/12 04:32:57 davem Exp $
+ * $Id: route.c,v 1.11 1997/04/16 05:58:05 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
};
struct rt6_info ip6_null_entry = {
- {{NULL, ATOMIC_INIT, ATOMIC_INIT, NULL,
+ {{NULL, ATOMIC_INIT(0), ATOMIC_INIT(0), NULL,
0, 0, 0, 0, 0, 0, 0, 0, -ENETUNREACH, NULL, NULL,
ip6_pkt_discard, ip6_pkt_discard, &ip6_dst_ops}},
NULL, {{{0}}}, 256, RTF_REJECT|RTF_NONEXTHOP, ~0UL,
#define ip6_rt_policy (0)
#endif
-static atomic_t rt6_tbl_lock = ATOMIC_INIT;
+static atomic_t rt6_tbl_lock = ATOMIC_INIT(0);
static int rt6_bh_mask = 0;
#define RT_BH_REQUEST 1
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: tcp_ipv6.c,v 1.20 1997/04/13 10:31:48 davem Exp $
+ * $Id: tcp_ipv6.c,v 1.21 1997/04/16 09:19:01 davem Exp $
*
* Based on:
* linux/net/ipv4/tcp.c
atomic_set(&sk->retransmits, 0);
skb_queue_tail(&sk->write_queue, buff);
- atomic_inc(&sk->packets_out);
+ sk->packets_out++;
buff->when = jiffies;
skb1 = skb_clone(buff, GFP_KERNEL);
skb_set_owner_w(skb1, sk);
newtp->snd_nxt = newsk->write_seq;
newsk->urg_data = 0;
- atomic_set(&newsk->packets_out, 0);
+ newsk->packets_out = 0;
atomic_set(&newsk->retransmits, 0);
newsk->linger=0;
newsk->destroy = 0;
if (scm->fp)
unix_attach_fds(scm, skb);
+ skb->h.raw = skb->data;
memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
other = unix_peer(sk);