Commit 6e8e8ad0 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://jfs.bkbits.net/linux-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents f67f7c15 551d9631
......@@ -247,6 +247,28 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.0.20:
- Support non-resident directory index bitmaps. This means we now cope
with huge directories without problems.
- Fix a page leak that manifested itself in some cases when reading
directory contents.
- Internal cleanups.
2.0.19:
- Fix race condition and improvements in block i/o interface.
- Optimization when reading compressed files.
2.0.18:
- Fix race condition in reading of compressed files.
2.0.17:
- Cleanups and optimizations.
2.0.16:
- Fix stupid bug introduced in 2.0.15 in new attribute inode API.
- Big internal cleanup replacing the mftbmp access hacks by using the
new attribute inode API instead.
2.0.15:
- Bug fix in parsing of remount options.
- Internal changes implementing attribute (fake) inodes allowing all
attribute i/o to go via the page cache and to use all the normal
vfs/mm functionality.
2.0.14:
- Internal changes improving run list merging code and minor locking
change to not rely on BKL in ntfs_statfs().
......
usb-xpad - Linux USB driver for XBOX HID gamecontrollers
This is the very first release of a driver for XBOX gamecontrollers.
Basically, this was hacked away in just a few hours, so don't expect
miracles.
0. Status
---------
For now, this driver has only been tested on just one Linux-Box.
This one is running a 2.4.18 kernel with usb-uhci on an amd athlon 600.
The jstest-program from joystick-1.2.15 (jstest-version 2.1.0) reports
8 axes and 10 buttons.
Alls 8 axes work, though they all have the same range (-32768..32767)
and the zero-setting is not correct for the triggers.
9 of the 10 buttons work (my black button does not work, though I can
see no reason for it not to), all of them are in digital mode, though
(the six buttons on the right side are "analog" ones).
1. USB adapter
--------------
Before you can actually use the driver, you need to get yourself an
adapter cable to connect the XBOX-controller to your Linux-Box.
Such a cable is pretty easy to build. The Controller itself is a USB device
(a hub with three ports; two expansion slots and the controller device)
with the only differnce in a nonstandard connector (5 pins vs. 4 on
standard USB connector).
You just need to solder an USB connector onto the cable and keep the
yellow wire unconnected. The other pins have the same order on both
connectors so there no magic to it. Detailed info on these matters can be found
on the net.
Thanks to the trip splitter found on the cable you don't even need to cut the
original cable, you can buy an extension cable and cut that instead. That way,
you can still use the controller with your XBOX, if you have one ;)
2. driver installation
----------------------
Once you have the adapter cable and the controller is connected, you need
to load your USB subsystem and should cat /proc/bus/usb/devices.
There should be an entry like the one in InterAct_german.dump.
Don't worry if the vendor and/or product ID don't match, those are easy to
add to the driver. You could do it yourself, just add the appropriate line
into the list after the line
'} xpad_device[] = {'
, but before the line that says
'{ 0x0000, 0x0000, "unknown...." }'.
In theory, the driver should work with other controllers than mine
(InterAct PowerPad pro, bought in Germany) just fine, but see for yourself.
If you compiled and installed the driver, test the functionality:
> modprobe usb-xpad
> modprobe joydev
> jstest /dev/input/js0
There should be a single line showing 18 inputs (8 axes, 10 buttons), and
it's values should change if you move the sticks and push the buttons.
It works? Voila, your done ;)
3. Thanks
---------
I have to thank ITO Takayuki for the detailed info on his site
http://euc.jp/periphs/xbox-controller.ja.html.
His useful info and both the usb-skeleton as well as the iforce input driver
helped a lot in rapid prototyping the basic functionality.
--
Marko Friedemann <mfr@bmx-chemnitz.de>
2002-07-02
This diff is collapsed.
......@@ -22,9 +22,8 @@ USB-specific:
-ENODEV specified USB-device or bus doesn't exist
-ENXIO a control or interrupt URB is already queued to this endpoint;
or (UHCI only) a bulk URB is already queued to this endpoint
and USB_QUEUE_BULK wasn't used
-ENXIO host controller driver does not support queuing of this type
of urb. (treat as a host controller bug.)
-EINVAL a) Invalid transfer type specified (or not supported)
b) Invalid interrupt interval (0<=n<256)
......@@ -90,9 +89,9 @@ one or more packets could finish before an error stops further endpoint I/O.
greater than either the max packet size of the
endpoint or the remaining buffer size. "Babble".
-EREMOTEIO The endpoint returned less than max packet size
and that amount did not fill the specified buffer
(and USB_DISBLE_SPD was not set in transfer_flags)
-EREMOTEIO The data read from the endpoint did not fill the
specified buffer, and URB_SHORT_NOT_OK was set in
urb->transfer_flags.
-ETIMEDOUT transfer timed out, NAK
......
......@@ -10,10 +10,12 @@
LDFLAGS_vmlinux :=-p -X -T arch/arm/vmlinux.lds
OBJCOPYFLAGS :=-O binary -R .note -R .comment -S
GZFLAGS :=-9
CFLAGS +=-pipe
#CFLAGS +=-pipe
CFLAGS :=$(CFLAGS:-O2=-Os)
ifneq ($(CONFIG_NO_FRAME_POINTER),y)
CFLAGS :=$(CFLAGS:-fomit-frame-pointer=)
CFLAGS :=$(CFLAGS: -fomit-frame-pointer=)
endif
ifeq ($(CONFIG_DEBUG_INFO),y)
......@@ -24,7 +26,7 @@ endif
# the options further down the list override previous items.
#
apcs-$(CONFIG_CPU_32) :=-mapcs-32
apcs-$(CONFIG_CPU_26) :=-mapcs-26 -mcpu=arm3 -Os
apcs-$(CONFIG_CPU_26) :=-mapcs-26 -mcpu=arm3
# This selects which instruction set is used.
# Note that GCC is lame - it doesn't numerically define an
......@@ -212,8 +214,11 @@ include/asm-arm/.proc: $(wildcard include/config/cpu/32.h) $(wildcard include/co
@ln -sf proc-$(PROCESSOR) include/asm-arm/proc
@touch $@
prepare: include/asm-arm/.arch include/asm-arm/.proc \
include/asm-arm/constants.h
prepare: maketools
.PHONY: maketools
maketools: include/asm-arm/.arch include/asm-arm/.proc \
include/asm-arm/constants.h include/linux/version.h FORCE
@$(MAKETOOLS)
vmlinux: arch/arm/vmlinux.lds
......@@ -222,6 +227,7 @@ arch/arm/vmlinux.lds: arch/arm/Makefile $(LDSCRIPT) \
$(wildcard include/config/cpu/32.h) \
$(wildcard include/config/cpu/26.h) \
$(wildcard include/config/arch/*.h)
@echo ' Generating $@'
@sed 's/TEXTADDR/$(TEXTADDR)/;s/DATAADDR/$(DATAADDR)/' $(LDSCRIPT) >$@
bzImage zImage zinstall Image bootpImage install: vmlinux
......@@ -243,10 +249,6 @@ archmrproper: FORCE
archclean: FORCE
@$(MAKEBOOT) clean
# we need version.h
maketools: include/linux/version.h FORCE
@$(MAKETOOLS)
# My testing targets (that short circuit a few dependencies)
zImg:; @$(MAKEBOOT) zImage
Img:; @$(MAKEBOOT) Image
......
......@@ -153,18 +153,15 @@ if [ "$CONFIG_ARCH_EP7211" = "y" -o \
fi
endmenu
if [ "$CONFIG_ARCH_IOP310" = "y" ]; then
mainmenu_option next_comment
comment 'IOP310 Implementation Options'
choice 'IOP310 System Type' \
"IQ80310 CONFIG_ARCH_IQ80310" IQ80310
comment 'IOP310 Chipset Features'
bool 'Support Intel 80312 Application Accelerator Unit (EXPERIMENTAL)' CONFIG_IOP310_AAU
bool 'Support Intel 80312 DMA (EXPERIMENTAL)' CONFIG_IOP310_DMA
bool 'Support Intel 80312 Messaging Unit (EXPERIMENTAL)' CONFIG_IOP310_MU
bool 'Support Intel 80312 Performance Monitor (EXPERIMENTAL)' CONFIG_IOP310_PMON
endmenu
fi
mainmenu_option next_comment
comment 'IOP310 Implementation Options'
dep_bool ' IQ80310' CONFIG_ARCH_IQ80310 $CONFIG_ARCH_IOP310
comment 'IOP310 Chipset Features'
dep_bool 'Support Intel 80312 Application Accelerator Unit (EXPERIMENTAL)' CONFIG_IOP310_AAU $CONFIG_ARCH_IOP310 $CONFIG_EXPERIMENTAL
dep_bool 'Support Intel 80312 DMA (EXPERIMENTAL)' CONFIG_IOP310_DMA $CONFIG_ARCH_IOP310 $CONFIG_EXPERIMENTAL
dep_bool 'Support Intel 80312 Messaging Unit (EXPERIMENTAL)' CONFIG_IOP310_MU $CONFIG_ARCH_IOP310 $CONFIG_EXPERIMENTAL
dep_bool 'Support Intel 80312 Performance Monitor (EXPERIMENTAL)' CONFIG_IOP310_PMON $CONFIG_ARCH_IOP310 $CONFIG_EXPERIMENTAL
endmenu
# Definitions to make life easier
if [ "$CONFIG_ARCH_ARCA5K" = "y" -o \
......
This diff is collapsed.
......@@ -712,7 +712,6 @@ __dabt_svc: sub sp, sp, #S_FRAME_SIZE
mrs r9, cpsr @ Enable interrupts if they were
tst r3, #PSR_I_BIT
biceq r9, r9, #PSR_I_BIT @ previously
mov r0, r2 @ *** remove once everyones in sync
/*
* This routine must not corrupt r9
*/
......@@ -855,7 +854,6 @@ __dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmdb r5, {sp, lr}^
alignment_trap r7, r7, __temp_abt
zero_fp
mov r0, r2 @ remove once everyones in sync
#ifdef MULTI_ABORT
ldr r4, .LCprocfns @ pass r0, r3 to
mov lr, pc @ processor code
......@@ -913,10 +911,13 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmdb r8, {sp, lr}^ @ Save user sp, lr
alignment_trap r4, r7, __temp_und
zero_fp
tst r6, #PSR_T_BIT @ Thumb mode?
bne fpundefinstr @ ignore FP
adrsvc al, r9, ret_from_exception @ r9 = normal FP return
adrsvc al, lr, fpundefinstr @ lr = undefined instr return
call_fpe: get_thread_info r10 @ get current thread
call_fpe: set_cpsr_c r0, #MODE_SVC @ Enable interrupts
get_thread_info r10 @ get current thread
ldr r4, [r10, #TI_TASK] @ get current task
mov r8, #1
strb r8, [r4, #TSK_USED_MATH] @ set current->used_math
......@@ -924,8 +925,7 @@ call_fpe: get_thread_info r10 @ get current thread
add r10, r10, #TI_FPSTATE @ r10 = workspace
ldr pc, [r4] @ Call FP module USR entry point
fpundefinstr: set_cpsr_c r0, #MODE_SVC @ Enable interrupts
mov r0, sp
fpundefinstr: mov r0, sp
adrsvc al, lr, ret_from_exception
b do_undefinstr
......
......@@ -202,8 +202,7 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
__cli();
spin_lock(&irq_controller_lock);
spin_lock_irq(&irq_controller_lock);
}
/*
......@@ -634,6 +633,8 @@ unsigned long probe_irq_on(void)
irq_desc[i].probing = 1;
irq_desc[i].triggered = 0;
if (irq_desc[i].chip->type)
irq_desc[i].chip->type(i, IRQT_PROBE);
irq_desc[i].chip->unmask(i);
irqs += 1;
}
......
......@@ -75,10 +75,10 @@ void (*pm_power_off)(void);
*/
void default_idle(void)
{
__cli();
local_irq_disable();
if (!need_resched() && !hlt_counter)
arch_idle();
__sti();
local_irq_enable();
}
/*
......
......@@ -40,12 +40,17 @@
* Get the address of the live pt_regs for the specified task.
* These are saved onto the top kernel stack when the process
* is not running.
*
* Note: if a user thread is execve'd from kernel space, the
* kernel stack will not be empty on entry to the kernel, so
* ptracing these tasks will fail.
*/
static inline struct pt_regs *
get_user_regs(struct task_struct *task)
{
return (struct pt_regs *)
((unsigned long)task->thread_info + 8192 - sizeof(struct pt_regs));
((unsigned long)task->thread_info + THREAD_SIZE -
8 - sizeof(struct pt_regs));
}
/*
......@@ -54,7 +59,7 @@ get_user_regs(struct task_struct *task)
* this routine assumes that all the privileged stacks are in our
* data space.
*/
static inline long get_stack_long(struct task_struct *task, int offset)
static inline long get_user_reg(struct task_struct *task, int offset)
{
return get_user_regs(task)->uregs[offset];
}
......@@ -66,7 +71,7 @@ static inline long get_stack_long(struct task_struct *task, int offset)
* data space.
*/
static inline int
put_stack_long(struct task_struct *task, int offset, long data)
put_user_reg(struct task_struct *task, int offset, long data)
{
struct pt_regs newregs, *regs = get_user_regs(task);
int ret = -EINVAL;
......@@ -111,7 +116,7 @@ ptrace_getrn(struct task_struct *child, unsigned long insn)
unsigned int reg = (insn >> 16) & 15;
unsigned long val;
val = get_stack_long(child, reg);
val = get_user_reg(child, reg);
if (reg == 15)
val = pc_pointer(val + 8);
......@@ -133,10 +138,10 @@ ptrace_getaluop2(struct task_struct *child, unsigned long insn)
shift = (insn >> 8) & 15;
type = 3;
} else {
val = get_stack_long (child, insn & 15);
val = get_user_reg (child, insn & 15);
if (insn & (1 << 4))
shift = (int)get_stack_long (child, (insn >> 8) & 15);
shift = (int)get_user_reg (child, (insn >> 8) & 15);
else
shift = (insn >> 7) & 31;
......@@ -166,7 +171,7 @@ ptrace_getldrop2(struct task_struct *child, unsigned long insn)
int shift;
int type;
val = get_stack_long(child, insn & 15);
val = get_user_reg(child, insn & 15);
shift = (insn >> 7) & 31;
type = (insn >> 5) & 3;
......@@ -215,7 +220,7 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
aluop1 = ptrace_getrn(child, insn);
aluop2 = ptrace_getaluop2(child, insn);
ccbit = get_stack_long(child, REG_PSR) & PSR_C_BIT ? 1 : 0;
ccbit = get_user_reg(child, REG_PSR) & PSR_C_BIT ? 1 : 0;
switch (insn & OP_MASK) {
case OP_AND: alt = aluop1 & aluop2; break;
......@@ -270,13 +275,7 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
unsigned int nr_regs;
if (insn & (1 << 23)) {
nr_regs = insn & 65535;
nr_regs = (nr_regs & 0x5555) + ((nr_regs & 0xaaaa) >> 1);
nr_regs = (nr_regs & 0x3333) + ((nr_regs & 0xcccc) >> 2);
nr_regs = (nr_regs & 0x0707) + ((nr_regs & 0x7070) >> 4);
nr_regs = (nr_regs & 0x000f) + ((nr_regs & 0x0f00) >> 8);
nr_regs <<= 2;
nr_regs = hweight16(insn & 65535) << 2;
if (!(insn & (1 << 24)))
nr_regs -= 4;
......@@ -348,6 +347,11 @@ int ptrace_set_bpt(struct task_struct *child)
regs = get_user_regs(child);
pc = instruction_pointer(regs);
if (thumb_mode(regs)) {
printk(KERN_WARNING "ptrace: can't handle thumb mode\n");
return -EINVAL;
}
res = read_tsk_long(child, pc, &insn);
if (!res) {
struct debug_info *dbg = &child->thread.debug;
......@@ -411,6 +415,118 @@ void ptrace_disable(struct task_struct *child)
__ptrace_cancel_bpt(child);
}
/*
* Handle hitting a breakpoint.
*/
void ptrace_break(struct task_struct *tsk, struct pt_regs *regs)
{
siginfo_t info;
/*
* The PC is always left pointing at the next instruction. Fix this.
*/
regs->ARM_pc -= 4;
if (tsk->thread.debug.nsaved == 0)
printk(KERN_ERR "ptrace: bogus breakpoint trap\n");
__ptrace_cancel_bpt(tsk);
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_BRKPT;
info.si_addr = (void *)instruction_pointer(regs) -
(thumb_mode(regs) ? 2 : 4);
force_sig_info(SIGTRAP, &info, tsk);
}
/*
* Read the word at offset "off" into the "struct user". We
* actually access the pt_regs stored on the kernel stack.
*/
static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
unsigned long *ret)
{
unsigned long tmp;
if (off & 3 || off >= sizeof(struct user))
return -EIO;
tmp = 0;
if (off < sizeof(struct pt_regs))
tmp = get_user_reg(tsk, off >> 2);
return put_user(tmp, ret);
}
/*
* Write the word at offset "off" into "struct user". We
* actually access the pt_regs stored on the kernel stack.
*/
static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
unsigned long val)
{
if (off & 3 || off >= sizeof(struct user))
return -EIO;
if (off >= sizeof(struct pt_regs))
return 0;
return put_user_reg(tsk, off >> 2, val);
}
/*
* Get all user integer registers.
*/
static int ptrace_getregs(struct task_struct *tsk, void *uregs)
{
struct pt_regs *regs = get_user_regs(tsk);
return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
}
/*
* Set all user integer registers.
*/
static int ptrace_setregs(struct task_struct *tsk, void *uregs)
{
struct pt_regs newregs;
int ret;
ret = -EFAULT;
if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
struct pt_regs *regs = get_user_regs(tsk);
ret = -EINVAL;
if (valid_user_regs(&newregs)) {
*regs = newregs;
ret = 0;
}
}
return ret;
}
/*
* Get the child FPU state.
*/
static int ptrace_getfpregs(struct task_struct *tsk, void *ufp)
{
return copy_to_user(ufp, &tsk->thread_info->fpstate,
sizeof(struct user_fp)) ? -EFAULT : 0;
}
/*
* Set the child FPU state.
*/
static int ptrace_setfpregs(struct task_struct *tsk, void *ufp)
{
tsk->used_math = 1;
return copy_from_user(&tsk->thread_info->fpstate, ufp,
sizeof(struct user_fp)) ? -EFAULT : 0;
}
static int do_ptrace(int request, struct task_struct *child, long addr, long data)
{
unsigned long tmp;
......@@ -427,18 +543,8 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
ret = put_user(tmp, (unsigned long *) data);
break;
/*
* read the word at location "addr" in the user registers.
*/
case PTRACE_PEEKUSR:
ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
break;
tmp = 0; /* Default return condition */
if (addr < sizeof(struct pt_regs))
tmp = get_stack_long(child, (int)addr >> 2);
ret = put_user(tmp, (unsigned long *)data);
ret = ptrace_read_user(child, addr, (unsigned long *)data);
break;
/*
......@@ -449,16 +555,8 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
ret = write_tsk_long(child, addr, data);
break;
/*
* write the word at location addr in the user registers.
*/
case PTRACE_POKEUSR:
ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
break;
if (addr < sizeof(struct pt_regs))
ret = put_stack_long(child, (int)addr >> 2, data);
ret = ptrace_write_user(child, addr, data);
break;
/*
......@@ -486,14 +584,12 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
* exit.
*/
case PTRACE_KILL:
/* already dead */
ret = 0;
if (child->state == TASK_ZOMBIE)
break;
child->exit_code = SIGKILL;
/* make sure single-step breakpoint is gone. */
__ptrace_cancel_bpt(child);
wake_up_process(child);
if (child->state != TASK_ZOMBIE) {
child->exit_code = SIGKILL;
wake_up_process(child);
}
ret = 0;
break;
......@@ -512,71 +608,32 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
ret = 0;
break;
/*
* detach a process that was attached.
*/
case PTRACE_DETACH:
ret = ptrace_detach(child, data);
break;
/*
* Get all gp regs from the child.
*/
case PTRACE_GETREGS: {
struct pt_regs *regs = get_user_regs(child);
ret = 0;
if (copy_to_user((void *)data, regs,
sizeof(struct pt_regs)))
ret = -EFAULT;
case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void *)data);
break;
}
/*
* Set all gp regs in the child.
*/
case PTRACE_SETREGS: {
struct pt_regs newregs;
ret = -EFAULT;
if (copy_from_user(&newregs, (void *)data,
sizeof(struct pt_regs)) == 0) {
struct pt_regs *regs = get_user_regs(child);
ret = -EINVAL;
if (valid_user_regs(&newregs)) {
*regs = newregs;
ret = 0;
}
}
case PTRACE_SETREGS:
ret = ptrace_setregs(child, (void *)data);
break;
}
/*
* Get the child FPU state.
*/
case PTRACE_GETFPREGS:
ret = -EIO;
if (!access_ok(VERIFY_WRITE, (void *)data, sizeof(struct user_fp)))
break;
/* we should check child->used_math here */
ret = __copy_to_user((void *)data, &child->thread_info->fpstate,
sizeof(struct user_fp)) ? -EFAULT : 0;
ret = ptrace_getfpregs(child, (void *)data);
break;
/*
* Set the child FPU state.
*/
case PTRACE_SETFPREGS:
ret = -EIO;
if (!access_ok(VERIFY_READ, (void *)data, sizeof(struct user_fp)))
break;
ret = ptrace_setfpregs(child, (void *)data);
break;
child->used_math = 1;
ret = __copy_from_user(&child->thread_info->fpstate, (void *)data,
sizeof(struct user_fp)) ? -EFAULT : 0;
case PTRACE_SETOPTIONS:
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
default:
......
/*
* linux/arch/arm/kernel/ptrace.h
*
* Copyright (C) 2000 Russell King
* Copyright (C) 2000-2002 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -9,6 +9,7 @@
*/
extern void __ptrace_cancel_bpt(struct task_struct *);
extern int ptrace_set_bpt(struct task_struct *);
extern void ptrace_break(struct task_struct *, struct pt_regs *);
/*
* Clear a breakpoint, if one exists.
......
/*
* linux/arch/arm/kernel/signal.c
*
* Copyright (C) 1995-2001 Russell King
* Copyright (C) 1995-2002 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -17,15 +17,15 @@
#include <linux/signal.h>
#include <linux/wait.h>
#include <linux/ptrace.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/personality.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
#include <linux/elf.h>
#include <asm/pgalloc.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include "ptrace.h"
......@@ -49,7 +49,7 @@ static const unsigned long retcodes[4] = {
SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
};
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
/*
* atomically swap in the new signal mask, and wait for a signal.
......@@ -325,7 +325,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
unsigned long retcode;
int thumb = 0;
#ifdef CONFIG_CPU_32
unsigned long cpsr = regs->ARM_cpsr;
unsigned long cpsr = regs->ARM_cpsr & ~PSR_f;
/*
* Maybe we need to deliver a 32-bit signal to a 26-bit task.
......@@ -501,7 +501,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
{
struct k_sigaction *ka;
siginfo_t info;
......@@ -516,9 +516,6 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
if (!user_mode(regs))
return 0;
if (!oldset)
oldset = &current->blocked;
single_stepping = ptrace_cancel_bpt(current);
for (;;) {
......@@ -598,6 +595,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
single_stepping |= ptrace_cancel_bpt(current);
continue;
}
......@@ -655,5 +653,5 @@ asmlinkage void
do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
{
if (thread_flags & _TIF_SIGPENDING)
do_signal(NULL, regs, syscall);
do_signal(&current->blocked, regs, syscall);
}
/*
* linux/arch/arm/kernel/traps.c
*
* Copyright (C) 1995, 1996 Russell King
* Copyright (C) 1995-2002 Russell King
* Fragments that appear the same as linux/arch/i386/kernel/traps.c (C) Linus Torvalds
*
* This program is free software; you can redistribute it and/or modify
......@@ -66,8 +66,17 @@ static int verify_stack(unsigned long sp)
static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
{
unsigned long p = bottom & ~31;
mm_segment_t fs;
int i;
/*
* We need to switch to kernel mode so that we can use __get_user
* to safely read from kernel space. Note that we now dump the
* code first, just in case the backtrace kills us.
*/
fs = get_fs();
set_fs(KERNEL_DS);
printk("%s", str);
printk("(0x%08lx to 0x%08lx)\n", bottom, top);
......@@ -86,6 +95,8 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
}
printk ("\n");
}
set_fs(fs);
}
static void dump_instr(struct pt_regs *regs)
......@@ -93,8 +104,17 @@ static void dump_instr(struct pt_regs *regs)
unsigned long addr = instruction_pointer(regs);
const int thumb = thumb_mode(regs);
const int width = thumb ? 4 : 8;
mm_segment_t fs;
int i;
/*
* We need to switch to kernel mode so that we can use __get_user
* to safely read from kernel space. Note that we now dump the
* code first, just in case the backtrace kills us.
*/
fs = get_fs();
set_fs(KERNEL_DS);
printk("Code: ");
for (i = -4; i < 1; i++) {
unsigned int val, bad;
......@@ -112,6 +132,8 @@ static void dump_instr(struct pt_regs *regs)
}
}
printk("\n");
set_fs(fs);
}
static void dump_stack(struct task_struct *tsk, unsigned long sp)
......@@ -171,22 +193,9 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
current->comm, current->pid, tsk->thread_info + 1);
if (!user_mode(regs) || in_interrupt()) {
mm_segment_t fs;
/*
* We need to switch to kernel mode so that we can
* use __get_user to safely read from kernel space.
* Note that we now dump the code first, just in case
* the backtrace kills us.
*/
fs = get_fs();
set_fs(KERNEL_DS);
dump_stack(tsk, (unsigned long)(regs + 1));
dump_backtrace(regs, tsk);
dump_instr(regs);
set_fs(fs);
}
spin_unlock_irq(&die_lock);
......@@ -233,7 +242,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
}
#ifdef CONFIG_CPU_26
asmlinkage void do_excpt(int address, struct pt_regs *regs, int mode)
asmlinkage void do_excpt(unsigned long address, struct pt_regs *regs, int mode)
{
siginfo_t info;
......@@ -274,21 +283,12 @@ asmlinkage void do_unexp_fiq (struct pt_regs *regs)
asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
{
unsigned int vectors = vectors_base();
mm_segment_t fs;
console_verbose();
printk(KERN_CRIT "Bad mode in %s handler detected: mode %s\n",
handler[reason], processor_modes[proc_mode]);
/*
* We need to switch to kernel mode so that we can use __get_user
* to safely read from kernel space. Note that we now dump the
* code first, just in case the backtrace kills us.
*/
fs = get_fs();
set_fs(KERNEL_DS);
/*
* Dump out the vectors and stub routines. Maybe a better solution
* would be to dump them out only if we detect that they are corrupted.
......@@ -296,10 +296,8 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
dump_mem(KERN_CRIT "Vectors: ", vectors, vectors + 0x40);
dump_mem(KERN_CRIT "Stubs: ", vectors + 0x200, vectors + 0x4b8);
set_fs(fs);
die("Oops", regs, 0);
cli();
local_irq_disable();
panic("bad mode");
}
......@@ -308,13 +306,7 @@ static int bad_syscall(int n, struct pt_regs *regs)
struct thread_info *thread = current_thread_info();
siginfo_t info;
/* You might think just testing `handler' would be enough, but PER_LINUX
* points it to no_lcall7 to catch undercover SVr4 binaries. Gutted.
*/
if (current->personality != PER_LINUX && thread->exec_domain->handler) {
/* Hand it off to iBCS. The extra parameter and consequent type
* forcing is necessary because of the weird ARM calling convention.
*/
thread->exec_domain->handler(n, regs);
return regs->ARM_r0;
}
......@@ -380,20 +372,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
return 0;
case NR(breakpoint): /* SWI BREAK_POINT */
/*
* The PC is always left pointing at the next
* instruction. Fix this.
*/
regs->ARM_pc -= 4;
__ptrace_cancel_bpt(current);
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_BRKPT;
info.si_addr = (void *)instruction_pointer(regs) -
(thumb_mode(regs) ? 2 : 4);
force_sig_info(SIGTRAP, &info, current);
ptrace_break(current, regs);
return regs->ARM_r0;
#ifdef CONFIG_CPU_32
......@@ -418,13 +397,13 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
case NR(usr26):
if (!(elf_hwcap & HWCAP_26BIT))
break;
regs->ARM_cpsr &= ~0x10;
regs->ARM_cpsr &= ~MODE32_BIT;
return regs->ARM_r0;
case NR(usr32):
if (!(elf_hwcap & HWCAP_26BIT))
break;
regs->ARM_cpsr |= 0x10;
regs->ARM_cpsr |= MODE32_BIT;
return regs->ARM_r0;
#else
case NR(cacheflush):
......
......@@ -52,25 +52,32 @@ ENTRY(c_backtrace)
3: tst frame, mask @ Check for address exceptions...
bne 1b
1001: ldmda frame, {r0, r1, r2, r3} @ fp, sp, lr, pc
mov next, r0
1001: ldr next, [frame, #-12] @ get fp
1002: ldr r2, [frame, #-4] @ get lr
1003: ldr r3, [frame, #0] @ get pc
sub save, r3, offset @ Correct PC for prefetching
bic save, save, mask
1004: ldr r1, [save, #0] @ get instruction at function
mov r1, r1, lsr #10
ldr r3, .Ldsi+4
teq r1, r3
subeq save, save, #4
adr r0, .Lfe
mov r1, save
bic r2, r2, mask
bl printk @ print pc and link register
sub r0, frame, #16
1002: ldr r1, [save, #4] @ get instruction at function+4
ldr r0, [frame, #-8] @ get sp
sub r0, r0, #4
1005: ldr r1, [save, #4] @ get instruction at function+4
mov r3, r1, lsr #10
ldr r2, .Ldsi+4
teq r3, r2 @ Check for stmia sp!, {args}
addeq save, save, #4 @ next instruction
bleq .Ldumpstm
1003: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction
sub r0, frame, #16
1006: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction
mov r3, r1, lsr #10
ldr r2, .Ldsi
teq r3, r2
......@@ -87,7 +94,7 @@ ENTRY(c_backtrace)
*/
.section .fixup,"ax"
.align 0
1004: ldr r0, =.Lbad
1007: ldr r0, =.Lbad
mov r1, frame
bl printk
LOADREGS(fd, sp!, {r4 - r8, pc})
......@@ -96,9 +103,12 @@ ENTRY(c_backtrace)
.section __ex_table,"a"
.align 3
.long 1001b, 1004b
.long 1002b, 1004b
.long 1003b, 1004b
.long 1001b, 1007b
.long 1002b, 1007b
.long 1003b, 1007b
.long 1004b, 1007b
.long 1005b, 1007b
.long 1006b, 1007b
.previous
#define instr r4
......
......@@ -50,7 +50,7 @@
*/
struct order {
struct page *queue;
struct list_head queue;
unsigned int mask; /* (1 << shift) - 1 */
unsigned int shift; /* (1 << shift) size of page */
unsigned int block_mask; /* nr_blocks - 1 */
......@@ -60,10 +60,10 @@ struct order {
static struct order orders[] = {
#if PAGE_SIZE == 4096
{ NULL, 2047, 11, 1, 0x00000003 }
{ LIST_HEAD_INIT(orders[0].queue), 2047, 11, 1, 0x00000003 }
#elif PAGE_SIZE == 32768
{ NULL, 2047, 11, 15, 0x0000ffff },
{ NULL, 8191, 13, 3, 0x0000000f }
{ LIST_HEAD_INIT(orders[0].queue), 2047, 11, 15, 0x0000ffff },
{ LIST_HEAD_INIT(orders[1].queue), 8191, 13, 3, 0x0000000f }
#else
#error unsupported page size
#endif
......@@ -75,70 +75,49 @@ static struct order orders[] = {
static spinlock_t small_page_lock = SPIN_LOCK_UNLOCKED;
static void add_page_to_queue(struct page *page, struct page **p)
{
#ifdef PEDANTIC
if (page->pprev_hash)
PAGE_BUG(page);
#endif
page->next_hash = *p;
if (*p)
(*p)->pprev_hash = &page->next_hash;
*p = page;
page->pprev_hash = p;
}
static void remove_page_from_queue(struct page *page)
{
if (page->pprev_hash) {
if (page->next_hash)
page->next_hash->pprev_hash = page->pprev_hash;
*page->pprev_hash = page->next_hash;
page->pprev_hash = NULL;
}
}
static unsigned long __get_small_page(int priority, struct order *order)
{
unsigned long flags;
struct page *page;
int offset;
if (!order->queue)
goto need_new_page;
do {
spin_lock_irqsave(&small_page_lock, flags);
if (list_empty(&order->queue))
goto need_new_page;
spin_lock_irqsave(&small_page_lock, flags);
page = order->queue;
page = list_entry(order->queue.next, struct page, list);
again:
#ifdef PEDANTIC
if (USED_MAP(page) & ~order->all_used)
PAGE_BUG(page);
if (USED_MAP(page) & ~order->all_used)
PAGE_BUG(page);
#endif
offset = ffz(USED_MAP(page));
SET_USED(page, offset);
if (USED_MAP(page) == order->all_used)
remove_page_from_queue(page);
spin_unlock_irqrestore(&small_page_lock, flags);
offset = ffz(USED_MAP(page));
SET_USED(page, offset);
if (USED_MAP(page) == order->all_used)
list_del_init(&page->list);
spin_unlock_irqrestore(&small_page_lock, flags);
return (unsigned long) page_address(page) + (offset << order->shift);
return (unsigned long) page_address(page) + (offset << order->shift);
need_new_page:
page = alloc_page(priority);
spin_lock_irqsave(&small_page_lock, flags);
if (!order->queue) {
if (!page)
goto no_page;
SetPageReserved(page);
USED_MAP(page) = 0;
cli();
add_page_to_queue(page, &order->queue);
} else {
spin_unlock_irqrestore(&small_page_lock, flags);
page = alloc_page(priority);
spin_lock_irqsave(&small_page_lock, flags);
if (list_empty(&order->queue)) {
if (!page)
goto no_page;
SetPageReserved(page);
USED_MAP(page) = 0;
list_add(&page->list, &order->queue);
goto again;
}
spin_unlock_irqrestore(&small_page_lock, flags);
__free_page(page);
cli();
page = order->queue;
}
goto again;
} while (1);
no_page:
spin_unlock_irqrestore(&small_page_lock, flags);
......@@ -173,7 +152,7 @@ static void __free_small_page(unsigned long spage, struct order *order)
spin_lock_irqsave(&small_page_lock, flags);
if (USED_MAP(page) == order->all_used)
add_page_to_queue(page, &order->queue);
list_add(&page->list, &order->queue);
if (!TEST_AND_CLEAR_USED(page, spage))
goto already_free;
......@@ -189,7 +168,7 @@ static void __free_small_page(unsigned long spage, struct order *order)
/*
* unlink the page from the small page queue and free it
*/
remove_page_from_queue(page);
list_del_init(&page->list);
spin_unlock_irqrestore(&small_page_lock, flags);
ClearPageReserved(page);
__free_page(page);
......
......@@ -53,4 +53,4 @@ static int __init personal_pci_init(void)
return 0;
}
subsys_initcall(&personal_pci_init);
subsys_initcall(personal_pci_init);
......@@ -56,6 +56,7 @@ static int __init integrator_init(void)
register_kmi(&integrator_keyboard);
register_kmi(&integrator_mouse);
#endif
return 0;
}
__initcall(integrator_init);
......
......@@ -3,7 +3,7 @@
*
* Copyright (C) 2001 Deep Blue Solutions Ltd.
*
* $Id: cpu.c,v 1.4 2002/05/29 11:41:55 rmk Exp $
* $Id: cpu.c,v 1.5 2002/07/06 16:53:17 rmk Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -121,8 +121,16 @@ static int __init cpu_init(void)
cpu_freq_khz = vco_to_freq(vco, 1);
#ifdef CONFIG_CPU_FREQ
cpufreq_init(cpu_freq_khz, 1000, 0);
cpufreq_setfunctions(integrator_validatespeed, integrator_setspeed);
{
struct cpufreq_driver cpufreq_driver;
cpufreq_driver.freq.min = 12000;
cpufreq_driver.freq.max = 160000;
cpufreq_driver.freq.cur = cpu_freq_khz;
cpufreq_driver.validate = &integrator_validatespeed;
cpufreq_driver.setspeed = &integrator_setspeed;
cpufreq_register(cpufreq_driver);
}
#endif
cm_stat = __raw_readl(CM_STAT);
......
......@@ -25,10 +25,11 @@
* format for those systems that do not already have PCI
* interrupts properly routed. We assume 1 <= pin <= 4
*/
#define PCI_IRQ_TABLE_LOOKUP(minid,maxid) \
({ int _ctl_ = -1; \
if (idsel >= minid && idsel <= maxid && pin >= 1 && pin <= 4) \
_ctl_ = pci_irq_table[idsel - minid][pin-1]; \
#define PCI_IRQ_TABLE_LOOKUP(minid,maxid) \
({ int _ctl_ = -1; \
unsigned int _idsel = idsel - minid; \
if (_idsel <= maxid) \
_ctl_ = pci_irq_table[_idsel][pin-1]; \
_ctl_; })
#define INTA IRQ_IQ80310_INTA
......@@ -64,6 +65,8 @@ iq80310_pri_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
{
irq_table *pci_irq_table;
BUG_ON(pin < 1 || pin > 4);
if (!system_rev) {
pci_irq_table = pci_pri_d_irq_table;
} else {
......@@ -99,6 +102,8 @@ iq80310_sec_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
{
irq_table *pci_irq_table;
BUG_ON(pin < 1 || pin > 4);
if (!system_rev) {
pci_irq_table = pci_sec_d_irq_table;
} else {
......
......@@ -59,7 +59,7 @@ static int __init adsbitsy_init(void)
/*
* Enable PWM control for LCD
*/
SKPCR |= SKPCR_PWMCLKEN;
sa1111_enable_device(SKPCR_PWMCLKEN);
SKPWM0 = 0x7F; // VEE
SKPEN0 = 1;
SKPWM1 = 0x01; // Backlight
......
......@@ -88,9 +88,21 @@ static int __init assabet_init(void)
return -EINVAL;
/*
* Set the IRQ edges
* Ensure that these pins are set as outputs and are driving
* logic 0. This ensures that we won't inadvertently toggle
* the WS latch in the CPLD, and we don't float causing
* excessive power drain. --rmk
*/
set_irq_type(IRQ_GPIO23, IRQT_RISING); /* UCB1300 */
GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
GPCR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
/*
* Set up registers for sleep mode.
*/
PWER = PWER_GPIO0;
PGSR = 0;
PCFR = 0;
PSDR = 0;
sa1100fb_lcd_power = assabet_lcd_power;
sa1100fb_backlight_power = assabet_backlight_power;
......@@ -254,13 +266,19 @@ static struct map_desc assabet_io_desc[] __initdata = {
static void __init assabet_map_io(void)
{
extern void neponset_map_io(void);
sa1100_map_io();
iotable_init(assabet_io_desc, ARRAY_SIZE(assabet_io_desc));
/*
* Set SUS bit in SDCR0 so serial port 1 functions.
* Its called GPCLKR0 in my SA1110 manual.
*/
Ser1SDCR0 |= SDCR0_SUS;
if (machine_has_neponset()) {
#ifdef CONFIG_ASSABET_NEPONSET
extern void neponset_map_io(void);
/*
* We map Neponset registers even if it isn't present since
* many drivers will try to probe their stuff (and fail).
......@@ -279,33 +297,11 @@ static void __init assabet_map_io(void)
*/
sa1100_register_uart(0, 3);
sa1100_register_uart(2, 1);
/*
* Set SUS bit in SDCR0 so serial port 1 functions.
* Its called GPCLKR0 in my SA1110 manual.
*/
Ser1SDCR0 |= SDCR0_SUS;
} else {
sa1100_register_uart_fns(&assabet_port_fns);
sa1100_register_uart(0, 1); /* com port */
sa1100_register_uart(2, 3); /* radio module */
}
/*
* Ensure that these pins are set as outputs and are driving
* logic 0. This ensures that we won't inadvertently toggle
* the WS latch in the CPLD, and we don't float causing
* excessive power drain. --rmk
*/
GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
GPCR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
/*
* Set up registers for sleep mode.
*/
PWER = PWER_GPIO0;
PGSR = 0;
PCFR = 0;
PSDR = 0;
}
......
......@@ -92,7 +92,7 @@
extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
extern unsigned int sa11x0_validatespeed(unsigned int khz);
extern unsigned int sa11x0_getspeed(void);
typedef struct {
int speed;
......@@ -187,7 +187,7 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed)
static int sa1100_dram_notifier(struct notifier_block *nb,
unsigned long val, void *data)
{
struct cpufreq_info *ci = data;
struct cpufreq_freqs *ci = data;
switch(val) {
case CPUFREQ_MINMAX:
......@@ -195,13 +195,13 @@ static int sa1100_dram_notifier(struct notifier_block *nb,
break;
case CPUFREQ_PRECHANGE:
if(ci->new_freq > ci->old_freq)
sa1100_update_dram_timings(ci->old_freq, ci->new_freq);
if(ci->new > ci->cur)
sa1100_update_dram_timings(ci->cur, ci->new);
break;
case CPUFREQ_POSTCHANGE:
if(ci->new_freq < ci->old_freq)
sa1100_update_dram_timings(ci->old_freq, ci->new_freq);
if(ci->new < ci->cur)
sa1100_update_dram_timings(ci->cur, ci->new);
break;
default:
......@@ -230,9 +230,19 @@ static int __init sa1100_dram_init(void)
int ret = -ENODEV;
if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) {
cpufreq_driver_t cpufreq_driver;
ret = cpufreq_register_notifier(&sa1100_dram_block);
if (ret)
return ret;
cpufreq_driver.freq.min = 59000;
cpufreq_driver.freq.max = 287000;
cpufreq_driver.freq.cur = sa11x0_getspeed();
cpufreq_driver.validate = &sa11x0_validatespeed;
cpufreq_driver.setspeed = &sa1100_setspeed;
cpufreq_setfunctions(sa11x0_validatespeed, sa1100_setspeed);
ret = cpufreq_register(cpufreq_driver);<
}
return ret;
......
......@@ -3,7 +3,7 @@
*
* Copyright (C) 2001 Russell King
*
* $Id: cpu-sa1110.c,v 1.8 2002/01/09 17:13:27 rmk Exp $
* $Id: cpu-sa1110.c,v 1.9 2002/07/06 16:53:18 rmk Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -31,6 +31,7 @@
extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
extern unsigned int sa11x0_validatespeed(unsigned int khz);
extern unsigned int sa11x0_getspeed(void);
struct sdram_params {
u_char rows; /* bits */
......@@ -88,6 +89,16 @@ static struct sdram_params samsung_km416s4030ct __initdata = {
cas_latency: 3,
};
static struct sdram_params wbond_w982516ah75l_cl3_params __initdata = {
rows: 16,
tck: 8,
trcd: 20,
trp: 20,
twr: 8,
refresh: 64000,
cas_latency: 3,
};
static struct sdram_params sdram_params;
/*
......@@ -287,6 +298,8 @@ static int __init sa1110_clk_init(void)
sdram = &samsung_km416s4030ct;
if (sdram) {
struct cpufreq_driver cpufreq_driver;
printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d"
" twr: %d refresh: %d cas_latency: %d\n",
sdram->tck, sdram->trcd, sdram->trp,
......@@ -294,8 +307,15 @@ static int __init sa1110_clk_init(void)
memcpy(&sdram_params, sdram, sizeof(sdram_params));
sa1110_setspeed(cpufreq_get(0));
cpufreq_setfunctions(sa11x0_validatespeed, sa1110_setspeed);
sa1110_setspeed(sa11x0_getspeed());
cpufreq_driver.freq.min = 59000;
cpufreq_driver.freq.max = 287000;
cpufreq_driver.freq.cur = sa11x0_getspeed();
cpufreq_driver.validate = &sa11x0_validatespeed;
cpufreq_driver.setspeed = &sa1110_setspeed;
return cpufreq_register(cpufreq_driver);
}
return 0;
......
......@@ -76,13 +76,10 @@ unsigned int sa11x0_validatespeed(unsigned int khz)
return cclk_frequency_100khz[sa11x0_freq_to_ppcr(khz)] * 100;
}
static int __init sa11x0_init_clock(void)
unsigned int sa11x0_getspeed(void)
{
cpufreq_init(cclk_frequency_100khz[PPCR & 0xf] * 100, 59000, 287000);
return 0;
return cclk_frequency_100khz[PPCR & 0xf] * 100;
}
__initcall(sa11x0_init_clock);
#else
/*
* We still need to provide this so building without cpufreq works.
......@@ -100,7 +97,7 @@ EXPORT_SYMBOL(cpufreq_get);
static void sa1100_power_off(void)
{
mdelay(100);
cli();
local_irq_disable();
/* disable internal oscillator, float CS lines */
PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS);
/* enable wake-up on GPIO0 (Assabet...) */
......
......@@ -49,7 +49,7 @@ static int __init graphicsmaster_init(void)
/*
* Enable PWM control for LCD
*/
SKPCR |= SKPCR_PWMCLKEN;
sa1111_enable_device(SKPCR_PWMCLKEN);
SKPWM0 = 0x7F; // VEE
SKPEN0 = 1;
SKPWM1 = 0x01; // Backlight
......
......@@ -55,6 +55,12 @@ static int sa1100_gpio_type(unsigned int irq, unsigned int type)
else
mask = GPIO11_27_MASK(irq);
if (type == IRQT_PROBE) {
if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
return 0;
type = __IRQT_RISEDGE | __IRQT_FALEDGE;
}
if (type & __IRQT_RISEDGE) {
GPIO_IRQ_rising_edge |= mask;
} else
......
......@@ -73,7 +73,7 @@ int pm_do_suspend(void)
{
unsigned long sleep_save[SLEEP_SAVE_SIZE];
cli();
local_irq_disable();
leds_event(led_stop);
......@@ -157,7 +157,7 @@ int pm_do_suspend(void)
leds_event(led_start);
sti();
local_irq_enable();
/*
* Restore the CPU frequency settings.
......
......@@ -117,11 +117,12 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
{
unsigned int mask = SA1111_IRQMASK_LO(irq);
if (flags == IRQT_PROBE)
return 0;
if ((!(flags & __IRQT_RISEDGE) ^ !(flags & __IRQT_FALEDGE)) == 0)
return -EINVAL;
printk("IRQ%d: %s edge\n", irq, flags & __IRQT_RISEDGE ? "rising" : "falling");
if (flags & __IRQT_RISEDGE)
INTPOL0 &= ~mask;
else
......@@ -181,11 +182,12 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
{
unsigned int mask = SA1111_IRQMASK_HI(irq);
if (flags == IRQT_PROBE)
return 0;
if ((!(flags & __IRQT_RISEDGE) ^ !(flags & __IRQT_FALEDGE)) == 0)
return -EINVAL;
printk("IRQ%d: %s edge\n", irq, flags & __IRQT_RISEDGE ? "rising" : "falling");
if (flags & __IRQT_RISEDGE)
INTPOL1 &= ~mask;
else
......@@ -302,7 +304,7 @@ sa1111_probe(struct device *parent, unsigned long phys_addr)
/*
* Probe for the chip. Only touch the SBI registers.
*/
id = readl(sa->base + SA1111_SKID);
id = sa1111_readl(sa->base + SA1111_SKID);
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id);
ret = -ENODEV;
......@@ -370,11 +372,11 @@ void sa1111_wake(void)
/*
* Turn VCO on, and disable PLL Bypass.
*/
r = readl(sa->base + SA1111_SKCR);
r = sa1111_readl(sa->base + SA1111_SKCR);
r &= ~SKCR_VCO_OFF;
writel(r, sa->base + SA1111_SKCR);
sa1111_writel(r, sa->base + SA1111_SKCR);
r |= SKCR_PLL_BYPASS | SKCR_OE_EN;
writel(r, sa->base + SA1111_SKCR);
sa1111_writel(r, sa->base + SA1111_SKCR);
/*
* Wait lock time. SA1111 manual _doesn't_
......@@ -386,7 +388,7 @@ void sa1111_wake(void)
* Enable RCLK. We also ensure that RDYEN is set.
*/
r |= SKCR_RCLKEN | SKCR_RDYEN;
writel(r, sa->base + SA1111_SKCR);
sa1111_writel(r, sa->base + SA1111_SKCR);
/*
* Wait 14 RCLK cycles for the chip to finish coming out
......@@ -397,7 +399,7 @@ void sa1111_wake(void)
/*
* Ensure all clocks are initially off.
*/
writel(0, sa->base + SA1111_SKPCR);
sa1111_writel(0, sa->base + SA1111_SKPCR);
local_irq_restore(flags);
}
......@@ -406,16 +408,18 @@ void sa1111_doze(void)
{
struct sa1111_device *sa = sa1111;
unsigned long flags;
unsigned int val;
local_irq_save(flags);
if (readl(sa->base + SA1111_SKPCR) & SKPCR_UCLKEN) {
if (sa1111_readl(sa->base + SA1111_SKPCR) & SKPCR_UCLKEN) {
local_irq_restore(flags);
printk("SA1111 doze mode refused\n");
return;
}
writel(readl(sa->base + SA1111_SKCR) & ~SKCR_RCLKEN, sa->base + SA1111_SKCR);
val = sa1111_readl(sa->base + SA1111_SKCR);
sa1111_writel(val & ~SKCR_RCLKEN, sa->base + SA1111_SKCR);
local_irq_restore(flags);
}
......@@ -430,9 +434,37 @@ void sa1111_configure_smc(int sdram, unsigned int drac, unsigned int cas_latency
if (cas_latency == 3)
smcr |= SMCR_CLAT;
writel(smcr, sa->base + SA1111_SMCR);
sa1111_writel(smcr, sa->base + SA1111_SMCR);
}
EXPORT_SYMBOL(sa1111_wake);
EXPORT_SYMBOL(sa1111_doze);
void sa1111_enable_device(unsigned int mask)
{
struct sa1111_device *sa = sa1111;
unsigned int val;
preempt_disable();
val = sa1111_readl(sa->base + SA1111_SKPCR);
sa1111_writel(val | mask, sa->base + SA1111_SKPCR);
preempt_enable();
}
void sa1111_disable_device(unsigned int mask)
{
struct sa1111_device *sa = sa1111;
unsigned int val;
preempt_disable();
val = sa1111_readl(sa->base + SA1111_SKPCR);
sa1111_writel(val & ~mask, sa->base + SA1111_SKPCR);
preempt_enable();
}
EXPORT_SYMBOL(sa1111_enable_device);
EXPORT_SYMBOL(sa1111_disable_device);
/* According to the "Intel StrongARM SA-1111 Microprocessor Companion
* Chip Specification Update" (June 2000), erratum #7, there is a
* significant bug in Serial Audio Controller DMA. If the SAC is
......@@ -527,7 +559,7 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq)
* We only need to turn on DCLK whenever we want to use the
* DMA. It can otherwise be held firmly in the off position.
*/
SKPCR |= SKPCR_DCLKEN;
sa1111_enable_device(SKPCR_DCLKEN);
/*
* Enable the SA1110 memory bus request and grant signals.
......
......@@ -13,6 +13,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/serial_sa1100.h>
#include <asm/arch/shannon.h>
#include "generic.h"
......@@ -23,13 +24,16 @@ static void __init shannon_map_io(void)
sa1100_register_uart(0, 3);
sa1100_register_uart(1, 1);
Ser1SDCR0 |= SDCR0_SUS;
GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD);
GPDR |= GPIO_UART_TXD;
GPDR |= GPIO_UART_TXD | SHANNON_GPIO_CODEC_RESET;
GPDR &= ~GPIO_UART_RXD;
PPAR |= PPAR_UPR;
set_GPIO_IRQ_edge(SHANNON_GPIO_IRQ_CODEC);
/* reset the codec */
GPCR = SHANNON_GPIO_CODEC_RESET;
GPSR = SHANNON_GPIO_CODEC_RESET;
}
MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
......
......@@ -44,7 +44,8 @@ ENTRY(sa1100_cpu_suspend)
mrc p15, 0, r7, c1, c0, 0 @ control reg
@ store them plus current virtual stack ptr on stack
stmfd sp!, {r4 - r7, sp}
mov r8, sp
stmfd sp!, {r4 - r8}
@ preserve phys address of stack
mov r0, sp
......
......@@ -309,7 +309,7 @@ static void system3_lcd_on(void)
PTCTRL0_set( PT_CTRL0_LCD_EN );
/* brightness / contrast */
SKPCR |= SKPCR_PWMCLKEN;
sa1111_enable_device(SKPCR_PWMCLKEN);
PB_DDR = 0xFFFFFFFF;
SKPEN0 = 1;
SKPEN1 = 1;
......@@ -325,7 +325,7 @@ static void system3_lcd_off(void)
PTCTRL0_clear( PT_CTRL0_LCD_EN );
SKPEN0 = 0;
SKPEN1 = 0;
SKPCR &= ~SKPCR_PWMCLKEN;
sa1111_disable_device(SKPCR_PWMCLKEN);
}
/**
......
......@@ -22,7 +22,7 @@
static void xp860_power_off(void)
{
cli();
local_irq_disable();
GPDR |= GPIO_GPIO20;
GPSR = GPIO_GPIO20;
mdelay(1000);
......
......@@ -42,7 +42,7 @@ p-$(CONFIG_CPU_SA1100) += proc-sa110.o tlb-v4wb.o copypage-v4mc.o abort-ev4.o
# ARMv5
p-$(CONFIG_CPU_ARM926T) += proc-arm926.o tlb-v4wb.o copypage-v4wb.o abort-ev5ej.o
p-$(CONFIG_CPU_XSCALE) += proc-xscale.o tlb-v4wb.o copypage-v5te.o abort-ev4t.o minicache.o
p-$(CONFIG_CPU_XSCALE) += proc-xscale.o tlb-v4wb.o copypage-xscale.o abort-xscale.o minicache.o
obj-y += $(sort $(p-y))
......
......@@ -7,7 +7,7 @@
* : r3 = saved SPSR
*
* Returns : r0 = address of abort
* : r1 = FSR, bit 8 = write
* : r1 = FSR, bit 11 = write
* : r2-r8 = corrupted
* : r9 = preserved
* : sp = pointer to registers
......@@ -22,8 +22,9 @@ ENTRY(v4_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
ldr r3, [r2] @ read aborted ARM instruction
bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
tst r3, #1 << 20 @ L = 1 -> write?
orreq r1, r1, #1 << 8 @ yes.
orreq r1, r1, #1 << 11 @ yes.
mov pc, lr
......@@ -7,7 +7,7 @@
* : r3 = saved SPSR
*
* Returns : r0 = address of abort
* : r1 = FSR, bit 8 = write
* : r1 = FSR, bit 11 = write
* : r2-r8 = corrupted
* : r9 = preserved
* : sp = pointer to registers
......@@ -24,8 +24,8 @@ ENTRY(v4t_early_abort)
tst r3, #PSR_T_BIT
ldrneh r3, [r2] @ read aborted thumb instruction
ldreq r3, [r2] @ read aborted ARM instruction
bic r1, r1, #1 << 8
bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
tst r3, #1 << 20 @ check write
orreq r1, r1, #1 << 8
orreq r1, r1, #1 << 11
mov pc, lr
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Function: v5ej_early_abort
* Function: v5tej_early_abort
*
* Params : r2 = address of aborted instruction
* : r3 = saved SPSR
*
* Returns : r0 = address of abort
* : r1 = FSR, bit 8 = write
* : r1 = FSR, bit 11 = write
* : r2-r8 = corrupted
* : r9 = preserved
* : sp = pointer to registers
......@@ -18,18 +18,19 @@
* picture. Unfortunately, this does happen. We live with it.
*/
.align 5
ENTRY(v5ej_early_abort)
ENTRY(v5tej_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
tst r3, #PSR_J_BIT
orrne r1, r1, #1 << 8 @ always assume write
orrne r1, r1, #1 << 11 @ always assume write
bne 1f
tst r3, #PSR_T_BIT
ldrneh r3, [r2] @ read aborted thumb instruction
ldreq r3, [r2] @ read aborted ARM instruction
movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
tst r3, #1 << 20 @ L = 1 -> write
orreq r1, r1, #1 << 8 @ yes.
orreq r1, r1, #1 << 11 @ yes.
1: mov pc, lr
......@@ -7,7 +7,7 @@
* : r3 = saved SPSR
*
* Returns : r0 = address of abort
* : r1 = FSR, bit 8 = writing
* : r1 = FSR, bit 11 = write
* : r2-r8 = corrupted
* : r9 = preserved
* : sp = pointer to registers
......@@ -21,10 +21,11 @@ ENTRY(v4t_late_abort)
tst r3, #PSR_T_BIT @ check for thumb mode
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
ldreq r8, [r2] @ read arm instruction
bne .data_thumb_abort
tst r8, #1 << 20 @ L = 1 -> write?
orreq r1, r1, #1 << 8 @ yes.
orreq r1, r1, #1 << 11 @ yes.
and r7, r8, #15 << 24
add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
nop
......
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Function: xscale_abort
*
* Params : r2 = address of aborted instruction
* : r3 = saved SPSR
*
* Returns : r0 = address of abort
* : r1 = FSR, bit 11 = write
* : r2-r8 = corrupted
* : r9 = preserved
* : sp = pointer to registers
*
* Purpose : obtain information about current aborted instruction.
* Note: we read user space. This means we might cause a data
* abort here if the I-TLB and D-TLB aren't seeing the same
* picture. Unfortunately, this does happen. We live with it.
*
* Note: Xscale is contains non-standard architecture extensions.
* It requires its own early abort handler
*/
.align 5
ENTRY(xscale_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
tst r3, #PSR_T_BIT
ldrneh r3, [r2] @ read aborted thumb instruction
ldreq r3, [r2] @ read aborted ARM instruction
bic r1, r1, #1 << 11 @ clear bits 11 of FSR
movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
tst r3, #1 << 20 @ check write
orreq r1, r1, #1 << 11
mov pc, lr
/*
* linux/arch/arm/lib/copypage-armv5te.S
* linux/arch/arm/lib/copypage-xscale.S
*
* Copyright (C) 2001 Russell King
*
......@@ -19,7 +19,7 @@
.text
.align 5
/*
* ARMv5TE optimised copy_user_page
* XScale optimised copy_user_page
* r0 = destination
* r1 = source
* r2 = virtual user address of ultimate destination page
......@@ -32,7 +32,7 @@
* page. We rely on the mini-cache being smaller than one page, so we'll
* cycle through the complete cache anyway.
*/
ENTRY(v5te_mc_copy_user_page)
ENTRY(xscale_mc_copy_user_page)
stmfd sp!, {r4, r5, lr}
mov r5, r0
mov r0, r1
......@@ -58,11 +58,11 @@ ENTRY(v5te_mc_copy_user_page)
.align 5
/*
* ARMv5TE optimised clear_user_page
* XScale optimised clear_user_page
* r0 = destination
* r1 = virtual user address of ultimate destination page
*/
ENTRY(v5te_mc_clear_user_page)
ENTRY(xscale_mc_clear_user_page)
str lr, [sp, #-4]!
mov r1, #PAGE_SZ/32
mov r2, #0
......@@ -80,6 +80,6 @@ ENTRY(v5te_mc_clear_user_page)
.section ".text.init", #alloc, #execinstr
ENTRY(v5te_mc_user_fns)
.long v5te_mc_clear_user_page
.long v5te_mc_copy_user_page
ENTRY(xscale_mc_user_fns)
.long xscale_mc_clear_user_page
.long xscale_mc_copy_user_page
......@@ -47,6 +47,10 @@ static struct fsr_info {
int sig;
const char *name;
} fsr_info[] = {
/*
* The following are the standard ARMv3 and ARMv4 aborts. ARMv5
* defines these to be "precise" aborts.
*/
{ do_bad, SIGSEGV, "vector exception" },
{ do_bad, SIGILL, "alignment exception" },
{ do_bad, SIGKILL, "terminal exception" },
......@@ -62,14 +66,35 @@ static struct fsr_info {
{ do_bad, SIGBUS, "external abort on translation" },
{ do_sect_fault, SIGSEGV, "section permission fault" },
{ do_bad, SIGBUS, "external abort on translation" },
{ do_page_fault, SIGSEGV, "page permission fault" }
{ do_page_fault, SIGSEGV, "page permission fault" },
/*
* The following are "imprecise" aborts, which are signalled by bit
* 10 of the FSR, and may not be recoverable. These are only
* supported if the CPU abort handler supports bit 10.
*/
{ do_bad, SIGBUS, "unknown 16" },
{ do_bad, SIGBUS, "unknown 17" },
{ do_bad, SIGBUS, "unknown 18" },
{ do_bad, SIGBUS, "unknown 19" },
{ do_bad, SIGBUS, "lock abort" }, /* xscale */
{ do_bad, SIGBUS, "unknown 21" },
{ do_bad, SIGBUS, "imprecise external abort" }, /* xscale */
{ do_bad, SIGBUS, "unknown 23" },
{ do_bad, SIGBUS, "dcache parity error" }, /* xscale */
{ do_bad, SIGBUS, "unknown 25" },
{ do_bad, SIGBUS, "unknown 26" },
{ do_bad, SIGBUS, "unknown 27" },
{ do_bad, SIGBUS, "unknown 28" },
{ do_bad, SIGBUS, "unknown 29" },
{ do_bad, SIGBUS, "unknown 30" },
{ do_bad, SIGBUS, "unknown 31" }
};
void __init
hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
int sig, const char *name)
{
if (nr >= 0 && nr < 16) {
if (nr >= 0 && nr < ARRAY_SIZE(fsr_info)) {
fsr_info[nr].fn = fn;
fsr_info[nr].sig = sig;
fsr_info[nr].name = name;
......@@ -82,7 +107,7 @@ hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *)
asmlinkage void
do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
const struct fsr_info *inf = fsr_info + (fsr & 15);
const struct fsr_info *inf = fsr_info + (fsr & 15) + ((fsr & (1 << 10)) >> 6);
if (!inf->fn(addr, fsr, regs))
return;
......
......@@ -34,12 +34,10 @@
#define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE))
#else
/*
* On 32-bit processors, we define "mode" to be zero when reading,
* non-zero when writing. This now ties up nicely with the polarity
* of the 26-bit machines, and also means that we avoid the horrible
* gcc code for "int val = !other_val;".
* "code" is actually the FSR register. Bit 11 set means the
* isntruction was performing a write.
*/
#define DO_COW(code) ((code) & (1 << 8))
#define DO_COW(code) ((code) & (1 << 11))
#define READ_FAULT(code) (!DO_COW(code))
#endif
......@@ -56,7 +54,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
printk(KERN_ALERT "pgd = %p\n", mm->pgd);
pgd = pgd_offset(mm, addr);
printk(KERN_ALERT "*pgd = %08lx", pgd_val(*pgd));
printk(KERN_ALERT "*pgd=%08lx", pgd_val(*pgd));
do {
pmd_t *pmd;
......@@ -71,7 +69,9 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
}
pmd = pmd_offset(pgd, addr);
printk(", *pmd = %08lx", pmd_val(*pmd));
#if PTRS_PER_PMD != 1
printk(", *pmd=%08lx", pmd_val(*pmd));
#endif
if (pmd_none(*pmd))
break;
......@@ -84,9 +84,9 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
#ifndef CONFIG_HIGHMEM
/* We must not map this if we have highmem enabled */
pte = pte_offset_map(pmd, addr);
printk(", *pte = %08lx", pte_val(*pte));
printk(", *pte=%08lx", pte_val(*pte));
#ifdef CONFIG_CPU_32
printk(", *ppte = %08lx", pte_val(pte[-PTRS_PER_PTE]));
printk(", *ppte=%08lx", pte_val(pte[-PTRS_PER_PTE]));
#endif
pte_unmap(pte);
#endif
......
......@@ -394,8 +394,6 @@ ENTRY(cpu_arm1020_set_pmd)
*/
.align 5
ENTRY(cpu_arm1020_set_pte)
tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
......@@ -553,7 +551,7 @@ __arm1020_proc_info:
b __arm1020_setup
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
.long cpu_arm1020_info
.long arm1020_processor_functions
.long v4wbi_tlb_fns
......
......@@ -272,8 +272,6 @@ ENTRY(cpu_arm7_set_pmd)
.align 5
ENTRY(cpu_arm6_set_pte)
ENTRY(cpu_arm7_set_pte)
tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
......
......@@ -135,8 +135,6 @@ ENTRY(cpu_arm720_set_pmd)
*/
.align 5
ENTRY(cpu_arm720_set_pte)
tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
......@@ -257,7 +255,7 @@ __arm720_proc_info:
b __arm720_setup @ cpu_flush
.long cpu_arch_name @ arch_name
.long cpu_elf_name @ elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_26BIT @ elf_hwcap
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB @ elf_hwcap
.long cpu_arm720_info @ info
.long arm720_processor_functions
.long v4_tlb_fns
......
......@@ -539,7 +539,7 @@ __arm920_proc_info:
b __arm920_setup
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
.long cpu_arm920_info
.long arm920_processor_functions
.long v4wbi_tlb_fns
......
......@@ -395,8 +395,6 @@ ENTRY(cpu_arm922_set_pmd)
*/
.align 5
ENTRY(cpu_arm922_set_pte)
tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
......@@ -540,7 +538,7 @@ __arm922_proc_info:
b __arm922_setup
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
.long cpu_arm922_info
.long arm922_processor_functions
.long v4wbi_tlb_fns
......
/*
* linux/arch/arm/mm/arm926.S: MMU functions for ARM926EJ-S
* linux/arch/arm/mm/proc-arm926.S: MMU functions for ARM926EJ-S
*
* Copyright (C) 1999-2001 ARM Limited
* Copyright (C) 2000 Deep Blue Solutions Ltd.
......@@ -378,8 +378,6 @@ ENTRY(cpu_arm926_set_pmd)
*/
.align 5
ENTRY(cpu_arm926_set_pte)
tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
......@@ -442,7 +440,7 @@ __arm926_setup:
mcr p15, 0, r4, c2, c0 @ load page table pointer
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
mov r0, #4 @ disable write-back on caches explicitly
mcr p15, 7, r0, c15, c0, 0
#endif
......@@ -483,7 +481,7 @@ __arm926_setup:
*/
.type arm926_processor_functions, #object
arm926_processor_functions:
.word v5ej_early_abort
.word v5tej_early_abort
.word cpu_arm926_check_bugs
.word cpu_arm926_proc_init
.word cpu_arm926_proc_fin
......@@ -519,12 +517,12 @@ cpu_arm926_info:
.type cpu_arch_name, #object
cpu_arch_name:
.asciz "armv5EJ"
.asciz "armv5tej"
.size cpu_arch_name, . - cpu_arch_name
.type cpu_elf_name, #object
cpu_elf_name:
.asciz "v5EJ"
.asciz "v5"
.size cpu_elf_name, . - cpu_elf_name
.align
......@@ -538,7 +536,8 @@ __arm926_proc_info:
b __arm926_setup
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | \
HWCAP_FAST_MULT | HWCAP_JAVA
.long cpu_arm926_info
.long arm926_processor_functions
.long v4wbi_tlb_fns
......
......@@ -602,8 +602,6 @@ ENTRY(cpu_xscale_set_pmd)
*/
.align 5
ENTRY(cpu_xscale_set_pte)
tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
bic r2, r1, #0xff0
......@@ -681,6 +679,9 @@ __xscale_setup:
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
mov r0, #0x1f @ Domains 0, 1 = client
mcr p15, 0, r0, c3, c0, 0 @ load domain access register
mov r0, #1 @ Allow access to CP0 and CP13
orr r0, r0, #1 << 13 @ Its undefined whether this
mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes
mrc p15, 0, r0, c1, c0, 0 @ get control register
bic r0, r0, #0x0200 @ .... ..R. .... ....
bic r0, r0, #0x0082 @ .... .... B... ..A.
......@@ -697,7 +698,7 @@ __xscale_setup:
.type xscale_processor_functions, #object
ENTRY(xscale_processor_functions)
.word v4t_early_abort
.word xscale_abort
.word cpu_xscale_check_bugs
.word cpu_xscale_proc_init
.word cpu_xscale_proc_fin
......@@ -739,7 +740,7 @@ cpu_pxa250_info:
.type cpu_arch_name, #object
cpu_arch_name:
.asciz "armv5"
.asciz "armv5te"
.size cpu_arch_name, . - cpu_arch_name
.type cpu_elf_name, #object
......@@ -762,7 +763,7 @@ __80200_proc_info:
.long cpu_80200_info
.long xscale_processor_functions
.long v4wbi_tlb_fns
.long v5te_mc_user_fns
.long xscale_mc_user_fns
.size __80200_proc_info, . - __80200_proc_info
.type __pxa250_proc_info,#object
......@@ -777,6 +778,6 @@ __pxa250_proc_info:
.long cpu_pxa250_info
.long xscale_processor_functions
.long v4wbi_tlb_fns
.long v5te_mc_user_fns
.long xscale_mc_user_fns
.size __pxa250_proc_info, . - __pxa250_proc_info
......@@ -142,9 +142,6 @@ void FPA11_CheckInit(void)
unsigned int EmulateAll(unsigned int opcode)
{
unsigned int nRc = 1, code;
unsigned long flags;
save_flags(flags); sti();
code = opcode & 0x00000f00;
if (code == 0x00000100 || code == 0x00000200)
......@@ -180,8 +177,6 @@ unsigned int EmulateAll(unsigned int opcode)
}
}
restore_flags(flags);
return(nRc);
}
......
......@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk
#
# Last update: Tue May 21 14:19:05 2002
# Last update: Fri Jul 5 21:32:20 2002
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
......@@ -192,3 +192,18 @@ ks8695 ARCH_KS8695 KS8695 180
brh ARCH_BRH BRH 181
s3c2410 ARCH_S3C2410 S3C2410 182
possio_px30 ARCH_POSSIO_PX30 POSSIO_PX30 183
s3c2800 ARCH_S3C2800 S3C2800 184
fleetwood SA1100_FLEETWOOD FLEETWOOD 185
omaha ARCH_OMAHA OMAHA 186
ta7 ARCH_TA7 TA7 187
nova SA1100_NOVA NOVA 188
hmk ARCH_HMK HMK 189
inphinity ARCH_INPHINITY INPHINITY 190
fester SA1100_FESTER FESTER 191
gpi ARCH_GPI GPI 192
smdk2410 ARCH_SMDK2410 SMDK2410 193
premium ARCH_PREMIUM PREMIUM 194
nexio SA1100_NEXIO NEXIO 195
bitbox SA1100_BITBOX BITBOX 196
g200 SA1100_G200 G200 197
gill SA1100_GILL GILL 198
......@@ -8,10 +8,9 @@ jiffies = jiffies_64;
SECTIONS
{
. = TEXTADDR;
.init : {
.init : { /* Init code and data */
_stext = .;
__init_begin = .; /* Init code and data */
__init_begin = .;
*(.text.init)
__proc_info_begin = .;
*(.proc.info)
......@@ -50,7 +49,7 @@ SECTIONS
*(.exitcall.exit)
}
.text : {
.text : { /* Real text segment */
_text = .; /* Text and read-only data */
*(.text)
*(.fixup)
......@@ -59,19 +58,24 @@ SECTIONS
*(.rodata.*)
*(.glue_7)
*(.glue_7t)
*(.kstrtab)
. = ALIGN(16); /* Exception table */
*(.got) /* Global offset table */
_etext = .; /* End of text section */
}
.kstrtab : { *(.kstrtab) }
. = ALIGN(16);
__ex_table : { /* Exception table */
__start___ex_table = .;
*(__ex_table)
__stop___ex_table = .;
}
__start___ksymtab = .; /* Kernel symbol table */
__ksymtab : { /* Kernel symbol table */
__start___ksymtab = .;
*(__ksymtab)
__stop___ksymtab = .;
*(.got) /* Global offset table */
_etext = .; /* End of text section */
}
.data : {
......@@ -90,14 +94,12 @@ SECTIONS
_edata = .;
}
.bss : {
__bss_start = .; /* BSS */
*(.bss)
*(COMMON)
_end = . ;
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
......
......@@ -703,11 +703,11 @@ static ide_startstop_t etrax_dma_intr(struct ata_device *drive, struct request *
i -= rq->current_nr_sectors;
ide_end_request(drive, rq, 1);
}
return ide_stopped;
return ATA_OP_FINISHED;
}
printk("%s: bad DMA status\n", drive->name);
}
return ata_error(drive, __FUNCTION__);
return ata_error(drive, rq, __FUNCTION__);
}
/*
......
......@@ -389,10 +389,7 @@ CONFIG_SCSI_FCAL=m
# Fusion MPT device support
#
CONFIG_FUSION=m
#
# (ability to boot linux kernel from Fusion device is DISABLED!)
#
# CONFIG_FUSION_BOOT is not set
CONFIG_FUSION_ISENSE=m
CONFIG_FUSION_CTL=m
CONFIG_FUSION_LAN=m
......@@ -576,22 +573,51 @@ CONFIG_DRM_TDFX=m
# Input device support
#
CONFIG_INPUT=y
#
# Userland interfaces
#
CONFIG_INPUT_KEYBDEV=y
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_TSDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
#
# Input I/O drivers
#
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
# CONFIG_GAMEPORT_NS558 is not set
# CONFIG_GAMEPORT_L4 is not set
# CONFIG_INPUT_EMU10K1 is not set
# CONFIG_GAMEPORT_PCIGAME is not set
# CONFIG_GAMEPORT_VORTEX is not set
# CONFIG_GAMEPORT_FM801 is not set
# CONFIG_GAMEPORT_CS461x is not set
# CONFIG_SERIO is not set
# CONFIG_SERIO_I8042 is not set
# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PARKBD is not set
#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_ATKBD is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_PS2SERKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
CONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_PS2 is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_INPORT is not set
# CONFIG_MOUSE_LOGIBM is not set
# CONFIG_MOUSE_PC110PAD is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_JOYSTICK_ANALOG is not set
# CONFIG_JOYSTICK_A3D is not set
......@@ -599,6 +625,7 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_JOYSTICK_COBRA is not set
# CONFIG_JOYSTICK_GF2K is not set
# CONFIG_JOYSTICK_GRIP is not set
# CONFIG_JOYSTICK_GUILLEMOT is not set
# CONFIG_JOYSTICK_INTERACT is not set
# CONFIG_JOYSTICK_SIDEWINDER is not set
# CONFIG_JOYSTICK_TMDC is not set
......@@ -609,9 +636,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_JOYSTICK_SPACEORB is not set
# CONFIG_JOYSTICK_SPACEBALL is not set
# CONFIG_JOYSTICK_STINGER is not set
# CONFIG_JOYSTICK_TWIDDLER is not set
# CONFIG_JOYSTICK_DB9 is not set
# CONFIG_JOYSTICK_GAMECON is not set
# CONFIG_JOYSTICK_TURBOGRAFX is not set
# CONFIG_INPUT_JOYDUMP is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_TOUCHSCREEN_GUNZE is not set
#
# File systems
......@@ -780,7 +811,6 @@ CONFIG_USB_DEVICEFS=y
#
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_UHCI_HCD_ALT is not set
#
......
......@@ -136,6 +136,16 @@ struct elf_prpsinfo32
#define NEW_TO_OLD_UID(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
#define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
#include <linux/time.h>
#define jiffies_to_timeval jiffies_to_timeval32
static __inline__ void
jiffies_to_timeval32(unsigned long jiffies, struct timeval32 *value)
{
value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
value->tv_sec = jiffies / HZ;
}
#define elf_addr_t u32
#define elf_caddr_t u32
#undef start_thread
......
......@@ -1202,6 +1202,26 @@ struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
return rq;
}
/*
* Non-locking blk_get_request variant, for special requests from drivers.
*/
struct request *__blk_get_request(request_queue_t *q, int rw)
{
struct request *rq;
BUG_ON(rw != READ && rw != WRITE);
rq = get_request(q, rw);
if (rq) {
rq->flags = 0;
rq->buffer = NULL;
rq->bio = rq->biotail = NULL;
rq->waiting = NULL;
}
return rq;
}
void blk_put_request(struct request *rq)
{
blkdev_release_request(rq);
......@@ -1381,6 +1401,14 @@ void blk_attempt_remerge(request_queue_t *q, struct request *rq)
spin_unlock_irqrestore(q->queue_lock, flags);
}
/*
* Non-locking blk_attempt_remerge variant.
*/
void __blk_attempt_remerge(request_queue_t *q, struct request *rq)
{
attempt_back_merge(q, rq);
}
static int __make_request(request_queue_t *q, struct bio *bio)
{
struct request *req, *freereq = NULL;
......@@ -2039,6 +2067,7 @@ EXPORT_SYMBOL(generic_unplug_device);
EXPORT_SYMBOL(blk_plug_device);
EXPORT_SYMBOL(blk_remove_plug);
EXPORT_SYMBOL(blk_attempt_remerge);
EXPORT_SYMBOL(__blk_attempt_remerge);
EXPORT_SYMBOL(blk_max_low_pfn);
EXPORT_SYMBOL(blk_max_pfn);
EXPORT_SYMBOL(blk_queue_max_sectors);
......@@ -2055,6 +2084,7 @@ EXPORT_SYMBOL(blk_queue_assign_lock);
EXPORT_SYMBOL(blk_phys_contig_segment);
EXPORT_SYMBOL(blk_hw_contig_segment);
EXPORT_SYMBOL(blk_get_request);
EXPORT_SYMBOL(__blk_get_request);
EXPORT_SYMBOL(blk_put_request);
EXPORT_SYMBOL(blk_queue_prep_rq);
......
......@@ -176,7 +176,6 @@ static int hci_usb_rx_submit(struct hci_usb *husb, struct urb *urb)
pipe = usb_rcvbulkpipe(husb->udev, husb->bulk_in_ep);
FILL_BULK_URB(urb, husb->udev, pipe, skb->data, size, hci_usb_rx_complete, skb);
urb->transfer_flags = USB_QUEUE_BULK;
skb_queue_tail(&husb->pending_q, skb);
err = usb_submit_urb(urb, GFP_ATOMIC);
......@@ -318,7 +317,7 @@ static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb)
FILL_BULK_URB(urb, husb->udev, pipe, skb->data, skb->len,
hci_usb_tx_complete, skb);
urb->transfer_flags = USB_QUEUE_BULK | USB_ZERO_PACKET;
urb->transfer_flags = USB_ZERO_PACKET;
BT_DBG("%s urb %p len %d", husb->hdev.name, urb, skb->len);
......
......@@ -8,8 +8,8 @@
* device are used to bind the other minor numbers to block devices.
*/
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/iobuf.h>
#include <linux/major.h>
#include <linux/blkdev.h>
#include <linux/raw.h>
......@@ -86,12 +86,6 @@ int raw_open(struct inode *inode, struct file *filp)
return 0;
}
if (!filp->f_iobuf) {
err = alloc_kiovec(1, &filp->f_iobuf);
if (err)
return err;
}
down(&raw_devices[minor].mutex);
/*
* No, it is a normal raw device. All we need to do on open is
......@@ -256,124 +250,46 @@ int raw_ctl_ioctl(struct inode *inode,
return err;
}
ssize_t raw_read(struct file *filp, char * buf,
size_t size, loff_t *offp)
ssize_t raw_read(struct file *filp, char * buf, size_t size, loff_t *offp)
{
return rw_raw_dev(READ, filp, buf, size, offp);
}
ssize_t raw_write(struct file *filp, const char *buf,
size_t size, loff_t *offp)
ssize_t raw_write(struct file *filp, const char *buf, size_t size, loff_t *offp)
{
return rw_raw_dev(WRITE, filp, (char *) buf, size, offp);
}
#define SECTOR_BITS 9
#define SECTOR_SIZE (1U << SECTOR_BITS)
#define SECTOR_MASK (SECTOR_SIZE - 1)
ssize_t rw_raw_dev(int rw, struct file *filp, char *buf,
size_t size, loff_t *offp)
ssize_t
rw_raw_dev(int rw, struct file *filp, char *buf, size_t size, loff_t *offp)
{
struct kiobuf * iobuf;
int new_iobuf;
int err = 0;
unsigned long blocks;
size_t transferred;
int iosize;
int minor;
kdev_t dev;
unsigned long limit;
int sector_size, sector_bits, sector_mask;
sector_t blocknr;
struct block_device *bdev;
/*
* First, a few checks on device size limits
*/
struct inode *inode;
int minor;
ssize_t ret = 0;
minor = minor(filp->f_dentry->d_inode->i_rdev);
new_iobuf = 0;
iobuf = filp->f_iobuf;
if (test_and_set_bit(0, &filp->f_iobuf_lock)) {
/*
* A parallel read/write is using the preallocated iobuf
* so just run slow and allocate a new one.
*/
err = alloc_kiovec(1, &iobuf);
if (err)
goto out;
new_iobuf = 1;
}
bdev = raw_devices[minor].binding;
dev = to_kdev_t(bdev->bd_dev);
sector_size = raw_devices[minor].sector_size;
sector_bits = raw_devices[minor].sector_bits;
sector_mask = sector_size - 1;
limit = bdev->bd_inode->i_size >> sector_bits;
if (!limit)
limit = INT_MAX;
dprintk ("rw_raw_dev: dev %d:%d (+%d)\n",
major(dev), minor(dev), limit);
err = -EINVAL;
if ((*offp & sector_mask) || (size & sector_mask))
goto out_free;
err = 0;
if (size)
err = -ENXIO;
if ((*offp >> sector_bits) >= limit)
goto out_free;
transferred = 0;
blocknr = *offp >> sector_bits;
while (size > 0) {
blocks = size >> sector_bits;
if (blocks > limit - blocknr)
blocks = limit - blocknr;
if (!blocks)
break;
iosize = blocks << sector_bits;
inode = bdev->bd_inode;
err = map_user_kiobuf(rw, iobuf, (unsigned long) buf, iosize);
if (err)
break;
err = brw_kiovec(rw, 1, &iobuf, raw_devices[minor].binding, &blocknr, sector_size);
if (rw == READ && err > 0)
mark_dirty_kiobuf(iobuf, err);
if (err >= 0) {
transferred += err;
size -= err;
buf += err;
}
blocknr += blocks;
unmap_kiobuf(iobuf);
if (err != iosize)
break;
if (size == 0)
goto out;
if (size < 0) {
ret = -EINVAL;
goto out;
}
if (transferred) {
*offp += transferred;
err = transferred;
if (*offp >= inode->i_size) {
ret = -ENXIO;
goto out;
}
out_free:
if (!new_iobuf)
clear_bit(0, &filp->f_iobuf_lock);
else
free_kiovec(1, &iobuf);
out:
return err;
if (size + *offp > inode->i_size)
size = inode->i_size - *offp;
ret = generic_file_direct_IO(rw, inode, buf, *offp, size);
if (ret > 0)
*offp += ret;
if (inode->i_mapping->nrpages)
invalidate_inode_pages2(inode->i_mapping);
out:
return ret;
}
......@@ -994,7 +994,7 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
*/
fc->rst_pkt->host->eh_action = &sem;
fc->rst_pkt->request.rq_status = RQ_SCSI_BUSY;
fc->rst_pkt->request->rq_status = RQ_SCSI_BUSY;
fc->rst_pkt->done = fcp_scsi_reset_done;
fcp_scsi_queue_it(fc, fc->rst_pkt, fcmd, 0);
......
......@@ -160,16 +160,15 @@ static void aec62xx_tune_drive(struct ata_device *drive, unsigned char pio)
}
#ifdef CONFIG_BLK_DEV_IDEDMA
static int aec62xx_udma_setup(struct ata_device *drive)
static int __init aec62xx_modes_map(struct ata_channel *ch)
{
u32 bmide = pci_resource_start(drive->channel->pci_dev, 4);
short speed;
u32 bmide = pci_resource_start(ch->pci_dev, 4);
int map;
map = XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA | XFER_SWDMA | XFER_UDMA;
map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA | XFER_UDMA;
if (drive->channel->udma_four)
switch (drive->channel->pci_dev->device) {
if (ch->udma_four)
switch (ch->pci_dev->device) {
case PCI_DEVICE_ID_ARTOP_ATP865R:
case PCI_DEVICE_ID_ARTOP_ATP865:
/* Can't use these modes simultaneously,
......@@ -180,11 +179,7 @@ static int aec62xx_udma_setup(struct ata_device *drive)
map |= XFER_UDMA_66;
}
speed = ata_timing_mode(drive, map);
aec_set_drive(drive, speed);
udma_enable(drive, drive->channel->autodma && (speed & XFER_MODE) != XFER_PIO, 0);
return 0;
return map;
}
#endif
......@@ -256,11 +251,12 @@ static void __init aec62xx_init_channel(struct ata_channel *ch)
ch->tuneproc = aec62xx_tune_drive;
ch->speedproc = aec_set_drive;
ch->autodma = 0;
ch->io_32bit = 1;
ch->unmask = 1;
ch->udma_four = aec62xx_ata66_check(ch);
for (i = 0; i < 2; i++) {
ch->drives[i].autotune = 1;
ch->drives[i].dn = ch->unit * 2 + i;
......@@ -269,11 +265,8 @@ static void __init aec62xx_init_channel(struct ata_channel *ch)
#ifdef CONFIG_BLK_DEV_IDEDMA
if (ch->dma_base) {
ch->highmem = 1;
ch->udma_setup = aec62xx_udma_setup;
#ifdef CONFIG_IDEDMA_AUTO
if (!noautodma)
ch->autodma = 1;
#endif
ch->modes_map = aec62xx_modes_map(ch);
ch->udma_setup = udma_generic_setup;
}
#endif
}
......@@ -306,17 +299,15 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_ARTOP,
device: PCI_DEVICE_ID_ARTOP_ATP860,
init_chipset: aec62xx_init_chipset,
ata66_check: aec62xx_ata66_check,
init_channel: aec62xx_init_channel,
enablebits: { {0x4a,0x02,0x02}, {0x4a,0x04,0x04} },
bootable: NEVER_BOARD,
flags: ATA_F_IRQ | ATA_F_NOADMA | ATA_F_DMA
flags: ATA_F_IRQ | ATA_F_DMA
},
{
vendor: PCI_VENDOR_ID_ARTOP,
device: PCI_DEVICE_ID_ARTOP_ATP860R,
init_chipset: aec62xx_init_chipset,
ata66_check: aec62xx_ata66_check,
init_channel: aec62xx_init_channel,
enablebits: { {0x4a,0x02,0x02}, {0x4a,0x04,0x04} },
bootable: OFF_BOARD,
......@@ -326,7 +317,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_ARTOP,
device: PCI_DEVICE_ID_ARTOP_ATP865,
init_chipset: aec62xx_init_chipset,
ata66_check: aec62xx_ata66_check,
init_channel: aec62xx_init_channel,
enablebits: { {0x4a,0x02,0x02}, {0x4a,0x04,0x04} },
bootable: NEVER_BOARD,
......@@ -336,7 +326,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_ARTOP,
device: PCI_DEVICE_ID_ARTOP_ATP865R,
init_chipset: aec62xx_init_chipset,
ata66_check: aec62xx_ata66_check,
init_channel: aec62xx_init_channel,
enablebits: { {0x4a,0x02,0x02}, {0x4a,0x04,0x04} },
bootable: OFF_BOARD,
......
......@@ -99,43 +99,6 @@ static void ali15x3_tune_drive(struct ata_device *drive, byte pio)
__restore_flags(flags);
}
static byte ali15x3_can_ultra(struct ata_device *drive)
{
if (m5229_revision <= 0x20) {
return 0;
} else if ((m5229_revision < 0xC2) &&
#ifndef CONFIG_WDC_ALI15X3
((chip_is_1543c_e && strstr(drive->id->model, "WDC ")) ||
(drive->type != ATA_DISK))) {
#else
(drive->type != ATA_DISK)) {
#endif
return 0;
} else {
return 1;
}
}
static int ali15x3_ratemask(struct ata_device *drive)
{
int map = 0;
if (!ali15x3_can_ultra(drive))
return 0;
map |= XFER_UDMA;
if (!eighty_ninty_three(drive))
return map;
if (m5229_revision >= 0xC4)
map |= XFER_UDMA_100;
if (m5229_revision >= 0xC2)
map |= XFER_UDMA_66;
return map;
}
static int ali15x3_tune_chipset(struct ata_device *drive, byte speed)
{
struct pci_dev *dev = drive->channel->pci_dev;
......@@ -156,6 +119,7 @@ static int ali15x3_tune_chipset(struct ata_device *drive, byte speed)
if (speed < XFER_SW_DMA_0)
ali15x3_tune_drive(drive, speed);
#ifdef CONFIG_BLK_DEV_IDEDMA
/* FIXME: no support for MWDMA and SWDMA modes --bkz */
else if (speed >= XFER_UDMA_0) {
pci_read_config_byte(dev, m5229_udma, &tmpbyte);
tmpbyte &= (0x0f << ((1-unit) << 2));
......@@ -176,91 +140,40 @@ static int ali15x3_tune_chipset(struct ata_device *drive, byte speed)
}
#ifdef CONFIG_BLK_DEV_IDEDMA
static int config_chipset_for_dma(struct ata_device *drive, u8 udma)
static int ali15x3_udma_setup(struct ata_device *drive, int map)
{
int map;
u8 mode;
if (udma)
map = ali15x3_ratemask(drive);
else
map = XFER_SWDMA | XFER_MWDMA;
mode = ata_timing_mode(drive, map);
if (mode < XFER_SW_DMA_0)
return 0;
return !ali15x3_tune_chipset(drive, mode);
#ifndef CONFIG_WDC_ALI15X3
if ((m5229_revision < 0xC2) && chip_is_1543c_e &&
strstr(drive->id->model, "WDC "))
map &= ~XFER_UDMA_ALL;
#endif
return udma_generic_setup(drive, map);
}
static int ali15x3_udma_setup(struct ata_device *drive)
static int ali15x3_udma_init(struct ata_device *drive, struct request *rq)
{
struct hd_driveid *id = drive->id;
struct ata_channel *hwif = drive->channel;
int on = 1;
int verbose = 1;
byte can_ultra_dma = ali15x3_can_ultra(drive);
if ((m5229_revision < 0xC2) && (drive->type != ATA_DISK))
return ATA_OP_FINISHED; /* try PIO instead of DMA */
if ((m5229_revision<=0x20) && (drive->type != ATA_DISK)) {
udma_enable(drive, 0, 0);
return 0;
}
return udma_pci_init(drive, rq);
}
if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma) {
/* Consult the list of known "bad" drives */
if (udma_black_list(drive)) {
on = 0;
goto fast_ata_pio;
}
on = 0;
verbose = 0;
if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) {
if (id->dma_ultra & 0x003F) {
/* Force if Capable UltraDMA */
on = config_chipset_for_dma(drive, can_ultra_dma);
if ((id->field_valid & 2) &&
(!on))
goto try_dma_modes;
}
} else if (id->field_valid & 2) {
try_dma_modes:
if ((id->dma_mword & 0x0007) ||
(id->dma_1word & 0x0007)) {
/* Force if Capable regular DMA modes */
on = config_chipset_for_dma(drive, can_ultra_dma);
if (!on)
goto no_dma_set;
}
} else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) {
goto no_dma_set;
}
/* Consult the list of known "good" drives */
on = config_chipset_for_dma(drive, can_ultra_dma);
if (!on)
goto no_dma_set;
} else {
goto fast_ata_pio;
}
} else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio:
on = 0;
verbose = 0;
no_dma_set:
ali15x3_tune_drive(drive, 255);
}
static int __init ali15x3_modes_map(struct ata_channel *ch)
{
int map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA;
udma_enable(drive, on, verbose);
if (m5229_revision <= 0x20)
return map;
return 0;
}
map |= XFER_UDMA;
static int ali15x3_udma_init(struct ata_device *drive, struct request *rq)
{
if ((m5229_revision < 0xC2) && (drive->type != ATA_DISK))
return ide_stopped; /* try PIO instead of DMA */
if (m5229_revision >= 0xC2) {
map |= XFER_UDMA_66;
if (m5229_revision >= 0xC4)
map |= XFER_UDMA_100;
}
return udma_pci_init(drive, rq);
return map;
}
#endif
......@@ -426,6 +339,8 @@ static void __init ali15x3_init_channel(struct ata_channel *hwif)
}
#endif /* CONFIG_SPARC64 */
hwif->udma_four = ali15x3_ata66_check(hwif);
hwif->tuneproc = &ali15x3_tune_drive;
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
......@@ -436,22 +351,21 @@ static void __init ali15x3_init_channel(struct ata_channel *hwif)
/*
* M1543C or newer for DMAing
*/
hwif->udma_init = ali15x3_udma_init;
hwif->modes_map = ali15x3_modes_map(hwif);
if (m5229_revision < 0xC2)
hwif->no_atapi_autodma = 1;
hwif->udma_setup = ali15x3_udma_setup;
hwif->autodma = 1;
hwif->udma_init = ali15x3_udma_init;
}
if (noautodma)
hwif->autodma = 0;
#else
hwif->autodma = 0;
#endif
}
static void __init ali15x3_init_dma(struct ata_channel *ch, unsigned long dmabase)
{
if ((dmabase) && (m5229_revision < 0x20))
if (dmabase && (m5229_revision < 0x20)) {
ch->autodma = 0;
return;
}
ata_init_dma(ch, dmabase);
}
......@@ -472,7 +386,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_AL,
device: PCI_DEVICE_ID_AL_M5229,
init_chipset: ali15x3_init_chipset,
ata66_check: ali15x3_ata66_check,
init_channel: ali15x3_init_channel,
init_dma: ali15x3_init_dma,
enablebits: { {0x00,0x00,0x00}, {0x00,0x00,0x00} },
......
......@@ -175,21 +175,15 @@ static void amd74xx_tune_drive(struct ata_device *drive, u8 pio)
}
#ifdef CONFIG_BLK_DEV_IDEDMA
static int amd74xx_udma_setup(struct ata_device *drive)
static int __init amd_modes_map(struct ata_channel *ch)
{
short w80 = drive->channel->udma_four;
short w80 = ch->udma_four;
int map = XFER_EPIO | XFER_MWDMA | XFER_UDMA |
((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) |
(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) |
(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0);
short speed = ata_timing_mode(drive,
XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) |
(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) |
(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0));
amd_set_drive(drive, speed);
udma_enable(drive, drive->channel->autodma && (speed & XFER_MODE) != XFER_PIO, 0);
return 0;
return map;
}
#endif
......@@ -274,9 +268,10 @@ static void __init amd74xx_init_channel(struct ata_channel *hwif)
{
int i;
hwif->udma_four = amd74xx_ata66_check(hwif);
hwif->tuneproc = &amd74xx_tune_drive;
hwif->speedproc = &amd_set_drive;
hwif->autodma = 0;
hwif->io_32bit = 1;
hwif->unmask = 1;
......@@ -289,11 +284,8 @@ static void __init amd74xx_init_channel(struct ata_channel *hwif)
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
hwif->highmem = 1;
hwif->udma_setup = amd74xx_udma_setup;
# ifdef CONFIG_IDEDMA_AUTO
if (!noautodma)
hwif->autodma = 1;
# endif
hwif->modes_map = amd_modes_map(hwif);
hwif->udma_setup = udma_generic_setup;
}
#endif
}
......@@ -314,7 +306,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_AMD,
device: PCI_DEVICE_ID_AMD_COBRA_7401,
init_chipset: amd74xx_init_chipset,
ata66_check: amd74xx_ata66_check,
init_channel: amd74xx_init_channel,
init_dma: amd74xx_init_dma,
enablebits: {{0x40,0x01,0x01}, {0x40,0x02,0x02}},
......@@ -324,7 +315,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_AMD,
device: PCI_DEVICE_ID_AMD_VIPER_7409,
init_chipset: amd74xx_init_chipset,
ata66_check: amd74xx_ata66_check,
init_channel: amd74xx_init_channel,
init_dma: amd74xx_init_dma,
enablebits: {{0x40,0x01,0x01}, {0x40,0x02,0x02}},
......@@ -335,7 +325,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_AMD,
device: PCI_DEVICE_ID_AMD_VIPER_7411,
init_chipset: amd74xx_init_chipset,
ata66_check: amd74xx_ata66_check,
init_channel: amd74xx_init_channel,
init_dma: amd74xx_init_dma,
enablebits: {{0x40,0x01,0x01}, {0x40,0x02,0x02}},
......@@ -345,7 +334,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_AMD,
device: PCI_DEVICE_ID_AMD_OPUS_7441,
init_chipset: amd74xx_init_chipset,
ata66_check: amd74xx_ata66_check,
init_channel: amd74xx_init_channel,
init_dma: amd74xx_init_dma,
enablebits: {{0x40,0x01,0x01}, {0x40,0x02,0x02}},
......@@ -355,7 +343,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_AMD,
device: PCI_DEVICE_ID_AMD_8111_IDE,
init_chipset: amd74xx_init_chipset,
ata66_check: amd74xx_ata66_check,
init_channel: amd74xx_init_channel,
init_dma: amd74xx_init_dma,
enablebits: {{0x40,0x01,0x01}, {0x40,0x02,0x02}},
......@@ -365,7 +352,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_NVIDIA,
device: PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,
init_chipset: amd74xx_init_chipset,
ata66_check: amd74xx_ata66_check,
init_channel: amd74xx_init_channel,
init_dma: amd74xx_init_dma,
enablebits: {{0x50,0x01,0x01}, {0x50,0x02,0x02}},
......
......@@ -86,9 +86,11 @@ short ata_timing_mode(struct ata_device *drive, int map)
if ((map & XFER_UDMA_100) == XFER_UDMA_100)
if ((best = (id->dma_ultra & 0x0020) ? XFER_UDMA_5 : 0)) return best;
if ((map & XFER_UDMA_66) == XFER_UDMA_66)
if ((best = (id->dma_ultra & 0x0010) ? XFER_UDMA_4 :
(id->dma_ultra & 0x0008) ? XFER_UDMA_3 : 0)) return best;
if ((map & XFER_UDMA_66_4) == XFER_UDMA_66_4)
if ((best = (id->dma_ultra & 0x0010) ? XFER_UDMA_4 : 0)) return best;
if ((map & XFER_UDMA_66_3) == XFER_UDMA_66_3)
if ((best = (id->dma_ultra & 0x0008) ? XFER_UDMA_3 : 0)) return best;
if ((best = (id->dma_ultra & 0x0004) ? XFER_UDMA_2 :
(id->dma_ultra & 0x0002) ? XFER_UDMA_1 :
......
......@@ -59,15 +59,22 @@ extern struct ata_timing ata_timing[];
#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
#define XFER_MODE 0xf0
#define XFER_UDMA_133 0x48
#define XFER_UDMA_100 0x44
#define XFER_UDMA_66 0x42
#define XFER_UDMA 0x40
#define XFER_MWDMA 0x20
#define XFER_SWDMA 0x10
#define XFER_EPIO 0x01
#define XFER_PIO 0x00
/* see hpt366.c for details */
#define XFER_UDMA_66_3 0x100
#define XFER_UDMA_66_4 0x200
#define XFER_MODE 0xff0
#define XFER_UDMA_133 0x800
#define XFER_UDMA_100 0x400
#define XFER_UDMA_66 0x300
#define XFER_UDMA 0x040
#define XFER_MWDMA 0x020
#define XFER_SWDMA 0x010
#define XFER_EPIO 0x001
#define XFER_PIO 0x000
#define XFER_UDMA_ALL 0xf40
#define XFER_UDMA_80W 0xf00
/* External interface to host chips channel timing setup.
*
......
......@@ -217,10 +217,10 @@ static void cmd64x_tuneproc(struct ata_device *drive, u8 pio)
ide_config_drive_speed(drive, speed);
}
static int cmd64x_ratemask(struct ata_device *drive)
static int __init cmd6xx_modes_map(struct ata_channel *ch)
{
struct pci_dev *dev = drive->channel->pci_dev;
int map = 0;
struct pci_dev *dev = ch->pci_dev;
int map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA;
switch(dev->device) {
case PCI_DEVICE_ID_CMD_680:
......@@ -234,10 +234,9 @@ static int cmd64x_ratemask(struct ata_device *drive)
break;
case PCI_DEVICE_ID_CMD_646:
{
u32 class_rev;
pci_read_config_dword(dev,
PCI_CLASS_REVISION, &class_rev);
class_rev &= 0xff;
u32 rev;
pci_read_config_dword(dev, PCI_CLASS_REVISION, &rev);
rev &= 0xff;
/*
* UltraDMA only supported on PCI646U and PCI646U2, which
* correspond to revisions 0x03, 0x05 and 0x07 respectively.
......@@ -250,7 +249,7 @@ static int cmd64x_ratemask(struct ata_device *drive)
*
* So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
*/
switch(class_rev) {
switch(rev) {
case 0x07:
case 0x05:
map |= XFER_UDMA;
......@@ -260,11 +259,6 @@ static int cmd64x_ratemask(struct ata_device *drive)
}
}
if (!eighty_ninty_three(drive)) {
if (map & XFER_UDMA)
return XFER_UDMA;
return 0;
}
return map;
}
......@@ -515,80 +509,6 @@ speed_break :
}
#ifdef CONFIG_BLK_DEV_IDEDMA
static int config_chipset_for_dma(struct ata_device *drive, u8 udma)
{
int map;
u8 mode;
if (udma)
map = cmd64x_ratemask(drive);
else
map = XFER_SWDMA | XFER_MWDMA;
mode = ata_timing_mode(drive, map);
return !drive->channel->speedproc(drive, mode);
}
static int cmd6xx_udma_setup(struct ata_device *drive)
{
struct hd_driveid *id = drive->id;
struct ata_channel *hwif = drive->channel;
int on = 1;
int verbose = 1;
hwif->tuneproc(drive, 255);
if ((id != NULL) && ((id->capability & 1) != 0) &&
hwif->autodma && (drive->type == ATA_DISK)) {
/* Consult the list of known "bad" drives */
if (udma_black_list(drive)) {
on = 0;
goto fast_ata_pio;
}
on = 0;
verbose = 0;
if ((id->field_valid & 4)) {
if (id->dma_ultra & 0x007F) {
/* Force if Capable UltraDMA */
on = config_chipset_for_dma(drive, 1);
if ((id->field_valid & 2) &&
(!on))
goto try_dma_modes;
}
} else if (id->field_valid & 2) {
try_dma_modes:
if ((id->dma_mword & 0x0007) ||
(id->dma_1word & 0x0007)) {
/* Force if Capable regular DMA modes */
on = config_chipset_for_dma(drive, 0);
if (!on)
goto no_dma_set;
}
} else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) {
goto no_dma_set;
}
/* Consult the list of known "good" drives */
on = config_chipset_for_dma(drive, 0);
if (!on)
goto no_dma_set;
} else {
goto fast_ata_pio;
}
} else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio:
on = 0;
verbose = 0;
no_dma_set:
hwif->tuneproc(drive, 255);
}
udma_enable(drive, on, verbose);
return 0;
}
static int cmd64x_udma_stop(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
......@@ -822,13 +742,6 @@ static unsigned int cmd64x_ata66(struct ata_channel *hwif)
return (ata66 & mask) ? 1 : 0;
}
static unsigned int __init cmd64x_ata66_check(struct ata_channel *hwif)
{
if (hwif->pci_dev->device == PCI_DEVICE_ID_CMD_680)
return cmd680_ata66(hwif);
return cmd64x_ata66(hwif);
}
static void __init cmd64x_init_channel(struct ata_channel *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
......@@ -843,32 +756,28 @@ static void __init cmd64x_init_channel(struct ata_channel *hwif)
switch(dev->device) {
case PCI_DEVICE_ID_CMD_680:
hwif->busproc = cmd680_busproc;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base)
hwif->udma_setup = cmd6xx_udma_setup;
#endif
hwif->resetproc = cmd680_reset;
hwif->speedproc = cmd680_tune_chipset;
hwif->tuneproc = cmd680_tuneproc;
hwif->udma_four = cmd680_ata66(hwif);
break;
case PCI_DEVICE_ID_CMD_649:
case PCI_DEVICE_ID_CMD_648:
case PCI_DEVICE_ID_CMD_643:
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
hwif->udma_setup = cmd6xx_udma_setup;
hwif->udma_stop = cmd64x_udma_stop;
hwif->udma_irq_status = cmd64x_udma_irq_status;
}
#endif
hwif->tuneproc = cmd64x_tuneproc;
hwif->speedproc = cmd64x_tune_chipset;
hwif->udma_four = cmd64x_ata66(hwif);
break;
case PCI_DEVICE_ID_CMD_646:
hwif->chipset = ide_cmd646;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
hwif->udma_setup = cmd6xx_udma_setup;
if (class_rev == 0x01) {
hwif->udma_stop = cmd646_1_udma_stop;
} else {
......@@ -879,6 +788,7 @@ static void __init cmd64x_init_channel(struct ata_channel *hwif)
#endif
hwif->tuneproc = cmd64x_tuneproc;
hwif->speedproc = cmd64x_tune_chipset;
hwif->udma_four = cmd64x_ata66(hwif);
break;
default:
break;
......@@ -887,10 +797,9 @@ static void __init cmd64x_init_channel(struct ata_channel *hwif)
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
hwif->highmem = 1;
# ifdef CONFIG_IDEDMA_AUTO
if (!noautodma)
hwif->autodma = 1;
# endif
hwif->modes_map = cmd6xx_modes_map(hwif);
hwif->no_atapi_autodma = 1;
hwif->udma_setup = udma_generic_setup;
}
#endif
}
......@@ -919,7 +828,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_CMD,
device: PCI_DEVICE_ID_CMD_648,
init_chipset: cmd64x_init_chipset,
ata66_check: cmd64x_ata66_check,
init_channel: cmd64x_init_channel,
bootable: ON_BOARD,
flags: ATA_F_DMA
......@@ -928,7 +836,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_CMD,
device: PCI_DEVICE_ID_CMD_649,
init_chipset: cmd64x_init_chipset,
ata66_check: cmd64x_ata66_check,
init_channel: cmd64x_init_channel,
bootable: ON_BOARD,
flags: ATA_F_DMA
......@@ -937,7 +844,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_CMD,
device: PCI_DEVICE_ID_CMD_680,
init_chipset: cmd64x_init_chipset,
ata66_check: cmd64x_ata66_check,
init_channel: cmd64x_init_channel,
bootable: ON_BOARD,
flags: ATA_F_DMA
......
......@@ -191,7 +191,7 @@ static int cs5530_config_dma(struct ata_device *drive)
return 0;
}
static int cs5530_udma_setup(struct ata_device *drive)
static int cs5530_udma_setup(struct ata_device *drive, int map)
{
return cs5530_config_dma(drive);
}
......@@ -285,17 +285,15 @@ static unsigned int __init pci_init_cs5530(struct pci_dev *dev)
*/
static void __init ide_init_cs5530(struct ata_channel *hwif)
{
u32 basereg, d0_timings;
hwif->serialized = 1;
if (!hwif->dma_base) {
hwif->autodma = 0;
} else {
unsigned int basereg, d0_timings;
#ifdef CONFIG_BLK_DEV_IDEDMA
hwif->udma_setup = cs5530_udma_setup;
hwif->highmem = 1;
#else
hwif->autodma = 0;
if (hwif->dma_base) {
hwif->highmem = 1;
hwif->udma_setup = cs5530_udma_setup;
}
#endif
hwif->tuneproc = &cs5530_tuneproc;
......@@ -311,7 +309,6 @@ static void __init ide_init_cs5530(struct ata_channel *hwif)
if (!hwif->drives[1].autotune)
hwif->drives[1].autotune = 1; /* needs autotuning later */
}
}
}
......
......@@ -237,7 +237,7 @@ static void cy82c693_dma_enable(struct ata_device *drive, int mode, int single)
/*
* used to set DMA mode for CY82C693 (single and multi modes)
*/
static int cy82c693_udma_setup(struct ata_device *drive)
static int cy82c693_udma_setup(struct ata_device *drive, int map)
{
/*
* Set dma mode for drive everything else is done by the defaul func.
......@@ -414,14 +414,11 @@ static void __init ide_init_cy82c693(struct ata_channel *hwif)
hwif->tuneproc = cy82c693_tune_drive;
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
hwif->autodma = 0;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
hwif->highmem = 1;
hwif->udma_setup = cy82c693_udma_setup;
if (!noautodma)
hwif->autodma = 1;
}
#endif
}
......
......@@ -79,30 +79,8 @@ void ata_mask(struct ata_device *drive)
ch->maskproc(drive);
}
/*
* Spin until the drive is no longer busy.
*
* Not exported, since it's not used within any modules.
*/
int ata_busy_poll(struct ata_device *drive, unsigned long timeout)
{
/* spec allows drive 400ns to assert "BUSY" */
udelay(1);
if (!ata_status(drive, 0, BUSY_STAT)) {
timeout += jiffies;
while (!ata_status(drive, 0, BUSY_STAT)) {
if (time_after(jiffies, timeout))
return 1;
}
}
return 0;
}
/*
* Check the state of the status register.
*
* FIXME: Channel lock should be held.
*/
int ata_status(struct ata_device *drive, u8 good, u8 bad)
{
......@@ -120,31 +98,33 @@ EXPORT_SYMBOL(ata_status);
* all of the "good" bits and none of the "bad" bits, and if all is okay it
* returns 0. All other cases return 1 after invoking error handler -- caller
* should just return.
*
* This routine should get fixed to not hog the cpu during extra long waits..
* That could be done by busy-waiting for the first jiffy or two, and then
* setting a timer to wake up at half second intervals thereafter, until
* timeout is achieved, before timing out.
*
* Channel lock should be held.
*/
int ata_status_poll(struct ata_device *drive, u8 good, u8 bad,
unsigned long timeout,
struct request *rq, ide_startstop_t *startstop)
unsigned long timeout, struct request *rq)
{
int i;
/* bail early if we've exceeded max_failures */
if (drive->max_failures && (drive->failures > drive->max_failures)) {
*startstop = ide_stopped;
return 1;
}
if (ata_busy_poll(drive, timeout)) {
*startstop = ata_error(drive, rq, "status timeout");
if (drive->max_failures && (drive->failures > drive->max_failures))
return ATA_OP_FINISHED;
/*
* Spin until the drive is no longer busy.
* Spec allows drive 400ns to assert "BUSY"
*/
udelay(1);
if (!ata_status(drive, 0, BUSY_STAT)) {
unsigned long flags;
return 1;
__save_flags(flags);
ide__sti();
timeout += jiffies;
while (!ata_status(drive, 0, BUSY_STAT)) {
if (time_after(jiffies, timeout)) {
__restore_flags(flags);
return ata_error(drive, rq, "status timeout");
}
}
__restore_flags(flags);
}
/*
......@@ -156,12 +136,10 @@ int ata_status_poll(struct ata_device *drive, u8 good, u8 bad,
for (i = 0; i < 10; i++) {
udelay(1);
if (ata_status(drive, good, bad))
return 0;
return ATA_OP_READY;
}
*startstop = ata_error(drive, rq, "status error");
return 1;
return ata_error(drive, rq, "status error");
}
EXPORT_SYMBOL(ata_status_poll);
......
......@@ -72,83 +72,13 @@ static void hpt34x_tune_drive(struct ata_device *drive, u8 pio)
}
#ifdef CONFIG_BLK_DEV_IDEDMA
static int config_chipset_for_dma(struct ata_device *drive, u8 udma)
static int hpt34x_udma_setup(struct ata_device *drive, int map)
{
int map;
u8 mode;
if (drive->type != ATA_DISK)
return 0;
if (udma)
map = XFER_UDMA;
else
map = XFER_SWDMA | XFER_MWDMA;
mode = ata_timing_mode(drive, map);
if (mode < XFER_SW_DMA_0)
return 0;
return !hpt34x_tune_chipset(drive, mode);
}
static int hpt34x_udma_setup(struct ata_device *drive)
{
struct hd_driveid *id = drive->id;
int on = 1;
int verbose = 1;
if (id && (id->capability & 1) && drive->channel->autodma) {
/* Consult the list of known "bad" drives */
if (udma_black_list(drive)) {
on = 0;
goto fast_ata_pio;
}
on = 0;
verbose = 0;
if (id->field_valid & 4) {
if (id->dma_ultra & 0x0007) {
/* Force if Capable UltraDMA */
on = config_chipset_for_dma(drive, 1);
if ((id->field_valid & 2) &&
(!on))
goto try_dma_modes;
}
} else if (id->field_valid & 2) {
try_dma_modes:
if ((id->dma_mword & 0x0007) ||
(id->dma_1word & 0x0007)) {
/* Force if Capable regular DMA modes */
on = config_chipset_for_dma(drive, 0);
if (!on)
goto no_dma_set;
}
} else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) {
goto no_dma_set;
}
/* Consult the list of known "good" drives */
on = config_chipset_for_dma(drive, 0);
if (!on)
goto no_dma_set;
} else {
goto fast_ata_pio;
}
} else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio:
on = 0;
verbose = 0;
no_dma_set:
hpt34x_tune_chipset(drive, ata_best_pio_mode(drive));
}
#ifndef CONFIG_HPT34X_AUTODMA
if (on)
on = 0;
#endif
udma_enable(drive, on, verbose);
#ifdef CONFIG_HPT34X_AUTODMA
return udma_generic_setup(drive, map);
#else
return 0;
#endif
}
static int hpt34x_udma_stop(struct ata_device *drive)
......@@ -173,7 +103,7 @@ static int hpt34x_udma_init(struct ata_device *drive, struct request *rq)
u8 cmd;
if (!(count = udma_new_table(drive, rq)))
return ide_stopped; /* try PIO instead of DMA */
return ATA_OP_FINISHED; /* try PIO instead of DMA */
if (rq_data_dir(rq) == READ)
cmd = 0x09;
......@@ -189,7 +119,7 @@ static int hpt34x_udma_init(struct ata_device *drive, struct request *rq)
OUT_BYTE((cmd == 0x09) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
}
return ide_started;
return ATA_OP_CONTINUES;
}
#endif
......@@ -252,24 +182,21 @@ static void __init ide_init_hpt34x(struct ata_channel *hwif)
unsigned short pcicmd = 0;
pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd);
if (!noautodma)
hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0;
else
hwif->autodma = 0;
#ifdef CONFIG_IDEDMA_AUTO
hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0;
#endif
hwif->udma_stop = hpt34x_udma_stop;
hwif->udma_init = hpt34x_udma_init;
hwif->modes_map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA | XFER_UDMA;
hwif->no_atapi_autodma = 1;
hwif->udma_setup = hpt34x_udma_setup;
hwif->highmem = 1;
} else {
} else
#endif
{
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
}
#else
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
hwif->autodma = 0;
#endif
}
......@@ -281,7 +208,7 @@ static struct ata_pci_device chipset __initdata = {
init_channel: ide_init_hpt34x,
bootable: NEVER_BOARD,
extra: 16,
flags: ATA_F_NOADMA | ATA_F_DMA
flags: ATA_F_DMA
};
int __init init_hpt34x(void)
......
......@@ -493,37 +493,23 @@ static unsigned int hpt_revision(struct pci_dev *dev)
return class_rev;
}
static int hpt3xx_ratemask(struct ata_device *drive)
static int __init hpt3xx_modes_map(struct ata_channel *ch)
{
u32 rev = hpt_revision(drive->channel->pci_dev);
int map = XFER_UDMA;
u32 rev = hpt_revision(ch->pci_dev);
int map = XFER_EPIO | XFER_MWDMA | XFER_UDMA | XFER_UDMA_66;
if (rev >= 8) { /* HPT374 */
if (HPT374_ALLOW_ATA133_6)
map |= XFER_UDMA_133;
map |= (XFER_UDMA_100 | XFER_UDMA_66);
map |= XFER_UDMA_100;
} else if (rev >= 5) { /* HPT372 */
if (HPT372_ALLOW_ATA133_6)
map |= XFER_UDMA_133;
map |= (XFER_UDMA_100 | XFER_UDMA_66);
} else if (rev >= 4) { /* HPT370A */
map |= XFER_UDMA_100;
} else if (rev >= 3) { /* HPT370A / HPT370 */
if (HPT370_ALLOW_ATA100_5)
map |= XFER_UDMA_100;
map |= XFER_UDMA_66;
} else if (rev >= 3) { /* HPT370 */
if (HPT370_ALLOW_ATA100_5)
map |= XFER_UDMA_100;
map |= XFER_UDMA_66;
if (check_in_drive_lists(drive, bad_ata33))
return 0;
} else { /* HPT366 and HPT368 */
map |= XFER_UDMA_66;
if (check_in_drive_lists(drive, bad_ata33))
return 0;
}
if (!eighty_ninty_three(drive))
return XFER_UDMA;
} /* HPT366 / HPT368 */
return map;
}
......@@ -662,62 +648,42 @@ static int hpt3xx_tune_chipset(struct ata_device *drive, u8 speed)
return ide_config_drive_speed(drive, speed);
}
/* FIXME: pio == 255 -> ata_best_pio_mode(drive) --bkz */
static void hpt3xx_tune_drive(struct ata_device *drive, u8 pio)
{
(void) hpt3xx_tune_chipset(drive, XFER_PIO_0 + min_t(u8, pio, 4));
}
#ifdef CONFIG_BLK_DEV_IDEDMA
static int config_chipset_for_dma(struct ata_device *drive)
static int hpt3xx_udma_setup(struct ata_device *drive, int map)
{
int map;
u32 rev;
u8 mode;
if (drive->type != ATA_DISK)
return 0;
rev = hpt_revision(drive->channel->pci_dev);
/* FIXME: check SWDMA modes --bkz */
map = hpt3xx_ratemask(drive) | XFER_MWDMA;
mode = ata_timing_mode(drive, map);
/* FIXME: badlists need futher investigation --bkz */
/* FIXME: badlists need futher investigation --bkz
bad_ata100_5 is for HPT370/370A,
bad_ata66_4, bad_ata66_3 and bad_ata33 are for HPT366/368
*/
if (mode == XFER_UDMA_5 && rev < 5) {
if (check_in_drive_lists(drive, bad_ata100_5)) {
/* FIXME: make XFER_UDMA_66/100/133
independent of XFER_UDMA --bkz */
map &= ~XFER_UDMA_100;
map |= XFER_UDMA;
mode = ata_timing_mode(drive, map);
}
}
if (mode == XFER_UDMA_4 && rev < 3) {
if (check_in_drive_lists(drive, bad_ata66_4)) {
if (drive->id->dma_ultra & 0x0008) {
mode = XFER_UDMA_3;
} else {
map &= ~XFER_UDMA_66;
map |= XFER_UDMA;
mode = ata_timing_mode(drive, map);
}
}
}
if (mode == XFER_UDMA_3 && rev < 3) {
if (check_in_drive_lists(drive, bad_ata66_3)) {
map &= ~XFER_UDMA_66;
map |= XFER_UDMA;
mode = ata_timing_mode(drive, map);
}
/* bad_ata100_5 is for HPT370/370A,
bad_ata66_4, bad_ata66_3 and bad_ata33 are for HPT366/368 */
if (rev < 5 && check_in_drive_lists(drive, bad_ata100_5))
map &= ~XFER_UDMA_100;
if (rev < 3) {
if (check_in_drive_lists(drive, bad_ata66_4))
map &= ~XFER_UDMA_66_4;
if (check_in_drive_lists(drive, bad_ata66_3))
map &= ~XFER_UDMA_66_3;
if (check_in_drive_lists(drive, bad_ata33))
map &= ~XFER_UDMA_ALL;
}
if (check_in_drive_lists(drive, bad_ata33) && rev < 3)
mode = ata_timing_mode(drive, XFER_MWDMA);
return !hpt3xx_tune_chipset(drive, mode);
return udma_generic_setup(drive, map);
}
static int hpt3xx_quirkproc(struct ata_device *drive)
......@@ -754,59 +720,6 @@ static void hpt3xx_maskproc(struct ata_device *drive)
}
}
static int hpt3xx_udma_setup(struct ata_device *drive)
{
struct hd_driveid *id = drive->id;
int on = 1;
int verbose = 1;
if (id && (id->capability & 1) && drive->channel->autodma) {
/* Consult the list of known "bad" drives */
if (udma_black_list(drive)) {
on = 0;
goto fast_ata_pio;
}
on = 0;
verbose = 0;
if (id->field_valid & 4) {
if (id->dma_ultra & 0x007F) {
/* Force if Capable UltraDMA */
on = config_chipset_for_dma(drive);
if ((id->field_valid & 2) &&
(!on))
goto try_dma_modes;
}
} else if (id->field_valid & 2) {
try_dma_modes:
if (id->dma_mword & 0x0007) {
/* Force if Capable regular DMA modes */
on = config_chipset_for_dma(drive);
if (!on)
goto no_dma_set;
}
} else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) {
goto no_dma_set;
}
/* Consult the list of known "good" drives */
on = config_chipset_for_dma(drive);
if (!on)
goto no_dma_set;
} else {
goto fast_ata_pio;
}
} else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio:
on = 0;
verbose = 0;
no_dma_set:
hpt3xx_tune_chipset(drive, ata_best_pio_mode(drive));
}
udma_enable(drive, on, verbose);
return 0;
}
static void hpt366_udma_irq_lost(struct ata_device *drive)
{
struct pci_dev *dev = drive->channel->pci_dev;
......@@ -1232,6 +1145,8 @@ static void __init hpt366_init_channel(struct ata_channel *ch)
struct pci_dev *dev = ch->pci_dev;
u32 rev = hpt_revision(dev);
ch->udma_four = hpt366_ata66_check(ch);
ch->tuneproc = hpt3xx_tune_drive;
ch->speedproc = hpt3xx_tune_chipset;
ch->quirkproc = hpt3xx_quirkproc;
......@@ -1272,17 +1187,12 @@ static void __init hpt366_init_channel(struct ata_channel *ch)
// ch->resetproc = hpt3xx_reset;
// ch->busproc = hpt3xx_tristate;
}
ch->modes_map = hpt3xx_modes_map(ch);
ch->udma_setup = hpt3xx_udma_setup;
if (!noautodma)
ch->autodma = 1;
else
ch->autodma = 0;
ch->highmem = 1;
} else
#endif
{
ch->autodma = 0;
ch->drives[0].autotune = 1;
ch->drives[1].autotune = 1;
}
......@@ -1315,7 +1225,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_TTI,
device: PCI_DEVICE_ID_TTI_HPT366,
init_chipset: hpt366_init_chipset,
ata66_check: hpt366_ata66_check,
init_channel: hpt366_init_channel,
init_dma: hpt366_init_dma,
bootable: OFF_BOARD,
......@@ -1326,7 +1235,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_TTI,
device: PCI_DEVICE_ID_TTI_HPT372,
init_chipset: hpt366_init_chipset,
ata66_check: hpt366_ata66_check,
init_channel: hpt366_init_channel,
init_dma: hpt366_init_dma,
bootable: OFF_BOARD,
......@@ -1337,7 +1245,6 @@ static struct ata_pci_device chipsets[] __initdata = {
vendor: PCI_VENDOR_ID_TTI,
device: PCI_DEVICE_ID_TTI_HPT374,
init_chipset: hpt366_init_chipset,
ata66_check: hpt366_ata66_check,
init_channel: hpt366_init_channel,
init_dma: hpt366_init_dma,
bootable: OFF_BOARD,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -1074,7 +1074,8 @@ int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driv
spin_unlock_irqrestore(&ide_lock, flags);
/* Default autotune or requested autotune */
if (drive->autotune != 2) {
if (drive->channel->udma_setup) {
struct ata_channel *ch = drive->channel;
if (ch->udma_setup) {
/*
* Force DMAing for the beginning of the check. Some
......@@ -1085,7 +1086,7 @@ int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driv
*/
udma_enable(drive, 0, 0);
drive->channel->udma_setup(drive);
ch->udma_setup(drive, ch->modes_map);
#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
udma_tcq_enable(drive, 1);
#endif
......
This diff is collapsed.
This diff is collapsed.
......@@ -117,7 +117,6 @@ struct ata_pci_device {
unsigned short vendor;
unsigned short device;
unsigned int (*init_chipset)(struct pci_dev *);
unsigned int (*ata66_check)(struct ata_channel *);
void (*init_channel)(struct ata_channel *);
void (*init_dma)(struct ata_channel *, unsigned long);
ide_pci_enablebit_t enablebits[2];
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment