diff -u --recursive --new-file v2.3.10/linux/CREDITS linux/CREDITS --- v2.3.10/linux/CREDITS Thu Jul 8 15:42:19 1999 +++ linux/CREDITS Sun Jul 18 14:08:53 1999 @@ -1714,12 +1714,13 @@ S: France N: Rik van Riel -E: H.H.vanRiel@humbolt.geo.uu.nl -W: http://humbolt.geo.uu.nl/ -D: Maintainer of the mm-patches page (see www.linuxhq.com) -D: Documentation/sysctl/*, kswapd fixes, random kernel hacker -S: Vorenkampsweg 1 -S: NL-9488 TG Zeijerveld +E: riel@nl.linux.org +W: http://www.nl.linux.org/~riel/ +D: Linux-MM site, Documentation/sysctl/*, swap/mm readaround +D: clustering contributor, kswapd fixes, random kernel hacker, +D: nl.linux.org maintainer, minor scheduler additions +S: IJsselstraat 23a +S: 9725 GA Groningen S: The Netherlands N: William E. Roadcap diff -u --recursive --new-file v2.3.10/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.3.10/linux/Documentation/Configure.help Thu Jul 8 15:42:19 1999 +++ linux/Documentation/Configure.help Wed Jul 21 12:54:07 1999 @@ -11945,13 +11945,15 @@ Support for user-space parallel port device drivers CONFIG_PPDEV - Saying Y to this adds support for /dev/parport device nodes. - NB. You have to make them before you can use them: - mknod /dev/parport00 c 99 0 - mknod /dev/parport01 c 99 1 - mknod /dev/parport10 c 99 16 - mknod /dev/parport11 c 99 17 - etc.. + Saying Y to this adds support for /dev/parport device nodes. This + is needed for programs that want portable access to the parallel + port, for instance deviceid (which displays Plug-and-Play device + IDs) and vlp (which makes a Linux computer act as though it's a + printer). + + This is the parallel port equivalent of SCSI generic support (sg). + It is safe to say N to this -- it is not needed for normal printing + or parallel port CD-ROM/disk support. # # A couple of things I keep forgetting: diff -u --recursive --new-file v2.3.10/linux/Documentation/kernel-parameters.txt linux/Documentation/kernel-parameters.txt --- v2.3.10/linux/Documentation/kernel-parameters.txt Thu Jul 8 15:42:19 1999 +++ linux/Documentation/kernel-parameters.txt Wed Jul 21 12:54:07 1999 @@ -19,7 +19,7 @@ HW Appropriate hardware is enabled. ISDN Appropriate ISDN support is enabled. JOY Appropriate joystick support is enabled. - LPT Printer support is enabled. + LP Printer support is enabled. MCA MCA bus support is enabled. MDA The MDA console is enabled. MOUSE Appropriate mouse support is enabled. @@ -29,6 +29,7 @@ PCI PCI bus support is enabled. PCMCIA The PCMCIA subsystem is enabled. PNP Plug & Play support is enabled. + PPT Parallel port support is enabled. PS2 Appropriate PS/2 support is enabled. RAM RAMdisc support is enabled. SCSI Appropriate SCSI support is enabled. @@ -187,7 +188,21 @@ load_ramdisk= [RAM] - lp= [LPT] Parallel Printer. + lp=0 [LP] Specify parallel ports to use, e.g, +or lp=port[,port...] lp=none,parport0 (lp0 not configured, lp1 uses +or lp=reset first parallel port). 'lp=0' disables the printer +or lp=auto driver. 'lp=reset' (which can be specified in + addition to the ports) causes attached + printers to be reset. Using + lp=port1,port2,... specifies the parallel + ports to associate lp devices with, starting + with lp0. A port specification may be 'none' + to skip that lp device, or a parport name such + as 'parport0'. Specifying 'lp=auto' instead + of a port specification list means that device + IDs from each port should be examined, to see + if an IEEE 1284-compliant printer is attached; + if so, the driver will manage that printer. ltpc= [HW] @@ -244,7 +259,19 @@ panic= - parport= [HW,LP] + parport=0 [HW,PPT] Specify parallel ports. 0 +or parport=auto disables. Use 'auto' to force the driver +or parport=0xBBB[,IRQ[,DMA]] to use any IRQ/DMA settings detected + (the default is to ignore detected + IRQ/DMA settings because of possible + conflicts). You can specify the base + address, IRQ, and DMA settings; IRQ + and DMA should be numbers or 'auto' + (for using detected settings on that + particular port). Parallel ports are + assigned in the order they are + specified on the command line, + starting with parport0. pas16= [HW,SCSI] @@ -262,7 +289,7 @@ pirq= [SMP,APIC] - plip= [LP,NET] Parallel port network link. + plip= [PPT,NET] Parallel port network link. profile= diff -u --recursive --new-file v2.3.10/linux/Makefile linux/Makefile --- v2.3.10/linux/Makefile Thu Jul 8 15:42:19 1999 +++ linux/Makefile Tue Jul 13 12:26:46 1999 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 3 -SUBLEVEL = 10 +SUBLEVEL = 11 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -87,6 +87,9 @@ # CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer + +# use '-fno-strict-aliasing', but only if the compiler can take it +CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi) ifdef CONFIG_SMP CFLAGS += -D__SMP__ diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile --- v2.3.10/linux/arch/alpha/kernel/Makefile Sun Jan 10 09:59:54 1999 +++ linux/arch/alpha/kernel/Makefile Mon Jul 12 07:49:36 1999 @@ -105,7 +105,7 @@ endif # Device support -ifdef CONFIG_ALPHA_MIATA +ifneq ($(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),) O_OBJS += es1888.o endif ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),) diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.3.10/linux/arch/alpha/kernel/alpha_ksyms.c Tue Jun 22 10:46:52 1999 +++ linux/arch/alpha/kernel/alpha_ksyms.c Mon Jul 12 07:49:36 1999 @@ -48,8 +48,6 @@ extern void __remqu (void); EXPORT_SYMBOL(alpha_mv); -EXPORT_SYMBOL(local_bh_count); -EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(disable_irq_nosync); @@ -178,6 +176,9 @@ EXPORT_SYMBOL(write_lock); EXPORT_SYMBOL(read_lock); #endif +#else /* __SMP__ */ +EXPORT_SYMBOL(__local_bh_count); +EXPORT_SYMBOL(__local_irq_count); #endif /* __SMP__ */ /* diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/core_pyxis.c linux/arch/alpha/kernel/core_pyxis.c --- v2.3.10/linux/arch/alpha/kernel/core_pyxis.c Mon Oct 12 11:40:12 1998 +++ linux/arch/alpha/kernel/core_pyxis.c Mon Jul 12 07:49:36 1999 @@ -425,19 +425,24 @@ { /* * Set up the PCI->physical memory translation windows. - * For now, windows 1,2 and 3 are disabled. In the future, we may + * For now, windows 2 and 3 are disabled. In the future, we may * want to use them to do scatter/gather DMA. * - * Window 0 goes at 1 GB and is 1 GB large. + * Window 0 goes at 2 GB and is 1 GB large. + * Window 1 goes at 3 GB and is 1 GB large. */ - *(vuip)PYXIS_W0_BASE = 1U | (PYXIS_DMA_WIN_BASE_DEFAULT & 0xfff00000U); + *(vuip)PYXIS_W0_BASE = PYXIS_DMA_WIN_BASE_DEFAULT | 1UL; *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; *(vuip)PYXIS_T0_BASE = 0; - *(vuip)PYXIS_W1_BASE = 0x0 ; - *(vuip)PYXIS_W2_BASE = 0x0 ; - *(vuip)PYXIS_W3_BASE = 0x0 ; + *(vuip)PYXIS_W1_BASE = (PYXIS_DMA_WIN_BASE_DEFAULT + + PYXIS_DMA_WIN_SIZE_DEFAULT) | 1U; + *(vuip)PYXIS_W1_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; + *(vuip)PYXIS_T1_BASE = PYXIS_DMA_WIN_SIZE_DEFAULT; + + *(vuip)PYXIS_W2_BASE = 0x0; + *(vuip)PYXIS_W3_BASE = 0x0; mb(); } diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/es1888.c linux/arch/alpha/kernel/es1888.c --- v2.3.10/linux/arch/alpha/kernel/es1888.c Sun Aug 9 12:09:05 1998 +++ linux/arch/alpha/kernel/es1888.c Mon Jul 12 07:49:36 1999 @@ -32,6 +32,7 @@ continue; inb(0x022a); /* pause */ outb(0xc6, 0x022c); /* enable extended mode */ + inb(0x022a); /* pause, also forces the write */ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ continue; outb(0xb1, 0x022c); /* setup for write to Interrupt CR */ @@ -44,4 +45,5 @@ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ continue; outb(0x18, 0x022c); /* set DMA channel 1 */ + inb(0x022c); /* force the write */ } diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c --- v2.3.10/linux/arch/alpha/kernel/irq.c Fri May 14 12:41:22 1999 +++ linux/arch/alpha/kernel/irq.c Mon Jul 12 07:49:36 1999 @@ -35,9 +35,12 @@ #define vulp volatile unsigned long * #define vuip volatile unsigned int * -unsigned int local_irq_count[NR_CPUS]; -unsigned int local_bh_count[NR_CPUS]; -unsigned long hardirq_no[NR_CPUS]; +/* Only uniprocessor needs this IRQ/BH locking depth, on SMP it lives + in the per-cpu structure for cache reasons. */ +#ifndef __SMP__ +int __local_irq_count; +int __local_bh_count; +#endif #if NR_IRQS > 64 # error Unable to handle more than 64 irq levels. @@ -384,6 +387,8 @@ static void show(char * str, void *where); +#define SYNC_OTHER_CPUS(x) udelay((x)+1); + static inline void wait_on_irq(int cpu, void *where) { @@ -397,8 +402,8 @@ * already executing in one.. */ if (!atomic_read(&global_irq_count)) { - if (local_bh_count[cpu] || - !atomic_read(&global_bh_count)) + if (local_bh_count(cpu) + || !atomic_read(&global_bh_count)) break; } @@ -412,19 +417,15 @@ count = MAXCOUNT; } __sti(); -#if 0 - SYNC_OTHER_CORES(cpu); -#else - udelay(cpu+1); -#endif + SYNC_OTHER_CPUS(cpu); __cli(); if (atomic_read(&global_irq_count)) continue; - if (global_irq_lock.lock) + if (spin_is_locked(&global_irq_lock)) continue; - if (!local_bh_count[cpu] && - atomic_read(&global_bh_count)) + if (!local_bh_count(cpu) + && atomic_read(&global_bh_count)) continue; if (spin_trylock(&global_irq_lock)) break; @@ -469,14 +470,14 @@ void __global_cli(void) { - int cpu; + int cpu = smp_processor_id(); void *where = __builtin_return_address(0); /* * Maximize ipl. If ipl was previously 0 and if this thread * is not in an irq, then take global_irq_lock. */ - if ((swpipl(7) == 0) && !local_irq_count[cpu = smp_processor_id()]) + if (swpipl(7) == 0 && !local_irq_count(cpu)) get_irqlock(cpu, where); } @@ -485,9 +486,8 @@ { int cpu = smp_processor_id(); - if (!local_irq_count[cpu]) { + if (!local_irq_count(cpu)) release_irqlock(cpu); - } __sti(); } @@ -512,7 +512,7 @@ retval = 2 + local_enabled; /* Check for global flags if we're not in an interrupt. */ - if (!local_irq_count[cpu]) { + if (!local_irq_count(cpu)) { if (local_enabled) retval = 1; if (global_irq_holder == cpu) @@ -550,7 +550,7 @@ #define STUCK \ if (!--stuck) { \ printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n", \ - irq, cpu,global_irq_holder); \ + irq, cpu, global_irq_holder); \ stuck = INIT_STUCK; \ } @@ -566,11 +566,11 @@ hardirq_enter(cpu, irq); barrier(); - while (global_irq_lock.lock) { + while (spin_is_locked(&global_irq_lock)) { if (cpu == global_irq_holder) { - int globl_locked = global_irq_lock.lock; + int globl_locked = spin_is_locked(&global_irq_lock); int globl_icount = atomic_read(&global_irq_count); - int local_count = local_irq_count[cpu]; + int local_count = local_irq_count(cpu); /* It is very important that we load the state variables before we do the first call to @@ -609,19 +609,16 @@ #endif int cpu = smp_processor_id(); - int global_count = atomic_read(&global_irq_count); - int local_count0 = local_irq_count[0]; - int local_count1 = local_irq_count[1]; - long hardirq_no0 = hardirq_no[0]; - long hardirq_no1 = hardirq_no[1]; - printk("\n%s, CPU %d: %p\n", str, cpu, where); - printk("irq: %d [%d(0x%016lx) %d(0x%016lx)]\n", global_count, - local_count0, hardirq_no0, local_count1, hardirq_no1); + printk("irq: %d [%d %d]\n", + atomic_read(&global_irq_count), + cpu_data[0].irq_count, + cpu_data[1].irq_count); printk("bh: %d [%d %d]\n", - atomic_read(&global_bh_count), local_bh_count[0], - local_bh_count[1]); + atomic_read(&global_bh_count), + cpu_data[0].bh_count, + cpu_data[1].bh_count); #if 0 stack = (unsigned long *) &str; for (i = 40; i ; i--) { @@ -644,6 +641,7 @@ count = ~0; } /* nothing .. wait for the other bh's to go away */ + barrier(); } while (atomic_read(&global_bh_count) != 0); } @@ -658,12 +656,8 @@ void synchronize_bh(void) { - if (atomic_read(&global_bh_count)) { - int cpu = smp_processor_id(); - if (!local_irq_count[cpu] && !local_bh_count[cpu]) { - wait_on_bh(); - } - } + if (atomic_read(&global_bh_count) && !in_interrupt()) + wait_on_bh(); } /* @@ -680,6 +674,8 @@ void synchronize_irq(void) { +#if 0 + /* Joe's version. */ int cpu = smp_processor_id(); int local_count; int global_count; @@ -688,7 +684,7 @@ mb(); do { - local_count = local_irq_count[cpu]; + local_count = local_irq_count(cpu); global_count = atomic_read(&global_irq_count); if (DEBUG_SYNCHRONIZE_IRQ && (--countdown == 0)) { printk("%d:%d/%d\n", cpu, local_count, global_count); @@ -696,12 +692,19 @@ break; } } while (global_count != local_count); +#else + /* Jay's version. */ + if (atomic_read(&global_irq_count)) { + cli(); + sti(); + } +#endif } #else /* !__SMP__ */ -#define irq_enter(cpu, irq) (++local_irq_count[cpu]) -#define irq_exit(cpu, irq) (--local_irq_count[cpu]) +#define irq_enter(cpu, irq) (++local_irq_count(cpu)) +#define irq_exit(cpu, irq) (--local_irq_count(cpu)) #endif /* __SMP__ */ @@ -868,31 +871,23 @@ unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs) { - unsigned long flags; - switch (type) { case 0: #ifdef __SMP__ - __save_and_cli(flags); handle_ipi(®s); - __restore_flags(flags); return; #else printk("Interprocessor interrupt? You must be kidding\n"); #endif break; case 1: - __save_and_cli(flags); handle_irq(RTC_IRQ, -1, ®s); - __restore_flags(flags); return; case 2: alpha_mv.machine_check(vector, la_ptr, ®s); return; case 3: - __save_and_cli(flags); alpha_mv.device_interrupt(vector, ®s); - __restore_flags(flags); return; case 4: perf_irq(vector, ®s); diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/irq.h linux/arch/alpha/kernel/irq.h --- v2.3.10/linux/arch/alpha/kernel/irq.h Wed Dec 30 15:06:22 1998 +++ linux/arch/alpha/kernel/irq.h Mon Jul 12 07:49:36 1999 @@ -31,3 +31,19 @@ #define TIMER_IRQ RTC_IRQ /* timer is the rtc */ #endif +extern char _stext; +static inline void alpha_do_profile (unsigned long pc) +{ + if (prof_buffer && current->pid) { + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Don't ignore out-of-bounds PC values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len - 1) + pc = prof_len - 1; + atomic_inc((atomic_t *)&prof_buffer[pc]); + } +} diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.3.10/linux/arch/alpha/kernel/osf_sys.c Wed Jun 30 13:38:18 1999 +++ linux/arch/alpha/kernel/osf_sys.c Mon Jul 12 07:49:36 1999 @@ -927,6 +927,7 @@ return -EINVAL; cpu = (struct percpu_struct*) ((char*)hwrpb + hwrpb->processor_offset); + w = cpu->type; if (put_user(w, (unsigned long *)buffer)) return -EFAULT; return 1; diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.3.10/linux/arch/alpha/kernel/process.c Tue Jun 22 10:46:52 1999 +++ linux/arch/alpha/kernel/process.c Mon Jul 12 07:49:36 1999 @@ -76,7 +76,7 @@ } #ifdef __SMP__ -void +int cpu_idle(void *unused) { /* An endless idle loop with no priority at all. */ @@ -329,7 +329,6 @@ p->tss.ksp = (unsigned long) childstack; p->tss.pal_flags = 1; /* set FEN, clear everything else */ p->tss.flags = current->tss.flags; - p->tss.mm_context = p->tss.asn = 0; return 0; } diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h --- v2.3.10/linux/arch/alpha/kernel/proto.h Tue Jun 22 10:46:52 1999 +++ linux/arch/alpha/kernel/proto.h Mon Jul 12 07:49:36 1999 @@ -193,7 +193,7 @@ /* process.c */ extern void generic_kill_arch (int mode, char *reboot_cmd); -extern void cpu_idle(void *) __attribute__((noreturn)); +extern int cpu_idle(void *) __attribute__((noreturn)); /* ptrace.c */ extern int ptrace_set_bpt (struct task_struct *child); diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c --- v2.3.10/linux/arch/alpha/kernel/ptrace.c Thu Jul 8 15:42:19 1999 +++ linux/arch/alpha/kernel/ptrace.c Mon Jul 12 07:49:36 1999 @@ -231,7 +231,6 @@ int a4, int a5, struct pt_regs regs) { struct task_struct *child; - unsigned long tmp; long ret; lock_kernel(); diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c --- v2.3.10/linux/arch/alpha/kernel/smp.c Thu Jul 8 15:42:19 1999 +++ linux/arch/alpha/kernel/smp.c Mon Jul 12 07:49:36 1999 @@ -97,6 +97,8 @@ cpu_data[cpuid].loops_per_sec = loops_per_sec; cpu_data[cpuid].last_asn = (cpuid << WIDTH_HARDWARE_ASN) + ASN_FIRST_VERSION; + cpu_data[cpuid].irq_count = 0; + cpu_data[cpuid].bh_count = 0; } /* @@ -107,12 +109,6 @@ { cpu_data[cpuid].prof_counter = 1; cpu_data[cpuid].prof_multiplier = 1; - -#ifdef NOT_YET_PROFILING - load_profile_irq(mid_xlate[cpu], lvl14_resolution); - if (cpu == smp_boot_cpuid) - enable_pil_irq(14); -#endif } /* @@ -586,14 +582,12 @@ smp_percpu_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); - int user = user_mode(regs); + unsigned long user = user_mode(regs); struct cpuinfo_alpha *data = &cpu_data[cpu]; -#ifdef NOT_YET_PROFILING - clear_profile_irq(mid_xlate[cpu]); + /* Record kernel PC. */ if (!user) alpha_do_profile(regs->pc); -#endif if (!--data->prof_counter) { /* We need to make like a normal interrupt -- otherwise @@ -630,28 +624,7 @@ int __init setup_profiling_timer(unsigned int multiplier) { -#ifdef NOT_YET_PROFILING - int i; - unsigned long flags; - - /* Prevent level14 ticker IRQ flooding. */ - if((!multiplier) || (lvl14_resolution / multiplier) < 500) - return -EINVAL; - - save_and_cli(flags); - for (i = 0; i < NR_CPUS; i++) { - if (cpu_present_mask & (1L << i)) { - load_profile_irq(mid_xlate[i], - lvl14_resolution / multiplier); - prof_multiplier[i] = multiplier; - } - } - restore_flags(flags); - - return 0; -#else return -EINVAL; -#endif } @@ -893,9 +866,11 @@ void flush_tlb_mm(struct mm_struct *mm) { - if (mm == current->mm) + if (mm == current->mm) { flush_tlb_current(mm); - else + if (atomic_read(&mm->count) == 1) + return; + } else flush_tlb_other(mm); if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) { @@ -923,15 +898,17 @@ struct flush_tlb_page_struct data; struct mm_struct *mm = vma->vm_mm; + if (mm == current->mm) { + flush_tlb_current_page(mm, vma, addr); + if (atomic_read(&mm->count) == 1) + return; + } else + flush_tlb_other(mm); + data.vma = vma; data.mm = mm; data.addr = addr; - if (mm == current->mm) - flush_tlb_current_page(mm, vma, addr); - else - flush_tlb_other(mm); - if (smp_call_function(ipi_flush_tlb_page, &data, 1, 1)) { printk(KERN_CRIT "flush_tlb_page: timed out\n"); } diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/sys_dp264.c linux/arch/alpha/kernel/sys_dp264.c --- v2.3.10/linux/arch/alpha/kernel/sys_dp264.c Tue Jun 22 10:46:52 1999 +++ linux/arch/alpha/kernel/sys_dp264.c Mon Jul 12 07:49:36 1999 @@ -393,8 +393,8 @@ { layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); common_pci_fixup(monet_map_irq, monet_swizzle); - /* es1888_init(); */ /* later? */ SMC669_Init(1); + es1888_init(); } static void __init diff -u --recursive --new-file v2.3.10/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c --- v2.3.10/linux/arch/alpha/kernel/time.c Tue Jun 22 10:46:52 1999 +++ linux/arch/alpha/kernel/time.c Mon Jul 12 07:49:36 1999 @@ -94,6 +94,10 @@ smp_percpu_timer_interrupt(regs); if (smp_processor_id() != smp_boot_cpuid) return; +#else + /* Not SMP, do kernel PC profiling here. */ + if (!user_mode(regs)) + alpha_do_profile(regs->pc); #endif write_lock(&xtime_lock); diff -u --recursive --new-file v2.3.10/linux/arch/alpha/math-emu/ieee-math.c linux/arch/alpha/math-emu/ieee-math.c --- v2.3.10/linux/arch/alpha/math-emu/ieee-math.c Mon May 10 09:55:21 1999 +++ linux/arch/alpha/math-emu/ieee-math.c Mon Jul 12 07:49:36 1999 @@ -704,20 +704,21 @@ * FPCR_INV if invalid operation occurred, etc. */ unsigned long -ieee_CVTQT (int f, unsigned long a, unsigned long *b) +ieee_CVTQT (int f, long a, unsigned long *b) { EXTENDED op_b; - op_b.s = 0; - op_b.f[0] = a; - op_b.f[1] = 0; - if (sign(a) < 0) { - op_b.s = 1; - op_b.f[0] = -a; + if (a != 0) { + op_b.s = (a < 0 ? 1 : 0); + op_b.f[0] = (a < 0 ? -a : a); + op_b.f[1] = 0; + op_b.e = 55; + normalize(&op_b); + return round_t_ieee(f, &op_b, b); + } else { + *b = 0; + return 0; } - op_b.e = 55; - normalize(&op_b); - return round_t_ieee(f, &op_b, b); } diff -u --recursive --new-file v2.3.10/linux/arch/alpha/math-emu/ieee-math.h linux/arch/alpha/math-emu/ieee-math.h --- v2.3.10/linux/arch/alpha/math-emu/ieee-math.h Mon May 10 09:55:21 1999 +++ linux/arch/alpha/math-emu/ieee-math.h Mon Jul 12 07:49:36 1999 @@ -20,7 +20,7 @@ extern unsigned long ieee_CVTST (int rm, unsigned long a, unsigned long *b); extern unsigned long ieee_CVTTS (int rm, unsigned long a, unsigned long *b); extern unsigned long ieee_CVTQS (int rm, unsigned long a, unsigned long *b); -extern unsigned long ieee_CVTQT (int rm, unsigned long a, unsigned long *b); +extern unsigned long ieee_CVTQT (int rm, long a, unsigned long *b); extern unsigned long ieee_CVTTQ (int rm, unsigned long a, unsigned long *b); extern unsigned long ieee_CMPTEQ (unsigned long a, unsigned long b, diff -u --recursive --new-file v2.3.10/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c --- v2.3.10/linux/arch/alpha/mm/fault.c Tue Jun 22 10:46:52 1999 +++ linux/arch/alpha/mm/fault.c Mon Jul 12 07:49:36 1999 @@ -41,7 +41,7 @@ get_new_mmu_context(struct task_struct *p, struct mm_struct *mm) { unsigned long new = __get_new_mmu_context(p, mm); - p->tss.mm_context = new; + mm->context = new; p->tss.asn = new & HARDWARE_ASN_MASK; } diff -u --recursive --new-file v2.3.10/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c --- v2.3.10/linux/arch/alpha/mm/init.c Wed Jun 30 13:38:18 1999 +++ linux/arch/alpha/mm/init.c Mon Jul 12 07:49:36 1999 @@ -173,7 +173,7 @@ extern unsigned long free_area_init(unsigned long, unsigned long); -static inline struct thread_struct * +static inline unsigned long load_PCB(struct thread_struct * pcb) { register unsigned long sp __asm__("$30"); @@ -192,7 +192,7 @@ unsigned long newptbr; struct memclust_struct * cluster; struct memdesc_struct * memdesc; - struct thread_struct *original_pcb_ptr; + unsigned long original_pcb_ptr; /* initialize mem_map[] */ start_mem = free_area_init(start_mem, end_mem); @@ -246,11 +246,11 @@ since KSEG values also happen to work, folks get confused. Check this here. */ - if ((unsigned long)original_pcb_ptr < PAGE_OFFSET) { - original_pcb_ptr = (struct thread_struct *) - phys_to_virt((unsigned long) original_pcb_ptr); + if (original_pcb_ptr < PAGE_OFFSET) { + original_pcb_ptr = (unsigned long) + phys_to_virt(original_pcb_ptr); } - original_pcb = *original_pcb_ptr; + original_pcb = *(struct thread_struct *) original_pcb_ptr; return start_mem; } diff -u --recursive --new-file v2.3.10/linux/arch/arm/def-configs/a5k linux/arch/arm/def-configs/a5k --- v2.3.10/linux/arch/arm/def-configs/a5k Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/a5k Mon Jul 19 09:52:57 1999 @@ -0,0 +1,425 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +CONFIG_ARCH_A5K=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_ACORN=y +# CONFIG_ISA_DMA is not set +# CONFIG_CPU_32 is not set +CONFIG_CPU_26=y +# CONFIG_CPU_ARM2 is not set +CONFIG_CPU_ARM3=y +# CONFIG_CPU_ARM6 is not set +# CONFIG_CPU_ARM7 is not set +# CONFIG_CPU_SA110 is not set +CONFIG_PAGESIZE_32=y +# CONFIG_PAGESIZE_16 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_TEXT_SECTIONS is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# General setup +# +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_NWFPE is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=m +# CONFIG_BINFMT_MISC is not set +CONFIG_PARPORT=y +CONFIG_PARPORT_PC=y + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=y +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Acorn-specific block devices +# +CONFIG_BLK_DEV_IDE_CARDS=y +CONFIG_BLK_DEV_IDE_ICSIDE=y +# CONFIG_BLK_DEV_IDE_RAPIDE is not set +# CONFIG_BLK_DEV_FD1772 is not set +CONFIG_BLK_DEV_MFM=m +CONFIG_BLK_DEV_MFM_AUTODETECT=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_SERIAL_EXTENDED is not set +CONFIG_ATOMWIDE_SERIAL=y +CONFIG_DUALSP_SERIAL=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +CONFIG_PRINTER=y +CONFIG_PRINTER_READBACK=y +CONFIG_MOUSE=y + +# +# Mice +# +# CONFIG_ATIXL_BUSMOUSE is not set +# CONFIG_BUSMOUSE is not set +# CONFIG_MS_BUSMOUSE is not set +# CONFIG_PSMOUSE is not set +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_KBDMOUSE=y + +# +# Console drivers +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_ACORN=y +# CONFIG_FB_MATROX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_MFB=y +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_FONT_ACORN_8x8=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_FIREWALL is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +# CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# +# CONFIG_INET_RARP is not set +# CONFIG_SKB_LARGE is not set +# CONFIG_IPV6 is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set +# CONFIG_CPU_IS_SLOW is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA subsystem support +# +# CONFIG_IRDA is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_NET_ETHERNET=y +CONFIG_ARM_ETHER1=y +CONFIG_ARM_ETHER3=y +# CONFIG_ARM_ETHERH is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_RTL8139 is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_EISA is not set +# CONFIG_NET_POCKET is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_DLCI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_RADIO is not set +# CONFIG_TR is not set +# CONFIG_SHAPER is not set +# CONFIG_HOSTESS_SV11 is not set +# CONFIG_COSA is not set +# CONFIG_RCPCI is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +CONFIG_SCSI_PPA=m +# CONFIG_SCSI_IMM is not set +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_SEAGATE is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_DEBUG is not set +CONFIG_SCSI_ACORNSCSI_3=y +CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y +CONFIG_SCSI_ACORNSCSI_SYNC=y +CONFIG_SCSI_ARXESCSI=m +# CONFIG_SCSI_CUMANA_2 is not set +CONFIG_SCSI_EESOXSCSI=y +# CONFIG_SCSI_POWERTECSCSI is not set + +# +# The following drivers are not fully supported +# +# CONFIG_SCSI_CUMANA_1 is not set +# CONFIG_SCSI_ECOSCSI is not set +# CONFIG_SCSI_OAK1 is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_ADFS_FS=y +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=m +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFSD=y +# CONFIG_NFSD_SUN is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# +# CONFIG_OSF_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +CONFIG_ACORN_PARTITION=y +CONFIG_ACORN_PARTITION_ADFS=y +CONFIG_ACORN_PARTITION_ICS=y +CONFIG_ACORN_PARTITION_POWERTEC=y +CONFIG_ACORN_PARTITION_RISCIX=y +CONFIG_NLS=y + +# +# Native Language Support +# +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_INFO is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_NO_PGT_CACHE=y +# CONFIG_DEBUG_LL is not set diff -u --recursive --new-file v2.3.10/linux/arch/arm/def-configs/ebsa110 linux/arch/arm/def-configs/ebsa110 --- v2.3.10/linux/arch/arm/def-configs/ebsa110 Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/ebsa110 Mon Jul 19 09:52:57 1999 @@ -0,0 +1,308 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +CONFIG_ARCH_EBSA110=y +# CONFIG_FOOTBRIDGE is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_ISA_DMA is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM2 is not set +# CONFIG_CPU_ARM3 is not set +# CONFIG_CPU_ARM6 is not set +# CONFIG_CPU_ARM7 is not set +CONFIG_CPU_SA110=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_TEXT_SECTIONS is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# General setup +# +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_NWFPE is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=m +# CONFIG_BINFMT_MISC is not set +CONFIG_PARPORT=y +CONFIG_PARPORT_PC=y +CONFIG_CMDLINE="root=/dev/nfs rw mem=16M console=ttyS1,38400n8" +CONFIG_LEDS=y + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_IDE is not set + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_ONLY is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=y +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +CONFIG_SERIAL_EXTENDED=y +# CONFIG_SERIAL_MANY_PORTS is not set +# CONFIG_SERIAL_SHARE_IRQ is not set +# CONFIG_SERIAL_DETECT_IRQ is not set +# CONFIG_SERIAL_MULTIPORT is not set +# CONFIG_HUB6 is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +CONFIG_PRINTER=m +CONFIG_PRINTER_READBACK=y +CONFIG_MOUSE=y + +# +# Mice +# +# CONFIG_ATIXL_BUSMOUSE is not set +# CONFIG_BUSMOUSE is not set +# CONFIG_MS_BUSMOUSE is not set +# CONFIG_PSMOUSE is not set +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_QIC02_TAPE is not set +CONFIG_WATCHDOG=y + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_WDT is not set +CONFIG_SOFT_WATCHDOG=y +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# +# Networking options +# +CONFIG_PACKET=m +# CONFIG_NETLINK is not set +CONFIG_FIREWALL=y +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +CONFIG_IP_FIREWALL=y +CONFIG_IP_ALWAYS_DEFRAG=y +# CONFIG_IP_TRANSPARENT_PROXY is not set +CONFIG_IP_MASQUERADE=y + +# +# Protocol-specific masquerading support will be built as modules. +# +CONFIG_IP_MASQUERADE_ICMP=y + +# +# Protocol-specific masquerading support will be built as modules. +# +# CONFIG_IP_MASQUERADE_MOD is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +CONFIG_SYN_COOKIES=y + +# +# (it is safe to leave these untouched) +# +# CONFIG_INET_RARP is not set +# CONFIG_SKB_LARGE is not set +# CONFIG_IPV6 is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set +# CONFIG_CPU_IS_SLOW is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA subsystem support +# +# CONFIG_IRDA is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_NET_ETHERNET=y +CONFIG_ARM_AM79C961A=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_RTL8139 is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_EISA is not set +# CONFIG_NET_POCKET is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_DLCI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=y + +# +# CCP compressors for PPP are only built as modules. +# +# CONFIG_SLIP is not set +# CONFIG_NET_RADIO is not set +# CONFIG_TR is not set +# CONFIG_SHAPER is not set +# CONFIG_HOSTESS_SV11 is not set +# CONFIG_COSA is not set +# CONFIG_RCPCI is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +CONFIG_MINIX_FS=y +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_EXT2_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# +# CONFIG_OSF_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ACORN_PARTITION is not set +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_ARTHUR is not set +# CONFIG_DEBUG_LL is not set diff -u --recursive --new-file v2.3.10/linux/arch/arm/def-configs/footbridge linux/arch/arm/def-configs/footbridge --- v2.3.10/linux/arch/arm/def-configs/footbridge Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/footbridge Mon Jul 19 09:52:57 1999 @@ -0,0 +1,493 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +CONFIG_FOOTBRIDGE=y +CONFIG_HOST_FOOTBRIDGE=y +# CONFIG_ADDIN_FOOTBRIDGE is not set +CONFIG_ARCH_EBSA285=y +# CONFIG_CATS is not set +CONFIG_ARCH_NETWINDER=y +# CONFIG_ARCH_ACORN is not set +CONFIG_PCI=y +CONFIG_ISA_DMA=y +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM2 is not set +# CONFIG_CPU_ARM3 is not set +# CONFIG_CPU_ARM6 is not set +# CONFIG_CPU_ARM7 is not set +CONFIG_CPU_SA110=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_ALIGNMENT_TRAP is not set +# CONFIG_TEXT_SECTIONS is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# General setup +# +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_NWFPE=y +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set +CONFIG_PARPORT=y +CONFIG_PARPORT_PC=y +CONFIG_CMDLINE="root=/dev/hda2 ro mem=32M parport=0x378,7 ide0=autotune" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +# CONFIG_LEDS_CPU is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_BLK_DEV_IDEDMA=y +CONFIG_BLK_DEV_OFFBOARD=y +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_VIA82C586 is not set +# CONFIG_BLK_DEV_CMD646 is not set +CONFIG_BLK_DEV_SL82C105=y +# CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_STRIPED=m +CONFIG_MD_MIRRORING=m +CONFIG_MD_RAID5=m +CONFIG_BLK_DEV_RAM=y +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=y +CONFIG_PARIDE=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +# CONFIG_BLK_DEV_HD is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +CONFIG_PRINTER=m +CONFIG_PRINTER_READBACK=y +CONFIG_MOUSE=y + +# +# Mice +# +# CONFIG_ATIXL_BUSMOUSE is not set +# CONFIG_BUSMOUSE is not set +# CONFIG_MS_BUSMOUSE is not set +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_QIC02_TAPE is not set +CONFIG_WATCHDOG=y + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_WDT is not set +CONFIG_SOFT_WATCHDOG=y +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +CONFIG_DS1620=y +CONFIG_NWBUTTON=y +CONFIG_NWBUTTON_REBOOT=y +CONFIG_NWFLASH=m +# CONFIG_NVRAM is not set +CONFIG_RTC=y + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# +# Console drivers +# +CONFIG_VGA_CONSOLE=y +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_PM2 is not set +CONFIG_FB_CYBER2000=y +# CONFIG_FB_MATROX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FBCON_ADVANCED=y +# CONFIG_FBCON_MFB is not set +# CONFIG_FBCON_CFB2 is not set +# CONFIG_FBCON_CFB4 is not set +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +# CONFIG_FBCON_CFB32 is not set +# CONFIG_FBCON_AFB is not set +# CONFIG_FBCON_ILBM is not set +# CONFIG_FBCON_IPLAN2P2 is not set +# CONFIG_FBCON_IPLAN2P4 is not set +# CONFIG_FBCON_IPLAN2P8 is not set +# CONFIG_FBCON_MAC is not set +CONFIG_FBCON_VGA=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +CONFIG_FONT_ACORN_8x8=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_NETLINK is not set +# CONFIG_FIREWALL is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +CONFIG_IP_ALIAS=y +# CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# +# CONFIG_INET_RARP is not set +CONFIG_SKB_LARGE=y +# CONFIG_IPV6 is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set +# CONFIG_CPU_IS_SLOW is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA subsystem support +# +# CONFIG_IRDA is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +CONFIG_NET_VENDOR_3COM=y +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set +# CONFIG_EL3 is not set +# CONFIG_3C515 is not set +CONFIG_VORTEX=y +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_RTL8139 is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_EISA=y +# CONFIG_PCNET32 is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_DE4X5 is not set +CONFIG_DEC_ELCP=m +# CONFIG_DGRS is not set +# CONFIG_EEXPRESS_PRO100 is not set +# CONFIG_LNE390 is not set +# CONFIG_NE3210 is not set +CONFIG_NE2K_PCI=y +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_ES3210 is not set +# CONFIG_EPIC100 is not set +# CONFIG_ZNET is not set +# CONFIG_NET_POCKET is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_DLCI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=m + +# +# CCP compressors for PPP are only built as modules. +# +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y +# CONFIG_NET_RADIO is not set +# CONFIG_TR is not set +# CONFIG_SHAPER is not set +# CONFIG_HOSTESS_SV11 is not set +# CONFIG_COSA is not set +# CONFIG_RCPCI is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Sound +# +CONFIG_SOUND=m +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +CONFIG_SOUND_OSS=m +# CONFIG_SOUND_PAS is not set +CONFIG_SOUND_SB=m +CONFIG_SOUND_ADLIB=m +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_WAVEFRONT is not set +# CONFIG_SOUND_CS4232 is not set +# CONFIG_SOUND_OPL3SA2 is not set +# CONFIG_SOUND_MAUI is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_SOFTOSS is not set +# CONFIG_SOUND_YM3812 is not set +# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_UART6850 is not set +# CONFIG_SOUND_VIDC is not set +CONFIG_SOUND_WAVEARTIST=m +CONFIG_WAVEARTIST_BASE=250 +CONFIG_WAVEARTIST_IRQ=12 +CONFIG_WAVEARTIST_DMA=3 +CONFIG_WAVEARTIST_DMA2=7 + +# +# Additional low level sound drivers +# +# CONFIG_LOWLEVEL_SOUND is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_ADFS_FS=y +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=m +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NFSD=m +# CONFIG_NFSD_SUN is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# +# CONFIG_OSF_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +CONFIG_ACORN_PARTITION=y +CONFIG_ACORN_PARTITION_ADFS=y +# CONFIG_ACORN_PARTITION_ICS is not set +# CONFIG_ACORN_PARTITION_POWERTEC is not set +# CONFIG_ACORN_PARTITION_RISCIX is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +CONFIG_NLS_ISO8859_15=m +# CONFIG_NLS_KOI8_R is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_INFO is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_LL is not set diff -u --recursive --new-file v2.3.10/linux/arch/arm/def-configs/rpc linux/arch/arm/def-configs/rpc --- v2.3.10/linux/arch/arm/def-configs/rpc Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/rpc Mon Jul 19 09:52:57 1999 @@ -0,0 +1,471 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +CONFIG_ARCH_RPC=y +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_ACORN=y +# CONFIG_ISA_DMA is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM2 is not set +# CONFIG_CPU_ARM3 is not set +# CONFIG_CPU_ARM6 is not set +# CONFIG_CPU_ARM7 is not set +CONFIG_CPU_SA110=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_ALIGNMENT_TRAP is not set +# CONFIG_TEXT_SECTIONS is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# General setup +# +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_NWFPE is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PARPORT=y +CONFIG_PARPORT_PC=y + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_BLK_DEV_IDECD=y +CONFIG_BLK_DEV_IDETAPE=y +CONFIG_BLK_DEV_IDEFLOPPY=y +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=y +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Acorn-specific block devices +# +CONFIG_BLK_DEV_IDE_CARDS=y +CONFIG_BLK_DEV_IDE_ICSIDE=y +CONFIG_BLK_DEV_IDE_RAPIDE=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_SERIAL_EXTENDED is not set +CONFIG_ATOMWIDE_SERIAL=y +CONFIG_DUALSP_SERIAL=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +CONFIG_PRINTER=m +CONFIG_PRINTER_READBACK=y +CONFIG_MOUSE=y + +# +# Mice +# +# CONFIG_ATIXL_BUSMOUSE is not set +# CONFIG_BUSMOUSE is not set +# CONFIG_MS_BUSMOUSE is not set +# CONFIG_PSMOUSE is not set +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_RPCMOUSE=y + +# +# Console drivers +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_ACORN=y +# CONFIG_FB_MATROX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FBCON_ADVANCED=y +CONFIG_FBCON_MFB=y +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +CONFIG_FBCON_CFB32=y +# CONFIG_FBCON_AFB is not set +# CONFIG_FBCON_ILBM is not set +# CONFIG_FBCON_IPLAN2P2 is not set +# CONFIG_FBCON_IPLAN2P4 is not set +# CONFIG_FBCON_IPLAN2P8 is not set +# CONFIG_FBCON_MAC is not set +# CONFIG_FBCON_VGA is not set +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +CONFIG_FONT_ACORN_8x8=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_FIREWALL is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +# CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# +# CONFIG_INET_RARP is not set +CONFIG_SKB_LARGE=y +# CONFIG_IPV6 is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set +# CONFIG_CPU_IS_SLOW is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA subsystem support +# +# CONFIG_IRDA is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_NET_ETHERNET=y +CONFIG_ARM_ETHER1=m +CONFIG_ARM_ETHER3=m +CONFIG_ARM_ETHERH=m +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_RTL8139 is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_EISA is not set +# CONFIG_NET_POCKET is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_DLCI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=m + +# +# CCP compressors for PPP are only built as modules. +# +# CONFIG_SLIP is not set +# CONFIG_NET_RADIO is not set +# CONFIG_TR is not set +# CONFIG_SHAPER is not set +# CONFIG_HOSTESS_SV11 is not set +# CONFIG_COSA is not set +# CONFIG_RCPCI is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_SEAGATE is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_DEBUG is not set +CONFIG_SCSI_ACORNSCSI_3=m +CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y +CONFIG_SCSI_ACORNSCSI_SYNC=y +CONFIG_SCSI_ARXESCSI=m +CONFIG_SCSI_CUMANA_2=m +CONFIG_SCSI_EESOXSCSI=m +CONFIG_SCSI_POWERTECSCSI=m + +# +# The following drivers are not fully supported +# +CONFIG_SCSI_CUMANA_1=m +CONFIG_SCSI_OAK1=m + +# +# Sound +# +CONFIG_SOUND=m +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +CONFIG_SOUND_OSS=m +# CONFIG_SOUND_PAS is not set +# CONFIG_SOUND_SB is not set +# CONFIG_SOUND_ADLIB is not set +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_WAVEFRONT is not set +# CONFIG_SOUND_CS4232 is not set +# CONFIG_SOUND_OPL3SA2 is not set +# CONFIG_SOUND_MAUI is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_SOFTOSS is not set +# CONFIG_SOUND_YM3812 is not set +# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_UART6850 is not set +CONFIG_SOUND_VIDC=m +# CONFIG_SOUND_WAVEARTIST is not set + +# +# Additional low level sound drivers +# +# CONFIG_LOWLEVEL_SOUND is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_ADFS_FS=y +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFSD is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# +# CONFIG_OSF_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +CONFIG_ACORN_PARTITION=y +CONFIG_ACORN_PARTITION_ADFS=y +CONFIG_ACORN_PARTITION_ICS=y +CONFIG_ACORN_PARTITION_POWERTEC=y +CONFIG_ACORN_PARTITION_RISCIX=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_ISO8859_9=m +# CONFIG_NLS_ISO8859_15 is not set +CONFIG_NLS_KOI8_R=m + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_INFO is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_ARTHUR is not set +# CONFIG_DEBUG_LL is not set diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile --- v2.3.10/linux/arch/arm/kernel/Makefile Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/Makefile Mon Jul 19 09:52:57 1999 @@ -20,7 +20,7 @@ O_OBJS_a5k = dma-a5k.o iic.o fiq.o O_OBJS_rpc = dma-rpc.o iic.o fiq.o O_OBJS_ebsa110 = dma-dummy.o -O_OBJS_footbridge = dma-footbridge.o $(ISA_DMA_OBJS) +O_OBJS_footbridge = dma-footbridge.o $(ISA_DMA_OBJS) isa.o O_OBJS_nexuspci = dma-dummy.o OX_OBJS_arc = dma.o diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c --- v2.3.10/linux/arch/arm/kernel/armksyms.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/armksyms.c Mon Jul 19 09:52:57 1999 @@ -116,10 +116,6 @@ EXPORT_SYMBOL(insw); EXPORT_SYMBOL(insl); -EXPORT_SYMBOL(_memcpy_fromio); -EXPORT_SYMBOL(_memcpy_toio); -EXPORT_SYMBOL(_memset_io); - /* address translation */ #ifndef __virt_to_phys__is_a_macro EXPORT_SYMBOL(__virt_to_phys); diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S --- v2.3.10/linux/arch/arm/kernel/calls.S Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/calls.S Mon Jul 19 09:52:57 1999 @@ -157,8 +157,8 @@ /* 145 */ .long SYMBOL_NAME(sys_readv) .long SYMBOL_NAME(sys_writev) .long SYMBOL_NAME(sys_getsid) - .long SYMBOL_NAME(sys_ni_syscall) - .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_fdatasync) + .long SYMBOL_NAME(sys_sysctl) /* 150 */ .long SYMBOL_NAME(sys_mlock) .long SYMBOL_NAME(sys_munlock) .long SYMBOL_NAME(sys_mlockall) diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/dma-arc.c linux/arch/arm/kernel/dma-arc.c --- v2.3.10/linux/arch/arm/kernel/dma-arc.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/dma-arc.c Mon Jul 19 09:52:57 1999 @@ -100,7 +100,7 @@ int arch_get_dma_residue(dmach_t channel, dma_t *dma) { switch (channel) { -#ifdef CONFIG_BLK_DEV_FD +#ifdef CONFIG_BLK_DEV_FD1772 case DMA_VIRTUAL_FLOPPY0: { /* Data DMA */ extern unsigned int fdc1772_bytestogo; diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S --- v2.3.10/linux/arch/arm/kernel/entry-armv.S Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/entry-armv.S Mon Jul 19 09:52:57 1999 @@ -244,6 +244,10 @@ movne \irqnr, #IRQ_PCI bne 1001f + tst \irqstat, #IRQ_MASK_DOORBELLHOST + movne \irqnr, #IRQ_DOORBELLHOST + bne 1001f + tst \irqstat, #IRQ_MASK_I2OINPOST movne \irqnr, #IRQ_I2OINPOST bne 1001f diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S --- v2.3.10/linux/arch/arm/kernel/entry-common.S Wed Jun 30 13:38:18 1999 +++ linux/arch/arm/kernel/entry-common.S Mon Jul 19 09:52:57 1999 @@ -132,7 +132,8 @@ SYMBOL_NAME(sys_syscall): eor r6, r0, #OS_NUMBER << 20 cmp r6, #NR_syscalls @ check range - ldmleib sp, {r0 - r4} @ get our args + add ip, sp, #4 + ldmleib ip, {r0 - r4} @ get our args strle r4, [sp] @ Put our arg on the stack ldrle pc, [r5, r6, lsl #2] mov r0, #-ENOSYS diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S --- v2.3.10/linux/arch/arm/kernel/head-armv.S Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/head-armv.S Mon Jul 19 09:52:57 1999 @@ -72,6 +72,8 @@ * r1 = 6 -> CATS * r1 = 7 -> tbox * r1 = 8 -> SA110/21285 as co-processor + * r1 = 9 -> CL-PS7110 system + * r1 = 12 -> SA1100 based system */ __entry: teq r0, #0 @ check for illegal entry... @@ -245,6 +247,12 @@ .long DC21285_ARMCSR_BASE @ Physical I/O base address .long 0x7cf00000 >> 18 @ Virtual I/O base address + @ SA1100 + .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0xc0000000 + .long 0xc0000000 + .long 0x80000000 @ IO mapping will change when kernel gets on its feet + .long 0x3800 + .LCProcTypes: @ ARM6 / 610 .long 0x41560600 .long 0xffffff00 @@ -266,9 +274,9 @@ b .Larmv3_flush_late @ arm v3 flush & ctrl late setup mov pc, lr - @ StrongARM - .long 0x4401a100 - .long 0xfffffff0 + @ StrongARM-110 and StrongARM-1100 + .long 0x4401a100 @ 4401a100 and 4401a110 + .long 0xffffffe0 .long 0x00000c02 b .Larmv4_flush_early b .Lsa_fastclock diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/hw-footbridge.c linux/arch/arm/kernel/hw-footbridge.c --- v2.3.10/linux/arch/arm/kernel/hw-footbridge.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/hw-footbridge.c Mon Jul 19 09:52:57 1999 @@ -866,8 +866,63 @@ #define DEFAULT_LEDS GPIO_GREEN_LED #endif +/* + * CATS stuff + */ +#ifdef CONFIG_CATS + +#define CONFIG_PORT 0x370 +#define INDEX_PORT (CONFIG_PORT) +#define DATA_PORT (CONFIG_PORT + 1) + +static void __init cats_hw_init(void) +{ + /* Set Aladdin to CONFIGURE mode */ + outb(0x51, CONFIG_PORT); + outb(0x23, CONFIG_PORT); + + /* Select logical device 3 */ + outb(0x07, INDEX_PORT); + outb(0x03, DATA_PORT); + + /* Set parallel port to DMA channel 3, ECP+EPP1.9, + enable EPP timeout */ + outb(0x74, INDEX_PORT); + outb(0x03, DATA_PORT); + + outb(0xf0, INDEX_PORT); + outb(0x0f, DATA_PORT); + + outb(0xf1, INDEX_PORT); + outb(0x07, DATA_PORT); + + /* Select logical device 4 */ + outb(0x07, INDEX_PORT); + outb(0x04, DATA_PORT); + + /* UART1 high speed mode */ + outb(0xf0, INDEX_PORT); + outb(0x02, DATA_PORT); + + /* Select logical device 5 */ + outb(0x07, INDEX_PORT); + outb(0x05, DATA_PORT); + + /* UART2 high speed mode */ + outb(0xf0, INDEX_PORT); + outb(0x02, DATA_PORT); + + /* Set Aladdin to RUN mode */ + outb(0xbb, CONFIG_PORT); +} + +#endif + __initfunc(void hw_init(void)) { + extern void register_isa_ports(unsigned int, unsigned int, + unsigned int); + register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0); #ifdef CONFIG_ARCH_NETWINDER /* * this ought to have a better home... @@ -888,6 +943,9 @@ spin_unlock_irqrestore(&gpio_lock, flags); } #endif + + if (machine_is_cats()) + cats_hw_init(); leds_event(led_start); } diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/isa.c linux/arch/arm/kernel/isa.c --- v2.3.10/linux/arch/arm/kernel/isa.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/isa.c Mon Jul 19 09:52:57 1999 @@ -0,0 +1,47 @@ +/* + * arch/arm/kernel/isa.c + * + * ISA shared memory and I/O port support + * + * Copyright (C) 1999 Phil Blundell + */ + +/* + * Nothing about this is actually ARM specific. One day we could move + * it into kernel/resource.c or some place like that. + */ + +#include +#include +#include +#include +#include +#include + +static unsigned int isa_membase, isa_portbase, isa_portshift; + +static ctl_table ctl_isa_vars[4] = { + {BUS_ISA_MEM_BASE, "membase", &isa_membase, + sizeof(isa_membase), 0444, NULL, &proc_dointvec}, + {BUS_ISA_PORT_BASE, "portbase", &isa_portbase, + sizeof(isa_portbase), 0444, NULL, &proc_dointvec}, + {BUS_ISA_PORT_SHIFT, "portshift", &isa_portshift, + sizeof(isa_portshift), 0444, NULL, &proc_dointvec}, + {0} +}; + +static struct ctl_table_header *isa_sysctl_header; + +static ctl_table ctl_isa[2] = {{BUS_ISA, "isa", NULL, 0, 0555, ctl_isa_vars}, + {0}}; +static ctl_table ctl_bus[2] = {{CTL_BUS, "bus", NULL, 0, 0555, ctl_isa}, + {0}}; + +__initfunc(void +register_isa_ports(unsigned int membase, unsigned int portbase, unsigned int portshift)) +{ + isa_membase = membase; + isa_portbase = portbase; + isa_portshift = portshift; + isa_sysctl_header = register_sysctl_table(ctl_bus, 0); +} diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/leds-footbridge.c linux/arch/arm/kernel/leds-footbridge.c --- v2.3.10/linux/arch/arm/kernel/leds-footbridge.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/leds-footbridge.c Mon Jul 19 09:52:57 1999 @@ -33,8 +33,9 @@ static char hw_led_state; static spinlock_t leds_lock = SPIN_LOCK_UNLOCKED; +extern spinlock_t gpio_lock; -#ifdef CONFIG_ARCH_EBSA285 +#ifdef CONFIG_FOOTBRIDGE static void __ebsa285_text ebsa285_leds_event(led_event_t evt) { @@ -226,8 +227,9 @@ init_leds_event(led_event_t evt)) { switch (machine_arch_type) { -#ifdef CONFIG_ARCH_EBSA285 +#ifdef CONFIG_FOOTBRIDGE case MACH_TYPE_EBSA285: + case MACH_TYPE_CO285: leds_event = ebsa285_leds_event; break; #endif diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c --- v2.3.10/linux/arch/arm/kernel/process.c Thu Jul 8 15:42:19 1999 +++ linux/arch/arm/kernel/process.c Mon Jul 19 09:52:57 1999 @@ -209,8 +209,7 @@ { int i; - for (i = 0; i < NR_DEBUGS; i++) - current->tss.debug[i] = 0; + memset(¤t->tss.debug, 0, sizeof(current->tss.debug)); current->used_math = 0; current->flags &= ~PF_USEDFPU; } @@ -255,8 +254,6 @@ */ void dump_thread(struct pt_regs * regs, struct user * dump) { - int i; - dump->magic = CMAGIC; dump->start_code = current->mm->start_code; dump->start_stack = regs->ARM_sp & ~(PAGE_SIZE - 1); @@ -265,8 +262,11 @@ dump->u_dsize = (current->mm->brk - current->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT; dump->u_ssize = 0; - for (i = 0; i < NR_DEBUGS; i++) - dump->u_debugreg[i] = current->tss.debug[i]; + dump->u_debugreg[0] = current->tss.debug.bp[0].address; + dump->u_debugreg[1] = current->tss.debug.bp[1].address; + dump->u_debugreg[2] = current->tss.debug.bp[0].insn; + dump->u_debugreg[3] = current->tss.debug.bp[1].insn; + dump->u_debugreg[4] = current->tss.debug.nsaved; if (dump->start_stack < 0x04000000) dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT; diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c --- v2.3.10/linux/arch/arm/kernel/ptrace.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/ptrace.c Mon Jul 19 09:52:57 1999 @@ -59,209 +59,24 @@ return 0; } -/* - * This routine gets a long from any process space by following the page - * tables. NOTE! You should check that the long isn't on a page boundary, - * and that it is in the task area before calling this: this routine does - * no checking. - */ -static unsigned long get_long(struct task_struct * tsk, - struct vm_area_struct * vma, unsigned long addr) +static int +read_long(struct task_struct *child, unsigned long addr, unsigned long *res) { - pgd_t *pgdir; - pmd_t *pgmiddle; - pte_t *pgtable; - unsigned long page; - -repeat: - pgdir = pgd_offset(vma->vm_mm, addr); - if (pgd_none(*pgdir)) { - handle_mm_fault(tsk, vma, addr, 0); - goto repeat; - } - if (pgd_bad(*pgdir)) { - printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir)); - pgd_clear(pgdir); - return 0; - } - pgmiddle = pmd_offset(pgdir, addr); - if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk, vma, addr, 0); - goto repeat; - } - if (pmd_bad(*pgmiddle)) { - printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); - pmd_clear(pgmiddle); - return 0; - } - pgtable = pte_offset(pgmiddle, addr); - if (!pte_present(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 0); - goto repeat; - } - page = pte_page(*pgtable); - - if(MAP_NR(page) >= max_mapnr) - return 0; - page += addr & ~PAGE_MASK; - return *(unsigned long *)page; -} + int copied; -/* - * This routine puts a long into any process space by following the page - * tables. NOTE! You should check that the long isn't on a page boundary, - * and that it is in the task area before calling this: this routine does - * no checking. - * - * Now keeps R/W state of the page so that a text page stays readonly - * even if a debugger scribbles breakpoints into it. -M.U- - */ -static void put_long(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long addr, - unsigned long data) -{ - pgd_t *pgdir; - pmd_t *pgmiddle; - pte_t *pgtable; - unsigned long page; - -repeat: - pgdir = pgd_offset(vma->vm_mm, addr); - if (!pgd_present(*pgdir)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; - } - if (pgd_bad(*pgdir)) { - printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir)); - pgd_clear(pgdir); - return; - } - pgmiddle = pmd_offset(pgdir, addr); - if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; - } - if (pmd_bad(*pgmiddle)) { - printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); - pmd_clear(pgmiddle); - return; - } - pgtable = pte_offset(pgmiddle, addr); - if (!pte_present(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; - } - page = pte_page(*pgtable); - if (!pte_write(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; - } - - if (MAP_NR(page) < max_mapnr) { - page += addr & ~PAGE_MASK; - - flush_cache_range(vma->vm_mm, addr, addr + sizeof(unsigned long)); - - *(unsigned long *)page = data; - - clean_cache_area(page, sizeof(unsigned long)); + copied = access_process_vm(child, addr, res, sizeof(*res), 0); - set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot))); - flush_tlb_page(vma, addr & PAGE_MASK); - } + return copied != sizeof(*res) ? -EIO : 0; } -/* - * This routine checks the page boundaries, and that the offset is - * within the task area. It then calls get_long() to read a long. - */ -static int read_long(struct task_struct * tsk, unsigned long addr, - unsigned long * result) +static int +write_long(struct task_struct *child, unsigned long addr, unsigned long val) { - struct vm_area_struct * vma = find_extend_vma(tsk, addr); + int copied; - if (!vma) - return -EIO; - if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) { - unsigned long low,high; - struct vm_area_struct * vma_high = vma; - - if (addr + sizeof(long) >= vma->vm_end) { - vma_high = vma->vm_next; - if (!vma_high || vma_high->vm_start != vma->vm_end) - return -EIO; - } - low = get_long(tsk, vma, addr & ~(sizeof(long)-1)); - high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1)); - switch (addr & (sizeof(long)-1)) { - case 1: - low >>= 8; - low |= high << 24; - break; - case 2: - low >>= 16; - low |= high << 16; - break; - case 3: - low >>= 24; - low |= high << 8; - break; - } - *result = low; - } else - *result = get_long(tsk, vma, addr); - return 0; -} - -/* - * This routine checks the page boundaries, and that the offset is - * within the task area. It then calls put_long() to write a long. - */ -static int write_long(struct task_struct * tsk, unsigned long addr, - unsigned long data) -{ - struct vm_area_struct * vma = find_extend_vma(tsk, addr); + copied = access_process_vm(child, addr, &val, sizeof(val), 1); - if (!vma) - return -EIO; - if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) { - unsigned long low,high; - struct vm_area_struct * vma_high = vma; - - if (addr + sizeof(long) >= vma->vm_end) { - vma_high = vma->vm_next; - if (!vma_high || vma_high->vm_start != vma->vm_end) - return -EIO; - } - low = get_long(tsk, vma, addr & ~(sizeof(long)-1)); - high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1)); - switch (addr & (sizeof(long)-1)) { - case 0: /* shouldn't happen, but safety first */ - low = data; - break; - case 1: - low &= 0x000000ff; - low |= data << 8; - high &= ~0xff; - high |= data >> 24; - break; - case 2: - low &= 0x0000ffff; - low |= data << 16; - high &= ~0xffff; - high |= data >> 16; - break; - case 3: - low &= 0x00ffffff; - low |= data << 24; - high &= ~0xffffff; - high |= data >> 8; - break; - } - put_long(tsk, vma, addr & ~(sizeof(long)-1),low); - put_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high); - } else - put_long(tsk, vma, addr, data); - return 0; + return copied != sizeof(val) ? -EIO : 0; } /* @@ -350,19 +165,12 @@ return val; } -int ptrace_set_bpt (struct task_struct *child) +static unsigned long +get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn) { - unsigned long insn, pc, alt; - int i, nsaved = 0, res; - - pc = pc_pointer (get_stack_long (child, 15/*REG_PC*/)); - - res = read_long (child, pc, &insn); - if (res < 0) - return res; + unsigned long alt = 0; - child->tss.debug[nsaved++] = alt = pc + 4; -printk ("ptrace_set_bpt: insn=%08lX pc=%08lX ", insn, pc); +printk(KERN_DEBUG "ptrace_set_bpt: insn=%08lX pc=%08lX ", insn, pc); switch (insn & 0x0e100000) { case 0x00000000: case 0x00100000: @@ -423,7 +231,7 @@ alt -= ptrace_getldrop2 (child, insn); } if (read_long (child, alt, &alt) < 0) - alt = pc + 4; /* not valid */ + alt = 0; /* not valid */ else alt = pc_pointer (alt); } @@ -440,7 +248,7 @@ alt -= insn & 0xfff; } if (read_long (child, alt, &alt) < 0) - alt = pc + 4; /* not valid */ + alt = 0; /* not valid */ else alt = pc_pointer (alt); } @@ -473,7 +281,7 @@ base = ptrace_getrn (child, insn); if (read_long (child, base + nr_regs, &alt) < 0) - alt = pc + 4; /* not valid */ + alt = 0; /* not valid */ else alt = pc_pointer (alt); break; @@ -499,22 +307,55 @@ break; } printk ("=%08lX\n", alt); - if (alt != pc + 4) - child->tss.debug[nsaved++] = alt; - for (i = 0; i < nsaved; i++) { - res = read_long (child, child->tss.debug[i], &insn); - if (res >= 0) { - child->tss.debug[i + 2] = insn; - res = write_long (child, child->tss.debug[i], BREAKINST); + return alt; +} + +static int +add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long addr) +{ + int nr = dbg->nsaved; + int res = -EINVAL; + + if (nr < 2) { + res = read_long(child, addr, &dbg->bp[nr].insn); + if (res == 0) + res = write_long(child, addr, BREAKINST); + + if (res == 0) { + dbg->bp[nr].address = addr; + dbg->nsaved += 1; } - if (res < 0) { - child->tss.debug[4] = 0; - return res; + } else + printk(KERN_DEBUG "add_breakpoint: too many breakpoints\n"); + + return res; +} + +int ptrace_set_bpt (struct task_struct *child) +{ + struct debug_info *dbg = &child->tss.debug; + unsigned long insn, pc, alt; + int res; + + pc = pc_pointer (get_stack_long (child, 15/*REG_PC*/)); + + res = read_long(child, pc, &insn); + if (res >= 0) { + res = 0; + + dbg->nsaved = 0; + + res = add_breakpoint(child, dbg, pc + 4); + + if (res == 0) { + alt = get_branch_address(child, pc, insn); + if (alt) + res = add_breakpoint(child, dbg, alt); } } - child->tss.debug[4] = nsaved; - return 0; + + return res; } /* Ensure no single-step breakpoint is pending. Returns non-zero @@ -522,16 +363,24 @@ */ int ptrace_cancel_bpt (struct task_struct *child) { - int i, nsaved = child->tss.debug[4]; + struct debug_info *dbg = &child->tss.debug; + unsigned long tmp; + int i, nsaved = dbg->nsaved; - child->tss.debug[4] = 0; + dbg->nsaved = 0; if (nsaved > 2) { printk ("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); nsaved = 2; } - for (i = 0; i < nsaved; i++) - write_long (child, child->tss.debug[i], child->tss.debug[i + 2]); + + for (i = 0; i < nsaved; i++) { + read_long(child, dbg->bp[i].address, &tmp); + if (tmp != BREAKINST) + printk(KERN_ERR "ptrace_cancel_bpt: weirdness\n"); + write_long(child, dbg->bp[i].address, dbg->bp[i].insn); + } + return nsaved != 0; } @@ -598,8 +447,8 @@ unsigned long tmp; ret = read_long(child, addr, &tmp); - if (ret >= 0) - ret = put_user(tmp, (unsigned long *)data); + if (ret) + put_user(tmp, (unsigned long *) data); goto out; } @@ -619,7 +468,7 @@ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: - ret = write_long(child,addr,data); + ret = write_long(child, addr, data); goto out; case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ @@ -665,7 +514,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) goto out; - child->tss.debug[4] = -1; + child->tss.debug.nsaved = -1; child->flags &= ~PF_TRACESYS; wake_up_process(child); child->exit_code = data; diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c --- v2.3.10/linux/arch/arm/kernel/setup.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/setup.c Mon Jul 19 09:52:57 1999 @@ -309,7 +309,8 @@ case MACH_TYPE_EBSA110: /* EBSA110 locks if we execute 'wait for interrupt' */ disable_hlt(); - params = NULL; + if (params && params->u1.s.page_size != 4096) + params = NULL; break; case MACH_TYPE_EBSA285: diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c --- v2.3.10/linux/arch/arm/kernel/time.c Thu Jul 8 15:42:19 1999 +++ linux/arch/arm/kernel/time.c Mon Jul 19 09:52:57 1999 @@ -76,6 +76,25 @@ )*60 + sec; /* finally seconds */ } +/* + * Handle profile stuff... + */ +static void do_profile(unsigned long pc) +{ + if (prof_buffer && current->pid) { + extern int _stext; + + pc -= (unsigned long)&_stext; + + pc >>= prof_shift; + + if (pc >= prof_len) + pc = prof_len - 1; + + prof_buffer[pc] += 1; + } +} + #include static unsigned long do_gettimeoffset(void) diff -u --recursive --new-file v2.3.10/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c --- v2.3.10/linux/arch/arm/kernel/traps.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/traps.c Mon Jul 19 09:52:57 1999 @@ -387,3 +387,9 @@ code, regs->ARM_pc, instr, regs->ARM_lr, regs->ARM_sp); } #endif + +asmlinkage void __div0(void) +{ + printk("Awooga, division by zero in kernel.\n"); + __backtrace(); +} diff -u --recursive --new-file v2.3.10/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile --- v2.3.10/linux/arch/arm/lib/Makefile Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/lib/Makefile Mon Jul 19 09:52:57 1999 @@ -5,7 +5,7 @@ # L_TARGET := lib.a -L_OBJS := backtrace.o bitops.o checksum.o delay.o io.o memcpy.o \ +L_OBJS := backtrace.o bitops.o checksum.o delay.o memcpy.o \ semaphore.o string.o system.o uaccess.o ifeq ($(PROCESSOR),armo) @@ -24,6 +24,8 @@ ifeq ($(MACHINE),ebsa110) L_OBJS += io-ebsa110.o +else + LX_OBJS += io.o endif ifeq ($(MACHINE),footbridge) diff -u --recursive --new-file v2.3.10/linux/arch/arm/lib/io.c linux/arch/arm/lib/io.c --- v2.3.10/linux/arch/arm/lib/io.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/lib/io.c Mon Jul 19 09:52:57 1999 @@ -1,3 +1,5 @@ +#include + #include /* @@ -40,3 +42,8 @@ dst++; } } + +EXPORT_SYMBOL(_memcpy_fromio); +EXPORT_SYMBOL(_memcpy_toio); +EXPORT_SYMBOL(_memset_io); + diff -u --recursive --new-file v2.3.10/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c --- v2.3.10/linux/arch/arm/mm/init.c Wed Jun 30 13:38:18 1999 +++ linux/arch/arm/mm/init.c Mon Jul 19 09:52:57 1999 @@ -247,7 +247,7 @@ (unsigned long)(&__netwinder_end), "netwinder"); - if (!machine_is_ebsa285() && !machine_is_cats()) + if (!machine_is_ebsa285() && !machine_is_cats() && !machine_is_co285()) free_area((unsigned long)(&__ebsa285_begin), (unsigned long)(&__ebsa285_end), "ebsa285/cats"); diff -u --recursive --new-file v2.3.10/linux/arch/i386/Makefile linux/arch/i386/Makefile --- v2.3.10/linux/arch/i386/Makefile Mon Jun 7 17:02:23 1999 +++ linux/arch/i386/Makefile Tue Jul 13 12:26:46 1999 @@ -12,6 +12,9 @@ # # Copyright (C) 1994 by Linus Torvalds # +# 19990713 Artur Skawina +# Added '-march' and '-mpreferred-stack-boundary' support +# LD=$(CROSS_COMPILE)ld -m elf_i386 CPP=$(CC) -E @@ -23,6 +26,9 @@ CFLAGS_NSR := -fno-strength-reduce CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) $(CFLAGS_NSR) +# prevent gcc from keeping the stack 16 byte aligned +CFLAGS += $(shell if $(CC) -mpreferred-stack-boundary=2 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mpreferred-stack-boundary=2"; fi) + ifdef CONFIG_M386 CFLAGS := $(CFLAGS) -m386 -DCPU=386 AFLAGS := $(AFLAGS) -DCPU=386 @@ -30,21 +36,25 @@ ifdef CONFIG_M486 CFLAGS := $(CFLAGS) -m486 -DCPU=486 +CFLAGS += $(shell if $(CC) -march=i486 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i486"; fi) AFLAGS := $(AFLAGS) -DCPU=486 endif ifdef CONFIG_M586 CFLAGS := $(CFLAGS) -DCPU=586 +CFLAGS += $(shell if $(CC) -march=i586 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i586"; fi) AFLAGS := $(AFLAGS) -DCPU=586 endif ifdef CONFIG_M586TSC CFLAGS := $(CFLAGS) -DCPU=586 +CFLAGS += $(shell if $(CC) -march=i586 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i586"; fi) AFLAGS := $(AFLAGS) -DCPU=586 endif ifdef CONFIG_M686 CFLAGS := $(CFLAGS) -DCPU=686 +CFLAGS += $(shell if $(CC) -march=i686 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i686"; fi) AFLAGS := $(AFLAGS) -DCPU=686 endif diff -u --recursive --new-file v2.3.10/linux/arch/i386/boot/compressed/Makefile linux/arch/i386/boot/compressed/Makefile --- v2.3.10/linux/arch/i386/boot/compressed/Makefile Mon Jul 20 10:05:15 1998 +++ linux/arch/i386/boot/compressed/Makefile Sun Jul 11 09:48:05 1999 @@ -30,7 +30,7 @@ bvmlinux: piggy.o $(OBJECTS) $(LD) $(BZLINKFLAGS) -o bvmlinux $(OBJECTS) piggy.o -head.o: head.S $(TOPDIR)/include/linux/tasks.h +head.o: head.S $(CC) $(AFLAGS) -traditional -c head.S piggy.o: $(SYSTEM) diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile --- v2.3.10/linux/arch/i386/kernel/Makefile Wed Jan 20 10:18:53 1999 +++ linux/arch/i386/kernel/Makefile Sun Jul 11 09:48:05 1999 @@ -50,7 +50,7 @@ O_OBJS += visws_apic.o endif -head.o: head.S $(TOPDIR)/include/linux/tasks.h +head.o: head.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.3.10/linux/arch/i386/kernel/entry.S Fri Apr 30 08:13:37 1999 +++ linux/arch/i386/kernel/entry.S Sun Jul 18 12:13:30 1999 @@ -153,11 +153,9 @@ ALIGN .globl ret_from_fork ret_from_fork: -#ifdef __SMP__ pushl %ebx call SYMBOL_NAME(schedule_tail) addl $4, %esp -#endif /* __SMP__ */ GET_CURRENT(%ebx) jmp ret_from_sys_call diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S --- v2.3.10/linux/arch/i386/kernel/head.S Thu Jan 14 22:57:25 1999 +++ linux/arch/i386/kernel/head.S Sun Jul 11 09:11:46 1999 @@ -8,11 +8,12 @@ */ .text -#include +#include #include #include #include #include +#include #define CL_MAGIC_ADDR 0x90020 @@ -330,7 +331,7 @@ * of tasks we can have.. */ #define IDT_ENTRIES 256 -#define GDT_ENTRIES (12+2*NR_TASKS) +#define GDT_ENTRIES (__TSS(NR_CPUS)) .globl SYMBOL_NAME(idt) @@ -519,8 +520,7 @@ ALIGN /* - * This contains up to 8192 quadwords depending on NR_TASKS - 64kB of - * gdt entries. Ugh. + * This contains typically 140 quadwords, depending on NR_CPUS. * * NOTE! Make sure the gdt descriptor in head.S matches this if you * change anything. @@ -542,7 +542,7 @@ .quad 0x00409a0000000000 /* 0x48 APM CS code */ .quad 0x00009a0000000000 /* 0x50 APM CS 16 code (16 bit) */ .quad 0x0040920000000000 /* 0x58 APM DS data */ - .fill 2*NR_TASKS,8,0 /* space for LDT's and TSS's etc */ + .fill NR_CPUS*4,8,0 /* space for TSS's and LDT's */ /* * This is to aid debugging, the various locking macros will be putting diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/init_task.c linux/arch/i386/kernel/init_task.c --- v2.3.10/linux/arch/i386/kernel/init_task.c Tue May 11 14:37:40 1999 +++ linux/arch/i386/kernel/init_task.c Mon Jul 19 15:23:49 1999 @@ -4,6 +4,7 @@ #include #include #include +#include static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; @@ -22,4 +23,13 @@ union task_union init_task_union __attribute__((__section__(".data.init_task"))) = { INIT_TASK(init_task_union.task) }; - + +/* + * per-CPU TSS segments. Threads are completely 'soft' on Linux, + * no more per-task TSS's. The TSS size is kept cacheline-aligned + * so they are allowed to end up in the .data.cacheline_aligned + * section. Since TSS's are completely CPU-local, we want them + * on exact cacheline boundaries, to eliminate cacheline ping-pong. + */ +struct tss_struct init_tss[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = INIT_TSS }; + diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/ioport.c linux/arch/i386/kernel/ioport.c --- v2.3.10/linux/arch/i386/kernel/ioport.c Mon Jan 11 15:02:52 1999 +++ linux/arch/i386/kernel/ioport.c Mon Jul 19 15:22:48 1999 @@ -54,7 +54,8 @@ */ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) { - struct thread_struct * t = ¤t->tss; + struct thread_struct * t = ¤t->thread; + struct tss_struct * tss = init_tss + smp_processor_id(); if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32)) return -EINVAL; @@ -65,14 +66,24 @@ * IO bitmap up. ioperm() is much less timing critical than clone(), * this is why we delay this operation until now: */ -#define IO_BITMAP_OFFSET offsetof(struct thread_struct,io_bitmap) - - if (t->bitmap != IO_BITMAP_OFFSET) { - t->bitmap = IO_BITMAP_OFFSET; + if (!t->ioperm) { + /* + * just in case ... + */ memset(t->io_bitmap,0xff,(IO_BITMAP_SIZE+1)*4); + t->ioperm = 1; + /* + * this activates it in the TSS + */ + tss->bitmap = IO_BITMAP_OFFSET; } - - set_bitmap((unsigned long *)t->io_bitmap, from, num, !turn_on); + + /* + * do it in the per-thread copy and in the TSS ... + */ + set_bitmap(t->io_bitmap, from, num, !turn_on); + set_bitmap(tss->io_bitmap, from, num, !turn_on); + return 0; } diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.3.10/linux/arch/i386/kernel/irq.c Mon May 10 10:32:45 1999 +++ linux/arch/i386/kernel/irq.c Thu Jul 15 15:50:47 1999 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -931,17 +930,21 @@ if (action->dev_id != dev_id) continue; - /* Found it - now free it */ + /* Found it - now remove it from the list of entries */ *p = action->next; - kfree(action); if (!irq_desc[irq].action) { irq_desc[irq].status |= IRQ_DISABLED; irq_desc[irq].handler->shutdown(irq); } - goto out; + spin_unlock_irqrestore(&irq_controller_lock,flags); + + /* Wait to make sure it's not being used on another CPU */ + while (irq_desc[irq].status & IRQ_INPROGRESS) + barrier(); + kfree(action); + return; } printk("Trying to free free IRQ%d\n",irq); -out: spin_unlock_irqrestore(&irq_controller_lock,flags); } @@ -1099,9 +1102,7 @@ /* IPI vector for APIC spurious interrupts */ set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); -#endif - request_region(0x20,0x20,"pic1"); - request_region(0xa0,0x20,"pic2"); +#endif /* * Set the clock to 100 Hz, we already have a valid diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/ldt.c linux/arch/i386/kernel/ldt.c --- v2.3.10/linux/arch/i386/kernel/ldt.c Sun Sep 13 12:16:22 1998 +++ linux/arch/i386/kernel/ldt.c Wed Jul 21 09:50:25 1999 @@ -2,6 +2,7 @@ * linux/kernel/ldt.c * * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds + * Copyright (C) 1999 Ingo Molnar */ #include @@ -17,19 +18,31 @@ #include #include +/* + * read_ldt() is not really atomic - this is not a problem since + * synchronization of reads and writes done to the LDT has to be + * assured by user-space anyway. Writes are atomic, to protect + * the security checks done on new descriptors. + */ static int read_ldt(void * ptr, unsigned long bytecount) { - void * address = current->mm->segments; + int err; unsigned long size; + struct mm_struct * mm = current->mm; + + err = 0; + if (!mm->segments) + goto out; - if (!ptr) - return -EINVAL; - if (!address) - return 0; size = LDT_ENTRIES*LDT_ENTRY_SIZE; if (size > bytecount) size = bytecount; - return copy_to_user(ptr, address, size) ? -EFAULT : size; + + err = size; + if (copy_to_user(ptr, mm->segments, size)) + err = -EFAULT; +out: + return err; } static int write_ldt(void * ptr, unsigned long bytecount, int oldmode) @@ -64,31 +77,29 @@ * you get strange behaviour (the kernel is safe, it's just user * space strangeness). * - * For no good reason except historical, the GDT index of the LDT - * is chosen to follow the index number in the task[] array. + * we have two choices: either we preallocate the LDT descriptor + * and can do a shared modify_ldt(), or we postallocate it and do + * an smp message pass to update it. Currently we are a bit + * un-nice to user-space and reload the LDT only on the next + * schedule. (only an issue on SMP) + * + * the GDT index of the LDT is allocated dynamically, and is + * limited by MAX_LDT_DESCRIPTORS. */ + down(&mm->mmap_sem); if (!mm->segments) { - void * ldt; + error = -ENOMEM; - ldt = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE); - if (!ldt) - goto out; - memset(ldt, 0, LDT_ENTRIES*LDT_ENTRY_SIZE); + mm->segments = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE); + if (!mm->segments) + goto out_unlock; + + if (atomic_read(&mm->mm_users) > 1) + printk(KERN_WARNING "LDT allocated for cloned task!\n"); /* - * Make sure someone else hasn't allocated it for us ... + * Possibly do an SMP cross-call to other CPUs to reload + * their LDTs */ - if (!mm->segments) { - int i = current->tarray_ptr - &task[0]; - mm->segments = ldt; - set_ldt_desc(i, ldt, LDT_ENTRIES); - current->tss.ldt = _LDT(i); - load_ldt(i); - if (atomic_read(&mm->count) > 1) - printk(KERN_WARNING - "LDT allocated for cloned task!\n"); - } else { - vfree(ldt); - } } lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->segments); @@ -127,6 +138,9 @@ *lp = entry_1; *(lp+1) = entry_2; error = 0; + +out_unlock: + up(&mm->mmap_sem); out: return error; } @@ -135,7 +149,6 @@ { int ret = -ENOSYS; - lock_kernel(); switch (func) { case 0: ret = read_ldt(ptr, bytecount); @@ -147,6 +160,5 @@ ret = write_ldt(ptr, bytecount, 0); break; } - unlock_kernel(); return ret; } diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c --- v2.3.10/linux/arch/i386/kernel/mca.c Wed Jun 30 13:38:18 1999 +++ linux/arch/i386/kernel/mca.c Mon Jul 19 12:32:54 1999 @@ -210,6 +210,18 @@ /*--------------------------------------------------------------------*/ +struct resource mca_standard_resources[] = { + { "system control port B (MCA)", 0x60, 0x60 }, + { "arbitration (MCA)", 0x90, 0x90 }, + { "card Select Feedback (MCA)", 0x91, 0x91 }, + { "system Control port A (MCA)", 0x92, 0x92 }, + { "system board setup (MCA)", 0x94, 0x94 }, + { "POS (MCA)", 0x96, 0x97 }, + { "POS (MCA)", 0x100, 0x107 } +}; + +#define MCA_STANDARD_RESOURCES (sizeof(mca_standard_resources)/sizeof(struct resource)) + __initfunc(void mca_init(void)) { unsigned int i, j; @@ -319,13 +331,8 @@ restore_flags(flags); - request_region(0x60,0x01,"system control port B (MCA)"); - request_region(0x90,0x01,"arbitration (MCA)"); - request_region(0x91,0x01,"card Select Feedback (MCA)"); - request_region(0x92,0x01,"system Control port A (MCA)"); - request_region(0x94,0x01,"system board setup (MCA)"); - request_region(0x96,0x02,"POS (MCA)"); - request_region(0x100,0x08,"POS (MCA)"); + for (i = 0; i < MCA_STANDARD_RESOURCES; i++) + request_resource(&ioport_resource, mca_standard_resources + i); #ifdef CONFIG_PROC_FS mca_do_proc_init(); diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.3.10/linux/arch/i386/kernel/process.c Thu Jul 8 15:42:19 1999 +++ linux/arch/i386/kernel/process.c Mon Jul 19 23:08:41 1999 @@ -405,6 +405,7 @@ regs->esi, regs->edi, regs->ebp); printk(" DS: %04x ES: %04x\n", 0xffff & regs->xds,0xffff & regs->xes); + __asm__("movl %%cr0, %0": "=r" (cr0)); __asm__("movl %%cr2, %0": "=r" (cr2)); __asm__("movl %%cr3, %0": "=r" (cr3)); @@ -475,11 +476,28 @@ free_pages((unsigned long) p, 1); } +/* + * No need to lock the MM as we are the last user + */ void release_segments(struct mm_struct *mm) { - if (mm->segments) { - void * ldt = mm->segments; + void * ldt = mm->segments; + + /* + * free the LDT + */ + if (ldt) { mm->segments = NULL; + /* + * special case, when we release the LDT from under + * the running CPU. Other CPUs cannot possibly use + * this LDT as we were getting here through mmput() ... + */ + if (mm == current->mm) + load_LDT(mm); + /* + * Nobody anymore uses the LDT, we can free it: + */ vfree(ldt); } } @@ -492,10 +510,9 @@ : "r" (0)); /* - * Get the LDT entry from init_task. + * Load the LDT entry of init_task. */ - current->tss.ldt = _LDT(0); - load_ldt(0); + load_LDT(&init_mm); } /* @@ -537,12 +554,9 @@ void flush_thread(void) { - int i; struct task_struct *tsk = current; - for (i=0 ; i<8 ; i++) - tsk->tss.debugreg[i] = 0; - + memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); /* * Forget coprocessor state.. */ @@ -552,33 +566,52 @@ void release_thread(struct task_struct *dead_task) { + if (dead_task->mm) { + void * ldt = dead_task->mm->segments; + + // temporary debugging check + if (ldt) { + printk("WARNING: dead process %8s still has LDT? <%p>\n", + dead_task->comm, ldt); + BUG(); + } + } } /* - * If new_mm is NULL, we're being called to set up the LDT descriptor - * for a clone task. Each clone must have a separate entry in the GDT. + * If new_mm is NULL, we're being called to set up the LDT for + * a clone task: this is easy since the clone is not running yet. + * otherwise we copy the old segment into a new segment. + * + * we do not have to muck with descriptors here, that is + * done in __switch_to() and get_mmu_context(). */ -void copy_segments(int nr, struct task_struct *p, struct mm_struct *new_mm) +void copy_segments(struct task_struct *p, struct mm_struct *new_mm) { struct mm_struct * old_mm = current->mm; void * old_ldt = old_mm->segments, * ldt = old_ldt; - /* default LDT - use the one from init_task */ - p->tss.ldt = _LDT(0); - if (old_ldt) { - if (new_mm) { - ldt = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE); - new_mm->segments = ldt; - if (!ldt) { - printk(KERN_WARNING "ldt allocation failed\n"); - return; - } - memcpy(ldt, old_ldt, LDT_ENTRIES*LDT_ENTRY_SIZE); - } - p->tss.ldt = _LDT(nr); - set_ldt_desc(nr, ldt, LDT_ENTRIES); + if (!old_mm->segments) { + /* + * default LDT - use the one from init_task + */ + if (new_mm) + new_mm->segments = NULL; return; } + + if (new_mm) { + /* + * Completely new LDT, we initialize it from the parent: + */ + ldt = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE); + if (!ldt) + printk(KERN_WARNING "ldt allocation failed\n"); + else + memcpy(ldt, old_ldt, LDT_ENTRIES*LDT_ENTRY_SIZE); + new_mm->segments = ldt; + } + return; } /* @@ -592,31 +625,21 @@ { struct pt_regs * childregs; - childregs = ((struct pt_regs *) (2*PAGE_SIZE + (unsigned long) p)) - 1; + childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1; *childregs = *regs; childregs->eax = 0; childregs->esp = esp; - p->tss.esp = (unsigned long) childregs; - p->tss.esp0 = (unsigned long) (childregs+1); - p->tss.ss0 = __KERNEL_DS; - - p->tss.tr = _TSS(nr); - set_tss_desc(nr,&(p->tss)); - p->tss.eip = (unsigned long) ret_from_fork; + p->thread.esp = (unsigned long) childregs; + p->thread.esp0 = (unsigned long) (childregs+1); - savesegment(fs,p->tss.fs); - savesegment(gs,p->tss.gs); + p->thread.eip = (unsigned long) ret_from_fork; - /* - * a bitmap offset pointing outside of the TSS limit causes a nicely - * controllable SIGSEGV. The first sys_ioperm() call sets up the - * bitmap properly. - */ - p->tss.bitmap = sizeof(struct thread_struct); + savesegment(fs,p->thread.fs); + savesegment(gs,p->thread.gs); unlazy_fpu(current); - p->tss.i387 = current->tss.i387; + p->thread.i387 = current->thread.i387; return 0; } @@ -632,7 +655,7 @@ fpvalid = tsk->used_math; if (fpvalid) { unlazy_fpu(tsk); - memcpy(fpu,&tsk->tss.i387.hard,sizeof(*fpu)); + memcpy(fpu,&tsk->thread.i387.hard,sizeof(*fpu)); } return fpvalid; @@ -654,7 +677,7 @@ dump->u_dsize -= dump->u_tsize; dump->u_ssize = 0; for (i = 0; i < 8; i++) - dump->u_debugreg[i] = current->tss.debugreg[i]; + dump->u_debugreg[i] = current->thread.debugreg[i]; if (dump->start_stack < TASK_SIZE) dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; @@ -683,11 +706,10 @@ /* * This special macro can be used to load a debugging register */ -#define loaddebug(tsk,register) \ +#define loaddebug(thread,register) \ __asm__("movl %0,%%db" #register \ : /* no output */ \ - :"r" (tsk->tss.debugreg[register])) - + :"r" (thread->debugreg[register])) /* * switch_to(x,yn) should switch tasks from x to y. @@ -712,60 +734,82 @@ * More important, however, is the fact that this allows us much * more flexibility. */ -void __switch_to(struct task_struct *prev, struct task_struct *next) +extern int cpus_initialized; +void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { - /* Do the FPU save and set TS if it wasn't set before.. */ - unlazy_fpu(prev); + struct thread_struct *prev = &prev_p->thread, + *next = &next_p->thread; + struct tss_struct *tss = init_tss + smp_processor_id(); + + unlazy_fpu(prev_p); /* - * Reload TR, LDT and the page table pointers.. - * - * We need TR for the IO permission bitmask (and - * the vm86 bitmasks in case we ever use enhanced - * v86 mode properly). - * - * We may want to get rid of the TR register some - * day, and copy the bitmaps around by hand. Oh, - * well. In the meantime we have to clear the busy - * bit in the TSS entry, ugh. + * Reload esp0, LDT and the page table pointer: */ - gdt_table[next->tss.tr >> 3].b &= 0xfffffdff; - asm volatile("ltr %0": :"g" (*(unsigned short *)&next->tss.tr)); + tss->esp0 = next->esp0; /* * Save away %fs and %gs. No need to save %es and %ds, as * those are always kernel segments while inside the kernel. */ - asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->tss.fs)); - asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->tss.gs)); + asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs)); + asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs)); - /* Re-load LDT if necessary */ - if (next->mm->segments != prev->mm->segments) - asm volatile("lldt %0": :"g" (*(unsigned short *)&next->tss.ldt)); + /* + * Re-load LDT if necessary + */ + if (prev_p->active_mm->segments != next_p->active_mm->segments) + load_LDT(next_p->mm); /* Re-load page tables */ { - unsigned long new_cr3 = next->tss.cr3; - if (new_cr3 != prev->tss.cr3) + unsigned long new_cr3 = next->cr3; + + tss->cr3 = new_cr3; + if (new_cr3 != prev->cr3) asm volatile("movl %0,%%cr3": :"r" (new_cr3)); } /* * Restore %fs and %gs. */ - loadsegment(fs,next->tss.fs); - loadsegment(gs,next->tss.gs); + loadsegment(fs, next->fs); + loadsegment(gs, next->gs); /* * Now maybe reload the debug registers */ - if (next->tss.debugreg[7]){ - loaddebug(next,0); - loaddebug(next,1); - loaddebug(next,2); - loaddebug(next,3); - loaddebug(next,6); - loaddebug(next,7); + if (next->debugreg[7]){ + loaddebug(next, 0); + loaddebug(next, 1); + loaddebug(next, 2); + loaddebug(next, 3); + /* no 4 and 5 */ + loaddebug(next, 6); + loaddebug(next, 7); + } + + if (prev->ioperm || next->ioperm) { + if (next->ioperm) { + /* + * 4 cachelines copy ... not good, but not that + * bad either. Anyone got something better? + * This only affects processes which use ioperm(). + * [Putting the TSSs into 4k-tlb mapped regions + * and playing VM tricks to switch the IO bitmap + * is not really acceptable.] + */ + memcpy(tss->io_bitmap, next->io_bitmap, + IO_BITMAP_SIZE*sizeof(unsigned long)); + tss->bitmap = IO_BITMAP_OFFSET; + } else + /* + * a bitmap offset pointing outside of the TSS limit + * causes a nicely controllable SIGSEGV if a process + * tries to use a port IO instruction. The first + * sys_ioperm() call sets up the bitmap properly. + */ + tss->bitmap = INVALID_IO_BITMAP_OFFSET; } } diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c --- v2.3.10/linux/arch/i386/kernel/ptrace.c Thu Jul 8 15:42:19 1999 +++ linux/arch/i386/kernel/ptrace.c Sun Jul 11 09:11:46 1999 @@ -45,7 +45,7 @@ { unsigned char *stack; - stack = (unsigned char *)task->tss.esp0; + stack = (unsigned char *)task->thread.esp0; stack += offset; return (*((int *)stack)); } @@ -61,7 +61,7 @@ { unsigned char * stack; - stack = (unsigned char *) task->tss.esp0; + stack = (unsigned char *) task->thread.esp0; stack += offset; *(unsigned long *) stack = data; return 0; @@ -76,12 +76,12 @@ case FS: if (value && (value & 3) != 3) return -EIO; - child->tss.fs = value; + child->thread.fs = value; return 0; case GS: if (value && (value & 3) != 3) return -EIO; - child->tss.gs = value; + child->thread.gs = value; return 0; case DS: case ES: @@ -112,10 +112,10 @@ switch (regno >> 2) { case FS: - retval = child->tss.fs; + retval = child->thread.fs; break; case GS: - retval = child->tss.gs; + retval = child->thread.gs; break; case DS: case ES: @@ -229,7 +229,7 @@ addr <= (long) &dummy->u_debugreg[7]){ addr -= (long) &dummy->u_debugreg[0]; addr = addr >> 2; - tmp = child->tss.debugreg[addr]; + tmp = child->thread.debugreg[addr]; }; ret = put_user(tmp,(unsigned long *) data); goto out; @@ -278,7 +278,7 @@ addr -= (long) &dummy->u_debugreg; addr = addr >> 2; - child->tss.debugreg[addr] = data; + child->thread.debugreg[addr] = data; ret = 0; goto out; }; @@ -409,18 +409,18 @@ ret = 0; if ( !child->used_math ) { /* Simulate an empty FPU. */ - child->tss.i387.hard.cwd = 0xffff037f; - child->tss.i387.hard.swd = 0xffff0000; - child->tss.i387.hard.twd = 0xffffffff; + child->thread.i387.hard.cwd = 0xffff037f; + child->thread.i387.hard.swd = 0xffff0000; + child->thread.i387.hard.twd = 0xffffffff; } #ifdef CONFIG_MATH_EMULATION if ( boot_cpu_data.hard_math ) { #endif - __copy_to_user((void *)data, &child->tss.i387.hard, + __copy_to_user((void *)data, &child->thread.i387.hard, sizeof(struct user_i387_struct)); #ifdef CONFIG_MATH_EMULATION } else { - save_i387_soft(&child->tss.i387.soft, + save_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data); } #endif @@ -438,11 +438,11 @@ #ifdef CONFIG_MATH_EMULATION if ( boot_cpu_data.hard_math ) { #endif - __copy_from_user(&child->tss.i387.hard, (void *)data, + __copy_from_user(&child->thread.i387.hard, (void *)data, sizeof(struct user_i387_struct)); #ifdef CONFIG_MATH_EMULATION } else { - restore_i387_soft(&child->tss.i387.soft, + restore_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data); } #endif diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.3.10/linux/arch/i386/kernel/setup.c Thu Jul 8 15:42:19 1999 +++ linux/arch/i386/kernel/setup.c Wed Jul 21 10:07:16 1999 @@ -49,6 +49,7 @@ #include #include #include +#include /* * Machine setup.. @@ -57,6 +58,8 @@ char ignore_irq13 = 0; /* set if exception 16 works */ struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; +unsigned long mmu_cr4_features __initdata = 0; + /* * Bus types .. */ @@ -249,12 +252,30 @@ static char command_line[COMMAND_LINE_SIZE] = { 0, }; char saved_command_line[COMMAND_LINE_SIZE]; +struct resource standard_resources[] = { + { "dma1", 0x00, 0x1f }, + { "pic1", 0x20, 0x3f }, + { "timer", 0x40, 0x5f }, + { "keyboard", 0x60, 0x6f }, + { "dma page reg", 0x80, 0x8f }, + { "pic2", 0xa0, 0xbf }, + { "dma2", 0xc0, 0xdf }, + { "fpu", 0xf0, 0xff } +}; + +/* For demonstration purposes only.. */ +#define keyboard_resources (standard_resources+3) +struct resource kbd_status_resource = { "status", 0x60, 0x60 }; + +#define STANDARD_RESOURCES (sizeof(standard_resources)/sizeof(struct resource)) + __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)) { unsigned long memory_start, memory_end; char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; + int i; #ifdef CONFIG_VISWS visws_get_board_type_and_rev(); @@ -368,11 +389,9 @@ #endif /* request I/O space for devices used on all i[345]86 PCs */ - request_region(0x00,0x20,"dma1"); - request_region(0x40,0x20,"timer"); - request_region(0x80,0x10,"dma page reg"); - request_region(0xc0,0x20,"dma2"); - request_region(0xf0,0x10,"fpu"); + for (i = 0; i < STANDARD_RESOURCES; i++) + request_resource(&ioport_resource, standard_resources+i); + request_resource(keyboard_resources, &kbd_status_resource); #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) @@ -381,10 +400,6 @@ conswitchp = &dummy_con; #endif #endif - /* - * Check the bugs that will bite us before we get booting - */ - } __initfunc(static int get_model_name(struct cpuinfo_x86 *c)) @@ -977,4 +992,65 @@ ((c->loops_per_sec+2500)/5000) % 100); } return p - buffer; +} + +int cpus_initialized = 0; +unsigned long cpu_initialized = 0; + +/* + * cpu_init() initializes state that is per-CPU. Some data is already + * initialized (naturally) in the bootstrap process, such as the GDT + * and IDT. We reload them nevertheless, this function acts as a + * 'CPU state barrier', nothing should get across. + */ +void cpu_init (void) +{ + int nr = smp_processor_id(); + struct tss_struct * t = &init_tss[nr]; + + if (test_and_set_bit(nr,&cpu_initialized)) { + printk("CPU#%d ALREADY INITIALIZED!!!!!!!!!\n", nr); + for (;;) __sti(); + } + cpus_initialized++; + printk("INITIALIZING CPU#%d\n", nr); + + if (boot_cpu_data.x86_capability & X86_FEATURE_PSE) + clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); + + __asm__ __volatile__("lgdt %0": "=m" (gdt_descr)); + __asm__ __volatile__("lidt %0": "=m" (idt_descr)); + + /* + * Delete NT + */ + __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); + + /* + * set up and load the per-CPU TSS and LDT + */ + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + t->esp0 = current->thread.esp0; + set_tss_desc(nr,t); + gdt_table[__TSS(nr)].b &= 0xfffffdff; + load_TR(nr); + load_LDT(&init_mm); + + /* + * Clear all 6 debug registers: + */ + +#define CD(register) __asm__("movl %0,%%db" #register ::"r"(0) ); + + CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7); + +#undef CD + + /* + * Force FPU initialization: + */ + current->flags &= ~PF_USEDFPU; + current->used_math = 0; + stts(); } diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c --- v2.3.10/linux/arch/i386/kernel/signal.c Mon Jun 7 16:14:06 1999 +++ linux/arch/i386/kernel/signal.c Sun Jul 11 09:11:46 1999 @@ -155,7 +155,7 @@ { struct task_struct *tsk = current; clear_fpu(tsk); - return __copy_from_user(&tsk->tss.i387.hard, buf, sizeof(*buf)); + return __copy_from_user(&tsk->thread.i387.hard, buf, sizeof(*buf)); } static inline int restore_i387(struct _fpstate *buf) @@ -167,7 +167,7 @@ if (boot_cpu_data.hard_math) err = restore_i387_hard(buf); else - err = restore_i387_soft(¤t->tss.i387.soft, buf); + err = restore_i387_soft(¤t->thread.i387.soft, buf); #endif current->used_math = 1; return err; @@ -308,8 +308,8 @@ struct task_struct *tsk = current; unlazy_fpu(tsk); - tsk->tss.i387.hard.status = tsk->tss.i387.hard.swd; - if (__copy_to_user(buf, &tsk->tss.i387.hard, sizeof(*buf))) + tsk->thread.i387.hard.status = tsk->thread.i387.hard.swd; + if (__copy_to_user(buf, &tsk->thread.i387.hard, sizeof(*buf))) return -1; return 1; } @@ -328,7 +328,7 @@ return save_i387_hard(buf); #else return boot_cpu_data.hard_math ? save_i387_hard(buf) - : save_i387_soft(¤t->tss.i387.soft, buf); + : save_i387_soft(¤t->thread.i387.soft, buf); #endif } @@ -354,8 +354,8 @@ err |= __put_user(regs->edx, &sc->edx); err |= __put_user(regs->ecx, &sc->ecx); err |= __put_user(regs->eax, &sc->eax); - err |= __put_user(current->tss.trap_no, &sc->trapno); - err |= __put_user(current->tss.error_code, &sc->err); + err |= __put_user(current->thread.trap_no, &sc->trapno); + err |= __put_user(current->thread.error_code, &sc->err); err |= __put_user(regs->eip, &sc->eip); err |= __put_user(regs->xcs, (unsigned int *)&sc->cs); err |= __put_user(regs->eflags, &sc->eflags); @@ -370,7 +370,7 @@ /* non-iBCS2 extensions.. */ err |= __put_user(mask, &sc->oldmask); - err |= __put_user(current->tss.cr2, &sc->cr2); + err |= __put_user(current->thread.cr2, &sc->cr2); return err; } diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c --- v2.3.10/linux/arch/i386/kernel/smp.c Thu Jul 8 15:42:19 1999 +++ linux/arch/i386/kernel/smp.c Sun Jul 11 22:50:27 1999 @@ -104,7 +104,7 @@ unsigned long cpu_present_map = 0; /* Bitmask of physically existing CPUs */ unsigned long cpu_online_map = 0; /* Bitmask of currently online CPUs */ -int smp_num_cpus = 1; /* Total count of live CPUs */ +int smp_num_cpus = 0; /* Total count of live CPUs */ int smp_threads_ready=0; /* Set when the idlers are all forked */ volatile int cpu_number_map[NR_CPUS]; /* which CPU maps to which logical number */ volatile int __cpu_logical_map[NR_CPUS]; /* which logical number maps to which CPU */ @@ -225,6 +225,7 @@ return n; } + /* * Read the MPC */ @@ -637,6 +638,8 @@ #endif } + + /* * Trampoline 80x86 program as an array. */ @@ -882,6 +885,7 @@ * booting is too fragile that we want to limit the * things done here to the most necessary things. */ + cpu_init(); smp_callin(); while (!atomic_read(&smp_commenced)) /* nothing */ ; @@ -896,15 +900,6 @@ */ void __init initialize_secondary(void) { - struct thread_struct * p = ¤t->tss; - - /* - * Load up the LDT and the task register. - */ - asm volatile("lldt %%ax": :"a" (p->ldt)); - asm volatile("ltr %%ax": :"a" (p->tr)); - stts(); - /* * We don't actually need to load the full TSS, * basically just the stack pointer and the eip. @@ -914,7 +909,7 @@ "movl %0,%%esp\n\t" "jmp *%1" : - :"r" (p->esp),"r" (p->eip)); + :"r" (current->thread.esp),"r" (current->thread.eip)); } extern struct { @@ -937,7 +932,13 @@ kernel_thread(start_secondary, NULL, CLONE_PID); cpucount++; - idle = task[cpucount]; + /* + * We remove it from the pidhash and the runqueue + * once we got the process: + */ + idle = init_task.prev_task; + + init_tasks[cpucount] = idle; if (!idle) panic("No idle process for CPU %d", i); @@ -945,7 +946,10 @@ __cpu_logical_map[cpucount] = i; cpu_number_map[i] = cpucount; idle->has_cpu = 1; /* we schedule the first task manually */ - idle->tss.eip = (unsigned long) start_secondary; + idle->thread.eip = (unsigned long) start_secondary; + + del_from_runqueue(idle); + unhash_process(idle); /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); @@ -1179,7 +1183,6 @@ /* Must be done before other processors booted */ mtrr_init_boot_cpu (); #endif - init_idle(); /* * Initialize the logical to physical CPU number mapping * and the per-CPU profiling counter/multiplier @@ -1210,6 +1213,8 @@ cpu_number_map[boot_cpu_id] = 0; + init_idle(); + /* * If we couldnt find an SMP configuration at boot time, * get out of here now! @@ -1356,30 +1361,32 @@ */ SMP_PRINTK(("Before bogomips.\n")); - if (cpucount==0) - { + if (!cpucount) { printk(KERN_ERR "Error: only one processor found.\n"); cpu_online_map = (1<tss.error_code = error_code; \ - tsk->tss.trap_no = trapnr; \ + tsk->thread.error_code = error_code; \ + tsk->thread.trap_no = trapnr; \ force_sig(signr, tsk); \ die_if_no_fixup(str,regs,error_code); \ } @@ -80,8 +80,8 @@ goto out; \ /* else fall through */ \ } \ - tsk->tss.error_code = error_code; \ - tsk->tss.trap_no = trapnr; \ + tsk->thread.error_code = error_code; \ + tsk->thread.trap_no = trapnr; \ force_sig(signr, tsk); \ die_if_kernel(str,regs,error_code); \ out: \ @@ -143,10 +143,8 @@ regs->esi, regs->edi, regs->ebp, esp); printk("ds: %04x es: %04x ss: %04x\n", regs->xds & 0xffff, regs->xes & 0xffff, ss); - store_TR(i); - printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)", - current->comm, current->pid, 0xffff & i, 4096+(unsigned long)current); - + printk("Process %s (pid: %d, stackpage=%08lx)", + current->comm, current->pid, 4096+(unsigned long)current); /* * When in-kernel, we also print out the stack and code at the * time of the fault.. @@ -201,6 +199,9 @@ spin_lock_irq(&die_lock); printk("%s: %04lx\n", str, err & 0xffff); show_registers(regs); + +spin_lock_irq(&die_lock); + spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } @@ -249,8 +250,8 @@ return; } die_if_kernel("cache flush denied",regs,error_code); - current->tss.error_code = error_code; - current->tss.trap_no = 19; + current->thread.error_code = error_code; + current->thread.trap_no = 19; force_sig(SIGSEGV, current); } @@ -262,8 +263,8 @@ if (!(regs->xcs & 3)) goto gp_in_kernel; - current->tss.error_code = error_code; - current->tss.trap_no = 13; + current->thread.error_code = error_code; + current->thread.trap_no = 13; force_sig(SIGSEGV, current); return; @@ -374,9 +375,9 @@ goto clear_TF; } - /* Mast out spurious debug traps due to lazy DR7 setting */ + /* Mask out spurious debug traps due to lazy DR7 setting */ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { - if (!tsk->tss.debugreg[7]) + if (!tsk->thread.debugreg[7]) goto clear_dr7; } @@ -385,8 +386,8 @@ goto clear_dr7; /* Ok, finally something we can handle */ - tsk->tss.trap_no = 1; - tsk->tss.error_code = error_code; + tsk->thread.trap_no = 1; + tsk->thread.error_code = error_code; force_sig(SIGTRAP, tsk); return; @@ -422,8 +423,8 @@ */ task = current; save_fpu(task); - task->tss.trap_no = 16; - task->tss.error_code = 0; + task->thread.trap_no = 16; + task->thread.error_code = 0; force_sig(SIGFPE, task); } @@ -453,7 +454,7 @@ { __asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */ if(current->used_math) - __asm__("frstor %0": :"m" (current->tss.i387)); + __asm__("frstor %0": :"m" (current->thread.i387)); else { /* @@ -486,6 +487,7 @@ pmd_t * pmd; pte_t * pte; +return; /* * Allocate a new page in virtual address space, * move the IDT into it and write protect this page. @@ -570,12 +572,12 @@ void set_tss_desc(unsigned int n, void *addr) { - _set_tssldt_desc(gdt_table+FIRST_TSS_ENTRY+(n<<1), (int)addr, 235, 0x89); + _set_tssldt_desc(gdt_table+__TSS(n), (int)addr, 235, 0x89); } void set_ldt_desc(unsigned int n, void *addr, unsigned int size) { - _set_tssldt_desc(gdt_table+FIRST_LDT_ENTRY+(n<<1), (int)addr, ((size << 3) - 1), 0x82); + _set_tssldt_desc(gdt_table+__LDT(n), (int)addr, ((size << 3)-1), 0x82); } #ifdef CONFIG_X86_VISWS_APIC @@ -672,7 +674,7 @@ { if (readl(0x0FFFD9) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24)) EISA_bus = 1; - set_call_gate(&default_ldt,lcall7); + set_trap_gate(0,÷_error); set_trap_gate(1,&debug); set_trap_gate(2,&nmi); @@ -693,14 +695,20 @@ set_trap_gate(17,&alignment_check); set_system_gate(SYSCALL_VECTOR,&system_call); - /* set up GDT task & ldt entries */ - set_tss_desc(0, &init_task.tss); - set_ldt_desc(0, &default_ldt, 1); - - /* Clear NT, so that we won't have troubles with that later on */ - __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); - load_TR(0); - load_ldt(0); + /* + * default LDT is a single-entry callgate to lcall7 + */ + set_call_gate(&default_ldt,lcall7); + + /* + * on SMP we do not yet know which CPU is on which TSS, + * so we delay this until smp_init(). (the CPU is already + * in a reasonable state, otherwise we wouldnt have gotten so far :) + */ +#ifndef __SMP__ + cpu_init(); +#endif + #ifdef CONFIG_X86_VISWS_APIC superio_init(); lithium_init(); diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/visws_apic.c linux/arch/i386/kernel/visws_apic.c --- v2.3.10/linux/arch/i386/kernel/visws_apic.c Thu May 6 16:12:23 1999 +++ linux/arch/i386/kernel/visws_apic.c Sun Jul 11 15:09:29 1999 @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.3.10/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c --- v2.3.10/linux/arch/i386/kernel/vm86.c Tue Dec 1 11:28:24 1998 +++ linux/arch/i386/kernel/vm86.c Mon Jul 19 15:23:49 1999 @@ -48,8 +48,8 @@ /* * virtual flags (16 and 32-bit versions) */ -#define VFLAGS (*(unsigned short *)&(current->tss.v86flags)) -#define VEFLAGS (current->tss.v86flags) +#define VFLAGS (*(unsigned short *)&(current->thread.v86flags)) +#define VEFLAGS (current->thread.v86flags) #define set_flags(X,new,mask) \ ((X) = ((X) & ~(mask)) | ((new) & (mask))) @@ -65,25 +65,27 @@ asmlinkage struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs)); struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs) { + struct tss_struct *tss; struct pt_regs *ret; unsigned long tmp; lock_kernel(); - if (!current->tss.vm86_info) { + if (!current->thread.vm86_info) { printk("no vm86_info: BAD\n"); do_exit(SIGSEGV); } - set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->tss.v86mask); - tmp = copy_to_user(¤t->tss.vm86_info->regs,regs, VM86_REGS_SIZE1); - tmp += copy_to_user(¤t->tss.vm86_info->regs.VM86_REGS_PART2, + set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->thread.v86mask); + tmp = copy_to_user(¤t->thread.vm86_info->regs,regs, VM86_REGS_SIZE1); + tmp += copy_to_user(¤t->thread.vm86_info->regs.VM86_REGS_PART2, ®s->VM86_REGS_PART2, VM86_REGS_SIZE2); - tmp += put_user(current->tss.screen_bitmap,¤t->tss.vm86_info->screen_bitmap); + tmp += put_user(current->thread.screen_bitmap,¤t->thread.vm86_info->screen_bitmap); if (tmp) { printk("vm86: could not access userspace vm86_info\n"); do_exit(SIGSEGV); } - current->tss.esp0 = current->tss.saved_esp0; - current->tss.saved_esp0 = 0; + tss = init_tss + smp_processor_id(); + tss->esp0 = current->thread.esp0 = current->thread.saved_esp0; + current->thread.saved_esp0 = 0; ret = KVM86->regs32; unlock_kernel(); return ret; @@ -138,7 +140,7 @@ lock_kernel(); tsk = current; - if (tsk->tss.saved_esp0) + if (tsk->thread.saved_esp0) goto out; tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1); tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2, @@ -148,7 +150,7 @@ goto out; memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus); info.regs32 = (struct pt_regs *) &v86; - tsk->tss.vm86_info = v86; + tsk->thread.vm86_info = v86; do_sys_vm86(&info, tsk); ret = 0; /* we never return here */ out: @@ -188,7 +190,7 @@ /* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */ ret = -EPERM; - if (tsk->tss.saved_esp0) + if (tsk->thread.saved_esp0) goto out; tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1); tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2, @@ -198,7 +200,7 @@ goto out; info.regs32 = (struct pt_regs *) &subfunction; info.vm86plus.is_vm86pus = 1; - tsk->tss.vm86_info = (struct vm86_struct *)v86; + tsk->thread.vm86_info = (struct vm86_struct *)v86; do_sys_vm86(&info, tsk); ret = 0; /* we never return here */ out: @@ -209,6 +211,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk) { + struct tss_struct *tss; /* * make sure the vm86() system call doesn't try to do anything silly */ @@ -231,16 +234,16 @@ switch (info->cpu_type) { case CPU_286: - tsk->tss.v86mask = 0; + tsk->thread.v86mask = 0; break; case CPU_386: - tsk->tss.v86mask = NT_MASK | IOPL_MASK; + tsk->thread.v86mask = NT_MASK | IOPL_MASK; break; case CPU_486: - tsk->tss.v86mask = AC_MASK | NT_MASK | IOPL_MASK; + tsk->thread.v86mask = AC_MASK | NT_MASK | IOPL_MASK; break; default: - tsk->tss.v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK; + tsk->thread.v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK; break; } @@ -248,10 +251,11 @@ * Save old state, set default return value (%eax) to 0 */ info->regs32->eax = 0; - tsk->tss.saved_esp0 = tsk->tss.esp0; - tsk->tss.esp0 = (unsigned long) &info->VM86_TSS_ESP0; + tsk->thread.saved_esp0 = tsk->thread.esp0; + tss = init_tss + smp_processor_id(); + tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; - tsk->tss.screen_bitmap = info->screen_bitmap; + tsk->thread.screen_bitmap = info->screen_bitmap; if (info->flags & VM86_SCREEN_BITMAP) mark_screen_rdonly(tsk); unlock_kernel(); @@ -295,7 +299,7 @@ static inline void set_vflags_long(unsigned long eflags, struct kernel_vm86_regs * regs) { - set_flags(VEFLAGS, eflags, current->tss.v86mask); + set_flags(VEFLAGS, eflags, current->thread.v86mask); set_flags(regs->eflags, eflags, SAFE_MASK); if (eflags & IF_MASK) set_IF(regs); @@ -303,7 +307,7 @@ static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs * regs) { - set_flags(VFLAGS, flags, current->tss.v86mask); + set_flags(VFLAGS, flags, current->thread.v86mask); set_flags(regs->eflags, flags, SAFE_MASK); if (flags & IF_MASK) set_IF(regs); @@ -315,7 +319,7 @@ if (VEFLAGS & VIF_MASK) flags |= IF_MASK; - return flags | (VEFLAGS & current->tss.v86mask); + return flags | (VEFLAGS & current->thread.v86mask); } static inline int is_revectored(int nr, struct revectored_struct * bitmap) @@ -447,8 +451,8 @@ spin_unlock_irqrestore(¤t->sigmask_lock, flags); } send_sig(SIGTRAP, current, 1); - current->tss.trap_no = trapno; - current->tss.error_code = error_code; + current->thread.trap_no = trapno; + current->thread.error_code = error_code; return 0; } diff -u --recursive --new-file v2.3.10/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v2.3.10/linux/arch/i386/mm/fault.c Thu Jul 8 15:42:19 1999 +++ linux/arch/i386/mm/fault.c Mon Jul 19 16:09:11 1999 @@ -109,7 +109,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || mm == &init_mm) + if (in_interrupt() || !mm) goto no_context; down(&mm->mmap_sem); @@ -177,7 +177,7 @@ if (regs->eflags & VM_MASK) { unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT; if (bit < 32) - tsk->tss.screen_bitmap |= 1 << bit; + tsk->thread.screen_bitmap |= 1 << bit; } up(&mm->mmap_sem); return; @@ -191,9 +191,9 @@ /* User mode accesses just cause a SIGSEGV */ if (error_code & 4) { - tsk->tss.cr2 = address; - tsk->tss.error_code = error_code; - tsk->tss.trap_no = 14; + tsk->thread.cr2 = address; + tsk->thread.error_code = error_code; + tsk->thread.trap_no = 14; force_sig(SIGSEGV, tsk); return; } @@ -243,9 +243,11 @@ else printk(KERN_ALERT "Unable to handle kernel paging request"); printk(" at virtual address %08lx\n",address); + printk(" printing eip:\n"); + printk("%08lx\n", regs->eip); __asm__("movl %%cr3,%0" : "=r" (page)); - printk(KERN_ALERT "current->tss.cr3 = %08lx, %%cr3 = %08lx\n", - tsk->tss.cr3, page); + printk(KERN_ALERT "current->thread.cr3 = %08lx, %%cr3 = %08lx\n", + tsk->thread.cr3, page); page = ((unsigned long *) __va(page))[address >> 22]; printk(KERN_ALERT "*pde = %08lx\n", page); if (page & 1) { @@ -275,9 +277,9 @@ * Send a sigbus, regardless of whether we were in kernel * or user mode. */ - tsk->tss.cr2 = address; - tsk->tss.error_code = error_code; - tsk->tss.trap_no = 14; + tsk->thread.cr2 = address; + tsk->thread.error_code = error_code; + tsk->thread.trap_no = 14; force_sig(SIGBUS, tsk); /* Kernel mode? Handle exceptions or die */ diff -u --recursive --new-file v2.3.10/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.3.10/linux/arch/i386/mm/init.c Wed Jun 30 13:38:18 1999 +++ linux/arch/i386/mm/init.c Mon Jul 19 23:08:41 1999 @@ -181,34 +181,6 @@ extern char _text, _etext, _edata, __bss_start, _end; extern char __init_begin, __init_end; -#define X86_CR4_VME 0x0001 /* enable vm86 extensions */ -#define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */ -#define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */ -#define X86_CR4_DE 0x0008 /* enable debugging extensions */ -#define X86_CR4_PSE 0x0010 /* enable page size extensions */ -#define X86_CR4_PAE 0x0020 /* enable physical address extensions */ -#define X86_CR4_MCE 0x0040 /* Machine check enable */ -#define X86_CR4_PGE 0x0080 /* enable global pages */ -#define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ - -/* - * Save the cr4 feature set we're using (ie - * Pentium 4MB enable and PPro Global page - * enable), so that any CPU's that boot up - * after us can get the correct flags. - */ -unsigned long mmu_cr4_features __initdata = 0; - -static inline void set_in_cr4(unsigned long mask) -{ - mmu_cr4_features |= mask; - __asm__("movl %%cr4,%%eax\n\t" - "orl %0,%%eax\n\t" - "movl %%eax,%%cr4\n" - : : "irg" (mask) - :"ax"); -} - /* * allocate page table(s) for compile-time fixed mappings */ @@ -358,7 +330,6 @@ printk("Checking if this processor honours the WP bit even in supervisor mode... "); pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY)); local_flush_tlb(); - current->mm->mmap->vm_start += PAGE_SIZE; __asm__ __volatile__( "jmp 1f; 1:\n" "movb %0,%1\n" @@ -370,7 +341,6 @@ :"memory"); pg0[0] = old; local_flush_tlb(); - current->mm->mmap->vm_start -= PAGE_SIZE; if (boot_cpu_data.wp_works_ok < 0) { boot_cpu_data.wp_works_ok = 0; printk("No.\n"); diff -u --recursive --new-file v2.3.10/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c --- v2.3.10/linux/arch/mips/kernel/irixelf.c Wed Jun 30 13:38:18 1999 +++ linux/arch/mips/kernel/irixelf.c Fri Jul 16 09:27:46 1999 @@ -732,9 +732,9 @@ if(retval) { set_fs(old_fs); printk("Unable to load IRIX ELF interpreter\n"); - kfree(elf_phdata); send_sig(SIGSEGV, current, 0); - return 0; + retval = 0; + goto out_file; } } diff -u --recursive --new-file v2.3.10/linux/arch/ppc/Makefile linux/arch/ppc/Makefile --- v2.3.10/linux/arch/ppc/Makefile Wed Jun 30 13:38:19 1999 +++ linux/arch/ppc/Makefile Mon Jul 12 15:12:55 1999 @@ -65,8 +65,7 @@ checks: @$(MAKE) -C arch/$(ARCH)/kernel checks -BOOT_TARGETS = netboot znetboot zImage floppy install \ - vmlinux.coff znetboot.initrd zImage.initrd vmlinux.coff.initrd +BOOT_TARGETS = zImage znetboot.initrd zImage.initrd ifdef CONFIG_MBX $(BOOT_TARGETS): $(CHECKS) vmlinux @@ -74,6 +73,24 @@ @$(MAKEMBXBOOT) $@ else $(BOOT_TARGETS): $(CHECKS) vmlinux + @$(MAKECOFFBOOT) $@ + @$(MAKEBOOT) $@ + @$(MAKECHRPBOOT) $@ + +znetboot: $(CHECKS) vmlinux +ifdef CONFIG_SMP +ifdef CONFIG_PPC64 + cp -f vmlinux /tftpboot/vmlinux.smp.64 +else + cp -f vmlinux /tftpboot/vmlinux.smp +endif +else +ifdef CONFIG_PPC64 + cp -f vmlinux /tftpboot/vmlinux.64 +else + cp -f vmlinux /tftpboot/vmlinux +endif +endif @$(MAKECOFFBOOT) $@ @$(MAKEBOOT) $@ @$(MAKECHRPBOOT) $@ diff -u --recursive --new-file v2.3.10/linux/arch/ppc/amiga/amiints.c linux/arch/ppc/amiga/amiints.c --- v2.3.10/linux/arch/ppc/amiga/amiints.c Thu Jul 8 15:42:19 1999 +++ linux/arch/ppc/amiga/amiints.c Mon Jul 12 15:12:55 1999 @@ -108,7 +108,7 @@ custom.intreq = 0x7fff; #ifdef CONFIG_APUS - /* Clear any inter-CPU interrupt requests. Circumvents bug in + /* Clear any inter-CPU interupt requests. Circumvents bug in Blizzard IPL emulation HW (or so it appears). */ APUS_WRITE(APUS_INT_LVL, INTLVL_SETRESET | INTLVL_MASK); diff -u --recursive --new-file v2.3.10/linux/arch/ppc/chrpboot/main.c linux/arch/ppc/chrpboot/main.c --- v2.3.10/linux/arch/ppc/chrpboot/main.c Wed Jun 30 13:38:19 1999 +++ linux/arch/ppc/chrpboot/main.c Mon Jul 12 15:12:55 1999 @@ -71,7 +71,7 @@ sa = *(unsigned long *)PROG_START+PROG_START; printf("start address = 0x%x\n\r", sa); - (*(void (*)())sa)(a1, a2, prom, 0, 0); + (*(void (*)())sa)(0, 0, prom, a1, a2); printf("returned?\n\r"); diff -u --recursive --new-file v2.3.10/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.3.10/linux/arch/ppc/config.in Thu Jul 8 15:42:19 1999 +++ linux/arch/ppc/config.in Mon Jul 12 15:12:55 1999 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.94 1999/06/25 11:00:07 davem Exp $ +# $Id: config.in,v 1.95 1999/07/03 08:57:06 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # diff -u --recursive --new-file v2.3.10/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c --- v2.3.10/linux/arch/ppc/kernel/chrp_pci.c Wed Jun 30 13:38:19 1999 +++ linux/arch/ppc/kernel/chrp_pci.c Mon Jul 12 15:12:55 1999 @@ -97,7 +97,7 @@ #define python_config_data(bus) ((0xfef00000+0xf8010)-(bus*0x100000)) #define PYTHON_CFA(b, d, o) (0x80 | ((b<<6) << 8) | ((d) << 16) \ | (((o) & ~3) << 24)) -unsigned int python_busnr = 1; +unsigned int python_busnr = 0; int python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val) @@ -347,7 +347,7 @@ } else if ( !strncmp("IBM,7043-260", get_property(find_path_device("/"), "name", NULL),12) ) { - pci_dram_offset = 0x80000000; + pci_dram_offset = 0x0; isa_mem_base = 0xc0000000; isa_io_base = 0xf8000000; } diff -u --recursive --new-file v2.3.10/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c --- v2.3.10/linux/arch/ppc/kernel/chrp_setup.c Wed Jun 30 13:38:19 1999 +++ linux/arch/ppc/kernel/chrp_setup.c Mon Jul 12 15:12:55 1999 @@ -71,6 +71,8 @@ void chrp_time_init(void); void chrp_setup_pci_ptrs(void); +extern void chrp_progress(char *, unsigned short); +void chrp_event_scan(void); extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); @@ -589,10 +591,10 @@ chrp_setup_pci_ptrs(); #ifdef CONFIG_BLK_DEV_INITRD /* take care of initrd if we have one */ - if ( r3 ) + if ( r6 ) { - initrd_start = r3 + KERNELBASE; - initrd_end = r3 + r4 + KERNELBASE; + initrd_start = r6 + KERNELBASE; + initrd_end = r6 + r7 + KERNELBASE; } #endif /* CONFIG_BLK_DEV_INITRD */ @@ -658,6 +660,8 @@ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate; SYSRQ_KEY = 0x54; #endif + if ( rtas_data ) + ppc_md.progress = chrp_progress; #endif #endif @@ -678,16 +682,33 @@ * Print the banner, then scroll down so boot progress * can be printed. -- Cort */ - chrp_progress("Linux/PPC "UTS_RELEASE"\n"); + if ( ppc_md.progress ) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); } -void chrp_progress(char *s) +void chrp_progress(char *s, unsigned short hex) { extern unsigned int rtas_data; + unsigned long width; + struct device_node *root; + char *os = s; + if ( (root = find_path_device("/rtas")) ) + width = *(unsigned long *)get_property(root, "ibm,display-line-length", NULL); + else + width = 0x10; + if ( (_machine != _MACH_chrp) || !rtas_data ) return; - call_rtas( "display-character", 1, 1, NULL, '\r' ); - while ( *s ) - call_rtas( "display-character", 1, 1, NULL, *s++ ); + if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) ) + { + /* assume no display-character RTAS method - use hex display */ + return; + } + while ( *os ) + call_rtas( "display-character", 1, 1, NULL, *os++ ); + /* scan back for the last newline or carriage return */ + for ( os-- ; (*os != '\n') && (*os != '\r') && (os > s) ; os--, width-- ) + /* nothing */ ; + /*while ( width-- )*/ + call_rtas( "display-character", 1, 1, NULL, ' ' ); } diff -u --recursive --new-file v2.3.10/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S --- v2.3.10/linux/arch/ppc/kernel/head.S Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/kernel/head.S Mon Jul 12 15:12:55 1999 @@ -1,7 +1,7 @@ /* * arch/ppc/kernel/head.S * - * $Id: head.S,v 1.133 1999/05/20 05:13:08 cort Exp $ + * $Id: head.S,v 1.134 1999/06/30 05:05:52 paulus Exp $ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -300,7 +300,7 @@ oris r21,r11,(KERNELBASE+0x20000000)@h mtspr DBAT2L,r18 /* N.B. 6xx (not 601) have valid */ mtspr DBAT2U,r21 /* bit in upper BAT register */ - mtspr IBAT2L,r28 + mtspr IBAT2L,r18 mtspr IBAT2U,r21 #endif /* CONFIG_PPC64 */ #endif @@ -1978,7 +1978,13 @@ lwz r6,GPR4(r1) lwz r7,GPR5(r1) lwz r8,GPR6(r1) - mr r9,r2 + lwz r9,GPR7(r1) + bl printk + lis r3,77f@ha + addi r3,r3,77f@l + lwz r4,GPR8(r1) + lwz r5,GPR9(r1) + mr r6,r2 bl printk lwz r0,GPR0(r1) lwz r3,GPR3(r1) @@ -2081,7 +2087,8 @@ 66: li r3,ENOSYS b 52b #ifdef SHOW_SYSCALLS -7: .string "syscall %d(%x, %x, %x, %x), current=%p\n" +7: .string "syscall %d(%x, %x, %x, %x, %x, " +77: .string "%x, %x), current=%p\n" 79: .string " -> %x\n" .align 2 #endif diff -u --recursive --new-file v2.3.10/linux/arch/ppc/kernel/openpic.c linux/arch/ppc/kernel/openpic.c --- v2.3.10/linux/arch/ppc/kernel/openpic.c Thu Apr 29 12:39:01 1999 +++ linux/arch/ppc/kernel/openpic.c Mon Jul 12 15:12:55 1999 @@ -182,6 +182,8 @@ if (!OpenPIC) panic("No OpenPIC found"); + if ( ppc_md.progress ) ppc_md.progress("openpic enter",0x122); + t = openpic_read(&OpenPIC->Global.Feature_Reporting0); switch (t & OPENPIC_FEATURE_VERSION_MASK) { case 1: @@ -201,6 +203,7 @@ OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1; NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >> OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1; + printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", version, NumProcessors, NumSources, OpenPIC); timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency); @@ -212,6 +215,8 @@ if ( main_pic ) { + if ( ppc_md.progress ) ppc_md.progress("openpic main",0x3ff); + /* Initialize timer interrupts */ for (i = 0; i < OPENPIC_NUM_TIMERS; i++) { /* Disabled, Priority 0 */ @@ -226,9 +231,12 @@ openpic_initipi(i, 0, OPENPIC_VEC_IPI+i); } + if ( ppc_md.progress ) ppc_md.progress("openpic initirq",0x3bb); /* Initialize external interrupts */ /* SIOint (8259 cascade) is special */ openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1); + + if ( ppc_md.progress ) ppc_md.progress("openpic map",0x3cc); /* Processor 0 */ openpic_mapirq(0, 1<<0); for (i = 1; i < NumSources; i++) { @@ -248,6 +256,7 @@ openpic_set_priority(0, 0); openpic_disable_8259_pass_through(); } + if ( ppc_md.progress ) ppc_md.progress("openpic exit",0x222); } diff -u --recursive --new-file v2.3.10/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c --- v2.3.10/linux/arch/ppc/kernel/pmac_setup.c Wed Jun 30 13:38:19 1999 +++ linux/arch/ppc/kernel/pmac_setup.c Mon Jul 12 15:12:55 1999 @@ -58,6 +58,7 @@ #include #include #include +#include #include "time.h" #include "local_irq.h" @@ -204,11 +205,12 @@ { Scsi_Disk *dp; int i; - +#ifdef CONFIG_BLK_DEV_SD for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp) if (dp->device != NULL && dp->device->host == host && dp->device->id == tgt) return MKDEV_SD(i); +#endif /* CONFIG_BLK_DEV_SD */ return 0; } #endif @@ -517,13 +519,13 @@ void pmac_ide_insw(ide_ioreg_t port, void *buf, int ns) { - _insw_ns(port+_IO_BASE, buf, ns); + _insw_ns((unsigned short *)(port+_IO_BASE), buf, ns); } void pmac_ide_outsw(ide_ioreg_t port, void *buf, int ns) { - _outsw_ns(port+_IO_BASE, buf, ns); + _outsw_ns((unsigned short *)(port+_IO_BASE), buf, ns); } int diff -u --recursive --new-file v2.3.10/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v2.3.10/linux/arch/ppc/kernel/process.c Thu Jul 8 15:42:19 1999 +++ linux/arch/ppc/kernel/process.c Mon Jul 12 15:12:55 1999 @@ -1,5 +1,5 @@ /* - * $Id: process.c,v 1.86 1999/06/17 21:53:46 cort Exp $ + * $Id: process.c,v 1.87 1999/07/03 08:57:07 davem Exp $ * * linux/arch/ppc/kernel/process.c * diff -u --recursive --new-file v2.3.10/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c --- v2.3.10/linux/arch/ppc/kernel/prom.c Wed Jun 30 13:38:19 1999 +++ linux/arch/ppc/kernel/prom.c Mon Jul 12 15:12:55 1999 @@ -1,5 +1,5 @@ /* - * $Id: prom.c,v 1.61 1999/06/17 06:05:52 paulus Exp $ + * $Id: prom.c,v 1.62 1999/07/02 19:59:31 cort Exp $ * * Procedures for interfacing to the Open Firmware PROM on * Power Macintosh computers. @@ -502,8 +502,8 @@ return; /* copy the holding pattern code to someplace safe (8M) */ - memcpy( (void *)(8<<20), RELOC(__secondary_hold), 0x10000 ); - for (i = 8<<20; i < ((8<<20)+0x10000); i += 32) + memcpy( (void *)(8<<20), RELOC(__secondary_hold), 0x100 ); + for (i = 8<<20; i < ((8<<20)+0x100); i += 32) { asm volatile("dcbf 0,%0" : : "r" (i) : "memory"); asm volatile("icbi 0,%0" : : "r" (i) : "memory"); diff -u --recursive --new-file v2.3.10/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c --- v2.3.10/linux/arch/ppc/kernel/ptrace.c Mon Jun 7 11:15:33 1999 +++ linux/arch/ppc/kernel/ptrace.c Mon Jul 12 15:12:55 1999 @@ -81,6 +81,7 @@ regs->msr &= ~MSR_SE; } +#if 0 /* * This routine gets a long from any process space by following the page * tables. NOTE! You should check that the long isn't on a page boundary, @@ -283,11 +284,13 @@ put_long(tsk, vma,addr,data); return 0; } +#endif asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret = -EPERM; + unsigned long flags; lock_kernel(); if (request == PTRACE_TRACEME) { @@ -302,7 +305,10 @@ if (pid == 1) /* you may not mess with init */ goto out; ret = -ESRCH; - if (!(child = find_task_by_pid(pid))) + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + read_unlock(&tasklist_lock); /* FIXME!!! */ + if ( !child ) goto out; ret = -EPERM; if (request == PTRACE_ATTACH) { @@ -322,11 +328,15 @@ if (child->flags & PF_PTRACED) goto out; child->flags |= PF_PTRACED; + + write_lock_irqsave(&tasklist_lock, flags); if (child->p_pptr != current) { REMOVE_LINKS(child); child->p_pptr = current; SET_LINKS(child); } + write_unlock_irqrestore(&tasklist_lock, flags); + send_sig(SIGSTOP, child, 1); ret = 0; goto out; @@ -342,22 +352,19 @@ goto out; switch (request) { - /* If I and D space are separate, these will need to be fixed. */ + /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { unsigned long tmp; + int copied; - down(&child->mm->mmap_sem); - ret = read_long(child, addr, &tmp); - up(&child->mm->mmap_sem); - if (ret < 0) + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) goto out; - ret = verify_area(VERIFY_WRITE, (void *) data, sizeof(long)); - if (!ret) - put_user(tmp, (unsigned long *) data); + ret = put_user(tmp,(unsigned long *) data); goto out; } - /* read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { unsigned long tmp; @@ -391,11 +398,11 @@ /* If I and D space are separate, this will have to be fixed. */ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: - down(&child->mm->mmap_sem); - ret = write_long(child,addr,data); - up(&child->mm->mmap_sem); + ret = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + goto out; + ret = -EIO; goto out; - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ ret = -EIO; if ((addr & 3) || addr < 0 || addr >= ((PT_FPR0 + 64) << 2)) @@ -459,9 +466,9 @@ goto out; child->flags &= ~PF_TRACESYS; set_single_step(child); - wake_up_process(child); child->exit_code = data; /* give it a chance to run. */ + wake_up_process(child); ret = 0; goto out; } @@ -473,9 +480,11 @@ child->flags &= ~(PF_PTRACED|PF_TRACESYS); wake_up_process(child); child->exit_code = data; + write_lock_irqsave(&tasklist_lock, flags); REMOVE_LINKS(child); child->p_pptr = child->p_opptr; SET_LINKS(child); + write_unlock_irqrestore(&tasklist_lock, flags); /* make sure the single step bit is not set. */ clear_single_step(child); ret = 0; @@ -493,7 +502,6 @@ asmlinkage void syscall_trace(void) { - lock_kernel(); if ((current->flags & (PF_PTRACED|PF_TRACESYS)) != (PF_PTRACED|PF_TRACESYS)) goto out; @@ -511,5 +519,4 @@ current->exit_code = 0; } out: - unlock_kernel(); } diff -u --recursive --new-file v2.3.10/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v2.3.10/linux/arch/ppc/kernel/setup.c Thu Jul 8 15:42:19 1999 +++ linux/arch/ppc/kernel/setup.c Tue Jul 13 02:29:35 1999 @@ -1,5 +1,5 @@ /* - * $Id: setup.c,v 1.136 1999/06/18 07:11:35 cort Exp $ + * $Id: setup.c,v 1.138 1999/07/11 16:32:21 cort Exp $ * Common prep/pmac/chrp boot and setup code. */ @@ -331,6 +331,7 @@ #ifdef __SMP__ if ( first_cpu_booted ) return 0; #endif /* __SMP__ */ + if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100); #ifndef CONFIG_MACH_SPECIFIC /* boot loader will tell us if we're APUS */ @@ -477,13 +478,13 @@ default: printk("Unknown machine type in identify_machine!\n"); } - /* Check for nobats option (used in mapin_ram). */ if (strstr(cmd_line, "nobats")) { extern int __map_without_bats; __map_without_bats = 1; } - + + if ( ppc_md.progress ) ppc_md.progress("id mach(): done", 0x200); return 0; } @@ -539,6 +540,8 @@ *memory_end_p = (unsigned long) end_of_DRAM; ppc_md.setup_arch(memory_start_p, memory_end_p); + /* clear the progress line */ + if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff); } void ppc_generic_ide_fix_driveid(struct hd_driveid *id) diff -u --recursive --new-file v2.3.10/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c --- v2.3.10/linux/arch/ppc/kernel/smp.c Thu Jul 8 15:42:19 1999 +++ linux/arch/ppc/kernel/smp.c Mon Jul 12 15:12:55 1999 @@ -1,5 +1,5 @@ /* - * $Id: smp.c,v 1.54 1999/06/24 17:13:34 cort Exp $ + * $Id: smp.c,v 1.55 1999/07/03 08:57:09 davem Exp $ * * Smp support for ppc. * diff -u --recursive --new-file v2.3.10/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.3.10/linux/arch/ppc/mm/init.c Wed Jun 30 13:38:19 1999 +++ linux/arch/ppc/mm/init.c Mon Jul 12 15:12:55 1999 @@ -1,5 +1,5 @@ /* - * $Id: init.c,v 1.170 1999/06/29 12:33:51 davem Exp $ + * $Id: init.c,v 1.171 1999/07/08 23:20:14 cort Exp $ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -50,6 +50,7 @@ #include #include #include +#include /* APUS includes */ #include #include @@ -961,7 +962,6 @@ } else { p = find_mem_piece(PAGE_SIZE, PAGE_SIZE); } - /*memset(p, 0, PAGE_SIZE);*/ __clear_user(p, PAGE_SIZE); return p; } @@ -1027,7 +1027,7 @@ #ifdef __SMP__ if ( first_cpu_booted ) return; #endif /* __SMP__ */ - + if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111); #ifndef CONFIG_8xx if (have_of) end_of_DRAM = pmac_find_end_of_memory(); @@ -1038,10 +1038,12 @@ else /* prep */ end_of_DRAM = prep_find_end_of_memory(); + if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300); hash_init(); _SDR1 = __pa(Hash) | (Hash_mask >> 10); ioremap_base = 0xf8000000; + if ( ppc_md.progress ) ppc_md.progress("MMU:mapin", 0x301); /* Map in all of RAM starting at KERNELBASE */ mapin_ram(); @@ -1050,6 +1052,7 @@ * the io areas. RAM was mapped by mapin_ram(). * -- Cort */ + if ( ppc_md.progress ) ppc_md.progress("MMU:setbat", 0x302); switch (_machine) { case _MACH_prep: setbat(0, 0x80000000, 0x80000000, 0x10000000, IO_PAGE); @@ -1102,6 +1105,7 @@ ioremap(0x80000000, 0x4000); ioremap(0x81000000, 0x4000); #endif /* CONFIG_8xx */ + if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211); } /* @@ -1310,7 +1314,7 @@ int i; /* max amount of RAM we allow -- Cort */ -#define RAM_LIMIT (768<<20) +#define RAM_LIMIT (256<<20) memory_node = find_devices("memory"); if (memory_node == NULL) { @@ -1509,6 +1513,7 @@ extern unsigned int hash_page_patch_A[], hash_page_patch_B[], hash_page_patch_C[], hash_page[]; + if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105); /* * Allow 64k of hash table for every 16MB of memory, * up to a maximum of 2MB. @@ -1542,6 +1547,7 @@ } #endif /* NO_RELOAD_HTAB */ + if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322); /* Find some memory for the hash table. */ if ( Hash_size ) Hash = find_mem_piece(Hash_size, Hash_size); @@ -1557,11 +1563,11 @@ #else #define b(x) (x) #endif - /*memset(Hash, 0, Hash_size);*/ - __clear_user(Hash, Hash_size); Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); - + __clear_user(Hash, Hash_size); + + if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345); /* * Patch up the instructions in head.S:hash_page */ @@ -1601,5 +1607,6 @@ flush_icache_range((unsigned long) b(hash_page), (unsigned long) b(hash_page + 1)); } + if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205); } #endif /* ndef CONFIG_8xx */ diff -u --recursive --new-file v2.3.10/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c --- v2.3.10/linux/drivers/block/ide-cd.c Fri May 28 09:34:41 1999 +++ linux/drivers/block/ide-cd.c Thu Jul 15 13:55:24 1999 @@ -2124,20 +2124,23 @@ msf.cdmsf_frame0); /* Make sure the TOC is up to date. */ - stat = cdrom_read_toc (drive, NULL); - if (stat) return stat; + if (cmd != CDROMREADRAW) { + stat = cdrom_read_toc (drive, NULL); + if (stat) + return stat; - toc = info->toc; + toc = info->toc; - if (lba < 0 || lba >= toc->capacity) - return -EINVAL; + if (lba < 0 || lba >= toc->capacity) + return -EINVAL; + } buf = (char *) kmalloc (blocksize, GFP_KERNEL); if (buf == NULL) return -ENOMEM; - stat = cdrom_read_block (drive, format, lba, 1, buf, blocksize, - NULL); + stat = cdrom_read_block (drive, format, lba, 1, buf, + blocksize, NULL); if (stat == 0) { if (cmd == CDROMREADMODE2) { diff -u --recursive --new-file v2.3.10/linux/drivers/block/ide-pmac.c linux/drivers/block/ide-pmac.c --- v2.3.10/linux/drivers/block/ide-pmac.c Wed Jun 30 13:38:19 1999 +++ linux/drivers/block/ide-pmac.c Mon Jul 12 16:21:25 1999 @@ -60,35 +60,44 @@ * N.B. this can't be an initfunc, because the media-bay task can * call ide_[un]register at any time. */ -void pmac_ide_init_hwif_ports ( hw_regs_t *hw, - ide_ioreg_t data_port, - ide_ioreg_t ctrl_port, - int *irq) +void pmac_ide_init_hwif_ports(hw_regs_t *hw, + ide_ioreg_t data_port, ide_ioreg_t ctrl_port, + int *irq) { - int i, r; + int i, ix; if (data_port == 0) return; + + for (ix = 0; ix < MAX_HWIFS; ++ix) + if (data_port == pmac_ide_regbase[ix]) + break; + + if (ix >= MAX_HWIFS) { + /* Probably a PCI interface... */ + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i) + hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET; + /* XXX is this right? */ + hw->io_ports[IDE_CONTROL_OFFSET] = 0; + if (irq != 0) + *irq = 0; + return; + } + /* we check only for -EINVAL meaning that we have found a matching bay but with the wrong device type */ - - r = check_media_bay_by_base(data_port, MB_CD); - if (r == -EINVAL) + i = check_media_bay_by_base(data_port, MB_CD); + if (i == -EINVAL) { + hw->io_ports[IDE_DATA_OFFSET] = 0; return; - - for ( i = 0; i < 8 ; ++i ) + } + + for (i = 0; i < 8; ++i) hw->io_ports[i] = data_port + i * 0x10; hw->io_ports[8] = data_port + 0x160; - if (irq != NULL) { - *irq = 0; - for (i = 0; i < MAX_HWIFS; ++i) { - if (data_port == pmac_ide_regbase[i]) { - *irq = pmac_ide_irq[i]; - break; - } - } - } + if (irq != NULL) + *irq = pmac_ide_irq[ix]; } void pmac_ide_tuneproc(ide_drive_t *drive, byte pio) @@ -100,10 +109,10 @@ pio = ide_get_best_pio_mode(drive, pio, 4, &d); switch (pio) { case 4: - out_le32((unsigned *)(IDE_DATA_REG + 0x200), 0x211025); + out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), 0x211025); break; default: - out_le32((unsigned *)(IDE_DATA_REG + 0x200), 0x2f8526); + out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), 0x2f8526); break; } } @@ -145,14 +154,36 @@ *pp = removables; for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) { + struct device_node *tp; + + /* + * If this node is not under a mac-io or dbdma node, + * leave it to the generic PCI driver. + */ + for (tp = np->parent; tp != 0; tp = tp->parent) + if (tp->type && (strcmp(tp->type, "mac-io") == 0 + || strcmp(tp->type, "dbdma") == 0)) + break; + if (tp == 0) + continue; + if (np->n_addrs == 0) { printk(KERN_WARNING "ide: no address for device %s\n", np->full_name); continue; } - base = (unsigned long) ioremap(np->addrs[0].address, 0x200); - + /* + * If this slot is taken (e.g. by ide-pci.c) try the next one. + */ + while (i < MAX_HWIFS + && ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0) + ++i; + if (i >= MAX_HWIFS) + break; + + base = (unsigned long) ioremap(np->addrs[0].address, 0x200) - _IO_BASE; + /* XXX This is bogus. Should be fixed in the registry by checking the kind of host interrupt controller, a bit like gatwick fixes in irq.c diff -u --recursive --new-file v2.3.10/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.3.10/linux/drivers/block/loop.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/block/loop.c Mon Jul 12 07:49:36 1999 @@ -375,7 +375,7 @@ a file structure */ lo->lo_backing_file = NULL; } else if (S_ISREG(inode->i_mode)) { - if (!inode->i_op->bmap) { + if (!inode->i_op->get_block) { printk(KERN_ERR "loop: device has no block access/not implemented\n"); goto out_putf; } diff -u --recursive --new-file v2.3.10/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c --- v2.3.10/linux/drivers/cdrom/cdrom.c Thu Apr 29 11:53:41 1999 +++ linux/drivers/cdrom/cdrom.c Thu Jul 15 13:49:33 1999 @@ -1145,7 +1145,9 @@ ((cdi->ops->capability & ~cdi->mask & CDC_PLAY_AUDIO)!=0)); strcpy(cdrom_drive_info+pos,"\n\n"); - *lenp=pos+3; + pos += 3; + if (*lenp > pos) + *lenp = pos; return proc_dostring(ctl, write, filp, buffer, lenp); } diff -u --recursive --new-file v2.3.10/linux/drivers/char/adbmouse.c linux/drivers/char/adbmouse.c --- v2.3.10/linux/drivers/char/adbmouse.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/adbmouse.c Mon Jul 12 16:21:25 1999 @@ -38,7 +38,9 @@ #ifdef __powerpc__ #include #endif +#ifdef __mc68000__ #include +#endif static struct mouse_status mouse; static unsigned char adb_mouse_buttons[16]; @@ -242,7 +244,7 @@ ADB_MOUSE_MINOR, "adbmouse", &adb_mouse_fops }; -int __init adb_mouse_init(void) +__initfunc(int adb_mouse_init(void)) { mouse.active = 0; mouse.ready = 0; @@ -268,7 +270,7 @@ * option, which is about using ADB keyboard buttons to emulate * mouse buttons. -- paulus */ -void __init adb_mouse_setup(char *str, int *ints) +__initfunc(void adb_mouse_setup(char *str, int *ints)) { if (ints[0] >= 1) { adb_emulate_buttons = ints[1] > 0; @@ -280,6 +282,7 @@ } #ifdef MODULE +#include int init_module(void) { diff -u --recursive --new-file v2.3.10/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v2.3.10/linux/drivers/char/cyclades.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/cyclades.c Fri Jul 16 14:57:41 1999 @@ -1,7 +1,7 @@ #define BLOCKMOVE #define Z_WAKE static char rcsid[] = -"$Revision: 2.2.2.3 $$Date: 1999/06/28 11:13:29 $"; +"$Revision: 2.3.1.1 $$Date: 1999/07/15 16:45:53 $"; /* * linux/drivers/char/cyclades.c @@ -31,6 +31,20 @@ * void cleanup_module(void); * * $Log: cyclades.c,v $ + * Revision 2.3.1.1 1999/07/15 16:45:53 ivan + * Removed CY_PROC conditional compilation; + * Implemented SMP-awareness for the driver; + * Implemented a new ISA IRQ autoprobe that uses the irq_probe_[on|off] + * functions; + * The driver now accepts memory addresses (maddr=0xMMMMM) and IRQs + * (irq=NN) as parameters (only for ISA boards); + * Fixed bug in set_line_char that would prevent the Cyclades-Z + * ports from being configured at speeds above 115.2Kbps; + * Fixed bug in cy_set_termios that would prevent XON/XOFF flow control + * switching from working properly; + * The driver now only prints IRQ info for the Cyclades-Z if it's + * configured to work in interrupt mode; + * * Revision 2.2.2.3 1999/06/28 11:13:29 ivan * Added support for interrupt mode operation for the Z cards; * Removed the driver inactivity control for the Z; @@ -557,7 +571,6 @@ #undef CY_16Y_HACK #undef CY_ENABLE_MONITORING #undef CY_PCI_DEBUG -#undef CY_PROC #if 0 #define PAUSE __asm__("nop"); @@ -613,6 +626,18 @@ #include #include +#include + +#define CY_LOCK(info,flags) \ + do { \ + spin_lock_irqsave(&cy_card[info->card].card_lock, flags); \ + } while (0) + +#define CY_UNLOCK(info,flags) \ + do { \ + spin_unlock_irqrestore(&cy_card[info->card].card_lock, flags); \ + } while (0) + #include #include #include @@ -668,11 +693,6 @@ static int serial_refcount; #ifndef CONFIG_COBALT_27 -static volatile int cy_irq_triggered; -static volatile int cy_triggered; -static int cy_wild_int_mask; -static volatile ucchar *intr_base_addr; - /* This is the address lookup table. The driver will probe for Cyclom-Y/ISA boards at all addresses in here. If you want the driver to probe addresses at a different address, add it to @@ -695,6 +715,14 @@ }; #define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*)) +#ifdef MODULE +static int maddr[NR_CARDS] = { 0, }; +static int irq[NR_CARDS] = { 0, }; + +MODULE_PARM(maddr, "1-" __MODULE_STRING(NR_CARDS) "l"); +MODULE_PARM(irq, "1-" __MODULE_STRING(NR_CARDS) "i"); +#endif + #endif /* CONFIG_COBALT_27 */ /* This is the per-card data structure containing address, irq, number of @@ -818,7 +846,7 @@ static void cy_start(struct tty_struct *); static void set_line_char(struct cyclades_port *); #ifndef CONFIG_COBALT_27 -static void cy_probe(int, void *, struct pt_regs *); +static unsigned detect_isa_irq (volatile ucchar *); #endif /* CONFIG_COBALT_27 */ #ifdef CYCLOM_SHOW_STATUS static void show_status(int); @@ -963,226 +991,79 @@ command to the Cirrus chip to complete and then issues the new command. An error is returned if the previous command didn't finish within the time limit. + + This function is only called from inside spinlock-protected code. */ static int cyy_issue_cmd(volatile ucchar *base_addr, u_char cmd, int index) { - unsigned long flags; volatile int i; - save_flags(flags); cli(); - /* Check to see that the previous command has completed */ - for(i = 0 ; i < 100 ; i++){ - if (cy_readb(base_addr+(CyCCR< 0)? irq : 0; +} #endif /* CONFIG_COBALT_27 */ /* The real interrupt service routine is called @@ -1245,6 +1126,7 @@ printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip); #endif /* determine the channel & change to that context */ + spin_lock(&cinfo->card_lock); save_xir = (u_char) cy_readb(base_addr+(CyRIR<first_line; @@ -1252,6 +1134,7 @@ info->last_active = jiffies; save_car = cy_readb(base_addr+(CyCAR<card_lock); /* if there is nowhere to put the data, discard it */ if(info->tty == 0){ @@ -1359,8 +1242,10 @@ queue_task(&tty->flip.tqueue, &tq_timer); } /* end of service */ + spin_lock(&cinfo->card_lock); cy_writeb((u_long)base_addr+(CyRIR<card_lock); } @@ -1373,23 +1258,29 @@ #endif /* determine the channel & change to that context */ + spin_lock(&cinfo->card_lock); save_xir = (u_char) cy_readb(base_addr+(CyTIR<first_line; save_car = cy_readb(base_addr+(CyCAR<card_lock); /* validate the port# (as configured and open) */ if( (i < 0) || (NR_PORTS <= i) ){ + spin_lock(&cinfo->card_lock); cy_writeb((u_long)base_addr+(CySRER<card_lock); goto txend; } info = &cy_port[i]; info->last_active = jiffies; if(info->tty == 0){ + spin_lock(&cinfo->card_lock); cy_writeb((u_long)base_addr+(CySRER<card_lock); goto txdone; } @@ -1421,21 +1312,27 @@ while (char_count-- > 0){ if (!info->xmit_cnt){ + spin_lock(&cinfo->card_lock); cy_writeb((u_long)base_addr+(CySRER<card_lock); goto txdone; } if (info->xmit_buf == 0){ + spin_lock(&cinfo->card_lock); cy_writeb((u_long)base_addr+(CySRER<card_lock); goto txdone; } if (info->tty->stopped || info->tty->hw_stopped){ + spin_lock(&cinfo->card_lock); cy_writeb((u_long)base_addr+(CySRER<card_lock); goto txdone; } /* Because the Embedded Transmit Commands have @@ -1475,14 +1372,17 @@ } txend: /* end of service */ + spin_lock(&cinfo->card_lock); cy_writeb((u_long)base_addr+(CyTIR<card_lock); } if (status & CySRModem) { /* modem interrupt */ /* determine the channel & change to that context */ + spin_lock(&cinfo->card_lock); save_xir = (u_char) cy_readb(base_addr+(CyMIR<card_lock); if(info->tty == 0){/* no place for data, ignore it*/ ; @@ -1517,9 +1418,11 @@ /* cy_start isn't used because... !!! */ info->tty->hw_stopped = 0; + spin_lock(&cinfo->card_lock); cy_writeb((u_long)base_addr+(CySRER<card_lock); cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); } @@ -1528,9 +1431,11 @@ /* cy_stop isn't used because ... !!! */ info->tty->hw_stopped = 1; + spin_lock(&cinfo->card_lock); cy_writeb((u_long)base_addr+(CySRER<card_lock); } } } @@ -1540,17 +1445,21 @@ } } /* end of service */ + spin_lock(&cinfo->card_lock); cy_writeb((u_long)base_addr+(CyMIR<card_lock); } } /* end while status != 0 */ } /* end loop for chips... */ } while(had_work); /* clear interrupts */ + spin_lock(&cinfo->card_lock); cy_writeb((u_long)card_base_addr + (Cy_ClrIntr<card_lock); } /* cyy_interrupt */ /***********************************************************/ @@ -1624,31 +1533,6 @@ return(0); } /* cyz_issue_cmd */ - -#if 0 -static int -cyz_update_channel( struct cyclades_card *cinfo, - u_long channel, u_char mode, u_char cmd) -{ - struct FIRM_ID *firm_id = - (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); - struct ZFW_CTRL *zfw_ctrl; - struct CH_CTRL *ch_ctrl; - - if (!ISZLOADED(*cinfo)){ - return (-1); - } - zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr)); - ch_ctrl = zfw_ctrl->ch_ctrl; - - cy_writel(&ch_ctrl[channel].op_mode, (uclong)mode); - - return cyz_issue_cmd(cinfo, channel, cmd, 0L); - -} /* cyz_update_channel */ -#endif - #ifdef CONFIG_CYZ_INTR static void cyz_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -2225,11 +2109,14 @@ int card,chip,channel,index; unsigned long page; + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + page = get_free_page(GFP_KERNEL); if (!page) return -ENOMEM; - save_flags(flags); cli(); + CY_LOCK(info, flags); if (info->flags & ASYNC_INITIALIZED){ free_page(page); @@ -2249,10 +2136,10 @@ else info->xmit_buf = (unsigned char *) page; + CY_UNLOCK(info, flags); + set_line_char(info); - card = info->card; - channel = (info->line) - (cy_card[card].first_line); if (!IS_CYC_Z(cy_card[card])) { chip = channel>>2; channel &= 0x03; @@ -2265,6 +2152,8 @@ card, chip, channel, (long)base_addr);/**/ #endif + CY_LOCK(info, flags); + cy_writeb((ulong)base_addr+(CyCAR<default_timeout @@ -2297,7 +2186,7 @@ info->idle_stats.recv_idle = info->idle_stats.xmit_idle = jiffies; - restore_flags(flags); + CY_UNLOCK(info, flags); } else { struct FIRM_ID *firm_id; @@ -2306,8 +2195,6 @@ struct CH_CTRL *ch_ctrl; int retval; - restore_flags(flags); - base_addr = (unsigned char*) (cy_card[card].base_addr); firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS); @@ -2326,6 +2213,8 @@ card, channel, (long)base_addr);/**/ #endif + CY_LOCK(info, flags); + cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE); #ifdef Z_WAKE #ifdef CONFIG_CYZ_INTR @@ -2380,6 +2269,8 @@ info->idle_stats.in_use = info->idle_stats.recv_idle = info->idle_stats.xmit_idle = jiffies; + + CY_UNLOCK(info, flags); } #ifdef CY_DEBUG_OPEN @@ -2388,7 +2279,7 @@ return 0; errout: - restore_flags(flags); + CY_UNLOCK(info, flags); return retval; } /* startup */ @@ -2410,21 +2301,21 @@ (cy_card[card].base_addr + (cy_chip_offset[chip]<xmit_buf){ unsigned char * temp; @@ -2488,7 +2379,7 @@ set_bit(TTY_IO_ERROR, &info->tty->flags); } info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); + CY_UNLOCK(info, flags); } else { struct FIRM_ID *firm_id; struct ZFW_CTRL *zfw_ctrl; @@ -2513,7 +2404,7 @@ board_ctrl = &(zfw_ctrl->board_ctrl); ch_ctrl = zfw_ctrl->ch_ctrl; - save_flags(flags); cli(); + CY_LOCK(info, flags); if (info->xmit_buf){ unsigned char * temp; @@ -2541,7 +2432,7 @@ } info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); + CY_UNLOCK(info, flags); } #ifdef CY_DEBUG_OPEN @@ -2568,6 +2459,9 @@ int retval; char *base_addr; + cinfo = &cy_card[info->card]; + channel = info->line - cinfo->first_line; + /* * If the device is in the middle of being closed, then block * until it's done, and then try again. @@ -2627,18 +2521,16 @@ printk("cyc block_til_ready before block: ttyC%d, count = %d\n", info->line, info->count);/**/ #endif - save_flags(flags); cli(); + CY_LOCK(info, flags); if (!tty_hung_up_p(filp)) info->count--; - restore_flags(flags); + CY_UNLOCK(info, flags); #ifdef CY_DEBUG_COUNT printk("cyc block_til_ready: (%d): decrementing count to %d\n", current->pid, info->count); #endif info->blocked_open++; - cinfo = &cy_card[info->card]; - channel = info->line - cinfo->first_line; if (!IS_CYC_Z(*cinfo)) { chip = channel>>2; channel &= 0x03; @@ -2647,7 +2539,7 @@ + (cy_chip_offset[chip]<flags & ASYNC_CALLOUT_ACTIVE) && (tty->termios->c_cflag & CBAUD)){ cy_writeb((u_long)base_addr+(CyCAR<state = TASK_INTERRUPTIBLE; if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED) ){ @@ -2668,16 +2561,18 @@ -EAGAIN : -ERESTARTSYS); break; } - save_flags(flags); cli(); + + CY_LOCK(info, flags); cy_writeb((u_long)base_addr+(CyCAR<flags & ASYNC_CALLOUT_ACTIVE) && !(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || (cy_readb(base_addr+(CyMSVR1<state = TASK_INTERRUPTIBLE; + current->counter = 0; /* make us low-priority */ schedule_timeout(char_time); if (signal_pending(current)) break; @@ -2968,6 +2864,7 @@ } /* Run one more char cycle */ current->state = TASK_INTERRUPTIBLE; + current->counter = 0; /* make us low-priority */ schedule_timeout(char_time * 5); current->state = TASK_RUNNING; #ifdef CY_DEBUG_WAIT_UNTIL_SENT @@ -2992,12 +2889,11 @@ return; } - save_flags(flags); cli(); - + CY_LOCK(info, flags); /* If the TTY is being hung up, nothing to do */ if (tty_hung_up_p(filp)) { MOD_DEC_USE_COUNT; - restore_flags(flags); + CY_UNLOCK(info, flags); return; } @@ -3028,7 +2924,7 @@ } if (info->count) { MOD_DEC_USE_COUNT; - restore_flags(flags); + CY_UNLOCK(info, flags); return; } info->flags |= ASYNC_CLOSING; @@ -3046,9 +2942,11 @@ * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; + CY_UNLOCK(info, flags); if (info->closing_wait != CY_CLOSING_WAIT_NONE) { tty_wait_until_sent(tty, info->closing_wait); } + CY_LOCK(info, flags); if (!IS_CYC_Z(cy_card[info->card])) { int channel = info->line - cy_card[info->card].first_line; @@ -3064,7 +2962,9 @@ if (info->flags & ASYNC_INITIALIZED) { /* Waiting for on-board buffers to be empty before closing the port */ + CY_UNLOCK(info, flags); cy_wait_until_sent(tty, info->timeout); + CY_LOCK(info, flags); } } else { #ifdef Z_WAKE @@ -3084,16 +2984,21 @@ if (retval != 0){ printk("cyc:shutdown retval (1) was %x\n", retval); } + CY_UNLOCK(info, flags); interruptible_sleep_on(&info->shutdown_wait); + CY_LOCK(info, flags); } #endif } + CY_UNLOCK(info, flags); shutdown(info); if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); + CY_LOCK(info, flags); + tty->closing = 0; info->event = 0; info->tty = 0; @@ -3113,7 +3018,7 @@ #endif MOD_DEC_USE_COUNT; - restore_flags(flags); + CY_UNLOCK(info, flags); return; } /* cy_close */ @@ -3151,8 +3056,7 @@ return 0; } - save_flags(flags); - + CY_LOCK(info, flags); if (from_user) { down(&tmp_buf_sem); while (1) { @@ -3168,13 +3072,11 @@ } break; } - cli(); c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); info->xmit_head = ((info->xmit_head + c) & (SERIAL_XMIT_SIZE-1)); info->xmit_cnt += c; - restore_flags(flags); buf += c; count -= c; ret += c; @@ -3182,22 +3084,20 @@ up(&tmp_buf_sem); } else { while (1) { - cli(); c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); if (c <= 0) { - restore_flags(flags); break; } memcpy(info->xmit_buf + info->xmit_head, buf, c); info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); info->xmit_cnt += c; - restore_flags(flags); buf += c; count -= c; ret += c; } } + CY_UNLOCK(info, flags); info->idle_stats.xmit_bytes += ret; info->idle_stats.xmit_idle = jiffies; @@ -3232,9 +3132,9 @@ if (!tty || !info->xmit_buf) return; - save_flags(flags); cli(); + CY_LOCK(info, flags); if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { - restore_flags(flags); + CY_UNLOCK(info, flags); return; } @@ -3243,7 +3143,7 @@ info->xmit_cnt++; info->idle_stats.xmit_bytes++; info->idle_stats.xmit_idle = jiffies; - restore_flags(flags); + CY_UNLOCK(info, flags); } /* cy_put_char */ @@ -3255,9 +3155,6 @@ cy_flush_chars(struct tty_struct *tty) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - unsigned char *base_addr; - int card,chip,channel,index; #ifdef CY_DEBUG_IO printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */ @@ -3270,25 +3167,7 @@ || tty->hw_stopped || !info->xmit_buf) return; - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<tty){ clear_bit(TTY_IO_ERROR, &info->tty->flags); } + CY_UNLOCK(info, flags); - restore_flags(flags); } else { struct FIRM_ID *firm_id; struct ZFW_CTRL *zfw_ctrl; @@ -3623,8 +3502,8 @@ /* baud rate */ baud = tty_get_baud_rate(info->tty); - if (baud > CD1400_MAX_SPEED) { - baud = CD1400_MAX_SPEED; + if (baud > CYZ_MAX_SPEED) { + baud = CYZ_MAX_SPEED; } cy_writel(&ch_ctrl->comm_baud , baud); @@ -3829,12 +3708,11 @@ (cy_card[card].base_addr + (cy_chip_offset[chip]<rtsdtr_inv) { result = ((status & CyRTS) ? TIOCM_DTR : 0) @@ -3905,17 +3783,17 @@ switch (cmd) { case TIOCMBIS: if (arg & TIOCM_RTS){ - save_flags(flags); cli(); + CY_LOCK(info, flags); cy_writeb((u_long)base_addr+(CyCAR<rtsdtr_inv) { cy_writeb((u_long)base_addr+(CyMSVR2<rtsdtr_inv) { cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { @@ -3941,10 +3819,10 @@ } else { cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { cy_writeb((u_long)base_addr+(CyMSVR2<rtsdtr_inv) { cy_writeb((u_long)base_addr+(CyMSVR2<rtsdtr_inv) { cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { cy_writeb((u_long)base_addr+(CyMSVR1<card], channel, C_CM_IOCTLM,0L); if (retval != 0){ printk("cyc:set_modem_info retval at %d was %x\n", __LINE__, retval); } + CY_UNLOCK(info, flags); } return 0; } /* set_modem_info */ @@ -4104,7 +4000,7 @@ if (serial_paranoia_check(info, tty->device, "cy_break")) return; - save_flags(flags); cli(); + CY_LOCK(info, flags); if (!IS_CYC_Z(cy_card[info->card])) { /* Let the transmit ISR take care of this (since it requires stuffing characters into the output stream). @@ -4113,14 +4009,18 @@ if (!info->breakon) { info->breakon = 1; if (!info->xmit_cnt) { + CY_UNLOCK(info, flags); start_xmit(info); + CY_LOCK(info, flags); } } } else { if (!info->breakoff) { info->breakoff = 1; if (!info->xmit_cnt) { + CY_UNLOCK(info, flags); start_xmit(info); + CY_LOCK(info, flags); } } } @@ -4145,8 +4045,7 @@ } } } - restore_flags(flags); - + CY_UNLOCK(info, flags); } /* cy_break */ static int @@ -4168,6 +4067,7 @@ { unsigned char *base_addr; int card,channel,chip,index; + unsigned long flags; card = info->card; channel = info->line - cy_card[card].first_line; @@ -4181,8 +4081,11 @@ info->cor3 &= ~CyREC_FIFO; info->cor3 |= value & CyREC_FIFO; - cy_writeb((u_long)base_addr+(CyCOR3<cor3); - cyy_issue_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index); + + CY_LOCK(info, flags); + cy_writeb((u_long)base_addr+(CyCOR3<cor3); + cyy_issue_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index); + CY_UNLOCK(info, flags); } else { // Nothing to do! } @@ -4236,6 +4139,7 @@ { unsigned char *base_addr; int card,channel,chip,index; + unsigned long flags; card = info->card; channel = info->line - cy_card[card].first_line; @@ -4247,7 +4151,9 @@ (cy_card[card].base_addr + (cy_chip_offset[chip]<line); #endif - if (tty->termios->c_cflag == old_termios->c_cflag) + if ((tty->termios->c_cflag == old_termios->c_cflag) && + ((tty->termios->c_iflag & IXON) == (old_termios->c_iflag & IXON))) return; set_line_char(info); @@ -4487,14 +4394,14 @@ (cy_card[card].base_addr + (cy_chip_offset[chip]<rtsdtr_inv) { cy_writeb((u_long)base_addr+(CyMSVR2<rtsdtr_inv) { cy_writeb((u_long)base_addr+(CyMSVR2<card].base_addr + (cy_chip_offset[chip]<card].base_addr + (cy_chip_offset[chip]<device, "cy_flush_buffer")) return; - save_flags(flags); cli(); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - restore_flags(flags); card = info->card; channel = (info->line) - (cy_card[card].first_line); + CY_LOCK(info, flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + CY_UNLOCK(info, flags); + if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board buffers as well */ + CY_LOCK(info, flags); retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L); if (retval != 0) { printk("cyc: flush_buffer retval was %x\n", retval); } + CY_UNLOCK(info, flags); } wake_up_interruptible(&tty->write_wait); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) @@ -4717,8 +4627,8 @@ /* initialize chips on Cyclom-Y card -- return number of valid chips (which is number of ports/4) */ -static unsigned short __init -cyy_init_card(volatile ucchar *true_base_addr,int index) +__initfunc(static unsigned short +cyy_init_card(volatile ucchar *true_base_addr,int index)) { unsigned int chip_number; volatile ucchar* base_addr; @@ -4803,14 +4713,30 @@ * sets global variables and return the number of ISA boards found. * --------------------------------------------------------------------- */ -static int __init cy_detect_isa(void) +__initfunc(static int +cy_detect_isa(void)) { unsigned short cy_isa_irq,nboard; volatile ucchar *cy_isa_address; unsigned short i,j,cy_isa_nchan; +#ifdef MODULE + int isparam = 0; +#endif nboard = 0; +#ifdef MODULE + /* Check for module parameters */ + for(i = 0 ; i < NR_CARDS; i++) { + if (maddr[i] || i) { + isparam = 1; + cy_isa_addresses[i] = (ucchar *)maddr[i]; + } + if (!maddr[i]) + break; + } +#endif + /* scan the address table probing for Cyclom-Y/ISA boards */ for (i = 0 ; i < NR_ISA_ADDRS ; i++) { cy_isa_address = cy_isa_addresses[i]; @@ -4829,8 +4755,13 @@ continue; } +#ifdef MODULE + if (isparam && irq[i]) + cy_isa_irq = irq[i]; + else +#endif /* find out the board's irq by probing */ - cy_isa_irq = do_auto_irq(cy_isa_address); + cy_isa_irq = detect_isa_irq(cy_isa_address); if (cy_isa_irq == 0) { printk("Cyclom-Y/ISA found at 0x%lx ", (unsigned long) cy_isa_address); @@ -4910,8 +4841,8 @@ * sets global variables and return the number of PCI boards found. * --------------------------------------------------------------------- */ -static int __init -cy_detect_pci(void) +__initfunc(static int +cy_detect_pci(void)) { #ifdef CONFIG_PCI @@ -5054,6 +4985,11 @@ default: /* Old boards, use PLX_9060 */ plx_init(cy_pci_addr0, 0x6c); + /* For some yet unknown reason, once the PLX9060 reloads + the EEPROM, the IRQ is lost and, thus, we have to + re-write it to the PCI config. registers. + This will remain here until we find a permanent fix. */ + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq); cy_writew(cy_pci_addr0+0x68, cy_readw(cy_pci_addr0+0x68)|0x0900); @@ -5095,6 +5031,11 @@ #endif plx_init(cy_pci_addr0, 0x6c); + /* For some yet unknown reason, once the PLX9060 reloads + the EEPROM, the IRQ is lost and, thus, we have to + re-write it to the PCI config. registers. + This will remain here until we find a permanent fix. */ + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq); mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) cy_pci_addr0)->mail_box_0); @@ -5203,17 +5144,19 @@ cy_card[j].num_chips = -1; /* print message */ +#ifdef CONFIG_CYZ_INTR /* don't report IRQ if board is no IRQ */ - if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) { + if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", j+1,(ulong)cy_pci_addr2, (ulong)(cy_pci_addr2 + CyPCI_Zwin - 1), (int)cy_pci_irq); - }else{ + else +#endif /* CONFIG_CYZ_INTR */ printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ", j+1,(ulong)cy_pci_addr2, (ulong)(cy_pci_addr2 + CyPCI_Zwin - 1)); - } + printk("%d channels starting from port %d.\n", cy_pci_nchan,cy_next_channel); #ifdef CONFIG_CYZ_INTR @@ -5288,17 +5231,19 @@ cy_card[j].num_chips = -1; /* print message */ +#ifdef CONFIG_CYZ_INTR /* don't report IRQ if board is no IRQ */ - if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) { + if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", j+1,(ulong)cy_pci_addr2, (ulong)(cy_pci_addr2 + CyPCI_Ze_win - 1), (int)cy_pci_irq); - }else{ + else +#endif /* CONFIG_CYZ_INTR */ printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ", j+1,(ulong)cy_pci_addr2, (ulong)(cy_pci_addr2 + CyPCI_Ze_win - 1)); - } + printk("%d channels starting from port %d.\n", cy_pci_nchan,cy_next_channel); #ifdef CONFIG_CYZ_INTR @@ -5414,8 +5359,8 @@ extra ports are ignored. */ -int __init -cy_init(void) +__initfunc(int +cy_init(void)) { struct cyclades_port *info; struct cyclades_card *cinfo; @@ -5424,9 +5369,6 @@ unsigned long mailbox; unsigned short chip_number; int nports; -#ifdef CY_PROC - struct proc_dir_entry *ent; -#endif init_bh(CYCLADES_BH, do_cyclades_bh); @@ -5530,12 +5472,13 @@ /* initialize per-port data structures for each valid board found */ for (board = 0 ; board < cy_nboard ; board++) { cinfo = &cy_card[board]; - if (cinfo->num_chips == -1){ /* Cyclades-Z */ + if (cinfo->num_chips == -1) { /* Cyclades-Z */ number_z_boards++; mailbox = cy_readl(&((struct RUNTIME_9060 *) cy_card[board].ctl_addr)->mail_box_0); nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; cinfo->intr_enabled = 0; + spin_lock_init(&cinfo->card_lock); for (port = cinfo->first_line ; port < cinfo->first_line + nports; port++) @@ -5578,9 +5521,9 @@ cy_callout_driver.init_termios; info->normal_termios = cy_serial_driver.init_termios; - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->shutdown_wait); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->shutdown_wait); /* info->session */ /* info->pgrp */ info->read_status_mask = 0; @@ -5594,6 +5537,7 @@ continue; }else{ /* Cyclom-Y of some kind*/ index = cinfo->bus_index; + spin_lock_init(&cinfo->card_lock); for (port = cinfo->first_line ; port < cinfo->first_line + 4*cinfo->num_chips ; port++) @@ -5647,9 +5591,9 @@ cy_callout_driver.init_termios; info->normal_termios = cy_serial_driver.init_termios; - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->shutdown_wait); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->shutdown_wait); /* info->session */ /* info->pgrp */ info->read_status_mask = @@ -5671,11 +5615,6 @@ } #endif /* CONFIG_CYZ_INTR */ -#ifdef CY_PROC - ent = create_proc_entry("cyclades", S_IFREG | S_IRUGO, 0); - ent->read_proc = cyclades_get_proc_info; -#endif - return 0; } /* cy_init */ @@ -5729,10 +5668,6 @@ free_page((unsigned long) tmp_buf); tmp_buf = NULL; } -#ifdef CY_PROC - remove_proc_entry("cyclades", 0); -#endif - } /* cleanup_module */ #else /* called by linux/init/main.c to parse command line options */ @@ -5796,8 +5731,7 @@ printk(" session pgrp open_wait = %lx %lx %lx\n", info->session, info->pgrp, (long)info->open_wait); - - save_flags(flags); cli(); + CY_LOCK(info, flags); base_addr = (unsigned char*) (cy_card[card].base_addr @@ -5854,7 +5788,7 @@ printk(" CyTBPR %x\n", cy_readb(base_addr + CyTBPR<= 0) { @@ -354,8 +353,6 @@ retv += written; } - up (&lp_table[minor].port_mutex); - if (signal_pending (current)) { if (retv == 0) retv = -EINTR; @@ -392,6 +389,8 @@ lp_parport_release (minor); + up (&lp_table[minor].port_mutex); + return retv; } @@ -414,35 +413,36 @@ if (count > LP_BUFFER_SIZE) count = LP_BUFFER_SIZE; + if (down_interruptible (&lp_table[minor].port_mutex)) + return -EINTR; + lp_parport_claim (minor); - if (!down_interruptible (&lp_table[minor].port_mutex)) { - for (;;) { - retval = parport_read (port, kbuf, count); + for (;;) { + retval = parport_read (port, kbuf, count); - if (retval) - break; + if (retval) + break; - if (file->f_flags & O_NONBLOCK) - break; + if (file->f_flags & O_NONBLOCK) + break; - /* Wait for an interrupt. */ - interruptible_sleep_on_timeout (&lp_table[minor].waitq, - LP_TIMEOUT_POLLED); + /* Wait for an interrupt. */ + interruptible_sleep_on_timeout (&lp_table[minor].waitq, + LP_TIMEOUT_POLLED); - if (signal_pending (current)) { - retval = -EINTR; - break; - } + if (signal_pending (current)) { + retval = -EINTR; + break; } - - up (&lp_table[minor].port_mutex); } lp_parport_release (minor); if (retval > 0 && copy_to_user (buf, kbuf, retval)) retval = -EFAULT; + + up (&lp_table[minor].port_mutex); return retval; } diff -u --recursive --new-file v2.3.10/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c --- v2.3.10/linux/drivers/char/pc_keyb.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/pc_keyb.c Fri Jul 9 17:03:24 1999 @@ -690,9 +690,6 @@ void __init pckbd_init_hw(void) { - /* Get the keyboard controller registers (incomplete decode) */ - request_region(0x60, 16, "keyboard"); - /* Flush any pending input. */ kbd_clear_input(); diff -u --recursive --new-file v2.3.10/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c --- v2.3.10/linux/drivers/char/ppdev.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/ppdev.c Sat Jul 17 21:17:21 1999 @@ -50,14 +50,10 @@ #define min(a,b) ((a) < (b) ? (a) : (b)) #endif -/* The device minor encodes the parport number and (arbitrary) - * pardevice number as (port << 4) | dev. */ -#define PP_PORT(minor) ((minor >> 4) & 0xf) -#define PP_DEV(minor) ((minor) & 0xf) - struct pp_struct { struct pardevice * pdev; wait_queue_head_t irq_wait; + int got_irq; int mode; unsigned int flags; }; @@ -71,7 +67,11 @@ #define PP_BUFFER_SIZE 256 #define PARDEVICE_MAX 8 -static struct pp_struct pp_table[PARPORT_MAX][PARDEVICE_MAX]; +static inline void enable_irq (struct pp_struct *pp) +{ + struct parport *port = pp->pdev->port; + port->ops->enable_irq (port); +} static loff_t pp_lseek (struct file * file, long long offset, int origin) { @@ -165,17 +165,16 @@ loff_t * ppos) { unsigned int minor = MINOR (file->f_dentry->d_inode->i_rdev); - unsigned int portnum = PP_PORT (minor); - unsigned int dev = PP_DEV (minor); + struct pp_struct *pp = file->private_data; char * kbuffer; ssize_t bytes_read = 0; ssize_t got = 0; - if (!(pp_table[portnum][dev].flags & PP_CLAIMED)) { + if (!(pp->flags & PP_CLAIMED)) { /* Don't have the port claimed */ - printk (KERN_DEBUG CHRDEV "%02x: claim the port first\n", + printk (KERN_DEBUG CHRDEV "%x: claim the port first\n", minor); - return -EPERM; + return -EINVAL; } kbuffer = kmalloc (min (count, PP_BUFFER_SIZE), GFP_KERNEL); @@ -185,16 +184,16 @@ while (bytes_read < count) { ssize_t need = min(count - bytes_read, PP_BUFFER_SIZE); - got = do_read (&pp_table[portnum][dev], kbuffer, need); + got = do_read (pp, kbuffer, need); - if (got < 0) { + if (got <= 0) { if (!bytes_read) bytes_read = got; break; } - if (copy_to_user (kbuffer, buf + bytes_read, got)) { + if (copy_to_user (buf + bytes_read, kbuffer, got)) { bytes_read = -EFAULT; break; } @@ -212,6 +211,7 @@ } kfree (kbuffer); + enable_irq (pp); return bytes_read; } @@ -219,17 +219,16 @@ loff_t * ppos) { unsigned int minor = MINOR (file->f_dentry->d_inode->i_rdev); - unsigned int portnum = PP_PORT (minor); - unsigned int dev = PP_DEV (minor); + struct pp_struct *pp = file->private_data; char * kbuffer; ssize_t bytes_written = 0; ssize_t wrote; - if (!(pp_table[portnum][dev].flags & PP_CLAIMED)) { + if (!(pp->flags & PP_CLAIMED)) { /* Don't have the port claimed */ - printk (KERN_DEBUG CHRDEV "%02x: claim the port first\n", + printk (KERN_DEBUG CHRDEV "%x: claim the port first\n", minor); - return -EPERM; + return -EINVAL; } kbuffer = kmalloc (min (count, PP_BUFFER_SIZE), GFP_KERNEL); @@ -244,7 +243,7 @@ break; } - wrote = do_write (&pp_table[portnum][dev], kbuffer, n); + wrote = do_write (pp, kbuffer, n); if (wrote < 0) { if (!bytes_written) @@ -265,19 +264,19 @@ } kfree (kbuffer); + enable_irq (pp); return bytes_written; } static void pp_irq (int irq, void * private, struct pt_regs * unused) { struct pp_struct * pp = (struct pp_struct *) private; + pp->got_irq = 1; wake_up_interruptible (&pp->irq_wait); } -static int register_device (int minor) +static int register_device (int minor, struct pp_struct *pp) { - unsigned int portnum = PP_PORT (minor); - unsigned int dev = PP_DEV (minor); struct parport * port; struct pardevice * pdev = NULL; char *name; @@ -287,10 +286,10 @@ if (name == NULL) return -ENOMEM; - sprintf (name, CHRDEV "%02x", minor); + sprintf (name, CHRDEV "%x", minor); port = parport_enumerate (); /* FIXME: use attach/detach */ - while (port && port->number != portnum) + while (port && port->number != minor) port = port->next; if (!port) { @@ -299,9 +298,9 @@ return -ENXIO; } - fl = (pp_table[portnum][dev].flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; + fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; pdev = parport_register_device (port, name, NULL, NULL, pp_irq, fl, - &pp_table[portnum][dev]); + pp); if (!pdev) { printk (KERN_WARNING "%s: failed to register device!\n", name); @@ -309,7 +308,7 @@ return -ENXIO; } - pp_table[portnum][dev].pdev = pdev; + pp->pdev = pdev; printk (KERN_DEBUG "%s: registered pardevice\n", name); return 0; } @@ -318,36 +317,38 @@ unsigned int cmd, unsigned long arg) { unsigned int minor = MINOR(inode->i_rdev); - unsigned int portnum = PP_PORT (minor); - unsigned int dev = PP_DEV (minor); + struct pp_struct *pp = file->private_data; struct parport * port; /* First handle the cases that don't take arguments. */ if (cmd == PPCLAIM) { - if (pp_table[portnum][dev].flags & PP_CLAIMED) { + if (pp->flags & PP_CLAIMED) { printk (KERN_DEBUG CHRDEV - "%02x: you've already got it!\n", minor); + "%x: you've already got it!\n", minor); return -EINVAL; } /* Deferred device registration. */ - if (!pp_table[portnum][dev].pdev) { - int err = register_device (minor); + if (!pp->pdev) { + int err = register_device (minor, pp); if (err) return err; } - parport_claim_or_block (pp_table[portnum][dev].pdev); - pp_table[portnum][dev].flags |= PP_CLAIMED; + parport_claim_or_block (pp->pdev); + pp->flags |= PP_CLAIMED; + + /* For interrupt-reporting to work, we need to be + * informed of each interrupt. */ + enable_irq (pp); return 0; } - port = pp_table[portnum][dev].pdev->port; if (cmd == PPEXCL) { - if (pp_table[portnum][dev].pdev) { - printk (KERN_DEBUG CHRDEV "%02x: too late for PPEXCL; " + if (pp->pdev) { + printk (KERN_DEBUG CHRDEV "%x: too late for PPEXCL; " "already registered\n", minor); - if (pp_table[portnum][dev].flags & PP_EXCL) + if (pp->flags & PP_EXCL) /* But it's not really an error. */ return 0; /* There's no chance of making the driver happy. */ @@ -356,22 +357,33 @@ /* Just remember to register the device exclusively * when we finally do the registration. */ - pp_table[portnum][dev].flags |= PP_EXCL; + pp->flags |= PP_EXCL; + return 0; + } + + if (cmd == PPSETMODE) { + int mode; + if (copy_from_user (&mode, (int *) arg, sizeof (mode))) + return -EFAULT; + /* FIXME: validate mode */ + pp->mode = mode; return 0; } /* Everything else requires the port to be claimed, so check * that now. */ - if ((pp_table[portnum][dev].flags & PP_CLAIMED) == 0) { - printk (KERN_DEBUG CHRDEV "%02x: claim the port first\n", + if ((pp->flags & PP_CLAIMED) == 0) { + printk (KERN_DEBUG CHRDEV "%x: claim the port first\n", minor); - return -EPERM; + return -EINVAL; } + port = pp->pdev->port; switch (cmd) { unsigned char reg; unsigned char mask; int mode; + int ret; case PPRSTATUS: reg = parport_read_status (port); @@ -389,19 +401,12 @@ sizeof (reg)); case PPYIELD: - parport_yield_blocking (pp_table[portnum][dev].pdev); + parport_yield_blocking (pp->pdev); return 0; case PPRELEASE: - parport_release (pp_table[portnum][dev].pdev); - pp_table[portnum][dev].flags &= ~PP_CLAIMED; - return 0; - - case PPSETMODE: - if (copy_from_user (&mode, (int *) arg, sizeof (mode))) - return -EFAULT; - /* FIXME: validate mode */ - pp_table[portnum][dev].mode = mode; + parport_release (pp->pdev); + pp->flags &= ~PP_CLAIMED; return 0; case PPWCONTROL: @@ -439,10 +444,12 @@ if (copy_from_user (&mode, (int *) arg, sizeof (mode))) return -EFAULT; /* FIXME: validate mode */ - return parport_negotiate (port, mode); + ret = parport_negotiate (port, mode); + enable_irq (pp); + return ret; default: - printk (KERN_DEBUG CHRDEV "%02x: What? (cmd=0x%x\n", minor, + printk (KERN_DEBUG CHRDEV "%x: What? (cmd=0x%x)\n", minor, cmd); return -EINVAL; } @@ -454,24 +461,26 @@ static int pp_open (struct inode * inode, struct file * file) { unsigned int minor = MINOR (inode->i_rdev); - unsigned int portnum = PP_PORT (minor); - unsigned int dev = PP_DEV (minor); + struct pp_struct *pp; - if (portnum >= PARPORT_MAX) + if (minor >= PARPORT_MAX) return -ENXIO; - if (pp_table[portnum][dev].pdev) - return -EBUSY; + pp = kmalloc (GFP_KERNEL, sizeof (struct pp_struct)); + if (!pp) + return -ENOMEM; - pp_table[portnum][dev].mode = IEEE1284_MODE_COMPAT; - pp_table[portnum][dev].flags = 0; - init_waitqueue_head (&pp_table[portnum][dev].irq_wait); + pp->mode = IEEE1284_MODE_COMPAT; + pp->flags = 0; + pp->got_irq = 0; + init_waitqueue_head (&pp->irq_wait); /* Defer the actual device registration until the first claim. * That way, we know whether or not the driver wants to have * exclusive access to the port (PPEXCL). */ - pp_table[portnum][dev].pdev = NULL; + pp->pdev = NULL; + file->private_data = pp; MOD_INC_USE_COUNT; return 0; @@ -480,42 +489,46 @@ static int pp_release (struct inode * inode, struct file * file) { unsigned int minor = MINOR (inode->i_rdev); - unsigned int portnum = PP_PORT (minor); - unsigned int dev = PP_DEV (minor); + struct pp_struct *pp = file->private_data; - if (pp_table[portnum][dev].flags & PP_CLAIMED) { - parport_release (pp_table[portnum][dev].pdev); - printk (KERN_DEBUG CHRDEV "%02x: released pardevice because " + if (pp->flags & PP_CLAIMED) { + parport_release (pp->pdev); + printk (KERN_DEBUG CHRDEV "%x: released pardevice because " "user-space forgot\n", minor); } - if (pp_table[portnum][dev].pdev) { - kfree (pp_table[portnum][dev].pdev->name); - parport_unregister_device (pp_table[portnum][dev].pdev); - pp_table[portnum][dev].pdev = NULL; - printk (KERN_DEBUG CHRDEV "%02x: unregistered pardevice\n", + if (pp->pdev) { + kfree (pp->pdev->name); + parport_unregister_device (pp->pdev); + pp->pdev = NULL; + printk (KERN_DEBUG CHRDEV "%x: unregistered pardevice\n", minor); } + kfree (pp); + MOD_DEC_USE_COUNT; return 0; } -#if 0 static unsigned int pp_poll (struct file * file, poll_table * wait) { - unsigned int minor = MINOR (file->f_dentry->d_inode->i_rdev); - poll_wait (file, &pp_table[minor].irq_wait, wait); - return 0; /* FIXME! Return value is wrong here */ + struct pp_struct *pp = file->private_data; + unsigned int mask = 0; + if (pp->got_irq) { + pp->got_irq = 0; + mask |= POLLIN | POLLRDNORM; + } + poll_wait (file, &pp->irq_wait, wait); + return mask; } -#endif static struct file_operations pp_fops = { pp_lseek, pp_read, pp_write, NULL, /* pp_readdir */ - NULL, /* pp_poll */ + pp_poll, pp_ioctl, NULL, /* pp_mmap */ pp_open, diff -u --recursive --new-file v2.3.10/linux/drivers/char/sysrq.c linux/drivers/char/sysrq.c --- v2.3.10/linux/drivers/char/sysrq.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/sysrq.c Mon Jul 19 23:08:41 1999 @@ -40,7 +40,7 @@ struct task_struct *p; for_each_task(p) { - if (p->pid && p->mm != &init_mm) { /* Not swapper nor kernel thread */ + if (p->mm) { /* Not swapper nor kernel thread */ if (p->pid == 1 && even_init) /* Ugly hack to kill init */ p->pid = 0x8000; force_sig(sig, p); diff -u --recursive --new-file v2.3.10/linux/drivers/char/vt.c linux/drivers/char/vt.c --- v2.3.10/linux/drivers/char/vt.c Wed Jun 30 13:38:19 1999 +++ linux/drivers/char/vt.c Fri Jul 9 15:05:41 1999 @@ -670,7 +670,7 @@ case KDSIGACCEPT: { extern int spawnpid, spawnsig; - if (!perm) + if (!perm || !capable(CAP_KILL)) return -EPERM; if (arg < 1 || arg > _NSIG || arg == SIGKILL) return -EINVAL; diff -u --recursive --new-file v2.3.10/linux/drivers/misc/parport_arc.c linux/drivers/misc/parport_arc.c --- v2.3.10/linux/drivers/misc/parport_arc.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/misc/parport_arc.c Tue Jul 13 09:29:34 1999 @@ -14,7 +14,7 @@ * a subset of the standard printer control lines connected. */ -#include +#include #include #include #include diff -u --recursive --new-file v2.3.10/linux/drivers/misc/parport_ieee1284.c linux/drivers/misc/parport_ieee1284.c --- v2.3.10/linux/drivers/misc/parport_ieee1284.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/misc/parport_ieee1284.c Wed Jul 21 15:38:39 1999 @@ -11,7 +11,7 @@ */ #include -#include +#include #include #include #include @@ -220,7 +220,7 @@ printk (KERN_ERR "parport: IEEE1284 not supported in this kernel\n"); return -1; #else - int m = mode; + int m = mode & ~IEEE1284_ADDR; unsigned char xflag; port = port->physport; @@ -229,6 +229,12 @@ if (port->ieee1284.mode == mode) return 0; + /* Is the difference just an address-or-not bit? */ + if ((port->ieee1284.mode & ~IEEE1284_ADDR) == (mode & ~IEEE1284_ADDR)){ + port->ieee1284.mode = mode; + return 0; + } + /* Go to compability forward idle mode */ if (port->ieee1284.mode != IEEE1284_MODE_COMPAT) parport_ieee1284_terminate (port); @@ -409,10 +415,11 @@ #else ssize_t retval; int mode = port->ieee1284.mode; + int addr = mode & IEEE1284_ADDR; size_t (*fn) (struct parport *, const void *, size_t, int); - /* Ignore the device-ID-request bit. */ - mode &= ~IEEE1284_DEVICEID; + /* Ignore the device-ID-request bit and the address bit. */ + mode &= ~(IEEE1284_DEVICEID | IEEE1284_ADDR); /* Use the mode we're in. */ switch (mode) { @@ -426,13 +433,19 @@ case IEEE1284_MODE_EPP: DPRINTK (KERN_DEBUG "%s: Using EPP mode\n", port->name); - fn = port->ops->epp_write_data; + if (addr) + fn = port->ops->epp_write_addr; + else + fn = port->ops->epp_write_data; break; case IEEE1284_MODE_ECP: case IEEE1284_MODE_ECPRLE: DPRINTK (KERN_DEBUG "%s: Using ECP mode\n", port->name); - fn = port->ops->ecp_write_data; + if (addr) + fn = port->ops->ecp_write_addr; + else + fn = port->ops->ecp_write_data; break; case IEEE1284_MODE_ECPSWE: @@ -440,7 +453,10 @@ port->name); /* The caller has specified that it must be emulated, * even if we have ECP hardware! */ - fn = parport_ieee1284_ecp_write_data; + if (addr) + fn = parport_ieee1284_ecp_write_addr; + else + fn = parport_ieee1284_ecp_write_data; break; default: @@ -464,10 +480,11 @@ return -ENODEV; #else int mode = port->physport->ieee1284.mode; + int addr = mode & IEEE1284_ADDR; size_t (*fn) (struct parport *, void *, size_t, int); - /* Ignore the device-ID-request bit. */ - mode &= ~IEEE1284_DEVICEID; + /* Ignore the device-ID-request bit and the address bit. */ + mode &= ~(IEEE1284_DEVICEID | IEEE1284_ADDR); /* Use the mode we're in. */ switch (mode) { @@ -486,7 +503,10 @@ case IEEE1284_MODE_EPP: DPRINTK (KERN_DEBUG "%s: Using EPP mode\n", port->name); - fn = port->ops->epp_read_data; + if (addr) + fn = port->ops->epp_read_addr; + else + fn = port->ops->epp_read_data; break; case IEEE1284_MODE_ECP: diff -u --recursive --new-file v2.3.10/linux/drivers/misc/parport_init.c linux/drivers/misc/parport_init.c --- v2.3.10/linux/drivers/misc/parport_init.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/misc/parport_init.c Tue Jul 13 09:29:34 1999 @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include diff -u --recursive --new-file v2.3.10/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c --- v2.3.10/linux/drivers/misc/parport_pc.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/misc/parport_pc.c Thu Jul 15 14:36:27 1999 @@ -314,8 +314,7 @@ void parport_pc_init_state(struct pardevice *dev, struct parport_state *s) { - struct parport_pc_private *priv = dev->port->physport->private_data; - priv->ctr = s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0); + s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0); s->u.pc.ecr = 0x24; } @@ -1377,7 +1376,8 @@ static int __init irq_probe_ECP(struct parport *pb) { - int irqs, i; + int i; + unsigned long irqs; sti(); irqs = probe_irq_on(); diff -u --recursive --new-file v2.3.10/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c --- v2.3.10/linux/drivers/misc/parport_share.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/misc/parport_share.c Tue Jul 13 09:29:34 1999 @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.3.10/linux/drivers/net/hp100.c linux/drivers/net/hp100.c --- v2.3.10/linux/drivers/net/hp100.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/hp100.c Tue Jul 13 02:29:35 1999 @@ -121,8 +121,6 @@ #ifndef __initfunc #define __initfunc(__initarg) __initarg -#else -#include #endif #include "hp100.h" diff -u --recursive --new-file v2.3.10/linux/drivers/net/mace.c linux/drivers/net/mace.c --- v2.3.10/linux/drivers/net/mace.c Wed Mar 10 21:48:46 1999 +++ linux/drivers/net/mace.c Mon Jul 12 16:21:25 1999 @@ -682,8 +682,10 @@ ++mp->stats.tx_carrier_errors; if (fs & (UFLO|LCOL|RTRY)) ++mp->stats.tx_aborted_errors; - } else + } else { + mp->stats.tx_bytes += mp->tx_bufs[i]->len; ++mp->stats.tx_packets; + } dev_kfree_skb(mp->tx_bufs[i]); --mp->tx_active; if (++i >= N_TX_RING) @@ -848,6 +850,7 @@ skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); mp->rx_bufs[i] = 0; + mp->stats.rx_bytes += skb->len; ++mp->stats.rx_packets; } } else { diff -u --recursive --new-file v2.3.10/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c --- v2.3.10/linux/drivers/net/pcnet32.c Sat Apr 24 17:51:48 1999 +++ linux/drivers/net/pcnet32.c Mon Jul 12 14:58:46 1999 @@ -13,7 +13,7 @@ * This driver is for PCnet32 and PCnetPCI based ethercards */ -static const char *version = "pcnet32.c:v1.21 31.3.99 tsbogend@alpha.franken.de\n"; +static const char *version = "pcnet32.c:v1.23 6.7.1999 tsbogend@alpha.franken.de\n"; #include #include @@ -149,6 +149,13 @@ * rewritten PCI card detection * added dwio mode to get driver working on some PPC machines * v1.21: added mii selection and mii ioctl + * v1.22: changed pci scanning code to make PPC people happy + * fixed switching to 32bit mode in pcnet32_open() (thanks + * to Michael Richard for noticing this one) + * added sub vendor/device id matching (thanks again to + * Michael Richard ) + * added chip id for 79c973/975 (thanks to Zach Brown ) + * v1.23 fixed small bug, when manual selecting MII speed/duplex */ @@ -185,6 +192,16 @@ #define PCNET32_TOTAL_SIZE 0x20 +/* some PCI ids */ +#ifndef PCI_DEVICE_ID_AMD_LANCE +#define PCI_VENDOR_ID_AMD 0x1022 +#define PCI_DEVICE_ID_AMD_LANCE 0x2000 +#endif +#ifndef PCI_DEVICE_ID_AMD_PCNETHOME +#define PCI_DEVICE_ID_AMD_PCNETHOME 0x2001 +#endif + + #define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ /* The PCNET32 Rx and Tx ring descriptors. */ @@ -272,14 +289,19 @@ struct pcnet32_pci_id_info { const char *name; - u16 vendor_id, device_id, device_id_mask, flags; + u16 vendor_id, device_id, svid, sdid, flags; int io_size; int (*probe1) (struct device *, unsigned long, unsigned char, int, int); }; static struct pcnet32_pci_id_info pcnet32_tbl[] = { { "AMD PCnetPCI series", - 0x1022, 0x2000, 0xfffe, PCI_USES_IO|PCI_USES_MASTER, PCNET32_TOTAL_SIZE, + PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0, 0, + PCI_USES_IO|PCI_USES_MASTER, PCNET32_TOTAL_SIZE, + pcnet32_probe1}, + { "AMD PCnetHome series", + PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PCNETHOME, 0, 0, + PCI_USES_IO|PCI_USES_MASTER, PCNET32_TOTAL_SIZE, pcnet32_probe1}, {0,} }; @@ -418,30 +440,27 @@ #if defined(CONFIG_PCI) if (pci_present()) { - struct pci_dev *pdev; - unsigned char pci_bus, pci_device_fn; - int pci_index; + struct pci_dev *pdev = NULL; printk("pcnet32.c: PCI bios is present, checking for devices...\n"); - for (pci_index = 0; pci_index < 0xff; pci_index++) { - u16 vendor, device, pci_command; + while ((pdev = pci_find_class (PCI_CLASS_NETWORK_ETHERNET<<8, pdev))) { + u16 pci_command; int chip_idx; + u16 sdid,svid; - if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, - pci_index, &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) - break; - - pcibios_read_config_word(pci_bus, pci_device_fn, PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, PCI_DEVICE_ID, &device); - + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &sdid); + pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &svid); for (chip_idx = 0; pcnet32_tbl[chip_idx].vendor_id; chip_idx++) - if (vendor == pcnet32_tbl[chip_idx].vendor_id && - (device & pcnet32_tbl[chip_idx].device_id_mask) == pcnet32_tbl[chip_idx].device_id) + if ((pdev->vendor == pcnet32_tbl[chip_idx].vendor_id) && + (pdev->device == pcnet32_tbl[chip_idx].device_id) && + (pcnet32_tbl[chip_idx].svid == 0 || + (svid == pcnet32_tbl[chip_idx].svid)) && + (pcnet32_tbl[chip_idx].sdid == 0 || + (sdid == pcnet32_tbl[chip_idx].sdid))) break; if (pcnet32_tbl[chip_idx].vendor_id == 0) continue; - pdev = pci_find_slot(pci_bus, pci_device_fn); ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; #if defined(ADDR_64BITS) && defined(__alpha__) ioaddr |= ((long)pdev->base_address[1]) << 32; @@ -541,6 +560,10 @@ chipname = "PCnet/FAST+ 79C972"; fdx = 1; mii = 1; break; + case 0x2625: + chipname = "PCnet/FAST III 79C973"; + fdx = 1; mii = 1; + break; case 0x2626: chipname = "PCnet/Home 79C978"; fdx = 1; @@ -561,6 +584,9 @@ printk("pcnet32: pcnet32 media reset to %#x.\n", media); a->write_bcr (ioaddr, 49, media); break; + case 0x2627: + chipname = "PCnet/FAST III 79C975"; + fdx = 1; mii = 1; default: printk("pcnet32: PCnet version %#x, no PCnet32 chip.\n",chip_version); return ENODEV; @@ -693,7 +719,7 @@ lp->a.reset (ioaddr); /* switch pcnet32 to 32bit mode */ - lp->a.write_csr (ioaddr, 20, 2); + lp->a.write_bcr (ioaddr, 20, 2); if (pcnet32_debug > 1) printk("%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n", @@ -725,7 +751,7 @@ val |= 0x10; lp->a.write_csr (ioaddr, 124, val); - if (lp->mii & (lp->options & PORT_ASEL)) { + if (lp->mii & !(lp->options & PORT_ASEL)) { val = lp->a.read_bcr (ioaddr, 32) & ~0x38; /* disable Auto Negotiation, set 10Mpbs, HD */ if (lp->options & PORT_FD) val |= 0x10; @@ -952,7 +978,7 @@ struct device *dev = (struct device *)dev_id; struct pcnet32_private *lp; unsigned long ioaddr; - u16 csr0; + u16 csr0,rap; int boguscnt = max_interrupt_work; int must_restart; @@ -968,6 +994,7 @@ dev->interrupt = 1; + rap = lp->a.read_rap(ioaddr); while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) { /* Acknowledge all of the current interrupt sources ASAP. */ lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f); @@ -1069,6 +1096,7 @@ /* Clear any other interrupt, and set interrupt enable. */ lp->a.write_csr (ioaddr, 0, 0x7940); + lp->a.write_rap(ioaddr,rap); if (pcnet32_debug > 4) printk("%s: exiting interrupt, csr0=%#4.4x.\n", diff -u --recursive --new-file v2.3.10/linux/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c --- v2.3.10/linux/drivers/net/rcpci45.c Mon Apr 12 16:18:27 1999 +++ linux/drivers/net/rcpci45.c Tue Jul 20 16:40:30 1999 @@ -63,7 +63,6 @@ #include #include #include -#include #include #include /* For NR_IRQS only. */ #include @@ -211,9 +210,8 @@ int scan_status; int board_index = 0; unsigned char pci_irq_line; - unsigned short pci_command, vendor, device, class; unsigned int pci_ioaddr; - + struct pci_dev *pdev; scan_status = (pcibios_find_device (RC_PCI45_VENDOR_ID, @@ -224,75 +222,22 @@ #ifdef RCDEBUG printk("rc scan_status = 0x%X\n", scan_status); #endif - if (scan_status != PCIBIOS_SUCCESSFUL) + if (scan_status != PCIBIOS_SUCCESSFUL || + !((pdev = pci_find_slot(pci_bus, pci_device_fn)))) break; - pcibios_read_config_word(pci_bus, - pci_device_fn, - PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, - pci_device_fn, - PCI_DEVICE_ID, &device); - pcibios_read_config_byte(pci_bus, - pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); - pcibios_read_config_dword(pci_bus, - pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - pcibios_read_config_word(pci_bus, - pci_device_fn, - PCI_CLASS_DEVICE, &class); - - pci_ioaddr &= ~0xf; + pci_irq_line = pdev->irq; + pci_ioaddr = pdev->base_address[0]; + pci_ioaddr &= PCI_BASE_ADDRESS_MEM_MASK; #ifdef RCDEBUG printk("rc: Found RedCreek PCI adapter\n"); - printk("rc: pci class = 0x%x 0x%x \n", class, class>>8); printk("rc: pci_bus = %d, pci_device_fn = %d\n", pci_bus, pci_device_fn); printk("rc: pci_irq_line = 0x%x \n", pci_irq_line); printk("rc: pci_ioaddr = 0x%x\n", pci_ioaddr); #endif - if (check_region(pci_ioaddr, 2*32768)) - { - printk("rc: check_region failed\n"); - continue; - } -#ifdef RCDEBUG - else - { - printk("rc: check_region passed\n"); - } -#endif - - /* - * Get and check the bus-master and latency values. - * Some PCI BIOSes fail to set the master-enable bit. - */ - - pcibios_read_config_word(pci_bus, - pci_device_fn, - PCI_COMMAND, - &pci_command); - if ( ! (pci_command & PCI_COMMAND_MASTER)) { - printk("rc: PCI Master Bit has not been set!\n"); - - pci_command |= PCI_COMMAND_MASTER; - pcibios_write_config_word(pci_bus, - pci_device_fn, - PCI_COMMAND, - pci_command); - } - if ( ! (pci_command & PCI_COMMAND_MEMORY)) { - /* - * If the BIOS did not set the memory enable bit, what else - * did it not initialize? Skip this adapter. - */ - printk("rc: Adapter %d, PCI Memory Bit has not been set!\n", - cards_found); - printk("rc: Bios problem? \n"); - continue; - } - + pci_set_master(pdev); + if (!RCfound_device(dev, pci_ioaddr, pci_irq_line, pci_bus, pci_device_fn, board_index++, cards_found)) diff -u --recursive --new-file v2.3.10/linux/drivers/net/rtl8139.c linux/drivers/net/rtl8139.c --- v2.3.10/linux/drivers/net/rtl8139.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/rtl8139.c Wed Jul 14 10:18:12 1999 @@ -680,6 +680,7 @@ tp->tx_bufs = kmalloc(TX_BUF_SIZE * NUM_TX_DESC, GFP_KERNEL); tp->rx_ring = kmalloc(RX_BUF_LEN + 16, GFP_KERNEL); if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { + free_irq(dev->irq, dev); if (tp->tx_bufs) kfree(tp->tx_bufs); if (rtl8129_debug > 0) diff -u --recursive --new-file v2.3.10/linux/drivers/nubus/nubus.c linux/drivers/nubus/nubus.c --- v2.3.10/linux/drivers/nubus/nubus.c Tue Dec 29 11:32:06 1998 +++ linux/drivers/nubus/nubus.c Tue Jul 20 16:40:30 1999 @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include diff -u --recursive --new-file v2.3.10/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c --- v2.3.10/linux/drivers/pci/oldproc.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/pci/oldproc.c Tue Jul 20 16:40:55 1999 @@ -903,11 +903,11 @@ vendor, device); } - str = 0; /* to keep gcc shut... */ switch (status & PCI_STATUS_DEVSEL_MASK) { case PCI_STATUS_DEVSEL_FAST: str = "Fast devsel. "; break; case PCI_STATUS_DEVSEL_MEDIUM: str = "Medium devsel. "; break; case PCI_STATUS_DEVSEL_SLOW: str = "Slow devsel. "; break; + default: str = "Unknown devsel. "; } if (len + strlen(str) > size) { return -1; diff -u --recursive --new-file v2.3.10/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c --- v2.3.10/linux/drivers/scsi/aic7xxx.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/scsi/aic7xxx.c Sun Jul 18 21:15:13 1999 @@ -242,7 +242,6 @@ #include #include #include -#include #include "sd.h" #include "scsi.h" #include "hosts.h" @@ -270,7 +269,7 @@ 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -#define AIC7XXX_C_VERSION "5.1.18" +#define AIC7XXX_C_VERSION "5.1.19" #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -7186,7 +7185,7 @@ static int acquire_seeprom(struct aic7xxx_host *p) { - int count=0; + int wait; /* * Request access of the memory port. When access is @@ -7196,10 +7195,11 @@ * should be no contention. */ aic_outb(p, SEEMS, SEECTL); - while( ((aic_inb(p, SEECTL) & SEERDY) == 0) && count < 1000) { - mb(); - udelay(1); - count++; + wait = 1000; /* 1000 msec = 1 second */ + while ((wait > 0) && ((aic_inb(p, SEECTL) & SEERDY) == 0)) + { + wait--; + mdelay(1); /* 1 msec */ } if ((aic_inb(p, SEECTL) & SEERDY) == 0) { @@ -7419,21 +7419,27 @@ static unsigned char read_brdctl(struct aic7xxx_host *p) { - unsigned char brdctl; + unsigned char brdctl, value; - if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) + if (p->features & AHC_ULTRA2) { - brdctl = BRDRW; - if (p->flags & AHC_CHNLB) - brdctl |= BRDCS; - } - else if (p->features & AHC_ULTRA2) brdctl = BRDRW_ULTRA2; - else - brdctl = BRDRW | BRDCS; + aic_outb(p, brdctl, BRDCTL); + udelay(4); + return(aic_inb(p, BRDCTL)); + } + brdctl = BRDRW; + if ( !((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) || + (p->flags & AHC_CHNLB) ) + { + brdctl |= BRDCS; + } aic_outb(p, brdctl, BRDCTL); - udelay(10); - return (aic_inb(p, BRDCTL)); + udelay(1); + value = aic_inb(p, BRDCTL); + aic_outb(p, 0, BRDCTL); + udelay(1); + return (value); } /*+F************************************************************************* @@ -7448,41 +7454,40 @@ { unsigned char brdctl; - if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) + if (p->features & AHC_ULTRA2) { - brdctl = BRDSTB; - if (p->flags & AHC_CHNLB) - brdctl |= BRDCS; + brdctl = value; aic_outb(p, brdctl, BRDCTL); udelay(4); - brdctl |= value; - } - else if (p->features & AHC_ULTRA2) - { - brdctl = value; + brdctl |= BRDSTB_ULTRA2; + aic_outb(p, brdctl, BRDCTL); + udelay(4); + brdctl &= ~BRDSTB_ULTRA2; + aic_outb(p, brdctl, BRDCTL); + udelay(4); + read_brdctl(p); } else { + brdctl = BRDSTB; + if ( !((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) || + (p->flags & AHC_CHNLB) ) + { + brdctl |= BRDCS; + } brdctl = BRDSTB | BRDCS; aic_outb(p, brdctl, BRDCTL); - udelay(4); + udelay(1); brdctl |= value; - } - aic_outb(p, brdctl, BRDCTL); - udelay(4); - if (p->features & AHC_ULTRA2) - brdctl |= BRDSTB_ULTRA2; - else + aic_outb(p, brdctl, BRDCTL); + udelay(1); brdctl &= ~BRDSTB; - aic_outb(p, brdctl, BRDCTL); - udelay(4); - if (p->features & AHC_ULTRA2) - brdctl &= ~BRDSTB_ULTRA2; - else + aic_outb(p, brdctl, BRDCTL); + udelay(1); brdctl &= ~BRDCS; - aic_outb(p, brdctl, BRDCTL); - udelay(4); - read_brdctl(p); + aic_outb(p, brdctl, BRDCTL); + udelay(1); + } } /*+F************************************************************************* @@ -7499,10 +7504,11 @@ unsigned char brdctl; aic_outb(p, BRDRW | BRDCS, BRDCTL); - udelay(4); + udelay(1); aic_outb(p, 0, BRDCTL); - udelay(4); + udelay(1); brdctl = aic_inb(p, BRDCTL); + udelay(1); *int_50 = !(brdctl & BRDDAT5); *ext_present = !(brdctl & BRDDAT6); *eeprom = (aic_inb(p, SPIOCAP) & EEPROM); @@ -7611,7 +7617,6 @@ else max_target = 8; aic_outb(p, SEEMS | SEECS, SEECTL); - udelay(4); sxfrctl1 &= ~STPWEN; if ( (p->adapter_control & CFAUTOTERM) || (p->features & AHC_ULTRA2) ) @@ -7736,14 +7741,6 @@ p->host_no); } - if (enableLVD_high != 0) - { - brddat |= BRDDAT4; - if (aic7xxx_verbose & VERBOSE_PROBE2) - printk(KERN_INFO "(scsi%d) LVD High byte termination Enabled\n", - p->host_no); - } - if (enableLVD_low != 0) { sxfrctl1 |= STPWEN; @@ -7752,17 +7749,17 @@ printk(KERN_INFO "(scsi%d) LVD Low byte termination Enabled\n", p->host_no); } - } - else - { - if (p->adapter_control & CFWSTERM) + + if (enableLVD_high != 0) { - brddat |= BRDDAT6; + brddat |= BRDDAT4; if (aic7xxx_verbose & VERBOSE_PROBE2) - printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n", + printk(KERN_INFO "(scsi%d) LVD High byte termination Enabled\n", p->host_no); } - + } + else + { if (p->adapter_control & CFSTERM) { if (p->features & AHC_ULTRA2) @@ -7773,6 +7770,14 @@ printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n", p->host_no); } + + if (p->adapter_control & CFWSTERM) + { + brddat |= BRDDAT6; + if (aic7xxx_verbose & VERBOSE_PROBE2) + printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n", + p->host_no); + } } aic_outb(p, sxfrctl1, SXFRCTL1); write_brdctl(p, brddat); @@ -8090,7 +8095,11 @@ /* Select channel B */ aic_outb(p, aic_inb(p, SBLKCTL) | SELBUSB, SBLKCTL); - term = (aic_inb(p, SXFRCTL1) & STPWEN); + if ((p->flags & AHC_SEEPROM_FOUND) || (aic7xxx_override_term != -1)) + term = (aic_inb(p, SXFRCTL1) & STPWEN); + else + term = ((p->flags & AHC_TERM_ENB_B) ? STPWEN : 0); + aic_outb(p, p->scsi_id_b, SCSIID); scsi_conf = aic_inb(p, SCSICONF + 1); aic_outb(p, DFON | SPIOEN, SXFRCTL0); @@ -8112,7 +8121,10 @@ { aic_outb(p, p->scsi_id, SCSIID); } - term = (aic_inb(p, SXFRCTL1) & STPWEN); + if ((p->flags & AHC_SEEPROM_FOUND) || (aic7xxx_override_term != -1)) + term = (aic_inb(p, SXFRCTL1) & STPWEN); + else + term = ((p->flags & (AHC_TERM_ENB_A|AHC_TERM_ENB_LVD)) ? STPWEN : 0); scsi_conf = aic_inb(p, SCSICONF); aic_outb(p, DFON | SPIOEN, SXFRCTL0); aic_outb(p, (scsi_conf & ENSPCHK) | STIMESEL | term | @@ -9049,11 +9061,44 @@ #if defined(__i386__) || defined(__alpha__) +#ifdef CONFIG_PCI + /* + * PCI-bus chipset probe. + */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) + if (pci_present()) + { + if (pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82450GX, + NULL)) + aic7xxx_no_probe = 1; + if (pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82451NX, + NULL)) + aic7xxx_no_probe = 1; + } +#else +#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca + if (pcibios_present()) + { + unsigned char pci_bus, pci_devfn; + if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82450GX, + 0, &pci_bus, &pci_devfn)) ) + aic7xxx_no_probe = 1; + if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82451NX, + 0, &pci_bus, &pci_devfn)) ) + aic7xxx_no_probe = 1; + } +#endif /* LINUX_VERSION_CODE */ +#endif /* CONFIG_PCI */ /* * EISA/VL-bus card signature probe. */ slot = MINSLOT; - while ( (slot <= MAXSLOT) && !(aic7xxx_no_probe) ) + while ( (slot <= MAXSLOT) && + !(aic7xxx_no_probe) ) { base = SLOTBASE(slot) + MINREG; @@ -9311,6 +9356,10 @@ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED, AHC_AIC7860_FE, 7, 32, C46 }, + {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_38602, AHC_AIC7860, + AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED, + AHC_AIC7860_FE, 7, + 32, C46 }, {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AHC_AIC7860, AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED, AHC_AIC7860_FE, 7, @@ -9489,6 +9538,23 @@ temp_p->pci_device_fn = pdev->devfn; temp_p->base = pdev->base_address[0]; temp_p->mbase = pdev->base_address[1]; + temp_p->base &= PCI_BASE_ADDRESS_IO_MASK; + temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK; + current_p = list_p; + while(current_p) + { + if ( ((current_p->pci_bus == temp_p->pci_bus) && + (current_p->pci_device_fn == temp_p->pci_device_fn)) || + (current_p->base == temp_p->base) ) + { + /* duplicate PCI entry, skip it */ + kfree(temp_p); + temp_p = NULL; + } + current_p = current_p->next; + } + if ( temp_p == NULL ) + continue; if (aic7xxx_verbose & VERBOSE_PROBE2) printk("aic7xxx: <%s> at PCI %d/%d\n", board_names[aic_pdevs[i].board_name_index], @@ -9522,11 +9588,6 @@ #else /* LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) */ temp_p->pci_bus = pci_bus; temp_p->pci_device_fn = pci_devfn; - if (aic7xxx_verbose & VERBOSE_PROBE2) - printk("aic7xxx: <%s> at PCI %d/%d\n", - board_names[aic_pdevs[i].board_name_index], - PCI_SLOT(temp_p->pci_device_fn), - PCI_FUNC(temp_p->pci_device_fn)); pcibios_read_config_byte(pci_bus, pci_devfn, PCI_INTERRUPT_LINE, &pci_irq); temp_p->irq = pci_irq; @@ -9536,6 +9597,28 @@ pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_1, &mmapbase); temp_p->mbase = mmapbase; + temp_p->base &= PCI_BASE_ADDRESS_IO_MASK; + temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK; + current_p = list_p; + while(current_p) + { + if ( ((current_p->pci_bus == temp_p->pci_bus) && + (current_p->pci_device_fn == temp_p->pci_device_fn)) || + (current_p->base == temp_p->base) ) + { + /* duplicate PCI entry, skip it */ + kfree(temp_p); + temp_p = NULL; + } + current_p = current_p->next; + } + if ( temp_p == NULL ) + continue; + if (aic7xxx_verbose & VERBOSE_PROBE2) + printk("aic7xxx: <%s> at PCI %d/%d\n", + board_names[aic_pdevs[i].board_name_index], + PCI_SLOT(temp_p->pci_device_fn), + PCI_FUNC(temp_p->pci_device_fn)); pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command); if (aic7xxx_verbose & VERBOSE_PROBE2) { @@ -9563,12 +9646,6 @@ #endif /* AIC7XXX_STRICT_PCI_SETUP */ #endif /* LINUIX_VERSION_CODE > KERNEL_VERSION(2,1,92) */ - /* - * The first bit (LSB) of PCI_BASE_ADDRESS_0 is always set, so - * we mask it off. - */ - temp_p->base &= PCI_BASE_ADDRESS_IO_MASK; - temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK; temp_p->unpause = INTEN; temp_p->pause = temp_p->unpause | PAUSE; if ( ((temp_p->base == 0) && @@ -9586,6 +9663,9 @@ } #ifdef MMAPIO + if ( !(temp_p->flags & AHC_MULTI_CHANNEL) || + ((temp_p->chip != (AHC_AIC7870 | AHC_PCI)) && + (temp_p->chip != (AHC_AIC7880 | AHC_PCI))) ) { unsigned long page_offset, base; diff -u --recursive --new-file v2.3.10/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c --- v2.3.10/linux/drivers/scsi/eata_dma.c Tue Dec 29 11:35:48 1998 +++ linux/drivers/scsi/eata_dma.c Tue Jul 20 16:40:30 1999 @@ -70,7 +70,6 @@ #include #include #include -#include #include #include #include @@ -1404,116 +1403,64 @@ void find_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt) { - #ifndef CONFIG_PCI printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); #else - - u8 pci_bus, pci_device_fn; - static s16 pci_index = 0; /* Device index to PCI BIOS calls */ - u32 base = 0; - u16 com_adr; - u16 rev_device; - u32 error, i, x; + struct pci_dev *dev; + u32 base, x; u8 pal1, pal2, pal3; - if (pci_present()) { - for (i = 0; i <= MAXPCI; ++i, ++pci_index) { - if (pcibios_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, - pci_index, &pci_bus, &pci_device_fn)) - break; + for(dev=NULL; dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev);) { DBG(DBG_PROBE && DBG_PCI, - printk("eata_dma: find_PCI, HBA at bus %d, device %d," - " function %d, index %d\n", (s32)pci_bus, - (s32)((pci_device_fn & 0xf8) >> 3), - (s32)(pci_device_fn & 7), pci_index)); - - if (!(error = pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_CLASS_DEVICE, &rev_device))) { - if (rev_device == PCI_CLASS_STORAGE_SCSI) { - if (!(error = pcibios_read_config_word(pci_bus, - pci_device_fn, PCI_COMMAND, - (u16 *) & com_adr))) { - if (!((com_adr & PCI_COMMAND_IO) && - (com_adr & PCI_COMMAND_MASTER))) { - printk("eata_dma: find_PCI, HBA has IO or" - " BUSMASTER mode disabled\n"); - continue; - } - } else - printk("eata_dma: find_PCI, error %x while reading " - "PCI_COMMAND\n", error); - } else - printk("eata_dma: find_PCI, DEVICECLASSID %x didn't match\n", - rev_device); - } else { - printk("eata_dma: find_PCI, error %x while reading " - "PCI_CLASS_BASE\n", - error); + printk("eata_dma: find_PCI, HBA at %s\n", dev->name)); + pci_set_master(dev); + base = dev->base_address[0]; + if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) { + printk("eata_dma: invalid base address of device %s\n", dev->name); continue; } - - if (!(error = pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, (int *) &base))){ - - /* Check if the address is valid */ - if (base & 0x01) { - base &= 0xfffffffe; - /* EISA tag there ? */ - pal1 = inb(base); - pal2 = inb(base + 1); - pal3 = inb(base + 2); - if (((pal1 == DPT_ID1) && (pal2 == DPT_ID2)) || - ((pal1 == NEC_ID1) && (pal2 == NEC_ID2) && - (pal3 == NEC_ID3)) || - ((pal1 == ATT_ID1) && (pal2 == ATT_ID2) && - (pal3 == ATT_ID3))) - base += 0x08; - else - base += 0x10; /* Now, THIS is the real address */ - - if (base != 0x1f8) { - /* We didn't find it in the primary search */ - if (get_conf_PIO(base, buf) == TRUE) { - - /* OK. We made it till here, so we can go now - * and register it. We only have to check and - * eventually remove it from the EISA and ISA list - */ - DBG(DBG_PCI, printk("Registering PCI HBA\n")); - register_HBA(base, buf, tpnt, IS_PCI); - - if (base < 0x1000) { - for (x = 0; x < MAXISA; ++x) { - if (ISAbases[x] == base) { - ISAbases[x] = 0; - break; - } - } - } else if ((base & 0x0fff) == 0x0c88) - EISAbases[(base >> 12) & 0x0f] = 0; - continue; /* break; */ - } -#if CHECK_BLINK - else if (check_blink_state(base) == TRUE) { - printk("eata_dma: HBA is in BLINK state.\n" - "Consult your HBAs manual to correct this.\n"); + base &= PCI_BASE_ADDRESS_IO_MASK; + /* EISA tag there ? */ + pal1 = inb(base); + pal2 = inb(base + 1); + pal3 = inb(base + 2); + if (((pal1 == DPT_ID1) && (pal2 == DPT_ID2)) || + ((pal1 == NEC_ID1) && (pal2 == NEC_ID2) && + (pal3 == NEC_ID3)) || + ((pal1 == ATT_ID1) && (pal2 == ATT_ID2) && + (pal3 == ATT_ID3))) + base += 0x08; + else + base += 0x10; /* Now, THIS is the real address */ + if (base != 0x1f8) { + /* We didn't find it in the primary search */ + if (get_conf_PIO(base, buf) == TRUE) { + /* OK. We made it till here, so we can go now + * and register it. We only have to check and + * eventually remove it from the EISA and ISA list + */ + DBG(DBG_PCI, printk("Registering PCI HBA\n")); + register_HBA(base, buf, tpnt, IS_PCI); + + if (base < 0x1000) { + for (x = 0; x < MAXISA; ++x) { + if (ISAbases[x] == base) { + ISAbases[x] = 0; + break; + } } -#endif - } + } else if ((base & 0x0fff) == 0x0c88) + EISAbases[(base >> 12) & 0x0f] = 0; + } +#if CHECK_BLINK + else if (check_blink_state(base) == TRUE) { + printk("eata_dma: HBA is in BLINK state.\n" + "Consult your HBAs manual to correct this.\n"); } - } else { - printk("eata_dma: error %x while reading " - "PCI_BASE_ADDRESS_0\n", error); +#endif } } - } else { - printk("eata_dma: No BIOS32 extensions present. This driver release " - "still depends on it.\n" - " Skipping scan for PCI HBAs. \n"); - } #endif /* #ifndef CONFIG_PCI */ - return; } int eata_detect(Scsi_Host_Template * tpnt) diff -u --recursive --new-file v2.3.10/linux/drivers/scsi/eata_pio.c linux/drivers/scsi/eata_pio.c --- v2.3.10/linux/drivers/scsi/eata_pio.c Tue Dec 29 11:35:48 1998 +++ linux/drivers/scsi/eata_pio.c Tue Jul 20 16:40:30 1999 @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -881,100 +880,60 @@ void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt) { - #ifndef CONFIG_PCI - printk(KERN_ERR "eata_pio: kernel PCI support not enabled. Skipping scan " - "for PCI HBAs.\n"); + printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); #else - - u8 pci_bus, pci_device_fn; - static s16 pci_index = 0; /* Device index to PCI BIOS calls */ - u32 base = 0; - u16 com_adr; - u16 rev_device; - u32 error, i, x; - - if (pci_present()) { - for (i = 0; i <= MAXPCI; ++i, ++pci_index) { - if (pcibios_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, - pci_index, &pci_bus, &pci_device_fn)) - break; + struct pci_dev *dev; + u32 base, x; + + for(dev=NULL; dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev);) { DBG(DBG_PROBE && DBG_PCI, - printk("eata_pio: HBA at bus %d, device %d," - " function %d, index %d\n", (s32)pci_bus, - (s32)((pci_device_fn & 0xf8) >> 3), - (s32)(pci_device_fn & 7), pci_index)); - - if (!(error = pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_CLASS_DEVICE, &rev_device))) { - if (rev_device == PCI_CLASS_STORAGE_SCSI) { - if (!(error = pcibios_read_config_word(pci_bus, - pci_device_fn, PCI_COMMAND, - (u16 *) & com_adr))) { - if (!((com_adr & PCI_COMMAND_IO) && - (com_adr & PCI_COMMAND_MASTER))) { - printk("HBA has IO or BUSMASTER mode disabled\n"); - continue; - } - } else - printk("eata_pio: error %x while reading " - "PCI_COMMAND\n", error); - } else - printk("DEVICECLASSID %x didn't match\n", rev_device); - } else { - printk("eata_pio: error %x while reading PCI_CLASS_BASE\n", - error); + printk("eata_pio: find_PCI, HBA at %s\n", dev->name)); + pci_set_master(dev); + base = dev->base_address[0]; + if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) { + printk("eata_pio: invalid base address of device %s\n", dev->name); continue; } - - if (!(error = pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, (int *) &base))){ - - /* Check if the address is valid */ - if (base & 0x01) { - base &= 0xfffffffe; - /* EISA tag there ? */ - if ((inb(base) == 0x12) && (inb(base + 1) == 0x14)) - continue; /* Jep, it's forced, so move on */ - base += 0x10; /* Now, THIS is the real address */ - if (base != 0x1f8) { - /* We didn't find it in the primary search */ - if (get_pio_conf_PIO(base, buf) == TRUE) { - if (buf->FORCADR) /* If the address is forced */ - continue; /* we'll find it later */ - - /* OK. We made it till here, so we can go now - * and register it. We only have to check and - * eventually remove it from the EISA and ISA list - */ - - register_pio_HBA(base, buf, tpnt); - - if (base < 0x1000) { - for (x = 0; x < MAXISA; ++x) { - if (ISAbases[x] == base) { - ISAbases[x] = 0; - break; - } - } - } else if ((base & 0x0fff) == 0x0c88) { - x = (base >> 12) & 0x0f; - EISAbases[x] = 0; + base &= PCI_BASE_ADDRESS_IO_MASK; + /* EISA tag there ? */ + if ((inb(base) == 0x12) && (inb(base + 1) == 0x14)) + continue; /* Jep, it's forced, so move on */ + base += 0x10; /* Now, THIS is the real address */ + if (base != 0x1f8) { + /* We didn't find it in the primary search */ + if (get_pio_conf_PIO(base, buf) == TRUE) { + if (buf->FORCADR) /* If the address is forced */ + continue; /* we'll find it later */ + + /* OK. We made it till here, so we can go now + * and register it. We only have to check and + * eventually remove it from the EISA and ISA list + */ + + register_pio_HBA(base, buf, tpnt); + + if (base < 0x1000) { + for (x = 0; x < MAXISA; ++x) { + if (ISAbases[x] == base) { + ISAbases[x] = 0; + break; } - continue; /* break; */ } + } else if ((base & 0x0fff) == 0x0c88) { + x = (base >> 12) & 0x0f; + EISAbases[x] = 0; } + } +#if CHECK_BLINK + else if (check_blink_state(base) == TRUE) { + printk("eata_pio: HBA is in BLINK state.\n" + "Consult your HBAs manual to correct this.\n"); } - } else - printk("eata_pio: error %x while reading " - "PCI_BASE_ADDRESS_0\n", error); +#endif + } } - } else - printk("eata_pio: No BIOS32 extensions present. This driver release " - "still depends on it.\n" - " Skipping scan for PCI HBAs.\n"); #endif /* #ifndef CONFIG_PCI */ - return; } diff -u --recursive --new-file v2.3.10/linux/drivers/sgi/char/shmiq.c linux/drivers/sgi/char/shmiq.c --- v2.3.10/linux/drivers/sgi/char/shmiq.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/sgi/char/shmiq.c Fri Jul 16 09:27:46 1999 @@ -214,6 +214,8 @@ goto bad_file; v = shmiq_manage_file (file); + if (v<0) + fput(file); return v; /* diff -u --recursive --new-file v2.3.10/linux/drivers/sound/awacs_defs.h linux/drivers/sound/awacs_defs.h --- v2.3.10/linux/drivers/sound/awacs_defs.h Wed Mar 10 21:48:46 1999 +++ linux/drivers/sound/awacs_defs.h Mon Jul 12 16:21:25 1999 @@ -70,8 +70,8 @@ #define MASK_GAINMIC (0x0 << 8) /* Change Gain for Mic??? */ #define MASK_MUX_CD (0x1 << 9) /* Select CD in MUX */ -#define MASK_MUX_MIC (0x1 << 10) /* Select Mic in MUX */ -#define MASK_MUX_AUDIN (0x1 << 11) /* Select Audio In in MUX */ +#define MASK_MUX_AUDIN (0x1 << 10) /* Select Audio In in MUX */ +#define MASK_MUX_MIC (0x1 << 11) /* Select Mic in MUX */ #define MASK_MUX_LINE MASK_MUX_AUDIN #define GAINRIGHT(x) ((x) & MASK_GAINRIGHT) diff -u --recursive --new-file v2.3.10/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c --- v2.3.10/linux/drivers/sound/dmasound.c Mon Jun 7 12:12:22 1999 +++ linux/drivers/sound/dmasound.c Mon Jul 12 16:21:25 1999 @@ -131,7 +131,7 @@ static int irq_installed = 0; #endif /* MODULE */ static char **sound_buffers = NULL; - +static char **sound_read_buffers = NULL; #ifdef CONFIG_ATARI extern void atari_microwire_cmd(int cmd); @@ -184,6 +184,9 @@ static void *awacs_tx_cmd_space; static volatile struct dbdma_cmd *awacs_tx_cmds; +static void *awacs_rx_cmd_space; +static volatile struct dbdma_cmd *awacs_rx_cmds; + /* * Cached values of AWACS registers (we can't read them). * Except on the burgundy. XXX @@ -239,6 +242,7 @@ static int beep_volume = BEEP_VOLUME; static int beep_playing = 0; +static int awacs_beep_state = 0; static short *beep_buf; static volatile struct dbdma_cmd *beep_dbdma_cmd; static void (*orig_mksound)(unsigned int, unsigned int); @@ -276,10 +280,15 @@ #define MIN_BUFSIZE 4 #define MAX_BUFSIZE 128 /* Limit for Amiga */ -static int catchRadius = 0, numBufs = 4, bufSize = 32; +static int catchRadius = 0; +static int numBufs = 4, bufSize = 32; +static int numReadBufs = 4, readbufSize = 32; + MODULE_PARM(catchRadius, "i"); MODULE_PARM(numBufs, "i"); MODULE_PARM(bufSize, "i"); +MODULE_PARM(numreadBufs, "i"); +MODULE_PARM(readbufSize, "i"); #define arraysize(x) (sizeof(x)/sizeof(*(x))) #define min(x, y) ((x) < (y) ? (x) : (y)) @@ -630,6 +639,12 @@ static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); +static ssize_t pmac_ct_s16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_u16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); #endif /* CONFIG_PPC */ /*** Machine definitions *****************************************************/ @@ -681,6 +696,9 @@ SETTINGS soft; /* software settings */ SETTINGS dsp; /* /dev/dsp default settings */ TRANS *trans; /* supported translations */ +#if defined(CONFIG_PPC) + TRANS *read_trans; /* supported translations */ +#endif int volume_left; /* volume (range is machine dependent) */ int volume_right; int bass; /* tone (range is machine dependent) */ @@ -746,9 +764,11 @@ static void PMacSilence(void); static void PMacInit(void); static void PMacPlay(void); +static void PMacRecord(void); static int PMacSetFormat(int format); static int PMacSetVolume(int volume); static void pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs); +static void pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs); static void pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs); static void awacs_write(int val); static int awacs_get_volume(int reg, int lshift); @@ -776,6 +796,10 @@ size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); +static ssize_t sound_copy_translate_read(const u_char *userPtr, + size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); /* @@ -809,8 +833,8 @@ * Amiga: Bit 0 is set: a frame is loaded * Bit 1 is set: a frame is playing */ - int playing; - wait_queue_head_t write_queue, open_queue, sync_queue; + int active; + wait_queue_head_t action_queue, open_queue, sync_queue; int open_mode; int busy, syncing; #ifdef CONFIG_ATARI @@ -822,6 +846,7 @@ }; static struct sound_queue sq; +static struct sound_queue read_sq; #define sq_block_address(i) (sq.buffers[i]) #define SIGNAL_RECEIVED (signal_pending(current)) @@ -2172,6 +2197,135 @@ return stereo? utotal * 4: utotal * 2; } +static ssize_t pmac_ct_s8_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = sound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + + val = *p++; + data = val >> 8; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + if (stereo) { + val = *p; + data = val >> 8; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + } + p++; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static ssize_t pmac_ct_u8_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = sound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + + val = *p++; + data = (val >> 8) ^ 0x80; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + if (stereo) { + val = *p; + data = (val >> 8) ^ 0x80; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + } + p++; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static ssize_t pmac_ct_s16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + int stereo = sound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min(userCount, frameLeft); + if (!stereo) { + short *up = (short *) userPtr; + while (count > 0) { + short data; + data = *fp; + if (put_user(data, up++)) + return -EFAULT; + fp+=2; + count--; + } + } else { + if (copy_to_user((u_char *)userPtr, fp, count * 4)) + return -EFAULT; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + +static ssize_t pmac_ct_u16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); + int stereo = sound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + short *up = (short *) userPtr; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min(userCount, frameLeft); + while (count > 0) { + int data; + + data = *fp++; + data ^= mask; + if (put_user(data, up++)) + return -EFAULT; + if (stereo) { + data = *fp; + data ^= mask; + if (put_user(data, up++)) + return -EFAULT; + } + fp++; + count--; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + + #endif /* CONFIG_PPC */ @@ -2212,6 +2366,11 @@ pmac_ctx_law, pmac_ctx_law, pmac_ctx_s8, pmac_ctx_u8, pmac_ctx_s16, pmac_ctx_u16, pmac_ctx_s16, pmac_ctx_u16 }; + +static TRANS transAwacsNormalRead = { + NULL, NULL, pmac_ct_s8_read, pmac_ct_u8_read, + pmac_ct_s16_read, pmac_ct_u16_read, pmac_ct_s16_read, pmac_ct_u16_read +}; #endif /* CONFIG_PPC */ /*** Low level stuff *********************************************************/ @@ -2574,18 +2733,18 @@ /* Since only an even number of samples per frame can be played, we might lose one byte here. (TO DO) */ sq.front = (sq.front+1) % sq.max_count; - sq.playing++; + sq.active++; tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT; } static void AtaPlay(void) { - /* ++TeSche: Note that sq.playing is no longer just a flag but holds + /* ++TeSche: Note that sq.active is no longer just a flag but holds * the number of frames the DMA is currently programmed for instead, * may be 0, 1 (currently being played) or 2 (pre-programmed). * - * Changes done to sq.count and sq.playing are a bit more subtle again + * Changes done to sq.count and sq.active are a bit more subtle again * so now I must admit I also prefer disabling the irq here rather * than considering all possible situations. But the point is that * disabling the irq doesn't have any bad influence on this version of @@ -2596,13 +2755,13 @@ */ atari_disable_irq(IRQ_MFP_TIMA); - if (sq.playing == 2 || /* DMA is 'full' */ + if (sq.active == 2 || /* DMA is 'full' */ sq.count <= 0) { /* nothing to do */ atari_enable_irq(IRQ_MFP_TIMA); return; } - if (sq.playing == 0) { + if (sq.active == 0) { /* looks like there's nothing 'in' the DMA yet, so try * to put two frames into it (at least one is available). */ @@ -2650,7 +2809,7 @@ #if 0 /* ++TeSche: if you should want to test this... */ static int cnt = 0; - if (sq.playing == 2) + if (sq.active == 2) if (++cnt == 10) { /* simulate losing an interrupt */ cnt = 0; @@ -2667,7 +2826,7 @@ return; } - if (!sq.playing) { + if (!sq.active) { /* playing was interrupted and sq_reset() has already cleared * the sq variables, so better don't do anything here. */ @@ -2683,29 +2842,29 @@ * as soon as the irq gets through. */ sq.count--; - sq.playing--; + sq.active--; - if (!sq.playing) { + if (!sq.active) { tt_dmasnd.ctrl = DMASND_CTRL_OFF; sq.ignore_int = 1; } - WAKE_UP(sq.write_queue); + WAKE_UP(sq.action_queue); /* At least one block of the queue is free now so wake up a writing process blocked because of a full queue. */ - if ((sq.playing != 1) || (sq.count != 1)) + if ((sq.active != 1) || (sq.count != 1)) /* We must be a bit carefully here: sq.count indicates the * number of buffers used and not the number of frames to - * be played. If sq.count==1 and sq.playing==1 that means + * be played. If sq.count==1 and sq.active==1 that means * the only remaining frame was already programmed earlier * (and is currently running) so we mustn't call AtaPlay() * here, otherwise we'll play one frame too much. */ AtaPlay(); - if (!sq.playing) WAKE_UP(sq.sync_queue); + if (!sq.active) WAKE_UP(sq.sync_queue); /* We are not playing after AtaPlay(), so there is nothing to play any more. Wake up a process waiting for audio output to drain. */ @@ -2902,7 +3061,7 @@ custom.dmacon = AMI_AUDIO_8; } sq.front = (sq.front+1) % sq.max_count; - sq.playing |= AMI_PLAY_LOADED; + sq.active |= AMI_PLAY_LOADED; } @@ -2912,13 +3071,13 @@ custom.intena = IF_AUD0; - if (sq.playing & AMI_PLAY_LOADED) { + if (sq.active & AMI_PLAY_LOADED) { /* There's already a frame loaded */ custom.intena = IF_SETCLR | IF_AUD0; return; } - if (sq.playing & AMI_PLAY_PLAYING) + if (sq.active & AMI_PLAY_PLAYING) /* Increase threshold: frame 1 is already being played */ minframes = 2; @@ -2946,7 +3105,7 @@ { int minframes = 1; - if (!sq.playing) { + if (!sq.active) { /* Playing was interrupted and sq_reset() has already cleared * the sq variables, so better don't do anything here. */ @@ -2954,20 +3113,20 @@ return; } - if (sq.playing & AMI_PLAY_PLAYING) { + if (sq.active & AMI_PLAY_PLAYING) { /* We've just finished a frame */ sq.count--; - WAKE_UP(sq.write_queue); + WAKE_UP(sq.action_queue); } - if (sq.playing & AMI_PLAY_LOADED) + if (sq.active & AMI_PLAY_LOADED) /* Increase threshold: frame 1 is already being played */ minframes = 2; /* Shift the flags */ - sq.playing = (sq.playing<<1) & AMI_PLAY_MASK; + sq.active = (sq.active<<1) & AMI_PLAY_MASK; - if (!sq.playing) + if (!sq.active) /* No frame is playing, disable audio DMA */ custom.dmacon = AMI_AUDIO_OFF; @@ -2975,7 +3134,7 @@ /* Try to play the next frame */ AmiPlay(); - if (!sq.playing) + if (!sq.active) /* Nothing to play anymore. Wake up a process waiting for audio output to drain. */ WAKE_UP(sq.sync_queue); @@ -3001,7 +3160,8 @@ static int __init PMacIrqInit(void) { if (request_irq(awacs_irq, pmac_awacs_intr, 0, "AWACS", 0) - || request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "AWACS out", 0)) + || request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "AWACS out", 0) + || request_irq(awacs_rx_irq, pmac_awacs_rx_intr, 0, "AWACS in", 0)) return 0; return 1; } @@ -3015,7 +3175,10 @@ out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff); free_irq(awacs_irq, pmac_awacs_intr); free_irq(awacs_tx_irq, pmac_awacs_tx_intr); + free_irq(awacs_rx_irq, pmac_awacs_rx_intr); kfree(awacs_tx_cmd_space); + if (awacs_rx_cmd_space) + kfree(awacs_rx_cmd_space); if (beep_buf) kfree(beep_buf); kd_mksound = orig_mksound; @@ -3065,10 +3228,10 @@ sound.trans = &transAwacsNormal; else sound.trans = &transAwacsExpand; + sound.read_trans = &transAwacsNormalRead; sound.hard.speed = awacs_freqs[i]; awacs_rate_index = i; - PMacSilence(); /* XXX disable error interrupt on burgundy for now */ out_le32(&awacs->control, MASK_IEPC | (i << 8) | 0x11 | (awacs_revision < AWACS_BURGUNDY? MASK_IEE: 0)); @@ -3076,6 +3239,18 @@ awacs_write(awacs_reg[1] | MASK_ADDR1); out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); + /* We really want to execute a DMA stop command, after the AWACS + * is initialized. + * For reasons I don't understand, it stops the hissing noise + * common to many PowerBook G3 systems (like mine :-). Maybe it + * is just the AWACS control register change...... + */ + out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); + st_le16(&beep_dbdma_cmd->command, DBDMA_STOP); + out_le32(&awacs->control, (in_le32(&awacs->control) & ~0x1f00)); + out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd)); + out_le32(&awacs_txdma->control, RUN | (RUN << 16)); + sound.bal = -sound.soft.speed; } @@ -3163,20 +3338,23 @@ unsigned long flags; save_flags(flags); cli(); - if (beep_playing) { + if (awacs_beep_state) { /* sound takes precedence over beeps */ out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); out_le32(&awacs->control, (in_le32(&awacs->control) & ~0x1f00) - || (awacs_rate_index << 8)); + | (awacs_rate_index << 8)); out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); + out_le32(&awacs_txdma->cmdptr, virt_to_bus(&(awacs_tx_cmds[(sq.front+sq.active) % sq.max_count]))); + beep_playing = 0; + awacs_beep_state = 0; } - i = sq.front + sq.playing; + i = sq.front + sq.active; if (i >= sq.max_count) i -= sq.max_count; - while (sq.playing < 2 && sq.playing < sq.count) { - count = (sq.count == sq.playing + 1)? sq.rear_size: sq.block_size; + while (sq.active < 2 && sq.active < sq.count) { + count = (sq.count == sq.active + 1)?sq.rear_size:sq.block_size; if (count < sq.block_size && !sq.syncing) /* last block not yet filled, and we're not syncing. */ break; @@ -3187,14 +3365,33 @@ i = 0; out_le16(&awacs_tx_cmds[i].command, DBDMA_STOP); out_le16(&cp->command, OUTPUT_MORE + INTR_ALWAYS); - if (sq.playing == 0) + if (sq.active == 0) out_le32(&awacs_txdma->cmdptr, virt_to_bus(cp)); out_le32(&awacs_txdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); - ++sq.playing; + ++sq.active; } restore_flags(flags); } + +static void PMacRecord(void) +{ + unsigned long flags; + + if (read_sq.active) + return; + + save_flags(flags); cli(); + + /* This is all we have to do......Just start it up. + */ + out_le32(&awacs_rxdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); + read_sq.active = 1; + + restore_flags(flags); +} + + static void pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs) { @@ -3202,26 +3399,78 @@ int stat; volatile struct dbdma_cmd *cp; - while (sq.playing > 0) { + while (sq.active > 0) { cp = &awacs_tx_cmds[i]; stat = ld_le16(&cp->xfer_status); if ((stat & ACTIVE) == 0) break; /* this frame is still going */ --sq.count; - --sq.playing; + --sq.active; if (++i >= sq.max_count) i = 0; } if (i != sq.front) - WAKE_UP(sq.write_queue); + WAKE_UP(sq.action_queue); sq.front = i; PMacPlay(); - if (!sq.playing) + if (!sq.active) WAKE_UP(sq.sync_queue); } + +static void +pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs) +{ + + /* For some reason on my PowerBook G3, I get one interrupt + * when the interrupt vector is installed (like something is + * pending). This happens before the dbdma is initialize by + * us, so I just check the command pointer and if it is zero, + * just blow it off. + */ + if (in_le32(&awacs_rxdma->cmdptr) == 0) + return; + + /* We also want to blow 'em off when shutting down. + */ + if (read_sq.active == 0) + return; + + /* Check multiple buffers in case we were held off from + * interrupt processing for a long time. Geeze, I really hope + * this doesn't happen. + */ + while (awacs_rx_cmds[read_sq.rear].xfer_status) { + + /* Clear status and move on to next buffer. + */ + awacs_rx_cmds[read_sq.rear].xfer_status = 0; + read_sq.rear++; + + /* Wrap the buffer ring. + */ + if (read_sq.rear >= read_sq.max_active) + read_sq.rear = 0; + + /* If we have caught up to the front buffer, bump it. + * This will cause weird (but not fatal) results if the + * read loop is currently using this buffer. The user is + * behind in this case anyway, so weird things are going + * to happen. + */ + if (read_sq.rear == read_sq.front) { + read_sq.front++; + if (read_sq.front >= read_sq.max_active) + read_sq.front = 0; + } + } + + WAKE_UP(read_sq.action_queue); +} + + static void pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs) { @@ -3294,7 +3543,7 @@ beep_timer.expires = jiffies + ticks; add_timer(&beep_timer); } - if (beep_playing || sq.playing || beep_buf == NULL) { + if (beep_playing || sq.active || beep_buf == NULL) { restore_flags(flags); return; /* too hard, sorry :-( */ } @@ -3324,6 +3573,7 @@ st_le16(&beep_dbdma_cmd->xfer_status, 0); st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd)); st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf)); + awacs_beep_state = 1; save_flags(flags); cli(); if (beep_playing) { /* i.e. haven't been terminated already */ @@ -3781,6 +4031,45 @@ return 0; } +static ssize_t sound_copy_translate_read(const u_char *userPtr, + size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL; + + switch (sound.soft.format) { + case AFMT_MU_LAW: + ct_func = sound.read_trans->ct_ulaw; + break; + case AFMT_A_LAW: + ct_func = sound.read_trans->ct_alaw; + break; + case AFMT_S8: + ct_func = sound.read_trans->ct_s8; + break; + case AFMT_U8: + ct_func = sound.read_trans->ct_u8; + break; + case AFMT_S16_BE: + ct_func = sound.read_trans->ct_s16be; + break; + case AFMT_U16_BE: + ct_func = sound.read_trans->ct_u16be; + break; + case AFMT_S16_LE: + ct_func = sound.read_trans->ct_s16le; + break; + case AFMT_U16_LE: + ct_func = sound.read_trans->ct_u16le; + break; + } + if (ct_func) + return ct_func(userPtr, userCount, frame, frameUsed, frameLeft); + else + return 0; +} + /* * /dev/mixer abstraction @@ -3999,7 +4288,8 @@ data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_RECLEV - | SOUND_MASK_ALTPCM; + | SOUND_MASK_ALTPCM + | SOUND_MASK_MONITOR; return IOCTL_OUT(arg, data); case SOUND_MIXER_READ_RECMASK: data = SOUND_MASK_LINE | SOUND_MASK_MIC @@ -4013,20 +4303,27 @@ data |= SOUND_MASK_MIC; if (awacs_reg[0] & MASK_MUX_CD) data |= SOUND_MASK_CD; + if (awacs_reg[1] & MASK_LOOPTHRU) + data |= SOUND_MASK_MONITOR; return IOCTL_OUT(arg, data); case SOUND_MIXER_WRITE_RECSRC: IOCTL_IN(arg, data); data &= (SOUND_MASK_LINE - | SOUND_MASK_MIC | SOUND_MASK_CD); + | SOUND_MASK_MIC | SOUND_MASK_CD + | SOUND_MASK_MONITOR); awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC | MASK_MUX_AUDIN); + awacs_reg[1] &= ~MASK_LOOPTHRU; if (data & SOUND_MASK_LINE) awacs_reg[0] |= MASK_MUX_AUDIN; if (data & SOUND_MASK_MIC) awacs_reg[0] |= MASK_MUX_MIC; if (data & SOUND_MASK_CD) awacs_reg[0] |= MASK_MUX_CD; + if (data & SOUND_MASK_MONITOR) + awacs_reg[1] |= MASK_LOOPTHRU; awacs_write(awacs_reg[0] | MASK_ADDR0); + awacs_write(awacs_reg[1] | MASK_ADDR1); return IOCTL_OUT(arg, data); case SOUND_MIXER_READ_STEREODEVS: data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER @@ -4347,7 +4644,61 @@ } -static void sq_setup(int numBufs, int bufSize, char **buffers) +static int sq_allocate_read_buffers(void) +{ + int i; + int j; + + if (sound_read_buffers) + return 0; + sound_read_buffers = kmalloc(numReadBufs * sizeof(char *), GFP_KERNEL); + if (!sound_read_buffers) + return -ENOMEM; + for (i = 0; i < numBufs; i++) { + sound_read_buffers[i] = sound.mach.dma_alloc (readbufSize<<10, + GFP_KERNEL); + if (!sound_read_buffers[i]) { + while (i--) + sound.mach.dma_free (sound_read_buffers[i], + readbufSize << 10); + kfree (sound_read_buffers); + sound_read_buffers = 0; + return -ENOMEM; + } + /* XXXX debugging code */ + for (j=0; jcommand, DBDMA_STOP); + } + /* We should probably wait for the thing to stop before we + release the memory */ +#endif + for (i = 0; i < numBufs; i++) + sound.mach.dma_free (sound_read_buffers[i], + bufSize << 10); + kfree (sound_read_buffers); + sound_read_buffers = 0; + } +} + + +static void sq_setup(int numBufs, int bufSize, char **write_buffers) { #ifdef CONFIG_PPC int i; @@ -4357,12 +4708,12 @@ sq.max_count = numBufs; sq.max_active = numBufs; sq.block_size = bufSize; - sq.buffers = buffers; + sq.buffers = write_buffers; sq.front = sq.count = 0; sq.rear = -1; sq.syncing = 0; - sq.playing = 0; + sq.active = 0; #ifdef CONFIG_ATARI sq.ignore_int = 0; @@ -4375,7 +4726,7 @@ cp = awacs_tx_cmds; memset((void *) cp, 0, (numBufs + 1) * sizeof(struct dbdma_cmd)); for (i = 0; i < numBufs; ++i, ++cp) { - st_le32(&cp->phy_addr, virt_to_bus(buffers[i])); + st_le32(&cp->phy_addr, virt_to_bus(write_buffers[i])); } st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); st_le32(&cp->cmd_dep, virt_to_bus(awacs_tx_cmds)); @@ -4384,6 +4735,59 @@ #endif /* CONFIG_PPC */ } +static void read_sq_setup(int numBufs, int bufSize, char **read_buffers) +{ +#ifdef CONFIG_PPC + int i; + volatile struct dbdma_cmd *cp; +#endif /* CONFIG_PPC */ + + read_sq.max_count = numBufs; + read_sq.max_active = numBufs; + read_sq.block_size = bufSize; + read_sq.buffers = read_buffers; + + read_sq.front = read_sq.count = 0; + read_sq.rear = 0; + read_sq.rear_size = 0; + read_sq.syncing = 0; + read_sq.active = 0; + +#ifdef CONFIG_ATARI + read_sq.ignore_int = 0; +#endif /* CONFIG_ATARI */ +#ifdef CONFIG_AMIGA + read_sq.block_size_half = read_sq.block_size>>1; + read_sq.block_size_quarter = read_sq.block_size_half>>1; +#endif /* CONFIG_AMIGA */ +#ifdef CONFIG_PPC + cp = awacs_rx_cmds; + memset((void *) cp, 0, (numBufs + 1) * sizeof(struct dbdma_cmd)); + + /* Set dma buffers up in a loop */ + for (i = 0; i < numBufs; i++,cp++) { + st_le32(&cp->phy_addr, virt_to_bus(read_buffers[i])); + st_le16(&cp->command, INPUT_MORE + INTR_ALWAYS); + st_le16(&cp->req_count, read_sq.block_size); + st_le16(&cp->xfer_status, 0); + } + + /* The next two lines make the thing loop around. + */ + st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); + st_le32(&cp->cmd_dep, virt_to_bus(awacs_rx_cmds)); + + /* Don't start until the first read is done. + * This will also abort any operations in progress if the DMA + * happens to be running (and it shouldn't). + */ + out_le32(&awacs_rxdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le32(&awacs_rxdma->cmdptr, virt_to_bus(awacs_rx_cmds)); + +#endif /* CONFIG_PPC */ +} + + static void sq_play(void) { (*sound.mach.play)(); @@ -4428,7 +4832,7 @@ sq_play(); if (NON_BLOCKING(sq.open_mode)) return uWritten > 0 ? uWritten : -EAGAIN; - SLEEP(sq.write_queue, ONE_SECOND); + SLEEP(sq.action_queue, ONE_SECOND); if (SIGNAL_RECEIVED) return uWritten > 0 ? uWritten : -EINTR; } @@ -4462,29 +4866,117 @@ } +/***********/ + +/* Here is how the values are used for reading. + * The value 'active' simply indicates the DMA is running. This is + * done so the driver semantics are DMA starts when the first read is + * posted. The value 'front' indicates the buffer we should next + * send to the user. The value 'rear' indicates the buffer the DMA is + * currently filling. When 'front' == 'rear' the buffer "ring" is + * empty (we always have an empty available). The 'rear_size' is used + * to track partial offsets into the current buffer. Right now, I just keep + * the DMA running. If the reader can't keep up, the interrupt tosses + * the oldest buffer. We could also shut down the DMA in this case. + */ +static ssize_t sq_read(struct file *file, char *dst, size_t uLeft, + loff_t *ppos) +{ + + ssize_t uRead, bLeft, bUsed, uUsed; + + if (uLeft == 0) + return 0; + + if (!read_sq.active) + PMacRecord(); /* Kick off the record process. */ + + uRead = 0; + + /* Move what the user requests, depending upon other options. + */ + while (uLeft > 0) { + + /* When front == rear, the DMA is not done yet. + */ + while (read_sq.front == read_sq.rear) { + if (NON_BLOCKING(read_sq.open_mode)) { + return uRead > 0 ? uRead : -EAGAIN; + } + SLEEP(read_sq.action_queue, ONE_SECOND); + if (SIGNAL_RECEIVED) + return uRead > 0 ? uRead : -EINTR; + } + + /* The amount we move is either what is left in the + * current buffer or what the user wants. + */ + bLeft = read_sq.block_size - read_sq.rear_size; + bUsed = read_sq.rear_size; + uUsed = sound_copy_translate_read(dst, uLeft, + read_sq.buffers[read_sq.front], &bUsed, bLeft); + if (uUsed <= 0) + return uUsed; + dst += uUsed; + uRead += uUsed; + uLeft -= uUsed; + read_sq.rear_size += bUsed; + if (read_sq.rear_size >= read_sq.block_size) { + read_sq.rear_size = 0; + read_sq.front++; + if (read_sq.front >= read_sq.max_active) + read_sq.front = 0; + } + } + return uRead; +} + static int sq_open(struct inode *inode, struct file *file) { int rc = 0; MOD_INC_USE_COUNT; - if (sq.busy) { - rc = -EBUSY; - if (NON_BLOCKING(file->f_flags)) - goto err_out; - rc = -EINTR; - while (sq.busy) { - SLEEP(sq.open_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) + if (file->f_mode & FMODE_WRITE) { + if (sq.busy) { + rc = -EBUSY; + if (NON_BLOCKING(file->f_flags)) goto err_out; + rc = -EINTR; + while (sq.busy) { + SLEEP(sq.open_queue, ONE_SECOND); + if (SIGNAL_RECEIVED) + goto err_out; + } } - rc = 0; + sq.busy = 1; /* Let's play spot-the-race-condition */ + + if (sq_allocate_buffers()) goto err_out_nobusy; + + sq_setup(numBufs, bufSize<<10,sound_buffers); + sq.open_mode = file->f_mode; } - sq.busy = 1; - rc = sq_allocate_buffers(); - if (rc) - goto err_out_nobusy; - sq_setup(numBufs, bufSize << 10, sound_buffers); - sq.open_mode = file->f_flags; + + + if (file->f_mode & FMODE_READ) { + if (read_sq.busy) { + rc = -EBUSY; + if (NON_BLOCKING(file->f_flags)) + goto err_out; + rc = -EINTR; + while (read_sq.busy) { + SLEEP(read_sq.open_queue, ONE_SECOND); + if (SIGNAL_RECEIVED) + goto err_out; + } + rc = 0; + } + read_sq.busy = 1; + if (sq_allocate_read_buffers()) goto err_out_nobusy; + + read_sq_setup(numReadBufs,readbufSize<<10, sound_read_buffers); + read_sq.open_mode = file->f_mode; + } + #ifdef CONFIG_ATARI sq.ignore_int = 1; #endif /* CONFIG_ATARI */ @@ -4497,10 +4989,25 @@ sound_set_stereo(0); sound_set_format(AFMT_MU_LAW); } + +#if 0 + if (file->f_mode == FMODE_READ) { + /* Start dma'ing straight away */ + PMacRecord(); + } +#endif + return 0; + err_out_nobusy: - sq.busy = 0; - WAKE_UP(sq.open_queue); + if (file->f_mode & FMODE_WRITE) { + sq.busy = 0; + WAKE_UP(sq.open_queue); + } + if (file->f_mode & FMODE_READ) { + read_sq.busy = 0; + WAKE_UP(read_sq.open_queue); + } err_out: MOD_DEC_USE_COUNT; return rc; @@ -4510,7 +5017,7 @@ static void sq_reset(void) { sound_silence(); - sq.playing = 0; + sq.active = 0; sq.count = 0; sq.front = (sq.rear+1) % sq.max_count; } @@ -4523,7 +5030,7 @@ sq.syncing = 1; sq_play(); /* there may be an incomplete frame waiting */ - while (sq.playing) { + while (sq.active) { SLEEP(sq.sync_queue, ONE_SECOND); if (SIGNAL_RECEIVED) { /* While waiting for audio output to drain, an @@ -4548,11 +5055,23 @@ sound.soft = sound.dsp; sound.hard = sound.dsp; sound_silence(); + + sq_release_read_buffers(); sq_release_buffers(); MOD_DEC_USE_COUNT; - sq.busy = 0; - WAKE_UP(sq.open_queue); + /* There is probably a DOS atack here. They change the mode flag. */ + /* XXX add check here */ + if (file->f_mode & FMODE_READ) { + read_sq.busy = 0; + WAKE_UP(read_sq.open_queue); + } + + if (file->f_mode & FMODE_WRITE) { + sq.busy = 0; + WAKE_UP(sq.open_queue); + } + /* Wake up a process waiting for the queue being released. * Note: There may be several processes waiting for a call * to open() returning. */ @@ -4624,7 +5143,7 @@ case SNDCTL_DSP_SUBDIVIDE: break; case SNDCTL_DSP_SETFRAGMENT: - if (sq.count || sq.playing || sq.syncing) + if (sq.count || sq.active || sq.syncing) return -EINVAL; IOCTL_IN(arg, size); nbufs = size >> 16; @@ -4654,7 +5173,7 @@ static struct file_operations sq_fops = { sound_lseek, - NULL, /* sq_read */ + sq_read, /* sq_read */ sq_write, NULL, /* sq_readdir */ NULL, /* sq_poll */ @@ -4675,10 +5194,16 @@ if (sq_unit < 0) return; - init_waitqueue_head(&sq.write_queue); + init_waitqueue_head(&sq.action_queue); init_waitqueue_head(&sq.open_queue); init_waitqueue_head(&sq.sync_queue); + + init_waitqueue_head(&read_sq.action_queue); + init_waitqueue_head(&read_sq.open_queue); + init_waitqueue_head(&read_sq.sync_queue); + sq.busy = 0; + read_sq.busy = 0; /* whatever you like as startup mode for /dev/dsp, * (/dev/audio hasn't got a startup mode). note that @@ -4726,7 +5251,7 @@ static int state_open(struct inode *inode, struct file *file) { - char *buffer = state.buf, *mach = ""; + char *buffer = state.buf, *mach = "", awacs_buf[50]; int len = 0; if (state.busy) @@ -4750,7 +5275,8 @@ #endif /* CONFIG_AMIGA */ #ifdef CONFIG_PPC case DMASND_AWACS: - sprintf(mach, "PowerMac (AWACS rev %d) ", awacs_revision); + sprintf(awacs_buf, "PowerMac (AWACS rev %d) ", awacs_revision); + mach = awacs_buf; break; #endif /* CONFIG_PPC */ } @@ -4821,8 +5347,8 @@ sq.block_size, sq.max_count, sq.max_active); len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count, sq.rear_size); - len += sprintf(buffer+len, "\tsq.playing = %d sq.syncing = %d\n", - sq.playing, sq.syncing); + len += sprintf(buffer+len, "\tsq.active = %d sq.syncing = %d\n", + sq.active, sq.syncing); state.len = len; return 0; } @@ -4951,15 +5477,18 @@ int vol; sound.mach = machPMac; has_sound = 1; + awacs = (volatile struct awacs_regs *) ioremap(np->addrs[0].address, 0x80); awacs_txdma = (volatile struct dbdma_regs *) ioremap(np->addrs[1].address, 0x100); awacs_rxdma = (volatile struct dbdma_regs *) ioremap(np->addrs[2].address, 0x100); + awacs_irq = np->intrs[0].line; awacs_tx_irq = np->intrs[1].line; awacs_rx_irq = np->intrs[2].line; + awacs_tx_cmd_space = kmalloc((numBufs + 4) * sizeof(struct dbdma_cmd), GFP_KERNEL); if (awacs_tx_cmd_space == NULL) { @@ -4968,6 +5497,18 @@ } awacs_tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(awacs_tx_cmd_space); + + + awacs_rx_cmd_space = kmalloc((numReadBufs + 4) * sizeof(struct dbdma_cmd), + GFP_KERNEL); + if (awacs_rx_cmd_space == NULL) { + printk("DMA sound driver: No memory for input"); + } + awacs_rx_cmds = (volatile struct dbdma_cmd *) + DBDMA_ALIGN(awacs_rx_cmd_space); + + + awacs_reg[0] = MASK_MUX_CD; awacs_reg[1] = MASK_LOOPTHRU | MASK_PAROUT; /* get default volume from nvram */ @@ -5083,6 +5624,7 @@ sound.mach.irqcleanup(); } + sq_release_read_buffers(); sq_release_buffers(); if (mixer_unit >= 0) diff -u --recursive --new-file v2.3.10/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c --- v2.3.10/linux/drivers/sound/es1370.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/sound/es1370.c Sat Jul 10 10:58:40 1999 @@ -100,6 +100,7 @@ * Guenter Geiger * 15.06.99 0.23 Fix bad allocation bug. * Thanks to Deti Fliegl + * 28.06.99 0.24 Add pci_set_master * * some important things missing in Ensoniq documentation: * @@ -2320,7 +2321,7 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1370: version v0.23 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1370: version v0.24 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) { if (pcidev->base_address[0] == 0 || @@ -2384,6 +2385,7 @@ /* initialize the chips */ outl(s->ctrl, s->io+ES1370_REG_CONTROL); outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL); + pci_set_master(pcidev); /* enable bus mastering */ wrcodec(s, 0x16, 3); /* no RST, PD */ wrcodec(s, 0x17, 0); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; program DAC_SYNC=0!! */ wrcodec(s, 0x18, 0); /* recording source is mixer */ diff -u --recursive --new-file v2.3.10/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c --- v2.3.10/linux/drivers/sound/es1371.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/sound/es1371.c Sat Jul 10 10:58:40 1999 @@ -67,6 +67,7 @@ * other than i386 * 15.06.99 0.12 Fix bad allocation bug. * Thanks to Deti Fliegl + * 28.06.99 0.13 Add pci_set_master * */ @@ -2735,7 +2736,7 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1371: version v0.12 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1371: version v0.13 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) { if (pcidev->base_address[0] == 0 || @@ -2792,6 +2793,7 @@ outl(s->ctrl, s->io+ES1371_REG_CONTROL); outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); outl(0, s->io+ES1371_REG_LEGACY); + pci_set_master(pcidev); /* enable bus mastering */ /* AC97 warm reset to start the bitclk */ outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL); udelay(2); diff -u --recursive --new-file v2.3.10/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c --- v2.3.10/linux/drivers/sound/sonicvibes.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/sound/sonicvibes.c Sat Jul 10 10:58:40 1999 @@ -70,6 +70,7 @@ * Note: dmaio hack might still be wrong on archs other than i386 * 15.06.99 0.15 Fix bad allocation bug. * Thanks to Deti Fliegl + * 28.06.99 0.16 Add pci_set_master * */ @@ -2324,7 +2325,7 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "sv: version v0.15 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "sv: version v0.16 time " __TIME__ " " __DATE__ "\n"); #if 0 if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT))) printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n"); @@ -2450,6 +2451,7 @@ goto err_dev3; if ((s->dev_dmfm = register_sound_special(&sv_dmfm_fops, 15 /* ?? */)) < 0) goto err_dev4; + pci_set_master(pcidev); /* enable bus mastering */ /* initialize the chips */ fs = get_fs(); set_fs(KERNEL_DS); diff -u --recursive --new-file v2.3.10/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.3.10/linux/drivers/usb/Config.in Mon Jun 7 20:04:01 1999 +++ linux/drivers/usb/Config.in Wed Jul 14 10:30:36 1999 @@ -34,6 +34,7 @@ if [ "$CONFIG_USB_SCSI" != "n" ]; then dep_tristate ' USB SCSI verbose debug' CONFIG_USB_SCSI_DEBUG $CONFIG_USB_SCSI fi + dep_tristate 'EZUSB Firmware downloader' CONFIG_USB_EZUSB $CONFIG_USB fi endmenu diff -u --recursive --new-file v2.3.10/linux/drivers/usb/Makefile linux/drivers/usb/Makefile --- v2.3.10/linux/drivers/usb/Makefile Tue Jun 8 10:52:26 1999 +++ linux/drivers/usb/Makefile Wed Jul 14 10:30:36 1999 @@ -116,6 +116,15 @@ endif endif +ifeq ($(CONFIG_USB_EZUSB),y) + L_OBJS += ezusb.o +endif + +ifeq ($(CONFIG_USB_EZUSB),m) + M_OBJS += ezusb.o + MIX_OBJS += ezusb.o +endif + include $(TOPDIR)/Rules.make keymap.o: keymap.c diff -u --recursive --new-file v2.3.10/linux/drivers/usb/acm.c linux/drivers/usb/acm.c --- v2.3.10/linux/drivers/usb/acm.c Wed Jun 30 13:38:20 1999 +++ linux/drivers/usb/acm.c Mon Jul 19 11:17:32 1999 @@ -231,7 +231,10 @@ continue; printk("USB ACM found\n"); - usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue); + if (usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue)) { + printk (KERN_INFO " Failed usb_set_configuration: ACM\n"); + continue; + } acm->dev=dev; acm->readendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[0].bEndpointAddress; acm->writeendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[1].bEndpointAddress; diff -u --recursive --new-file v2.3.10/linux/drivers/usb/audio.c linux/drivers/usb/audio.c --- v2.3.10/linux/drivers/usb/audio.c Wed Jun 30 13:38:20 1999 +++ linux/drivers/usb/audio.c Mon Jul 19 11:17:32 1999 @@ -81,7 +81,10 @@ endpoint = &interface->endpoint[0]; -// usb_set_configuration(dev, dev->config[0].bConfigurationValue); +// if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) { +// printk (KERN_INFO " Failed usb_set_configuration: Audio\n"); +// break; +// } // usb_set_protocol(dev, 0); // usb_set_idle(dev, 0, 0); @@ -92,8 +95,13 @@ aud); list_add(&aud->list, &usb_audio_list); + + return 0; } - return 0; + + if (aud) + kfree (aud); + return -1; } static void usb_audio_disconnect(struct usb_device *dev) diff -u --recursive --new-file v2.3.10/linux/drivers/usb/cpia.c linux/drivers/usb/cpia.c --- v2.3.10/linux/drivers/usb/cpia.c Wed Jun 30 13:38:20 1999 +++ linux/drivers/usb/cpia.c Mon Jul 19 11:17:32 1999 @@ -23,7 +23,6 @@ #include #include "usb.h" -#include "uhci.h" #include "cpia.h" #define MAX_FRAME_SIZE (384 * 288 * 3) @@ -478,10 +477,10 @@ sbuf = &cpia->sbuf[cpia->receivesbuf]; - uhci_unsched_isochronous(dev, sbuf->isodesc); + usb_unschedule_isochronous(dev, sbuf->isodesc); /* Do something to it now */ - sbuf->len = uhci_compress_isochronous(dev, sbuf->isodesc); + sbuf->len = usb_compress_isochronous(dev, sbuf->isodesc); if (sbuf->len) printk("%d bytes received\n", sbuf->len); @@ -498,7 +497,7 @@ } /* Reschedule this block of Isochronous desc */ - uhci_sched_isochronous(dev, sbuf->isodesc, cpia->sbuf[(cpia->receivesbuf + 2) % 3].isodesc); + usb_schedule_isochronous(dev, sbuf->isodesc, cpia->sbuf[(cpia->receivesbuf + 2) % 3].isodesc); /* Move to the next one */ cpia->receivesbuf = (cpia->receivesbuf + 1) % 3; @@ -521,18 +520,18 @@ cpia->state = STATE_SCANNING; /* Allocate all of the memory necessary */ - cpia->sbuf[0].isodesc = uhci_alloc_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[0].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia); - cpia->sbuf[1].isodesc = uhci_alloc_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[1].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia); - cpia->sbuf[2].isodesc = uhci_alloc_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[2].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia); + cpia->sbuf[0].isodesc = usb_allocate_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[0].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia); + cpia->sbuf[1].isodesc = usb_allocate_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[1].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia); + cpia->sbuf[2].isodesc = usb_allocate_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[2].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia); printk("isodesc[0] @ %p\n", cpia->sbuf[0].isodesc); printk("isodesc[1] @ %p\n", cpia->sbuf[1].isodesc); printk("isodesc[2] @ %p\n", cpia->sbuf[2].isodesc); /* Schedule the queues */ - uhci_sched_isochronous(dev, cpia->sbuf[0].isodesc, NULL); - uhci_sched_isochronous(dev, cpia->sbuf[1].isodesc, cpia->sbuf[0].isodesc); - uhci_sched_isochronous(dev, cpia->sbuf[2].isodesc, cpia->sbuf[1].isodesc); + usb_schedule_isochronous(dev, cpia->sbuf[0].isodesc, NULL); + usb_schedule_isochronous(dev, cpia->sbuf[1].isodesc, cpia->sbuf[0].isodesc); + usb_schedule_isochronous(dev, cpia->sbuf[2].isodesc, cpia->sbuf[1].isodesc); if (usb_set_interface(cpia->dev, 1, 3)) { printk("cpia_set_interface error\n"); @@ -561,18 +560,18 @@ /* Set packet size to 0 */ if (usb_set_interface(cpia->dev, 1, 0)) { printk("cpia_set_interface error\n"); - return -EINVAL; + return /* -EINVAL */; } /* Unschedule all of the iso td's */ - uhci_unsched_isochronous(dev, cpia->sbuf[2].isodesc); - uhci_unsched_isochronous(dev, cpia->sbuf[1].isodesc); - uhci_unsched_isochronous(dev, cpia->sbuf[0].isodesc); + usb_unschedule_isochronous(dev, cpia->sbuf[2].isodesc); + usb_unschedule_isochronous(dev, cpia->sbuf[1].isodesc); + usb_unschedule_isochronous(dev, cpia->sbuf[0].isodesc); /* Delete them all */ - uhci_delete_isochronous(dev, cpia->sbuf[2].isodesc); - uhci_delete_isochronous(dev, cpia->sbuf[1].isodesc); - uhci_delete_isochronous(dev, cpia->sbuf[0].isodesc); + usb_delete_isochronous(dev, cpia->sbuf[2].isodesc); + usb_delete_isochronous(dev, cpia->sbuf[1].isodesc); + usb_delete_isochronous(dev, cpia->sbuf[0].isodesc); } /* Video 4 Linux API */ @@ -980,7 +979,7 @@ struct usb_cpia *cpia = (struct usb_cpia *)dev; int len; - printk("cpia_read: %d bytes\n", count); + printk("cpia_read: %ld bytes\n", count); #if 0 len = cpia_capture(cpia, buf, count); @@ -995,7 +994,7 @@ unsigned long start = (unsigned long)adr; unsigned long page, pos; - printk("mmap: %d (%X) bytes\n", size, size); + printk("mmap: %ld (%lX) bytes\n", size, size); if (size > (((2 * MAX_FRAME_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) return -EINVAL; @@ -1048,7 +1047,10 @@ unsigned char camerastat[8]; unsigned char *buf; - usb_set_configuration(dev, dev->config[0].bConfigurationValue); + if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) { + printk (KERN_INFO " Failed usb_set_configuration: CPIA\n"); + return; + } if (usb_cpia_get_version(dev, version)) { printk("cpia_get_version error\n"); diff -u --recursive --new-file v2.3.10/linux/drivers/usb/ezusb.c linux/drivers/usb/ezusb.c --- v2.3.10/linux/drivers/usb/ezusb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/ezusb.c Wed Jul 14 10:30:36 1999 @@ -0,0 +1,473 @@ +/*****************************************************************************/ + +/* + * ezusb.c -- Firmware download miscdevice for Anchorchips EZUSB microcontrollers. + * + * Copyright (C) 1999 + * Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * History: + * 0.1 26.05.99 Created + * + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "usb.h" +#include "ezusb.h" + +/* --------------------------------------------------------------------- */ + +#define NREZUSB 1 + +static struct ezusb { + struct semaphore mutex; + struct usb_device *usbdev; + unsigned int irqep; + unsigned int intlen; + unsigned char intdata[64]; +} ezusb[NREZUSB]; + +/* --------------------------------------------------------------------- */ + +static int ezusb_irq(int state, void *__buffer, int len, void *dev_id) +{ + struct ezusb *ez = (struct ezusb *)dev_id; + + if (len > sizeof(ez->intdata)) + len = sizeof(ez->intdata); + ez->intlen = len; + memcpy(ez->intdata, __buffer, len); + return 1; +} + +/* --------------------------------------------------------------------- */ + +static loff_t ezusb_llseek(struct file *file, loff_t offset, int origin) +{ + struct ezusb *ez = (struct ezusb *)file->private_data; + + switch(origin) { + case 1: + offset += file->f_pos; + break; + case 2: + offset += 0x10000; + break; + } + if (offset < 0 || offset >= 0x10000) + return -EINVAL; + return (file->f_pos = offset); +} + +static ssize_t ezusb_read(struct file *file, char *buf, size_t sz, loff_t *ppos) +{ + struct ezusb *ez = (struct ezusb *)file->private_data; + unsigned pos = *ppos; + unsigned ret = 0; + unsigned len; + unsigned char b[64]; + devrequest dr; + int i; + + if (*ppos < 0 || *ppos >= 0x10000) + return -EINVAL; + down(&ez->mutex); + if (!ez->usbdev) { + up(&ez->mutex); + return -EIO; + } + while (sz > 0 && pos < 0x10000) { + len = sz; + if (len > sizeof(b)) + len = sizeof(b); + if (pos + len > 0x10000) + len = 0x10000 - pos; + dr.requesttype = 0xc0; + dr.request = 0xa0; + dr.value = pos; + dr.index = 0; + dr.length = len; + i = ez->usbdev->bus->op->control_msg(ez->usbdev, usb_rcvctrlpipe(ez->usbdev, 0), &dr, b, len); + if (i) { + up(&ez->mutex); + printk(KERN_WARNING "ezusb: upload failed pos %u len %u ret %d\n", dr.value, dr.length, i); + *ppos = pos; + if (ret) + return ret; + return -ENXIO; + } + if (copy_to_user(buf, b, len)) { + up(&ez->mutex); + *ppos = pos; + if (ret) + return ret; + return -EFAULT; + } + pos += len; + buf += len; + sz -= len; + ret += len; + } + up(&ez->mutex); + *ppos = pos; + return ret; +} + +static ssize_t ezusb_write(struct file *file, const char *buf, size_t sz, loff_t *ppos) +{ + struct ezusb *ez = (struct ezusb *)file->private_data; + unsigned pos = *ppos; + unsigned ret = 0; + unsigned len; + unsigned char b[64]; + devrequest dr; + int i; + + if (*ppos < 0 || *ppos >= 0x10000) + return -EINVAL; + down(&ez->mutex); + if (!ez->usbdev) { + up(&ez->mutex); + return -EIO; + } + while (sz > 0 && pos < 0x10000) { + len = sz; + if (len > sizeof(b)) + len = sizeof(b); + if (pos + len > 0x10000) + len = 0x10000 - pos; + if (copy_from_user(b, buf, len)) { + up(&ez->mutex); + *ppos = pos; + if (ret) + return ret; + return -EFAULT; + } + dr.requesttype = 0x40; + dr.request = 0xa0; + dr.value = pos; + dr.index = 0; + dr.length = len; + i = ez->usbdev->bus->op->control_msg(ez->usbdev, usb_sndctrlpipe(ez->usbdev, 0), &dr, b, len); + if (i) { + up(&ez->mutex); + printk(KERN_WARNING "ezusb: download failed pos %u len %u ret %d\n", dr.value, dr.length, i); + *ppos = pos; + if (ret) + return ret; + return -ENXIO; + } + pos += len; + buf += len; + sz -= len; + ret += len; + } + up(&ez->mutex); + *ppos = pos; + return ret; +} + +static int ezusb_open(struct inode *inode, struct file *file) +{ + struct ezusb *ez = &ezusb[0]; + + down(&ez->mutex); + while (!ez->usbdev) { + up(&ez->mutex); + if (!(file->f_flags & O_NONBLOCK)) { + return -EIO; + } + schedule_timeout(HZ/2); + if (signal_pending(current)) + return -EAGAIN; + down(&ez->mutex); + } + up(&ez->mutex); + file->f_pos = 0; + file->private_data = ez; + return 0; +} + +static int ezusb_release(struct inode *inode, struct file *file) +{ + struct ezusb *ez = (struct ezusb *)file->private_data; + return 0; +} + +static int ezusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct ezusb *ez = (struct ezusb *)file->private_data; + struct ezusb_ctrltransfer ctrl; + struct ezusb_bulktransfer bulk; + unsigned int len1, ep; + unsigned long len2; + unsigned int irqep; + unsigned char tbuf[1024]; + int i; + + switch (cmd) { + case EZUSB_CONTROL: + copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT); + if (ctrl.dlen > sizeof(tbuf) || ctrl.dlen > 1024) + return -EINVAL; + if (ctrl.requesttype & 0x80) { + if (ctrl.dlen && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.dlen)) + return -EINVAL; + down(&ez->mutex); + if (!ez->usbdev) { + up(&ez->mutex); + return -EIO; + } + i = ez->usbdev->bus->op->control_msg(ez->usbdev, usb_rcvctrlpipe(ez->usbdev, 0), + (devrequest *)&ctrl, tbuf, ctrl.dlen); + up(&ez->mutex); + if (!i && ctrl.dlen) { + copy_to_user_ret(ctrl.data, tbuf, ctrl.dlen, -EFAULT); + } + } else { + if (ctrl.dlen) { + copy_from_user_ret(tbuf, ctrl.data, ctrl.dlen, -EFAULT); + } + down(&ez->mutex); + if (!ez->usbdev) { + up(&ez->mutex); + return -EIO; + } + i = ez->usbdev->bus->op->control_msg(ez->usbdev, usb_sndctrlpipe(ez->usbdev, 0), + (devrequest *)&ctrl, tbuf, ctrl.dlen); + up(&ez->mutex); + } + if (i) { + printk(KERN_WARNING "ezusb: EZUSB_CONTROL failed rqt %u rq %u len %u ret %d\n", + ctrl.requesttype, ctrl.request, ctrl.length, i); + return -ENXIO; + } + return 0; + + case EZUSB_INTERRUPT: + get_user_ret(irqep, (unsigned int *)arg, -EFAULT); + if (irqep != ez->irqep) { + if (ez->irqep) + return -EIO; + ez->irqep = irqep; + usb_request_irq(ez->usbdev, usb_rcvctrlpipe(ez->usbdev, ez->irqep), + ezusb_irq, 2 /* interval */, ez); + ez->intlen = 0; + return -EAGAIN; + } + copy_to_user_ret((&((struct ezusb_interrupttransfer *)0)->data) + arg, + ez->intdata, 64, -EFAULT); + return ez->intlen; + + case EZUSB_BULK: + copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT); + len1 = bulk.len; + if (len1 > sizeof(tbuf)) + len1 = sizeof(tbuf); + if (bulk.ep & 0x80) { + if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) + return -EINVAL; + down(&ez->mutex); + if (!ez->usbdev) { + up(&ez->mutex); + return -EIO; + } + i = ez->usbdev->bus->op->bulk_msg(ez->usbdev, usb_rcvbulkpipe(ez->usbdev, bulk.ep & 0x7f), + tbuf, len1, &len2); + up(&ez->mutex); + if (!i && len2) { + copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT); + } + } else { + if (len1) { + copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT); + } + down(&ez->mutex); + if (!ez->usbdev) { + up(&ez->mutex); + return -EIO; + } + i = ez->usbdev->bus->op->bulk_msg(ez->usbdev, usb_sndbulkpipe(ez->usbdev, bulk.ep & 0x7f), + tbuf, len1, &len2); + up(&ez->mutex); + } + if (i) { + printk(KERN_WARNING "ezusb: EZUSB_BULK failed ep 0x%x len %u ret %d\n", + bulk.ep, bulk.len, i); + return -ENXIO; + } + return len2; + + case EZUSB_RESETEP: + get_user_ret(ep, (unsigned int *)arg, -EFAULT); + if ((ep & ~0x80) >= 16) + return -EINVAL; + usb_settoggle(ez->usbdev, ep & 0xf, !(ep & 0x80), 0); + return 0; + } + return -ENOIOCTLCMD; +} + +static struct file_operations ezusb_fops = { + ezusb_llseek, + ezusb_read, + ezusb_write, + NULL, /* readdir */ + NULL, /* poll */ + ezusb_ioctl, + NULL, /* mmap */ + ezusb_open, + NULL, /* flush */ + ezusb_release, + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ + NULL /* lock */ +}; + +static struct miscdevice ezusb_misc = { + 192, "ezusb", &ezusb_fops +}; + +/* --------------------------------------------------------------------- */ + +static int ezusb_probe(struct usb_device *usbdev) +{ + struct ezusb *ez = &ezusb[0]; + struct usb_interface_descriptor *interface; + struct usb_endpoint_descriptor *endpoint; + +#undef KERN_DEBUG +#define KERN_DEBUG "" + printk(KERN_DEBUG "ezusb: probe: vendor id 0x%x, device id 0x%x\n", + usbdev->descriptor.idVendor, usbdev->descriptor.idProduct); + + /* the 1234:5678 is just a self assigned test ID */ + if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131) && + (usbdev->descriptor.idVendor != 0x1234 || usbdev->descriptor.idProduct != 0x5678)) + return -1; + + /* We don't handle multiple configurations */ + if (usbdev->descriptor.bNumConfigurations != 1) + return -1; + + /* We don't handle multiple interfaces */ + if (usbdev->config[0].bNumInterfaces != 1) + return -1; + + down(&ez->mutex); + if (ez->usbdev) { + up(&ez->mutex); + printk(KERN_INFO "ezusb: device already used\n"); + return -1; + } + ez->usbdev = usbdev; + usbdev->private = ez; + if (usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue)) { + printk(KERN_ERR "ezusb: set_configuration failed\n"); + goto err; + } + interface = &usbdev->config[0].altsetting[1].interface[0]; + if (usb_set_interface(usbdev, 0, 1)) { + printk(KERN_ERR "ezusb: set_interface failed\n"); + goto err; + } + up(&ez->mutex); + MOD_INC_USE_COUNT; + return 0; + + err: + up(&ez->mutex); + ez->usbdev = NULL; + usbdev->private = NULL; + return -1; +} + +static void ezusb_disconnect(struct usb_device *usbdev) +{ + struct ezusb *ez = (struct ezusb *)usbdev->private; + + down(&ez->mutex); + ez->usbdev = NULL; + up(&ez->mutex); + usbdev->private = NULL; + MOD_DEC_USE_COUNT; +} + +static struct usb_driver ezusb_driver = { + "ezusb", + ezusb_probe, + ezusb_disconnect, + { NULL, NULL } +}; + +/* --------------------------------------------------------------------- */ + +int ezusb_init(void) +{ + unsigned u; + + /* initialize struct */ + for (u = 0; u < NREZUSB; u++) { + init_MUTEX(&ezusb[u].mutex); + ezusb[u].usbdev = NULL; + ezusb[u].irqep = 0; + } + /* register misc device */ + if (misc_register(&ezusb_misc)) { + printk(KERN_WARNING "ezusb: cannot register minor %d\n", ezusb_misc.minor); + return -1; + } + usb_register(&ezusb_driver); + printk(KERN_INFO "ezusb: Anchorchip firmware download driver registered\n"); + return 0; +} + +void ezusb_cleanup(void) +{ + usb_deregister(&ezusb_driver); + misc_deregister(&ezusb_misc); +} + +/* --------------------------------------------------------------------- */ + +#ifdef MODULE + +int minor = 192; + +int init_module(void) +{ + ezusb_misc.minor = minor; + return ezusb_init(); +} + +void cleanup_module(void) +{ + ezusb_cleanup(); +} + +#endif + +/* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.10/linux/drivers/usb/ezusb.h linux/drivers/usb/ezusb.h --- v2.3.10/linux/drivers/usb/ezusb.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/ezusb.h Wed Jul 14 10:30:36 1999 @@ -0,0 +1,67 @@ +/*****************************************************************************/ + +/* + * ezusb.h -- Firmware download miscdevice for Anchorchips EZUSB microcontrollers. + * + * Copyright (C) 1999 + * Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/*****************************************************************************/ + +#ifndef _LINUX_EZUSB_H +#define _LINUX_EZUSB_H + +#include + +/* --------------------------------------------------------------------- */ + +struct ezusb_ctrltransfer { + /* keep in sync with usb.h:devrequest */ + unsigned char requesttype; + unsigned char request; + unsigned short value; + unsigned short index; + unsigned short length; + /* pointer to data */ + unsigned dlen; + void *data; +}; + +#define EZUSB_CONTROL _IOWR('E', 0, struct ezusb_ctrltransfer) + +struct ezusb_interrupttransfer { + unsigned int ep; + unsigned char data[64]; +}; + +#define EZUSB_INTERRUPT _IOWR('E', 1, struct ezusb_interrupttransfer) + +struct ezusb_bulktransfer { + unsigned int ep; + unsigned int len; + void *data; +}; + +#define EZUSB_BULK _IOWR('E', 2, struct ezusb_bulktransfer) + +#define EZUSB_RESETEP _IOR('E', 3, unsigned int) + + +/* --------------------------------------------------------------------- */ +#endif /* _LINUX_EZUSB_H */ diff -u --recursive --new-file v2.3.10/linux/drivers/usb/hub.c linux/drivers/usb/hub.c --- v2.3.10/linux/drivers/usb/hub.c Wed Jun 30 13:38:20 1999 +++ linux/drivers/usb/hub.c Mon Jul 19 15:25:27 1999 @@ -3,6 +3,7 @@ * * (C) Copyright 1999 Linus Torvalds * (C) Copyright 1999 Johannes Erdfelt + * (C) Copyright 1999 Gregory P. Smith */ #include @@ -20,10 +21,14 @@ /* Wakes up khubd */ static DECLARE_WAIT_QUEUE_HEAD(usb_hub_wait); static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t hub_list_lock = SPIN_LOCK_UNLOCKED; /* List of hubs needing servicing */ static struct list_head hub_event_list; +/* List containing all of the hubs (for cleanup) */ +static struct list_head all_hubs_list; + /* PID of khubd */ static int khubd_pid = 0; @@ -149,6 +154,7 @@ struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct usb_hub *hub; + unsigned long flags; /* We don't handle multi-config hubs */ if (dev->descriptor.bNumConfigurations != 1) @@ -196,9 +202,15 @@ INIT_LIST_HEAD(&hub->event_list); hub->dev = dev; + /* Record the new hub's existence */ + spin_lock_irqsave(&hub_list_lock, flags); + INIT_LIST_HEAD(&hub->hub_list); + list_add(&hub->hub_list, &all_hubs_list); + spin_unlock_irqrestore(&hub_list_lock, flags); + usb_hub_configure(hub); - usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), hub_irq, endpoint->bInterval, hub); + hub->irq_handle = usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), hub_irq, endpoint->bInterval, hub); /* Wake up khubd */ wake_up(&usb_hub_wait); @@ -216,9 +228,14 @@ /* Delete it and then reset it */ list_del(&hub->event_list); INIT_LIST_HEAD(&hub->event_list); + list_del(&hub->hub_list); + INIT_LIST_HEAD(&hub->hub_list); spin_unlock_irqrestore(&hub_event_lock, flags); + usb_release_irq(hub->dev, hub->irq_handle); + hub->irq_handle = NULL; + /* Free the memory */ kfree(hub); } @@ -353,13 +370,16 @@ static int usb_hub_thread(void *__hub) { + MOD_INC_USE_COUNT; + + printk(KERN_INFO "USB hub driver registered\n"); + lock_kernel(); /* * This thread doesn't need any user-level access, * so get rid of all our resources */ - printk("usb_hub_thread at %p\n", &usb_hub_thread); exit_mm(current); exit_files(current); exit_fs(current); @@ -373,6 +393,8 @@ usb_hub_events(); } while (!signal_pending(current)); + MOD_DEC_USE_COUNT; + printk("usb_hub_thread exiting\n"); return 0; @@ -393,6 +415,7 @@ int pid; INIT_LIST_HEAD(&hub_event_list); + INIT_LIST_HEAD(&all_hubs_list); usb_register(&hub_driver); pid = kernel_thread(usb_hub_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); @@ -409,11 +432,39 @@ void usb_hub_cleanup(void) { - if (khubd_pid >= 0) - kill_proc(khubd_pid, SIGINT, 1); + struct list_head *next, *tmp, *head = &all_hubs_list; + struct usb_hub *hub; + unsigned long flags, flags2; + + /* Free the resources allocated by each hub */ + spin_lock_irqsave(&hub_list_lock, flags); + spin_lock_irqsave(&hub_event_lock, flags2); + + tmp = head->next; + while (tmp != head) { + hub = list_entry(tmp, struct usb_hub, hub_list); + + next = tmp->next; + + list_del(&hub->event_list); + INIT_LIST_HEAD(&hub->event_list); + list_del(tmp); /* &hub->hub_list */ + INIT_LIST_HEAD(tmp); /* &hub->hub_list */ + + /* XXX we should disconnect each connected port here */ + + usb_release_irq(hub->dev, hub->irq_handle); + hub->irq_handle = NULL; + kfree(hub); + + tmp = next; + } usb_deregister(&hub_driver); -} + + spin_unlock_irqrestore(&hub_event_lock, flags2); + spin_unlock_irqrestore(&hub_list_lock, flags); +} /* usb_hub_cleanup() */ #ifdef MODULE int init_module(void){ diff -u --recursive --new-file v2.3.10/linux/drivers/usb/hub.h linux/drivers/usb/hub.h --- v2.3.10/linux/drivers/usb/hub.h Thu Jul 8 15:42:21 1999 +++ linux/drivers/usb/hub.h Tue Jul 13 10:09:01 1999 @@ -68,6 +68,12 @@ /* Device structure */ struct usb_device *dev; + /* Reference to the hub's polling IRQ */ + void* irq_handle; + + /* List of hubs */ + struct list_head hub_list; + /* Temporary event list */ struct list_head event_list; diff -u --recursive --new-file v2.3.10/linux/drivers/usb/keyboard.c linux/drivers/usb/keyboard.c --- v2.3.10/linux/drivers/usb/keyboard.c Sun Jun 20 18:51:52 1999 +++ linux/drivers/usb/keyboard.c Mon Jul 19 11:17:32 1999 @@ -195,7 +195,10 @@ kbd->dev = dev; dev->private = kbd; - usb_set_configuration(dev, dev->config[0].bConfigurationValue); + if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) { + printk (KERN_INFO " Failed usb_set_configuration: kbd\n"); + goto probe_err; + } usb_set_protocol(dev, 0); usb_set_idle(dev, 0, 0); @@ -206,9 +209,14 @@ kbd); list_add(&kbd->list, &usb_kbd_list); + + return 0; } - return 0; +probe_err: + if (kbd) + kfree (kbd); + return -1; } static void diff -u --recursive --new-file v2.3.10/linux/drivers/usb/mouse.c linux/drivers/usb/mouse.c --- v2.3.10/linux/drivers/usb/mouse.c Wed Jun 30 13:38:20 1999 +++ linux/drivers/usb/mouse.c Mon Jul 19 11:17:32 1999 @@ -53,6 +53,12 @@ struct fasync_struct *fasync; /* later, add a list here to support multiple mice */ /* but we will also need a list of file pointers to identify it */ + + /* FIXME: move these to a per-mouse structure */ + struct usb_device *dev; /* host controller this mouse is on */ + void* irq_handle; /* host controller's IRQ transfer handle */ + __u8 bEndpointAddress; /* these are from the endpoint descriptor */ + __u8 bInterval; /* ... used when calling usb_request_irq */ }; static struct mouse_state static_mouse_state; @@ -103,8 +109,16 @@ struct mouse_state *mouse = &static_mouse_state; fasync_mouse(-1, file, 0); - if (--mouse->active) - return 0; + + MOD_DEC_USE_COUNT; + + if (--mouse->active == 0) { + /* stop polling the mouse while its not in use */ + usb_release_irq(mouse->dev, mouse->irq_handle); + /* never keep a reference to a released IRQ! */ + mouse->irq_handle = NULL; + } + return 0; } @@ -118,6 +132,13 @@ return 0; /* flush state */ mouse->buttons = mouse->dx = mouse->dy = mouse->dz = 0; + + /* prevent the driver from being unloaded while its in use */ + MOD_INC_USE_COUNT; + + /* start the usb controller's polling of the mouse */ + mouse->irq_handle = usb_request_irq(mouse->dev, usb_rcvctrlpipe(mouse->dev, mouse->bEndpointAddress), mouse_irq, mouse->bInterval, NULL); + return 0; } @@ -272,9 +293,15 @@ printk("USB mouse found\n"); - usb_set_configuration(dev, dev->config[0].bConfigurationValue); + if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) { + printk (KERN_INFO " Failed usb_set_configuration: mouse\n"); + return -1; + } - usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), mouse_irq, endpoint->bInterval, NULL); + /* these are used to request the irq when the mouse is opened */ + mouse->dev = dev; + mouse->bEndpointAddress = endpoint->bEndpointAddress; + mouse->bInterval = endpoint->bInterval; mouse->present = 1; return 0; @@ -284,6 +311,15 @@ { struct mouse_state *mouse = &static_mouse_state; + /* stop the usb interrupt transfer */ + if (mouse->present) { + usb_release_irq(mouse->dev, mouse->irq_handle); + /* never keep a reference to a released IRQ! */ + mouse->irq_handle = NULL; + } + + mouse->irq_handle = NULL; + /* this might need work */ mouse->present = 0; printk("Mouse disconnected\n"); @@ -303,6 +339,7 @@ misc_register(&usb_mouse); mouse->present = mouse->active = 0; + mouse->irq_handle = NULL; init_waitqueue_head(&mouse->wait); mouse->fasync = NULL; @@ -313,6 +350,15 @@ void usb_mouse_cleanup(void) { + struct mouse_state *mouse = &static_mouse_state; + + /* stop the usb interrupt transfer */ + if (mouse->present) { + usb_release_irq(mouse->dev, mouse->irq_handle); + /* never keep a reference to a released IRQ! */ + mouse->irq_handle = NULL; + } + /* this, too, probably needs work */ usb_deregister(&mouse_driver); misc_deregister(&usb_mouse); diff -u --recursive --new-file v2.3.10/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c --- v2.3.10/linux/drivers/usb/ohci-hcd.c Sun Jun 20 18:51:52 1999 +++ linux/drivers/usb/ohci-hcd.c Mon Jul 19 11:17:32 1999 @@ -280,12 +280,44 @@ } +static void *sohci_alloc_isochronous (struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id) +{ + return NULL; +} + +static void sohci_delete_isochronous (struct usb_device *dev, void *_isodesc) +{ + return; +} + +static int sohci_sched_isochronous (struct usb_device *usb_dev, void *_isodesc, void *_pisodesc) +{ + return USB_ST_NOTSUPPORTED; +} + +static int sohci_unsched_isochronous (struct usb_device *usb_dev, void *_isodesc) +{ + return USB_ST_NOTSUPPORTED; +} + +static int sohci_compress_isochronous (struct usb_device *usb_dev, void *_isodesc) +{ + return USB_ST_NOTSUPPORTED; +} + + struct usb_operations sohci_device_operations = { sohci_usb_allocate, sohci_usb_deallocate, sohci_control_msg, sohci_bulk_msg, sohci_request_irq, + NULL, /* FIXME: should be release_irq/remove_irq */ + sohci_alloc_isochronous, + sohci_delete_isochronous, + sohci_sched_isochronous, + sohci_unsched_isochronous, + sohci_compress_isochronous }; diff -u --recursive --new-file v2.3.10/linux/drivers/usb/ohci.c linux/drivers/usb/ohci.c --- v2.3.10/linux/drivers/usb/ohci.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/usb/ohci.c Mon Jul 19 11:18:10 1999 @@ -437,6 +437,59 @@ ohci_remove_norm_ed_from_hw(ohci, ed, HCD_ED_BULK); } + +/* + * Remove a periodic ED from the host controller + */ +void ohci_remove_periodic_ed(struct ohci *ohci, struct ohci_ed *ed) +{ + struct ohci_device *root_hub = usb_to_ohci(ohci->bus->root_hub); + struct ohci_ed *cur_ed = NULL, *prev_ed; + unsigned long flags; + + /* FIXME: this will need to up fixed when add_periodic_ed() + * is updated to spread similar polling rate EDs out over + * multiple periodic queues. Currently this assumes that the + * 32ms (slowest) polling queue links to all others... */ + + /* search the periodic EDs, skipping the first one which is + * only a placeholder. */ + prev_ed = &root_hub->ed[ED_INT_32]; + if (prev_ed->next_ed) + cur_ed = bus_to_virt(le32_to_cpup(&prev_ed->next_ed)); + + while (cur_ed) { + if (ed == cur_ed) { /* remove the ED */ + /* set its SKIP bit and be sure its not in use */ + ohci_wait_for_ed_safe(ohci->regs, ed, HCD_ED_INT); + + /* unlink it */ + spin_lock_irqsave(&ohci_edtd_lock, flags); + prev_ed->next_ed = ed->next_ed; + spin_unlock_irqrestore(&ohci_edtd_lock, flags); + ed->next_ed = 0; + + break; + } + + spin_lock_irqsave(&ohci_edtd_lock, flags); + if (cur_ed->next_ed) { + prev_ed = cur_ed; + cur_ed = bus_to_virt(le32_to_cpup(&cur_ed->next_ed)); + spin_unlock_irqrestore(&ohci_edtd_lock, flags); + } else { + spin_unlock_irqrestore(&ohci_edtd_lock, flags); + + /* if multiple polling queues need to be checked, + * here is where you'd advance to the next one */ + + printk("usb-ohci: ed %p not found on periodic queue\n", ed); + break; + } + } +} /* ohci_remove_periodic_ed() */ + + /* * Remove all the EDs which have a given device address from a list. * Used when the device is unplugged. @@ -584,6 +637,8 @@ new_td->info = cpu_to_le32(OHCI_TD_CC_NEW); /* mark it as allocated */ allocate_td(new_td); + /* record the device that its on */ + new_td->usb_dev = ohci_to_usb(dev); return new_td; } } @@ -879,8 +934,11 @@ * * Period is desired polling interval in ms. The closest, shorter * match will be used. Powers of two from 1-32 are supported by OHCI. + * + * Returns: a "handle pointer" that release_irq can use to stop this + * interrupt. (It's really a pointer to the TD). NULL = error. */ -static int ohci_request_irq(struct usb_device *usb, unsigned int pipe, +static void* ohci_request_irq(struct usb_device *usb, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) { struct ohci_device *dev = usb_to_ohci(usb); @@ -892,14 +950,14 @@ interrupt_ed = ohci_get_free_ed(dev); if (!interrupt_ed) { printk(KERN_ERR "Out of EDs on device %p in ohci_request_irq\n", dev); - return -1; + return NULL; } td = ohci_get_free_td(dev); if (!td) { printk(KERN_ERR "Out of TDs in ohci_request_irq\n"); ohci_free_ed(interrupt_ed); - return -1; + return NULL; } /* @@ -917,10 +975,6 @@ OHCI_TD_ROUND, dev->data, maxps, dev_id, handler); - /* - * TODO: be aware of how the OHCI controller deals with DMA - * spanning more than one page. - */ /* * Put the TD onto our ED and make sure its ready to run @@ -936,17 +990,54 @@ /* Assimilate the new ED into the collective */ ohci_add_periodic_ed(dev->ohci, interrupt_ed, period); - /* FIXME: return a request handle that can be used by the - * caller to cancel this request. Be sure its guaranteed not - * to be re-used until the caller is guaranteed to know that - * the transfer has ended or been cancelled */ - return 0; + return (void*)td; } /* ohci_request_irq() */ - /* - * Control thread operations: + * Release an interrupt handler previously allocated using + * ohci_request_irq. This function does no validity checking, so make + * sure you're not releasing an already released handle as it may be + * in use by something else.. + * + * This function can NOT be called from an interrupt. */ +int ohci_release_irq(void* handle) +{ + struct ohci_device *dev; + struct ohci_td *int_td; + struct ohci_ed *int_ed; + +#ifdef OHCI_DEBUG + if (handle) + printk("usb-ohci: Releasing irq handle %p\n", handle); +#endif + + int_td = (struct ohci_td*)handle; + if (int_td == NULL) + return USB_ST_INTERNALERROR; + + dev = usb_to_ohci(int_td->usb_dev); + int_ed = int_td->ed; + + ohci_remove_periodic_ed(dev->ohci, int_ed); + + /* Tell the driver that the IRQ has been killed. */ + /* Passing NULL in the "buffer" void* along with the + * USB_ST_REMOVED status is the signal. */ + if (int_td->completed != NULL) + int_td->completed(USB_ST_REMOVED, NULL, 0, int_td->dev_id); + + /* Free the ED (& TD) */ + ohci_free_ed(int_ed); + + return USB_ST_NOERROR; +} /* ohci_release_irq() */ + + +/************************************ + * OHCI control transfer operations * + ************************************/ + static DECLARE_WAIT_QUEUE_HEAD(control_wakeup); /* @@ -1134,7 +1225,7 @@ #ifdef OHCI_DEBUG if (completion_status != 0) { - char *what = (completion_status < 0)? "timed out": + const char *what = (completion_status < 0)? "timed out": cc_names[completion_status & 0xf]; printk(KERN_ERR "ohci_control_msg: %s on pipe %x cmd %x %x %x %x %x\n", what, pipe, cmd->requesttype, cmd->request, @@ -1407,6 +1498,7 @@ /* .......... */ + /* * Allocate a new USB device to be attached to an OHCI controller */ @@ -1479,6 +1571,32 @@ } +static void *ohci_alloc_isochronous (struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id) +{ + return NULL; +} + +static void ohci_delete_isochronous (struct usb_device *dev, void *_isodesc) +{ + return; +} + +static int ohci_sched_isochronous (struct usb_device *usb_dev, void *_isodesc, void *_pisodesc) +{ + return USB_ST_NOTSUPPORTED; +} + +static int ohci_unsched_isochronous (struct usb_device *usb_dev, void *_isodesc) +{ + return USB_ST_NOTSUPPORTED; +} + +static int ohci_compress_isochronous (struct usb_device *usb_dev, void *_isodesc) +{ + return USB_ST_NOTSUPPORTED; +} + + /* * functions for the generic USB driver */ @@ -1488,6 +1606,12 @@ ohci_control_msg, ohci_bulk_msg, ohci_request_irq, + ohci_release_irq, + ohci_alloc_isochronous, + ohci_delete_isochronous, + ohci_sched_isochronous, + ohci_unsched_isochronous, + ohci_compress_isochronous }; diff -u --recursive --new-file v2.3.10/linux/drivers/usb/ohci.h linux/drivers/usb/ohci.h --- v2.3.10/linux/drivers/usb/ohci.h Thu Jul 8 15:42:21 1999 +++ linux/drivers/usb/ohci.h Tue Jul 13 10:09:01 1999 @@ -44,8 +44,10 @@ /* bit3: this is NOT the last TD in a contiguious TD chain * on the indicated ED. (0 means it is the last) */ + struct usb_device *usb_dev; /* the owning device */ + void *dev_id; /* user defined pointer passed to irq handler */ -} __attribute((aligned(16))); +} __attribute((aligned(32))); #define OHCI_TD_ROUND (1 << 18) /* buffer rounding bit */ #define OHCI_TD_D (3 << 19) /* direction of xfer: */ @@ -210,7 +212,7 @@ struct ohci_td td[NUM_TDS]; /* Transfer Descriptors */ unsigned long data[DATA_BUF_LEN]; -}; +} __attribute((aligned(32))); /* .... */ diff -u --recursive --new-file v2.3.10/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.3.10/linux/drivers/usb/printer.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/usb/printer.c Mon Jul 19 11:17:32 1999 @@ -318,7 +318,7 @@ } if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) { - printk(KERN_INFO " Failed to set configuration\n"); + printk(KERN_INFO " Failed usb_set_configuration: printer\n"); return -1; } #if 0 @@ -414,8 +414,6 @@ void cleanup_module(void) { - unsigned int offset; - usb_deregister(&printer_driver); unregister_chrdev(mymajor, "usblp"); } diff -u --recursive --new-file v2.3.10/linux/drivers/usb/stopusb linux/drivers/usb/stopusb --- v2.3.10/linux/drivers/usb/stopusb Fri Jun 4 13:33:43 1999 +++ linux/drivers/usb/stopusb Tue Jul 13 10:09:01 1999 @@ -1,7 +1,11 @@ #!/bin/sh +killall khubd +killall ohci-control killall uhci-control sleep 2 +rmmod hub +rmmod usb-ohci rmmod usb-uhci diff -u --recursive --new-file v2.3.10/linux/drivers/usb/uhci-debug.c linux/drivers/usb/uhci-debug.c --- v2.3.10/linux/drivers/usb/uhci-debug.c Sun Jun 20 11:43:42 1999 +++ linux/drivers/usb/uhci-debug.c Mon Jul 19 11:17:32 1999 @@ -43,9 +43,9 @@ spid = "?"; break; } - printk("MaxLen=%x %sEndPt=%x Dev=%x, PID=%x(%s) ", + printk("MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ", td->info >> 21, - ((td->info >> 19) & 1) ? "DT " : "", + ((td->info >> 19) & 1), (td->info >> 15) & 15, (td->info >> 8) & 127, (td->info & 0xff), diff -u --recursive --new-file v2.3.10/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.3.10/linux/drivers/usb/uhci.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/usb/uhci.c Mon Jul 19 11:18:42 1999 @@ -344,10 +344,14 @@ spin_unlock_irqrestore(&irqlist_lock, flags); } + /* * Request a interrupt handler.. + * + * Returns: a "handle pointer" that release_irq can use to stop this + * interrupt. (It's really a pointer to the TD). */ -static int uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) +static void* uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) { struct uhci_device *dev = usb_to_uhci(usb_dev); struct uhci_device *root_hub=usb_to_uhci(dev->uhci->bus->root_hub); @@ -357,7 +361,7 @@ unsigned int destination, status; /* Destination: pipe destination with INPUT */ - destination = (pipe & 0x0007ff00) | 0x69; + destination = (pipe & PIPE_DEVEP_MASK) | 0x69; /* Status: slow/fast, Interrupt, Active, Short Packet Detect Infinite Errors */ status = (pipe & (1 << 26)) | (1 << 24) | (1 << 23) | (1 << 29) | (0 << 27); @@ -368,7 +372,8 @@ td->link = 1; td->status = status; /* In */ - td->info = destination | (7 << 21) | (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* 8 bytes of data */ + td->info = destination | ((usb_maxpacket(usb_dev, pipe) - 1) << 21) | + (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); td->buffer = virt_to_bus(dev->data); td->first = td; td->qh = interrupt_qh; @@ -388,13 +393,16 @@ /* Add it into the skeleton */ uhci_insert_qh(interrupt_qh->skel, interrupt_qh); - return 0; + + return (void*)td; } /* * Remove running irq td from queues + * + * This function is not used anymore. */ - +#if 0 static int uhci_remove_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) { struct uhci_device *dev = usb_to_uhci(usb_dev); @@ -435,11 +443,56 @@ spin_unlock_irqrestore(&irqlist_lock, flags); return USB_ST_INTERNALERROR; } +#endif + +/* + * Release an interrupt handler previously allocated using + * uhci_request_irq. This function does no validity checking, so make + * sure you're not releasing an already released handle as it may be + * in use by something else.. + * + * This function can NOT be called from an interrupt. + */ +int uhci_release_irq(void* handle) +{ + struct uhci_td *td; + struct uhci_qh *interrupt_qh; + unsigned long flags; + +#ifdef UHCI_DEBUG + printk("usb-uhci: Releasing irq handle %p\n", handle); +#endif + + td = (struct uhci_td*)handle; + if (td == NULL) + return USB_ST_INTERNALERROR; + + /* Remove it from the internal irq_list */ + spin_lock_irqsave(&irqlist_lock, flags); + list_del(&td->irq_list); + spin_unlock_irqrestore(&irqlist_lock, flags); + + /* Remove the interrupt TD and QH */ + uhci_remove_td(td); + interrupt_qh = td->qh; + uhci_remove_qh(interrupt_qh->skel, interrupt_qh); + + if (td->completed != NULL) + td->completed(USB_ST_REMOVED, NULL, 0, td->dev_id); + + /* Free the TD and QH */ + uhci_td_deallocate(td); + uhci_qh_deallocate(interrupt_qh); + + return USB_ST_NOERROR; +} /* uhci_release_irq() */ + + /* * Isochronous thread operations */ -int uhci_compress_isochronous(struct usb_device *usb_dev, void *_isodesc) +static int uhci_compress_isochronous(struct usb_device *usb_dev, void *_isodesc) { struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc; char *data = isodesc->data; @@ -466,7 +519,7 @@ return totlen; } -int uhci_unsched_isochronous(struct usb_device *usb_dev, void *_isodesc) +static int uhci_unschedule_isochronous(struct usb_device *usb_dev, void *_isodesc) { struct uhci_device *dev = usb_to_uhci(usb_dev); struct uhci *uhci = dev->uhci; @@ -489,7 +542,7 @@ } /* td points to the one td we allocated for isochronous transfers */ -int uhci_sched_isochronous(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc) +static int uhci_schedule_isochronous(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc) { struct uhci_device *dev = usb_to_uhci(usb_dev); struct uhci *uhci = dev->uhci; @@ -499,7 +552,7 @@ if (isodesc->frame != -1) { printk("isoc queue not removed\n"); - uhci_unsched_isochronous(usb_dev, isodesc); + uhci_unschedule_isochronous(usb_dev, isodesc); } /* Insert TD into list */ @@ -541,7 +594,7 @@ /* * Initialize isochronous queue */ -void *uhci_alloc_isochronous(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id) +static void *uhci_allocate_isochronous(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id) { struct uhci_device *dev = usb_to_uhci(usb_dev); unsigned long destination, status; @@ -580,7 +633,7 @@ td = &isodesc->td[i]; /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (pipe & 0x0007ff00); + destination = (pipe & PIPE_DEVEP_MASK); if (usb_pipeout(pipe)) destination |= 0xE1; /* OUT */ @@ -616,13 +669,13 @@ return isodesc; } -void uhci_delete_isochronous(struct usb_device *usb_dev, void *_isodesc) +static void uhci_delete_isochronous(struct usb_device *usb_dev, void *_isodesc) { struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc; /* If it's still scheduled, unschedule them */ if (isodesc->frame) - uhci_unsched_isochronous(usb_dev, isodesc); + uhci_unschedule_isochronous(usb_dev, isodesc); /* Remove it from the IRQ list */ uhci_remove_irq_list(&isodesc->td[isodesc->num - 1]); @@ -732,7 +785,7 @@ * information, that's just ridiculously high. Most * control messages have just a few bytes of data. */ -static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, void *cmd, void *data, int len) +static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd, void *data, int len) { struct uhci_device *dev = usb_to_uhci(usb_dev); struct uhci_td *first, *td, *prevtd; @@ -746,7 +799,7 @@ first = td = uhci_td_allocate(dev); /* The "pipe" thing contains the destination in bits 8--18, 0x2D is SETUP */ - destination = (pipe & 0x0007ff00) | 0x2D; + destination = (pipe & PIPE_DEVEP_MASK) | 0x2D; /* Status: slow/fast, Active, Short Packet Detect Three Errors */ status = (pipe & (1 << 26)) | (1 << 23) | (1 << 29) | (3 << 27); @@ -807,7 +860,7 @@ td->backptr = &prevtd->link; td->status = (status /* & ~(3 << 27) */) | (1 << 24); /* no limit on final packet */ - td->info = destination | (0x7ff << 21); /* 0 bytes of data */ + td->info = destination | (UHCI_NULL_DATA_SIZE << 21); /* 0 bytes of data */ td->buffer = 0; td->first = first; td->link = 1; /* Terminate */ @@ -837,7 +890,7 @@ } if (uhci_debug && ret) { - __u8 *p = cmd; + __u8 *p = (__u8 *)cmd; printk("Failed cmd - %02X %02X %02X %02X %02X %02X %02X %02X\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); @@ -964,10 +1017,10 @@ I FORGOT WHAT IT EXACTLY DOES */ if (usb_pipeout(pipe)) { - destination = (pipe & 0x0007ff00) | 0xE1; + destination = (pipe & PIPE_DEVEP_MASK) | 0xE1; } else { - destination = (pipe & 0x0007ff00) | 0x69; + destination = (pipe & PIPE_DEVEP_MASK) | 0x69; } /* Status: slow/fast, Active, Short Packet Detect Three Errors */ @@ -1124,7 +1177,12 @@ uhci_control_msg, uhci_bulk_msg, uhci_request_irq, - uhci_remove_irq, + uhci_release_irq, + uhci_allocate_isochronous, + uhci_delete_isochronous, + uhci_schedule_isochronous, + uhci_unschedule_isochronous, + uhci_compress_isochronous }; /* @@ -1192,6 +1250,9 @@ * and find out what it wants to do.. */ usb_dev = uhci_usb_allocate(root_hub->usb); + if (!usb_dev) + return; + dev = usb_dev->hcpriv; dev->uhci = uhci; @@ -1622,8 +1683,8 @@ printk("UHCI queue dump:\n"); show_queues(uhci); } else if (signr == SIGUSR2) { - printk("UHCI debug toggle\n"); uhci_debug = !uhci_debug; + printk("UHCI debug toggle = %x\n", uhci_debug); } else { break; } diff -u --recursive --new-file v2.3.10/linux/drivers/usb/uhci.h linux/drivers/usb/uhci.h --- v2.3.10/linux/drivers/usb/uhci.h Thu Jul 8 15:42:21 1999 +++ linux/drivers/usb/uhci.h Mon Jul 19 11:17:32 1999 @@ -53,6 +53,8 @@ #define USBPORTSC_PR 0x0200 /* Port Reset */ #define USBPORTSC_SUSP 0x1000 /* Suspend */ +#define UHCI_NULL_DATA_SIZE 0x7ff /* for UHCI controller TD */ + struct uhci_qh { unsigned int link; /* Next queue */ unsigned int element; /* Queue element pointer */ @@ -237,12 +239,6 @@ void show_td(struct uhci_td * td); void show_status(struct uhci *uhci); void show_queues(struct uhci *uhci); - -int uhci_compress_isochronous(struct usb_device *usb_dev, void *_isodesc); -int uhci_unsched_isochronous(struct usb_device *usb_dev, void *_isodesc); -int uhci_sched_isochronous(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc); -void *uhci_alloc_isochronous(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id); -void uhci_delete_isochronous(struct usb_device *dev, void *_isodesc); #endif diff -u --recursive --new-file v2.3.10/linux/drivers/usb/usb-debug.c linux/drivers/usb/usb-debug.c --- v2.3.10/linux/drivers/usb/usb-debug.c Fri Jun 4 13:33:43 1999 +++ linux/drivers/usb/usb-debug.c Mon Jul 19 11:17:32 1999 @@ -53,12 +53,21 @@ */ void usb_show_device_descriptor(struct usb_device_descriptor *desc) { - printk(" USB version %x.%02x\n", desc->bcdUSB >> 8, desc->bcdUSB & 0xff); - printk(" Vendor: %04x\n", desc->idVendor); - printk(" Product: %04x\n", desc->idProduct); - printk(" Configurations: %d\n", desc->bNumConfigurations); + printk(" Length = %2d%s\n", desc->bLength, + desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)"); + printk(" DescriptorType = %02x\n", desc->bDescriptorType); + + printk(" USB version = %x.%02x\n", + desc->bcdUSB >> 8, desc->bcdUSB & 0xff); + printk(" Vendor:Product = %04x:%04x\n", + desc->idVendor, desc->idProduct); + printk(" MaxPacketSize0 = %d\n", desc->bMaxPacketSize0); + printk(" NumConfigurations = %d\n", desc->bNumConfigurations); + printk(" Device version = %x.%02x\n", + desc->bcdDevice >> 8, desc->bcdDevice & 0xff); - printk(" Device Class: %d\n", desc->bDeviceClass); + printk(" Device Class:SubClass:Protocol = %02x:%02x:%02x\n", + desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol); switch (desc->bDeviceClass) { case 0: printk(" Per-interface classes\n"); @@ -78,7 +87,7 @@ { printk("Configuration:\n"); printk(" bLength = %4d%s\n", desc->bLength, - desc->bLength == 9 ? "" : " (!!!)"); + desc->bLength == USB_DT_CONFIG_SIZE ? "" : " (!!!)"); printk(" bDescriptorType = %02x\n", desc->bDescriptorType); printk(" wTotalLength = %04x\n", desc->wTotalLength); printk(" bNumInterfaces = %02x\n", desc->bNumInterfaces); @@ -92,14 +101,13 @@ { printk(" Interface:\n"); printk(" bLength = %4d%s\n", desc->bLength, - desc->bLength == 9 ? "" : " (!!!)"); + desc->bLength == USB_DT_INTERFACE_SIZE ? "" : " (!!!)"); printk(" bDescriptorType = %02x\n", desc->bDescriptorType); printk(" bInterfaceNumber = %02x\n", desc->bInterfaceNumber); printk(" bAlternateSetting = %02x\n", desc->bAlternateSetting); printk(" bNumEndpoints = %02x\n", desc->bNumEndpoints); - printk(" bInterfaceClass = %02x\n", desc->bInterfaceClass); - printk(" bInterfaceSubClass = %02x\n", desc->bInterfaceSubClass); - printk(" bInterfaceProtocol = %02x\n", desc->bInterfaceProtocol); + printk(" bInterface Class:SubClass:Protocol = %02x:%02x:%02x\n", + desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol); printk(" iInterface = %02x\n", desc->iInterface); } @@ -108,7 +116,7 @@ char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" }; printk(" Endpoint:\n"); printk(" bLength = %4d%s\n", desc->bLength, - desc->bLength == 7 ? "" : " (!!!)"); + desc->bLength == USB_DT_ENDPOINT_SIZE ? "" : " (!!!)"); printk(" bDescriptorType = %02x\n", desc->bDescriptorType); printk(" bEndpointAddress = %02x (%s)\n", desc->bEndpointAddress, (desc->bEndpointAddress & 0x80) ? "in" : "out"); @@ -133,6 +141,8 @@ void usb_show_string(struct usb_device* dev, char *id, int index) { - if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index]) - printk("%s: %s\n", id, dev->stringindex[index]); + char *p = usb_string(dev, index); + + if (p != 0) + printk(KERN_INFO "%s: %s\n", id, p); } diff -u --recursive --new-file v2.3.10/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.3.10/linux/drivers/usb/usb.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/usb/usb.c Mon Jul 19 11:17:32 1999 @@ -1,5 +1,5 @@ /* - * driver/usb/usb.c + * drivers/usb/usb.c * * (C) Copyright Linus Torvalds 1999 * @@ -476,10 +476,18 @@ } kfree(dev->config); + for (i = 1; i < USB_MAXSTRINGS; ++i) { + if (dev->stringindex[i]) { + kfree(dev->stringindex[i]); + dev->stringindex[i] = 0; + } + } +#if 0 if (dev->stringindex) kfree(dev->stringindex); if (dev->stringtable) kfree(dev->stringtable); +#endif } void usb_init_root_hub(struct usb_device *dev) @@ -567,7 +575,8 @@ dr.length = size; while (i--) { - if (!(result = dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, buf, size))) + if (!(result = dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, buf, size)) + || result == USB_ST_STALL) break; } return result; @@ -588,11 +597,15 @@ int usb_get_device_descriptor(struct usb_device *dev) { - return usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor)); - le16_to_cpus(&dev->descriptor.bcdUSB); - le16_to_cpus(&dev->descriptor.idVendor); - le16_to_cpus(&dev->descriptor.idProduct); - le16_to_cpus(&dev->descriptor.bcdDevice); + int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, + sizeof(dev->descriptor)); + if (ret == 0) { + le16_to_cpus(&dev->descriptor.bcdUSB); + le16_to_cpus(&dev->descriptor.idVendor); + le16_to_cpus(&dev->descriptor.idProduct); + le16_to_cpus(&dev->descriptor.bcdDevice); + } + return ret; } int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) @@ -634,6 +647,19 @@ return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0); } +int usb_get_status (struct usb_device *dev, int type, int target, void *data) +{ + devrequest dr; + + dr.requesttype = USB_DIR_IN | type; /* USB_RECIP_DEVICE, _INTERFACE, or _ENDPOINT */ + dr.request = USB_REQ_GET_STATUS; + dr.value = 0; + dr.index = target; + dr.length = 2; + + return dev->bus->op->control_msg (dev, usb_rcvctrlpipe (dev,0), &dr, data, 2); +} + int usb_get_hub_status(struct usb_device *dev, void *data) { devrequest dr; @@ -884,6 +910,7 @@ return parse; } +#if 0 int usb_get_stringtable(struct usb_device *dev) { int i; @@ -914,7 +941,7 @@ return -1; /* get space for strings and index */ - dev->stringindex = kmalloc(sizeof(char *)*maxindex, GFP_KERNEL); + dev->stringindex = kmalloc(sizeof(char *) * (maxindex+1), GFP_KERNEL); if (!dev->stringindex) return -1; dev->stringtable = kmalloc(totalchars, GFP_KERNEL); @@ -925,7 +952,7 @@ } /* fill them in */ - memset(dev->stringindex, 0, sizeof(char *)*maxindex); + memset(dev->stringindex, 0, sizeof(char *) * (maxindex+1)); for (i=1, string = dev->stringtable; i <= maxindex; i++) { if (usb_get_string(dev, langid, i, buffer, bLengths[i])) continue; @@ -938,6 +965,48 @@ dev->maxstring = maxindex; return 0; } +#endif + +char *usb_string(struct usb_device *dev, int index) +{ + int len, i; + char *ptr; + union { + unsigned char buffer[256]; + struct usb_string_descriptor desc; + } u; + + if (index <= 0 || index >= USB_MAXSTRINGS) + return 0; + if (dev->stringindex[index] != 0) + return dev->stringindex[index]; + + if (dev->string_langid == 0) { + /* read string descriptor 0 */ + if (usb_get_string(dev, 0, 0, u.buffer, 2) == 0 + && u.desc.bLength >= 4 + && usb_get_string(dev, 0, 0, u.buffer, 4) == 0) + dev->string_langid = le16_to_cpup(&u.desc.wData[0]); + dev->string_langid |= 0x10000; /* so it's non-zero */ + } + + if (usb_get_string(dev, dev->string_langid, index, u.buffer, 2) + || usb_get_string(dev, dev->string_langid, index, u.buffer, + u.desc.bLength)) + return 0; + + len = u.desc.bLength / 2; /* includes terminating null */ + ptr = kmalloc(len, GFP_KERNEL); + if (ptr == 0) + return 0; + + for (i = 0; i < len - 1; ++i) + ptr[i] = le16_to_cpup(&u.desc.wData[i]); + ptr[i] = 0; + + dev->stringindex[index] = ptr; + return ptr; +} /* * By the time we get here, the device has gotten a new device ID @@ -1010,7 +1079,7 @@ return; } - usb_get_stringtable(dev); + /* usb_get_stringtable(dev); */ dev->actconfig = dev->config; dev->ifnum = 0; @@ -1036,7 +1105,38 @@ } } -int usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) +void* usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) { return dev->bus->op->request_irq(dev, pipe, handler, period, dev_id); +} + + +void *usb_allocate_isochronous (struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id) +{ + return usb_dev->bus->op->alloc_isoc (usb_dev, pipe, data, len, maxsze, completed, dev_id); +} + +void usb_delete_isochronous (struct usb_device *dev, void *_isodesc) +{ + return dev->bus->op->delete_isoc (dev, _isodesc); +} + +int usb_schedule_isochronous (struct usb_device *usb_dev, void *_isodesc, void *_pisodesc) +{ + return usb_dev->bus->op->sched_isoc (usb_dev, _isodesc, _pisodesc); +} + +int usb_unschedule_isochronous (struct usb_device *usb_dev, void *_isodesc) +{ + return usb_dev->bus->op->unsched_isoc (usb_dev, _isodesc); +} + +int usb_compress_isochronous (struct usb_device *usb_dev, void *_isodesc) +{ + return usb_dev->bus->op->compress_isoc (usb_dev, _isodesc); +} + +int usb_release_irq(struct usb_device *dev, void* handle) +{ + return dev->bus->op->release_irq(handle); } diff -u --recursive --new-file v2.3.10/linux/drivers/usb/usb.h linux/drivers/usb/usb.h --- v2.3.10/linux/drivers/usb/usb.h Thu Jul 8 15:42:21 1999 +++ linux/drivers/usb/usb.h Mon Jul 19 11:19:28 1999 @@ -149,6 +149,7 @@ #define USB_ST_REMOVED 0x100 #define USB_ST_TIMEOUT 0x110 #define USB_ST_INTERNALERROR -1 +#define USB_ST_NOTSUPPORTED -2 /* * USB device number allocation bitmap. There's one bitmap @@ -169,7 +170,7 @@ #define USB_MAXALTSETTING 5 #define USB_MAXINTERFACES 32 #define USB_MAXENDPOINTS 32 -#define USB_MAXSTRINGS 16 +#define USB_MAXSTRINGS 32 struct usb_device_descriptor { __u8 bLength; @@ -276,6 +277,9 @@ * of the buffer by this transfer. (-1 = unknown/unsupported) * void *dev_id - This is a user defined pointer set when the IRQ * is requested that is passed back. + * + * Special Cases: + * if (status == USB_ST_REMOVED), don't trust buffer or len. */ typedef int (*usb_device_irq)(int, void *, int, void *); @@ -284,8 +288,13 @@ int (*deallocate)(struct usb_device *); int (*control_msg)(struct usb_device *, unsigned int, devrequest *, void *, int); int (*bulk_msg)(struct usb_device *, unsigned int, void *, int,unsigned long *); - int (*request_irq)(struct usb_device *, unsigned int, usb_device_irq, int, void *); - int (*remove_irq)(struct usb_device *, unsigned int, usb_device_irq, int, void *); + void* (*request_irq)(struct usb_device *, unsigned int, usb_device_irq, int, void *); + int (*release_irq)(void* handle); + void *(*alloc_isoc)(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id); + void (*delete_isoc)(struct usb_device *dev, void *_isodesc); + int (*sched_isoc)(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc); + int (*unsched_isoc)(struct usb_device *usb_dev, void *_isodesc); + int (*compress_isoc)(struct usb_device *usb_dev, void *_isodesc); }; /* @@ -306,8 +315,8 @@ int devnum; /* Device number on USB bus */ int slow; /* Slow device? */ int maxpacketsize; /* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */ - int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */ - int halted; /* endpoint halts */ + unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */ + unsigned int halted; /* endpoint halts */ struct usb_config_descriptor *actconfig;/* the active configuration */ int epmaxpacket[16]; /* endpoint specific maximums */ int ifnum; /* active interface number */ @@ -316,10 +325,9 @@ struct usb_device_descriptor descriptor;/* Descriptor */ struct usb_config_descriptor *config; /* All of the configs */ struct usb_device *parent; - char *stringtable; /* Strings (multiple, null term) */ - char **stringindex; /* pointers to strings */ - int maxstring; /* max valid index */ - + char *stringindex[USB_MAXSTRINGS]; /* pointers to strings */ + int string_langid; /* language ID for strings */ + /* * Child devices - these can be either new devices * (if this is a hub device), or different instances @@ -341,7 +349,8 @@ extern void usb_register_bus(struct usb_bus *); extern void usb_deregister_bus(struct usb_bus *); -extern int usb_request_irq(struct usb_device *, unsigned int, usb_device_irq, int, void *); +extern void* usb_request_irq(struct usb_device *, unsigned int, usb_device_irq, int, void *); +extern int usb_release_irq(struct usb_device *dev, void *handle); extern void usb_init_root_hub(struct usb_device *dev); extern void usb_connect(struct usb_device *dev); @@ -353,6 +362,13 @@ extern int usb_parse_configuration(struct usb_device *dev, void *buf, int len); extern void usb_destroy_configuration(struct usb_device *dev); +extern void *usb_allocate_isochronous (struct usb_device *usb_dev, unsigned int pipe, void *data, int len, + int maxsze, usb_device_irq completed, void *dev_id); +extern void usb_delete_isochronous (struct usb_device *dev, void *_isodesc); +extern int usb_schedule_isochronous (struct usb_device *usb_dev, void *_isodesc, void *_pisodesc); +extern int usb_unschedule_isochronous (struct usb_device *usb_dev, void *_isodesc); +extern int usb_compress_isochronous (struct usb_device *usb_dev, void *_isodesc); + /* * Calling this entity a "pipe" is glorifying it. A USB pipe * is something embarrassingly simple: it basically consists @@ -377,7 +393,7 @@ * - device: bits 8-14 * - endpoint: bits 15-18 * - Data0/1: bit 19 - * - speed: bit 26 (00 = Full, 01 = Low Speed) + * - speed: bit 26 (0 = Full, 1 = Low Speed) * - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt, 10 = control, 11 = bulk) * * Why? Because it's arbitrary, and whatever encoding we select is really @@ -389,19 +405,18 @@ #define usb_maxpacket(dev,pipe) ((dev)->epmaxpacket[usb_pipeendpoint(pipe)]) #define usb_packetid(pipe) (((pipe) & 0x80) ? 0x69 : 0xE1) +#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1) #define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f) +#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff) #define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf) #define usb_pipedata(pipe) (((pipe) >> 19) & 1) -#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1) #define usb_pipeslow(pipe) (((pipe) >> 26) & 1) - #define usb_pipetype(pipe) (((pipe) >> 30) & 3) #define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == 0) #define usb_pipeint(pipe) (usb_pipetype((pipe)) == 1) #define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == 2) #define usb_pipebulk(pipe) (usb_pipetype((pipe)) == 3) -#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff) #define PIPE_DEVEP_MASK 0x0007ff00 /* The D0/D1 toggle bits */ @@ -445,21 +460,18 @@ int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size); int usb_clear_port_feature(struct usb_device *dev, int port, int feature); int usb_set_port_feature(struct usb_device *dev, int port, int feature); +int usb_get_status (struct usb_device *dev, int type, int target, void *data); int usb_get_hub_status(struct usb_device *dev, void *data); int usb_get_port_status(struct usb_device *dev, int port, void *data); int usb_get_protocol(struct usb_device *dev); int usb_set_protocol(struct usb_device *dev, int protocol); +int usb_set_interface(struct usb_device *dev, int interface, int alternate); int usb_set_idle(struct usb_device *dev, int duration, int report_id); +int usb_set_interface(struct usb_device *dev, int interface, int alternate); int usb_set_configuration(struct usb_device *dev, int configuration); int usb_get_report(struct usb_device *dev); +char *usb_string(struct usb_device *dev, int index); int usb_clear_halt(struct usb_device *dev, int endp); -static inline char * usb_string(struct usb_device* dev, int index) -{ - if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index]) - return dev->stringindex[index]; - else - return NULL; -} /* * Debugging helpers.. diff -u --recursive --new-file v2.3.10/linux/drivers/video/vgacon.c linux/drivers/video/vgacon.c --- v2.3.10/linux/drivers/video/vgacon.c Wed Jun 16 19:26:27 1999 +++ linux/drivers/video/vgacon.c Mon Jul 19 12:30:06 1999 @@ -186,18 +186,21 @@ vga_video_port_val = 0x3b5; if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { + static struct resource ega_console_resource = { "ega", 0x3B0, 0x3BF }; vga_video_type = VIDEO_TYPE_EGAM; vga_vram_end = 0xb8000; display_desc = "EGA+"; - request_region(0x3b0,16,"ega"); + request_resource(&ioport_resource, &ega_console_resource); } else { + static struct resource mda1_console_resource = { "mda", 0x3B0, 0x3BB }; + static struct resource mda2_console_resource = { "mda", 0x3BF, 0x3BF }; vga_video_type = VIDEO_TYPE_MDA; vga_vram_end = 0xb2000; display_desc = "*MDA"; - request_region(0x3b0,12,"mda"); - request_region(0x3bf, 1,"mda"); + request_resource(&ioport_resource, &mda1_console_resource); + request_resource(&ioport_resource, &mda2_console_resource); vga_video_font_height = 14; } } @@ -214,13 +217,15 @@ vga_vram_end = 0xc0000; if (!ORIG_VIDEO_ISVGA) { + static struct resource ega_console_resource = { "ega", 0x3C0, 0x3DF }; vga_video_type = VIDEO_TYPE_EGAC; display_desc = "EGA"; - request_region(0x3c0,32,"ega"); + request_resource(&ioport_resource, &ega_console_resource); } else { + static struct resource vga_console_resource = { "vga+", 0x3C0, 0x3DF }; vga_video_type = VIDEO_TYPE_VGAC; display_desc = "VGA+"; - request_region(0x3c0,32,"vga+"); + request_resource(&ioport_resource, &vga_console_resource); #ifdef VGA_CAN_DO_64KB /* @@ -261,10 +266,11 @@ } else { + static struct resource cga_console_resource = { "cga", 0x3D4, 0x3D5 }; vga_video_type = VIDEO_TYPE_CGA; vga_vram_end = 0xba000; display_desc = "*CGA"; - request_region(0x3d4,2,"cga"); + request_resource(&ioport_resource, &cga_console_resource); vga_video_font_height = 8; } } diff -u --recursive --new-file v2.3.10/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c --- v2.3.10/linux/fs/binfmt_aout.c Thu Jul 8 15:42:21 1999 +++ linux/fs/binfmt_aout.c Wed Jul 21 09:47:15 1999 @@ -106,7 +106,7 @@ # define START_STACK(u) (u.start_stack) #endif - if (!current->dumpable || atomic_read(¤t->mm->count) != 1) + if (!current->dumpable || atomic_read(¤t->mm->mm_users) != 1) return 0; current->dumpable = 0; diff -u --recursive --new-file v2.3.10/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v2.3.10/linux/fs/binfmt_elf.c Thu Jul 8 15:42:21 1999 +++ linux/fs/binfmt_elf.c Wed Jul 21 09:47:01 1999 @@ -1060,7 +1060,7 @@ if (!current->dumpable || limit < ELF_EXEC_PAGESIZE || - atomic_read(¤t->mm->count) != 1) + atomic_read(¤t->mm->mm_users) != 1) return 0; current->dumpable = 0; diff -u --recursive --new-file v2.3.10/linux/fs/buffer.c linux/fs/buffer.c --- v2.3.10/linux/fs/buffer.c Wed Jun 30 13:38:20 1999 +++ linux/fs/buffer.c Wed Jul 21 10:05:13 1999 @@ -757,9 +757,9 @@ free = test_and_clear_bit(PG_free_after, &page->flags); - if (page->owner != -1) + if (page->owner != (void *)-1) PAGE_BUG(page); - page->owner = (int)current; + page->owner = current; UnlockPage(page); if (free) @@ -1195,7 +1195,7 @@ if (!PageLocked(page)) BUG(); - if (page->owner != (int)current) + if (page->owner != current) PAGE_BUG(page); /* * Allocate async buffer heads pointing to this page, just for I/O. @@ -1270,6 +1270,7 @@ mark_buffer_clean(bh); clear_bit(BH_Uptodate, &bh->b_state); clear_bit(BH_Mapped, &bh->b_state); + clear_bit(BH_Req, &bh->b_state); bh->b_blocknr = 0; atomic_dec(&bh->b_count); } @@ -1556,7 +1557,7 @@ } if (!page->buffers) BUG(); - page->owner = -1; + page->owner = (void *)-1; head = page->buffers; bh = head; @@ -1605,7 +1606,7 @@ } else { if (!nr && rw == READ) { SetPageUptodate(page); - page->owner = (int)current; + page->owner = current; UnlockPage(page); } if (nr && (rw == WRITE)) @@ -1639,7 +1640,7 @@ blocks = PAGE_SIZE >> inode->i_sb->s_blocksize_bits; iblock = page->offset >> inode->i_sb->s_blocksize_bits; - page->owner = -1; + page->owner = (void *)-1; head = page->buffers; bh = head; nr = 0; @@ -1674,7 +1675,7 @@ * uptodate as well. */ SetPageUptodate(page); - page->owner = (int)current; + page->owner = current; UnlockPage(page); } return 0; @@ -1968,8 +1969,25 @@ goto out; if (func == 1) { - error = sync_old_buffers(); - goto out; + struct mm_struct *user_mm; + /* + * bdflush will spend all of it's time in kernel-space, + * without touching user-space, so we can switch it into + * 'lazy TLB mode' to reduce the cost of context-switches + * to and from bdflush. + */ + user_mm = current->mm; + atomic_inc(&user_mm->mm_count); + current->mm = NULL; + /* active_mm is still 'user_mm' */ + + error = sync_old_buffers(); + + current->mm = user_mm; + mmdrop(current->active_mm); + current->active_mm = user_mm; + + goto out; } /* Basically func 1 means read param 1, 2 means write param 1, etc */ diff -u --recursive --new-file v2.3.10/linux/fs/exec.c linux/fs/exec.c --- v2.3.10/linux/fs/exec.c Thu Jul 8 15:42:21 1999 +++ linux/fs/exec.c Wed Jul 21 13:57:56 1999 @@ -366,54 +366,41 @@ static int exec_mmap(void) { struct mm_struct * mm, * old_mm; - int retval, nr; - if (atomic_read(¤t->mm->count) == 1) { - flush_cache_mm(current->mm); + old_mm = current->mm; + if (old_mm && atomic_read(&old_mm->mm_users) == 1) { + flush_cache_mm(old_mm); mm_release(); - release_segments(current->mm); - exit_mmap(current->mm); - flush_tlb_mm(current->mm); + release_segments(old_mm); + exit_mmap(old_mm); + flush_tlb_mm(old_mm); return 0; } - retval = -ENOMEM; mm = mm_alloc(); - if (!mm) - goto fail_nomem; - - mm->cpu_vm_mask = (1UL << smp_processor_id()); - mm->total_vm = 0; - mm->rss = 0; - /* - * Make sure we have a private ldt if needed ... - */ - nr = current->tarray_ptr - &task[0]; - copy_segments(nr, current, mm); - - old_mm = current->mm; - current->mm = mm; - retval = new_page_tables(current); - if (retval) - goto fail_restore; - activate_context(current); - up(&mm->mmap_sem); - mm_release(); - mmput(old_mm); - return 0; - - /* - * Failure ... restore the prior mm_struct. - */ -fail_restore: - current->mm = old_mm; - /* restore the ldt for this task */ - copy_segments(nr, current, NULL); - release_segments(mm); - kmem_cache_free(mm_cachep, mm); - -fail_nomem: - return retval; + if (mm) { + mm->cpu_vm_mask = (1UL << smp_processor_id()); + mm->total_vm = 0; + mm->rss = 0; + mm->pgd = pgd_alloc(); + if (mm->pgd) { + struct mm_struct *active_mm = current->active_mm; + + current->mm = mm; + current->active_mm = mm; + SET_PAGE_DIR(current, mm->pgd); + activate_context(current); + mm_release(); + if (old_mm) { + mmput(old_mm); + return 0; + } + mmdrop(active_mm); + return 0; + } + kmem_cache_free(mm_cachep, mm); + } + return -ENOMEM; } /* @@ -632,7 +619,7 @@ if (id_change || cap_raised) { /* We can't suid-execute if we're sharing parts of the executable */ /* or if we're being traced (or if suid execs are not allowed) */ - /* (current->mm->count > 1 is ok, as we'll get a new mm anyway) */ + /* (current->mm->mm_users > 1 is ok, as we'll get a new mm anyway) */ if (IS_NOSUID(inode) || must_not_trace_exec(current) || (atomic_read(¤t->fs->count) > 1) diff -u --recursive --new-file v2.3.10/linux/fs/fcntl.c linux/fs/fcntl.c --- v2.3.10/linux/fs/fcntl.c Thu Jul 8 15:42:21 1999 +++ linux/fs/fcntl.c Mon Jul 12 10:15:18 1999 @@ -31,6 +31,7 @@ return error; out_putf: + write_unlock(&files->file_lock); fput(file); goto out; } diff -u --recursive --new-file v2.3.10/linux/fs/file_table.c linux/fs/file_table.c --- v2.3.10/linux/fs/file_table.c Thu Jul 8 15:42:21 1999 +++ linux/fs/file_table.c Wed Jul 14 13:30:36 1999 @@ -116,16 +116,29 @@ return 0; } -void _fput(struct file *file) +/* + * Called when retiring the last use of a file pointer. + */ +static void __fput(struct file *filp) { - atomic_inc(&file->f_count); + struct dentry * dentry = filp->f_dentry; + struct inode * inode = dentry->d_inode; + + if (filp->f_op && filp->f_op->release) + filp->f_op->release(inode, filp); + filp->f_dentry = NULL; + if (filp->f_mode & FMODE_WRITE) + put_write_access(inode); + dput(dentry); +} +void _fput(struct file *file) +{ lock_kernel(); locks_remove_flock(file); /* Still need the */ __fput(file); /* big lock here. */ unlock_kernel(); - atomic_set(&file->f_count, 0); file_list_lock(); list_del(&file->f_list); list_add(&file->f_list, &free_list); @@ -182,7 +195,7 @@ /* Writable file? */ if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)) - return 0; + goto too_bad; } file_list_unlock(); return 1; /* Tis' cool bro. */ diff -u --recursive --new-file v2.3.10/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c --- v2.3.10/linux/fs/ncpfs/dir.c Thu Jul 8 15:42:21 1999 +++ linux/fs/ncpfs/dir.c Fri Jul 16 10:57:40 1999 @@ -349,6 +349,9 @@ int len = dentry->d_name.len; struct ncpfs_inode_info finfo; __u8 __name[dentry->d_name.len + 1]; + + if (!dir) + return 0; server = NCP_SERVER(dir); diff -u --recursive --new-file v2.3.10/linux/fs/nfs/read.c linux/fs/nfs/read.c --- v2.3.10/linux/fs/nfs/read.c Thu Jul 8 15:42:21 1999 +++ linux/fs/nfs/read.c Mon Jul 19 12:29:29 1999 @@ -152,7 +152,7 @@ fail++; dprintk("NFS: %d successful reads, %d failures\n", succ, fail); } - page->owner = (int)current; // HACK, FIXME, will go away. + page->owner = current; // HACK, FIXME, will go away. UnlockPage(page); free_page(address); diff -u --recursive --new-file v2.3.10/linux/fs/open.c linux/fs/open.c --- v2.3.10/linux/fs/open.c Thu Jul 8 15:42:21 1999 +++ linux/fs/open.c Wed Jul 14 13:28:04 1999 @@ -765,22 +765,6 @@ #endif /* - * Called when retiring the last use of a file pointer. - */ -void __fput(struct file *filp) -{ - struct dentry * dentry = filp->f_dentry; - struct inode * inode = dentry->d_inode; - - if (filp->f_op && filp->f_op->release) - filp->f_op->release(inode, filp); - filp->f_dentry = NULL; - if (filp->f_mode & FMODE_WRITE) - put_write_access(inode); - dput(dentry); -} - -/* * "id" is the POSIX thread ID. We use the * files pointer for this.. */ diff -u --recursive --new-file v2.3.10/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.3.10/linux/fs/proc/array.c Wed Jun 30 13:38:20 1999 +++ linux/fs/proc/array.c Wed Jul 21 09:45:56 1999 @@ -223,7 +223,7 @@ LOAD_INT(a), LOAD_FRAC(a), LOAD_INT(b), LOAD_FRAC(b), LOAD_INT(c), LOAD_FRAC(c), - nr_running, nr_tasks, last_pid); + nr_running, nr_threads, last_pid); } static int get_kstat(char * buffer) @@ -312,7 +312,7 @@ unsigned long idle; uptime = jiffies; - idle = task[0]->times.tms_utime + task[0]->times.tms_stime; + idle = init_tasks[0]->times.tms_utime + init_tasks[0]->times.tms_stime; /* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but that would overflow about every five days at HZ == 100. @@ -495,7 +495,7 @@ int count = 0; stack_page = (unsigned long)p; - esp = p->tss.esp; + esp = p->thread.esp; if (!stack_page || esp < stack_page || esp >= 8188+stack_page) return 0; /* include/asm-i386/system.h:switch_to() pushes ebp last. */ @@ -742,7 +742,7 @@ { struct mm_struct * mm = p->mm; - if (mm && mm != &init_mm) { + if (mm) { struct vm_area_struct * vma = mm->mmap; unsigned long data = 0, stack = 0; unsigned long exec = 0, lib = 0; @@ -868,7 +868,7 @@ return 0; state = *get_task_state(tsk); vsize = eip = esp = 0; - if (tsk->mm && tsk->mm != &init_mm) { + if (tsk->mm) { struct vm_area_struct *vma = tsk->mm->mmap; while (vma) { vsize += vma->vm_end - vma->vm_start; @@ -1025,7 +1025,7 @@ read_unlock(&tasklist_lock); /* FIXME!! This should be done after the last use */ if (!tsk) return 0; - if (tsk->mm && tsk->mm != &init_mm) { + if (tsk->mm) { struct vm_area_struct * vma = tsk->mm->mmap; while (vma) { @@ -1111,11 +1111,11 @@ if (!p) goto freepage_out; - if (!p->mm || p->mm == &init_mm || count == 0) + if (!p->mm || count == 0) goto getlen_out; /* Check whether the mmaps could change if we sleep */ - volatile_task = (p != current || atomic_read(&p->mm->count) > 1); + volatile_task = (p != current || atomic_read(&p->mm->mm_users) > 1); /* decode f_pos */ lineno = *ppos >> MAPS_LINE_SHIFT; @@ -1378,8 +1378,6 @@ ok = p->dumpable; if(!cap_issubset(p->cap_permitted, current->cap_permitted)) ok=0; - if(!p->mm) /* Scooby scooby doo where are you ? */ - p=NULL; } read_unlock(&tasklist_lock); diff -u --recursive --new-file v2.3.10/linux/fs/proc/fd.c linux/fs/proc/fd.c --- v2.3.10/linux/fs/proc/fd.c Thu Jul 8 15:42:21 1999 +++ linux/fs/proc/fd.c Sun Jul 11 09:11:46 1999 @@ -133,7 +133,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; - struct task_struct * p, **tarrayp; + struct task_struct *p, *tmp; unsigned int fd, pid, ino; int retval; char buf[NUMBUF]; @@ -157,7 +157,6 @@ p = find_task_by_pid(pid); if (!p) goto out_unlock; - tarrayp = p->tarray_ptr; for (fd -= 2 ; p->files && fd < p->files->max_fds; fd++, filp->f_pos++) { @@ -182,8 +181,13 @@ goto out; read_lock(&tasklist_lock); - /* filldir() might have slept, so we must re-validate "p" */ - if (p != *tarrayp || p->pid != pid) + /* + * filldir() might have slept, so we must + * re-validate "p". This is fast enough due + * to the pidhash + */ + tmp = find_task_by_pid(pid); + if (p != tmp) break; } out_unlock: diff -u --recursive --new-file v2.3.10/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.3.10/linux/fs/proc/root.c Thu Jul 8 15:42:21 1999 +++ linux/fs/proc/root.c Sun Jul 11 09:11:46 1999 @@ -849,14 +849,29 @@ int len; if (dir->i_ino == PROC_ROOT_INO) { /* check for safety... */ - dir->i_nlink = proc_root.nlink; + extern unsigned long total_forks; + static int last_timestamp = 0; - read_lock(&tasklist_lock); - for_each_task(p) { - if (p->pid) - dir->i_nlink++; + /* + * this one can be a serious 'ps' performance problem if + * there are many threads running - thus we do 'lazy' + * link-recalculation - we change it only if the number + * of threads has increased. + */ + if (total_forks != last_timestamp) { + int nlink = proc_root.nlink; + + read_lock(&tasklist_lock); + last_timestamp = total_forks; + for_each_task(p) + nlink++; + read_unlock(&tasklist_lock); + /* + * subtract the # of idle threads which + * do not show up in /proc: + */ + dir->i_nlink = nlink - smp_num_cpus; } - read_unlock(&tasklist_lock); } if (!proc_lookup(dir, dentry)) diff -u --recursive --new-file v2.3.10/linux/include/asm-alpha/core_pyxis.h linux/include/asm-alpha/core_pyxis.h --- v2.3.10/linux/include/asm-alpha/core_pyxis.h Sun Dec 27 15:21:50 1998 +++ linux/include/asm-alpha/core_pyxis.h Mon Jul 12 07:49:36 1999 @@ -74,8 +74,8 @@ #define PYXIS_MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */ #define PYXIS_MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */ -#define PYXIS_DMA_WIN_BASE_DEFAULT (1024*1024*1024) -#define PYXIS_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) +#define PYXIS_DMA_WIN_BASE_DEFAULT (2UL*1024*1024*1024) +#define PYXIS_DMA_WIN_SIZE_DEFAULT (1UL*1024*1024*1024) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) #define PYXIS_DMA_WIN_BASE alpha_mv.dma_win_base diff -u --recursive --new-file v2.3.10/linux/include/asm-alpha/hardirq.h linux/include/asm-alpha/hardirq.h --- v2.3.10/linux/include/asm-alpha/hardirq.h Mon Oct 12 11:40:13 1998 +++ linux/include/asm-alpha/hardirq.h Mon Jul 19 13:12:47 1999 @@ -5,8 +5,12 @@ #include -extern unsigned int local_irq_count[NR_CPUS]; -extern unsigned long hardirq_no[NR_CPUS]; +#ifndef __SMP__ +extern int __local_irq_count; +#define local_irq_count(cpu) ((void)(cpu), __local_irq_count) +#else +#define local_irq_count(cpu) (cpu_data[cpu].irq_count) +#endif /* * Are we in an interrupt context? Either doing bottom half @@ -16,16 +20,16 @@ #define in_interrupt() \ ({ \ int __cpu = smp_processor_id(); \ - (local_irq_count[__cpu] + local_bh_count[__cpu]) != 0; \ + (local_irq_count(__cpu) + local_bh_count(__cpu)) != 0; \ }) #ifndef __SMP__ -#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) +#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) #define hardirq_endlock(cpu) ((void) 0) -#define hardirq_enter(cpu, irq) (local_irq_count[cpu]++) -#define hardirq_exit(cpu, irq) (local_irq_count[cpu]--) +#define hardirq_enter(cpu, irq) (local_irq_count(cpu)++) +#define hardirq_exit(cpu, irq) (local_irq_count(cpu)--) #define synchronize_irq() barrier() @@ -50,21 +54,20 @@ static inline void hardirq_enter(int cpu, int irq) { - ++local_irq_count[cpu]; + ++local_irq_count(cpu); atomic_inc(&global_irq_count); - hardirq_no[cpu] |= 1L << irq; /* debugging only */ } static inline void hardirq_exit(int cpu, int irq) { - hardirq_no[cpu] &= ~(1L << irq); /* debugging only */ atomic_dec(&global_irq_count); - --local_irq_count[cpu]; + --local_irq_count(cpu); } static inline int hardirq_trylock(int cpu) { - return !atomic_read(&global_irq_count) && !global_irq_lock.lock; + return (!atomic_read(&global_irq_count) + && !spin_is_locked(&global_irq_lock)); } #define hardirq_endlock(cpu) ((void)0) diff -u --recursive --new-file v2.3.10/linux/include/asm-alpha/mmu_context.h linux/include/asm-alpha/mmu_context.h --- v2.3.10/linux/include/asm-alpha/mmu_context.h Tue Jun 22 10:46:52 1999 +++ linux/include/asm-alpha/mmu_context.h Mon Jul 19 13:12:47 1999 @@ -66,7 +66,11 @@ #endif /* __SMP__ */ #define WIDTH_HARDWARE_ASN 8 +#ifdef __SMP__ #define WIDTH_THIS_PROCESSOR 5 +#else +#define WIDTH_THIS_PROCESSOR 0 +#endif #define ASN_FIRST_VERSION (1UL << (WIDTH_THIS_PROCESSOR + WIDTH_HARDWARE_ASN)) #define HARDWARE_ASN_MASK ((1UL << WIDTH_HARDWARE_ASN) - 1) @@ -95,12 +99,11 @@ unsigned long asn = cpu_last_asn(smp_processor_id()); unsigned long next = asn + 1; - if ((next ^ asn) & ~MAX_ASN) { + if ((asn & HARDWARE_ASN_MASK) >= MAX_ASN) { tbiap(); next = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION; } cpu_last_asn(smp_processor_id()) = next; - mm->context = next; /* full version + asn */ return next; } @@ -110,6 +113,12 @@ /* As described, ASN's are broken. But we can optimize for switching between threads -- if the mm is unchanged from current we needn't flush. */ + /* ??? May not be needed because EV4 PALcode recognizes that + ASN's are broken and does a tbiap itself on swpctx, under + the "Must set ASN or flush" rule. At least this is true + for a 1992 SRM, reports Joseph Martin (jmartin@hlo.dec.com). + I'm going to leave this here anyway, just to Be Sure. -- r~ */ + if (current->mm != p->mm) tbiap(); } @@ -119,17 +128,23 @@ { /* Check if our ASN is of an older version, or on a different CPU, and thus invalid. */ + /* ??? If we have two threads on different cpus, we'll continually + fight over the context. Find a way to record a per-mm, per-cpu + value for the asn. */ - long asn = cpu_last_asn(smp_processor_id()); + unsigned long asn = cpu_last_asn(smp_processor_id()); struct mm_struct *mm = p->mm; - long mmc = mm->context; + unsigned long mmc = mm->context; - if ((p->tss.mm_context ^ asn) & ~HARDWARE_ASN_MASK) { - if ((mmc ^ asn) & ~HARDWARE_ASN_MASK) - mmc = __get_new_mmu_context(p, mm); - p->tss.mm_context = mmc; - p->tss.asn = mmc & HARDWARE_ASN_MASK; + if ((mmc ^ asn) & ~HARDWARE_ASN_MASK) { + mmc = __get_new_mmu_context(p, mm); + mm->context = mmc; } + + /* Always update the PCB ASN. Another thread may have allocated + a new mm->context (via flush_tlb_mm) without the ASN serial + number wrapping. We have no way to detect when this is needed. */ + p->tss.asn = mmc & HARDWARE_ASN_MASK; } #ifdef CONFIG_ALPHA_GENERIC diff -u --recursive --new-file v2.3.10/linux/include/asm-alpha/param.h linux/include/asm-alpha/param.h --- v2.3.10/linux/include/asm-alpha/param.h Sun Mar 24 02:09:37 1996 +++ linux/include/asm-alpha/param.h Tue Jul 13 02:29:35 1999 @@ -1,8 +1,18 @@ #ifndef _ASM_ALPHA_PARAM_H #define _ASM_ALPHA_PARAM_H +/* ??? Gross. I don't want to parameterize this, and supposedly the + hardware ignores reprogramming. We also need userland buy-in to the + change in HZ, since this is visible in the wait4 resources etc. */ + +#include + #ifndef HZ -# define HZ 1024 +# ifndef CONFIG_ALPHA_RAWHIDE +# define HZ 1024 +# else +# define HZ 1200 +# endif #endif #define EXEC_PAGESIZE 8192 diff -u --recursive --new-file v2.3.10/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h --- v2.3.10/linux/include/asm-alpha/pgtable.h Wed Jun 30 13:38:20 1999 +++ linux/include/asm-alpha/pgtable.h Mon Jul 19 13:12:47 1999 @@ -49,7 +49,6 @@ __EXTERN_INLINE void ev5_flush_tlb_current(struct mm_struct *mm) { - mm->context = 0; get_new_mmu_context(current, mm); reload_context(current); } diff -u --recursive --new-file v2.3.10/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h --- v2.3.10/linux/include/asm-alpha/processor.h Tue Jun 22 10:46:52 1999 +++ linux/include/asm-alpha/processor.h Mon Jul 12 07:49:36 1999 @@ -61,15 +61,6 @@ */ unsigned long flags; - /* The full version of the ASN including serial number. - - Two threads running on two different processors must of necessity - have different serial numbers. Having this duplicated from - mm->context allows them to be slightly out of sync preventing - the asn from incrementing each and every time the two threads - are scheduled. */ - unsigned long mm_context; - /* Perform syscall argument validation (get/set_fs). */ mm_segment_t fs; @@ -86,7 +77,7 @@ 0, 0, 0, \ 0, 0, 0, \ 0, 0, 0, \ - 0, 0, \ + 0, \ KERNEL_DS \ } diff -u --recursive --new-file v2.3.10/linux/include/asm-alpha/ptrace.h linux/include/asm-alpha/ptrace.h --- v2.3.10/linux/include/asm-alpha/ptrace.h Mon Apr 7 11:35:31 1997 +++ linux/include/asm-alpha/ptrace.h Mon Jul 12 07:49:36 1999 @@ -67,7 +67,7 @@ }; #ifdef __KERNEL__ -#define user_mode(regs) ((regs)->ps & 8) +#define user_mode(regs) (((regs)->ps & 8) != 0) #define instruction_pointer(regs) ((regs)->pc) extern void show_regs(struct pt_regs *); #endif diff -u --recursive --new-file v2.3.10/linux/include/asm-alpha/smp.h linux/include/asm-alpha/smp.h --- v2.3.10/linux/include/asm-alpha/smp.h Tue Jun 22 10:46:52 1999 +++ linux/include/asm-alpha/smp.h Mon Jul 19 13:12:47 1999 @@ -4,7 +4,6 @@ #ifdef __SMP__ #include -#include #include struct cpuinfo_alpha { @@ -16,7 +15,8 @@ unsigned long ipi_count; unsigned long prof_multiplier; unsigned long prof_counter; -} __cacheline_aligned; + int irq_count, bh_count; +} __attribute__((aligned(64))); extern struct cpuinfo_alpha cpu_data[NR_CPUS]; diff -u --recursive --new-file v2.3.10/linux/include/asm-alpha/softirq.h linux/include/asm-alpha/softirq.h --- v2.3.10/linux/include/asm-alpha/softirq.h Tue Jun 22 10:46:52 1999 +++ linux/include/asm-alpha/softirq.h Mon Jul 19 13:12:47 1999 @@ -5,28 +5,33 @@ #include #include -extern unsigned int local_bh_count[NR_CPUS]; +#ifndef __SMP__ +extern int __local_bh_count; +#define local_bh_count(cpu) ((void)(cpu), __local_bh_count) +#else +#define local_bh_count(cpu) (cpu_data[cpu].bh_count) +#endif extern inline void cpu_bh_disable(int cpu) { - local_bh_count[cpu]++; + local_bh_count(cpu)++; mb(); } extern inline void cpu_bh_enable(int cpu) { mb(); - local_bh_count[cpu]--; + local_bh_count(cpu)--; } extern inline int cpu_bh_trylock(int cpu) { - return local_bh_count[cpu] ? 0 : (local_bh_count[cpu] = 1); + return local_bh_count(cpu) ? 0 : (local_bh_count(cpu) = 1); } extern inline void cpu_bh_endlock(int cpu) { - local_bh_count[cpu] = 0; + local_bh_count(cpu) = 0; } #define local_bh_enable() cpu_bh_enable(smp_processor_id()) diff -u --recursive --new-file v2.3.10/linux/include/asm-alpha/spinlock.h linux/include/asm-alpha/spinlock.h --- v2.3.10/linux/include/asm-alpha/spinlock.h Tue Jun 22 10:46:52 1999 +++ linux/include/asm-alpha/spinlock.h Mon Jul 19 13:12:47 1999 @@ -65,11 +65,12 @@ #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } #endif -#define spin_lock_init(lock) ((void) 0) -#define spin_lock(lock) ((void) 0) -#define spin_trylock(lock) (1) -#define spin_unlock_wait(lock) ((void) 0) -#define spin_unlock(lock) ((void) 0) +#define spin_lock_init(lock) ((void)(lock)) +#define spin_lock(lock) ((void)(lock)) +#define spin_trylock(lock) ((void)(lock), 1) +#define spin_unlock_wait(lock) ((void)(lock)) +#define spin_unlock(lock) ((void)(lock)) +#define spin_is_locked(lock) ((void)(lock), 0) /* * Read-write spinlocks, allowing multiple readers @@ -91,10 +92,10 @@ #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } #endif -#define read_lock(lock) ((void) 0) -#define read_unlock(lock) ((void) 0) -#define write_lock(lock) ((void) 0) -#define write_unlock(lock) ((void) 0) +#define read_lock(lock) ((void)(lock)) +#define read_unlock(lock) ((void)(lock)) +#define write_lock(lock) ((void)(lock)) +#define write_unlock(lock) ((void)(lock)) #else /* __SMP__ */ @@ -131,8 +132,8 @@ #define spin_lock_init(x) ((x)->lock = 0) #endif -#define spin_unlock_wait(x) \ - ({ do { barrier(); } while(((volatile spinlock_t *)x)->lock); }) +#define spin_is_locked(x) ((x)->lock != 0) +#define spin_unlock_wait(x) ({ do { barrier(); } while ((x)->lock); }) typedef struct { unsigned long a[100]; } __dummy_lock_t; #define __dummy_lock(lock) (*(__dummy_lock_t *)(lock)) diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/arch-arc/time.h linux/include/asm-arm/arch-arc/time.h --- v2.3.10/linux/include/asm-arm/arch-arc/time.h Sat May 8 11:06:57 1999 +++ linux/include/asm-arm/arch-arc/time.h Mon Jul 19 09:52:57 1999 @@ -167,6 +167,9 @@ else last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ } + + if (!user_mode(regs)) + do_profile(instruction_pointer(regs)); } static struct irqaction timerirq = { diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/arch-ebsa110/hardware.h linux/include/asm-arm/arch-ebsa110/hardware.h --- v2.3.10/linux/include/asm-arm/arch-ebsa110/hardware.h Sat May 8 11:06:57 1999 +++ linux/include/asm-arm/arch-ebsa110/hardware.h Mon Jul 19 09:52:57 1999 @@ -40,5 +40,7 @@ #define FLUSH_BASE 0xdf000000 #define PCIO_BASE 0xf0000000 +#define PARAMS_BASE (PAGE_OFFSET + 0x400) + #endif diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/arch-ebsa285/io.h linux/include/asm-arm/arch-ebsa285/io.h --- v2.3.10/linux/include/asm-arm/arch-ebsa285/io.h Sat May 8 11:06:57 1999 +++ linux/include/asm-arm/arch-ebsa285/io.h Mon Jul 19 09:52:57 1999 @@ -1,10 +1,11 @@ /* * linux/include/asm-arm/arch-ebsa285/io.h * - * Copyright (C) 1997,1998 Russell King + * Copyright (C) 1997-1999 Russell King * * Modifications: - * 06-Dec-1997 RMK Created. + * 06-12-1997 RMK Created. + * 07-04-1999 RMK Major cleanup */ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H @@ -18,132 +19,33 @@ #undef ARCH_IO_DELAY #define ARCH_READWRITE -/* - * Dynamic IO functions - let the compiler - * optimize the expressions - */ -#define DECLARE_DYN_OUT(fnsuffix,instr,typ) \ -extern __inline__ void \ -__out##fnsuffix (unsigned int value, unsigned int port) \ -{ \ - __asm__ __volatile__( \ - "str%?" ##instr## " %0, [%1, %2] @ out"###fnsuffix \ - : \ - : "r" (value), "r" (PCIO_BASE), typ (port)); \ -} +#define __pci_io_addr(x) (PCIO_BASE + (unsigned int)(x)) -#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ) \ -extern __inline__ unsigned sz \ -__in##fnsuffix (unsigned int port) \ -{ \ - unsigned long value; \ - __asm__ __volatile__( \ - "ldr%?" ##instr## " %0, [%1, %2] @ in"###fnsuffix \ - : "=&r" (value) \ - : "r" (PCIO_BASE), typ (port)); \ - return (unsigned sz)value; \ -} +#define __inb(p) (*(volatile unsigned char *)__pci_io_addr(p)) +#define __inl(p) (*(volatile unsigned long *)__pci_io_addr(p)) -extern __inline__ unsigned int __ioaddr (unsigned int port) \ -{ \ - return (unsigned int)(PCIO_BASE + port); \ +extern __inline__ unsigned int __inw(unsigned int port) +{ + unsigned int value; + __asm__ __volatile__( + "ldr%?h %0, [%1, %2] @ inw" + : "=&r" (value) + : "r" (PCIO_BASE), "r" (port)); + return value; } -#define DECLARE_IO(sz,fnsuffix,instr,typ) \ - DECLARE_DYN_OUT(fnsuffix,instr,typ) \ - DECLARE_DYN_IN(sz,fnsuffix,instr,typ) - -DECLARE_IO(char,b,"b","Jr") -DECLARE_IO(short,w,"h","r") -DECLARE_IO(long,l,"","Jr") - -#undef DECLARE_IO -#undef DECLARE_DYN_OUT -#undef DECLARE_DYN_IN - -/* - * Constant address IO functions - * - * These have to be macros for the 'J' constraint to work - - * +/-4096 immediate operand. - */ -#define __outbc(value,port) \ -({ \ - __asm__ __volatile__( \ - "str%?b %0, [%1, %2] @ outbc" \ - : \ - : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \ -}) - -#define __inbc(port) \ -({ \ - unsigned char result; \ - __asm__ __volatile__( \ - "ldr%?b %0, [%1, %2] @ inbc" \ - : "=r" (result) \ - : "r" (PCIO_BASE), "Jr" (port)); \ - result; \ -}) - -#define __outwc(value,port) \ -({ \ - __asm__ __volatile__( \ - "str%?h %0, [%1, %2] @ outwc" \ - : \ - : "r" (value), "r" (PCIO_BASE), "r" (port)); \ -}) - -#define __inwc(port) \ -({ \ - unsigned short result; \ - __asm__ __volatile__( \ - "ldr%?h %0, [%1, %2] @ inwc" \ - : "=r" (result) \ - : "r" (PCIO_BASE), "r" (port)); \ - result & 0xffff; \ -}) - -#define __outlc(value,port) \ -({ \ - __asm__ __volatile__( \ - "str%? %0, [%1, %2] @ outlc" \ - : \ - : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \ -}) - -#define __inlc(port) \ -({ \ - unsigned long result; \ - __asm__ __volatile__( \ - "ldr%? %0, [%1, %2] @ inlc" \ - : "=r" (result) \ - : "r" (PCIO_BASE), "Jr" (port)); \ - result; \ -}) -#define __ioaddrc(port) \ -({ \ - unsigned long addr; \ - addr = PCIO_BASE + port; \ - addr; \ -}) +#define __outb(v,p) (*(volatile unsigned char *)__pci_io_addr(p) = (v)) +#define __outl(v,p) (*(volatile unsigned long *)__pci_io_addr(p) = (v)) -/* - * Translated address IO functions - * - * IO address has already been translated to a virtual address - */ -#define outb_t(v,p) \ - (*(volatile unsigned char *)(p) = (v)) - -#define inb_t(p) \ - (*(volatile unsigned char *)(p)) - -#define outl_t(v,p) \ - (*(volatile unsigned long *)(p) = (v)) +extern __inline__ void __outw(unsigned int value, unsigned int port) +{ + __asm__ __volatile__( + "str%?h %0, [%1, %2] @ outw" + : : "r" (value), "r" (PCIO_BASE), "r" (port)); +} -#define inl_t(p) \ - (*(volatile unsigned long *)(p)) +#define __ioaddr(p) __pci_io_addr(p) /* * ioremap support - validate a PCI memory address, @@ -151,7 +53,7 @@ * address for the page tables. */ #define valid_ioaddr(iomem,size) ((iomem) < 0x80000000 && (iomem) + (size) <= 0x80000000) -#define io_to_phys(iomem) ((iomem) + DC21285_PCI_MEM) +#define io_to_phys(iomem) ((iomem) + DC21285_PCI_MEM) /* * Fudge up IO addresses by this much. Once we're confident that nobody @@ -178,28 +80,20 @@ extern void iounmap(void *addr); -#define DECLARE_PCI_WRITE(typ,fnsuffix) \ -static inline void write##fnsuffix(unsigned typ val, unsigned int addr) \ -{ \ - *(volatile unsigned typ *)(IO_FUDGE_FACTOR + addr) = val; \ -} +#define __pci_mem_addr(x) ((void *)(IO_FUDGE_FACTOR + (unsigned long)(x))) -#define DECLARE_PCI_READ(typ,fnsuffix) \ -static inline unsigned typ read##fnsuffix (unsigned int addr) \ -{ \ - return *(volatile unsigned typ *)(IO_FUDGE_FACTOR + addr); \ -} +#define readb(addr) (*(volatile unsigned char *)__pci_mem_addr(addr)) +#define readw(addr) (*(volatile unsigned short *)__pci_mem_addr(addr)) +#define readl(addr) (*(volatile unsigned long *)__pci_mem_addr(addr)) + +#define writeb(b,addr) (*(volatile unsigned char *)__pci_mem_addr(addr) = (b)) +#define writew(b,addr) (*(volatile unsigned short *)__pci_mem_addr(addr) = (b)) +#define writel(b,addr) (*(volatile unsigned long *)__pci_mem_addr(addr) = (b)) + +#define memset_io(a,b,c) memset(__pci_mem_addr(a),(b),(c)) +#define memcpy_fromio(a,b,c) memcpy((a),__pci_mem_addr(b),(c)) +#define memcpy_toio(a,b,c) memcpy(__pci_mem_addr(a),(b),(c)) -#define DECLARE_PCI(typ,fnsuffix) \ - DECLARE_PCI_WRITE(typ,fnsuffix) \ - DECLARE_PCI_READ(typ,fnsuffix) - -DECLARE_PCI(char,b) -DECLARE_PCI(short,w) -DECLARE_PCI(long,l) - -#undef DECLARE_PCI -#undef DECLARE_PCI_READ -#undef DECLARE_PCI_WRITE +#define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__pci_mem_addr(b),(c),(d)) #endif diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/arch-ebsa285/irq.h linux/include/asm-arm/arch-ebsa285/irq.h --- v2.3.10/linux/include/asm-arm/arch-ebsa285/irq.h Wed Jun 30 13:38:20 1999 +++ linux/include/asm-arm/arch-ebsa285/irq.h Mon Jul 19 09:52:57 1999 @@ -159,6 +159,8 @@ if (isa_irq != -1) { /* * Setup, and then probe for an ISA PIC + * If the PIC is not there, then we + * ignore the PIC. */ outb(0x11, PIC_LO); outb(_ISA_IRQ(0), PIC_MASK_LO); /* IRQ number */ diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/arch-ebsa285/time.h linux/include/asm-arm/arch-ebsa285/time.h --- v2.3.10/linux/include/asm-arm/arch-ebsa285/time.h Thu Jun 17 01:11:35 1999 +++ linux/include/asm-arm/arch-ebsa285/time.h Mon Jul 19 09:52:57 1999 @@ -115,6 +115,9 @@ else last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ } + + if (!user_mode(regs)) + do_profile(instruction_pointer(regs)); } static struct irqaction isa_timer_irq = { @@ -257,6 +260,9 @@ else last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ } + + if (!user_mode(regs)) + do_profile(instruction_pointer(regs)); } static struct irqaction __ebsa285_data timer1_irq = { @@ -279,22 +285,20 @@ */ extern __inline__ void setup_timer(void) { - switch(machine_arch_type) { - case MACH_TYPE_CO285: + if (machine_arch_type == MACH_TYPE_CO285) /* * Add-in 21285s shouldn't access the RTC */ rtc_base = 0; - break; - - default: + else rtc_base = 0x70; - break; - } if (rtc_base) { int reg_d, reg_b; + /* + * Probe for the RTC. + */ reg_d = CMOS_READ(RTC_REG_D); /* @@ -314,7 +318,7 @@ CMOS_READ(RTC_REG_B) == reg_b) { /* - * Check the battery + * We have a RTC. Check the battery */ if ((reg_d & 0x80) == 0) printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n"); @@ -332,7 +336,6 @@ xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0); set_rtc_mmss = set_dummy_time; } - if (machine_is_ebsa285() || machine_is_co285()) { gettimeoffset = timer1_gettimeoffset; diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/arch-rpc/time.h linux/include/asm-arm/arch-rpc/time.h --- v2.3.10/linux/include/asm-arm/arch-rpc/time.h Sat May 8 11:06:57 1999 +++ linux/include/asm-arm/arch-rpc/time.h Mon Jul 19 09:52:57 1999 @@ -151,7 +151,7 @@ */ buf[4] &= 0x1f; buf[3] &= 0x3f; -printk("Year %4d mon %02X day %02X hour %02X min %02X sec %02X\n", year, buf[4], buf[3], buf[2], buf[1], buf[0]); + for (i = 0; i < 5; i++) BCD_TO_BIN(buf[i]); @@ -175,6 +175,9 @@ else last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ } + + if (!user_mode(regs)) + do_profile(instruction_pointer(regs)); } static struct irqaction timerirq = { diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/io.h linux/include/asm-arm/io.h --- v2.3.10/linux/include/asm-arm/io.h Thu Jun 17 01:11:35 1999 +++ linux/include/asm-arm/io.h Mon Jul 19 09:52:57 1999 @@ -22,17 +22,6 @@ extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); -/* - * String version of IO memory access ops: - */ -extern void _memcpy_fromio(void *, unsigned long, unsigned long); -extern void _memcpy_toio(unsigned long, const void *, unsigned long); -extern void _memset_io(unsigned long, int, unsigned long); - -#define memcpy_fromio(to,from,len) _memcpy_fromio((to),(unsigned long)(from),(len)) -#define memcpy_toio(to,from,len) _memcpy_toio((unsigned long)(to),(from),(len)) -#define memset_io(addr,c,len) _memset_io((unsigned long)(addr),(c),(len)) - #endif #include @@ -121,8 +110,12 @@ * This macro will give you the translated IO address for this particular * architecture, which can be used with the out_t... functions. */ +#ifdef __ioaddrc #define ioaddr(port) \ (__builtin_constant_p((port)) ? __ioaddrc((port)) : __ioaddr((port))) +#else +#define ioaddr(port) __ioaddr((port)) +#endif #ifndef ARCH_IO_DELAY /* @@ -203,6 +196,19 @@ #define writew(v,p) panic("writew called, but not implemented") #define writel(v,p) panic("writel called, but not implemented") +#endif + +#ifndef memcpy_fromio +/* + * String version of IO memory access ops: + */ +extern void _memcpy_fromio(void *, unsigned long, unsigned long); +extern void _memcpy_toio(unsigned long, const void *, unsigned long); +extern void _memset_io(unsigned long, int, unsigned long); + +#define memcpy_fromio(to,from,len) _memcpy_fromio((to),(unsigned long)(from),(len)) +#define memcpy_toio(to,from,len) _memcpy_toio((unsigned long)(to),(from),(len)) +#define memset_io(addr,c,len) _memset_io((unsigned long)(addr),(c),(len)) #endif /* diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/page.h linux/include/asm-arm/page.h --- v2.3.10/linux/include/asm-arm/page.h Sat May 8 11:06:57 1999 +++ linux/include/asm-arm/page.h Mon Jul 19 09:52:57 1999 @@ -6,6 +6,19 @@ #ifdef __KERNEL__ +#ifndef __ASSEMBLY__ + +#define BUG() do { \ + printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ + *(int *)0 = 0; \ +} while (0) + +#define PAGE_BUG(page) do { \ + BUG(); \ +} while (0) + +#endif /* __ASSEMBLY__ */ + #define get_user_page(vaddr) __get_free_page(GFP_KERNEL) #define free_user_page(page, addr) free_page(addr) #define clear_page(page) memzero((void *)(page), PAGE_SIZE) diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/processor.h linux/include/asm-arm/processor.h --- v2.3.10/linux/include/asm-arm/processor.h Thu Jun 17 01:11:35 1999 +++ linux/include/asm-arm/processor.h Mon Jul 19 09:52:57 1999 @@ -40,12 +40,20 @@ #include #include +struct debug_info { + int nsaved; + struct { + unsigned long address; + unsigned long insn; + } bp[2]; +}; + struct thread_struct { unsigned long address; /* Address of fault */ unsigned long trap_no; /* Trap number */ unsigned long error_code; /* Error code of trap */ union fp_state fpstate; /* FPE save state */ - unsigned long debug[NR_DEBUGS]; /* Debug/ptrace */ + struct debug_info debug; /* Debug/ptrace */ struct context_save_struct *save; /* context save */ unsigned long memmap; /* page tables */ EXTRA_THREAD_STRUCT diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/spinlock.h linux/include/asm-arm/spinlock.h --- v2.3.10/linux/include/asm-arm/spinlock.h Thu Jun 17 01:11:35 1999 +++ linux/include/asm-arm/spinlock.h Mon Jul 19 13:12:47 1999 @@ -54,7 +54,7 @@ #define SPIN_LOCK_UNLOCKED EMPTY_STRUCT_INIT(spinlock_t) #define spin_lock_init(lock) do { } while(0) -#define spin_lock(lock) do { } while(0) +#define spin_lock(lock) (void)(lock) /* Not "unused variable". */ #define spin_trylock(lock) (1) #define spin_unlock_wait(lock) do { } while(0) #define spin_unlock(lock) do { } while(0) @@ -105,9 +105,9 @@ typedef EMPTY_STRUCT rwlock_t; #define RW_LOCK_UNLOCKED EMPTY_STRUCT_INIT(rwlock_t) -#define read_lock(lock) do { } while(0) +#define read_lock(lock) (void)(lock) /* Not "unused variable". */ #define read_unlock(lock) do { } while(0) -#define write_lock(lock) do { } while(0) +#define write_lock(lock) (void)(lock) /* Not "unused variable". */ #define write_unlock(lock) do { } while(0) #else diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/string.h linux/include/asm-arm/string.h --- v2.3.10/linux/include/asm-arm/string.h Tue Jan 20 16:39:43 1998 +++ linux/include/asm-arm/string.h Mon Jul 19 09:52:57 1999 @@ -14,6 +14,7 @@ #define __HAVE_ARCH_MEMCPY #define __HAVE_ARCH_MEMMOVE #define __HAVE_ARCH_MEMSET +#define __HAVE_ARCH_MEMCHR #define __HAVE_ARCH_MEMZERO extern void memzero(void *ptr, int n); diff -u --recursive --new-file v2.3.10/linux/include/asm-arm/system.h linux/include/asm-arm/system.h --- v2.3.10/linux/include/asm-arm/system.h Thu Jun 17 01:11:35 1999 +++ linux/include/asm-arm/system.h Mon Jul 19 09:52:57 1999 @@ -32,6 +32,7 @@ #define MACH_TYPE_CLPS7110 9 #define MACH_TYPE_ARCHIMEDES 10 #define MACH_TYPE_A5K 11 +#define MACH_TYPE_SA1100 12 /* not allocated!!! */ /* * Sort out a definition for machine_arch_type diff -u --recursive --new-file v2.3.10/linux/include/asm-i386/desc.h linux/include/asm-i386/desc.h --- v2.3.10/linux/include/asm-i386/desc.h Wed Sep 9 08:56:58 1998 +++ linux/include/asm-i386/desc.h Sun Jul 11 09:11:46 1999 @@ -1,6 +1,46 @@ #ifndef __ARCH_DESC_H #define __ARCH_DESC_H +#include + +/* + * The layout of the GDT under Linux: + * + * 0 - null + * 1 - not used + * 2 - kernel code segment + * 3 - kernel data segment + * 4 - user code segment <-- new cacheline + * 5 - user data segment + * 6 - not used + * 7 - not used + * 8 - APM BIOS support <-- new cacheline + * 9 - APM BIOS support + * 10 - APM BIOS support + * 11 - APM BIOS support + * + * The TSS+LDT descriptors are spread out a bit so that every CPU + * has an exclusive cacheline for the per-CPU TSS and LDT: + * + * 12 - CPU#0 TSS <-- new cacheline + * 13 - CPU#0 LDT + * 14 - not used + * 15 - not used + * 16 - CPU#1 TSS <-- new cacheline + * 17 - CPU#1 LDT + * 18 - not used + * 19 - not used + * ... NR_CPUS per-CPU TSS+LDT's if on SMP + * + * Entry into gdt where to find first TSS. + */ +#define __FIRST_TSS_ENTRY 12 +#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY+1) + +#define __TSS(n) (((n)<<2) + __FIRST_TSS_ENTRY) +#define __LDT(n) (((n)<<2) + __FIRST_LDT_ENTRY) + +#ifndef __ASSEMBLY__ struct desc_struct { unsigned long a,b; }; @@ -16,46 +56,33 @@ #define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2)) #define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2)) +#define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3)) + +#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3)) + /* - * Entry into gdt where to find first TSS. GDT layout: - * 0 - null - * 1 - not used - * 2 - kernel code segment - * 3 - kernel data segment - * 4 - user code segment - * 5 - user data segment - * 6 - not used - * 7 - not used - * 8 - APM BIOS support - * 9 - APM BIOS support - * 10 - APM BIOS support - * 11 - APM BIOS support - * 12 - TSS #0 - * 13 - LDT #0 - * 14 - TSS #1 - * 15 - LDT #1 + * This is the ldt that every process will get unless we need + * something other than this. */ -#define FIRST_TSS_ENTRY 12 -#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1) -#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3)) -#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3)) -#define load_TR(n) __asm__ __volatile__("ltr %%ax": /* no output */ :"a" (_TSS(n))) -#define load_ldt(n) __asm__ __volatile__("lldt %%ax": /* no output */ :"a" (_LDT(n))) -#define store_TR(n) \ -__asm__("str %%ax\n\t" \ - "subl %2,%%eax\n\t" \ - "shrl $4,%%eax" \ - :"=a" (n) \ - :"0" (0),"i" (FIRST_TSS_ENTRY<<3)) - +extern struct desc_struct default_ldt; extern void set_intr_gate(unsigned int irq, void * addr); extern void set_ldt_desc(unsigned int n, void *addr, unsigned int size); extern void set_tss_desc(unsigned int n, void *addr); /* - * This is the ldt that every process will get unless we need - * something other than this. + * load one particular LDT into the current CPU */ -extern struct desc_struct default_ldt; +extern inline void load_LDT (struct mm_struct *mm) +{ + int cpu = smp_processor_id(); + + if (mm->segments) + set_ldt_desc(cpu, mm->segments, LDT_ENTRIES); + else + set_ldt_desc(cpu, &default_ldt, 1); + __load_LDT(cpu); +} + +#endif /* !__ASSEMBLY__ */ #endif diff -u --recursive --new-file v2.3.10/linux/include/asm-i386/hardirq.h linux/include/asm-i386/hardirq.h --- v2.3.10/linux/include/asm-i386/hardirq.h Tue Jun 22 14:41:40 1999 +++ linux/include/asm-i386/hardirq.h Wed Jul 21 14:52:45 1999 @@ -1,7 +1,7 @@ #ifndef __ASM_HARDIRQ_H #define __ASM_HARDIRQ_H -#include +#include extern unsigned int local_irq_count[NR_CPUS]; diff -u --recursive --new-file v2.3.10/linux/include/asm-i386/ldt.h linux/include/asm-i386/ldt.h --- v2.3.10/linux/include/asm-i386/ldt.h Wed Dec 11 06:41:23 1996 +++ linux/include/asm-i386/ldt.h Sun Jul 11 09:11:46 1999 @@ -11,6 +11,7 @@ /* The size of each LDT entry. */ #define LDT_ENTRY_SIZE 8 +#ifndef __ASSEMBLY__ struct modify_ldt_ldt_s { unsigned int entry_number; unsigned long base_addr; @@ -27,4 +28,5 @@ #define MODIFY_LDT_CONTENTS_STACK 1 #define MODIFY_LDT_CONTENTS_CODE 2 +#endif /* !__ASSEMBLY__ */ #endif diff -u --recursive --new-file v2.3.10/linux/include/asm-i386/mmu_context.h linux/include/asm-i386/mmu_context.h --- v2.3.10/linux/include/asm-i386/mmu_context.h Tue May 5 21:33:33 1998 +++ linux/include/asm-i386/mmu_context.h Mon Jul 19 16:18:57 1999 @@ -1,13 +1,27 @@ #ifndef __I386_MMU_CONTEXT_H #define __I386_MMU_CONTEXT_H +#include + /* - * get a new mmu context.. x86's don't know about contexts. + * get a new mmu context.. x86's don't know much about contexts, + * but we have to reload the new LDT in exec(). + * + * We implement lazy MMU context-switching on x86 to optimize context + * switches done to/from kernel threads. Kernel threads 'inherit' the + * previous MM, so Linux doesnt have to flush the TLB. In most cases + * we switch back to the same process so we preserve the TLB cache. + * This all means that kernel threads have about as much overhead as + * a function call ... */ -#define get_mmu_context(x) do { } while (0) +#define get_mmu_context(next) do { } while (0) +#define set_mmu_context(prev,next) do { next->thread.cr3 = prev->thread.cr3; } while(0) #define init_new_context(mm) do { } while(0) +/* + * possibly do the LDT unload here? + */ #define destroy_context(mm) do { } while(0) -#define activate_context(tsk) do { } while(0) +#define activate_context(x) load_LDT((x)->mm) #endif diff -u --recursive --new-file v2.3.10/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h --- v2.3.10/linux/include/asm-i386/pgtable.h Wed Jun 30 13:38:20 1999 +++ linux/include/asm-i386/pgtable.h Wed Jul 21 14:52:46 1999 @@ -15,7 +15,7 @@ #ifndef __ASSEMBLY__ #include #include -#include +#include /* Caches aren't brain-dead on the intel. */ #define flush_cache_all() do { } while (0) @@ -101,7 +101,7 @@ static inline void flush_tlb_current_task(void) { /* just one copy of this mm? */ - if (atomic_read(¤t->mm->count) == 1) + if (atomic_read(¤t->mm->mm_users) == 1) local_flush_tlb(); /* and that's us, so.. */ else smp_flush_tlb(); @@ -113,7 +113,7 @@ static inline void flush_tlb_mm(struct mm_struct * mm) { - if (mm == current->mm && atomic_read(&mm->count) == 1) + if (mm == current->mm && atomic_read(&mm->mm_users) == 1) local_flush_tlb(); else smp_flush_tlb(); @@ -122,7 +122,7 @@ static inline void flush_tlb_page(struct vm_area_struct * vma, unsigned long va) { - if (vma->vm_mm == current->mm && atomic_read(¤t->mm->count) == 1) + if (vma->vm_mm == current->mm && atomic_read(¤t->mm->mm_users) == 1) __flush_tlb_one(va); else smp_flush_tlb(); @@ -306,7 +306,7 @@ #define SET_PAGE_DIR(tsk,pgdir) \ do { \ unsigned long __pgdir = __pa(pgdir); \ - (tsk)->tss.cr3 = __pgdir; \ + (tsk)->thread.cr3 = __pgdir; \ if ((tsk) == current) \ __asm__ __volatile__("movl %0,%%cr3": :"r" (__pgdir)); \ } while (0) @@ -481,9 +481,9 @@ extern void __bad_pte(pmd_t *pmd); extern void __bad_pte_kernel(pmd_t *pmd); -#define pte_free_kernel(pte) free_pte_fast(pte) -#define pte_free(pte) free_pte_fast(pte) -#define pgd_free(pgd) free_pgd_fast(pgd) +#define pte_free_kernel(pte) free_pte_slow(pte) +#define pte_free(pte) free_pte_slow(pte) +#define pgd_free(pgd) free_pgd_slow(pgd) #define pgd_alloc() get_pgd_fast() extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) diff -u --recursive --new-file v2.3.10/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h --- v2.3.10/linux/include/asm-i386/processor.h Tue Jun 22 14:41:40 1999 +++ linux/include/asm-i386/processor.h Wed Jul 21 14:52:46 1999 @@ -12,6 +12,7 @@ #include #include #include +#include /* * Default implementation of macro that returns current @@ -95,6 +96,7 @@ #define X86_FEATURE_AMD3D 0x80000000 extern struct cpuinfo_x86 boot_cpu_data; +extern struct tss_struct init_tss[NR_CPUS]; #ifdef __SMP__ extern struct cpuinfo_x86 cpu_data[]; @@ -124,6 +126,48 @@ : "cc"); } + +/* + * Intel CPU features in CR4 + */ +#define X86_CR4_VME 0x0001 /* enable vm86 extensions */ +#define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */ +#define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */ +#define X86_CR4_DE 0x0008 /* enable debugging extensions */ +#define X86_CR4_PSE 0x0010 /* enable page size extensions */ +#define X86_CR4_PAE 0x0020 /* enable physical address extensions */ +#define X86_CR4_MCE 0x0040 /* Machine check enable */ +#define X86_CR4_PGE 0x0080 /* enable global pages */ +#define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ + +/* + * Save the cr4 feature set we're using (ie + * Pentium 4MB enable and PPro Global page + * enable), so that any CPU's that boot up + * after us can get the correct flags. + */ +extern unsigned long mmu_cr4_features; + +static inline void set_in_cr4 (unsigned long mask) +{ + mmu_cr4_features |= mask; + __asm__("movl %%cr4,%%eax\n\t" + "orl %0,%%eax\n\t" + "movl %%eax,%%cr4\n" + : : "irg" (mask) + :"ax"); +} + +static inline void clear_in_cr4 (unsigned long mask) +{ + mmu_cr4_features &= ~mask; + __asm__("movl %%cr4,%%eax\n\t" + "andl %0,%%eax\n\t" + "movl %%eax,%%cr4\n" + : : "irg" (~mask) + :"ax"); +} + /* * Cyrix CPU configuration register indexes */ @@ -177,6 +221,8 @@ * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. */ #define IO_BITMAP_SIZE 32 +#define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap) +#define INVALID_IO_BITMAP_OFFSET 0x8000 struct i387_hard_struct { long cwd; @@ -213,7 +259,7 @@ unsigned long seg; } mm_segment_t; -struct thread_struct { +struct tss_struct { unsigned short back_link,__blh; unsigned long esp0; unsigned short ss0,__ss0h; @@ -238,19 +284,44 @@ unsigned short ldt, __ldth; unsigned short trace, bitmap; unsigned long io_bitmap[IO_BITMAP_SIZE+1]; - unsigned long tr; + /* + * pads the TSS to be cacheline-aligned (size is 0x100) + */ + unsigned long __cacheline_filler[5]; +}; + +struct thread_struct { + unsigned long esp0; + unsigned long cr3; + unsigned long eip; + unsigned long esp; + unsigned long fs; + unsigned long gs; +/* Hardware debugging registers */ + unsigned long debugreg[8]; /* %%db0-7 debug registers */ +/* fault info */ unsigned long cr2, trap_no, error_code; - mm_segment_t segment; -/* debug registers */ - long debugreg[8]; /* Hardware debugging registers */ /* floating point info */ - union i387_union i387; + union i387_union i387; /* virtual 86 mode info */ - struct vm86_struct * vm86_info; - unsigned long screen_bitmap; - unsigned long v86flags, v86mask, v86mode, saved_esp0; + struct vm86_struct * vm86_info; + unsigned long screen_bitmap; + unsigned long v86flags, v86mask, v86mode, saved_esp0; +/* IO permissions */ + int ioperm; + unsigned long io_bitmap[IO_BITMAP_SIZE+1]; }; +#define INIT_THREAD { \ + 0,(long) &swapper_pg_dir - PAGE_OFFSET, \ + 0, 0, 0, 0, \ + { [0 ... 7] = 0 }, /* debugging registers */ \ + 0, 0, 0, \ + { { 0, }, }, /* 387 state */ \ + 0,0,0,0,0,0, \ + 0,{~0,} /* io permissions */ \ +} + #define INIT_MMAP \ { &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL } @@ -265,13 +336,9 @@ 0,0,0,0, /* esp,ebp,esi,edi */ \ 0,0,0,0,0,0, /* es,cs,ss */ \ 0,0,0,0,0,0, /* ds,fs,gs */ \ - _LDT(0),0, /* ldt */ \ - 0, 0x8000, /* tace, bitmap */ \ - {~0, }, /* ioperm */ \ - _TSS(0), 0, 0, 0, (mm_segment_t) { 0 }, /* obsolete */ \ - { 0, }, \ - { { 0, }, }, /* 387 state */ \ - NULL, 0, 0, 0, 0, 0, /* vm86_info */ \ + __LDT(0),0, /* ldt */ \ + 0, INVALID_IO_BITMAP_OFFSET, /* tace, bitmap */ \ + {~0, } /* ioperm */ \ } #define start_thread(regs, new_eip, new_esp) do { \ @@ -291,10 +358,13 @@ /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); +/* + * create a kernel thread without removing it from tasklists + */ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); /* Copy and release all segment info associated with a VM */ -extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm); +extern void copy_segments(struct task_struct *p, struct mm_struct * mm); extern void release_segments(struct mm_struct * mm); extern void forget_segments(void); @@ -302,7 +372,7 @@ * FPU lazy state save handling.. */ #define save_fpu(tsk) do { \ - asm volatile("fnsave %0\n\tfwait":"=m" (tsk->tss.i387)); \ + asm volatile("fnsave %0\n\tfwait":"=m" (tsk->thread.i387)); \ tsk->flags &= ~PF_USEDFPU; \ stts(); \ } while (0) @@ -327,6 +397,7 @@ return ((unsigned long *)t->esp)[3]; } +#define THREAD_SIZE (2*PAGE_SIZE) extern struct task_struct * alloc_task_struct(void); extern void free_task_struct(struct task_struct *); diff -u --recursive --new-file v2.3.10/linux/include/asm-i386/resource.h linux/include/asm-i386/resource.h --- v2.3.10/linux/include/asm-i386/resource.h Wed Nov 18 21:06:56 1998 +++ linux/include/asm-i386/resource.h Sun Jul 11 09:11:46 1999 @@ -28,7 +28,7 @@ { _STK_LIM, LONG_MAX }, \ { 0, LONG_MAX }, \ { LONG_MAX, LONG_MAX }, \ - { MAX_TASKS_PER_USER, MAX_TASKS_PER_USER }, \ + { 0, 0 }, \ { NR_OPEN, NR_OPEN }, \ { LONG_MAX, LONG_MAX }, \ { LONG_MAX, LONG_MAX }, \ diff -u --recursive --new-file v2.3.10/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h --- v2.3.10/linux/include/asm-i386/smp.h Tue Jun 22 14:41:41 1999 +++ linux/include/asm-i386/smp.h Wed Jul 21 14:52:46 1999 @@ -16,7 +16,7 @@ #ifdef __SMP__ #ifndef ASSEMBLY -#include +#include #include /* diff -u --recursive --new-file v2.3.10/linux/include/asm-i386/system.h linux/include/asm-i386/system.h --- v2.3.10/linux/include/asm-i386/system.h Tue Jun 22 14:41:38 1999 +++ linux/include/asm-i386/system.h Wed Jul 21 14:52:45 1999 @@ -22,9 +22,9 @@ "popl %%ebp\n\t" \ "popl %%edi\n\t" \ "popl %%esi\n\t" \ - :"=m" (prev->tss.esp),"=m" (prev->tss.eip), \ + :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \ "=b" (last) \ - :"m" (next->tss.esp),"m" (next->tss.eip), \ + :"m" (next->thread.esp),"m" (next->thread.eip), \ "a" (prev), "d" (next), \ "b" (prev)); \ } while (0) diff -u --recursive --new-file v2.3.10/linux/include/asm-ppc/machdep.h linux/include/asm-ppc/machdep.h --- v2.3.10/linux/include/asm-ppc/machdep.h Wed Jun 30 13:38:20 1999 +++ linux/include/asm-ppc/machdep.h Mon Jul 12 15:12:55 1999 @@ -39,6 +39,8 @@ unsigned long heartbeat_reset; unsigned long heartbeat_count; + void (*progress)(char *, unsigned short); + unsigned char (*nvram_read_val)(int addr); void (*nvram_write_val)(int addr, unsigned char val); diff -u --recursive --new-file v2.3.10/linux/include/asm-ppc/system.h linux/include/asm-ppc/system.h --- v2.3.10/linux/include/asm-ppc/system.h Mon Jun 7 12:11:51 1999 +++ linux/include/asm-ppc/system.h Mon Jul 19 13:12:47 1999 @@ -75,8 +75,6 @@ extern void cvt_fd(float *from, double *to, unsigned long *fpscr); extern void cvt_df(double *from, float *to, unsigned long *fpscr); extern int call_rtas(const char *, int, int, unsigned long *, ...); -extern void chrp_progress(char *); -void chrp_event_scan(void); struct device_node; extern void note_scsi_host(struct device_node *, void *); diff -u --recursive --new-file v2.3.10/linux/include/linux/bios32.h linux/include/linux/bios32.h --- v2.3.10/linux/include/linux/bios32.h Tue Jun 22 14:43:01 1999 +++ linux/include/linux/bios32.h Wed Dec 31 16:00:00 1969 @@ -1,34 +0,0 @@ -/* - * This is only a stub file to make drivers not yet converted to the new - * PCI probing mechanism work. [mj] - */ - -#ifndef BIOS32_H -#define BIOS32_H - -#include - -#warning This driver uses the old PCI interface, please fix it (see Documentation/pci.txt) - -extern inline int __pcibios_read_irq(unsigned char bus, unsigned char dev_fn, unsigned char *to) -{ - struct pci_dev *pdev = pci_find_slot(bus, dev_fn); - if (!pdev) { - *to = 0; - return PCIBIOS_DEVICE_NOT_FOUND; - } else { - *to = pdev->irq; - return PCIBIOS_SUCCESSFUL; - } -} - -extern inline int __pcibios_read_config_byte(unsigned char bus, - unsigned char dev_fn, unsigned char where, unsigned char *to) -{ - return pcibios_read_config_byte(bus, dev_fn, where, to); -} - -#define pcibios_read_config_byte(b,d,w,p) \ - (((w) == PCI_INTERRUPT_LINE) ? __pcibios_read_irq(b,d,p) : __pcibios_read_config_byte(b,d,w,p)) - -#endif diff -u --recursive --new-file v2.3.10/linux/include/linux/cyclades.h linux/include/linux/cyclades.h --- v2.3.10/linux/include/linux/cyclades.h Thu Jul 8 15:42:21 1999 +++ linux/include/linux/cyclades.h Fri Jul 16 14:57:41 1999 @@ -490,7 +490,26 @@ /****************** ****************** *******************/ #endif +/* Per card data structure */ +struct cyclades_card { + long base_addr; + long ctl_addr; + int irq; + int num_chips; /* 0 if card absent, -1 if Z/PCI, else Y */ + int first_line; /* minor number of first channel on card */ + int bus_index; /* address shift - 0 for ISA, 1 for PCI */ + int intr_enabled; /* FW Interrupt flag - 0 disabled, 1 enabled */ +#ifdef __KERNEL__ + spinlock_t card_lock; +#else + uclong filler; +#endif +}; + +struct cyclades_chip { + int filler; +}; #ifdef __KERNEL__ @@ -508,22 +527,6 @@ #define cy_readw(port) readw(port) #define cy_readl(port) readl(port) -/* Per card data structure */ - -struct cyclades_card { - long base_addr; - long ctl_addr; - int irq; - int num_chips; /* 0 if card absent, -1 if Z/PCI, else Y */ - int first_line; /* minor number of first channel on card */ - int bus_index; /* address shift - 0 for ISA, 1 for PCI */ - int intr_enabled; /* FW Interrupt flag - 0 disabled, 1 enabled */ -}; - -struct cyclades_chip { - int filler; -}; - /* * This is our internal structure for each serial port's state. * @@ -568,16 +571,16 @@ int xmit_cnt; int default_threshold; int default_timeout; - struct tq_struct tqueue; + unsigned long jiffies[3]; + unsigned long rflush_count; struct termios normal_termios; struct termios callout_termios; - wait_queue_head_t open_wait; - wait_queue_head_t close_wait; - wait_queue_head_t shutdown_wait; struct cyclades_monitor mon; - unsigned long jiffies[3]; - unsigned long rflush_count; struct cyclades_idle_stats idle_stats; + struct tq_struct tqueue; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; + wait_queue_head_t shutdown_wait; }; /* diff -u --recursive --new-file v2.3.10/linux/include/linux/file.h linux/include/linux/file.h --- v2.3.10/linux/include/linux/file.h Thu Jul 8 15:42:21 1999 +++ linux/include/linux/file.h Wed Jul 14 13:25:51 1999 @@ -5,7 +5,6 @@ #ifndef __LINUX_FILE_H #define __LINUX_FILE_H -extern void __fput(struct file *); /* goner? */ extern void _fput(struct file *); /* diff -u --recursive --new-file v2.3.10/linux/include/linux/ioport.h linux/include/linux/ioport.h --- v2.3.10/linux/include/linux/ioport.h Fri Jun 18 12:43:41 1999 +++ linux/include/linux/ioport.h Sat Jul 17 02:04:28 1999 @@ -2,56 +2,45 @@ * ioport.h Definitions of routines for detecting, reserving and * allocating system resources. * - * Authors: Donald Becker (becker@cesdis.gsfc.nasa.gov) - * David Hinds (dhinds@zen.stanford.edu) + * Authors: Linus Torvalds */ #ifndef _LINUX_IOPORT_H #define _LINUX_IOPORT_H -#define RES_IO 0 -#define RES_MEM 1 +/* + * Resources are tree-like, allowing + * nesting etc.. + */ +struct resource { + const char *name; + unsigned long start, end; + unsigned long flags; + struct resource *parent, *sibling, *child; +}; + +/* PC/ISA/whatever - the normal PC address spaces: IO and memory */ +extern struct resource ioport_resource; +extern struct resource iomem_resource; extern void reserve_setup(char *str, int *ints); +extern int get_resource_list(struct resource *, char *buf, int size); -extern struct resource_entry *iolist, *memlist; - -extern int get_resource_list(int class, char *buf); -extern int check_resource(int class, - unsigned long from, unsigned long extent); -extern void request_resource(int class, - unsigned long from, unsigned long extent, - const char *name); -extern void release_resource(int class, - unsigned long from, unsigned long extent); -extern unsigned long occupy_resource(int class, - unsigned long base, unsigned long end, - unsigned long num, unsigned long align, - const char *name); -extern void vacate_resource(int class, - unsigned long from, unsigned long extent); +extern int request_resource(struct resource *root, struct resource *new); +extern int release_resource(struct resource *new); -#define get_ioport_list(buf) get_resource_list(RES_IO, buf) -#define get_mem_list(buf) get_resource_list(RES_MEM, buf) +/* Convenience shorthand with allocation */ +#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name)) +extern struct resource * __request_region(struct resource *, unsigned long start, unsigned long n, const char *name); + +/* Compatibility cruft */ +#define check_region(start,n) __check_region(&ioport_resource, (start), (n)) +#define release_region(start,n) __release_region(&ioport_resource, (start), (n)) +extern int __check_region(struct resource *, unsigned long, unsigned long); +extern void __release_region(struct resource *, unsigned long, unsigned long); -#define HAVE_PORTRESERVE -/* - * Call check_region() before probing for your hardware. - * Once you have found you hardware, register it with request_region(). - * If you unload the driver, use release_region to free ports. - */ -#define check_region(f,e) check_resource(RES_IO,f,e) -#define request_region(f,e,n) request_resource(RES_IO,f,e,n) -#define release_region(f,e) release_resource(RES_IO,f,e) -#define occupy_region(b,e,n,a,s) occupy_resource(RES_IO,b,e,n,a,s) -#define vacate_region(f,e) vacate_resource(RES_IO,f,e) - -#define HAVE_MEMRESERVE -#define check_mem_region(f,e) check_resource(RES_MEM,f,e) -#define request_mem_region(f,e,n) request_resource(RES_MEM,f,e,n) -#define release_mem_region(f,e) release_resource(RES_MEM,f,e) -#define occupy_mem_region(b,e,n,a,s) occupy_resource(RES_MEM,b,e,n,a,s) -#define vacate_mem_region(f,e) vacate_resource(RES_MEM,f,e) +#define get_ioport_list(buf) get_resource_list(&ioport_resource, buf, PAGE_SIZE) +#define get_mem_list(buf) get_resource_list(&iomem_resource, buf, PAGE_SIZE) #define HAVE_AUTOIRQ extern void autoirq_setup(int waittime); diff -u --recursive --new-file v2.3.10/linux/include/linux/kernel_stat.h linux/include/linux/kernel_stat.h --- v2.3.10/linux/include/linux/kernel_stat.h Tue Jun 22 14:41:43 1999 +++ linux/include/linux/kernel_stat.h Wed Jul 21 14:52:47 1999 @@ -3,7 +3,7 @@ #include #include -#include +#include /* * 'kernel_stat.h' contains the definitions needed for doing diff -u --recursive --new-file v2.3.10/linux/include/linux/list.h linux/include/linux/list.h --- v2.3.10/linux/include/linux/list.h Mon Dec 1 11:16:57 1997 +++ linux/include/linux/list.h Sun Jul 11 22:50:27 1999 @@ -17,8 +17,10 @@ struct list_head *next, *prev; }; +#define LIST_HEAD_INIT(name) { &(name), &(name) } + #define LIST_HEAD(name) \ - struct list_head name = { &name, &name } + struct list_head name = LIST_HEAD_INIT(name) #define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ @@ -46,6 +48,14 @@ static __inline__ void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); +} + +/* + * Insert a new entry before the specified head.. + */ +static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); } /* diff -u --recursive --new-file v2.3.10/linux/include/linux/mm.h linux/include/linux/mm.h --- v2.3.10/linux/include/linux/mm.h Thu Jul 8 15:42:21 1999 +++ linux/include/linux/mm.h Wed Jul 21 14:52:49 1999 @@ -128,7 +128,7 @@ wait_queue_head_t wait; struct page **pprev_hash; struct buffer_head * buffers; - int owner; /* temporary debugging check */ + void *owner; /* temporary debugging check */ } mem_map_t; #define get_page(p) do { atomic_inc(&(p)->count); \ @@ -167,11 +167,11 @@ do { int _ret = test_and_set_bit(PG_locked, &(page)->flags); \ if (_ret) PAGE_BUG(page); \ if (page->owner) PAGE_BUG(page); \ - page->owner = (int)current; } while (0) + page->owner = current; } while (0) #define TryLockPage(page) ({ int _ret = test_and_set_bit(PG_locked, &(page)->flags); \ - if (!_ret) page->owner = (int)current; _ret; }) + if (!_ret) page->owner = current; _ret; }) #define UnlockPage(page) do { \ - if (page->owner != (int)current) { \ + if (page->owner != current) { \ BUG(); } page->owner = 0; \ if (!test_and_clear_bit(PG_locked, &(page)->flags)) { \ PAGE_BUG(page); } wake_up(&page->wait); } while (0) @@ -306,7 +306,6 @@ extern void free_page_tables(struct mm_struct * mm); extern void clear_page_tables(struct mm_struct *, unsigned long, int); -extern int new_page_tables(struct task_struct * tsk); extern void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size); extern int copy_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma); @@ -328,6 +327,7 @@ extern void show_mem(void); extern void oom(struct task_struct * tsk); extern void si_meminfo(struct sysinfo * val); +extern void swapin_readahead(unsigned long); /* mmap.c */ extern void vma_init(void); diff -u --recursive --new-file v2.3.10/linux/include/linux/parport.h linux/include/linux/parport.h --- v2.3.10/linux/include/linux/parport.h Thu Jul 8 15:42:21 1999 +++ linux/include/linux/parport.h Wed Jul 21 15:38:39 1999 @@ -70,6 +70,11 @@ #define IEEE1284_MODE_EPPSWE (1<<12) /* Software-emulated */ #define IEEE1284_DEVICEID (1<<2) /* This is a flag */ +/* For the benefit of parport_read/write, you can use these with + * parport_negotiate to use address operations. They have no effect + * other than to make parport_read/write use address transfers. */ +#define IEEE1284_ADDR (1<<13) /* This is a flag */ + /* The rest is for the kernel only */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.3.10/linux/include/linux/sched.h linux/include/linux/sched.h --- v2.3.10/linux/include/linux/sched.h Thu Jul 8 15:42:21 1999 +++ linux/include/linux/sched.h Wed Jul 21 14:52:48 1999 @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include @@ -63,7 +63,7 @@ #define CT_TO_SECS(x) ((x) / HZ) #define CT_TO_USECS(x) (((x) % HZ) * 1000000/HZ) -extern int nr_running, nr_tasks; +extern int nr_running, nr_threads; extern int last_pid; #include @@ -119,6 +119,7 @@ extern void sched_init(void); extern void init_idle(void); extern void show_state(void); +extern void cpu_init (void); extern void trap_init(void); #define MAX_SCHEDULE_TIMEOUT LONG_MAX @@ -169,7 +170,8 @@ struct vm_area_struct * mmap_avl; /* tree of VMAs */ struct vm_area_struct * mmap_cache; /* last find_vma result */ pgd_t * pgd; - atomic_t count; + atomic_t mm_users; /* How many users with user space? */ + atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */ int map_count; /* number of VMAs */ struct semaphore mmap_sem; spinlock_t page_table_lock; @@ -192,7 +194,7 @@ #define INIT_MM(name) { \ &init_mmap, NULL, NULL, \ swapper_pg_dir, \ - ATOMIC_INIT(1), 1, \ + ATOMIC_INIT(2), ATOMIC_INIT(1), 1, \ __MUTEX_INITIALIZER(name.mmap_sem), \ SPIN_LOCK_UNLOCKED, \ 0, \ @@ -243,7 +245,7 @@ int last_processor; int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */ struct task_struct *next_task, *prev_task; - struct task_struct *next_run, *prev_run; + struct list_head run_list; /* task state */ struct linux_binfmt *binfmt; @@ -270,9 +272,6 @@ struct task_struct *pidhash_next; struct task_struct **pidhash_pprev; - /* Pointer to task[] array linkage. */ - struct task_struct **tarray_ptr; - wait_queue_head_t wait_chldexit; /* for wait4() */ struct semaphore *vfork_sem; /* for vfork() */ unsigned long policy, rt_priority; @@ -302,14 +301,15 @@ /* ipc stuff */ struct sem_undo *semundo; struct sem_queue *semsleeping; -/* tss for this task */ - struct thread_struct tss; +/* CPU-specific state of this task */ + struct thread_struct thread; /* filesystem information */ struct fs_struct *fs; /* open file information */ struct files_struct *files; + /* memory management info */ - struct mm_struct *mm; + struct mm_struct *mm, *active_mm; /* signal handlers */ spinlock_t sigmask_lock; /* Protects signal and blocked */ @@ -355,13 +355,12 @@ /* state etc */ { 0,0,0,KERNEL_DS,&default_exec_domain,0, \ /* counter */ DEF_PRIORITY,DEF_PRIORITY,0, \ /* SMP */ 0,0,0,-1, \ -/* schedlink */ &init_task,&init_task, &init_task, &init_task, \ +/* schedlink */ &init_task,&init_task, LIST_HEAD_INIT(init_task.run_list), \ /* binfmt */ NULL, \ /* ec,brk... */ 0,0,0,0,0,0, \ /* pid etc.. */ 0,0,0,0,0, \ /* proc links*/ &init_task,&init_task,NULL,NULL,NULL, \ /* pidhash */ NULL, NULL, \ -/* tarray */ &task[0], \ /* chld wait */ __WAIT_QUEUE_HEAD_INITIALIZER(name.wait_chldexit), NULL, \ /* timeout */ SCHED_OTHER,0,0,0,0,0,0,0, \ /* timer */ { NULL, NULL, 0, 0, it_real_fn }, \ @@ -379,10 +378,10 @@ /* comm */ "swapper", \ /* fs info */ 0,NULL, \ /* ipc */ NULL, NULL, \ -/* tss */ INIT_TSS, \ +/* thread */ INIT_THREAD, \ /* fs */ &init_fs, \ /* files */ &init_files, \ -/* mm */ &init_mm, \ +/* mm */ NULL, &init_mm, \ /* signals */ SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \ } @@ -398,33 +397,10 @@ extern union task_union init_task_union; extern struct mm_struct init_mm; -extern struct task_struct *task[NR_TASKS]; - -extern struct task_struct **tarray_freelist; -extern spinlock_t taskslot_lock; - -extern __inline__ void add_free_taskslot(struct task_struct **t) -{ - spin_lock(&taskslot_lock); - *t = (struct task_struct *) tarray_freelist; - tarray_freelist = t; - spin_unlock(&taskslot_lock); -} - -extern __inline__ struct task_struct **get_free_taskslot(void) -{ - struct task_struct **tslot; - - spin_lock(&taskslot_lock); - if((tslot = tarray_freelist) != NULL) - tarray_freelist = (struct task_struct **) *tslot; - spin_unlock(&taskslot_lock); - - return tslot; -} +extern struct task_struct *init_tasks[NR_CPUS]; -/* PID hashing. */ -#define PIDHASH_SZ (NR_TASKS >> 2) +/* PID hashing. (shouldnt this be dynamic?) */ +#define PIDHASH_SZ (4096 >> 2) extern struct task_struct *pidhash[PIDHASH_SZ]; #define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1)) @@ -616,10 +592,16 @@ * Routines for handling mm_structs */ extern struct mm_struct * mm_alloc(void); -static inline void mmget(struct mm_struct * mm) + +/* mmdrop drops the mm and the page tables */ +extern inline void FASTCALL(__mmdrop(struct mm_struct *)); +static inline void mmdrop(struct mm_struct * mm) { - atomic_inc(&mm->count); + if (atomic_dec_and_test(&mm->mm_count)) + __mmdrop(mm); } + +/* mmput gets rid of the mappings and all user-space */ extern void mmput(struct mm_struct *); /* Remove the current tasks stale references to the old mm_struct */ extern void mm_release(void); @@ -740,6 +722,29 @@ #define for_each_task(p) \ for (p = &init_task ; (p = p->next_task) != &init_task ; ) + + +static inline void del_from_runqueue(struct task_struct * p) +{ + nr_running--; + list_del(&p->run_list); + p->run_list.next = NULL; +} + +extern inline int task_on_runqueue(struct task_struct *p) +{ + return (p->run_list.next != NULL); +} + +extern inline void unhash_process(struct task_struct *p) +{ + if (task_on_runqueue(p)) BUG(); + nr_threads--; + write_lock_irq(&tasklist_lock); + unhash_pid(p); + REMOVE_LINKS(p); + write_unlock_irq(&tasklist_lock); +} #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.3.10/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.3.10/linux/include/linux/sysctl.h Wed Jun 30 13:38:20 1999 +++ linux/include/linux/sysctl.h Sun Jul 11 09:11:46 1999 @@ -100,7 +100,8 @@ KERN_SHMMAX=34, /* int: Maximum shared memory segment */ KERN_MSGMAX=35, /* int: Maximum size of a messege */ KERN_MSGMNB=36, /* int: Maximum message queue size */ - KERN_MSGPOOL=37 /* int: Maximum system message pool size */ + KERN_MSGPOOL=37, /* int: Maximum system message pool size */ + KERN_MAX_THREADS=38 /* int: Maximum nr of threads in the system */ }; diff -u --recursive --new-file v2.3.10/linux/include/linux/tasks.h linux/include/linux/tasks.h --- v2.3.10/linux/include/linux/tasks.h Tue Jun 22 14:41:38 1999 +++ linux/include/linux/tasks.h Wed Dec 31 16:00:00 1969 @@ -1,25 +0,0 @@ -#ifndef _LINUX_TASKS_H -#define _LINUX_TASKS_H - -/* - * This is the maximum nr of tasks - change it if you need to - */ - -#ifdef __SMP__ -#define NR_CPUS 32 /* Max processors that can be running in SMP */ -#else -#define NR_CPUS 1 -#endif - -#define NR_TASKS 512 /* On x86 Max 4092, or 4090 w/APM configured. */ - -#define MAX_TASKS_PER_USER (NR_TASKS/2) -#define MIN_TASKS_LEFT_FOR_ROOT 4 - - -/* - * This controls the maximum pid allocated to a process - */ -#define PID_MAX 0x8000 - -#endif diff -u --recursive --new-file v2.3.10/linux/include/linux/threads.h linux/include/linux/threads.h --- v2.3.10/linux/include/linux/threads.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/threads.h Wed Jul 21 14:52:45 1999 @@ -0,0 +1,22 @@ +#ifndef _LINUX_THREADS_H +#define _LINUX_THREADS_H + +/* + * The default limit for the nr of threads is now in + * /proc/sys/kernel/max-threads. + */ + +#ifdef __SMP__ +#define NR_CPUS 32 /* Max processors that can be running in SMP */ +#else +#define NR_CPUS 1 +#endif + +#define MIN_THREADS_LEFT_FOR_ROOT 4 + +/* + * This controls the maximum pid allocated to a process + */ +#define PID_MAX 0x8000 + +#endif diff -u --recursive --new-file v2.3.10/linux/init/main.c linux/init/main.c --- v2.3.10/linux/init/main.c Thu Jul 8 15:42:21 1999 +++ linux/init/main.c Mon Jul 12 15:04:50 1999 @@ -75,7 +75,7 @@ extern void init_modules(void); extern long console_init(long, long); extern void sock_init(void); -extern void uidcache_init(void); +extern void fork_init(unsigned long); extern void mca_init(void); extern void sbus_init(void); extern void ppc_init(void); @@ -1187,7 +1187,7 @@ #ifdef CONFIG_PROC_FS proc_root_init(); #endif - uidcache_init(); + fork_init(memory_end-memory_start); filescache_init(); dcache_init(); vma_init(); diff -u --recursive --new-file v2.3.10/linux/ipc/shm.c linux/ipc/shm.c --- v2.3.10/linux/ipc/shm.c Thu Jul 8 15:42:21 1999 +++ linux/ipc/shm.c Tue Jul 13 09:25:59 1999 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -626,6 +627,8 @@ pte_t pte; struct shmid_kernel *shp; unsigned int id, idx; + unsigned long page; + struct page * page_map; id = SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK; idx = (address - shmd->vm_start + shmd->vm_offset) >> PAGE_SHIFT; @@ -649,26 +652,32 @@ } #endif + lock_kernel(); + again: pte = __pte(shp->shm_pages[idx]); if (!pte_present(pte)) { - unsigned long page = get_free_page(GFP_USER); - if (!page) { - oom(current); - return 0; - } - pte = __pte(shp->shm_pages[idx]); - if (pte_present(pte)) { - free_page (page); /* doesn't sleep */ - goto done; - } - if (!pte_none(pte)) { - rw_swap_page_nocache(READ, pte_val(pte), (char *)page); - pte = __pte(shp->shm_pages[idx]); - if (pte_present(pte)) { - free_page (page); /* doesn't sleep */ - goto done; + if (pte_none(pte)) { + page = get_free_page(GFP_USER); + if (!page) + goto oom; + if (pte_val(pte) != shp->shm_pages[idx]) + goto changed; + } else { + unsigned long entry = pte_val(pte); + + page_map = lookup_swap_cache(entry); + if (!page_map) { + swapin_readahead(entry); + page_map = read_swap_cache(entry); } - swap_free(pte_val(pte)); + pte = __pte(shp->shm_pages[idx]); + page = page_address(page_map); + if (pte_present(pte)) + goto present; + if (!page_map) + goto oom; + delete_from_swap_cache(page_map); + swap_free(entry); shm_swp--; } shm_rss++; @@ -678,9 +687,21 @@ --current->maj_flt; /* was incremented in do_no_page */ done: /* pte_val(pte) == shp->shm_pages[idx] */ + unlock_kernel(); current->min_flt++; get_page(mem_map + MAP_NR(pte_page(pte))); return pte_page(pte); + +changed: + free_page(page); + goto again; +present: + if (page_map) + free_page_and_swap_cache(page); + goto done; +oom: + unlock_kernel(); + return -1; } /* @@ -697,6 +718,7 @@ unsigned long id, idx; int loop = 0; int counter; + struct page * page_map; counter = shm_rss >> prio; if (!counter || !(swap_nr = get_swap_page())) @@ -725,7 +747,8 @@ page = __pte(shp->shm_pages[idx]); if (!pte_present(page)) goto check_table; - if ((gfp_mask & __GFP_DMA) && !PageDMA(&mem_map[MAP_NR(pte_page(page))])) + page_map = &mem_map[MAP_NR(pte_page(page))]; + if ((gfp_mask & __GFP_DMA) && !PageDMA(page_map)) goto check_table; swap_attempts++; @@ -737,8 +760,11 @@ if (page_count(mem_map + MAP_NR(pte_page(page))) != 1) goto check_table; shp->shm_pages[idx] = swap_nr; - rw_swap_page_nocache (WRITE, swap_nr, (char *) pte_page(page)); - free_page(pte_page(page)); + swap_duplicate(swap_nr); + add_to_swap_cache(page_map, swap_nr); + rw_swap_page(WRITE, page_map, 0); + + __free_page(page_map); swap_successes++; shm_swp++; shm_rss--; diff -u --recursive --new-file v2.3.10/linux/kernel/exit.c linux/kernel/exit.c --- v2.3.10/linux/kernel/exit.c Thu Jul 8 15:42:21 1999 +++ linux/kernel/exit.c Wed Jul 21 13:14:41 1999 @@ -27,29 +27,15 @@ if (p != current) { #ifdef __SMP__ /* - * Wait to make sure the process isn't active on any - * other CPU + * Wait to make sure the process isn't on the + * runqueue (active on some other CPU still) */ - for (;;) { - int has_cpu; - spin_lock_irq(&runqueue_lock); - has_cpu = p->has_cpu; - spin_unlock_irq(&runqueue_lock); - if (!has_cpu) - break; - do { - barrier(); - } while (p->has_cpu); - } + do { + barrier(); + } while (p->has_cpu); #endif free_uid(p); - nr_tasks--; - add_free_taskslot(p->tarray_ptr); - - write_lock_irq(&tasklist_lock); - unhash_pid(p); - REMOVE_LINKS(p); - write_unlock_irq(&tasklist_lock); + unhash_process(p); release_thread(p); current->cmin_flt += p->min_flt + p->cmin_flt; @@ -243,19 +229,18 @@ __exit_sighand(tsk); } +/* + * Turn us into a lazy TLB process if we + * aren't already.. + */ static inline void __exit_mm(struct task_struct * tsk) { struct mm_struct * mm = tsk->mm; - /* Set us up to use the kernel mm state */ - if (mm != &init_mm) { - flush_cache_mm(mm); - flush_tlb_mm(mm); - destroy_context(mm); - tsk->mm = &init_mm; - tsk->swappable = 0; - SET_PAGE_DIR(tsk, swapper_pg_dir); + if (mm) { mm_release(); + atomic_inc(&mm->mm_count); + tsk->mm = NULL; mmput(mm); } } diff -u --recursive --new-file v2.3.10/linux/kernel/fork.c linux/kernel/fork.c --- v2.3.10/linux/kernel/fork.c Thu Jul 8 15:42:21 1999 +++ linux/kernel/fork.c Wed Jul 21 11:22:04 1999 @@ -22,11 +22,12 @@ #include #include -/* The idle tasks do not count.. */ -int nr_tasks=0; +/* The idle threads do not count.. */ +int nr_threads=0; int nr_running=0; -unsigned long int total_forks=0; /* Handle normal Linux uptimes. */ +int max_threads; +unsigned long total_forks = 0; /* Handle normal Linux uptimes. */ int last_pid=0; /* SLAB cache for mm_struct's. */ @@ -37,9 +38,6 @@ struct task_struct *pidhash[PIDHASH_SZ]; -struct task_struct **tarray_freelist = NULL; -spinlock_t taskslot_lock = SPIN_LOCK_UNLOCKED; - /* UID task count cache, to prevent walking entire process list every * single fork() operation. */ @@ -159,7 +157,7 @@ return 0; } -void __init uidcache_init(void) +void __init fork_init(unsigned long memsize) { int i; @@ -171,15 +169,16 @@ for(i = 0; i < UIDHASH_SZ; i++) uidhash[i] = 0; -} -static inline struct task_struct ** find_empty_process(void) -{ - struct task_struct **tslot = NULL; + /* + * The default maximum number of threads is set to a safe + * value: the thread structures can take up at most half + * of memory. + */ + max_threads = memsize / THREAD_SIZE / 2; - if ((nr_tasks < NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT) || !current->uid) - tslot = get_free_taskslot(); - return tslot; + init_task.rlim[RLIMIT_NPROC].rlim_cur = max_threads/2; + init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2; } /* Protects next_safe and last_pid. */ @@ -233,6 +232,9 @@ struct vm_area_struct * mpnt, *tmp, **pprev; int retval; + /* Kill me slowly. UGLY! FIXME! */ + memcpy(&mm->start_code, ¤t->mm->start_code, 15*sizeof(unsigned long)); + flush_cache_mm(current->mm); pprev = &mm->mmap; for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) { @@ -290,9 +292,6 @@ /* * Allocate and initialize an mm_struct. - * - * NOTE! The mm mutex will be locked until the - * caller decides that all systems are go.. */ struct mm_struct * mm_alloc(void) { @@ -300,23 +299,12 @@ mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL); if (mm) { - *mm = *current->mm; + memset(mm, 0, sizeof(*mm)); init_new_context(mm); - atomic_set(&mm->count, 1); - mm->map_count = 0; - mm->def_flags = 0; - init_MUTEX_LOCKED(&mm->mmap_sem); + atomic_set(&mm->mm_users, 1); + atomic_set(&mm->mm_count, 1); + init_MUTEX(&mm->mmap_sem); mm->page_table_lock = SPIN_LOCK_UNLOCKED; - /* - * Leave mm->pgd set to the parent's pgd - * so that pgd_offset() is always valid. - */ - mm->mmap = mm->mmap_avl = mm->mmap_cache = NULL; - - /* It has not run yet, so cannot be present in anyone's - * cache or tlb. - */ - mm->cpu_vm_mask = 0; } return mm; } @@ -346,19 +334,30 @@ } /* + * Called when the last reference to the mm + * is dropped: either by a lazy thread or by + * mmput + */ +inline void __mmdrop(struct mm_struct *mm) +{ + if (mm == &init_mm) BUG(); + free_page_tables(mm); + kmem_cache_free(mm_cachep, mm); +} + +/* * Decrement the use count and release all resources for an mm. */ void mmput(struct mm_struct *mm) { - if (atomic_dec_and_test(&mm->count)) { + if (atomic_dec_and_test(&mm->mm_users)) { release_segments(mm); exit_mmap(mm); - free_page_tables(mm); - kmem_cache_free(mm_cachep, mm); + mmdrop(mm); } } -static inline int copy_mm(int nr, unsigned long clone_flags, struct task_struct * tsk) +static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk) { struct mm_struct * mm; int retval; @@ -367,14 +366,21 @@ tsk->cmin_flt = tsk->cmaj_flt = 0; tsk->nswap = tsk->cnswap = 0; - if (clone_flags & CLONE_VM) { - mmget(current->mm); - /* - * Set up the LDT descriptor for the clone task. - */ - copy_segments(nr, tsk, NULL); - SET_PAGE_DIR(tsk, current->mm->pgd); + tsk->mm = NULL; + tsk->active_mm = NULL; + + /* + * Are we cloning a kernel thread? + * + * We need to steal a active VM for that.. + */ + mm = current->mm; + if (!mm) return 0; + + if (clone_flags & CLONE_VM) { + atomic_inc(&mm->mm_users); + goto good_mm; } retval = -ENOMEM; @@ -383,23 +389,33 @@ goto fail_nomem; tsk->mm = mm; - copy_segments(nr, tsk, mm); - retval = new_page_tables(tsk); - if (retval) + tsk->active_mm = mm; + + mm->pgd = pgd_alloc(); + if (!mm->pgd) goto free_mm; + + /* + * child gets a private LDT (if there was an LDT in the parent) + */ + copy_segments(tsk, mm); + + down(¤t->mm->mmap_sem); retval = dup_mmap(mm); + up(¤t->mm->mmap_sem); if (retval) goto free_pt; - up(&mm->mmap_sem); + +good_mm: + tsk->mm = mm; + tsk->active_mm = mm; + SET_PAGE_DIR(tsk, mm->pgd); return 0; free_mm: - tsk->mm = NULL; - release_segments(mm); kmem_cache_free(mm_cachep, mm); return retval; free_pt: - tsk->mm = NULL; mmput(mm); fail_nomem: return retval; @@ -542,7 +558,6 @@ */ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) { - int nr; int retval = -ENOMEM; struct task_struct *p; DECLARE_MUTEX_LOCKED(sem); @@ -555,7 +570,6 @@ *p = *current; - down(¤t->mm->mmap_sem); lock_kernel(); retval = -EAGAIN; @@ -565,15 +579,12 @@ atomic_inc(&p->user->count); } - { - struct task_struct **tslot; - tslot = find_empty_process(); - if (!tslot) - goto bad_fork_cleanup_count; - p->tarray_ptr = tslot; - *tslot = p; - nr = tslot - &task[0]; - } + /* + * Counter atomicity is protected by + * the kernel lock + */ + if (nr_threads >= max_threads) + goto bad_fork_cleanup_count; if (p->exec_domain && p->exec_domain->module) __MOD_INC_USE_COUNT(p->exec_domain->module); @@ -594,8 +605,8 @@ * very end). */ p->state = TASK_RUNNING; - p->next_run = p; - p->prev_run = p; + p->run_list.next = NULL; + p->run_list.prev = NULL; p->p_pptr = p->p_opptr = current; p->p_cptr = NULL; @@ -638,9 +649,9 @@ goto bad_fork_cleanup_files; if (copy_sighand(clone_flags, p)) goto bad_fork_cleanup_fs; - if (copy_mm(nr, clone_flags, p)) + if (copy_mm(clone_flags, p)) goto bad_fork_cleanup_sighand; - retval = copy_thread(nr, clone_flags, usp, p, regs); + retval = copy_thread(0, clone_flags, usp, p, regs); if (retval) goto bad_fork_cleanup_sighand; p->semundo = NULL; @@ -666,22 +677,17 @@ * Let it rip! */ retval = p->pid; - if (retval) { - write_lock_irq(&tasklist_lock); - SET_LINKS(p); - hash_pid(p); - write_unlock_irq(&tasklist_lock); - - nr_tasks++; - - p->next_run = NULL; - p->prev_run = NULL; - wake_up_process(p); /* do this last */ - } + write_lock_irq(&tasklist_lock); + SET_LINKS(p); + hash_pid(p); + write_unlock_irq(&tasklist_lock); + + nr_threads++; + wake_up_process(p); /* do this last */ ++total_forks; + bad_fork: unlock_kernel(); - up(¤t->mm->mmap_sem); fork_out: if ((clone_flags & CLONE_VFORK) && (retval > 0)) down(&sem); @@ -699,7 +705,7 @@ if (p->binfmt && p->binfmt->module) __MOD_DEC_USE_COUNT(p->binfmt->module); - add_free_taskslot(p->tarray_ptr); + nr_threads--; bad_fork_cleanup_count: if (p->user) free_uid(p); diff -u --recursive --new-file v2.3.10/linux/kernel/info.c linux/kernel/info.c --- v2.3.10/linux/kernel/info.c Fri Nov 20 11:43:19 1998 +++ linux/kernel/info.c Sun Jul 11 09:11:46 1999 @@ -26,7 +26,7 @@ val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); - val.procs = nr_tasks-1; + val.procs = nr_threads-1; sti(); si_meminfo(&val); diff -u --recursive --new-file v2.3.10/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.3.10/linux/kernel/ksyms.c Thu Jul 8 15:42:21 1999 +++ linux/kernel/ksyms.c Mon Jul 19 12:31:25 1999 @@ -116,7 +116,6 @@ EXPORT_SYMBOL(get_super); EXPORT_SYMBOL(get_fs_type); EXPORT_SYMBOL(getname); -EXPORT_SYMBOL(__fput); /* goner? */ EXPORT_SYMBOL(_fput); EXPORT_SYMBOL(igrab); EXPORT_SYMBOL(iunique); @@ -193,7 +192,10 @@ EXPORT_SYMBOL(vfs_rename); EXPORT_SYMBOL(__pollwait); EXPORT_SYMBOL(ROOT_DEV); - +EXPORT_SYMBOL(add_to_page_cache_unique); +EXPORT_SYMBOL(__find_get_page); +EXPORT_SYMBOL(__find_lock_page); + #if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE) EXPORT_SYMBOL(do_nfsservctl); #endif @@ -308,11 +310,13 @@ #endif /* resource handling */ -EXPORT_SYMBOL(check_resource); EXPORT_SYMBOL(request_resource); EXPORT_SYMBOL(release_resource); -EXPORT_SYMBOL(occupy_resource); -EXPORT_SYMBOL(vacate_resource); +EXPORT_SYMBOL(__request_region); +EXPORT_SYMBOL(__check_region); +EXPORT_SYMBOL(__release_region); +EXPORT_SYMBOL(ioport_resource); +EXPORT_SYMBOL(iomem_resource); /* process management */ EXPORT_SYMBOL(__wake_up); diff -u --recursive --new-file v2.3.10/linux/kernel/panic.c linux/kernel/panic.c --- v2.3.10/linux/kernel/panic.c Sun Dec 27 22:45:13 1998 +++ linux/kernel/panic.c Sun Jul 11 09:11:46 1999 @@ -40,7 +40,7 @@ vsprintf(buf, fmt, args); va_end(args); printk(KERN_EMERG "Kernel panic: %s\n",buf); - if (current == task[0]) + if (current == init_tasks[0]) printk(KERN_EMERG "In swapper task - not syncing\n"); else if (in_interrupt()) printk(KERN_EMERG "In interrupt handler - not syncing\n"); diff -u --recursive --new-file v2.3.10/linux/kernel/ptrace.c linux/kernel/ptrace.c --- v2.3.10/linux/kernel/ptrace.c Thu Jul 8 15:42:21 1999 +++ linux/kernel/ptrace.c Mon Jul 19 12:29:05 1999 @@ -39,6 +39,8 @@ if (!pte_present(*pgtable)) goto fault_in_page; page = pte_page(*pgtable); + if (write && (!pte_write(*pgtable) || !pte_dirty(*pgtable))) + goto fault_in_page; if (MAP_NR(page) >= max_mapnr) return 0; flush_cache_page(vma, addr); diff -u --recursive --new-file v2.3.10/linux/kernel/resource.c linux/kernel/resource.c --- v2.3.10/linux/kernel/resource.c Fri Jun 18 12:43:41 1999 +++ linux/kernel/resource.c Mon Jul 19 12:56:18 1999 @@ -1,232 +1,186 @@ /* * linux/kernel/resource.c * - * Copyright (C) 1995, 1999 Linus Torvalds - * David Hinds + * Copyright (C) 1999 Linus Torvalds * - * Kernel resource management - * - * We now distinguish between claiming space for devices (using the - * 'occupy' and 'vacate' calls), and associating a resource with a - * device driver (with the 'request', 'release', and 'check' calls). - * A resource can be claimed even if there is no associated driver - * (by occupying with name=NULL). Vacating a resource makes it - * available for other dynamically configured devices. + * Arbitrary resource management. */ #include #include #include #include +#include -#define RSRC_TABLE_SIZE 128 - -struct resource_entry { - u_long from, num; - const char *name; - struct resource_entry *next; -}; - -struct resource_entry res_list[] = { - { 0, 0, NULL, NULL }, /* IO */ - { 0, 0, NULL, NULL } /* mem */ -}; - -static struct resource_entry rsrc_table[RSRC_TABLE_SIZE]; +struct resource ioport_resource = { "PCI IO", 0x0000, 0xFFFF }; +struct resource iomem_resource = { "PCI mem", 0x00000000, 0xFFFFFFFF }; /* * This generates reports for /proc/ioports and /proc/memory */ -int get_resource_list(int class, char *buf) +static char * do_resource_list(struct resource *entry, const char *fmt, int offset, char *buf, char *end) { - struct resource_entry *root = &res_list[class]; - struct resource_entry *p; - int len = 0; - char *fmt = (class == RES_IO) ? - "%04lx-%04lx : %s\n" : "%08lx-%08lx : %s\n"; - - for (p = root->next; (p) && (len < 4000); p = p->next) - len += sprintf(buf+len, fmt, p->from, p->from+p->num-1, - (p->name ? p->name : "occupied")); - if (p) - len += sprintf(buf+len, "4K limit reached!\n"); - return len; + if (offset < 0) + offset = 0; + + while (entry) { + const char *name = entry->name; + unsigned long from, to; + + if ((int) (end-buf) < 80) + return buf; + + from = entry->start; + to = entry->end; + if (!name) + name = ""; + + buf += sprintf(buf, fmt + offset, from, to, name); + if (entry->child) + buf = do_resource_list(entry->child, fmt, offset-2, buf, end); + entry = entry->sibling; + } + + return buf; } -/* - * Basics: find a matching resource entry, or find an insertion point - */ -static struct resource_entry * -find_match(struct resource_entry *root, u_long from, u_long num) +int get_resource_list(struct resource *root, char *buf, int size) { - struct resource_entry *p; - for (p = root; p; p = p->next) - if ((p->from == from) && (p->num == num)) - return p; - return NULL; -} - -static struct resource_entry * -find_gap(struct resource_entry *root, u_long from, u_long num) -{ - struct resource_entry *p; - if (from > from+num-1) - return NULL; - for (p = root; ; p = p->next) { - if ((p != root) && (p->from+p->num-1 >= from)) { - p = NULL; - break; + char *fmt; + + fmt = " %08lx-%08lx : %s\n"; + if (root == &ioport_resource) + fmt = " %04lx-%04lx : %s\n"; + return do_resource_list(root->child, fmt, 8, buf, buf + size) - buf; +} + +int request_resource(struct resource *root, struct resource *new) +{ + unsigned long start = new->start; + unsigned long end = new->end; + struct resource *tmp, **p; + + if (end < start) + return -EINVAL; + if (start < root->start) + return -EINVAL; + if (end > root->end) + return -EINVAL; + p = &root->child; + for (;;) { + tmp = *p; + if (!tmp || tmp->start > end) { + new->sibling = tmp; + *p = new; + new->parent = root; + return 0; } - if ((p->next == NULL) || (p->next->from > from+num-1)) - break; + p = &tmp->sibling; + if (tmp->end < start) + continue; + return -EBUSY; } - return p; } -/* - * Call this from a driver to assert ownership of a resource - */ -void request_resource(int class, unsigned long from, - unsigned long num, const char *name) +int release_resource(struct resource *old) { - struct resource_entry *root = &res_list[class]; - struct resource_entry *p; - long flags; - int i; - - p = find_match(root, from, num); - if (p) { - p->name = name; - return; - } + struct resource *tmp, **p; - save_flags(flags); - cli(); - for (i = 0; i < RSRC_TABLE_SIZE; i++) - if (rsrc_table[i].num == 0) - break; - if (i == RSRC_TABLE_SIZE) - printk("warning: resource table is full\n"); - else { - p = find_gap(root, from, num); - if (p == NULL) { - restore_flags(flags); - return; + p = &old->parent->child; + for (;;) { + tmp = *p; + if (!tmp) + break; + if (tmp == old) { + *p = tmp->sibling; + old->parent = NULL; + return 0; } - rsrc_table[i].name = name; - rsrc_table[i].from = from; - rsrc_table[i].num = num; - rsrc_table[i].next = p->next; - p->next = &rsrc_table[i]; + p = &tmp->sibling; } - restore_flags(flags); + return -EINVAL; } -/* - * Call these when a driver is unloaded but the device remains - */ -void release_resource(int class, unsigned long from, unsigned long num) +struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name) { - struct resource_entry *root = &res_list[class]; - struct resource_entry *p; - p = find_match(root, from, num); - if (p) p->name = NULL; -} + struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL); -/* - * Call these to check a region for conflicts before probing - */ -int check_resource(int class, unsigned long from, unsigned long num) -{ - struct resource_entry *root = &res_list[class]; - struct resource_entry *p; - p = find_match(root, from, num); - if (p != NULL) - return (p->name != NULL) ? -EBUSY : 0; - return (find_gap(root, from, num) == NULL) ? -EBUSY : 0; + if (res) { + memset(res, 0, sizeof(*res)); + res->name = name; + res->start = start; + res->end = start + n - 1; + if (request_resource(parent, res) != 0) { + kfree(res); + res = NULL; + } + } + return res; } /* - * Call this to claim a resource for a piece of hardware + * Compatibility cruft. + * + * Check-region returns non-zero if something already exists. + * + * Release-region releases an anonymous region that matches + * the IO port range. */ -unsigned long occupy_resource(int class, unsigned long base, - unsigned long end, unsigned long num, - unsigned long align, const char *name) -{ - struct resource_entry *root = &res_list[class]; - unsigned long from = 0, till; - unsigned long flags; - int i; - struct resource_entry *p, *q; +int __check_region(struct resource *parent, unsigned long start, unsigned long n) +{ + struct resource * res; - if ((base > end-1) || (num > end - base)) - return 0; + res = __request_region(parent, start, n, "check-region"); + if (!res) + return -EBUSY; - for (i = 0; i < RSRC_TABLE_SIZE; i++) - if (rsrc_table[i].num == 0) - break; - if (i == RSRC_TABLE_SIZE) - return 0; + release_resource(res); + kfree(res); + return 0; +} - save_flags(flags); - cli(); - /* printk("occupy: search in %08lx[%08lx] ", base, end - base); */ - for (p = root; p != NULL; p = q) { - q = p->next; - /* Find window in list */ - from = (p->from+p->num + align-1) & ~(align-1); - till = (q == NULL) ? (0 - align) : q->from; - /* printk(" %08lx:%08lx", from, till); */ - /* Clip window with base and end */ - if (from < base) from = base; - if (till > end) till = end; - /* See if result is large enougth */ - if ((from < till) && (from + num < till)) - break; - } - /* printk("\r\n"); */ - restore_flags(flags); +void __release_region(struct resource *parent, unsigned long start, unsigned long n) +{ + struct resource **p; + unsigned long end; - if (p == NULL) - return 0; + p = &parent->child; + end = start + n - 1; - rsrc_table[i].name = name; - rsrc_table[i].from = from; - rsrc_table[i].num = num; - rsrc_table[i].next = p->next; - p->next = &rsrc_table[i]; - return from; -} + for (;;) { + struct resource *res = *p; -/* - * Call this when a resource becomes available for other hardware - */ -void vacate_resource(int class, unsigned long from, unsigned long num) -{ - struct resource_entry *root = &res_list[class]; - struct resource_entry *p, *q; - long flags; - - save_flags(flags); - cli(); - for (p = root; ; p = q) { - q = p->next; - if (q == NULL) + if (!res) break; - if ((q->from == from) && (q->num == num)) { - q->num = 0; - p->next = q->next; + if (res->start == start && res->end == end) { + *p = res->sibling; + kfree(res); break; } + p = &res->sibling; } - restore_flags(flags); } -/* Called from init/main.c to reserve IO ports. */ +/* + * Called from init/main.c to reserve IO ports. + */ +#define MAXRESERVE 4 void __init reserve_setup(char *str, int *ints) { int i; + static int reserved = 0; + static struct resource reserve[MAXRESERVE]; - for (i = 1; i < ints[0]; i += 2) - request_region(ints[i], ints[i+1], "reserved"); + for (i = 1; i < ints[0]; i += 2) { + int x = reserved; + if (x < MAXRESERVE) { + struct resource *res = reserve + x; + res->name = "reserved"; + res->start = ints[i]; + res->end = res->start + ints[i] - 1; + res->child = NULL; + if (request_resource(&ioport_resource, res) == 0) + reserved = x+1; + } + } } diff -u --recursive --new-file v2.3.10/linux/kernel/sched.c linux/kernel/sched.c --- v2.3.10/linux/kernel/sched.c Thu Jul 8 15:42:21 1999 +++ linux/kernel/sched.c Wed Jul 21 10:38:11 1999 @@ -94,7 +94,23 @@ * via the SMP irq return path. */ -struct task_struct * task[NR_TASKS] = {&init_task, }; +struct task_struct * init_tasks[NR_CPUS] = {&init_task, }; + +/* + * The tasklist_lock protects the linked list of processes. + * + * The scheduler lock is protecting against multiple entry + * into the scheduling code, and doesn't need to worry + * about interrupts (because interrupts cannot call the + * scheduler). + * + * The run-queue lock locks the parts that actually access + * and change the run-queues, and have to be interrupt-safe. + */ +spinlock_t runqueue_lock = SPIN_LOCK_UNLOCKED; /* second */ +rwlock_t tasklist_lock = RW_LOCK_UNLOCKED; /* third */ + +static LIST_HEAD(runqueue_head); /* * We align per-CPU scheduling data on cacheline boundaries, @@ -114,7 +130,7 @@ #ifdef __SMP__ -#define idle_task(cpu) (task[cpu_number_map[(cpu)]]) +#define idle_task(cpu) (init_tasks[cpu_number_map[(cpu)]]) #define can_schedule(p) (!(p)->has_cpu) #else @@ -140,8 +156,7 @@ * +1000: realtime process, select this. */ -static inline int goodness (struct task_struct * prev, - struct task_struct * p, int this_cpu) +static inline int goodness(struct task_struct * p, int this_cpu, struct mm_struct *this_mm) { int weight; @@ -174,7 +189,7 @@ #endif /* .. and a slight advantage to the current MM */ - if (p->mm == prev->mm) + if (p->mm == this_mm) weight += 1; weight += p->priority; @@ -191,24 +206,22 @@ * to care about SCHED_YIELD is when we calculate the previous process' * goodness ... */ -static inline int prev_goodness (struct task_struct * prev, - struct task_struct * p, int this_cpu) +static inline int prev_goodness(struct task_struct * p, int this_cpu, struct mm_struct *this_mm) { if (p->policy & SCHED_YIELD) { p->policy &= ~SCHED_YIELD; return 0; } - return goodness(prev, p, this_cpu); + return goodness(p, this_cpu, this_mm); } /* * the 'goodness value' of replacing a process on a given CPU. * positive value means 'replace', zero or negative means 'dont'. */ -static inline int preemption_goodness (struct task_struct * prev, - struct task_struct * p, int cpu) +static inline int preemption_goodness(struct task_struct * prev, struct task_struct * p, int cpu) { - return goodness(prev, p, cpu) - goodness(prev, prev, cpu); + return goodness(p, cpu, prev->mm) - goodness(prev, cpu, prev->mm); } /* @@ -366,74 +379,23 @@ */ static inline void add_to_runqueue(struct task_struct * p) { - struct task_struct *next = init_task.next_run; - - p->prev_run = &init_task; - init_task.next_run = p; - p->next_run = next; - next->prev_run = p; + list_add(&p->run_list, &runqueue_head); nr_running++; } -static inline void del_from_runqueue(struct task_struct * p) -{ - struct task_struct *next = p->next_run; - struct task_struct *prev = p->prev_run; - - nr_running--; - next->prev_run = prev; - prev->next_run = next; - p->next_run = NULL; - p->prev_run = NULL; -} - static inline void move_last_runqueue(struct task_struct * p) { - struct task_struct *next = p->next_run; - struct task_struct *prev = p->prev_run; - - /* remove from list */ - next->prev_run = prev; - prev->next_run = next; - /* add back to list */ - p->next_run = &init_task; - prev = init_task.prev_run; - init_task.prev_run = p; - p->prev_run = prev; - prev->next_run = p; + list_del(&p->run_list); + list_add_tail(&p->run_list, &runqueue_head); } static inline void move_first_runqueue(struct task_struct * p) { - struct task_struct *next = p->next_run; - struct task_struct *prev = p->prev_run; - - /* remove from list */ - next->prev_run = prev; - prev->next_run = next; - /* add back to list */ - p->prev_run = &init_task; - next = init_task.next_run; - init_task.next_run = p; - p->next_run = next; - next->prev_run = p; + list_del(&p->run_list); + list_add(&p->run_list, &runqueue_head); } /* - * The tasklist_lock protects the linked list of processes. - * - * The scheduler lock is protecting against multiple entry - * into the scheduling code, and doesn't need to worry - * about interrupts (because interrupts cannot call the - * scheduler). - * - * The run-queue lock locks the parts that actually access - * and change the run-queues, and have to be interrupt-safe. - */ -spinlock_t runqueue_lock = SPIN_LOCK_UNLOCKED; /* second */ -rwlock_t tasklist_lock = RW_LOCK_UNLOCKED; /* third */ - -/* * Wake up a process. Put it on the run-queue if it's not * already there. The "current" process is always on the * run-queue (except when the actual re-schedule is in @@ -450,7 +412,7 @@ */ spin_lock_irqsave(&runqueue_lock, flags); p->state = TASK_RUNNING; - if (p->next_run) + if (task_on_runqueue(p)) goto out; add_to_runqueue(p); spin_unlock_irqrestore(&runqueue_lock, flags); @@ -657,8 +619,17 @@ * cleans up all remaining scheduler things, without impacting the * common case. */ -static inline void __schedule_tail (struct task_struct *prev) +static inline void __schedule_tail(struct task_struct *prev) { + if (!current->active_mm) BUG(); + + if (!prev->mm) { + struct mm_struct *mm = prev->active_mm; + if (mm) { + prev->active_mm = NULL; + mmdrop(mm); + } + } #ifdef __SMP__ if ((prev->state == TASK_RUNNING) && (prev != idle_task(smp_processor_id()))) @@ -668,7 +639,7 @@ #endif /* __SMP__ */ } -void schedule_tail (struct task_struct *prev) +void schedule_tail(struct task_struct *prev) { __schedule_tail(prev); } @@ -687,8 +658,10 @@ { struct schedule_data * sched_data; struct task_struct *prev, *next, *p; + struct list_head *tmp; int this_cpu, c; + if (!current->active_mm) BUG(); if (tq_scheduler) goto handle_tq_scheduler; tq_scheduler_back: @@ -731,42 +704,29 @@ } prev->need_resched = 0; -repeat_schedule: - /* * this is the scheduler proper: */ - p = init_task.next_run; - /* Default process to select.. */ +repeat_schedule: + /* + * Default process to select.. + */ next = idle_task(this_cpu); c = -1000; if (prev->state == TASK_RUNNING) goto still_running; still_running_back: - /* - * This is subtle. - * Note how we can enable interrupts here, even - * though interrupts can add processes to the run- - * queue. This is because any new processes will - * be added to the front of the queue, so "p" above - * is a safe starting point. - * run-queue deletion and re-ordering is protected by - * the scheduler lock - */ -/* - * Note! there may appear new tasks on the run-queue during this, as - * interrupts are enabled. However, they will be put on front of the - * list, so our list starting at "p" is essentially fixed. - */ - while (p != &init_task) { + tmp = runqueue_head.next; + while (tmp != &runqueue_head) { + p = list_entry(tmp, struct task_struct, run_list); if (can_schedule(p)) { - int weight = goodness(prev, p, this_cpu); + int weight = goodness(p, this_cpu, prev->active_mm); if (weight > c) c = weight, next = p; } - p = p->next_run; + tmp = tmp->next; } /* Do we need to re-calculate counters? */ @@ -819,12 +779,31 @@ #endif /* __SMP__ */ kstat.context_swtch++; + /* + * there are 3 processes which are affected by a context switch: + * + * prev == .... ==> (last => next) + * + * It's the 'much more previous' 'prev' that is on next's stack, + * but prev is set to (the just run) 'last' process by switch_to(). + * This might sound slightly confusing but makes tons of sense. + */ + { + struct mm_struct *mm = next->mm; + if (!mm) { + mm = prev->active_mm; + set_mmu_context(prev,next); + if (next->active_mm) BUG(); + next->active_mm = mm; + atomic_inc(&mm->mm_count); + } + } + get_mmu_context(next); switch_to(prev, next, prev); __schedule_tail(prev); same_process: - reacquire_kernel_lock(current); return; @@ -837,11 +816,11 @@ p->counter = (p->counter >> 1) + p->priority; read_unlock(&tasklist_lock); spin_lock_irq(&runqueue_lock); - goto repeat_schedule; } + goto repeat_schedule; still_running: - c = prev_goodness(prev, prev, this_cpu); + c = prev_goodness(prev, this_cpu, prev->active_mm); next = prev; goto still_running_back; @@ -1760,7 +1739,7 @@ retval = 0; p->policy = policy; p->rt_priority = lp.sched_priority; - if (p->next_run) + if (task_on_runqueue(p)) move_first_runqueue(p); current->need_resched = 1; @@ -1934,13 +1913,13 @@ return 0; } -static void show_task(int nr,struct task_struct * p) +static void show_task(struct task_struct * p) { unsigned long free = 0; int state; static const char * stat_nam[] = { "R", "S", "D", "Z", "T", "W" }; - printk("%-8s %3d ", p->comm, (p == current) ? -nr : nr); + printk("%-8s ", p->comm); state = p->state ? ffz(~p->state) + 1 : 0; if (((unsigned) state) < sizeof(stat_nam)/sizeof(char *)) printk(stat_nam[state]); @@ -1950,12 +1929,12 @@ if (p == current) printk(" current "); else - printk(" %08lX ", thread_saved_pc(&p->tss)); + printk(" %08lX ", thread_saved_pc(&p->thread)); #else if (p == current) printk(" current task "); else - printk(" %016lx ", thread_saved_pc(&p->tss)); + printk(" %016lx ", thread_saved_pc(&p->thread)); #endif { unsigned long * n = (unsigned long *) (p+1); @@ -1968,6 +1947,10 @@ printk("%5d ", p->p_cptr->pid); else printk(" "); + if (!p->mm) + printk(" (L-TLB) "); + else + printk(" (NOTLB) "); if (p->p_ysptr) printk("%7d", p->p_ysptr->pid); else @@ -2020,7 +2003,7 @@ #endif read_lock(&tasklist_lock); for_each_task(p) - show_task((p->tarray_ptr - &task[0]),p); + show_task(p); read_unlock(&tasklist_lock); } @@ -2030,6 +2013,11 @@ struct schedule_data * sched_data; sched_data = &aligned_data[smp_processor_id()].schedule_data; + if (current != &init_task && task_on_runqueue(current)) { + printk("UGH! (%d:%d) was on the runqueue, removing.\n", + smp_processor_id(), current->pid); + del_from_runqueue(current); + } t = get_cycles(); sched_data->curr = current; sched_data->last_schedule = t; @@ -2042,18 +2030,20 @@ * process right in SMP mode. */ int cpu=hard_smp_processor_id(); - int nr = NR_TASKS; + int nr; init_task.processor=cpu; - /* Init task array free list and pidhash table. */ - while(--nr > 0) - add_free_taskslot(&task[nr]); - for(nr = 0; nr < PIDHASH_SZ; nr++) pidhash[nr] = NULL; init_bh(TIMER_BH, timer_bh); init_bh(TQUEUE_BH, tqueue_bh); init_bh(IMMEDIATE_BH, immediate_bh); + + /* + * The boot idle thread does lazy MMU switching as well: + */ + atomic_inc(&init_mm.mm_count); } + diff -u --recursive --new-file v2.3.10/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.3.10/linux/kernel/sysctl.c Thu Jul 8 15:42:21 1999 +++ linux/kernel/sysctl.c Sun Jul 11 09:11:46 1999 @@ -34,6 +34,7 @@ extern int console_loglevel, C_A_D; extern int bdf_prm[], bdflush_min[], bdflush_max[]; extern int sysctl_overcommit_memory; +extern int max_threads; extern int nr_queued_signals, max_queued_signals; #ifdef CONFIG_KMOD @@ -207,6 +208,8 @@ {KERN_SHMMAX, "shmmax", &shmmax, sizeof (int), 0644, NULL, &proc_dointvec}, #endif + {KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int), + 0644, NULL, &proc_dointvec}, {0} }; diff -u --recursive --new-file v2.3.10/linux/mm/filemap.c linux/mm/filemap.c --- v2.3.10/linux/mm/filemap.c Thu Jul 8 15:42:21 1999 +++ linux/mm/filemap.c Mon Jul 12 07:49:36 1999 @@ -463,7 +463,7 @@ flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error)); page->flags = flags | ((1 << PG_locked) | (1 << PG_referenced)); - page->owner = (int)current; /* REMOVEME */ + page->owner = current; /* REMOVEME */ get_page(page); page->offset = offset; add_page_to_inode_queue(inode, page); @@ -1855,7 +1855,7 @@ if (!PageLocked(page)) { PAGE_BUG(page); } else { - if (page->owner != (int)current) { + if (page->owner != current) { PAGE_BUG(page); } } diff -u --recursive --new-file v2.3.10/linux/mm/memory.c linux/mm/memory.c --- v2.3.10/linux/mm/memory.c Thu Jul 8 15:42:21 1999 +++ linux/mm/memory.c Tue Jul 20 22:58:05 1999 @@ -164,17 +164,6 @@ return; } -int new_page_tables(struct task_struct * tsk) -{ - pgd_t * new_pg; - - if (!(new_pg = pgd_alloc())) - return -ENOMEM; - SET_PAGE_DIR(tsk, new_pg); - tsk->mm->pgd = new_pg; - return 0; -} - #define PTE_TABLE_MASK ((PTRS_PER_PTE-1) * sizeof(pte_t)) #define PMD_TABLE_MASK ((PTRS_PER_PMD-1) * sizeof(pmd_t)) @@ -781,7 +770,7 @@ * because it doesn't cost us any seek time. We also make sure to queue * the 'original' request together with the readahead ones... */ -static void swapin_readahead(unsigned long entry) +void swapin_readahead(unsigned long entry) { int i; struct page *new_page; @@ -898,6 +887,8 @@ page = vma->vm_ops->nopage(vma, address & PAGE_MASK, (vma->vm_flags & VM_SHARED)?0:write_access); if (!page) return 0; /* SIGBUS - but we _really_ should know whether it is OOM or SIGBUS */ + if (page == -1) + return -1; /* OOM */ ++tsk->maj_flt; ++vma->vm_mm->rss; diff -u --recursive --new-file v2.3.10/linux/mm/mremap.c linux/mm/mremap.c --- v2.3.10/linux/mm/mremap.c Thu Jul 8 15:42:21 1999 +++ linux/mm/mremap.c Mon Jul 12 07:51:42 1999 @@ -118,7 +118,7 @@ flush_cache_range(mm, new_addr, new_addr + len); while ((offset += PAGE_SIZE) < len) move_one_page(mm, new_addr + offset, old_addr + offset); - zap_page_range(mm, new_addr, new_addr + len); + zap_page_range(mm, new_addr, len); flush_tlb_range(mm, new_addr, new_addr + len); return -1; } diff -u --recursive --new-file v2.3.10/linux/mm/slab.c linux/mm/slab.c --- v2.3.10/linux/mm/slab.c Fri May 28 10:13:37 1999 +++ linux/mm/slab.c Tue Jul 20 14:29:38 1999 @@ -1577,7 +1577,7 @@ #if 1 /* FORCE A KERNEL DUMP WHEN THIS HAPPENS. SPEAK IN ALL CAPS. GET THE CALL CHAIN. */ -*(int *) 0 = 0; + BUG(); #endif return; diff -u --recursive --new-file v2.3.10/linux/mm/swapfile.c linux/mm/swapfile.c --- v2.3.10/linux/mm/swapfile.c Wed Jun 30 13:38:20 1999 +++ linux/mm/swapfile.c Mon Jul 19 23:08:41 1999 @@ -266,7 +266,7 @@ /* * Go through process' page directory. */ - if (!mm || mm == &init_mm) + if (!mm) return; for (vma = mm->mmap; vma; vma = vma->vm_next) { pgd_t * pgd = pgd_offset(mm, vma->vm_start); @@ -661,7 +661,9 @@ else p->swap_map[page] = SWAP_MAP_BAD; } - nr_good_pages = swap_header->info.last_page - i; + nr_good_pages = swap_header->info.last_page - + swap_header->info.nr_badpages - + 1 /* header page */; lock_map_size = (p->max + 7) / 8; if (error) goto bad_swap; diff -u --recursive --new-file v2.3.10/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.3.10/linux/mm/vmscan.c Thu Jul 8 15:42:21 1999 +++ linux/mm/vmscan.c Tue Jul 20 13:27:53 1999 @@ -338,11 +338,11 @@ * Think of swap_cnt as a "shadow rss" - it tells us which process * we want to page out (always try largest first). */ - counter = nr_tasks / (priority+1); + counter = nr_threads / (priority+1); if (counter < 1) counter = 1; - if (counter > nr_tasks) - counter = nr_tasks; + if (counter > nr_threads) + counter = nr_threads; for (; counter >= 0; counter--) { assign = 0; @@ -352,7 +352,7 @@ read_lock(&tasklist_lock); p = init_task.next_task; for (; p != &init_task; p = p->next_task) { - if (!p->swappable) + if (!p->swappable || !p->mm) continue; if (p->mm->rss <= 0) continue;