fi
endmenu
+mainmenu_option next_comment
+comment 'General options'
+
# Visual Workstation support is utterly broken.
# If you want to see it working mail an VW540 to hch@infradead.org 8)
#bool 'SGI Visual Workstation support' CONFIG_VISWS
boot_cpu_logical_apicid = logical_smp_processor_id();
map_cpu_to_boot_apicid(0, boot_cpu_apicid);
- global_irq_holder = 0;
+ global_irq_holder = NO_PROC_ID;
current->cpu = 0;
smp_tune_scheduling();
tsk_ptrace = 24
PT_TRACESYS = 0x00000002
-PF_USEDFPU = 0x00100000
ENOSYS = 38
EINVAL = 22
.align 2
restore_all:
-#if defined(__SH4__)
- mov.l __fpu_prepare_fd, r0
- jsr @r0
- stc sr, r4
-#endif
- !
mov.l @r15+, r0
mov.l @r15+, r1
mov.l @r15+, r2
stc sr, r8
mov.l __blrb_flags, r9 ! BL =1, RB=1
or r9, r8
- ldc r8, sr ! here, change the register bank
+ ldc r8, sr ! here, change the register bank
!
mov.l @r15+, r8
mov.l @r15+, r9
mov.l @r15+, r12
mov.l @r15+, r13
mov.l @r15+, r14
- mov.l @r15+, k4 ! original stack pointer
+ mov.l @r15+, k4 ! original stack pointer
ldc.l @r15+, spc
lds.l @r15+, pr
- mov.l @r15+, k3 ! original SR
+ mov.l @r15+, k3 ! original SR
ldc.l @r15+, gbr
lds.l @r15+, mach
lds.l @r15+, macl
- add #4, r15 ! Skip syscall number
+ add #4, r15 ! Skip syscall number
!
! Calculate new SR value
- mov k3, k2 ! original SR value
+ mov k3, k2 ! original SR value
mov.l 1f, k1
stc sr, k0
- and k1, k0 ! Get current FD-bit
+ and k1, k0 ! Get current FD-bit
mov.l 2f, k1
- and k1, k2 ! Mask orignal SR value
- or k0, k2 ! Inherit current FD-bit
+ and k1, k2 ! Mask orignal SR value
+ or k0, k2 ! Inherit current FD-bit
!
- mov k3, k0 ! Calculate IMASK-bits
+ mov k3, k0 ! Calculate IMASK-bits
shlr2 k0
and #0x3c, k0
cmp/eq #0x3c, k0
shll2 k0
mov g_imask, k0
!
-7: or k0, k2 ! Set the IMASK-bits
+7: or k0, k2 ! Set the IMASK-bits
ldc k2, ssr
!
-#if defined(__SH4__)
- shll k2
- shll k2
- bf 9f ! user mode
- /* Kernel to kernel transition */
- mov.l 1f, k1
- tst k1, k3
- bf 9f ! it hadn't FPU
- ! Kernel to kernel and FPU was used
- ! There's the case we don't get FPU now
- stc sr, k2
- tst k1, k2
- bt 8f
- ! We need to grab FPU here
- xor k1, k2
- ldc k2, sr ! Grab FPU
- mov.l __init_task_flags, k1
- mov.l @k1, k2
- mov.l __PF_USEDFPU, k0
- or k0, k2
- mov.l k2, @k1 ! Set init_task.flags |= PF_USEDFPU
- !
- ! Restoring FPU...
- !
-8: mov.l 3f, k1
- lds k1, fpscr
- fmov.s @r15+, fr0
- fmov.s @r15+, fr1
- fmov.s @r15+, fr2
- fmov.s @r15+, fr3
- fmov.s @r15+, fr4
- fmov.s @r15+, fr5
- fmov.s @r15+, fr6
- fmov.s @r15+, fr7
- fmov.s @r15+, fr8
- fmov.s @r15+, fr9
- fmov.s @r15+, fr10
- fmov.s @r15+, fr11
- fmov.s @r15+, fr12
- fmov.s @r15+, fr13
- fmov.s @r15+, fr14
- fmov.s @r15+, fr15
- lds.l @r15+, fpscr
- lds.l @r15+, fpul
-9:
-#endif
mov k4, r15
rte
nop
.align 2
__blrb_flags: .long 0x30000000
-#if defined(__SH4__)
-__fpu_prepare_fd:
- .long SYMBOL_NAME(fpu_prepare_fd)
-__init_task_flags:
- .long SYMBOL_NAME(init_task_union)+4
-__PF_USEDFPU:
- .long PF_USEDFPU
-#endif
1: .long 0x00008000 ! FD
2: .long 0xffff7f0f ! ~(IMASK+FD)
3: .long 0x00080000 ! SZ=0, PR=1
! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
! save all registers onto stack.
!
- stc ssr, k0 ! from kernel space?
- shll k0 ! Check MD bit (bit30) by shifting it into the T bit
- shll k0
-#if defined(__SH4__)
- bf/s 8f ! it's from user to kernel transition
- mov r15, k0 ! save original stack to k0
- /* It's a kernel to kernel transition. */
- /* Is the FPU disabled? */
- mov.l 2f, k1
- stc ssr, k0
- tst k1, k0
- mov.l 4f, k1
- bf/s 9f ! FPU is not enabled, no need to save it
- mov r15, k0 ! save original stack to k0
- ! FPU is enabled, save it
- ! /* XXX: Need to save another bank of FPU if all FPU feature is used */
- ! /* Currently it's not the case for GCC (only udivsi3_i4, divsi3_i4) */
- sts.l fpul, @-r15
- sts.l fpscr, @-r15
- mov.l 6f, k1
- lds k1, fpscr
- mov.l 3f, k1
- fmov.s fr15, @-r15
- fmov.s fr14, @-r15
- fmov.s fr13, @-r15
- fmov.s fr12, @-r15
- fmov.s fr11, @-r15
- fmov.s fr10, @-r15
- fmov.s fr9, @-r15
- fmov.s fr8, @-r15
- fmov.s fr7, @-r15
- fmov.s fr6, @-r15
- fmov.s fr5, @-r15
- fmov.s fr4, @-r15
- fmov.s fr3, @-r15
- fmov.s fr2, @-r15
- fmov.s fr1, @-r15
- bra 9f
- fmov.s fr0, @-r15
-#else
- mov.l 3f, k1
- bt/s 9f ! it's a kernel to kernel transition, and skip the FPU save.
- mov r15, k0 ! save original stack to k0 anyway
-#endif
-8: /* User space to kernel */
+ stc ssr, k0 ! Is it from kernel space?
+ shll k0 ! Check MD bit (bit30) by shifting it into...
+ shll k0 ! ...the T bit
+ bt/s 9f ! It's a kernel to kernel transition.
+ mov r15, k0 ! save original stack to k0
+ /* User space to kernel */
mov #0x20, k1
- shll8 k1 ! k1 <= 8192 == THREAD_SIZE
+ shll8 k1 ! k1 <= 8192 == THREAD_SIZE
add current, k1
mov k1, r15 ! change to kernel stack
!
- mov.l 4f, k1 ! let kernel release FPU
-9: ! Save the user registers on the stack.
- ! At this point, k1 should have been set to the new SR value
- mov #-1, k4
- mov.l k4, @-r15 ! syscall_nr (default: -1)
+9: mov #-1, k4
+ mov.l 3f, k1
+ ! Save the user registers on the stack.
+ mov.l k4, @-r15 ! syscall_nr (default: -1)
!
sts.l macl, @-r15
sts.l mach, @-r15
mov.l r9, @-r15
mov.l r8, @-r15
!
- stc sr, r8 ! Back to normal register bank, and
- or k1, r8 ! Block all interrupts, may release FPU
+ stc sr, r8 ! Back to normal register bank, and
+ or k1, r8 ! Block all interrupts
mov.l 5f, k1
- and k1, r8 ! ...
- ldc r8, sr ! ...changed here.
+ and k1, r8 ! ...
+ ldc r8, sr ! ...changed here.
!
mov.l r7, @-r15
mov.l r6, @-r15
nop
.align 2
1: .long SYMBOL_NAME(exception_handling_table)
-2: .long 0x00008000 ! FD=1
3: .long 0x000000f0 ! FD=0, IMASK=15
-4: .long 0x000080f0 ! FD=1, IMASK=15
5: .long 0xcfffffff ! RB=0, BL=0
6: .long 0x00080000 ! SZ=0, PR=1
#include <asm/processor.h>
#include <asm/io.h>
+/*
+ * Save FPU registers onto task structure.
+ * Assume called with FPU enabled (SR.FD=0).
+ */
void
save_fpu(struct task_struct *tsk)
{
* double precission represents signaling NANS.
*/
-void fpu_init(void)
+static void
+fpu_init(void)
{
asm volatile("lds %0, fpul\n\t"
"lds %1, fpscr\n\t"
: "r" (0), "r" (FPSCR_INIT));
}
+/**
+ * denormal_to_double - Given denormalized float number,
+ * store double float
+ *
+ * @fpu: Pointer to sh_fpu_hard structure
+ * @n: Index to FP register
+ */
+static void
+denormal_to_double (struct sh_fpu_hard_struct *fpu, int n)
+{
+ unsigned long du, dl;
+ unsigned long x = fpu->fpul;
+ int exp = 1023 - 126;
+
+ if (x != 0 && (x & 0x7f800000) == 0) {
+ du = (x & 0x80000000);
+ while ((x & 0x00800000) == 0) {
+ x <<= 1;
+ exp--;
+ }
+ x &= 0x007fffff;
+ du |= (exp << 20) | (x >> 3);
+ dl = x << 29;
+
+ fpu->fp_regs[n] = du;
+ fpu->fp_regs[n+1] = dl;
+ }
+}
+
+/**
+ * ieee_fpe_handler - Handle denormalized number exception
+ *
+ * @regs: Pointer to register structure
+ *
+ * Returns 1 when it's handled (should not cause exception).
+ */
+static int
+ieee_fpe_handler (struct pt_regs *regs)
+{
+ unsigned short insn = *(unsigned short *) regs->pc;
+ unsigned short finsn;
+ unsigned long nextpc;
+ int nib[4] = {
+ (insn >> 12) & 0xf,
+ (insn >> 8) & 0xf,
+ (insn >> 4) & 0xf,
+ insn & 0xf};
+
+ if (nib[0] == 0xb ||
+ (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */
+ regs->pr = regs->pc + 4;
+
+ if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */
+ nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3);
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */
+ if (regs->sr & 1)
+ nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+ else
+ nextpc = regs->pc + 4;
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */
+ if (regs->sr & 1)
+ nextpc = regs->pc + 4;
+ else
+ nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x4 && nib[3] == 0xb &&
+ (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */
+ nextpc = regs->regs[nib[1]];
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x0 && nib[3] == 0x3 &&
+ (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */
+ nextpc = regs->pc + 4 + regs->regs[nib[1]];
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (insn == 0x000b) { /* rts */
+ nextpc = regs->pr;
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else {
+ nextpc = regs->pc + 2;
+ finsn = insn;
+ }
+
+ if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
+ struct task_struct *tsk = current;
+
+ save_fpu(tsk);
+ if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) {
+ /* FPU error */
+ denormal_to_double (&tsk->thread.fpu.hard,
+ (finsn >> 8) & 0xf);
+ tsk->thread.fpu.hard.fpscr &=
+ ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
+ grab_fpu();
+ restore_fpu(tsk);
+ tsk->flags |= PF_USEDFPU;
+ } else {
+ tsk->thread.trap_no = 11;
+ tsk->thread.error_code = 0;
+ force_sig(SIGFPE, tsk);
+ }
+
+ regs->pc = nextpc;
+ return 1;
+ }
+
+ return 0;
+}
+
asmlinkage void
do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
struct task_struct *tsk = current;
- regs.pc += 2;
+ if (ieee_fpe_handler (®s))
+ return;
- grab_fpu();
+ regs.pc += 2;
save_fpu(tsk);
tsk->thread.trap_no = 11;
tsk->thread.error_code = 0;
{
struct task_struct *tsk = current;
- if (!user_mode(®s)) {
- if (tsk != &init_task) {
- unlazy_fpu(tsk);
- }
- tsk = &init_task;
- if (tsk->flags & PF_USEDFPU) {
- /*
- * This weird situation can be occurred.
- *
- * There's race condition in __cli:
- *
- * (1) SR --> register
- * (2) Set IMASK of register
- * (3) SR <-- register
- *
- * Between (1) and (2), or (2) and (3) getting
- * interrupt, and interrupt handler (or
- * softirq) may use FPU.
- *
- * Then, SR.FD is overwritten by (3).
- *
- * This results init_task.PF_USEDFPU is on,
- * with SR.FD == 1.
- *
- */
- release_fpu();
- return;
- }
- }
-
grab_fpu();
- if (tsk->used_math) {
- /* Using the FPU again. */
- restore_fpu(tsk);
- } else {
- /* First time FPU user. */
- fpu_init();
- tsk->used_math = 1;
- }
- tsk->flags |= PF_USEDFPU;
- release_fpu();
-}
-
-/*
- * Change current FD flag to set FD flag back to exception
- */
-asmlinkage void
-fpu_prepare_fd(unsigned long sr, unsigned long r5, unsigned long r6,
- unsigned long r7, struct pt_regs regs)
-{
- __cli();
if (!user_mode(®s)) {
- if (init_task.flags & PF_USEDFPU)
- grab_fpu();
- else {
- if (!(sr & SR_FD)) {
- BUG();
- release_fpu();
- }
- }
+ printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
return;
}
- if (sr & SR_FD) { /* Kernel doesn't grab FPU */
- if (current->flags & PF_USEDFPU)
- grab_fpu();
- else {
- if (init_task.flags & PF_USEDFPU) {
- /*
- * This weird situation can be occurred.
- * See the comment in do_fpu_state_restore.
- */
- grab_fpu();
- save_fpu(&init_task);
- }
- }
- } else {
- if (init_task.flags & PF_USEDFPU)
- save_fpu(&init_task);
- else {
- BUG();
- release_fpu();
- }
- }
-}
-
-/* Short cut for the FPU exception */
-asmlinkage void
-enable_fpu_in_danger(void)
-{
- struct task_struct *tsk = current;
-
- if (tsk != &init_task)
- unlazy_fpu(tsk);
-
- tsk = &init_task;
if (tsk->used_math) {
/* Using the FPU again. */
restore_fpu(tsk);
sub r1, r0 !
ldc r0, r7_bank ! ... and init_task
!
-#if defined(__SH4__)
- ! Initialize fpu
- mov.l 7f, r0
- jsr @r0
- nop
-#endif
! Enable cache
mov.l 6f, r0
jsr @r0
nop
.balign 4
-1: .long 0x400000F0 ! MD=1, RB=0, BL=0, FD=0, IMASK=0xF
+1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
2: .long SYMBOL_NAME(stack)
3: .long SYMBOL_NAME(__bss_start)
4: .long SYMBOL_NAME(_end)
5: .long SYMBOL_NAME(start_kernel)
6: .long SYMBOL_NAME(cache_init)
-#if defined(__SH4__)
-7: .long SYMBOL_NAME(fpu_init)
-#endif
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/smp.h>
*/
#include <linux/unistd.h>
+#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/a.out.h>
#include <asm/io.h>
#include <asm/uaccess.h>
void cpu_idle(void *unused)
{
/* endless idle loop with no priority at all */
- init_idle();
- current->nice = 20;
-
while (1) {
if (hlt_counter) {
if (need_resched())
} while ((ctrl_inb(RCR1) & RCR1_CF) != 0);
#if RTC_BIT_INVERTED != 0
- /* Work around to avoid reading correct value. */
+ /* Work around to avoid reading incorrect value. */
if (sec128 == RTC_BIT_INVERTED) {
schedule_timeout(1);
goto again;
goto again;
}
+#if RTC_BIT_INVERTED != 0
+ if ((sec128 & RTC_BIT_INVERTED))
+ sec--;
+#endif
+
tv->tv_sec = mktime(yr100 * 100 + yr, mon, day, hr, min, sec);
- tv->tv_usec = ((sec128 ^ RTC_BIT_INVERTED) * 1000000) / 128;
+ tv->tv_usec = (sec128 * 1000000) / 128;
}
-static int set_rtc_time(unsigned long nowtime)
+int sh_rtc_settimeofday(const struct timeval *tv)
{
+ unsigned long nowtime = tv->tv_sec;
int retval = 0;
int real_seconds, real_minutes, cmos_minutes;
return retval;
}
-
-int sh_rtc_settimeofday(const struct timeval *tv)
-{
-#if RTC_BIT_INVERTED != 0
- /* This is not accurate, but better than nothing. */
- schedule_timeout(HZ/2);
-#endif
- return set_rtc_time(tv->tv_sec);
-}
static kdev_t sh_console_device(struct console *c)
{
- /* TODO: this is totally bogus */
- /* return MKDEV(SCI_MAJOR, SCI_MINOR_START + c->index); */
- return 0;
+ /* /dev/null */
+ return mk_kdev(MEM_MAJOR, 3);
}
/*
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/personality.h>
+#include <linux/tty.h>
+
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
/*
* handle an instruction that does an unaligned memory access
* - have to be careful of branch delay-slot instructions that fault
+ * SH3:
* - if the branch would be taken PC points to the branch
* - if the branch would not be taken, PC points to delay-slot
+ * SH4:
+ * - PC always points to delayed branch
* - return 0 if handled, -EFAULT if failed (may not return if in kernel)
*/
+
+/* Macros to determine offset from current PC for branch instructions */
+/* Explicit type coercion is used to force sign extension where needed */
+#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4)
+#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
+
static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
{
u_int rm;
break;
case 0x0F00: /* bf/s lab */
ret = handle_unaligned_delayslot(regs);
- if (ret==0)
- regs->pc += (instruction&0x00FF)*2 + 4;
+ if (ret==0) {
+#if defined(__SH4__)
+ if ((regs->sr & 0x00000001) != 0)
+ regs->pc += 4; /* next after slot */
+ else
+#endif
+ regs->pc += SH_PC_8BIT_OFFSET(instruction);
+ }
break;
case 0x0900: /* bt lab - no delayslot */
break;
case 0x0D00: /* bt/s lab */
ret = handle_unaligned_delayslot(regs);
- if (ret==0)
- regs->pc += (instruction&0x00FF)*2 + 4;
+ if (ret==0) {
+#if defined(__SH4__)
+ if ((regs->sr & 0x00000001) == 0)
+ regs->pc += 4; /* next after slot */
+ else
+#endif
+ regs->pc += SH_PC_8BIT_OFFSET(instruction);
+ }
break;
}
break;
case 0xA000: /* bra label */
ret = handle_unaligned_delayslot(regs);
if (ret==0)
- regs->pc += (instruction&0x0FFF)*2 + 4;
+ regs->pc += SH_PC_12BIT_OFFSET(instruction);
break;
case 0xB000: /* bsr label */
ret = handle_unaligned_delayslot(regs);
if (ret==0) {
regs->pr = regs->pc + 4;
- regs->pc += (instruction&0x0FFF)*2 + 4;
+ regs->pc += SH_PC_12BIT_OFFSET(instruction);
}
break;
}
out_of_memory:
up_read(&mm->mmap_sem);
if (current->pid == 1) {
- current->policy |= SCHED_YIELD;
- schedule();
+ yield();
down_read(&mm->mmap_sem);
goto survive;
}
dir = pgd_offset_k(address);
else if (address >= TASK_SIZE)
return 1;
+ else if (!current->mm)
+ return 1;
else
dir = pgd_offset(current->mm, address);
#include <linux/watchdog.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
-#include <linux/smp_lock.h>
#include <linux/ioport.h>
#include <asm/io.h>
#define WTCSR_CKS1 0x02
#define WTCSR_CKS0 0x01
-#define WTCSR_CKS 0x07
-#define WTCSR_CKS_1 0x00
-#define WTCSR_CKS_4 0x01
-#define WTCSR_CKS_16 0x02
-#define WTCSR_CKS_32 0x03
-#define WTCSR_CKS_64 0x04
-#define WTCSR_CKS_256 0x05
-#define WTCSR_CKS_1024 0x06
+/*
+ * CKS0-2 supports a number of clock division ratios. At the time the watchdog
+ * is enabled, it defaults to a 41 usec overflow period .. we overload this to
+ * something a little more reasonable, and really can't deal with anything
+ * lower than WTCSR_CKS_1024, else we drop back into the usec range.
+ *
+ * Clock Division Ratio Overflow Period
+ * --------------------------------------------
+ * 1/32 (initial value) 41 usecs
+ * 1/64 82 usecs
+ * 1/128 164 usecs
+ * 1/256 328 usecs
+ * 1/512 656 usecs
+ * 1/1024 1.31 msecs
+ * 1/2048 2.62 msecs
+ * 1/4096 5.25 msecs
+ */
+#define WTCSR_CKS_32 0x00
+#define WTCSR_CKS_64 0x01
+#define WTCSR_CKS_128 0x02
+#define WTCSR_CKS_256 0x03
+#define WTCSR_CKS_512 0x04
+#define WTCSR_CKS_1024 0x05
+#define WTCSR_CKS_2048 0x06
#define WTCSR_CKS_4096 0x07
-static int sh_is_open = 0;
+/*
+ * Default clock division ratio is 5.25 msecs. Overload this at module load
+ * time. Any value not in the msec range will default to a timeout of one
+ * jiffy, which exceeds the usec overflow periods.
+ */
+static int clock_division_ratio = WTCSR_CKS_4096;
+
+#define msecs_to_jiffies(msecs) (jiffies + ((HZ * msecs + 999) / 1000))
+#define next_ping_period(cks) msecs_to_jiffies(cks - 4)
+#define user_ping_period(cks) (next_ping_period(cks) * 10)
+
+static unsigned long sh_is_open = 0;
static struct watchdog_info sh_wdt_info;
+static struct timer_list timer;
+static unsigned long next_heartbeat;
/**
* sh_wdt_write_cnt - Write to Counter
*/
static void sh_wdt_start(void)
{
+ timer.expires = next_ping_period(clock_division_ratio);
+ next_heartbeat = user_ping_period(clock_division_ratio);
+ add_timer(&timer);
+
sh_wdt_write_csr(WTCSR_WT | WTCSR_CKS_4096);
sh_wdt_write_cnt(0);
sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME));
*/
static void sh_wdt_stop(void)
{
+ del_timer(&timer);
+
sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_TME));
}
*/
static void sh_wdt_ping(unsigned long data)
{
- sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF));
- sh_wdt_write_cnt(0);
+ if (time_before(jiffies, next_heartbeat)) {
+ sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF));
+ sh_wdt_write_cnt(0);
+
+ timer.expires = next_ping_period(clock_division_ratio);
+ add_timer(&timer);
+ }
}
/**
{
switch (minor(inode->i_rdev)) {
case WATCHDOG_MINOR:
- if (sh_is_open) {
+ if (test_and_set_bit(0, &sh_is_open))
return -EBUSY;
- }
- sh_is_open = 1;
sh_wdt_start();
- return 0;
+ break;
default:
return -ENODEV;
}
*/
static int sh_wdt_close(struct inode *inode, struct file *file)
{
- lock_kernel();
-
if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
#ifndef CONFIG_WATCHDOG_NOWAYOUT
sh_wdt_stop();
#endif
- sh_is_open = 0;
+ clear_bit(0, &sh_is_open);
}
- unlock_kernel();
-
return 0;
}
return -ESPIPE;
if (count) {
- sh_wdt_ping(0);
+ next_heartbeat = user_ping_period(clock_division_ratio);
return 1;
}
break;
case WDIOC_KEEPALIVE:
- sh_wdt_ping(0);
+ next_heartbeat = user_ping_period(clock_division_ratio);
break;
default:
return -EINVAL;
}
+ init_timer(&timer);
+ timer.function = sh_wdt_ping;
+ timer.data = 0;
+
return 0;
}
MODULE_AUTHOR("Paul Mundt <lethal@chaoticdreams.org>");
MODULE_DESCRIPTION("SH 3/4 watchdog driver");
MODULE_LICENSE("GPL");
+MODULE_PARM(clock_division_ratio, "i");
+MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7.");
module_init(sh_wdt_init);
module_exit(sh_wdt_exit);
MODULE_PARM (multicast_filter_limit, "i");
MODULE_PARM_DESC (multicast_filter_limit, "8139cp maximum number of filtered multicast addresses");
-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
-#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
- || defined(__sparc_) || defined(__ia64__) \
- || defined(__sh__) || defined(__mips__)
-static int rx_copybreak = 1518;
-#else
-static int rx_copybreak = 100;
-#endif
-MODULE_PARM (rx_copybreak, "i");
-MODULE_PARM_DESC (rx_copybreak, "8139cp Breakpoint at which Rx packets are copied");
-
#define PFX DRV_NAME ": "
#define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \
netif_rx (skb);
}
-static inline void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
- u32 status, u32 len)
+static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
+ u32 status, u32 len)
{
if (netif_msg_rx_err (cp))
printk (KERN_DEBUG
while (rx_work--) {
u32 status, len;
dma_addr_t mapping;
- struct sk_buff *skb, *copy_skb;
- unsigned copying_skb, buflen;
+ struct sk_buff *skb, *new_skb;
+ unsigned buflen;
skb = cp->rx_skb[rx_tail].skb;
if (!skb)
goto rx_next;
}
- copying_skb = (len <= rx_copybreak);
-
if (netif_msg_rx_status(cp))
- printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d copying? %d\n",
- cp->dev->name, rx_tail, status, len,
- copying_skb);
+ printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d\n",
+ cp->dev->name, rx_tail, status, len);
- buflen = copying_skb ? len : cp->rx_buf_sz;
- copy_skb = dev_alloc_skb (buflen + RX_OFFSET);
- if (!copy_skb) {
+ buflen = cp->rx_buf_sz + RX_OFFSET;
+ new_skb = dev_alloc_skb (buflen);
+ if (!new_skb) {
cp->net_stats.rx_dropped++;
goto rx_next;
}
- skb_reserve(copy_skb, RX_OFFSET);
- copy_skb->dev = cp->dev;
-
- if (!copying_skb) {
- pci_unmap_single(cp->pdev, mapping,
- buflen, PCI_DMA_FROMDEVICE);
- skb->ip_summed = CHECKSUM_NONE;
- skb_trim(skb, len);
-
- mapping =
- cp->rx_skb[rx_tail].mapping =
- pci_map_single(cp->pdev, copy_skb->data,
- buflen, PCI_DMA_FROMDEVICE);
- cp->rx_skb[rx_tail].skb = copy_skb;
- skb_put(copy_skb, buflen);
- } else {
- skb_put(copy_skb, len);
- pci_dma_sync_single(cp->pdev, mapping, len, PCI_DMA_FROMDEVICE);
- memcpy(copy_skb->data, skb->data, len);
-
- /* We'll reuse the original ring buffer. */
- skb = copy_skb;
- }
+ skb_reserve(new_skb, RX_OFFSET);
+ new_skb->dev = cp->dev;
+
+ pci_unmap_single(cp->pdev, mapping,
+ buflen, PCI_DMA_FROMDEVICE);
+ skb->ip_summed = CHECKSUM_NONE;
+ skb_put(skb, len);
+
+ mapping =
+ cp->rx_skb[rx_tail].mapping =
+ pci_map_single(cp->pdev, new_skb->tail,
+ buflen, PCI_DMA_FROMDEVICE);
+ cp->rx_skb[rx_tail].skb = new_skb;
cp_rx_skb(cp, skb);
skb->dev = cp->dev;
skb_reserve(skb, RX_OFFSET);
- skb_put(skb, cp->rx_buf_sz);
cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
- skb->data, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
cp->rx_skb[i].skb = skb;
cp->rx_skb[i].frag = 0;
struct cp_private *cp = dev->priv;
int rc = 0;
+ if (!netif_running(dev))
+ return -EINVAL;
+
switch (cmd) {
case SIOCETHTOOL:
return cp_ethtool_ioctl(cp, (void *) rq->ifr_data);
int rc = 0;
int phy = tp->phys[0] & 0x3f;
+ if (!netif_running(dev))
+ return -EINVAL;
+
if (cmd != SIOCETHTOOL) {
/* With SIOCETHTOOL, this would corrupt the pointer. */
data->phy_id &= 0x1f;
export-objs := 8390.o arlan.o aironet4500_core.o aironet4500_card.o \
ppp_async.o ppp_generic.o slhc.o pppox.o auto_irq.o \
- net_init.o
+ net_init.o mii.o
list-multi := rcpci.o
rcpci-objs := rcpci45.o rclanmtl.o
dev->dev_addr[i*2+1] = eeprom_buff[i] >> 8;
}
if (net_debug > 1)
- printk(KERN_DEBUG "%s: new adapter_cnf: 0%x\n",
+ printk(KERN_DEBUG "%s: new adapter_cnf: 0x%x\n",
dev->name, lp->adapter_cnf);
}
i = lp->isa_config & INT_NO_MASK;
if (lp->chip_type == CS8900) {
/* Translate the IRQ using the IRQ mapping table. */
- if (i > sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
- printk("\ncs89x0: bug: isa_config is %d\n", i);
+ if (i >= sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
+ printk("\ncs89x0: invalid ISA interrupt number %d\n", i);
else
i = cs8900_irq_map[i];
case SIOCSMIIREG: /* Write MII PHY register. */
case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
return 0;
--- /dev/null
+/*
+
+ mii.c: MII interface library
+
+ Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>
+ Copyright 2001 Jeff Garzik
+
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+
+int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
+{
+ struct net_device *dev = mii->dev;
+ u32 advert, bmcr, lpa, nego;
+
+ ecmd->supported =
+ (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
+
+ /* only supports twisted-pair */
+ ecmd->port = PORT_MII;
+
+ /* only supports internal transceiver */
+ ecmd->transceiver = XCVR_INTERNAL;
+
+ /* this isn't fully supported at higher layers */
+ ecmd->phy_address = mii->phy_id;
+
+ ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
+ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
+ if (advert & ADVERTISE_10HALF)
+ ecmd->advertising |= ADVERTISED_10baseT_Half;
+ if (advert & ADVERTISE_10FULL)
+ ecmd->advertising |= ADVERTISED_10baseT_Full;
+ if (advert & ADVERTISE_100HALF)
+ ecmd->advertising |= ADVERTISED_100baseT_Half;
+ if (advert & ADVERTISE_100FULL)
+ ecmd->advertising |= ADVERTISED_100baseT_Full;
+
+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+ lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
+ if (bmcr & BMCR_ANENABLE) {
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ ecmd->autoneg = AUTONEG_ENABLE;
+
+ nego = mii_nway_result(advert & lpa);
+ if (nego == LPA_100FULL || nego == LPA_100HALF)
+ ecmd->speed = SPEED_100;
+ else
+ ecmd->speed = SPEED_10;
+ if (nego == LPA_100FULL || nego == LPA_10FULL) {
+ ecmd->duplex = DUPLEX_FULL;
+ mii->full_duplex = 1;
+ } else {
+ ecmd->duplex = DUPLEX_HALF;
+ mii->full_duplex = 0;
+ }
+ } else {
+ ecmd->autoneg = AUTONEG_DISABLE;
+
+ ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
+ ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
+ }
+
+ /* ignore maxtxpkt, maxrxpkt for now */
+
+ return 0;
+}
+
+int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
+{
+ struct net_device *dev = mii->dev;
+
+ if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
+ return -EINVAL;
+ if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
+ return -EINVAL;
+ if (ecmd->port != PORT_MII)
+ return -EINVAL;
+ if (ecmd->transceiver != XCVR_INTERNAL)
+ return -EINVAL;
+ if (ecmd->phy_address != mii->phy_id)
+ return -EINVAL;
+ if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
+ return -EINVAL;
+
+ /* ignore supported, maxtxpkt, maxrxpkt */
+
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
+ u32 bmcr, advert, tmp;
+
+ if ((ecmd->advertising & (ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full)) == 0)
+ return -EINVAL;
+
+ /* advertise only what has been requested */
+ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
+ tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+ if (ADVERTISED_10baseT_Half)
+ tmp |= ADVERTISE_10HALF;
+ if (ADVERTISED_10baseT_Full)
+ tmp |= ADVERTISE_10FULL;
+ if (ADVERTISED_100baseT_Half)
+ tmp |= ADVERTISE_100HALF;
+ if (ADVERTISED_100baseT_Full)
+ tmp |= ADVERTISE_100FULL;
+ if (advert != tmp) {
+ mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
+ mii->advertising = tmp;
+ }
+
+ /* turn on autonegotiation, and force a renegotiate */
+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
+
+ mii->duplex_lock = 0;
+ } else {
+ u32 bmcr, tmp;
+
+ /* turn off auto negotiation, set speed and duplexity */
+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+ tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
+ if (ecmd->speed == SPEED_100)
+ bmcr |= BMCR_SPEED100;
+ if (ecmd->duplex == DUPLEX_FULL) {
+ bmcr |= BMCR_FULLDPLX;
+ mii->full_duplex = 1;
+ } else
+ mii->full_duplex = 0;
+ if (bmcr != tmp)
+ mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
+
+ mii->duplex_lock = 1;
+ }
+ return 0;
+}
+
+int mii_link_ok (struct mii_if_info *mii)
+{
+ if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)
+ return 1;
+ return 0;
+}
+
+int mii_nway_restart (struct mii_if_info *mii)
+{
+ int bmcr;
+ int r = -EINVAL;
+
+ /* if autoneg is off, it's an error */
+ bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR);
+
+ if (bmcr & BMCR_ANENABLE) {
+ bmcr |= BMCR_ANRESTART;
+ mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr);
+ r = 0;
+ }
+
+ return r;
+}
+
+EXPORT_SYMBOL(mii_link_ok);
+EXPORT_SYMBOL(mii_nway_restart);
+EXPORT_SYMBOL(mii_ethtool_gset);
+EXPORT_SYMBOL(mii_ethtool_sset);
Support and updates available at
http://www.scyld.com/network/sundance.html
+
+
+ Version 1.01a (jgarzik):
+ - Replace some MII-related magic numbers with constants
+
*/
#define DRV_NAME "sundance"
-#define DRV_VERSION "1.01"
-#define DRV_RELDATE "4/09/00"
+#define DRV_VERSION "1.01a"
+#define DRV_RELDATE "11-Nov-2001"
/* The user-configurable values.
int irq;
int i;
long ioaddr;
- u16 mii_reg0;
+ u16 mii_ctl;
void *ring_space;
dma_addr_t ring_dma;
}
}
/* Reset PHY */
- mdio_write (dev, np->phys[0], 0, 0x8000);
+ mdio_write (dev, np->phys[0], MII_BMCR, BMCR_RESET);
mdelay (300);
- mdio_write (dev, np->phys[0], 0, 0x1200);
+ mdio_write (dev, np->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART);
/* Force media type */
if (!np->an_enable) {
- mii_reg0 = 0;
- mii_reg0 |= (np->speed == 100) ? 0x2000 : 0;
- mii_reg0 |= (np->full_duplex) ? 0x0100 : 0;
- mdio_write (dev, np->phys[0], 0, mii_reg0);
+ mii_ctl = 0;
+ mii_ctl |= (np->speed == 100) ? BMCR_SPEED100 : 0;
+ mii_ctl |= (np->full_duplex) ? BMCR_FULLDPLX : 0;
+ mdio_write (dev, np->phys[0], MII_BMCR, mii_ctl);
printk (KERN_INFO "Override speed=%d, %s duplex\n",
np->speed, np->full_duplex ? "Full" : "Half");
{
struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
- int mii_reg5 = mdio_read(dev, np->phys[0], 5);
- int negotiated = mii_reg5 & np->advertising;
+ int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
+ int negotiated = mii_lpa & np->advertising;
int duplex;
/* Force media */
- if (!np->an_enable || mii_reg5 == 0xffff) {
+ if (!np->an_enable || mii_lpa == 0xffff) {
if (np->full_duplex)
writew (readw (ioaddr + MACCtrl0) | EnbFullDuplex,
ioaddr + MACCtrl0);
{
long ioaddr = dev->base_addr;
struct netdev_private *np = dev->priv;
- u16 mii_reg0, mii_reg4, mii_reg5;
+ u16 mii_ctl, mii_advertise, mii_lpa;
int speed;
if (intr_status & IntrDrvRqst) {
}
if (intr_status & LinkChange) {
if (np->an_enable) {
- mii_reg4 = mdio_read (dev, np->phys[0], 4);
- mii_reg5= mdio_read (dev, np->phys[0], 5);
- mii_reg4 &= mii_reg5;
+ mii_advertise = mdio_read (dev, np->phys[0], MII_ADVERTISE);
+ mii_lpa= mdio_read (dev, np->phys[0], MII_LPA);
+ mii_advertise &= mii_lpa;
printk (KERN_INFO "%s: Link changed: ", dev->name);
- if (mii_reg4 & 0x0100)
+ if (mii_advertise & ADVERTISE_100FULL)
printk ("100Mbps, full duplex\n");
- else if (mii_reg4 & 0x0080)
+ else if (mii_advertise & ADVERTISE_100HALF)
printk ("100Mbps, half duplex\n");
- else if (mii_reg4 & 0x0040)
+ else if (mii_advertise & ADVERTISE_10FULL)
printk ("10Mbps, full duplex\n");
- else if (mii_reg4 & 0x0020)
+ else if (mii_advertise & ADVERTISE_10HALF)
printk ("10Mbps, half duplex\n");
else
printk ("\n");
} else {
- mii_reg0 = mdio_read (dev, np->phys[0], 0);
- speed = (mii_reg0 & 0x2000) ? 100 : 10;
+ mii_ctl = mdio_read (dev, np->phys[0], MII_BMCR);
+ speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
printk (KERN_INFO "%s: Link changed: %dMbps ,",
dev->name, speed);
- printk ("%s duplex.\n", (mii_reg0 & 0x0100) ?
+ printk ("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ?
"full" : "half");
}
check_duplex (dev);
static int via_mixer_open (struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct via_info *card;
struct pci_dev *pdev;
struct pci_driver *drvr;
static int via_dsp_open (struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct via_info *card;
struct pci_dev *pdev;
struct via_channel *chan;
static struct clgenfb_info boards[MAX_NUM_BOARDS]; /* the boards */
static unsigned clgen_def_mode = 1;
+static int noaccel = 0;
static int release_io_ports = 0;
break;
case BT_PICASSO4:
+#ifdef CONFIG_ZORRO
vga_wseq (fb_info->regs, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */
+#endif
/* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */
break;
DPRINTK ("clgen: (RAM start set to: 0x%p)\n", fb_info->fbmem);
+ if (noaccel)
+ {
+ printk("clgen: disabling text acceleration support\n");
+#ifdef FBCON_HAS_CFB8
+ fbcon_clgen_8.bmove = fbcon_cfb8_bmove;
+ fbcon_clgen_8.clear = fbcon_cfb8_clear;
+#endif
+#ifdef FBCON_HAS_CFB16
+ fbcon_clgen_16.bmove = fbcon_cfb16_bmove;
+ fbcon_clgen_16.clear = fbcon_cfb16_clear;
+#endif
+#ifdef FBCON_HAS_CFB32
+ fbcon_clgen_32.bmove = fbcon_cfb32_bmove;
+ fbcon_clgen_32.clear = fbcon_cfb32_clear;
+#endif
+ }
+
init_vgachip (fb_info);
/* set up a few more things, register framebuffer driver etc */
if (strcmp (this_opt, s) == 0)
clgen_def_mode = i;
}
+ if (!strcmp(this_opt, "noaccel"))
+ noaccel = 1;
}
return 0;
}
static int driverfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
{
struct inode *inode = driverfs_get_inode(dir->i_sb, mode, dev);
- int error = -ENOSPC;
+ int error = -EPERM;
- if (inode) {
+ /* only allow create if ->d_fsdata is not NULL (so we can assume it
+ * comes from the driverfs API below. */
+ if (dentry->d_fsdata && inode) {
d_instantiate(dentry, inode);
dget(dentry);
error = 0;
DBG("%s: file entry is NULL\n",__FUNCTION__);
return -ENOENT;
}
+ if (!entry->show)
+ return 0;
dev = list_entry(entry->parent,struct device, dir);
- get_device(dev);
-
- if (!entry->show)
- goto done;
page = (unsigned char*)__get_free_page(GFP_KERNEL);
- if (!page) {
- retval = -ENOMEM;
- goto done;
- }
+ if (!page)
+ return -ENOMEM;
while (count > 0) {
ssize_t len;
retval += len;
}
free_page((unsigned long)page);
-
- done:
- put_device(dev);
return retval;
}
DBG("%s: file entry is NULL\n",__FUNCTION__);
return -ENOENT;
}
+ if (!entry->store)
+ return 0;
dev = list_entry(entry->parent,struct device, dir);
- get_device(dev);
-
- if (!entry->store)
- goto done;
while (count > 0) {
ssize_t len;
*ppos += len;
buf += len;
}
- done:
- put_device(dev);
return retval;
}
static int driverfs_open_file(struct inode * inode, struct file * filp)
{
- if (filp && inode)
- filp->private_data = inode->u.generic_ip;
+ struct driver_file_entry * entry;
+ struct device * dev;
+
+ entry = (struct driver_file_entry *)inode->u.generic_ip;
+ if (!entry)
+ return -EFAULT;
+ dev = (struct device *)list_entry(entry->parent,struct device,dir);
+ get_device(dev);
+ filp->private_data = entry;
+ return 0;
+}
+
+static int driverfs_flush(struct file * filp)
+{
+ struct driver_file_entry * entry;
+ struct device * dev;
+ entry = (struct driver_file_entry *)filp->private_data;
+ if (!entry)
+ return -EFAULT;
+ dev = (struct device *)list_entry(entry->parent,struct device,dir);
+ put_device(dev);
return 0;
}
llseek: driverfs_file_lseek,
mmap: generic_file_mmap,
open: driverfs_open_file,
+ flush: driverfs_flush,
fsync: driverfs_sync_file,
};
dentry = lookup_hash(&qstr,parent_dentry);
if (IS_ERR(dentry))
error = PTR_ERR(dentry);
- else
+ else {
+ dentry->d_fsdata = (void *)entry;
error = vfs_create(parent_dentry->d_inode,dentry,entry->mode);
-
+ }
/* Still good? Ok, then fill in the blanks: */
if (!error) {
- dentry->d_fsdata = (void *)entry;
dentry->d_inode->u.generic_ip = (void *)entry;
entry->dentry = dentry;
enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
{
}
+
+/*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 168-bit bitmap where the first 128 bits are
+ * unlikely to be set. It's guaranteed that at least one of the 168
+ * bits is cleared.
+ */
+#if MAX_RT_PRIO != 128 || MAX_PRIO != 168
+# error update this function.
+#endif
+
+static inline int sched_find_first_zero_bit(unsigned long *b)
+{
+ unsigned int rt;
+
+ rt = b[0] & b[1] & b[2] & b[3];
+ if (unlikely(rt != 0xffffffff))
+ return find_first_zero_bit(b, MAX_RT_PRIO);
+
+ if (b[4] != ~0)
+ return ffz(b[4]) + MAX_RT_PRIO;
+ return ffz(b[5]) + 32 + MAX_RT_PRIO;
+}
+
#endif /* __ASM_SH_MMU_CONTEXT_H */
static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
+/*
+ * Macro and implementation to make a page protection as uncachable.
+ */
+#define pgprot_noncached pgprot_noncached
+
+static inline pgprot_t pgprot_noncached(pgprot_t _prot)
+{
+ unsigned long prot = pgprot_val(_prot);
+
+ prot &= ~_PAGE_CACHABLE;
+ return __pgprot(prot);
+}
+
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
#define unlazy_fpu(tsk) do { \
if ((tsk)->flags & PF_USEDFPU) { \
- grab_fpu(); \
save_fpu(tsk); \
} \
} while (0)
#define clear_fpu(tsk) do { \
- if ((tsk)->flags & PF_USEDFPU) \
+ if ((tsk)->flags & PF_USEDFPU) { \
(tsk)->flags &= ~PF_USEDFPU; \
+ release_fpu(); \
+ } \
} while (0)
/* Double presision, NANS as NANS, rounding to nearest, no exceptions */
#define FPSCR_INIT 0x00080000
+#define FPSCR_CAUSE_MASK 0x0001f000 /* Cause bits */
+#define FPSCR_FLAG_MASK 0x0000007c /* Flag bits */
+
/*
* Return saved PC of a blocked thread.
*/
#define __ASM_SH_SCATTERLIST_H
struct scatterlist {
- char * address; /* Location data is to be transferred to */
+ char * address; /* Location data is to be transferred to, NULL for
+ * highmem page */
+ struct page * page; /* Location for highmem page, if any */
+ unsigned int offset;/* for highmem, page offset */
+ dma_addr_t dma_address;
unsigned int length;
};
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
+#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
+ ADVERTISE_CSMA)
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
ADVERTISE_100HALF | ADVERTISE_100FULL)
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
#define NWAYTEST_RESV2 0xfe00 /* Unused... */
+
+struct mii_if_info {
+ int phy_id;
+ int advertising;
+
+ unsigned int full_duplex : 1;
+ unsigned int duplex_lock : 1;
+
+ struct net_device *dev;
+ int (*mdio_read) (struct net_device *dev, int phy_id, int location);
+ void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
+};
+
+struct ethtool_cmd;
+
+int mii_link_ok (struct mii_if_info *mii);
+int mii_nway_restart (struct mii_if_info *mii);
+int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+
+
/* This structure is used in all SIOCxMIIxxx ioctl calls */
struct mii_ioctl_data {
u16 phy_id;
bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
bool 'Sysctl support' CONFIG_SYSCTL
+endmenu
+
mainmenu_option next_comment
comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
-
-