Commit d39a11f3 authored by Linus Torvalds's avatar Linus Torvalds

v2.4.3.3 -> v2.4.3.4

  - David Miller: sparc rw semaphores moved over
  - Alan Cox: yet more resyncs
  - NIIBE Yutaka: Super-H driver update
  - David Howells: more rw-sem cleanups, updates
  - USB updates
  - Al Viro: filesystem init cleanup
parent 1a015350
......@@ -11002,16 +11002,16 @@ CONFIG_USB_USS720
USB device file system
CONFIG_USB_DEVICEFS
If you say Y here (and to "/proc file system support" below), you
will get a file /proc/usb/devices which lists the devices currently
connected to your USB busses, a file /proc/usb/drivers which lists
the USB kernel client drivers currently loaded, and for every
connected device a file named "/proc/usb/xxx/yyy", where xxx is the
bus number and yyy the device number; the latter files can be used
by user space programs to talk directly to the device. These files
are "virtual", meaning they are generated on the fly and not stored
on the hard drive.
will get a file /proc/bus/usb/devices which lists the devices
currently connected to your USB busses, a file /proc/bus/usb/drivers
which lists the USB kernel client drivers currently loaded, and for
every connected device a file named "/proc/bus/usb/xxx/yyy", where
xxx is the bus number and yyy the device number; the latter files
can be used by user space programs to talk directly to the device.
These files are "virtual", meaning they are generated on the fly
and not stored on the hard drive.
For the format of the /proc/usb/ files, please read
For the format of the /proc/bus/usb/ files, please read
Documentation/usb/proc_usb_info.txt.
Please note that this code is completely unrelated to devfs, the
......
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 4
EXTRAVERSION =-pre3
EXTRAVERSION =-pre4
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
......
......@@ -5,6 +5,8 @@
define_bool CONFIG_ALPHA y
define_bool CONFIG_UID16 n
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
mainmenu_name "Kernel configuration of Linux for Alpha machines"
......
......@@ -190,7 +190,6 @@ EXPORT_SYMBOL(kernel_flag);
EXPORT_SYMBOL(synchronize_irq);
EXPORT_SYMBOL(flush_tlb_all);
EXPORT_SYMBOL(flush_tlb_mm);
EXPORT_SYMBOL(flush_tlb_page);
EXPORT_SYMBOL(flush_tlb_range);
EXPORT_SYMBOL(smp_imb);
EXPORT_SYMBOL(cpu_data);
......
......@@ -263,185 +263,3 @@ up(struct semaphore *sem)
#endif
__up(sem);
}
/*
* RW Semaphores
*/
void
__down_read_failed(struct rw_semaphore *sem, int count)
{
DECLARE_WAITQUEUE(wait, current);
retry_down:
if (count < 0) {
/* Waiting on multiple readers and/or writers. */
/* Undo the acquisition we started in down_read. */
atomic_inc(&sem->count);
current->state = TASK_UNINTERRUPTIBLE;
wmb();
add_wait_queue(&sem->wait, &wait);
mb();
while (atomic_read(&sem->count) < 0) {
schedule();
set_task_state(current, TASK_UNINTERRUPTIBLE);
}
remove_wait_queue(&sem->wait, &wait);
current->state = TASK_RUNNING;
mb();
count = atomic_dec_return(&sem->count);
if (count <= 0)
goto retry_down;
} else {
/* Waiting on exactly one writer. */
current->state = TASK_UNINTERRUPTIBLE;
wmb();
add_wait_queue(&sem->wait, &wait);
mb();
while (!test_and_clear_bit(0, &sem->granted)) {
schedule();
set_task_state(current, TASK_UNINTERRUPTIBLE);
}
remove_wait_queue(&sem->wait, &wait);
current->state = TASK_RUNNING;
}
}
void
__down_write_failed(struct rw_semaphore *sem, int count)
{
DECLARE_WAITQUEUE(wait, current);
retry_down:
if (count + RW_LOCK_BIAS < 0) {
/* Waiting on multiple readers and/or writers. */
/* Undo the acquisition we started in down_write. */
atomic_add(RW_LOCK_BIAS, &sem->count);
current->state = TASK_UNINTERRUPTIBLE;
wmb();
add_wait_queue_exclusive(&sem->wait, &wait);
mb();
while (atomic_read(&sem->count) + RW_LOCK_BIAS < 0) {
schedule();
set_task_state(current, TASK_UNINTERRUPTIBLE);
}
remove_wait_queue(&sem->wait, &wait);
current->state = TASK_RUNNING;
count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
if (count != 0)
goto retry_down;
} else {
/* Waiting on exactly one writer. */
current->state = TASK_UNINTERRUPTIBLE;
wmb();
add_wait_queue_exclusive(&sem->wait, &wait);
mb();
while (!test_and_clear_bit(1, &sem->granted)) {
schedule();
set_task_state(current, TASK_UNINTERRUPTIBLE);
}
remove_wait_queue(&sem->write_bias_wait, &wait);
current->state = TASK_RUNNING;
/* If the lock is currently unbiased, awaken the sleepers.
FIXME: This wakes up the readers early in a bit of a
stampede -> bad! */
count = atomic_read(&sem->count);
if (__builtin_expect(count >= 0, 0))
wake_up(&sem->wait);
}
}
void
__rwsem_wake(struct rw_semaphore *sem, int readers)
{
if (readers) {
if (test_and_set_bit(0, &sem->granted))
BUG();
wake_up(&sem->wait);
} else {
if (test_and_set_bit(1, &sem->granted))
BUG();
wake_up(&sem->write_bias_wait);
}
}
void
down_read(struct rw_semaphore *sem)
{
#if WAITQUEUE_DEBUG
CHECK_MAGIC(sem->__magic);
#endif
__down_read(sem);
#if WAITQUEUE_DEBUG
if (sem->granted & 2)
BUG();
if (atomic_read(&sem->writers))
BUG();
atomic_inc(&sem->readers);
#endif
}
void
down_write(struct rw_semaphore *sem)
{
#if WAITQUEUE_DEBUG
CHECK_MAGIC(sem->__magic);
#endif
__down_write(sem);
#if WAITQUEUE_DEBUG
if (sem->granted & 3)
BUG();
if (atomic_read(&sem->writers))
BUG();
if (atomic_read(&sem->readers))
BUG();
atomic_inc(&sem->writers);
#endif
}
void
up_read(struct rw_semaphore *sem)
{
#if WAITQUEUE_DEBUG
CHECK_MAGIC(sem->__magic);
if (sem->granted & 2)
BUG();
if (atomic_read(&sem->writers))
BUG();
atomic_dec(&sem->readers);
#endif
__up_read(sem);
}
void
up_write(struct rw_semaphore *sem)
{
#if WAITQUEUE_DEBUG
CHECK_MAGIC(sem->__magic);
if (sem->granted & 3)
BUG();
if (atomic_read(&sem->readers))
BUG();
if (atomic_read(&sem->writers) != 1)
BUG();
atomic_dec(&sem->writers);
#endif
__up_write(sem);
}
......@@ -43,20 +43,6 @@ struct thread_struct original_pcb;
struct pgtable_cache_struct quicklists;
#endif
void
__bad_pmd(pgd_t *pgd)
{
printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
pgd_set(pgd, BAD_PAGETABLE);
}
void
__bad_pte(pmd_t *pmd)
{
printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
}
pgd_t *
get_pgd_slow(void)
{
......@@ -80,66 +66,26 @@ get_pgd_slow(void)
return ret;
}
pmd_t *
get_pmd_slow(pgd_t *pgd, unsigned long offset)
{
pmd_t *pmd;
pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
if (pgd_none(*pgd)) {
if (pmd) {
clear_page((void *)pmd);
pgd_set(pgd, pmd);
return pmd + offset;
}
pgd_set(pgd, BAD_PAGETABLE);
return NULL;
}
free_page((unsigned long)pmd);
if (pgd_bad(*pgd)) {
__bad_pmd(pgd);
return NULL;
}
return (pmd_t *) pgd_page(*pgd) + offset;
}
pte_t *
get_pte_slow(pmd_t *pmd, unsigned long offset)
{
pte_t *pte;
pte = (pte_t *) __get_free_page(GFP_KERNEL);
if (pmd_none(*pmd)) {
if (pte) {
clear_page((void *)pte);
pmd_set(pmd, pte);
return pte + offset;
}
pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
return NULL;
}
free_page((unsigned long)pte);
if (pmd_bad(*pmd)) {
__bad_pte(pmd);
return NULL;
}
return (pte_t *) pmd_page(*pmd) + offset;
}
int do_check_pgt_cache(int low, int high)
{
int freed = 0;
if(pgtable_cache_size > high) {
do {
if(pgd_quicklist)
free_pgd_slow(get_pgd_fast()), freed++;
if(pmd_quicklist)
free_pmd_slow(get_pmd_fast()), freed++;
if(pte_quicklist)
free_pte_slow(get_pte_fast()), freed++;
} while(pgtable_cache_size > low);
}
return freed;
if(pgtable_cache_size > high) {
do {
if(pgd_quicklist) {
free_pgd_slow(get_pgd_fast());
freed++;
}
if(pmd_quicklist) {
pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
freed++;
}
if(pte_quicklist) {
pte_free_slow(pte_alloc_one_fast(NULL, 0));
freed++;
}
} while(pgtable_cache_size > low);
}
return freed;
}
/*
......
......@@ -9,6 +9,8 @@ define_bool CONFIG_EISA n
define_bool CONFIG_SBUS n
define_bool CONFIG_MCA n
define_bool CONFIG_UID16 y
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
mainmenu_option next_comment
......@@ -44,7 +46,7 @@ choice 'ARM system type' \
mainmenu_option next_comment
comment 'Archimedes/A5000 Implementations'
# These architectures will be combined. However, until this
# is complete... Note that the ARC will take precidence over
# is complete... Note that the ARC will take precedence over
# A5K
comment 'Archimedes/A5000 Implementations (select only ONE)'
dep_bool ' Archimedes' CONFIG_ARCH_ARC $CONFIG_ARCH_ARCA5K
......
......@@ -165,321 +165,3 @@ int __down_trylock(struct semaphore * sem)
spin_unlock_irqrestore(&semaphore_lock, flags);
return 1;
}
struct rw_semaphore *down_read_failed_biased(struct rw_semaphore *sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */
for (;;) {
if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
break;
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (!sem->read_bias_granted)
schedule();
}
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
return sem;
}
struct rw_semaphore *down_write_failed_biased(struct rw_semaphore *sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
for (;;) {
if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
break;
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (!sem->write_bias_granted)
schedule();
}
remove_wait_queue(&sem->write_bias_wait, &wait);
tsk->state = TASK_RUNNING;
/* if the lock is currently unbiased, awaken the sleepers
* FIXME: this wakes up the readers early in a bit of a
* stampede -> bad!
*/
if (atomic_read(&sem->count) >= 0)
wake_up(&sem->wait);
return sem;
}
/* Wait for the lock to become unbiased. Readers
* are non-exclusive. =)
*/
struct rw_semaphore *down_read_failed(struct rw_semaphore *sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
/* this takes care of granting the lock */
__up_op_read(sem, __rwsem_wake);
add_wait_queue(&sem->wait, &wait);
while (atomic_read(&sem->count) < 0) {
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (atomic_read(&sem->count) >= 0)
break;
schedule();
}
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
return sem;
}
/* Wait for the lock to become unbiased. Since we're
* a writer, we'll make ourselves exclusive.
*/
struct rw_semaphore *down_write_failed(struct rw_semaphore *sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
/* this takes care of granting the lock */
__up_op_write(sem, __rwsem_wake);
add_wait_queue_exclusive(&sem->wait, &wait);
while (atomic_read(&sem->count) < 0) {
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (atomic_read(&sem->count) >= 0)
break; /* we must attempt to acquire or bias the lock */
schedule();
}
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
return sem;
}
/* Called when someone has done an up that transitioned from
* negative to non-negative, meaning that the lock has been
* granted to whomever owned the bias.
*/
struct rw_semaphore *rwsem_wake_readers(struct rw_semaphore *sem)
{
if (xchg(&sem->read_bias_granted, 1))
BUG();
wake_up(&sem->wait);
return sem;
}
struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem)
{
if (xchg(&sem->write_bias_granted, 1))
BUG();
wake_up(&sem->write_bias_wait);
return sem;
}
/*
* The semaphore operations have a special calling sequence that
* allow us to do a simpler in-line version of them. These routines
* need to convert that sequence back into the C sequence when
* there is contention on the semaphore.
*
* ip contains the semaphore pointer on entry. Save the C-clobbered
* registers (r0 to r3 and lr), but not ip, as we use it as a return
* value in some cases..
*/
#ifdef CONFIG_CPU_26
asm(" .section .text.lock, \"ax\"
.align 5
.globl __down_failed
__down_failed:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bl __down
ldmfd sp!, {r0 - r3, pc}^
.align 5
.globl __down_interruptible_failed
__down_interruptible_failed:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bl __down_interruptible
mov ip, r0
ldmfd sp!, {r0 - r3, pc}^
.align 5
.globl __down_trylock_failed
__down_trylock_failed:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bl __down_trylock
mov ip, r0
ldmfd sp!, {r0 - r3, pc}^
.align 5
.globl __up_wakeup
__up_wakeup:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bl __up
ldmfd sp!, {r0 - r3, pc}^
.align 5
.globl __down_read_failed
__down_read_failed:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bcc 1f
1: bl down_read_failed_biased
ldmfd sp!, {r0 - r3, pc}^
2: bl down_read_failed
mov r1, pc
orr r2, r1, #
teqp r2, #0
ldr r3, [r0]
subs r3, r3, #1
str r3, [r0]
ldmplfd sp!, {r0 - r3, pc}^
orrcs r1, r1, #0x20000000 @ Set carry
teqp r1, #0
bcc 2b
b 1b
.align 5
.globl __down_write_failed
__down_write_failed:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bcc 1f
1: bl down_write_failed_biased
ldmfd sp!, {r0 - r3, pc}^
2: bl down_write_failed
mov r1, pc
orr r2, r1, #128
teqp r2, #0
ldr r3, [r0]
subs r3, r3, #"RW_LOCK_BIAS_STR"
str r3, [r0]
ldmeqfd sp!, {r0 - r3, pc}^
orrcs r1, r1, #0x20000000 @ Set carry
teqp r1, #0
bcc 2b
b 1b
.align 5
.globl __rwsem_wake
__rwsem_wake:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
beq 1f
bl rwsem_wake_readers
ldmfd sp!, {r0 - r3, pc}^
1: bl rwsem_wake_writer
ldmfd sp!, {r0 - r3, pc}^
.previous
");
#else
/* 32 bit version */
asm(" .section .text.lock, \"ax\"
.align 5
.globl __down_failed
__down_failed:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bl __down
ldmfd sp!, {r0 - r3, pc}
.align 5
.globl __down_interruptible_failed
__down_interruptible_failed:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bl __down_interruptible
mov ip, r0
ldmfd sp!, {r0 - r3, pc}
.align 5
.globl __down_trylock_failed
__down_trylock_failed:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bl __down_trylock
mov ip, r0
ldmfd sp!, {r0 - r3, pc}
.align 5
.globl __up_wakeup
__up_wakeup:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bl __up
ldmfd sp!, {r0 - r3, pc}
.align 5
.globl __down_read_failed
__down_read_failed:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bcc 1f
1: bl down_read_failed_biased
ldmfd sp!, {r0 - r3, pc}
2: bl down_read_failed
mrs r1, cpsr
orr r2, r1, #128
msr cpsr_c, r2
ldr r3, [r0]
subs r3, r3, #1
str r3, [r0]
msr cpsr_c, r1
ldmplfd sp!, {r0 - r3, pc}
bcc 2b
b 1b
.align 5
.globl __down_write_failed
__down_write_failed:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
bcc 1f
1: bl down_write_failed_biased
ldmfd sp!, {r0 - r3, pc}
2: bl down_write_failed
mrs r1, cpsr
orr r2, r1, #128
msr cpsr_c, r2
ldr r3, [r0]
subs r3, r3, #"RW_LOCK_BIAS_STR"
str r3, [r0]
msr cpsr_c, r1
ldmeqfd sp!, {r0 - r3, pc}
bcc 2b
b 1b
.align 5
.globl __rwsem_wake
__rwsem_wake:
stmfd sp!, {r0 - r3, lr}
mov r0, ip
beq 1f
bl rwsem_wake_readers
ldmfd sp!, {r0 - r3, pc}
1: bl rwsem_wake_writer
ldmfd sp!, {r0 - r3, pc}
.previous
");
#endif
......@@ -5,6 +5,8 @@
mainmenu_name "Linux/CRIS Kernel Configuration"
define_bool CONFIG_UID16 y
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
mainmenu_option next_comment
comment 'Code maturity level options'
......
......@@ -127,112 +127,3 @@ int __down_trylock(struct semaphore * sem)
{
return waking_non_zero_trylock(sem);
}
/*
* RW Semaphores
*/
void
__down_read(struct rw_semaphore *sem, int count)
{
DOWN_VAR;
retry_down:
if (count < 0) {
/* Wait for the lock to become unbiased. Readers
are non-exclusive. */
/* This takes care of granting the lock. */
up_read(sem);
add_wait_queue(&sem->wait, &wait);
while (atomic_read(&sem->count) < 0) {
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (atomic_read(&sem->count) >= 0)
break;
schedule();
}
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
mb();
count = atomic_dec_return(&sem->count);
if (count <= 0)
goto retry_down;
} else {
add_wait_queue(&sem->wait, &wait);
while (1) {
if (test_and_clear_bit(0, &sem->granted))
break;
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if ((sem->granted & 1) == 0)
schedule();
}
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
}
}
void
__down_write(struct rw_semaphore *sem, int count)
{
DOWN_VAR;
retry_down:
if (count + RW_LOCK_BIAS < 0) {
up_write(sem);
add_wait_queue_exclusive(&sem->wait, &wait);
while (atomic_read(&sem->count) < 0) {
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (atomic_read(&sem->count) >= RW_LOCK_BIAS)
break;
schedule();
}
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
mb();
count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
if (count != 0)
goto retry_down;
} else {
/* Put ourselves at the end of the list. */
add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
while (1) {
if (test_and_clear_bit(1, &sem->granted))
break;
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if ((sem->granted & 2) == 0)
schedule();
}
remove_wait_queue(&sem->write_bias_wait, &wait);
tsk->state = TASK_RUNNING;
/* If the lock is currently unbiased, awaken the sleepers.
FIXME: This wakes up the readers early in a bit of a
stampede -> bad! */
if (atomic_read(&sem->count) >= 0)
wake_up(&sem->wait);
}
}
void
__rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
{
if (readers) {
if (test_and_set_bit(0, &sem->granted))
BUG();
wake_up(&sem->wait);
} else {
if (test_and_set_bit(1, &sem->granted))
BUG();
wake_up(&sem->write_bias_wait);
}
}
......@@ -9,6 +9,8 @@ define_bool CONFIG_ISA y
define_bool CONFIG_SBUS n
define_bool CONFIG_UID16 y
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
mainmenu_option next_comment
comment 'Code maturity level options'
......
......@@ -34,6 +34,8 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n)
else
mmx_copy_user_zeroing(to, from, n);
}
else
memset(to, 0, n);
return n;
}
......@@ -52,6 +54,8 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n)
{
if (access_ok(VERIFY_READ, from, n))
__copy_user_zeroing(to,from,n);
else
memset(to, 0, n);
return n;
}
......
......@@ -23,6 +23,8 @@ define_bool CONFIG_ISA n
define_bool CONFIG_EISA n
define_bool CONFIG_MCA n
define_bool CONFIG_SBUS n
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
choice 'IA-64 processor type' \
"Itanium CONFIG_ITANIUM \
......
......@@ -155,180 +155,3 @@ __down_trylock (struct semaphore *sem)
spin_unlock_irqrestore(&semaphore_lock, flags);
return 1;
}
/*
* Helper routines for rw semaphores. These could be optimized some
* more, but since they're off the critical path, I prefer clarity for
* now...
*/
/*
* This gets called if we failed to acquire the lock, but we're biased
* to acquire the lock by virtue of causing the count to change from 0
* to -1. Being biased, we sleep and attempt to grab the lock until
* we succeed. When this function returns, we own the lock.
*/
static inline void
down_read_failed_biased (struct rw_semaphore *sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */
for (;;) {
if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
break;
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (!sem->read_bias_granted)
schedule();
}
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
}
/*
* This gets called if we failed to acquire the lock and we are not
* biased to acquire the lock. We undo the decrement that was
* done earlier, go to sleep, and then attempt to re-acquire the
* lock afterwards.
*/
static inline void
down_read_failed (struct rw_semaphore *sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
/*
* Undo the decrement we did in down_read() and check if we
* need to wake up someone.
*/
__up_read(sem);
add_wait_queue(&sem->wait, &wait);
while (sem->count < 0) {
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (sem->count >= 0)
break;
schedule();
}
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
}
/*
* Wait for the lock to become unbiased. Readers are non-exclusive.
*/
void
__down_read_failed (struct rw_semaphore *sem, long count)
{
while (1) {
if (count == -1) {
down_read_failed_biased(sem);
return;
}
/* unbiased */
down_read_failed(sem);
count = ia64_fetch_and_add(-1, &sem->count);
if (count >= 0)
return;
}
}
static inline void
down_write_failed_biased (struct rw_semaphore *sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
/* put ourselves at the end of the list */
add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
for (;;) {
if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
break;
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (!sem->write_bias_granted)
schedule();
}
remove_wait_queue(&sem->write_bias_wait, &wait);
tsk->state = TASK_RUNNING;
/*
* If the lock is currently unbiased, awaken the sleepers
* FIXME: this wakes up the readers early in a bit of a
* stampede -> bad!
*/
if (sem->count >= 0)
wake_up(&sem->wait);
}
static inline void
down_write_failed (struct rw_semaphore *sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
__up_write(sem); /* this takes care of granting the lock */
add_wait_queue_exclusive(&sem->wait, &wait);
while (sem->count < 0) {
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (sem->count >= 0)
break; /* we must attempt to acquire or bias the lock */
schedule();
}
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
}
/*
* Wait for the lock to become unbiased. Since we're a writer, we'll
* make ourselves exclusive.
*/
void
__down_write_failed (struct rw_semaphore *sem, long count)
{
long old_count;
while (1) {
if (count == -RW_LOCK_BIAS) {
down_write_failed_biased(sem);
return;
}
down_write_failed(sem);
do {
old_count = sem->count;
count = old_count - RW_LOCK_BIAS;
} while (cmpxchg_acq(&sem->count, old_count, count) != old_count);
if (count == 0)
return;
}
}
void
__rwsem_wake (struct rw_semaphore *sem, long count)
{
wait_queue_head_t *wq;
if (count == 0) {
/* wake a writer */
if (xchg(&sem->write_bias_granted, 1))
BUG();
wq = &sem->write_bias_wait;
} else {
/* wake reader(s) */
if (xchg(&sem->read_bias_granted, 1))
BUG();
wq = &sem->wait;
}
wake_up(wq); /* wake up everyone on the wait queue */
}
......@@ -769,20 +769,6 @@ static int amiga_wait_key (struct console *co)
return 0;
}
void dbprintf(const char *fmt , ...)
{
static char buf[1024];
va_list args;
extern void console_print (const char *str);
extern int vsprintf(char * buf, const char * fmt, va_list args);
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
console_print (buf);
}
static NORET_TYPE void amiga_reset( void )
ATTRIB_NORET;
......
......@@ -4,6 +4,8 @@
#
define_bool CONFIG_UID16 y
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
mainmenu_name "Linux/68k Kernel Configuration"
......
......@@ -130,111 +130,3 @@ int __down_trylock(struct semaphore * sem)
{
return waking_non_zero_trylock(sem);
}
/* Wait for the lock to become unbiased. Readers
* are non-exclusive. =)
*/
void down_read_failed(struct rw_semaphore *sem)
{
DECLARE_WAITQUEUE(wait, current);
__up_read(sem); /* this takes care of granting the lock */
add_wait_queue(&sem->wait, &wait);
while (atomic_read(&sem->count) < 0) {
set_task_state(current, TASK_UNINTERRUPTIBLE);
if (atomic_read(&sem->count) >= 0)
break;
schedule();
}
remove_wait_queue(&sem->wait, &wait);
current->state = TASK_RUNNING;
}
void down_read_failed_biased(struct rw_semaphore *sem)
{
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */
for (;;) {
if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
break;
set_task_state(current, TASK_UNINTERRUPTIBLE);
if (!sem->read_bias_granted)
schedule();
}
remove_wait_queue(&sem->wait, &wait);
current->state = TASK_RUNNING;
}
/* Wait for the lock to become unbiased. Since we're
* a writer, we'll make ourselves exclusive.
*/
void down_write_failed(struct rw_semaphore *sem)
{
DECLARE_WAITQUEUE(wait, current);
__up_write(sem); /* this takes care of granting the lock */
add_wait_queue_exclusive(&sem->wait, &wait);
while (atomic_read(&sem->count) < 0) {
set_task_state(current, TASK_UNINTERRUPTIBLE);
if (atomic_read(&sem->count) >= 0)
break; /* we must attempt to acquire or bias the lock */
schedule();
}
remove_wait_queue(&sem->wait, &wait);
current->state = TASK_RUNNING;
}
void down_write_failed_biased(struct rw_semaphore *sem)
{
DECLARE_WAITQUEUE(wait, current);
add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
for (;;) {
if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
break;
set_task_state(current, TASK_UNINTERRUPTIBLE);
if (!sem->write_bias_granted)
schedule();
}
remove_wait_queue(&sem->write_bias_wait, &wait);
current->state = TASK_RUNNING;
/* if the lock is currently unbiased, awaken the sleepers
* FIXME: this wakes up the readers early in a bit of a
* stampede -> bad!
*/
if (atomic_read(&sem->count) >= 0)
wake_up(&sem->wait);
}
/* Called when someone has done an up that transitioned from
* negative to non-negative, meaning that the lock has been
* granted to whomever owned the bias.
*/
void rwsem_wake_readers(struct rw_semaphore *sem)
{
if (xchg(&sem->read_bias_granted, 1))
BUG();
wake_up(&sem->wait);
}
void rwsem_wake_writer(struct rw_semaphore *sem)
{
if (xchg(&sem->write_bias_granted, 1))
BUG();
wake_up(&sem->write_bias_wait);
}
......@@ -39,10 +39,6 @@
#include <linux/blk.h>
#endif
#ifndef CONFIG_AMIGA
#define dbprintf printk
#endif
unsigned long m68k_machtype;
unsigned long m68k_cputype;
unsigned long m68k_fputype;
......
......@@ -17,8 +17,10 @@
#
ifdef CONFIG_CPU_LITTLE_ENDIAN
tool-prefix = mipsel-linux-
output-format = elf32-littlemips
else
tool-prefix = mips-linux-
output-format = elf32-bigmips
endif
ifdef CONFIG_CROSSCOMPILE
......@@ -26,16 +28,16 @@ CROSS_COMPILE = $(tool-prefix)
endif
#
# The ELF GCC uses -G0 -mabicalls -fpic as default. We don't need PIC
# code in the kernel since it only slows down the whole thing. For the
# old GCC these options are just the defaults. At some point we might
# make use of global pointer optimizations.
# GCC uses -G0 -mabicalls -fpic as default. We don't want PIC in the kernel
# code since it only slows down the whole thing. At some point we might make
# use of global pointer optimizations but their use of $28 conflicts with
# the current pointer optimization.
#
# The DECStation requires an ECOFF kernel for remote booting, other MIPS
# machines may also. Since BFD is incredibly buggy with respect to
# crossformat linking we rely on the elf2ecoff tool for format conversion.
#
CFLAGS += -G 0 -mno-abicalls -fno-pic
GCCFLAGS := -G 0 -mno-abicalls -fno-pic
LINKFLAGS += -static -G 0
MODFLAGS += -mlong-calls
......@@ -47,37 +49,63 @@ endif
# CPU-dependent compiler/assembler options for optimization.
#
ifdef CONFIG_CPU_R3000
CFLAGS := $(CFLAGS) -mcpu=r3000 -mips1
GCCFLAGS += -mcpu=r3000 -mips1
endif
ifdef CONFIG_CPU_R3912
GCCFLAGS += -mcpu=r3000 -mips1
endif
ifdef CONFIG_CPU_R6000
CFLAGS := $(CFLAGS) -mcpu=r6000 -mips2 -Wa,--trap
GCCFLAGS += -mcpu=r6000 -mips2 -Wa,--trap
endif
ifdef CONFIG_CPU_R4300
CFLAGS := $(CFLAGS) -mcpu=r4300 -mips2 -Wa,--trap
GCCFLAGS += -mcpu=r4300 -mips2 -Wa,--trap
endif
ifdef CONFIG_CPU_R4X00
CFLAGS := $(CFLAGS) -mcpu=r4600 -mips2 -Wa,--trap
GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap
endif
ifdef CONFIG_CPU_MIPS32
GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap
endif
ifdef CONFIG_CPU_R5000
CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap
endif
ifdef CONFIG_CPU_R5432
GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap
endif
ifdef CONFIG_CPU_NEVADA
CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap -mmad
GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap -mmad
endif
ifdef CONFIG_CPU_RM7000
GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap
endif
ifdef CONFIG_CPU_R8000
CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap
endif
ifdef CONFIG_CPU_R10000
CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap
endif
ifdef CONFIG_MIPS_FPU_EMULATOR
CORE_FILES +=arch/mips/math-emu/fpu_emulator.o
SUBDIRS +=arch/mips/math-emu
endif
#
# The pipe options is bad for my low-mem machine
# Uncomment this if you want this.
#
GCCFLAGS += -pipe
CFLAGS := -I $(TOPDIR)/include/asm/gcc $(CFLAGS) $(GCCFLAGS)
AFLAGS += $(GCCFLAGS)
#
# Board-dependent options and extra files
#
ifdef CONFIG_ALGOR_P4032
CORE_FILES += arch/mips/algor/algor.o
SUBDIRS += arch/mips/algor
#LOADADDR += 0x80000000
LOADADDR += 0x80000000
endif
#
......@@ -90,6 +118,18 @@ LIBS += arch/mips/dec/prom/rexlib.a
LOADADDR += 0x80040000
endif
ifdef CONFIG_MIPS_ATLAS
LIBS += arch/mips/mips-boards/atlas/atlas.o arch/mips/mips-boards/generic/mipsboards.o
SUBDIRS += arch/mips/mips-boards/generic arch/mips/mips-boards/atlas
LOADADDR += 0x80100000
endif
ifdef CONFIG_MIPS_MALTA
LIBS += arch/mips/mips-boards/malta/malta.o arch/mips/mips-boards/generic/mipsboards.o
SUBDIRS += arch/mips/mips-boards/malta arch/mips/mips-boards/generic
LOADADDR += 0x80100000
endif
#
# Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
#
......@@ -100,12 +140,6 @@ LIBS += arch/mips/arc/arclib.a
LOADADDR += 0x80080000
endif
ifdef CONFIG_COBALT_MICRO_SERVER
ARCHIVES += arch/mips/cobalt/cobalt.o
SUBDIRS += arch/mips/cobalt
LOADADDR += 0x80000000
endif
ifdef CONFIG_SNI_RM200_PCI
CORE_FILES += arch/mips/sni/sni.o
SUBDIRS += arch/mips/sni arch/mips/arc
......@@ -114,7 +148,8 @@ LOADADDR += 0x80080000
endif
ifdef CONFIG_SGI_IP22
LIBS += arch/mips/sgi/kernel/sgikern.a arch/mips/arc/arclib.a
CORE_FILES += arch/mips/sgi/kernel/ip22-kern.o
LIBS += arch/mips/arc/arclib.a
SUBDIRS += arch/mips/sgi/kernel arch/mips/arc
#
# Set LOADADDR to >= 0x88069000 if you want to leave space for symmon,
......@@ -152,28 +187,74 @@ LINKSCRIPT = arch/mips/orion/ld.script.orion
endif
#
# Choosing incompatible machines durings configuration will result in
# error messages during linking. Select a default linkscript if
# none has been choosen above.
#
ifndef LINKSCRIPT
ifndef CONFIG_CPU_LITTLE_ENDIAN
LINKSCRIPT = arch/mips/ld.script.big
else
LINKSCRIPT = arch/mips/ld.script.little
# NEC DDB Vrc-5476
#
ifdef CONFIG_DDB5476
SUBDIRS += arch/mips/ddb5476
LIBS += arch/mips/ddb5476/ddb5476.a
LOADADDR += 0x80080000
endif
#
# Galileo EV64120 Board
#
ifdef CONFIG_MIPS_EV64120
LIBS += arch/mips/galileo-boards/ev64120/ev64120.o
SUBDIRS += arch/mips/galileo-boards/ev64120
LOADADDR += 0x80100000
endif
LINKFLAGS += -T $(word 1,$(LINKSCRIPT))
ifdef LOADADDR
LINKFLAGS += -Ttext $(word 1,$(LOADADDR))
#
# Galileo EV96100 Board
#
ifdef CONFIG_MIPS_EV96100
LIBS += arch/mips/galileo-boards/ev96100/ev96100.o arch/mips/galileo-boards/generic/galboards.o
SUBDIRS += arch/mips/galileo-boards/generic arch/mips/galileo-boards/ev96100
LOADADDR += 0x80100000
endif
#
# The pipe options is bad for my low-mem machine
# Uncomment this if you want this.
# Momentum Ocelot board
#
ifdef CONFIG_MOMENCO_OCELOT
LIBS += arch/mips/gt64120/common/gt64120.o arch/mips/gt64120/momenco_ocelot/momenco_ocelot.o
SUBDIRS += arch/mips/gt64120/common arch/mips/gt64120/momenco_ocelot
LOADADDR += 0x80100000
endif
#
CFLAGS += -pipe
# Philips Nino
#
ifdef CONFIG_NINO
CORE_FILES += arch/mips/philips/nino/nino.o \
arch/mips/philips/drivers/drivers.o
SUBDIRS += arch/mips/philips/nino arch/mips/philips/drivers
LOADADDR += 0x80000000
endif
#
# ITE 8172 eval board with QED 5231 CPU
#
ifdef CONFIG_MIPS_ITE8172
LIBS += arch/mips/ite-boards/qed-4n-s01b/ite.o \
arch/mips/ite-boards/generic/it8172.o
SUBDIRS += arch/mips/ite-boards/generic \
arch/mips/ite-boards/qed-4n-s01b
LOADADDR += 0x80100000
endif
#
# Choosing incompatible machines durings configuration will result in
# error messages during linking. Select a default linkscript if
# none has been choosen above.
#
vmlinux: arch/$(ARCH)/ld.script
arch/$(ARCH)/ld.script: arch/$(ARCH)/ld.script.in arch/$(ARCH)/Makefile
sed -e 's/@@OUTPUT_FORMAT@@/$(output-format)/' \
-e 's/@@LOADADDR@@/$(LOADADDR)/' <$< >$@
LINKFLAGS += -T arch/$(ARCH)/ld.script
HEAD := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
......@@ -197,8 +278,18 @@ orionboot:
$(ORIONBOOT) orionboot
endif
ifdef CONFIG_MIPS_EV64120
GALILEOBOOT = $(MAKE) -C arch/$(ARCH)/galileo-boards/ev64120
gboot: vmlinux
$(MAKE) -C arch/$(ARCH)/galileo-boards/ev64120/compressed
endif
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
vmlinux.ecoff: vmlinux
@$(MAKEBOOT) $@
zImage: vmlinux
@$(MAKEBOOT) zImage
......@@ -209,7 +300,7 @@ zdisk: vmlinux
archclean:
@$(MAKEBOOT) clean
$(MAKE) -C arch/$(ARCH)/kernel clean
rm -f arch/$(ARCH)/ld.script
$(MAKE) -C arch/$(ARCH)/tools clean
$(MAKE) -C arch/mips/baget clean
......
# $Id: Makefile,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
#
# Makefile for the SGI arcs prom monitor library routines
# under Linux.
......@@ -10,7 +9,10 @@
# Note 2! The CFLAGS definitions are now in the main makefile...
L_TARGET = arclib.a
L_OBJS = console.o init.o printf.o memory.o tree.o env.o cmdline.o misc.o \
time.o file.o identify.o
obj-y += console.o init.o memory.o tree.o env.o cmdline.o misc.o \
time.o file.o identify.o
obj-$(CONFIG_ARC_CONSOLE) += arc_con.o
include $(TOPDIR)/Rules.make
/*
* Wrap-around code for a console using the
* ARC io-routines.
*
* Copyright (c) 1998 Harald Koerfgen
*/
#include <linux/tty.h>
#include <linux/major.h>
#include <linux/ptrace.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/fs.h>
extern char prom_getchar (void);
extern void prom_printf (char *, ...);
static void prom_console_write(struct console *co, const char *s,
unsigned count)
{
unsigned i;
/*
* Now, do each character
*/
for (i = 0; i < count; i++) {
if (*s == 10)
prom_printf("%c", 13);
prom_printf("%c", *s++);
}
}
static int prom_console_wait_key(struct console *co)
{
return prom_getchar();
}
static int __init prom_console_setup(struct console *co, char *options)
{
return 0;
}
static kdev_t prom_console_device(struct console *c)
{
return MKDEV(TTY_MAJOR, 64 + c->index);
}
static struct console arc_cons = {
"ttyS",
prom_console_write,
NULL,
prom_console_device,
prom_console_wait_key,
NULL,
prom_console_setup,
CON_PRINTBUFFER,
-1,
0,
NULL
};
/*
* Register console.
*/
void __init arc_console_init(void)
{
register_console(&arc_cons);
}
......@@ -2,8 +2,6 @@
* cmdline.c: Kernel command line creation using ARCS argc/argv.
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
* $Id: cmdline.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
*/
#include <linux/init.h>
#include <linux/kernel.h>
......@@ -12,9 +10,9 @@
#include <asm/sgialib.h>
#include <asm/bootinfo.h>
/* #define DEBUG_CMDLINE */
#undef DEBUG_CMDLINE
char arcs_cmdline[CL_SIZE];
char arcs_cmdline[COMMAND_LINE_SIZE];
char * __init prom_getcmdline(void)
{
......
/*
* console.c: SGI arcs console code.
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1996 David S. Miller (dm@sgi.com)
* Compability with board caches, Ulf Carlsson
*
* $Id: console.c,v 1.3 1999/10/09 00:00:57 ralf Exp $
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <asm/sgialib.h>
#include <asm/bcache.h>
#include <linux/console.h>
#include <linux/kdev_t.h>
#include <linux/major.h>
#ifdef CONFIG_ARC_CONSOLE
#define __init
#endif
/* The romvec is not compatible with board caches. Thus we disable it during
* romvec action. Since r4xx0.c is always compiled and linked with your kernel,
* this shouldn't cause any harm regardless what MIPS processor you have.
/*
* IP22 boardcache is not compatible with board caches. Thus we disable it
* during romvec action. Since r4xx0.c is always compiled and linked with your
* kernel, this shouldn't cause any harm regardless what MIPS processor you
* have.
*
* The romvec write and read functions seem to interfere with the serial lines
* The ARC write and read functions seem to interfere with the serial lines
* in some way. You should be careful with them.
*/
extern struct bcache_ops *bcops;
#ifdef CONFIG_SGI_PROM_CONSOLE
void prom_putchar(char c)
#else
void __init prom_putchar(char c)
#endif
{
long cnt;
char it = c;
bcops->bc_disable();
bc_disable();
romvec->write(1, &it, 1, &cnt);
bcops->bc_enable();
bc_enable();
}
#ifdef CONFIG_SGI_PROM_CONSOLE
char prom_getchar(void)
#else
char __init prom_getchar(void)
#endif
{
long cnt;
char c;
bcops->bc_disable();
bc_disable();
romvec->read(0, &c, 1, &cnt);
bcops->bc_enable();
bc_enable();
return c;
}
static char ppbuf[1024];
void __init prom_printf(char *fmt, ...)
{
va_list args;
char ch, *bptr;
int i;
va_start(args, fmt);
i = vsprintf(ppbuf, fmt, args);
bptr = ppbuf;
while ((ch = *(bptr++)) != 0) {
if (ch == '\n')
prom_putchar('\r');
prom_putchar(ch);
}
va_end(args);
}
static void
arc_console_write(struct console *con, const char *s, unsigned n)
{
prom_printf("%s", s);
}
static kdev_t
arc_console_dev(struct console *c)
{
return MKDEV(TTY_MAJOR, 64 + c->index);
}
static struct console arc_prom_console = {
name: "prom",
write: arc_console_write,
device: arc_console_dev,
flags: CON_PRINTBUFFER,
index: -1,
};
__init void arc_setup_console(void)
{
register_console(&arc_prom_console);
}
......@@ -6,8 +6,6 @@
* This code is based on arch/mips/sgi/kernel/system.c, which is
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
* $Id: identify.c,v 1.2 1999/02/25 21:04:13 tsbogend Exp $
*/
#include <linux/init.h>
#include <linux/kernel.h>
......@@ -19,50 +17,51 @@
#include <asm/bootinfo.h>
struct smatch {
char *name;
int group;
int type;
int flags;
char *name;
int group;
int type;
int flags;
};
static struct smatch mach_table[] = {
{ "SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS },
{ "Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0 },
{ "PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0 },
{ "RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0 }
{"SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS},
{"Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0},
{"PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0},
{"RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0}
};
int prom_flags;
static struct smatch * __init string_to_mach(char *s)
static struct smatch *__init string_to_mach(char *s)
{
int i;
for (i = 0; i < sizeof (mach_table); i++) {
if(!strcmp(s, mach_table[i].name))
return &mach_table[i];
}
prom_printf("\nYeee, could not determine architecture type <%s>\n", s);
prom_printf("press a key to reboot\n");
prom_getchar();
romvec->imode();
return NULL;
int i;
for (i = 0; i < sizeof(mach_table); i++) {
if (!strcmp(s, mach_table[i].name))
return &mach_table[i];
}
prom_printf("\nYeee, could not determine architecture type <%s>\n",
s);
prom_printf("press a key to reboot\n");
prom_getchar();
romvec->imode();
return NULL;
}
void __init prom_identify_arch(void)
{
pcomponent *p;
struct smatch *mach;
/* The root component tells us what machine architecture we
* have here.
*/
p = prom_getchild(PROM_NULL_COMPONENT);
printk("ARCH: %s\n", p->iname);
mach = string_to_mach(p->iname);
pcomponent *p;
struct smatch *mach;
mips_machgroup = mach->group;
mips_machtype = mach->type;
prom_flags = mach->flags;
}
/*
* The root component tells us what machine architecture we
* have here.
*/
p = prom_getchild(PROM_NULL_COMPONENT);
printk("ARCH: %s\n", p->iname);
mach = string_to_mach(p->iname);
mips_machgroup = mach->group;
mips_machtype = mach->type;
prom_flags = mach->flags;
}
/* $Id: init.c,v 1.5 2000/03/07 15:45:27 ralf Exp $
/*
* This file is subject to the terms and conditions of the GNU General Public+
* License. See the file "COPYING" in the main directory of this archive
* for more details.
......@@ -23,7 +23,9 @@ unsigned short prom_vers, prom_rev;
extern void prom_testtree(void);
int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
extern void arc_setup_console(void);
void __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
{
struct linux_promblock *pb;
......@@ -33,7 +35,20 @@ int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
prom_argv = argv;
prom_envp = envp;
if(pb->magic != 0x53435241) {
#if 0
/* arc_printf should not use prom_printf as soon as we free
* the prom buffers - This horribly breaks on Indys with framebuffer
* as it simply stops after initialising swap - On the Indigo2 serial
* console you will get A LOT illegal instructions - Only enable
* this for early init crashes - This also brings up artefacts of
* printing everything twice on serial console and on GFX Console
* this has the effect of having the prom printing everything
* in the small rectangle and the kernel printing around.
*/
arc_setup_console();
#endif
if (pb->magic != 0x53435241) {
prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic);
while(1)
;
......@@ -55,5 +70,4 @@ int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
romvec->imode();
}
#endif
return 0;
}
......@@ -3,8 +3,6 @@
* given to us from the ARCS firmware.
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
* $Id: memory.c,v 1.10 2000/01/27 23:21:57 ralf Exp $
*/
#include <linux/init.h>
#include <linux/kernel.h>
......@@ -47,31 +45,25 @@ static char *arc_mtypes[8] = {
"LoadedProgram",
"FirmwareTemporary",
"FirmwarePermanent",
"FreeContigiuous"
"FreeContiguous"
};
#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc]
#endif
static struct prom_pmemblock pblocks[PROM_MAX_PMEMBLOCKS];
#define MEMTYPE_DONTUSE 0
#define MEMTYPE_PROM 1
#define MEMTYPE_FREE 2
static inline int memtype_classify_arcs (union linux_memtypes type)
{
switch (type.arcs) {
case arcs_fcontig:
case arcs_free:
return MEMTYPE_FREE;
return BOOT_MEM_RAM;
case arcs_atmp:
return MEMTYPE_PROM;
return BOOT_MEM_ROM_DATA;
case arcs_eblock:
case arcs_rvpage:
case arcs_bmem:
case arcs_prog:
case arcs_aperm:
return MEMTYPE_DONTUSE;
return BOOT_MEM_RESERVED;
default:
BUG();
}
......@@ -83,15 +75,15 @@ static inline int memtype_classify_arc (union linux_memtypes type)
switch (type.arc) {
case arc_free:
case arc_fcontig:
return MEMTYPE_FREE;
return BOOT_MEM_RAM;
case arc_atmp:
return MEMTYPE_PROM;
return BOOT_MEM_ROM_DATA;
case arc_eblock:
case arc_rvpage:
case arc_bmem:
case arc_prog:
case arc_aperm:
return MEMTYPE_DONTUSE;
return BOOT_MEM_RESERVED;
default:
BUG();
}
......@@ -106,50 +98,13 @@ static int __init prom_memtype_classify (union linux_memtypes type)
return memtype_classify_arc(type);
}
static inline unsigned long find_max_low_pfn(void)
{
struct prom_pmemblock *p, *highest;
unsigned long pfn;
p = pblocks;
highest = 0;
while (p->size != 0) {
if (!highest || p->base > highest->base)
highest = p;
p++;
}
pfn = (highest->base + highest->size) >> PAGE_SHIFT;
#ifdef DEBUG
prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn);
#endif
return pfn;
}
static inline struct prom_pmemblock *find_largest_memblock(void)
{
struct prom_pmemblock *p, *largest;
p = pblocks;
largest = 0;
while (p->size != 0) {
if (!largest || p->size > largest->size)
largest = p;
p++;
}
return largest;
}
void __init prom_meminit(void)
{
struct prom_pmemblock *largest;
unsigned long bootmap_size;
struct linux_mdesc *p;
int totram;
int i = 0;
#ifdef DEBUG
int i = 0;
prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
while(p) {
......@@ -160,77 +115,36 @@ void __init prom_meminit(void)
}
#endif
totram = 0;
i = 0;
p = PROM_NULL_MDESC;
while ((p = ArcGetMemoryDescriptor(p))) {
pblocks[i].type = prom_memtype_classify(p->type);
pblocks[i].base = p->base << PAGE_SHIFT;
pblocks[i].size = p->pages << PAGE_SHIFT;
unsigned long base, size;
long type;
switch (pblocks[i].type) {
case MEMTYPE_FREE:
totram += pblocks[i].size;
#ifdef DEBUG
prom_printf("free_chunk[%d]: base=%08lx size=%x\n",
i, pblocks[i].base,
pblocks[i].size);
#endif
i++;
break;
case MEMTYPE_PROM:
#ifdef DEBUG
prom_printf("prom_chunk[%d]: base=%08lx size=%x\n",
i, pblocks[i].base,
pblocks[i].size);
#endif
i++;
break;
default:
break;
}
}
pblocks[i].size = 0;
max_low_pfn = find_max_low_pfn();
largest = find_largest_memblock();
bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn);
for (i = 0; pblocks[i].size; i++)
if (pblocks[i].type == MEMTYPE_FREE)
free_bootmem(pblocks[i].base, pblocks[i].size);
base = p->base << PAGE_SHIFT;
size = p->pages << PAGE_SHIFT;
type = prom_memtype_classify(p->type);
/* This test is simpleminded. It will fail if the bootmem bitmap
falls into multiple adjacent ARC memory areas. */
if (bootmap_size > largest->size) {
prom_printf("CRITIAL: overwriting PROM data.\n");
BUG();
add_memory_region(base, size, type);
}
/* Reserve the memory bootmap itself */
reserve_bootmem(largest->base, bootmap_size);
printk("PROMLIB: Total free ram %dK / %dMB.\n",
totram >> 10, totram >> 20);
}
void __init
prom_free_prom_memory (void)
{
struct prom_pmemblock *p;
unsigned long freed = 0;
unsigned long addr;
int i;
for (p = pblocks; p->size != 0; p++) {
if (p->type != MEMTYPE_PROM)
for (i = 0; i < boot_mem_map.nr_map; i++) {
if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
continue;
addr = PAGE_OFFSET + p->base;
while (addr < p->base + p->size) {
ClearPageReserved(virt_to_page(addr));
set_page_count(virt_to_page(addr), 1);
free_page(addr);
addr = boot_mem_map.map[i].addr;
while (addr < boot_mem_map.map[i].addr
+ boot_mem_map.map[i].size) {
ClearPageReserved(virt_to_page(__va(addr)));
set_page_count(virt_to_page(__va(addr)), 1);
free_page((unsigned long)__va(addr));
addr += PAGE_SIZE;
freed += PAGE_SIZE;
}
......
/* $Id: misc.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $
*
/*
* misc.c: Miscellaneous ARCS PROM routines.
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
......@@ -13,13 +12,12 @@
#include <asm/bootinfo.h>
#include <asm/system.h>
extern unsigned long mips_cputype;
extern void *sgiwd93_host;
extern void reset_wd33c93(void *instance);
void prom_halt(void)
{
bcops->bc_disable();
bc_disable();
cli();
#if CONFIG_SCSI_SGIWD93
reset_wd33c93(sgiwd93_host);
......@@ -29,7 +27,7 @@ void prom_halt(void)
void prom_powerdown(void)
{
bcops->bc_disable();
bc_disable();
cli();
#if CONFIG_SCSI_SGIWD93
reset_wd33c93(sgiwd93_host);
......@@ -40,7 +38,7 @@ void prom_powerdown(void)
/* XXX is this a soft reset basically? XXX */
void prom_restart(void)
{
bcops->bc_disable();
bc_disable();
cli();
#if CONFIG_SCSI_SGIWD93
reset_wd33c93(sgiwd93_host);
......@@ -50,7 +48,7 @@ void prom_restart(void)
void prom_reboot(void)
{
bcops->bc_disable();
bc_disable();
cli();
#if CONFIG_SCSI_SGIWD93
reset_wd33c93(sgiwd93_host);
......@@ -60,7 +58,7 @@ void prom_reboot(void)
void prom_imode(void)
{
bcops->bc_disable();
bc_disable();
cli();
#if CONFIG_SCSI_SGIWD93
reset_wd33c93(sgiwd93_host);
......
/*
* printf.c: Putting things on the screen using SGI arcs
* PROM facilities.
*
* Copyright (C) 1996 David S. Miller (dm@sgi.com)
*
* $Id: printf.c,v 1.3 1999/10/09 00:00:57 ralf Exp $
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <asm/sgialib.h>
static char ppbuf[1024];
#ifdef CONFIG_SGI_PROM_CONSOLE
void prom_printf(char *fmt, ...)
#else
void __init prom_printf(char *fmt, ...)
#endif
{
va_list args;
char ch, *bptr;
int i;
va_start(args, fmt);
i = vsprintf(ppbuf, fmt, args);
bptr = ppbuf;
while((ch = *(bptr++)) != 0) {
if(ch == '\n')
prom_putchar('\r');
prom_putchar(ch);
}
va_end(args);
return;
}
# $Id: Makefile,v 1.3 1999/08/13 17:07:26 harald Exp $
#
# Makefile for the Baget specific kernel interface routines
# under Linux.
......@@ -12,22 +11,12 @@
all: baget.a
O_TARGET := baget.a
O_OBJS := baget.o print.o setup.o time.o irq.o bagetIRQ.o reset.o wbflush.o
ifeq ($(CONFIG_SERIAL),y)
OX_OBJS += vacserial.o
else
ifeq ($(CONFIG_SERIAL),m)
MX_OBJS += vacserial.o
endif
endif
ifeq ($(CONFIG_VAC_RTC),y)
OX_OBJS += vacrtc.o
else
ifeq ($(CONFIG_VAC_RTC),m)
MX_OBJS += vacrtc.o
endif
endif
export-objs := vacserial.o vacrtc.o
obj-y := baget.o print.o setup.o time.o irq.o bagetIRQ.o \
reset.o wbflush.o
obj-$(CONFIG_SERIAL) += vacserial.o
obj-$(CONFIG_VAC_RTC) += vacrtc.o
bagetIRQ.o : bagetIRQ.S
$(CC) $(CFLAGS) -c -o $@ $<
......
# $Id$
#
# Makefile for the Baget/MIPS prom emulator library routines.
#
# Note! Dependencies are done automagically by 'make dep', which also
......@@ -7,9 +7,8 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := bagetlib.a
O_OBJS := init.o
L_TARGET := bagetlib.a
all: $(O_TARGET)
obj-y := init.o
include $(TOPDIR)/Rules.make
......@@ -28,6 +28,9 @@ bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700
bool 'Support for SGI IP22' CONFIG_SGI_IP22
bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
#
# Select some configuration options automatically for certain systems.
#
......@@ -329,7 +332,10 @@ if [ "$CONFIG_DECSTATION" = "y" ]; then
# if [ "$CONFIG_ACCESSBUS" = "y" ]; then
# bool 'MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE
# fi
bool 'Enhanced Real Time Clock Support' CONFIG_RTC
bool 'Enhanced Real Time Clock Support' CONFIG_MIPS_RTC
define_tristate CONFIG_RTC $CONFIG_MIPS_RTC
endmenu
fi
......
......@@ -8,8 +8,6 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile...
#
# $Id$
#
.S.s:
$(CPP) $(CFLAGS) $< -o $*.s
......@@ -17,6 +15,7 @@
$(CC) $(CFLAGS) -c $< -o $*.o
O_TARGET = ddb5074.a
O_OBJS = setup.o irq.o time.o prom.o pci.o pci-dma.o int-handler.o nile4.o
obj-y := setup.o irq.o time.o prom.o pci.o int-handler.o nile4.o
include $(TOPDIR)/Rules.make
......@@ -7,54 +7,50 @@
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*
* $Id: int-handler.S,v 1.1 2000/01/26 00:07:44 ralf Exp $
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
/* A lot of complication here is taken away because:
*
* 1) We handle one interrupt and return, sitting in a loop
* and moving across all the pending IRQ bits in the cause
* register is _NOT_ the answer, the common case is one
* pending IRQ so optimize in that direction.
*
* 2) We need not check against bits in the status register
* IRQ mask, that would make this routine slow as hell.
*
* 3) Linux only thinks in terms of all IRQs on or all IRQs
* off, nothing in between like BSD spl() brain-damage.
*
* Furthermore, the IRQs on the INDY look basically (barring
* software IRQs which we don't use at all) like:
*
* MIPS IRQ Source
* -------- ------
* 0 Software (ignored)
* 1 Software (ignored)
* 2 Local IRQ level zero
* 3 Local IRQ level one
* 4 8254 Timer zero
* 5 8254 Timer one
* 6 Bus Error
* 7 R4k timer (what we use)
*
* We handle the IRQ according to _our_ priority which is:
*
* Highest ---- R4k Timer
* Local IRQ zero
* Local IRQ one
* Bus Error
* 8254 Timer zero
* Lowest ---- 8254 Timer one
*
* then we just return, if multiple IRQs are pending then
* we will just take another exception, big deal.
*/
/* A lot of complication here is taken away because:
*
* 1) We handle one interrupt and return, sitting in a loop and moving across
* all the pending IRQ bits in the cause register is _NOT_ the answer, the
* common case is one pending IRQ so optimize in that direction.
*
* 2) We need not check against bits in the status register IRQ mask, that
* would make this routine slow as hell.
*
* 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
* between like BSD spl() brain-damage.
*
* Furthermore, the IRQs on the INDY look basically (barring software IRQs
* which we don't use at all) like:
*
* MIPS IRQ Source
* -------- ------
* 0 Software (ignored)
* 1 Software (ignored)
* 2 Local IRQ level zero
* 3 Local IRQ level one
* 4 8254 Timer zero
* 5 8254 Timer one
* 6 Bus Error
* 7 R4k timer (what we use)
*
* We handle the IRQ according to _our_ priority which is:
*
* Highest ---- R4k Timer
* Local IRQ zero
* Local IRQ one
* Bus Error
* 8254 Timer zero
* Lowest ---- 8254 Timer one
*
* then we just return, if multiple IRQs are pending then we will just take
* another exception, big deal.
*/
.text
.set noreorder
......
......@@ -3,10 +3,7 @@
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*
* $Id: irq.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/signal.h>
......@@ -14,6 +11,7 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/ptrace.h>
......@@ -27,7 +25,7 @@ extern void i8259_enable_irq(unsigned int irq_nr);
extern asmlinkage void ddbIRQ(void);
extern asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs);
extern asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
void no_action(int cpl, void *dev_id, struct pt_regs *regs)
......@@ -55,177 +53,174 @@ void no_action(int cpl, void *dev_id, struct pt_regs *regs)
static void m1543_irq_setup(void)
{
/*
* The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all
* the possible IO sources in the M1543 are in use by us. We will
* use the following mapping:
*
* IRQ1 - keyboard (default set by M1543)
* IRQ3 - reserved for UART B (default set by M1543) (note that
* the schematics for the DDB Vrc-5074 board seem to
* indicate that IRQ3 is connected to the DS1386
* watchdog timer interrupt output so we might have
* a conflict)
* IRQ4 - reserved for UART A (default set by M1543)
* IRQ5 - parallel (default set by M1543)
* IRQ8 - DS1386 time of day (RTC) interrupt
* IRQ12 - mouse
*/
/*
* Assing mouse interrupt to IRQ12
*/
/* Enter configuration mode */
outb(0x51, M1543_PNP_CONFIG);
outb(0x23, M1543_PNP_CONFIG);
/* Select logical device 7 (Keyboard) */
outb(0x07, M1543_PNP_INDEX);
outb(0x07, M1543_PNP_DATA);
/* Select IRQ12 */
outb(0x72, M1543_PNP_INDEX);
outb(0x0c, M1543_PNP_DATA);
/* Leave configration mode */
outb(0xbb, M1543_PNP_CONFIG);
/* Initialize the 8259 PIC in the M1543 */
i8259_init();
/* Enable the interrupt cascade */
nile4_enable_irq(NILE4_INT_INTE);
request_region(M1543_PNP_CONFIG, 2, "M1543 config");
request_region(M1543_INT1_MASTER_ELCR, 2, "pic ELCR");
/*
* The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all
* the possible IO sources in the M1543 are in use by us. We will
* use the following mapping:
*
* IRQ1 - keyboard (default set by M1543)
* IRQ3 - reserved for UART B (default set by M1543) (note that
* the schematics for the DDB Vrc-5074 board seem to
* indicate that IRQ3 is connected to the DS1386
* watchdog timer interrupt output so we might have
* a conflict)
* IRQ4 - reserved for UART A (default set by M1543)
* IRQ5 - parallel (default set by M1543)
* IRQ8 - DS1386 time of day (RTC) interrupt
* IRQ12 - mouse
*/
/*
* Assing mouse interrupt to IRQ12
*/
/* Enter configuration mode */
outb(0x51, M1543_PNP_CONFIG);
outb(0x23, M1543_PNP_CONFIG);
/* Select logical device 7 (Keyboard) */
outb(0x07, M1543_PNP_INDEX);
outb(0x07, M1543_PNP_DATA);
/* Select IRQ12 */
outb(0x72, M1543_PNP_INDEX);
outb(0x0c, M1543_PNP_DATA);
/* Leave configration mode */
outb(0xbb, M1543_PNP_CONFIG);
/* Initialize the 8259 PIC in the M1543 */
i8259_init();
/* Enable the interrupt cascade */
nile4_enable_irq(NILE4_INT_INTE);
request_region(M1543_PNP_CONFIG, 2, "M1543 config");
request_region(M1543_INT1_MASTER_ELCR, 2, "pic ELCR");
}
static void nile4_irq_setup(void)
{
int i;
int i;
/* Map all interrupts to CPU int #0 */
nile4_map_irq_all(0);
/* Map all interrupts to CPU int #0 */
nile4_map_irq_all(0);
/* PCI INTA#-E# must be level triggered */
nile4_set_pci_irq_level_or_edge(0, 1);
nile4_set_pci_irq_level_or_edge(1, 1);
nile4_set_pci_irq_level_or_edge(2, 1);
nile4_set_pci_irq_level_or_edge(3, 1);
nile4_set_pci_irq_level_or_edge(4, 1);
/* PCI INTA#-E# must be level triggered */
nile4_set_pci_irq_level_or_edge(0, 1);
nile4_set_pci_irq_level_or_edge(1, 1);
nile4_set_pci_irq_level_or_edge(2, 1);
nile4_set_pci_irq_level_or_edge(3, 1);
nile4_set_pci_irq_level_or_edge(4, 1);
/* PCI INTA#-D# must be active low, INTE# must be active high */
nile4_set_pci_irq_polarity(0, 0);
nile4_set_pci_irq_polarity(1, 0);
nile4_set_pci_irq_polarity(2, 0);
nile4_set_pci_irq_polarity(3, 0);
nile4_set_pci_irq_polarity(4, 1);
/* PCI INTA#-D# must be active low, INTE# must be active high */
nile4_set_pci_irq_polarity(0, 0);
nile4_set_pci_irq_polarity(1, 0);
nile4_set_pci_irq_polarity(2, 0);
nile4_set_pci_irq_polarity(3, 0);
nile4_set_pci_irq_polarity(4, 1);
for (i = 0; i < 16; i++)
nile4_clear_irq(i);
for (i = 0; i < 16; i++)
nile4_clear_irq(i);
/* Enable CPU int #0 */
nile4_enable_irq_output(0);
/* Enable CPU int #0 */
nile4_enable_irq_output(0);
request_mem_region(NILE4_BASE, NILE4_SIZE, "Nile 4");
request_mem_region(NILE4_BASE, NILE4_SIZE, "Nile 4");
}
/*
* IRQ2 is cascade interrupt to second interrupt controller
*/
static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL };
static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL };
void disable_irq(unsigned int irq_nr)
{
if (is_i8259_irq(irq_nr))
i8259_disable_irq(irq_nr);
else
nile4_disable_irq(irq_to_nile4(irq_nr));
if (is_i8259_irq(irq_nr))
i8259_disable_irq(irq_nr);
else
nile4_disable_irq(irq_to_nile4(irq_nr));
}
void enable_irq(unsigned int irq_nr)
{
if (is_i8259_irq(irq_nr))
i8259_enable_irq(irq_nr);
else
nile4_enable_irq(irq_to_nile4(irq_nr));
if (is_i8259_irq(irq_nr))
i8259_enable_irq(irq_nr);
else
nile4_enable_irq(irq_to_nile4(irq_nr));
}
int table[16] = { 0, };
void ddb_local0_irqdispatch(struct pt_regs *regs)
{
u32 mask;
int nile4_irq;
u32 mask;
int nile4_irq;
#if 1
volatile static int nesting = 0;
if (nesting++ == 0)
ddb5074_led_d3(1);
ddb5074_led_hex(nesting < 16 ? nesting : 15);
volatile static int nesting = 0;
if (nesting++ == 0)
ddb5074_led_d3(1);
ddb5074_led_hex(nesting < 16 ? nesting : 15);
#endif
mask = nile4_get_irq_stat(0);
nile4_clear_irq_mask(mask);
/* Handle the timer interrupt first */
if (mask & (1<<NILE4_INT_GPT)) {
nile4_disable_irq(NILE4_INT_GPT);
do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
nile4_enable_irq(NILE4_INT_GPT);
mask &= ~(1<<NILE4_INT_GPT);
}
for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
if (mask & 1) {
nile4_disable_irq(nile4_irq);
if (nile4_irq == NILE4_INT_INTE) {
int i8259_irq = nile4_i8259_iack();
i8259_do_irq(i8259_irq, regs);
} else
do_IRQ(nile4_to_irq(nile4_irq), regs);
nile4_enable_irq(nile4_irq);
}
mask = nile4_get_irq_stat(0);
nile4_clear_irq_mask(mask);
/* Handle the timer interrupt first */
if (mask & (1 << NILE4_INT_GPT)) {
nile4_disable_irq(NILE4_INT_GPT);
do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
nile4_enable_irq(NILE4_INT_GPT);
mask &= ~(1 << NILE4_INT_GPT);
}
for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
if (mask & 1) {
nile4_disable_irq(nile4_irq);
if (nile4_irq == NILE4_INT_INTE) {
int i8259_irq = nile4_i8259_iack();
i8259_do_irq(i8259_irq, regs);
} else
do_IRQ(nile4_to_irq(nile4_irq), regs);
nile4_enable_irq(nile4_irq);
}
#if 1
if (--nesting == 0)
ddb5074_led_d3(0);
ddb5074_led_hex(nesting < 16 ? nesting : 15);
if (--nesting == 0)
ddb5074_led_d3(0);
ddb5074_led_hex(nesting < 16 ? nesting : 15);
#endif
}
void ddb_local1_irqdispatch(void)
{
printk("ddb_local1_irqdispatch called\n");
printk("ddb_local1_irqdispatch called\n");
}
void ddb_buserror_irq(void)
{
printk("ddb_buserror_irq called\n");
printk("ddb_buserror_irq called\n");
}
void ddb_8254timer_irq(void)
{
printk("ddb_8254timer_irq called\n");
printk("ddb_8254timer_irq called\n");
}
void __init ddb_irq_setup(void)
{
#ifdef CONFIG_REMOTE_DEBUG
if (remote_debug)
set_debug_traps();
breakpoint(); /* you may move this line to whereever you want :-) */
if (remote_debug)
set_debug_traps();
breakpoint(); /* you may move this line to whereever you want :-) */
#endif
request_region(0x20, 0x20, "pic1");
request_region(0xa0, 0x20, "pic2");
i8259_setup_irq(2, &irq2);
request_region(0x20, 0x20, "pic1");
request_region(0xa0, 0x20, "pic2");
i8259_setup_irq(2, &irq2);
nile4_irq_setup();
m1543_irq_setup();
nile4_irq_setup();
m1543_irq_setup();
set_except_vector(0, ddbIRQ);
set_except_vector(0, ddbIRQ);
}
This diff is collapsed.
/*
* Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com>
*
*
* Dynamic DMA mapping support.
*
* swiped from i386, and cloned for MIPS by Geert.
*
*/
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <asm/io.h>
void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle)
{
void *ret;
int gfp = GFP_ATOMIC;
if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
gfp |= GFP_DMA;
ret = (void *)__get_free_pages(gfp, get_order(size));
if (ret != NULL) {
memset(ret, 0, size);
*dma_handle = virt_to_bus(ret);
}
return ret;
}
void pci_free_consistent(struct pci_dev *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
free_pages((unsigned long)vaddr, get_order(size));
}
This diff is collapsed.
......@@ -3,58 +3,32 @@
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*
* $Id: prom.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
*/
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
char arcs_cmdline[CL_SIZE];
extern char _end;
#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
char arcs_cmdline[COMMAND_LINE_SIZE];
void __init prom_init(const char *s)
{
int i = 0;
unsigned long mem_size, free_start, free_end, start_pfn, bootmap_size;
int i = 0;
// _serinit();
if (s != (void *) -1)
while (*s && i < sizeof(arcs_cmdline) - 1)
arcs_cmdline[i++] = *s++;
arcs_cmdline[i] = '\0';
if (s != (void *)-1)
while (*s && i < sizeof(arcs_cmdline)-1)
arcs_cmdline[i++] = *s++;
arcs_cmdline[i] = '\0';
mips_machgroup = MACH_GROUP_NEC_DDB;
mips_machtype = MACH_NEC_DDB5074;
mips_machgroup = MACH_GROUP_NEC_DDB;
mips_machtype = MACH_NEC_DDB5074;
/* 64 MB non-upgradable */
mem_size = 64 << 20;
free_start = PHYSADDR(PFN_ALIGN(&_end));
free_end = mem_size;
start_pfn = PFN_UP((unsigned long)&_end);
/* Register all the contiguous memory with the bootmem allocator
and free it. Be careful about the bootmem freemap. */
bootmap_size = init_bootmem(start_pfn, mem_size >> PAGE_SHIFT);
/* Free the entire available memory after the _end symbol. */
free_start += bootmap_size;
free_bootmem(free_start, free_end-free_start);
}
void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
{
/* 64 MB non-upgradable */
add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
}
void __init prom_free_prom_memory(void)
......
......@@ -3,10 +3,7 @@
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*
* $Id: setup.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/kbd_ll.h>
......@@ -42,85 +39,83 @@ extern void console_setup(char *);
extern struct ide_ops std_ide_ops;
extern struct rtc_ops ddb_rtc_ops;
static void (*back_to_prom)(void) = (void (*)(void))0xbfc00000;
static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
static void ddb_machine_restart(char *command)
{
u32 t;
/* PCI cold reset */
t = nile4_in32(NILE4_PCICTRL+4);
t |= 0x40000000;
nile4_out32(NILE4_PCICTRL+4, t);
/* CPU cold reset */
t = nile4_in32(NILE4_CPUSTAT);
t |= 1;
nile4_out32(NILE4_CPUSTAT, t);
/* Call the PROM */
back_to_prom();
u32 t;
/* PCI cold reset */
t = nile4_in32(NILE4_PCICTRL + 4);
t |= 0x40000000;
nile4_out32(NILE4_PCICTRL + 4, t);
/* CPU cold reset */
t = nile4_in32(NILE4_CPUSTAT);
t |= 1;
nile4_out32(NILE4_CPUSTAT, t);
/* Call the PROM */
back_to_prom();
}
static void ddb_machine_halt(void)
{
printk("DDB Vrc-5074 halted.\n");
do {} while (1);
printk("DDB Vrc-5074 halted.\n");
do {
} while (1);
}
static void ddb_machine_power_off(void)
{
printk("DDB Vrc-5074 halted. Please turn off the power.\n");
do {} while (1);
printk("DDB Vrc-5074 halted. Please turn off the power.\n");
do {
} while (1);
}
extern void ddb_irq_setup(void);
void (*board_time_init)(struct irqaction *irq);
void (*board_time_init) (struct irqaction * irq);
static void __init ddb_time_init(struct irqaction *irq)
{
/* set the clock to 1 Hz */
nile4_out32(NILE4_T2CTRL, 1000000);
/* enable the General-Purpose Timer */
nile4_out32(NILE4_T2CTRL+4, 0x00000001);
/* reset timer */
nile4_out32(NILE4_T2CNTR, 0);
/* enable interrupt */
nile4_enable_irq(NILE4_INT_GPT);
i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
set_cp0_status(ST0_IM, IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
/* set the clock to 1 Hz */
nile4_out32(NILE4_T2CTRL, 1000000);
/* enable the General-Purpose Timer */
nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
/* reset timer */
nile4_out32(NILE4_T2CNTR, 0);
/* enable interrupt */
nile4_enable_irq(NILE4_INT_GPT);
i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
change_cp0_status(ST0_IM,
IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
}
void __init ddb_setup(void)
{
extern int panic_timeout;
irq_setup = ddb_irq_setup;
mips_io_port_base = NILE4_PCI_IO_BASE;
isa_slot_offset = NILE4_PCI_MEM_BASE;
request_region(0x00, 0x20, "dma1");
request_region(0x40, 0x20, "timer");
request_region(0x70, 0x10, "rtc");
request_region(0x80, 0x10, "dma page reg");
request_region(0xc0, 0x20, "dma2");
board_time_init = ddb_time_init;
_machine_restart = ddb_machine_restart;
_machine_halt = ddb_machine_halt;
_machine_power_off = ddb_machine_power_off;
extern int panic_timeout;
irq_setup = ddb_irq_setup;
mips_io_port_base = NILE4_PCI_IO_BASE;
isa_slot_offset = NILE4_PCI_MEM_BASE;
request_region(0x00, 0x20, "dma1");
request_region(0x40, 0x20, "timer");
request_region(0x70, 0x10, "rtc");
request_region(0x80, 0x10, "dma page reg");
request_region(0xc0, 0x20, "dma2");
board_time_init = ddb_time_init;
_machine_restart = ddb_machine_restart;
_machine_halt = ddb_machine_halt;
_machine_power_off = ddb_machine_power_off;
#ifdef CONFIG_BLK_DEV_IDE
ide_ops = &std_ide_ops;
ide_ops = &std_ide_ops;
#endif
rtc_ops = &ddb_rtc_ops;
rtc_ops = &ddb_rtc_ops;
/* Reboot on panic */
panic_timeout = 180;
}
int __init page_is_ram(unsigned long pagenr)
{
return 1;
/* Reboot on panic */
panic_timeout = 180;
}
......@@ -133,12 +128,12 @@ int __init page_is_ram(unsigned long pagenr)
#define NS16550_BASE (NILE4_PCI_IO_BASE+0x03f8)
static inline u8 ns16550_in(u32 reg)
{
return *(volatile u8 *)(NS16550_BASE+reg);
return *(volatile u8 *) (NS16550_BASE + reg);
}
static inline void ns16550_out(u32 reg, u8 val)
{
*(volatile u8 *)(NS16550_BASE+reg) = val;
*(volatile u8 *) (NS16550_BASE + reg) = val;
}
#endif
......@@ -168,87 +163,84 @@ static inline void ns16550_out(u32 reg, u8 val)
void _serinit(void)
{
#if USE_NILE4_SERIAL
ns16550_out(NS16550_LCR, 0x80);
ns16550_out(NS16550_DLM, 0x00);
ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */
ns16550_out(NS16550_LCR, 0x00);
ns16550_out(NS16550_LCR, 0x03);
ns16550_out(NS16550_FCR, 0x47);
ns16550_out(NS16550_LCR, 0x80);
ns16550_out(NS16550_DLM, 0x00);
ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */
ns16550_out(NS16550_LCR, 0x00);
ns16550_out(NS16550_LCR, 0x03);
ns16550_out(NS16550_FCR, 0x47);
#else
/* done by PMON */
/* done by PMON */
#endif
}
void _putc(char c)
{
while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
ns16550_out(NS16550_THR, c);
if (c == '\n') {
while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
ns16550_out(NS16550_THR, '\r');
}
ns16550_out(NS16550_THR, c);
if (c == '\n') {
while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
ns16550_out(NS16550_THR, '\r');
}
}
void _puts(const char *s)
{
char c;
while ((c = *s++))
_putc(c);
char c;
while ((c = *s++))
_putc(c);
}
char _getc(void)
{
while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
return ns16550_in(NS16550_RBR);
while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
return ns16550_in(NS16550_RBR);
}
int _testc(void)
{
return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
}
/*
* Hexadecimal 7-segment LED
*/
/*
* Hexadecimal 7-segment LED
*/
void ddb5074_led_hex(int hex)
{
outb(hex, 0x80);
outb(hex, 0x80);
}
/*
* LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
*/
/*
* LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
*/
struct pci_dev *pci_pmu = NULL;
void ddb5074_led_d2(int on)
{
u8 t;
if (pci_pmu) {
pci_read_config_byte(pci_pmu, 0x7e, &t);
if (on)
t &= 0x7f;
else
t |= 0x80;
pci_write_config_byte(pci_pmu, 0x7e, t);
}
u8 t;
if (pci_pmu) {
pci_read_config_byte(pci_pmu, 0x7e, &t);
if (on)
t &= 0x7f;
else
t |= 0x80;
pci_write_config_byte(pci_pmu, 0x7e, t);
}
}
void ddb5074_led_d3(int on)
{
u8 t;
if (pci_pmu) {
pci_read_config_byte(pci_pmu, 0x7e, &t);
if (on)
t &= 0xbf;
else
t |= 0x40;
pci_write_config_byte(pci_pmu, 0x7e, t);
}
}
u8 t;
if (pci_pmu) {
pci_read_config_byte(pci_pmu, 0x7e, &t);
if (on)
t &= 0xbf;
else
t |= 0x40;
pci_write_config_byte(pci_pmu, 0x7e, t);
}
}
......@@ -3,33 +3,30 @@
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*
* $Id*
*/
#include <linux/init.h>
#include <asm/mc146818rtc.h>
static unsigned char ddb_rtc_read_data(unsigned long addr)
{
outb_p(addr, RTC_PORT(0));
return inb_p(RTC_PORT(1));
outb_p(addr, RTC_PORT(0));
return inb_p(RTC_PORT(1));
}
static void ddb_rtc_write_data(unsigned char data, unsigned long addr)
{
outb_p(addr, RTC_PORT(0));
outb_p(data, RTC_PORT(1));
outb_p(addr, RTC_PORT(0));
outb_p(data, RTC_PORT(1));
}
static int ddb_rtc_bcd_mode(void)
{
return 1;
return 1;
}
struct rtc_ops ddb_rtc_ops = {
ddb_rtc_read_data,
ddb_rtc_write_data,
ddb_rtc_bcd_mode
ddb_rtc_read_data,
ddb_rtc_write_data,
ddb_rtc_bcd_mode
};
#
# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines
# under Linux.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
#
.S.s:
$(CPP) $(CFLAGS) $< -o $*.s
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
O_TARGET = ddb5476.a
obj-y += setup.o irq.o time.o prom.o pci.o \
int-handler.o nile4.o
obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
include $(TOPDIR)/Rules.make
#include <linux/config.h>
#if (defined(CONFIG_DDB5476) && defined(CONFIG_REMOTE_DEBUG))
/* --- CONFIG --- */
/* we need uint32 uint8 */
/* #include "types.h" */
typedef unsigned char uint8;
typedef unsigned int uint32;
/* --- END OF CONFIG --- */
#define UART16550_BAUD_2400 2400
#define UART16550_BAUD_4800 4800
#define UART16550_BAUD_9600 9600
#define UART16550_BAUD_19200 19200
#define UART16550_BAUD_38400 38400
#define UART16550_BAUD_57600 57600
#define UART16550_BAUD_115200 115200
#define UART16550_PARITY_NONE 0
#define UART16550_PARITY_ODD 0x08
#define UART16550_PARITY_EVEN 0x18
#define UART16550_PARITY_MARK 0x28
#define UART16550_PARITY_SPACE 0x38
#define UART16550_DATA_5BIT 0x0
#define UART16550_DATA_6BIT 0x1
#define UART16550_DATA_7BIT 0x2
#define UART16550_DATA_8BIT 0x3
#define UART16550_STOP_1BIT 0x0
#define UART16550_STOP_2BIT 0x4
/* ----------------------------------------------------- */
/* === CONFIG === */
/* [jsun] we use the second serial port for kdb */
#define BASE 0xa60002f8
#define MAX_BAUD 115200
/* === END OF CONFIG === */
/* register offset */
#define OFS_RCV_BUFFER 0
#define OFS_TRANS_HOLD 0
#define OFS_SEND_BUFFER 0
#define OFS_INTR_ENABLE 1
#define OFS_INTR_ID 2
#define OFS_DATA_FORMAT 3
#define OFS_LINE_CONTROL 3
#define OFS_MODEM_CONTROL 4
#define OFS_RS232_OUTPUT 4
#define OFS_LINE_STATUS 5
#define OFS_MODEM_STATUS 6
#define OFS_RS232_INPUT 6
#define OFS_SCRATCH_PAD 7
#define OFS_DIVISOR_LSB 0
#define OFS_DIVISOR_MSB 1
/* memory-mapped read/write of the port */
#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
{
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
/* set up buad rate */
{
uint32 divisor;
/* set DIAB bit */
UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
/* set divisor */
divisor = MAX_BAUD / baud;
UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
/* clear DIAB bit */
UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
}
/* set data format */
UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
}
static int remoteDebugInitialized = 0;
uint8 getDebugChar(void)
{
if (!remoteDebugInitialized) {
remoteDebugInitialized = 1;
debugInit(UART16550_BAUD_38400,
UART16550_DATA_8BIT,
UART16550_PARITY_NONE, UART16550_STOP_1BIT);
}
while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
return UART16550_READ(OFS_RCV_BUFFER);
}
int putDebugChar(uint8 byte)
{
if (!remoteDebugInitialized) {
remoteDebugInitialized = 1;
debugInit(UART16550_BAUD_9600,
UART16550_DATA_8BIT,
UART16550_PARITY_NONE, UART16550_STOP_1BIT);
}
while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
UART16550_WRITE(OFS_SEND_BUFFER, byte);
return 1;
}
#endif
/*
* arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
*
* Based on arch/mips/sgi/kernel/indyIRQ.S
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
/*
* A lot of complication here is taken away because:
*
* 1) We handle one interrupt and return, sitting in a loop and moving across
* all the pending IRQ bits in the cause register is _NOT_ the answer, the
* common case is one pending IRQ so optimize in that direction.
*
* 2) We need not check against bits in the status register IRQ mask, that
* would make this routine slow as hell.
*
* 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
* between like BSD spl() brain-damage.
*
* Furthermore, the IRQs on the INDY look basically (barring software IRQs
* which we don't use at all) like:
*
* MIPS IRQ Source
* -------- ------
* 0 Software (ignored)
* 1 Software (ignored)
* 2 Local IRQ level zero
* 3 Local IRQ level one
* 4 8254 Timer zero
* 5 8254 Timer one
* 6 Bus Error
* 7 R4k timer (what we use)
*
* We handle the IRQ according to _our_ priority which is:
*
* Highest ---- R4k Timer
* Local IRQ zero
* Local IRQ one
* Bus Error
* 8254 Timer zero
* Lowest ---- 8254 Timer one
*
* then we just return, if multiple IRQs are pending then we will just take
* another exception, big deal.
*/
.text
.set noreorder
.set noat
.align 5
NESTED(ddbIRQ, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
mfc0 s1, CP0_CAUSE # get irq mask
#if 1
mfc0 t2,CP0_STATUS # get enabled interrupts
and s0, s1, t2 # isolate allowed ones
#endif
/* First we check for r4k counter/timer IRQ. */
andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
beq a0, zero, 1f
andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
/* Wheee, local level zero interrupt. */
jal ddb_local0_irqdispatch
move a0, sp # delay slot
j ret_from_irq
nop # delay slot
1:
beq a0, zero, 1f
andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
/* Wheee, local level one interrupt. */
move a0, sp
jal ddb_local1_irqdispatch
nop
j ret_from_irq
nop
1:
beq a0, zero, 1f
nop
/* Wheee, an asynchronous bus error... */
move a0, sp
jal ddb_buserror_irq
nop
j ret_from_irq
nop
1:
/* Here by mistake? This is possible, what can happen
* is that by the time we take the exception the IRQ
* pin goes low, so just leave if this is the case.
*/
andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
beq a0, zero, 1f
/* Must be one of the 8254 timers... */
move a0, sp
jal ddb_8254timer_irq
nop
1:
/* phamtom interrupt */
move a0, s1
jal ddb_phantom_irq
nop
j ret_from_irq
nop
END(ddbIRQ)
/*
* arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/ptrace.h>
#include <asm/nile4.h>
extern void __init i8259_init(void);
extern void i8259_disable_irq(unsigned int irq_nr);
extern void i8259_enable_irq(unsigned int irq_nr);
extern asmlinkage void ddbIRQ(void);
extern asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs);
extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
void no_action(int cpl, void *dev_id, struct pt_regs *regs)
{
}
#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */
#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */
#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */
#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */
#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */
#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */
#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */
#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */
#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */
#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */
#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */
#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */
static struct {
struct resource m1543_config;
struct resource pic_elcr;
} m1543_ioport = {
{ "M1543 config", M1543_PNP_CONFIG, M1543_PNP_CONFIG + 1,
IORESOURCE_BUSY},
{ "pic ELCR", M1543_INT1_MASTER_ELCR, M1543_INT1_MASTER_ELCR + 1,
IORESOURCE_BUSY}
};
static void m1543_irq_setup(void)
{
/*
* The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all
* the possible IO sources in the M1543 are in use by us. We will
* use the following mapping:
*
* IRQ1 - keyboard (default set by M1543)
* IRQ3 - reserved for UART B (default set by M1543) (note that
* the schematics for the DDB Vrc-5476 board seem to
* indicate that IRQ3 is connected to the DS1386
* watchdog timer interrupt output so we might have
* a conflict)
* IRQ4 - reserved for UART A (default set by M1543)
* IRQ5 - parallel (default set by M1543)
* IRQ8 - DS1386 time of day (RTC) interrupt
* IRQ9 - USB (hardwired in ddb_setup)
* IRQ10 - PMU (hardwired in ddb_setup)
* IRQ12 - mouse
* IRQ14,15 - IDE controller (need to be confirmed, jsun)
*/
/*
* Assing mouse interrupt to IRQ12
*/
/* Enter configuration mode */
outb(0x51, M1543_PNP_CONFIG);
outb(0x23, M1543_PNP_CONFIG);
/* Select logical device 7 (Keyboard) */
outb(0x07, M1543_PNP_INDEX);
outb(0x07, M1543_PNP_DATA);
/* Select IRQ12 */
outb(0x72, M1543_PNP_INDEX);
outb(0x0c, M1543_PNP_DATA);
/* Leave configration mode */
outb(0xbb, M1543_PNP_CONFIG);
/* Initialize the 8259 PIC in the M1543 */
i8259_init();
/* Enable the interrupt cascade from M1543 */
nile4_enable_irq(NILE4_INT_INTC);
/* request io ports */
if (request_resource(&ioport_resource, &m1543_ioport.m1543_config)
|| request_resource(&ioport_resource, &m1543_ioport.pic_elcr)) {
printk("m1543_irq_setup : requesting io ports failed.\n");
for (;;);
}
}
static void nile4_irq_setup(void)
{
int i;
/* Map all interrupts to CPU int #0 */
nile4_map_irq_all(0);
/* PCI INTA#-E# must be level triggered */
nile4_set_pci_irq_level_or_edge(0, 1);
nile4_set_pci_irq_level_or_edge(1, 1);
nile4_set_pci_irq_level_or_edge(2, 1);
nile4_set_pci_irq_level_or_edge(3, 1);
/* PCI INTA#, B#, D# must be active low, INTC# must be active high */
nile4_set_pci_irq_polarity(0, 0);
nile4_set_pci_irq_polarity(1, 0);
nile4_set_pci_irq_polarity(2, 1);
nile4_set_pci_irq_polarity(3, 0);
for (i = 0; i < 16; i++)
nile4_clear_irq(i);
/* Enable CPU int #0 */
nile4_enable_irq_output(0);
/* memory resource acquire in ddb_setup */
}
/*
* IRQ2 is cascade interrupt to second interrupt controller
*/
static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL };
void disable_irq(unsigned int irq_nr)
{
if (is_i8259_irq(irq_nr))
i8259_disable_irq(irq_nr);
else
nile4_disable_irq(irq_to_nile4(irq_nr));
}
void enable_irq(unsigned int irq_nr)
{
if (is_i8259_irq(irq_nr))
i8259_enable_irq(irq_nr);
else
nile4_enable_irq(irq_to_nile4(irq_nr));
}
int table[16] = { 0, };
void ddb_local0_irqdispatch(struct pt_regs *regs)
{
u32 mask;
int nile4_irq;
#if 0
volatile static int nesting = 0;
if (nesting++ == 0)
ddb5476_led_d3(1);
ddb5476_led_hex(nesting < 16 ? nesting : 15);
#endif
mask = nile4_get_irq_stat(0);
nile4_clear_irq_mask(mask);
/* Handle the timer interrupt first */
if (mask & (1 << NILE4_INT_GPT)) {
nile4_disable_irq(NILE4_INT_GPT);
do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
nile4_enable_irq(NILE4_INT_GPT);
mask &= ~(1 << NILE4_INT_GPT);
}
for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
if (mask & 1) {
nile4_disable_irq(nile4_irq);
if (nile4_irq == NILE4_INT_INTC) {
int i8259_irq = nile4_i8259_iack();
i8259_do_irq(i8259_irq, regs);
} else {
do_IRQ(nile4_to_irq(nile4_irq), regs);
}
nile4_enable_irq(nile4_irq);
}
#if 0
if (--nesting == 0)
ddb5476_led_d3(0);
ddb5476_led_hex(nesting < 16 ? nesting : 15);
#endif
}
void ddb_local1_irqdispatch(void)
{
printk("ddb_local1_irqdispatch called\n");
}
void ddb_buserror_irq(void)
{
printk("ddb_buserror_irq called\n");
}
void ddb_8254timer_irq(void)
{
printk("ddb_8254timer_irq called\n");
}
void ddb_phantom_irq(unsigned long cause)
{
printk("phantom interrupts detected : \n");
printk("\tcause \t\t0x%08x\n", cause);
printk("\tcause reg\t0x%08x\n",
read_32bit_cp0_register(CP0_CAUSE));
printk("\tstatus reg\t0x%08x\n",
read_32bit_cp0_register(CP0_STATUS));
}
void __init ddb_irq_setup(void)
{
#ifdef CONFIG_REMOTE_DEBUG
printk("Wait for gdb client connection ...\n");
set_debug_traps();
breakpoint(); /* you may move this line to whereever you want :-) */
#endif
i8259_setup_irq(2, &irq2);
nile4_irq_setup();
m1543_irq_setup();
/* we pin #0 - #4 (no internal timer) */
change_cp0_status(ST0_IM,
IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
set_except_vector(0, ddbIRQ);
}
/*
* arch/mips/ddb5074/nile4.c -- NEC Vrc-5074 Nile 4 support routines
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/nile4.h>
/*
* Physical Device Address Registers
*
* Note: 32 bit addressing only!
*/
void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
int on_memory_bus, int visible)
{
u32 maskbits;
u32 widthbits;
if (pdar > NILE4_BOOTCS || (pdar & 7)) {
printk("nile4_set_pdar: invalid pdar %d\n", pdar);
return;
}
if (pdar == NILE4_INTCS && size != 0x00200000) {
printk("nile4_set_pdar: INTCS size must be 2 MB\n");
return;
}
switch (size) {
#if 0 /* We don't support 4 GB yet */
case 0x100000000: /* 4 GB */
maskbits = 4;
break;
#endif
case 0x80000000: /* 2 GB */
maskbits = 5;
break;
case 0x40000000: /* 1 GB */
maskbits = 6;
break;
case 0x20000000: /* 512 MB */
maskbits = 7;
break;
case 0x10000000: /* 256 MB */
maskbits = 8;
break;
case 0x08000000: /* 128 MB */
maskbits = 9;
break;
case 0x04000000: /* 64 MB */
maskbits = 10;
break;
case 0x02000000: /* 32 MB */
maskbits = 11;
break;
case 0x01000000: /* 16 MB */
maskbits = 12;
break;
case 0x00800000: /* 8 MB */
maskbits = 13;
break;
case 0x00400000: /* 4 MB */
maskbits = 14;
break;
case 0x00200000: /* 2 MB */
maskbits = 15;
break;
case 0: /* OFF */
maskbits = 0;
break;
default:
printk("nile4_set_pdar: unsupported size %p\n",
(void *) size);
return;
}
switch (width) {
case 8:
widthbits = 0;
break;
case 16:
widthbits = 1;
break;
case 32:
widthbits = 2;
break;
case 64:
widthbits = 3;
break;
default:
printk("nile4_set_pdar: unsupported width %d\n", width);
return;
}
nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) |
(visible ? 0x20 : 0) | (widthbits << 6) |
(phys & 0xffe00000));
nile4_out32(pdar + 4, 0);
/*
* When programming a PDAR, the register should be read immediately
* after writing it. This ensures that address decoders are properly
* configured.
*/
nile4_in32(pdar);
nile4_in32(pdar + 4);
}
/*
* PCI Master Registers
*
* Note: 32 bit addressing only!
*/
void nile4_set_pmr(u32 pmr, u32 type, u32 addr)
{
if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) {
printk("nile4_set_pmr: invalid pmr %d\n", pmr);
return;
}
switch (type) {
case NILE4_PCICMD_IACK: /* PCI Interrupt Acknowledge */
case NILE4_PCICMD_IO: /* PCI I/O Space */
case NILE4_PCICMD_MEM: /* PCI Memory Space */
case NILE4_PCICMD_CFG: /* PCI Configuration Space */
break;
default:
printk("nile4_set_pmr: invalid type %d\n", type);
return;
}
nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000));
nile4_out32(pmr + 4, 0);
}
/*
* Interrupt Programming
*/
void nile4_map_irq(int nile4_irq, int cpu_irq)
{
u32 offset, t;
offset = NILE4_INTCTRL;
if (nile4_irq >= 8) {
offset += 4;
nile4_irq -= 8;
}
t = nile4_in32(offset);
t &= ~(7 << (nile4_irq * 4));
t |= cpu_irq << (nile4_irq * 4);
nile4_out32(offset, t);
}
void nile4_map_irq_all(int cpu_irq)
{
u32 all, t;
all = cpu_irq;
all |= all << 4;
all |= all << 8;
all |= all << 16;
t = nile4_in32(NILE4_INTCTRL);
t &= 0x88888888;
t |= all;
nile4_out32(NILE4_INTCTRL, t);
t = nile4_in32(NILE4_INTCTRL + 4);
t &= 0x88888888;
t |= all;
nile4_out32(NILE4_INTCTRL + 4, t);
}
void nile4_enable_irq(int nile4_irq)
{
u32 offset, t;
offset = NILE4_INTCTRL;
if (nile4_irq >= 8) {
offset += 4;
nile4_irq -= 8;
}
t = nile4_in32(offset);
t |= 8 << (nile4_irq * 4);
nile4_out32(offset, t);
}
void nile4_disable_irq(int nile4_irq)
{
u32 offset, t;
offset = NILE4_INTCTRL;
if (nile4_irq >= 8) {
offset += 4;
nile4_irq -= 8;
}
t = nile4_in32(offset);
t &= ~(8 << (nile4_irq * 4));
nile4_out32(offset, t);
}
void nile4_disable_irq_all(void)
{
nile4_out32(NILE4_INTCTRL, 0);
nile4_out32(NILE4_INTCTRL + 4, 0);
}
u16 nile4_get_irq_stat(int cpu_irq)
{
return nile4_in16(NILE4_INTSTAT0 + cpu_irq * 2);
}
void nile4_enable_irq_output(int cpu_irq)
{
u32 t;
t = nile4_in32(NILE4_INTSTAT1 + 4);
t |= 1 << (16 + cpu_irq);
nile4_out32(NILE4_INTSTAT1, t);
}
void nile4_disable_irq_output(int cpu_irq)
{
u32 t;
t = nile4_in32(NILE4_INTSTAT1 + 4);
t &= ~(1 << (16 + cpu_irq));
nile4_out32(NILE4_INTSTAT1, t);
}
void nile4_set_pci_irq_polarity(int pci_irq, int high)
{
u32 t;
t = nile4_in32(NILE4_INTPPES);
if (high)
t &= ~(1 << (pci_irq * 2));
else
t |= 1 << (pci_irq * 2);
nile4_out32(NILE4_INTPPES, t);
}
void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
{
u32 t;
t = nile4_in32(NILE4_INTPPES);
if (level)
t |= 2 << (pci_irq * 2);
else
t &= ~(2 << (pci_irq * 2));
nile4_out32(NILE4_INTPPES, t);
}
void nile4_clear_irq(int nile4_irq)
{
nile4_out32(NILE4_INTCLR, 1 << nile4_irq);
}
void nile4_clear_irq_mask(u32 mask)
{
nile4_out32(NILE4_INTCLR, mask);
}
u8 nile4_i8259_iack(void)
{
u8 irq;
/* Set window 0 for interrupt acknowledge */
nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0);
irq = *(volatile u8 *) NILE4_PCI_IACK_BASE;
/* Set window 0 for PCI I/O space */
nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
return irq;
}
#if 0
void nile4_dump_irq_status(void)
{
printk("CPUSTAT = %p:%p\n", (void *) nile4_in32(NILE4_CPUSTAT + 4),
(void *) nile4_in32(NILE4_CPUSTAT));
printk("INTCTRL = %p:%p\n", (void *) nile4_in32(NILE4_INTCTRL + 4),
(void *) nile4_in32(NILE4_INTCTRL));
printk("INTSTAT0 = %p:%p\n",
(void *) nile4_in32(NILE4_INTSTAT0 + 4),
(void *) nile4_in32(NILE4_INTSTAT0));
printk("INTSTAT1 = %p:%p\n",
(void *) nile4_in32(NILE4_INTSTAT1 + 4),
(void *) nile4_in32(NILE4_INTSTAT1));
printk("INTCLR = %p:%p\n", (void *) nile4_in32(NILE4_INTCLR + 4),
(void *) nile4_in32(NILE4_INTCLR));
printk("INTPPES = %p:%p\n", (void *) nile4_in32(NILE4_INTPPES + 4),
(void *) nile4_in32(NILE4_INTPPES));
}
#endif
This diff is collapsed.
/*
* arch/mips/ddb5476/prom.c -- NEC DDB Vrc-5476 PROM routines
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*
* Jun Sun - modified for DDB5476.
*/
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
char arcs_cmdline[COMMAND_LINE_SIZE];
/* [jsun@junsun.net] PMON passes arguments in C main() style */
void __init prom_init(int argc, const char **arg)
{
int i;
/* arg[0] is "g", the rest is boot parameters */
arcs_cmdline[0] = '\0';
for (i = 1; i < argc; i++) {
if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
>= sizeof(arcs_cmdline))
break;
strcat(arcs_cmdline, arg[i]);
strcat(arcs_cmdline, " ");
}
mips_machgroup = MACH_GROUP_NEC_DDB;
mips_machtype = MACH_NEC_DDB5476;
/* 64 MB non-upgradable */
add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
}
void __init prom_free_prom_memory(void)
{
}
This diff is collapsed.
/*
* arch/mips/ddb5074/time.c -- Timer routines
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*/
#include <linux/init.h>
#include <asm/mc146818rtc.h>
static unsigned char ddb_rtc_read_data(unsigned long addr)
{
outb_p(addr, RTC_PORT(0));
return inb_p(RTC_PORT(1));
}
static void ddb_rtc_write_data(unsigned char data, unsigned long addr)
{
outb_p(addr, RTC_PORT(0));
outb_p(data, RTC_PORT(1));
}
static int ddb_rtc_bcd_mode(void)
{
return 1;
}
struct rtc_ops ddb_rtc_ops = {
ddb_rtc_read_data,
ddb_rtc_write_data,
ddb_rtc_bcd_mode
};
This diff is collapsed.
......@@ -18,7 +18,8 @@ netboot: all
all: dec_boot.o
O_TARGET := dec_boot.o
O_OBJS := decstation.o
obj-y := decstation.o
clean:
rm -f nbImage
......
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.
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